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
<!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">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.purple.min.css">
<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; }
#transcript pre { margin: 0; padding: 0.25rem; white-space: pre-wrap; word-break: break-word; }
</style>
<title>asyncai</title>
<script type="importmap">{ "imports": { "@atproto/oauth-client-browser": "https://esm.sh/@atproto/oauth-client-browser@0.5.14" } }</script>
<script type="module" src="./main.js"></script>
</head>
<body>
<main class="container">
<h1>asyncai</h1>
<p>An agent loop in a wasm module: inference on co/core (as you, no key), Anthropic, or any compatible
endpoint; tools from MCP servers. Credentials stay in this page's host allowlist; the module never sees them.</p>
<form id="login" hidden>
<div class="grid">
<input name="handle" placeholder="you.bsky.social (co/core runs as you)" autocomplete="username" required>
<button>Sign in for co/core</button>
</div>
<small id="login-error"></small>
</form>
<p id="signed-in" hidden>Signed in as <code id="who"></code> <a href="#" id="logout">Sign out</a>.
<small>co/core needs your account connected once at <a href="https://cocore.dev">cocore.dev</a>.</small></p>
<form id="form">
<label>Prompt <textarea name="prompt" rows="3" required></textarea></label>
<fieldset class="grid">
<label><input type="radio" name="backend" value="cocore" checked> co/core</label>
<label><input type="radio" name="backend" value="anthropic"> Anthropic</label>
<label><input type="radio" name="backend" value="custom"> Custom URL + token</label>
</fieldset>
<div class="grid" id="custom" hidden>
<label>Base URL <input name="endpoint" placeholder="https://api.example.com/v1"></label>
<label>Format <select name="format"><option value="openai">OpenAI chat completions</option><option value="anthropic">Anthropic Messages</option></select></label>
</div>
<details>
<summary>Settings</summary>
<label>System prompt <textarea name="system" rows="2"></textarea></label>
<div class="grid">
<label>Model <input name="model" placeholder="co/core: stub, or a model from cocore.dev/api/v1/models"></label>
<label>API key or token (Anthropic, custom) <input name="apiKey" type="password" autocomplete="off"></label>
</div>
<div class="grid">
<label>Inference calls at most <input name="maxSteps" inputmode="numeric" placeholder="9"></label>
</div>
<div class="grid">
<label>Context window, tokens (compacts at 0.8 of it) <input name="contextWindow" inputmode="numeric" placeholder="200000"></label>
<label>Compaction <select name="compact"><option value="client">client (any endpoint)</option><option value="server">server (Anthropic's beta, Anthropic only)</option><option value="off">off</option></select></label>
</div>
<label>MCP servers (JSON; remote ones over Streamable HTTP; the server must allow this page's origin)
<textarea name="mcp" rows="2">[{"name": "deepwiki", "url": "https://mcp.deepwiki.com/mcp"}]</textarea></label>
<label>MCP servers the agent may connect mid-run (dynamicMcp: URL prefixes, space-separated; empty: none)
<input name="dynamicMcp" placeholder="https://mcp.example.com/"></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>
<details open><summary>MCP servers (after a run: the live set)</summary><ul id="servers"></ul></details>
<ol id="transcript"></ol>
</main>
</body>
</html>