agentic-assistant 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/README.md +139 -7
- package/SKILL.md +17 -0
- package/dist/chat-CXbhePC5.d.ts +120 -0
- package/dist/chunk-3LKTJJ75.js +846 -0
- package/dist/chunk-3X6KU636.js +569 -0
- package/dist/chunk-DXTIEMOT.js +142 -0
- package/dist/chunk-GLU222OQ.js +302 -0
- package/dist/chunk-HYT732TN.js +36 -0
- package/dist/chunk-T5WVSGYQ.js +82 -0
- package/dist/cli.d.ts +27 -2
- package/dist/cli.js +303 -19
- package/dist/client.d.ts +78 -0
- package/dist/client.js +195 -0
- package/dist/demo.d.ts +21 -0
- package/dist/demo.js +158 -0
- package/dist/index.d.ts +38 -63
- package/dist/index.js +55 -975
- package/dist/{loop-CDbbDwSs.d.ts → loop-D4qWbRu6.d.ts} +66 -7
- package/dist/mcp-server-ZPCPYMCT.js +12 -0
- package/dist/react.d.ts +2 -2
- package/dist/react.js +9 -3
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +3 -32
- package/dist/{types-C47SyHH5.d.ts → types-DGH8FS56.d.ts} +13 -1
- package/dist/worker.d.ts +44 -3
- package/dist/worker.js +10 -14
- package/llms.txt +4 -0
- package/package.json +17 -4
- package/dist/chunk-4QE7E5UQ.js +0 -7
package/dist/demo.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createStaticTokenAuth,
|
|
3
|
+
createWorker
|
|
4
|
+
} from "./chunk-GLU222OQ.js";
|
|
5
|
+
import {
|
|
6
|
+
AnthropicProvider
|
|
7
|
+
} from "./chunk-DXTIEMOT.js";
|
|
8
|
+
import {
|
|
9
|
+
ToolRegistry,
|
|
10
|
+
VERSION
|
|
11
|
+
} from "./chunk-3LKTJJ75.js";
|
|
12
|
+
|
|
13
|
+
// src/demo-page.ts
|
|
14
|
+
var DEMO_CSP = "default-src 'none'; style-src 'unsafe-inline'; script-src 'unsafe-inline'; connect-src 'self'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'";
|
|
15
|
+
var DEMO_PAGE = `<!doctype html>
|
|
16
|
+
<html lang="en">
|
|
17
|
+
<head>
|
|
18
|
+
<meta charset="utf-8">
|
|
19
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
20
|
+
<title>agentic-assistant demo</title>
|
|
21
|
+
<style>
|
|
22
|
+
body{font:16px/1.5 system-ui,sans-serif;max-width:42rem;margin:2rem auto;padding:0 1rem;color:#1a1a1a;background:#fff}
|
|
23
|
+
label{display:block;margin-top:1rem;font-weight:600}
|
|
24
|
+
input,textarea,button{font:inherit;padding:.5rem;width:100%;box-sizing:border-box}
|
|
25
|
+
button{width:auto;min-height:2.5rem;margin-top:1rem;cursor:pointer}
|
|
26
|
+
:focus-visible{outline:3px solid #0b57d0;outline-offset:2px}
|
|
27
|
+
#out{white-space:pre-wrap;border:1px solid #767676;padding:1rem;margin-top:1rem;min-height:4rem}
|
|
28
|
+
.badge{display:inline-block;border:1px solid #1a1a1a;padding:0 .5rem;font-size:.875rem}
|
|
29
|
+
</style>
|
|
30
|
+
</head>
|
|
31
|
+
<body>
|
|
32
|
+
<main>
|
|
33
|
+
<h1>agentic-assistant demo</h1>
|
|
34
|
+
<p>Send a message to the hosted API. You need a bearer key. The key stays in this page and goes only to this Worker.</p>
|
|
35
|
+
<form id="f">
|
|
36
|
+
<label for="key">Bearer key</label>
|
|
37
|
+
<input id="key" type="password" autocomplete="off" required>
|
|
38
|
+
<label for="msg">Message</label>
|
|
39
|
+
<textarea id="msg" rows="3" required></textarea>
|
|
40
|
+
<button type="submit">Send</button>
|
|
41
|
+
</form>
|
|
42
|
+
<h2>Answer <span class="badge">AI-generated</span></h2>
|
|
43
|
+
<div id="out" role="log" aria-live="polite" aria-label="Assistant answer, AI-generated"></div>
|
|
44
|
+
</main>
|
|
45
|
+
<script>
|
|
46
|
+
const out = document.getElementById("out");
|
|
47
|
+
document.getElementById("f").addEventListener("submit", async (e) => {
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
out.textContent = "";
|
|
50
|
+
let res;
|
|
51
|
+
try {
|
|
52
|
+
res = await fetch("/api/v1/chat", {
|
|
53
|
+
method: "POST",
|
|
54
|
+
headers: { authorization: "Bearer " + document.getElementById("key").value, "content-type": "application/json" },
|
|
55
|
+
body: JSON.stringify({ message: document.getElementById("msg").value }),
|
|
56
|
+
});
|
|
57
|
+
} catch {
|
|
58
|
+
out.textContent = "The request failed. Check the network and try again.";
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (!res.ok || !res.body) {
|
|
62
|
+
const body = await res.json().catch(() => ({}));
|
|
63
|
+
out.textContent = "Error " + res.status + ": " + (body.message || body.error || "request failed");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const reader = res.body.getReader();
|
|
67
|
+
const decoder = new TextDecoder();
|
|
68
|
+
let buffer = "";
|
|
69
|
+
let finished = false;
|
|
70
|
+
try {
|
|
71
|
+
for (;;) {
|
|
72
|
+
const { done, value } = await reader.read();
|
|
73
|
+
if (done) break;
|
|
74
|
+
buffer += decoder.decode(value, { stream: true });
|
|
75
|
+
let end;
|
|
76
|
+
while ((end = buffer.indexOf("\\n\\n")) >= 0) {
|
|
77
|
+
const block = buffer.slice(0, end);
|
|
78
|
+
buffer = buffer.slice(end + 2);
|
|
79
|
+
const data = block.split("\\n").find((l) => l.startsWith("data: "));
|
|
80
|
+
if (!data) continue;
|
|
81
|
+
let event;
|
|
82
|
+
try { event = JSON.parse(data.slice(6)); } catch { continue; }
|
|
83
|
+
if (event.type === "text_delta" && typeof event.text === "string") out.textContent += event.text;
|
|
84
|
+
if (event.type === "error") { finished = true; out.textContent += "\\n[stopped: " + event.error + "]"; }
|
|
85
|
+
if (event.type === "done") { finished = true; if (event.reason !== "end_turn") out.textContent += "\\n[stopped: " + event.reason + (event.error ? ", " + event.error : "") + "]"; }
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
} catch {
|
|
89
|
+
// The stream broke. The check below reports it.
|
|
90
|
+
}
|
|
91
|
+
if (!finished) out.textContent += "\\n[stopped: the connection closed before the answer was complete]";
|
|
92
|
+
});
|
|
93
|
+
</script>
|
|
94
|
+
</body>
|
|
95
|
+
</html>`;
|
|
96
|
+
|
|
97
|
+
// src/demo.ts
|
|
98
|
+
var demoRegistry = () => new ToolRegistry().register({
|
|
99
|
+
name: "demo_time",
|
|
100
|
+
description: "Return the current UTC time as an ISO 8601 text.",
|
|
101
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
102
|
+
scope: "demo:read",
|
|
103
|
+
risk: "safe",
|
|
104
|
+
handler: () => ({ now: (/* @__PURE__ */ new Date()).toISOString() })
|
|
105
|
+
});
|
|
106
|
+
var DEMO_SYSTEM = "You are a demo assistant. You may use the demo_time tool. Answer in short, plain text.";
|
|
107
|
+
function modelOptions(env) {
|
|
108
|
+
if (!env.MODEL_KEY) return void 0;
|
|
109
|
+
if (env.MODEL_URL) return { apiKey: env.MODEL_KEY, baseUrl: env.MODEL_URL, model: env.MODEL_NAME || void 0 };
|
|
110
|
+
if (env.MODEL_USE_DEFAULT_ENDPOINT === "1") return { apiKey: env.MODEL_KEY, useDefaultEndpoint: true, model: env.MODEL_NAME || void 0 };
|
|
111
|
+
return void 0;
|
|
112
|
+
}
|
|
113
|
+
var notConfigured = (message) => Response.json({ error: "not_configured", message }, { status: 503, headers: { "cache-control": "no-store" } });
|
|
114
|
+
var demos = /* @__PURE__ */ new WeakMap();
|
|
115
|
+
async function buildDemo(env) {
|
|
116
|
+
const tokens = env.ASSISTANT_TOKENS ? JSON.parse(env.ASSISTANT_TOKENS) : {};
|
|
117
|
+
const auth = await createStaticTokenAuth(tokens);
|
|
118
|
+
const worker = createWorker({
|
|
119
|
+
auth,
|
|
120
|
+
registry: demoRegistry(),
|
|
121
|
+
system: DEMO_SYSTEM,
|
|
122
|
+
limits: { maxTurns: 4, maxTotalTokens: 2e4, maxOutputTokensPerTurn: 1024 },
|
|
123
|
+
provider: () => {
|
|
124
|
+
const options = modelOptions(env);
|
|
125
|
+
if (options === void 0) throw new Error("no model");
|
|
126
|
+
return new AnthropicProvider(options);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return { worker, auth };
|
|
130
|
+
}
|
|
131
|
+
var demo_default = {
|
|
132
|
+
async fetch(request, env) {
|
|
133
|
+
const url = new URL(request.url);
|
|
134
|
+
if (request.method === "GET" && url.pathname === "/health") return Response.json({ ok: true, pack: env.PACK_NAME ?? "agentic-assistant", version: VERSION });
|
|
135
|
+
if (request.method === "GET" && url.pathname === "/") {
|
|
136
|
+
return new Response(DEMO_PAGE, {
|
|
137
|
+
headers: { "content-type": "text/html; charset=utf-8", "content-security-policy": DEMO_CSP, "cache-control": "no-store", "x-content-type-options": "nosniff" }
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (!url.pathname.startsWith("/api/v1/")) return Response.json({ error: "not found" }, { status: 404 });
|
|
141
|
+
let demo;
|
|
142
|
+
try {
|
|
143
|
+
let built = demos.get(env);
|
|
144
|
+
if (built === void 0) demos.set(env, built = buildDemo(env));
|
|
145
|
+
demo = await built;
|
|
146
|
+
} catch {
|
|
147
|
+
demos.delete(env);
|
|
148
|
+
return notConfigured("this demo is not set up");
|
|
149
|
+
}
|
|
150
|
+
if (request.method === "POST" && url.pathname.replace(/\/$/, "") === "/api/v1/chat" && modelOptions(env) === void 0) {
|
|
151
|
+
if (await demo.auth.authenticate(request.clone()) !== null) return notConfigured("this demo has no model key or model endpoint set");
|
|
152
|
+
}
|
|
153
|
+
return demo.worker.fetch(request, env);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
export {
|
|
157
|
+
demo_default as default
|
|
158
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,70 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export { d as ACTIONS, e as Action, b as Actor, f as ApprovalDecision, g as ApprovalGate, a as ApprovalRequest, h as Approver, i as ApproverKind, A as AssistantEvent, j as AssistantPrincipal, k as DATA_NOTICE, D as DeniedReason, c as DoneReason, P as PrincipalError, l as PrincipalInput, m as Provenance, n as ProvenanceInput, Q as QueueApprovalGate, o as RunLimits, p as RunOptions, R as RunTotals, S as Scope, T as TOOL_RISKS, q as TRAINED_ALGORITHMIC_MEDIA, r as ToolContext, s as ToolDefinition, t as ToolRegistry, u as ToolRisk, v as actorOf, w as assertPrincipal, x as canonicalJson, y as createPrincipal, z as createProvenance, B as defineTool, C as digestCall, E as hasScope, F as parseScope, G as provenanceLabel, H as provenanceMarker, I as runAssistant, J as scopeCovers } from './loop-D4qWbRu6.js';
|
|
2
|
+
import { S as Setup } from './chat-CXbhePC5.js';
|
|
3
|
+
export { C as ChatConfig, a as ChatIo, b as ConfigError, c as ConnectMcpOptions, M as McpToolInfo, d as McpTools, e as McpTransportConfig, f as buildSetup, g as connectMcpTools, p as parseTarget, r as runChat } from './chat-CXbhePC5.js';
|
|
3
4
|
import Anthropic from '@anthropic-ai/sdk';
|
|
4
|
-
import { M as ModelProvider, P as Pricing, a as ModelRequest, b as ModelEvent } from './types-
|
|
5
|
-
export { C as ContentBlock, J as JsonSchema, c as Message, d as ProviderError, S as StopReason, T as ToolSpec, U as Usage } from './types-
|
|
5
|
+
import { M as ModelProvider, P as Pricing, a as ModelRequest, b as ModelEvent } from './types-DGH8FS56.js';
|
|
6
|
+
export { A as AnsweredBy, C as ContentBlock, J as JsonSchema, c as Message, d as ProviderError, S as StopReason, T as ToolSpec, U as Usage } from './types-DGH8FS56.js';
|
|
7
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
6
8
|
|
|
7
9
|
declare const VERSION: string;
|
|
8
10
|
|
|
9
|
-
type McpTransportConfig = {
|
|
10
|
-
type: "stdio";
|
|
11
|
-
command: string;
|
|
12
|
-
args?: string[];
|
|
13
|
-
env?: Record<string, string>;
|
|
14
|
-
cwd?: string;
|
|
15
|
-
} | {
|
|
16
|
-
type: "http";
|
|
17
|
-
url: string;
|
|
18
|
-
headers?: Record<string, string>;
|
|
19
|
-
};
|
|
20
|
-
interface McpToolInfo {
|
|
21
|
-
name: string;
|
|
22
|
-
description?: string;
|
|
23
|
-
annotations?: {
|
|
24
|
-
readOnlyHint?: boolean;
|
|
25
|
-
destructiveHint?: boolean;
|
|
26
|
-
idempotentHint?: boolean;
|
|
27
|
-
openWorldHint?: boolean;
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
interface ConnectMcpOptions {
|
|
31
|
-
transport: McpTransportConfig;
|
|
32
|
-
/** The scope each tool needs. There is no default. A function can choose per tool. */
|
|
33
|
-
scope: Scope | ((tool: McpToolInfo) => Scope);
|
|
34
|
-
/** How risky each tool is. There is no default. A function can choose per tool. Do not trust the server's hints. */
|
|
35
|
-
risk: ToolRisk | ((tool: McpToolInfo) => ToolRisk);
|
|
36
|
-
/** Put before each tool name, to keep names from two servers apart. */
|
|
37
|
-
prefix?: string;
|
|
38
|
-
/** Most characters of tool output to keep. Default 32768. */
|
|
39
|
-
maxOutputChars?: number;
|
|
40
|
-
/** Most tools to load. Default 200. */
|
|
41
|
-
maxTools?: number;
|
|
42
|
-
/** Longest tool description to pass to the model. Default 1000. */
|
|
43
|
-
maxDescriptionChars?: number;
|
|
44
|
-
/** Time to wait for one tool call. Default 30000. */
|
|
45
|
-
callTimeoutMs?: number;
|
|
46
|
-
/** Time to connect and list every tool, all pages together. Default 30000. */
|
|
47
|
-
loadTimeoutMs?: number;
|
|
48
|
-
/** Most bytes to read from one HTTP response. Default 4000000. Stdio is limited by the SDK. */
|
|
49
|
-
maxResponseBytes?: number;
|
|
50
|
-
}
|
|
51
|
-
interface McpTools {
|
|
52
|
-
tools: ToolDefinition[];
|
|
53
|
-
/** Tools that were not loaded, with the reason. */
|
|
54
|
-
skipped: {
|
|
55
|
-
name: string;
|
|
56
|
-
reason: string;
|
|
57
|
-
}[];
|
|
58
|
-
close(): Promise<void>;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Connects to an MCP server and turns its tools into assistant tools. The host
|
|
62
|
-
* names the scope each tool needs. Output text is capped, and non-text content is
|
|
63
|
-
* left out. Tools with a bad name, schema, or scope are skipped, not loaded.
|
|
64
|
-
*/
|
|
65
|
-
declare function connectMcpTools(options: ConnectMcpOptions): Promise<McpTools>;
|
|
66
|
-
|
|
67
11
|
declare const DEFAULT_ANTHROPIC_MODEL = "claude-sonnet-5-5";
|
|
12
|
+
/** The day someone last compared KNOWN_PRICING with the published model table. Update it with the table. */
|
|
13
|
+
declare const PRICING_CHECKED_ON = "2026-10-29";
|
|
68
14
|
interface AnthropicProviderOptions {
|
|
69
15
|
/** Read from ANTHROPIC_API_KEY when absent. */
|
|
70
16
|
apiKey?: string;
|
|
@@ -111,4 +57,33 @@ declare class OpenAICompatibleProvider implements ModelProvider {
|
|
|
111
57
|
stream(request: ModelRequest): AsyncGenerator<ModelEvent>;
|
|
112
58
|
}
|
|
113
59
|
|
|
114
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Asks `primary`. When it refuses or fails, asks `fallback` once, with the same request.
|
|
62
|
+
* The final message says which model answered. The fallback gets no second fallback: its
|
|
63
|
+
* answer, its refusal, or its error is the result.
|
|
64
|
+
*
|
|
65
|
+
* Text from the first model is held until its turn ends, so a refused turn shows no text from
|
|
66
|
+
* it. A turn with a fallback model configured therefore streams after the turn ends, not word by word.
|
|
67
|
+
* Usage counts both asks. The price is the higher of the two, so a cost cap never counts too little.
|
|
68
|
+
* The loop sizes the output room of a turn for one ask. The fallback gets only what the first ask left of it,
|
|
69
|
+
* and the loop counts the input twice (`maxAsks`), so a cap holds. A first ask that failed after it streamed
|
|
70
|
+
* is counted by an estimate of three characters per token, and its whole input. One that failed before it
|
|
71
|
+
* streamed anything is not counted.
|
|
72
|
+
*/
|
|
73
|
+
declare class FallbackProvider implements ModelProvider {
|
|
74
|
+
private readonly primary;
|
|
75
|
+
private readonly fallback;
|
|
76
|
+
readonly name: string;
|
|
77
|
+
readonly model: string;
|
|
78
|
+
readonly pricing?: Pricing;
|
|
79
|
+
readonly maxAsks: number;
|
|
80
|
+
constructor(primary: ModelProvider, fallback: ModelProvider);
|
|
81
|
+
stream(request: ModelRequest): AsyncGenerator<ModelEvent>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** An MCP server with one tool, `assistant_chat`. Each call starts a new conversation. */
|
|
85
|
+
declare function createAssistantMcpServer(setup: Setup, shutdown?: AbortSignal): Server;
|
|
86
|
+
/** Serves on stdio. Resolves when the client closes its input, or the transport closes. */
|
|
87
|
+
declare function startAssistantMcp(setup: Setup): Promise<void>;
|
|
88
|
+
|
|
89
|
+
export { AnthropicProvider, type AnthropicProviderOptions, DEFAULT_ANTHROPIC_MODEL, FallbackProvider, ModelEvent, ModelProvider, ModelRequest, type OpenAICompatibleOptions, OpenAICompatibleProvider, PRICING_CHECKED_ON, Pricing, Setup, VERSION, createAssistantMcpServer, startAssistantMcp };
|