@immediately-run/sdk 0.57.1 → 0.57.4
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/dist/agentChatClient.cjs +112 -0
- package/dist/agentChatClient.cjs.map +1 -0
- package/dist/agentChatClient.d.cts +9 -0
- package/dist/agentChatClient.d.ts +9 -0
- package/dist/agentChatClient.js +89 -0
- package/dist/agentChatClient.js.map +1 -0
- package/dist/agentContext.cjs +69 -0
- package/dist/agentContext.cjs.map +1 -0
- package/dist/agentContext.d.cts +45 -0
- package/dist/agentContext.d.ts +45 -0
- package/dist/agentContext.js +45 -0
- package/dist/agentContext.js.map +1 -0
- package/dist/agentLoop.cjs +301 -0
- package/dist/agentLoop.cjs.map +1 -0
- package/dist/agentLoop.d.cts +267 -0
- package/dist/agentLoop.d.ts +267 -0
- package/dist/agentLoop.js +271 -0
- package/dist/agentLoop.js.map +1 -0
- package/dist/agentSteering.cjs +127 -0
- package/dist/agentSteering.cjs.map +1 -0
- package/dist/agentSteering.d.cts +80 -0
- package/dist/agentSteering.d.ts +80 -0
- package/dist/agentSteering.js +98 -0
- package/dist/agentSteering.js.map +1 -0
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +33 -2
- package/dist/auth.d.ts +33 -2
- package/dist/auth.js.map +1 -1
- package/dist/bundle.cjs +91 -0
- package/dist/bundle.cjs.map +1 -0
- package/dist/bundle.d.cts +63 -0
- package/dist/bundle.d.ts +63 -0
- package/dist/bundle.js +62 -0
- package/dist/bundle.js.map +1 -0
- package/dist/collectHeadings.cjs +59 -0
- package/dist/collectHeadings.cjs.map +1 -0
- package/dist/collectHeadings.d.cts +16 -0
- package/dist/collectHeadings.d.ts +16 -0
- package/dist/collectHeadings.js +36 -0
- package/dist/collectHeadings.js.map +1 -0
- package/dist/corpus.cjs +9 -58
- package/dist/corpus.cjs.map +1 -1
- package/dist/corpus.d.cts +3 -63
- package/dist/corpus.d.ts +3 -63
- package/dist/corpus.js +15 -57
- package/dist/corpus.js.map +1 -1
- package/dist/debug.cjs +115 -0
- package/dist/debug.cjs.map +1 -1
- package/dist/debug.js +115 -0
- package/dist/debug.js.map +1 -1
- package/dist/fence.cjs +49 -0
- package/dist/fence.cjs.map +1 -0
- package/dist/fence.d.cts +4 -0
- package/dist/fence.d.ts +4 -0
- package/dist/fence.js +26 -0
- package/dist/fence.js.map +1 -0
- package/dist/formFactor.cjs.map +1 -1
- package/dist/formFactor.d.cts +11 -2
- package/dist/formFactor.d.ts +11 -2
- package/dist/formFactor.js.map +1 -1
- package/dist/fs.cjs.map +1 -1
- package/dist/fs.d.cts +16 -6
- package/dist/fs.d.ts +16 -6
- package/dist/fs.js.map +1 -1
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.cts +7 -0
- package/dist/hooks.d.ts +7 -0
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +19 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/launch.cjs +45 -6
- package/dist/launch.cjs.map +1 -1
- package/dist/launch.d.cts +3 -0
- package/dist/launch.d.ts +3 -0
- package/dist/launch.js +45 -6
- package/dist/launch.js.map +1 -1
- package/dist/llm.cjs.map +1 -1
- package/dist/llm.d.cts +20 -3
- package/dist/llm.d.ts +20 -3
- package/dist/llm.js.map +1 -1
- package/dist/metadataQueryTool.cjs +271 -0
- package/dist/metadataQueryTool.cjs.map +1 -0
- package/dist/metadataQueryTool.d.cts +159 -0
- package/dist/metadataQueryTool.d.ts +159 -0
- package/dist/metadataQueryTool.js +241 -0
- package/dist/metadataQueryTool.js.map +1 -0
- package/dist/mounts.cjs.map +1 -1
- package/dist/mounts.d.cts +22 -3
- package/dist/mounts.d.ts +22 -3
- package/dist/mounts.js.map +1 -1
- package/dist/onFsChange.cjs +13 -1
- package/dist/onFsChange.cjs.map +1 -1
- package/dist/onFsChange.d.cts +21 -1
- package/dist/onFsChange.d.ts +21 -1
- package/dist/onFsChange.js +13 -1
- package/dist/onFsChange.js.map +1 -1
- package/dist/protocolSchemes.cjs +1 -0
- package/dist/protocolSchemes.cjs.map +1 -1
- package/dist/protocolSchemes.d.cts +1 -0
- package/dist/protocolSchemes.d.ts +1 -0
- package/dist/protocolSchemes.js +2 -0
- package/dist/protocolSchemes.js.map +1 -1
- package/dist/recents.cjs +41 -0
- package/dist/recents.cjs.map +1 -0
- package/dist/recents.d.cts +23 -0
- package/dist/recents.d.ts +23 -0
- package/dist/recents.js +17 -0
- package/dist/recents.js.map +1 -0
- package/dist/tasks.cjs +41 -7
- package/dist/tasks.cjs.map +1 -1
- package/dist/tasks.d.cts +136 -7
- package/dist/tasks.d.ts +136 -7
- package/dist/tasks.js +39 -7
- package/dist/tasks.js.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.cts +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +6 -5
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var agentChatClient_exports = {};
|
|
20
|
+
__export(agentChatClient_exports, {
|
|
21
|
+
createChatModelClient: () => createChatModelClient
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(agentChatClient_exports);
|
|
24
|
+
var import_llm = require("./llm");
|
|
25
|
+
function toChatMessages(system, messages) {
|
|
26
|
+
const out = [];
|
|
27
|
+
if (system) out.push({ role: "system", content: [{ type: "text", text: system }] });
|
|
28
|
+
for (const m of messages) {
|
|
29
|
+
const content = m.content.map((b) => {
|
|
30
|
+
if (b.type === "text") return { type: "text", text: b.text };
|
|
31
|
+
if (b.type === "tool_use") return { type: "tool-use", id: b.id, name: b.name, input: b.input };
|
|
32
|
+
if (b.type === "image") return { type: "image", mimeType: b.mimeType, data: b.data };
|
|
33
|
+
if (b.type === "reasoning") {
|
|
34
|
+
return b.redactedData !== void 0 ? { type: "reasoning-redacted", data: b.redactedData } : { type: "reasoning", text: b.text, ...b.signature ? { signature: b.signature } : {} };
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
type: "tool-result",
|
|
38
|
+
toolCallId: b.tool_use_id,
|
|
39
|
+
content: b.content,
|
|
40
|
+
...b.is_error ? { isError: true } : {}
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
out.push({ role: m.role, content });
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
function toChatTools(tools) {
|
|
48
|
+
return tools.map((t) => ({ name: t.name, description: t.description, inputSchema: t.input_schema }));
|
|
49
|
+
}
|
|
50
|
+
const mapStop = (s) => s === "tool" ? "tool_use" : s === "length" ? "max_tokens" : "end_turn";
|
|
51
|
+
function createChatModelClient() {
|
|
52
|
+
return {
|
|
53
|
+
async createMessage(req) {
|
|
54
|
+
const chatReq = {
|
|
55
|
+
messages: toChatMessages(req.system, req.messages),
|
|
56
|
+
...req.tools.length ? { tools: toChatTools(req.tools) } : {},
|
|
57
|
+
modelHint: "smart",
|
|
58
|
+
// Hand the loop's abort signal to the host so a stop aborts the in-flight
|
|
59
|
+
// upstream request (host stops generating + billing), not just the app-side
|
|
60
|
+
// iterator. `chat()` peels it off before the wire params.
|
|
61
|
+
...req.signal ? { signal: req.signal } : {}
|
|
62
|
+
};
|
|
63
|
+
let text = "";
|
|
64
|
+
const toolUses = [];
|
|
65
|
+
const reasoning = [];
|
|
66
|
+
let stopReason = "end_turn";
|
|
67
|
+
let usage;
|
|
68
|
+
const gen = (0, import_llm.chat)(chatReq);
|
|
69
|
+
for (; ; ) {
|
|
70
|
+
const step = await gen.next();
|
|
71
|
+
if (step.done) {
|
|
72
|
+
stopReason = mapStop(step.value.stopReason);
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
const d = step.value;
|
|
76
|
+
if (d.type === "text-delta") {
|
|
77
|
+
text += d.text;
|
|
78
|
+
req.onTextDelta?.(d.text);
|
|
79
|
+
} else if (d.type === "tool-call") {
|
|
80
|
+
toolUses.push({
|
|
81
|
+
type: "tool_use",
|
|
82
|
+
id: d.id,
|
|
83
|
+
name: d.name,
|
|
84
|
+
input: d.input ?? {}
|
|
85
|
+
});
|
|
86
|
+
} else if (d.type === "reasoning-delta") {
|
|
87
|
+
req.onReasoningDelta?.(d.text);
|
|
88
|
+
} else if (d.type === "reasoning") {
|
|
89
|
+
reasoning.push({ type: "reasoning", text: d.text, ...d.signature ? { signature: d.signature } : {} });
|
|
90
|
+
} else if (d.type === "reasoning-redacted") {
|
|
91
|
+
reasoning.push({ type: "reasoning", text: "", redactedData: d.data });
|
|
92
|
+
} else if (d.type === "usage") {
|
|
93
|
+
usage = {
|
|
94
|
+
inputTokens: d.inputTokens,
|
|
95
|
+
outputTokens: d.outputTokens,
|
|
96
|
+
...d.cacheReadTokens !== void 0 ? { cacheReadTokens: d.cacheReadTokens } : {},
|
|
97
|
+
...d.cacheWriteTokens !== void 0 ? { cacheWriteTokens: d.cacheWriteTokens } : {}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const content = [...reasoning];
|
|
102
|
+
if (text) content.push({ type: "text", text });
|
|
103
|
+
content.push(...toolUses);
|
|
104
|
+
return { content, stopReason, ...usage ? { usage } : {} };
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
109
|
+
0 && (module.exports = {
|
|
110
|
+
createChatModelClient
|
|
111
|
+
});
|
|
112
|
+
//# sourceMappingURL=agentChatClient.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/agentChatClient.ts"],"sourcesContent":["// A {@link ModelClient} (the `agentLoop.ts` provider seam) backed by the host\n// `llm.chat` slot — the SDK {@link chat} stream. PORTED from agent-demo\n// `src/lib/chatModelClient.ts` (GROVE_AGENT_SPEC §7: the loop seam, shared).\n//\n// The provider AND the model are the USER's host-side preference — this client names\n// neither. The app holds no secret/`net:fetch` grant; it needs only the `llm:chat`\n// capability (elevated, app-scoped: a fork earns it by ordinary consent).\nimport { chat } from './llm';\nimport type { ChatRequest, ChatDelta, ContentPart } from './llm';\nimport type { AgentMessage, ModelClient, ReasoningBlock, TextBlock, TokenUsage, ToolUseBlock } from './agentLoop';\nimport type { AgentTool } from './agentLoop';\n\n// The loop's Anthropic-shaped conversation → the chat slot's tool-aware ChatRequest.\n// The agentic history round-trips: a `tool_use` block becomes a `tool-use` content\n// part, a `tool_result` becomes a `tool-result` part.\nfunction toChatMessages(system: string | undefined, messages: AgentMessage[]): ChatRequest['messages'] {\n const out: ChatRequest['messages'] = [];\n if (system) out.push({ role: 'system', content: [{ type: 'text', text: system }] });\n for (const m of messages) {\n const content: ContentPart[] = m.content.map((b): ContentPart => {\n if (b.type === 'text') return { type: 'text', text: b.text };\n if (b.type === 'tool_use') return { type: 'tool-use', id: b.id, name: b.name, input: b.input };\n // An image the model should LOOK at (the transport already accepts it when the\n // provider advertises `features.vision`).\n if (b.type === 'image') return { type: 'image', mimeType: b.mimeType, data: b.data };\n // Echo the model's own reasoning back. Some providers REQUIRE it (with its\n // signature) for the next turn of a tool-use chain to be accepted; the host\n // adapter puts it in the position that provider wants.\n if (b.type === 'reasoning') {\n return b.redactedData !== undefined\n ? { type: 'reasoning-redacted', data: b.redactedData }\n : { type: 'reasoning', text: b.text, ...(b.signature ? { signature: b.signature } : {}) };\n }\n return {\n type: 'tool-result',\n toolCallId: b.tool_use_id,\n content: b.content,\n ...(b.is_error ? { isError: true } : {}),\n };\n });\n out.push({ role: m.role, content });\n }\n return out;\n}\n\nfunction toChatTools(tools: AgentTool[]): NonNullable<ChatRequest['tools']> {\n return tools.map((t) => ({ name: t.name, description: t.description, inputSchema: t.input_schema }));\n}\n\n// ChatResult.stopReason ('end'|'length'|'tool'|'filtered') → the loop's\n// Anthropic-style stop reason (the loop branches on 'tool_use' to keep iterating).\nconst mapStop = (s: string): string => (s === 'tool' ? 'tool_use' : s === 'length' ? 'max_tokens' : 'end_turn');\n\n/** A {@link ModelClient} over the host `llm.chat` slot. Streams text deltas (forwarded\n * to `onTextDelta`) and assembles tool calls; the resolved provider + model are the\n * user's preference, never named here. Requires the `llm:chat` capability. */\nexport function createChatModelClient(): ModelClient {\n return {\n async createMessage(req) {\n const chatReq: ChatRequest = {\n messages: toChatMessages(req.system, req.messages),\n ...(req.tools.length ? { tools: toChatTools(req.tools) } : {}),\n modelHint: 'smart',\n // Hand the loop's abort signal to the host so a stop aborts the in-flight\n // upstream request (host stops generating + billing), not just the app-side\n // iterator. `chat()` peels it off before the wire params.\n ...(req.signal ? { signal: req.signal } : {}),\n };\n let text = '';\n const toolUses: ToolUseBlock[] = [];\n // Reasoning blocks for this turn, in the order the provider emitted them.\n const reasoning: ReasoningBlock[] = [];\n let stopReason = 'end_turn';\n // The provider `usage` delta — the loop reads it to drive compaction/spend\n // rather than discarding it. Absent when the provider reports none; the loop\n // then falls back to a char/4 estimate.\n let usage: TokenUsage | undefined;\n const gen = chat(chatReq);\n for (;;) {\n const step = await gen.next();\n if (step.done) {\n stopReason = mapStop(step.value.stopReason);\n break;\n }\n const d: ChatDelta = step.value;\n if (d.type === 'text-delta') {\n text += d.text;\n req.onTextDelta?.(d.text);\n } else if (d.type === 'tool-call') {\n toolUses.push({\n type: 'tool_use',\n id: d.id,\n name: d.name,\n input: (d.input ?? {}) as Record<string, unknown>,\n });\n } else if (d.type === 'reasoning-delta') {\n // Live only — the WHOLE block arrives as its own delta, carrying the\n // signature. Accumulating the slices here instead would silently lose it.\n req.onReasoningDelta?.(d.text);\n } else if (d.type === 'reasoning') {\n reasoning.push({ type: 'reasoning', text: d.text, ...(d.signature ? { signature: d.signature } : {}) });\n } else if (d.type === 'reasoning-redacted') {\n reasoning.push({ type: 'reasoning', text: '', redactedData: d.data });\n } else if (d.type === 'usage') {\n // Carry the cache counters through verbatim, INCLUDING their absence: a\n // provider that reports nothing must not look like one that cached nothing.\n usage = {\n inputTokens: d.inputTokens,\n outputTokens: d.outputTokens,\n ...(d.cacheReadTokens !== undefined ? { cacheReadTokens: d.cacheReadTokens } : {}),\n ...(d.cacheWriteTokens !== undefined ? { cacheWriteTokens: d.cacheWriteTokens } : {}),\n };\n }\n }\n // Reasoning comes FIRST in the turn: it is what the model did before answering,\n // and it is the order a provider that requires the echo expects to read back.\n const content: (TextBlock | ToolUseBlock | ReasoningBlock)[] = [...reasoning];\n if (text) content.push({ type: 'text', text });\n content.push(...toolUses);\n return { content, stopReason, ...(usage ? { usage } : {}) };\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ModelClient } from './agentLoop.cjs';
|
|
2
|
+
import './agentSteering.cjs';
|
|
3
|
+
|
|
4
|
+
/** A {@link ModelClient} over the host `llm.chat` slot. Streams text deltas (forwarded
|
|
5
|
+
* to `onTextDelta`) and assembles tool calls; the resolved provider + model are the
|
|
6
|
+
* user's preference, never named here. Requires the `llm:chat` capability. */
|
|
7
|
+
declare function createChatModelClient(): ModelClient;
|
|
8
|
+
|
|
9
|
+
export { createChatModelClient };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ModelClient } from './agentLoop.js';
|
|
2
|
+
import './agentSteering.js';
|
|
3
|
+
|
|
4
|
+
/** A {@link ModelClient} over the host `llm.chat` slot. Streams text deltas (forwarded
|
|
5
|
+
* to `onTextDelta`) and assembles tool calls; the resolved provider + model are the
|
|
6
|
+
* user's preference, never named here. Requires the `llm:chat` capability. */
|
|
7
|
+
declare function createChatModelClient(): ModelClient;
|
|
8
|
+
|
|
9
|
+
export { createChatModelClient };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import "./chunk-VHAA22YE.js";
|
|
2
|
+
import { chat } from "./llm";
|
|
3
|
+
function toChatMessages(system, messages) {
|
|
4
|
+
const out = [];
|
|
5
|
+
if (system) out.push({ role: "system", content: [{ type: "text", text: system }] });
|
|
6
|
+
for (const m of messages) {
|
|
7
|
+
const content = m.content.map((b) => {
|
|
8
|
+
if (b.type === "text") return { type: "text", text: b.text };
|
|
9
|
+
if (b.type === "tool_use") return { type: "tool-use", id: b.id, name: b.name, input: b.input };
|
|
10
|
+
if (b.type === "image") return { type: "image", mimeType: b.mimeType, data: b.data };
|
|
11
|
+
if (b.type === "reasoning") {
|
|
12
|
+
return b.redactedData !== void 0 ? { type: "reasoning-redacted", data: b.redactedData } : { type: "reasoning", text: b.text, ...b.signature ? { signature: b.signature } : {} };
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
type: "tool-result",
|
|
16
|
+
toolCallId: b.tool_use_id,
|
|
17
|
+
content: b.content,
|
|
18
|
+
...b.is_error ? { isError: true } : {}
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
out.push({ role: m.role, content });
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
}
|
|
25
|
+
function toChatTools(tools) {
|
|
26
|
+
return tools.map((t) => ({ name: t.name, description: t.description, inputSchema: t.input_schema }));
|
|
27
|
+
}
|
|
28
|
+
const mapStop = (s) => s === "tool" ? "tool_use" : s === "length" ? "max_tokens" : "end_turn";
|
|
29
|
+
function createChatModelClient() {
|
|
30
|
+
return {
|
|
31
|
+
async createMessage(req) {
|
|
32
|
+
const chatReq = {
|
|
33
|
+
messages: toChatMessages(req.system, req.messages),
|
|
34
|
+
...req.tools.length ? { tools: toChatTools(req.tools) } : {},
|
|
35
|
+
modelHint: "smart",
|
|
36
|
+
// Hand the loop's abort signal to the host so a stop aborts the in-flight
|
|
37
|
+
// upstream request (host stops generating + billing), not just the app-side
|
|
38
|
+
// iterator. `chat()` peels it off before the wire params.
|
|
39
|
+
...req.signal ? { signal: req.signal } : {}
|
|
40
|
+
};
|
|
41
|
+
let text = "";
|
|
42
|
+
const toolUses = [];
|
|
43
|
+
const reasoning = [];
|
|
44
|
+
let stopReason = "end_turn";
|
|
45
|
+
let usage;
|
|
46
|
+
const gen = chat(chatReq);
|
|
47
|
+
for (; ; ) {
|
|
48
|
+
const step = await gen.next();
|
|
49
|
+
if (step.done) {
|
|
50
|
+
stopReason = mapStop(step.value.stopReason);
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
const d = step.value;
|
|
54
|
+
if (d.type === "text-delta") {
|
|
55
|
+
text += d.text;
|
|
56
|
+
req.onTextDelta?.(d.text);
|
|
57
|
+
} else if (d.type === "tool-call") {
|
|
58
|
+
toolUses.push({
|
|
59
|
+
type: "tool_use",
|
|
60
|
+
id: d.id,
|
|
61
|
+
name: d.name,
|
|
62
|
+
input: d.input ?? {}
|
|
63
|
+
});
|
|
64
|
+
} else if (d.type === "reasoning-delta") {
|
|
65
|
+
req.onReasoningDelta?.(d.text);
|
|
66
|
+
} else if (d.type === "reasoning") {
|
|
67
|
+
reasoning.push({ type: "reasoning", text: d.text, ...d.signature ? { signature: d.signature } : {} });
|
|
68
|
+
} else if (d.type === "reasoning-redacted") {
|
|
69
|
+
reasoning.push({ type: "reasoning", text: "", redactedData: d.data });
|
|
70
|
+
} else if (d.type === "usage") {
|
|
71
|
+
usage = {
|
|
72
|
+
inputTokens: d.inputTokens,
|
|
73
|
+
outputTokens: d.outputTokens,
|
|
74
|
+
...d.cacheReadTokens !== void 0 ? { cacheReadTokens: d.cacheReadTokens } : {},
|
|
75
|
+
...d.cacheWriteTokens !== void 0 ? { cacheWriteTokens: d.cacheWriteTokens } : {}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const content = [...reasoning];
|
|
80
|
+
if (text) content.push({ type: "text", text });
|
|
81
|
+
content.push(...toolUses);
|
|
82
|
+
return { content, stopReason, ...usage ? { usage } : {} };
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export {
|
|
87
|
+
createChatModelClient
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=agentChatClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/agentChatClient.ts"],"sourcesContent":["// A {@link ModelClient} (the `agentLoop.ts` provider seam) backed by the host\n// `llm.chat` slot — the SDK {@link chat} stream. PORTED from agent-demo\n// `src/lib/chatModelClient.ts` (GROVE_AGENT_SPEC §7: the loop seam, shared).\n//\n// The provider AND the model are the USER's host-side preference — this client names\n// neither. The app holds no secret/`net:fetch` grant; it needs only the `llm:chat`\n// capability (elevated, app-scoped: a fork earns it by ordinary consent).\nimport { chat } from './llm';\nimport type { ChatRequest, ChatDelta, ContentPart } from './llm';\nimport type { AgentMessage, ModelClient, ReasoningBlock, TextBlock, TokenUsage, ToolUseBlock } from './agentLoop';\nimport type { AgentTool } from './agentLoop';\n\n// The loop's Anthropic-shaped conversation → the chat slot's tool-aware ChatRequest.\n// The agentic history round-trips: a `tool_use` block becomes a `tool-use` content\n// part, a `tool_result` becomes a `tool-result` part.\nfunction toChatMessages(system: string | undefined, messages: AgentMessage[]): ChatRequest['messages'] {\n const out: ChatRequest['messages'] = [];\n if (system) out.push({ role: 'system', content: [{ type: 'text', text: system }] });\n for (const m of messages) {\n const content: ContentPart[] = m.content.map((b): ContentPart => {\n if (b.type === 'text') return { type: 'text', text: b.text };\n if (b.type === 'tool_use') return { type: 'tool-use', id: b.id, name: b.name, input: b.input };\n // An image the model should LOOK at (the transport already accepts it when the\n // provider advertises `features.vision`).\n if (b.type === 'image') return { type: 'image', mimeType: b.mimeType, data: b.data };\n // Echo the model's own reasoning back. Some providers REQUIRE it (with its\n // signature) for the next turn of a tool-use chain to be accepted; the host\n // adapter puts it in the position that provider wants.\n if (b.type === 'reasoning') {\n return b.redactedData !== undefined\n ? { type: 'reasoning-redacted', data: b.redactedData }\n : { type: 'reasoning', text: b.text, ...(b.signature ? { signature: b.signature } : {}) };\n }\n return {\n type: 'tool-result',\n toolCallId: b.tool_use_id,\n content: b.content,\n ...(b.is_error ? { isError: true } : {}),\n };\n });\n out.push({ role: m.role, content });\n }\n return out;\n}\n\nfunction toChatTools(tools: AgentTool[]): NonNullable<ChatRequest['tools']> {\n return tools.map((t) => ({ name: t.name, description: t.description, inputSchema: t.input_schema }));\n}\n\n// ChatResult.stopReason ('end'|'length'|'tool'|'filtered') → the loop's\n// Anthropic-style stop reason (the loop branches on 'tool_use' to keep iterating).\nconst mapStop = (s: string): string => (s === 'tool' ? 'tool_use' : s === 'length' ? 'max_tokens' : 'end_turn');\n\n/** A {@link ModelClient} over the host `llm.chat` slot. Streams text deltas (forwarded\n * to `onTextDelta`) and assembles tool calls; the resolved provider + model are the\n * user's preference, never named here. Requires the `llm:chat` capability. */\nexport function createChatModelClient(): ModelClient {\n return {\n async createMessage(req) {\n const chatReq: ChatRequest = {\n messages: toChatMessages(req.system, req.messages),\n ...(req.tools.length ? { tools: toChatTools(req.tools) } : {}),\n modelHint: 'smart',\n // Hand the loop's abort signal to the host so a stop aborts the in-flight\n // upstream request (host stops generating + billing), not just the app-side\n // iterator. `chat()` peels it off before the wire params.\n ...(req.signal ? { signal: req.signal } : {}),\n };\n let text = '';\n const toolUses: ToolUseBlock[] = [];\n // Reasoning blocks for this turn, in the order the provider emitted them.\n const reasoning: ReasoningBlock[] = [];\n let stopReason = 'end_turn';\n // The provider `usage` delta — the loop reads it to drive compaction/spend\n // rather than discarding it. Absent when the provider reports none; the loop\n // then falls back to a char/4 estimate.\n let usage: TokenUsage | undefined;\n const gen = chat(chatReq);\n for (;;) {\n const step = await gen.next();\n if (step.done) {\n stopReason = mapStop(step.value.stopReason);\n break;\n }\n const d: ChatDelta = step.value;\n if (d.type === 'text-delta') {\n text += d.text;\n req.onTextDelta?.(d.text);\n } else if (d.type === 'tool-call') {\n toolUses.push({\n type: 'tool_use',\n id: d.id,\n name: d.name,\n input: (d.input ?? {}) as Record<string, unknown>,\n });\n } else if (d.type === 'reasoning-delta') {\n // Live only — the WHOLE block arrives as its own delta, carrying the\n // signature. Accumulating the slices here instead would silently lose it.\n req.onReasoningDelta?.(d.text);\n } else if (d.type === 'reasoning') {\n reasoning.push({ type: 'reasoning', text: d.text, ...(d.signature ? { signature: d.signature } : {}) });\n } else if (d.type === 'reasoning-redacted') {\n reasoning.push({ type: 'reasoning', text: '', redactedData: d.data });\n } else if (d.type === 'usage') {\n // Carry the cache counters through verbatim, INCLUDING their absence: a\n // provider that reports nothing must not look like one that cached nothing.\n usage = {\n inputTokens: d.inputTokens,\n outputTokens: d.outputTokens,\n ...(d.cacheReadTokens !== undefined ? { cacheReadTokens: d.cacheReadTokens } : {}),\n ...(d.cacheWriteTokens !== undefined ? { cacheWriteTokens: d.cacheWriteTokens } : {}),\n };\n }\n }\n // Reasoning comes FIRST in the turn: it is what the model did before answering,\n // and it is the order a provider that requires the echo expects to read back.\n const content: (TextBlock | ToolUseBlock | ReasoningBlock)[] = [...reasoning];\n if (text) content.push({ type: 'text', text });\n content.push(...toolUses);\n return { content, stopReason, ...(usage ? { usage } : {}) };\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var agentContext_exports = {};
|
|
20
|
+
__export(agentContext_exports, {
|
|
21
|
+
renderAgentContext: () => renderAgentContext,
|
|
22
|
+
useAgentContext: () => useAgentContext
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(agentContext_exports);
|
|
25
|
+
var import_react = require("react");
|
|
26
|
+
var import_TinkerableContext = require("./TinkerableContext");
|
|
27
|
+
var import_auth = require("./auth");
|
|
28
|
+
var import_mounts = require("./mounts");
|
|
29
|
+
var import_fence = require("./fence");
|
|
30
|
+
function useAgentContext(app = {}) {
|
|
31
|
+
const tinker = (0, import_react.useContext)(import_TinkerableContext.TinkerableContext);
|
|
32
|
+
const auth = (0, import_auth.useAuth)();
|
|
33
|
+
const mounts = (0, import_mounts.useMounts)();
|
|
34
|
+
const nav = tinker?.navigationState;
|
|
35
|
+
return {
|
|
36
|
+
repository: nav?.repository ?? "",
|
|
37
|
+
revision: nav?.ref ?? "",
|
|
38
|
+
...auth.status === "signed-in" || auth.status === "signed-out" ? { signedIn: auth.status === "signed-in" } : {},
|
|
39
|
+
// unknown ⇒ omitted, never guessed
|
|
40
|
+
mounts: mounts.map((m) => ({ path: m.path, ...m.mode ? { mode: m.mode } : {} })),
|
|
41
|
+
// Fail-closed (PERSISTENCE §7A.6): a git-backed source classifies shared until
|
|
42
|
+
// sole authorship of the full reachable history is verifiable — which it is not
|
|
43
|
+
// today — so both packagings (dispatched repo, fork's own repo) read as
|
|
44
|
+
// "treated as if others can write".
|
|
45
|
+
sourceShared: true,
|
|
46
|
+
sourceSharedBasis: "git-indeterminate",
|
|
47
|
+
...app
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function renderAgentContext(block) {
|
|
51
|
+
const payload = {
|
|
52
|
+
repository: block.repository,
|
|
53
|
+
revision: block.revision,
|
|
54
|
+
...block.signedIn === void 0 ? {} : { signedIn: block.signedIn },
|
|
55
|
+
mounts: block.mounts,
|
|
56
|
+
sourceShared: block.sourceShared,
|
|
57
|
+
...block.entryPath !== void 0 ? { entryPath: block.entryPath } : {},
|
|
58
|
+
...block.entryTitle !== void 0 ? { entryTitle: block.entryTitle } : {},
|
|
59
|
+
...block.heading !== void 0 ? { heading: block.heading } : {},
|
|
60
|
+
...block.selection !== void 0 ? { selection: block.selection } : {}
|
|
61
|
+
};
|
|
62
|
+
return (0, import_fence.fenceUntrusted)("agent-context", JSON.stringify(payload, null, 2));
|
|
63
|
+
}
|
|
64
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
65
|
+
0 && (module.exports = {
|
|
66
|
+
renderAgentContext,
|
|
67
|
+
useAgentContext
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=agentContext.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/agentContext.tsx"],"sourcesContent":["// The deixis context block (GROVE_AGENT_SPEC §5) — platform primitive B.\n//\n// The user's first questions are indexical: *this* wiki, *this* entry, *this*\n// section. The agent should never need a tool call to know where it is. The SDK\n// assembles the PLATFORM half (repository/ref, sign-in status, mounts, source trust)\n// and the app spreads in its local fields (entry, heading, selection).\n//\n// TWO RULES (normative, G-GA-5):\n// 1. The block is DATA IN A FENCE — never instructions (threat_model P8) — and it\n// EGRESSES to the provider like everything else in the prompt (R-GA-6), which\n// is exactly why identity stays out: `signedIn` is a boolean from the baseline\n// `auth:status` projection; the login/user belongs to `auth:identity`, and\n// collapsing that split (threat_model T6) widens the egress for convenience.\n// 2. `signedIn` is OMITTED while auth status is `unknown` — three states, because\n// collapsing `unknown` to `false` is the R3-300 false-banner bug class.\nimport { useContext } from 'react';\nimport { TinkerableContext } from './TinkerableContext';\nimport { useAuth } from './auth';\nimport { useMounts } from './mounts';\nimport { fenceUntrusted } from './fence';\n\n/** The app-local half of the deixis block — supplied by the app at call time. */\nexport interface AgentContextAppFields {\n /** The entry the reader is on (app router's key/path). */\n entryPath?: string;\n /** Its display title. */\n entryTitle?: string;\n /** The `#fragment` the app resolved — \"the section you're looking at\". */\n heading?: string;\n /** Future: selected text as deixis. */\n selection?: string;\n}\n\n/** The whole block, as it enters the loop. */\nexport interface AgentContextBlock {\n repository: string;\n revision: string;\n /** Omitted while auth status is `unknown` (R3-300). Status only — never identity. */\n signedIn?: boolean;\n mounts: Array<{ path: string; mode?: string }>;\n /** Whether the source is treated as \"others can write here\" (feeds the reach\n * card's row and the copy under it). */\n sourceShared: boolean;\n /** Why `sourceShared` reads as it does — today the git classifier is fail-closed\n * indeterminate (`PERSISTENCE §7A.6` Q11), so a git-backed corpus is treated as\n * shared with the softer copy; a mount trust-mode API would replace this basis. */\n sourceSharedBasis: 'git-indeterminate' | 'mount-trust-mode';\n entryPath?: string;\n entryTitle?: string;\n heading?: string;\n selection?: string;\n}\n\n/**\n * Assemble the deixis block: the platform fields from the SDK's own state, the app's\n * local fields spread in. Additive-only; the app passes new local fields as they\n * exist.\n */\nexport function useAgentContext(app: AgentContextAppFields = {}): AgentContextBlock {\n const tinker = useContext(TinkerableContext);\n const auth = useAuth();\n const mounts = useMounts();\n const nav = tinker?.navigationState;\n return {\n repository: nav?.repository ?? '',\n revision: nav?.ref ?? '',\n ...(auth.status === 'signed-in' || auth.status === 'signed-out' ? { signedIn: auth.status === 'signed-in' } : {}), // unknown ⇒ omitted, never guessed\n mounts: mounts.map((m) => ({ path: m.path, ...(m.mode ? { mode: m.mode } : {}) })),\n // Fail-closed (PERSISTENCE §7A.6): a git-backed source classifies shared until\n // sole authorship of the full reachable history is verifiable — which it is not\n // today — so both packagings (dispatched repo, fork's own repo) read as\n // \"treated as if others can write\".\n sourceShared: true,\n sourceSharedBasis: 'git-indeterminate',\n ...app,\n };\n}\n\n/** Serialize the block as the fenced data segment that enters the system prompt.\n * Every field is attacker-influenced only through repo/mount metadata — still, the\n * fence is unconditional (R-GA-7): the block is corpus-derived data. */\nexport function renderAgentContext(block: AgentContextBlock): string {\n // Field allowlist, deliberately: nothing joins the prompt except the fields named\n // here (G-GA-5's allowlist assertion reads this shape).\n const payload = {\n repository: block.repository,\n revision: block.revision,\n ...(block.signedIn === undefined ? {} : { signedIn: block.signedIn }),\n mounts: block.mounts,\n sourceShared: block.sourceShared,\n ...(block.entryPath !== undefined ? { entryPath: block.entryPath } : {}),\n ...(block.entryTitle !== undefined ? { entryTitle: block.entryTitle } : {}),\n ...(block.heading !== undefined ? { heading: block.heading } : {}),\n ...(block.selection !== undefined ? { selection: block.selection } : {}),\n };\n return fenceUntrusted('agent-context', JSON.stringify(payload, null, 2));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeA,mBAA2B;AAC3B,+BAAkC;AAClC,kBAAwB;AACxB,oBAA0B;AAC1B,mBAA+B;AAuCxB,SAAS,gBAAgB,MAA6B,CAAC,GAAsB;AAClF,QAAM,aAAS,yBAAW,0CAAiB;AAC3C,QAAM,WAAO,qBAAQ;AACrB,QAAM,aAAS,yBAAU;AACzB,QAAM,MAAM,QAAQ;AACpB,SAAO;AAAA,IACL,YAAY,KAAK,cAAc;AAAA,IAC/B,UAAU,KAAK,OAAO;AAAA,IACtB,GAAI,KAAK,WAAW,eAAe,KAAK,WAAW,eAAe,EAAE,UAAU,KAAK,WAAW,YAAY,IAAI,CAAC;AAAA;AAAA,IAC/G,QAAQ,OAAO,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,EAAG,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA,IAKjF,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB,GAAG;AAAA,EACL;AACF;AAKO,SAAS,mBAAmB,OAAkC;AAGnE,QAAM,UAAU;AAAA,IACd,YAAY,MAAM;AAAA,IAClB,UAAU,MAAM;AAAA,IAChB,GAAI,MAAM,aAAa,SAAY,CAAC,IAAI,EAAE,UAAU,MAAM,SAAS;AAAA,IACnE,QAAQ,MAAM;AAAA,IACd,cAAc,MAAM;AAAA,IACpB,GAAI,MAAM,cAAc,SAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,IACtE,GAAI,MAAM,eAAe,SAAY,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,IACzE,GAAI,MAAM,YAAY,SAAY,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;AAAA,IAChE,GAAI,MAAM,cAAc,SAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,EACxE;AACA,aAAO,6BAAe,iBAAiB,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AACzE;","names":[]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** The app-local half of the deixis block — supplied by the app at call time. */
|
|
2
|
+
interface AgentContextAppFields {
|
|
3
|
+
/** The entry the reader is on (app router's key/path). */
|
|
4
|
+
entryPath?: string;
|
|
5
|
+
/** Its display title. */
|
|
6
|
+
entryTitle?: string;
|
|
7
|
+
/** The `#fragment` the app resolved — "the section you're looking at". */
|
|
8
|
+
heading?: string;
|
|
9
|
+
/** Future: selected text as deixis. */
|
|
10
|
+
selection?: string;
|
|
11
|
+
}
|
|
12
|
+
/** The whole block, as it enters the loop. */
|
|
13
|
+
interface AgentContextBlock {
|
|
14
|
+
repository: string;
|
|
15
|
+
revision: string;
|
|
16
|
+
/** Omitted while auth status is `unknown` (R3-300). Status only — never identity. */
|
|
17
|
+
signedIn?: boolean;
|
|
18
|
+
mounts: Array<{
|
|
19
|
+
path: string;
|
|
20
|
+
mode?: string;
|
|
21
|
+
}>;
|
|
22
|
+
/** Whether the source is treated as "others can write here" (feeds the reach
|
|
23
|
+
* card's row and the copy under it). */
|
|
24
|
+
sourceShared: boolean;
|
|
25
|
+
/** Why `sourceShared` reads as it does — today the git classifier is fail-closed
|
|
26
|
+
* indeterminate (`PERSISTENCE §7A.6` Q11), so a git-backed corpus is treated as
|
|
27
|
+
* shared with the softer copy; a mount trust-mode API would replace this basis. */
|
|
28
|
+
sourceSharedBasis: 'git-indeterminate' | 'mount-trust-mode';
|
|
29
|
+
entryPath?: string;
|
|
30
|
+
entryTitle?: string;
|
|
31
|
+
heading?: string;
|
|
32
|
+
selection?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Assemble the deixis block: the platform fields from the SDK's own state, the app's
|
|
36
|
+
* local fields spread in. Additive-only; the app passes new local fields as they
|
|
37
|
+
* exist.
|
|
38
|
+
*/
|
|
39
|
+
declare function useAgentContext(app?: AgentContextAppFields): AgentContextBlock;
|
|
40
|
+
/** Serialize the block as the fenced data segment that enters the system prompt.
|
|
41
|
+
* Every field is attacker-influenced only through repo/mount metadata — still, the
|
|
42
|
+
* fence is unconditional (R-GA-7): the block is corpus-derived data. */
|
|
43
|
+
declare function renderAgentContext(block: AgentContextBlock): string;
|
|
44
|
+
|
|
45
|
+
export { type AgentContextAppFields, type AgentContextBlock, renderAgentContext, useAgentContext };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** The app-local half of the deixis block — supplied by the app at call time. */
|
|
2
|
+
interface AgentContextAppFields {
|
|
3
|
+
/** The entry the reader is on (app router's key/path). */
|
|
4
|
+
entryPath?: string;
|
|
5
|
+
/** Its display title. */
|
|
6
|
+
entryTitle?: string;
|
|
7
|
+
/** The `#fragment` the app resolved — "the section you're looking at". */
|
|
8
|
+
heading?: string;
|
|
9
|
+
/** Future: selected text as deixis. */
|
|
10
|
+
selection?: string;
|
|
11
|
+
}
|
|
12
|
+
/** The whole block, as it enters the loop. */
|
|
13
|
+
interface AgentContextBlock {
|
|
14
|
+
repository: string;
|
|
15
|
+
revision: string;
|
|
16
|
+
/** Omitted while auth status is `unknown` (R3-300). Status only — never identity. */
|
|
17
|
+
signedIn?: boolean;
|
|
18
|
+
mounts: Array<{
|
|
19
|
+
path: string;
|
|
20
|
+
mode?: string;
|
|
21
|
+
}>;
|
|
22
|
+
/** Whether the source is treated as "others can write here" (feeds the reach
|
|
23
|
+
* card's row and the copy under it). */
|
|
24
|
+
sourceShared: boolean;
|
|
25
|
+
/** Why `sourceShared` reads as it does — today the git classifier is fail-closed
|
|
26
|
+
* indeterminate (`PERSISTENCE §7A.6` Q11), so a git-backed corpus is treated as
|
|
27
|
+
* shared with the softer copy; a mount trust-mode API would replace this basis. */
|
|
28
|
+
sourceSharedBasis: 'git-indeterminate' | 'mount-trust-mode';
|
|
29
|
+
entryPath?: string;
|
|
30
|
+
entryTitle?: string;
|
|
31
|
+
heading?: string;
|
|
32
|
+
selection?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Assemble the deixis block: the platform fields from the SDK's own state, the app's
|
|
36
|
+
* local fields spread in. Additive-only; the app passes new local fields as they
|
|
37
|
+
* exist.
|
|
38
|
+
*/
|
|
39
|
+
declare function useAgentContext(app?: AgentContextAppFields): AgentContextBlock;
|
|
40
|
+
/** Serialize the block as the fenced data segment that enters the system prompt.
|
|
41
|
+
* Every field is attacker-influenced only through repo/mount metadata — still, the
|
|
42
|
+
* fence is unconditional (R-GA-7): the block is corpus-derived data. */
|
|
43
|
+
declare function renderAgentContext(block: AgentContextBlock): string;
|
|
44
|
+
|
|
45
|
+
export { type AgentContextAppFields, type AgentContextBlock, renderAgentContext, useAgentContext };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import "./chunk-VHAA22YE.js";
|
|
2
|
+
import { useContext } from "react";
|
|
3
|
+
import { TinkerableContext } from "./TinkerableContext";
|
|
4
|
+
import { useAuth } from "./auth";
|
|
5
|
+
import { useMounts } from "./mounts";
|
|
6
|
+
import { fenceUntrusted } from "./fence";
|
|
7
|
+
function useAgentContext(app = {}) {
|
|
8
|
+
const tinker = useContext(TinkerableContext);
|
|
9
|
+
const auth = useAuth();
|
|
10
|
+
const mounts = useMounts();
|
|
11
|
+
const nav = tinker?.navigationState;
|
|
12
|
+
return {
|
|
13
|
+
repository: nav?.repository ?? "",
|
|
14
|
+
revision: nav?.ref ?? "",
|
|
15
|
+
...auth.status === "signed-in" || auth.status === "signed-out" ? { signedIn: auth.status === "signed-in" } : {},
|
|
16
|
+
// unknown ⇒ omitted, never guessed
|
|
17
|
+
mounts: mounts.map((m) => ({ path: m.path, ...m.mode ? { mode: m.mode } : {} })),
|
|
18
|
+
// Fail-closed (PERSISTENCE §7A.6): a git-backed source classifies shared until
|
|
19
|
+
// sole authorship of the full reachable history is verifiable — which it is not
|
|
20
|
+
// today — so both packagings (dispatched repo, fork's own repo) read as
|
|
21
|
+
// "treated as if others can write".
|
|
22
|
+
sourceShared: true,
|
|
23
|
+
sourceSharedBasis: "git-indeterminate",
|
|
24
|
+
...app
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function renderAgentContext(block) {
|
|
28
|
+
const payload = {
|
|
29
|
+
repository: block.repository,
|
|
30
|
+
revision: block.revision,
|
|
31
|
+
...block.signedIn === void 0 ? {} : { signedIn: block.signedIn },
|
|
32
|
+
mounts: block.mounts,
|
|
33
|
+
sourceShared: block.sourceShared,
|
|
34
|
+
...block.entryPath !== void 0 ? { entryPath: block.entryPath } : {},
|
|
35
|
+
...block.entryTitle !== void 0 ? { entryTitle: block.entryTitle } : {},
|
|
36
|
+
...block.heading !== void 0 ? { heading: block.heading } : {},
|
|
37
|
+
...block.selection !== void 0 ? { selection: block.selection } : {}
|
|
38
|
+
};
|
|
39
|
+
return fenceUntrusted("agent-context", JSON.stringify(payload, null, 2));
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
renderAgentContext,
|
|
43
|
+
useAgentContext
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=agentContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/agentContext.tsx"],"sourcesContent":["// The deixis context block (GROVE_AGENT_SPEC §5) — platform primitive B.\n//\n// The user's first questions are indexical: *this* wiki, *this* entry, *this*\n// section. The agent should never need a tool call to know where it is. The SDK\n// assembles the PLATFORM half (repository/ref, sign-in status, mounts, source trust)\n// and the app spreads in its local fields (entry, heading, selection).\n//\n// TWO RULES (normative, G-GA-5):\n// 1. The block is DATA IN A FENCE — never instructions (threat_model P8) — and it\n// EGRESSES to the provider like everything else in the prompt (R-GA-6), which\n// is exactly why identity stays out: `signedIn` is a boolean from the baseline\n// `auth:status` projection; the login/user belongs to `auth:identity`, and\n// collapsing that split (threat_model T6) widens the egress for convenience.\n// 2. `signedIn` is OMITTED while auth status is `unknown` — three states, because\n// collapsing `unknown` to `false` is the R3-300 false-banner bug class.\nimport { useContext } from 'react';\nimport { TinkerableContext } from './TinkerableContext';\nimport { useAuth } from './auth';\nimport { useMounts } from './mounts';\nimport { fenceUntrusted } from './fence';\n\n/** The app-local half of the deixis block — supplied by the app at call time. */\nexport interface AgentContextAppFields {\n /** The entry the reader is on (app router's key/path). */\n entryPath?: string;\n /** Its display title. */\n entryTitle?: string;\n /** The `#fragment` the app resolved — \"the section you're looking at\". */\n heading?: string;\n /** Future: selected text as deixis. */\n selection?: string;\n}\n\n/** The whole block, as it enters the loop. */\nexport interface AgentContextBlock {\n repository: string;\n revision: string;\n /** Omitted while auth status is `unknown` (R3-300). Status only — never identity. */\n signedIn?: boolean;\n mounts: Array<{ path: string; mode?: string }>;\n /** Whether the source is treated as \"others can write here\" (feeds the reach\n * card's row and the copy under it). */\n sourceShared: boolean;\n /** Why `sourceShared` reads as it does — today the git classifier is fail-closed\n * indeterminate (`PERSISTENCE §7A.6` Q11), so a git-backed corpus is treated as\n * shared with the softer copy; a mount trust-mode API would replace this basis. */\n sourceSharedBasis: 'git-indeterminate' | 'mount-trust-mode';\n entryPath?: string;\n entryTitle?: string;\n heading?: string;\n selection?: string;\n}\n\n/**\n * Assemble the deixis block: the platform fields from the SDK's own state, the app's\n * local fields spread in. Additive-only; the app passes new local fields as they\n * exist.\n */\nexport function useAgentContext(app: AgentContextAppFields = {}): AgentContextBlock {\n const tinker = useContext(TinkerableContext);\n const auth = useAuth();\n const mounts = useMounts();\n const nav = tinker?.navigationState;\n return {\n repository: nav?.repository ?? '',\n revision: nav?.ref ?? '',\n ...(auth.status === 'signed-in' || auth.status === 'signed-out' ? { signedIn: auth.status === 'signed-in' } : {}), // unknown ⇒ omitted, never guessed\n mounts: mounts.map((m) => ({ path: m.path, ...(m.mode ? { mode: m.mode } : {}) })),\n // Fail-closed (PERSISTENCE §7A.6): a git-backed source classifies shared until\n // sole authorship of the full reachable history is verifiable — which it is not\n // today — so both packagings (dispatched repo, fork's own repo) read as\n // \"treated as if others can write\".\n sourceShared: true,\n sourceSharedBasis: 'git-indeterminate',\n ...app,\n };\n}\n\n/** Serialize the block as the fenced data segment that enters the system prompt.\n * Every field is attacker-influenced only through repo/mount metadata — still, the\n * fence is unconditional (R-GA-7): the block is corpus-derived data. */\nexport function renderAgentContext(block: AgentContextBlock): string {\n // Field allowlist, deliberately: nothing joins the prompt except the fields named\n // here (G-GA-5's allowlist assertion reads this shape).\n const payload = {\n repository: block.repository,\n revision: block.revision,\n ...(block.signedIn === undefined ? {} : { signedIn: block.signedIn }),\n mounts: block.mounts,\n sourceShared: block.sourceShared,\n ...(block.entryPath !== undefined ? { entryPath: block.entryPath } : {}),\n ...(block.entryTitle !== undefined ? { entryTitle: block.entryTitle } : {}),\n ...(block.heading !== undefined ? { heading: block.heading } : {}),\n ...(block.selection !== undefined ? { selection: block.selection } : {}),\n };\n return fenceUntrusted('agent-context', JSON.stringify(payload, null, 2));\n}\n"],"mappings":";AAeA,SAAS,kBAAkB;AAC3B,SAAS,yBAAyB;AAClC,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAuCxB,SAAS,gBAAgB,MAA6B,CAAC,GAAsB;AAClF,QAAM,SAAS,WAAW,iBAAiB;AAC3C,QAAM,OAAO,QAAQ;AACrB,QAAM,SAAS,UAAU;AACzB,QAAM,MAAM,QAAQ;AACpB,SAAO;AAAA,IACL,YAAY,KAAK,cAAc;AAAA,IAC/B,UAAU,KAAK,OAAO;AAAA,IACtB,GAAI,KAAK,WAAW,eAAe,KAAK,WAAW,eAAe,EAAE,UAAU,KAAK,WAAW,YAAY,IAAI,CAAC;AAAA;AAAA,IAC/G,QAAQ,OAAO,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,EAAG,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA,IAKjF,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB,GAAG;AAAA,EACL;AACF;AAKO,SAAS,mBAAmB,OAAkC;AAGnE,QAAM,UAAU;AAAA,IACd,YAAY,MAAM;AAAA,IAClB,UAAU,MAAM;AAAA,IAChB,GAAI,MAAM,aAAa,SAAY,CAAC,IAAI,EAAE,UAAU,MAAM,SAAS;AAAA,IACnE,QAAQ,MAAM;AAAA,IACd,cAAc,MAAM;AAAA,IACpB,GAAI,MAAM,cAAc,SAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,IACtE,GAAI,MAAM,eAAe,SAAY,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,IACzE,GAAI,MAAM,YAAY,SAAY,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;AAAA,IAChE,GAAI,MAAM,cAAc,SAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,EACxE;AACA,SAAO,eAAe,iBAAiB,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AACzE;","names":[]}
|