1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="referrer" content="no-referrer">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>atlibs agent</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2.1.1/css/pico.min.css">
<script type="importmap">
{
"imports": {
"@atproto/oauth-client-browser": "https://esm.sh/@atproto/oauth-client-browser@0.5.14",
"@noble/curves/secp256k1.js": "https://esm.sh/@noble/curves@2.4.0/secp256k1.js",
"age-encryption": "https://esm.sh/age-encryption@0.3.1",
"@publicdomainrelay/atlibs/": "https://cdn.jsdelivr.net/npm/@publicdomainrelay/atlibs@0.3.0/src/",
"@publicdomainrelay/atlibs-code-mode/": "https://cdn.jsdelivr.net/npm/@publicdomainrelay/atlibs-code-mode@0.3.0/js/",
"@publicdomainrelay/atlibs-webrtc/": "https://cdn.jsdelivr.net/npm/@publicdomainrelay/atlibs-webrtc@0.3.0/js/",
"assemblyscript/asc": "https://cdn.jsdelivr.net/npm/assemblyscript@0.28.20/dist/asc.js",
"assemblyscript": "https://cdn.jsdelivr.net/npm/assemblyscript@0.28.20/dist/assemblyscript.js",
"binaryen": "https://cdn.jsdelivr.net/npm/binaryen@131.0.0-nightly.20260721/index.js",
"long": "https://cdn.jsdelivr.net/npm/long@5.3.2/index.js"
}
}
</script>
<style>
#transcript { list-style: none; padding: 0; }
#transcript li { margin-bottom: 0.5rem; padding: 0.5rem; border-left: 3px solid var(--pico-muted-border-color); }
#transcript li.tool_use, #transcript li.tool_result { border-color: var(--pico-primary); }
#transcript li.error { border-color: var(--pico-del-color); }
#transcript li.thinking { opacity: 0.7; }
pre { margin: 0; padding: 0.25rem; white-space: pre-wrap; word-break: break-word; max-height: 30rem; overflow: auto; }
pre.out:empty { display: none; }
#tools ul { list-style: none; padding-left: 0; }
#tools li { list-style: none; }
#log { font-family: ui-monospace, monospace; font-size: 0.8rem; max-height: 15rem; overflow: auto; }
.write { color: var(--pico-del-color); }
code { word-break: break-all; }
</style>
<script type="module" src="./main.js"></script>
</head>
<body>
<main class="container">
<h1>atlibs agent</h1>
<p><small><a id="source" href="https://knotless.dev/johnandersen777.bsky.social/atlibs-agent-reference-spa">Source</a></small></p>
<p>An agent in this tab: the asyncai loop, with code mode and every lib's actions as MCP tools. Each tool runs as you,
held to its own module's OAuth scope; tools that change your data ask you first.</p>
<form id="login" hidden>
<fieldset role="group">
<input name="handle" placeholder="you.bsky.social" autocomplete="username" required>
<button>Sign in</button>
</fieldset>
<small id="login-error"></small>
</form>
<p id="who" hidden>Signed in as <code></code> <a href="#" id="logout">Sign out</a></p>
<section>
<h2>Agent</h2>
<form id="agent">
<label>Prompt <textarea name="prompt" rows="3" required></textarea></label>
<details>
<summary>Inference and servers</summary>
<input type="hidden" name="provider" value="cocore">
<div class="grid">
<label><input type="checkbox" role="switch" id="use-custom"> Custom endpoint <small>(off: co/core, your atproto session, no key)</small> <small id="cocore-cors" hidden>co/core: browser CORS blocks this origin — use a custom endpoint</small></label>
<label>Model <input name="model" placeholder="blank: co/core's largest instruct model"></label>
</div>
<div class="grid" id="custom">
<label>Base URL <input name="endpoint" placeholder="https://api.deepseek.com/anthropic"></label>
<label>Format <select name="format"><option value="anthropic">Anthropic Messages</option><option value="openai">OpenAI chat completions</option></select></label>
</div>
<div class="grid">
<label id="key">API key or token <input name="apiKey" type="password" autocomplete="off"><small id="key-state"></small> <a href="#" id="forget-key" hidden>Forget the key</a></label>
<label>Inference calls at most <input name="maxSteps" inputmode="numeric" placeholder="12"></label>
</div>
<label>System prompt (blank: the default, which names you and the tools) <textarea name="system" rows="2"></textarea></label>
<label>Remote MCP servers, Streamable HTTP (JSON; each origin must allow this page's)
<textarea name="remote" rows="2" placeholder='[{"name": "deepwiki", "url": "https://mcp.deepwiki.com/mcp"}]'></textarea></label>
</details>
<div class="grid">
<button id="run" type="submit">Run</button>
<button id="stop" type="button" class="secondary" disabled>Stop</button>
<button id="forget" type="button" class="outline">Forget the conversation</button>
</div>
</form>
<p id="status"></p>
<h3>Connected by the agent</h3>
<ul id="connected"></ul>
<ol id="transcript"></ol>
</section>
<section>
<h2>VMs</h2>
<p><small>socialweb.computer VMs you keep (a contract with release false). Their MCP shell is reached over WebRTC from this tab. Release one when done: it terminates the VM and deletes the records it made.</small></p>
<p id="vms-none"><small>None kept.</small></p>
<ul id="vms"></ul>
</section>
<section id="tools">
<h2>MCP servers</h2>
<label><input type="checkbox" role="switch" id="publish"> Publish these servers from this tab through the fedproxy ingress (while the tab is open)</label>
<p><small>Only the tools checked below are public: read-only ones to start with. A public write tool still asks you here before it runs.</small></p>
<div id="servers"></div>
<ol id="log" reversed></ol>
</section>
<section>
<h2>Actions</h2>
<p><small>Every lib's actions as plain forms, without the agent; each runs as you, held to its module's own scope.</small></p>
<div id="actions"></div>
</section>
<p id="error" class="write"></p>
</main>
<dialog id="confirm">
<article>
<h3>Allow this change?</h3>
<p><span class="who"></span> wants to run <code class="tool"></code>:</p>
<pre class="args"></pre>
<footer>
<button class="secondary" value="deny">Deny</button>
<button value="allow">Allow</button>
</footer>
</article>
</dialog>
</body>
</html>