@tangle-network/agent-app 0.6.0 → 0.7.1
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/{chunk-EO4IGDQD.js → chunk-4YTWB5MG.js} +70 -10
- package/dist/chunk-4YTWB5MG.js.map +1 -0
- package/dist/{chunk-HZZD3ZYD.js → chunk-OLCVUGGI.js} +2 -2
- package/dist/{chunk-JANT2G2E.js → chunk-QAQBR6KQ.js} +10 -3
- package/dist/chunk-QAQBR6KQ.js.map +1 -0
- package/dist/{chunk-GMFPCCQZ.js → chunk-SDOT7RNB.js} +152 -2
- package/dist/chunk-SDOT7RNB.js.map +1 -0
- package/dist/chunk-UIWB2F6N.js +1074 -0
- package/dist/chunk-UIWB2F6N.js.map +1 -0
- package/dist/eval/index.d.ts +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +58 -4
- package/dist/missions/index.d.ts +698 -0
- package/dist/missions/index.js +45 -0
- package/dist/missions/index.js.map +1 -0
- package/dist/preset-cloudflare/index.d.ts +1 -1
- package/dist/runtime/index.d.ts +32 -7
- package/dist/runtime/index.js +2 -2
- package/dist/stream/index.d.ts +88 -1
- package/dist/stream/index.js +13 -1
- package/dist/tools/index.d.ts +10 -2
- package/dist/tools/index.js +2 -2
- package/dist/{types-CTOaTNtU.d.ts → types-By4B3K37.d.ts} +4 -0
- package/dist/web-react/index.d.ts +119 -2
- package/dist/web-react/index.js +257 -20
- package/dist/web-react/index.js.map +1 -1
- package/package.json +6 -1
- package/dist/chunk-EO4IGDQD.js.map +0 -1
- package/dist/chunk-GMFPCCQZ.js.map +0 -1
- package/dist/chunk-JANT2G2E.js.map +0 -1
- /package/dist/{chunk-HZZD3ZYD.js.map → chunk-OLCVUGGI.js.map} +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_MISSION_STEP_KINDS,
|
|
3
|
+
MISSION_CONTROL_CHANNEL_ID,
|
|
4
|
+
MissionConcurrencyError,
|
|
5
|
+
RetryableStepError,
|
|
6
|
+
applyMissionEvent,
|
|
7
|
+
asMissionStreamEvent,
|
|
8
|
+
budgetGateProposalId,
|
|
9
|
+
buildAgentMissionPlan,
|
|
10
|
+
createInMemoryMissionStore,
|
|
11
|
+
createMissionEngine,
|
|
12
|
+
createMissionService,
|
|
13
|
+
isMissionStopRequested,
|
|
14
|
+
isMissionTerminal,
|
|
15
|
+
mergeMissionState,
|
|
16
|
+
noopEventSink,
|
|
17
|
+
parseMissionBlocks,
|
|
18
|
+
parseSessionStreamEnvelope,
|
|
19
|
+
reduceMissionEvents,
|
|
20
|
+
stepGateProposalId,
|
|
21
|
+
volumeGateProposalId
|
|
22
|
+
} from "../chunk-UIWB2F6N.js";
|
|
23
|
+
export {
|
|
24
|
+
DEFAULT_MISSION_STEP_KINDS,
|
|
25
|
+
MISSION_CONTROL_CHANNEL_ID,
|
|
26
|
+
MissionConcurrencyError,
|
|
27
|
+
RetryableStepError,
|
|
28
|
+
applyMissionEvent,
|
|
29
|
+
asMissionStreamEvent,
|
|
30
|
+
budgetGateProposalId,
|
|
31
|
+
buildAgentMissionPlan,
|
|
32
|
+
createInMemoryMissionStore,
|
|
33
|
+
createMissionEngine,
|
|
34
|
+
createMissionService,
|
|
35
|
+
isMissionStopRequested,
|
|
36
|
+
isMissionTerminal,
|
|
37
|
+
mergeMissionState,
|
|
38
|
+
noopEventSink,
|
|
39
|
+
parseMissionBlocks,
|
|
40
|
+
parseSessionStreamEnvelope,
|
|
41
|
+
reduceMissionEvents,
|
|
42
|
+
stepGateProposalId,
|
|
43
|
+
volumeGateProposalId
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { KeyProvisioner, KeyCrypto, WorkspaceKeyManager, WorkspaceKeyStore } from '../billing/index.js';
|
|
2
2
|
import { KnowledgeStateAccessor } from '../knowledge/index.js';
|
|
3
|
-
import { c as AppToolHandlers } from '../types-
|
|
3
|
+
import { c as AppToolHandlers } from '../types-By4B3K37.js';
|
|
4
4
|
import { KvLike } from '../web/index.js';
|
|
5
5
|
import '@tangle-network/agent-eval';
|
|
6
6
|
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { C as CatalogModel, M as ModelCatalog, R as RouterModel, _ as __resetCatalogCache, b as buildCatalog, f as fetchModelCatalog, n as normalizeModelId } from '../model-catalog-BEAEVDaa.js';
|
|
2
2
|
export { C as CreateTangleRouterModelConfigOptions, D as DEFAULT_TANGLE_BILLING_ENFORCEMENT_ENV_VAR, a as DEFAULT_TANGLE_ROUTER_BASE_URL, R as ResolveModelOptions, b as ResolveUserTangleExecutionKeyForUserOptions, c as ResolveUserTangleExecutionKeyOptions, d as ResolvedTangleExecutionKey, T as TangleBillingEnforcementOptions, e as TangleExecutionEnvironment, f as TangleExecutionKeyError, g as TangleExecutionKeyErrorCode, h as TangleExecutionKeyHttpError, i as TangleExecutionKeySource, j as TangleModelConfig, k as createTangleRouterModelConfig, l as isTangleBillingEnforcementDisabled, m as isTangleExecutionKeyError, r as resolveTangleExecutionEnvironment, n as resolveTangleModelConfig, o as resolveUserTangleExecutionKey, p as resolveUserTangleExecutionKeyForUser, t as tangleExecutionKeyHttpError } from '../model-CKzniMMr.js';
|
|
3
|
-
import { b as AppToolContext, e as AppToolProducedEvent, f as AppToolTaxonomy, c as AppToolHandlers, d as AppToolOutcome } from '../types-
|
|
3
|
+
import { b as AppToolContext, e as AppToolProducedEvent, f as AppToolTaxonomy, c as AppToolHandlers, d as AppToolOutcome } from '../types-By4B3K37.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* OpenAI-compatible stream → `LoopEvent` adapter, for NON-sandbox copilots.
|
|
@@ -129,7 +129,8 @@ interface CreateAgentRuntimeOptions {
|
|
|
129
129
|
handlers: AppToolHandlers;
|
|
130
130
|
/** Default agent identity / system prompt. A turn may override it. */
|
|
131
131
|
systemPrompt: string;
|
|
132
|
-
/**
|
|
132
|
+
/** Runaway-backstop cap. Default 200 — set far above any legitimate workflow.
|
|
133
|
+
* For per-workflow limits use `deadlineMs` or `maxCostUsd` on the loop options. */
|
|
133
134
|
maxToolTurns?: number;
|
|
134
135
|
/** Extra OpenAI tool definitions advertised ALONGSIDE the four app tools
|
|
135
136
|
* (e.g. `integration_invoke`). Pair with {@link executeOtherTool}. */
|
|
@@ -228,6 +229,12 @@ type LoopEvent = {
|
|
|
228
229
|
type: 'other';
|
|
229
230
|
event: unknown;
|
|
230
231
|
};
|
|
232
|
+
/** Why the loop stopped. `completed` = model finished naturally; `stuck-loop` =
|
|
233
|
+
* ≥3 consecutive identical tool calls (same tool + args); `backstop` = hit the
|
|
234
|
+
* runaway-backstop cap (200 by default); `deadline` = wall-clock deadlineMs
|
|
235
|
+
* exceeded; `budget` = maxCostUsd exhausted. Non-`completed` stops are infra /
|
|
236
|
+
* resource outcomes — eval scoring must distinguish them from capability failure. */
|
|
237
|
+
type ToolLoopStopReason = 'completed' | 'stuck-loop' | 'backstop' | 'deadline' | 'budget';
|
|
231
238
|
interface ToolLoopResult {
|
|
232
239
|
/** The model's final text across the loop. */
|
|
233
240
|
finalText: string;
|
|
@@ -239,7 +246,9 @@ interface ToolLoopResult {
|
|
|
239
246
|
}>;
|
|
240
247
|
/** Number of model turns run (1 + tool-driven re-runs). */
|
|
241
248
|
turns: number;
|
|
242
|
-
/**
|
|
249
|
+
/** Why the loop stopped. */
|
|
250
|
+
stopReason: ToolLoopStopReason;
|
|
251
|
+
/** @deprecated Use `stopReason !== 'completed'` instead. */
|
|
243
252
|
cappedOut: boolean;
|
|
244
253
|
}
|
|
245
254
|
interface AppToolLoopOptions {
|
|
@@ -260,8 +269,16 @@ interface AppToolLoopOptions {
|
|
|
260
269
|
/** Which emitted tool names are executable (others are ignored — e.g. a UI-only
|
|
261
270
|
* tool the app renders but doesn't run here). */
|
|
262
271
|
isExecutableTool: (toolName: string) => boolean;
|
|
263
|
-
/**
|
|
272
|
+
/** Runaway-backstop cap. Default 200 — set far above any legitimate workflow.
|
|
273
|
+
* For per-workflow limits use `maxCostUsd` or `deadlineMs` instead. */
|
|
264
274
|
maxToolTurns?: number;
|
|
275
|
+
/** Wall-clock deadline in ms since epoch (Date.now()-based). When exceeded the
|
|
276
|
+
* loop stops with stopReason `deadline`. */
|
|
277
|
+
deadlineMs?: number;
|
|
278
|
+
/** Maximum total cost in USD. Requires `costOf` to meter each tool call. */
|
|
279
|
+
maxCostUsd?: number;
|
|
280
|
+
/** Return the USD cost of one outcome. Required for `maxCostUsd` to work. */
|
|
281
|
+
costOf?: (call: LoopToolCall, outcome: AppToolOutcome) => number;
|
|
265
282
|
/** Render one tool outcome as the `content` of its `role: 'tool'` message.
|
|
266
283
|
* Default is a compact `<label> → ok/failed: …`. */
|
|
267
284
|
renderResult?: (label: string, outcome: AppToolOutcome) => string;
|
|
@@ -288,6 +305,7 @@ type StreamLoopYield<Raw> = {
|
|
|
288
305
|
} | {
|
|
289
306
|
kind: 'capped';
|
|
290
307
|
pending: number;
|
|
308
|
+
stopReason: Exclude<ToolLoopStopReason, 'completed'>;
|
|
291
309
|
};
|
|
292
310
|
interface StreamAppToolLoopOptions<Raw> {
|
|
293
311
|
systemPrompt: string;
|
|
@@ -309,16 +327,23 @@ interface StreamAppToolLoopOptions<Raw> {
|
|
|
309
327
|
isExecutableTool: (toolName: string) => boolean;
|
|
310
328
|
/** Execute one call — the app routes to its integration / app-tool executor. */
|
|
311
329
|
executeToolCall: (call: LoopToolCall) => Promise<AppToolOutcome>;
|
|
330
|
+
/** Runaway-backstop cap. Default 200 — set far above any legitimate workflow. */
|
|
312
331
|
maxToolTurns?: number;
|
|
332
|
+
/** Wall-clock deadline in ms since epoch (Date.now()-based). */
|
|
333
|
+
deadlineMs?: number;
|
|
334
|
+
/** Maximum total cost in USD. Requires `costOf` to meter each tool call. */
|
|
335
|
+
maxCostUsd?: number;
|
|
336
|
+
/** Return the USD cost of one outcome. Required for `maxCostUsd` to work. */
|
|
337
|
+
costOf?: (call: LoopToolCall, outcome: AppToolOutcome) => number;
|
|
313
338
|
renderResult?: (label: string, outcome: AppToolOutcome) => string;
|
|
314
339
|
labelFor?: (call: LoopToolCall) => string;
|
|
315
340
|
}
|
|
316
341
|
/**
|
|
317
342
|
* The streaming bounded tool loop. Yields `event` for each raw turn event and
|
|
318
|
-
* `tool_result` for each executed tool; emits a single `capped`
|
|
319
|
-
*
|
|
343
|
+
* `tool_result` for each executed tool; emits a single `capped` (with stopReason)
|
|
344
|
+
* when it stops for any non-completed reason. The app drives telemetry + UI
|
|
320
345
|
* emission off the yielded items.
|
|
321
346
|
*/
|
|
322
347
|
declare function streamAppToolLoop<Raw>(opts: StreamAppToolLoopOptions<Raw>): AsyncGenerator<StreamLoopYield<Raw>, void, unknown>;
|
|
323
348
|
|
|
324
|
-
export { type AgentRuntime, type AgentRuntimeModelConfig, type AgentTurnOptions, type AppToolLoopOptions, type CreateAgentRuntimeOptions, type LoopAssistantToolCall, type LoopEvent, type LoopMessage, type LoopToolCall, type OpenAICompatStreamTurnOptions, type OpenAIStreamChunk, type StreamAppToolLoopOptions, type StreamLoopYield, type ToolLoopResult, createAgentRuntime, createOpenAICompatStreamTurn, runAppToolLoop, streamAppToolLoop, toLoopEvents };
|
|
349
|
+
export { type AgentRuntime, type AgentRuntimeModelConfig, type AgentTurnOptions, type AppToolLoopOptions, type CreateAgentRuntimeOptions, type LoopAssistantToolCall, type LoopEvent, type LoopMessage, type LoopToolCall, type OpenAICompatStreamTurnOptions, type OpenAIStreamChunk, type StreamAppToolLoopOptions, type StreamLoopYield, type ToolLoopResult, type ToolLoopStopReason, createAgentRuntime, createOpenAICompatStreamTurn, runAppToolLoop, streamAppToolLoop, toLoopEvents };
|
package/dist/runtime/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
runAppToolLoop,
|
|
9
9
|
streamAppToolLoop,
|
|
10
10
|
toLoopEvents
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-4YTWB5MG.js";
|
|
12
12
|
import {
|
|
13
13
|
DEFAULT_TANGLE_BILLING_ENFORCEMENT_ENV_VAR,
|
|
14
14
|
DEFAULT_TANGLE_ROUTER_BASE_URL,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
resolveUserTangleExecutionKeyForUser,
|
|
23
23
|
tangleExecutionKeyHttpError
|
|
24
24
|
} from "../chunk-EHPK7GKR.js";
|
|
25
|
-
import "../chunk-
|
|
25
|
+
import "../chunk-QAQBR6KQ.js";
|
|
26
26
|
export {
|
|
27
27
|
DEFAULT_TANGLE_BILLING_ENFORCEMENT_ENV_VAR,
|
|
28
28
|
DEFAULT_TANGLE_ROUTER_BASE_URL,
|
package/dist/stream/index.d.ts
CHANGED
|
@@ -36,4 +36,91 @@ declare function resolveChatTurn(input: {
|
|
|
36
36
|
turnId?: string;
|
|
37
37
|
}): ResolvedChatTurn;
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Resumable chat turns — the router-path answer to "streams resume on
|
|
41
|
+
* disconnect" (issue #27). A turn's loop events are teed into a store as they
|
|
42
|
+
* stream; the turn keeps running under `ctx.waitUntil` when the client drops;
|
|
43
|
+
* a reconnecting client replays the buffered tail by sequence number and
|
|
44
|
+
* keeps following until the turn completes.
|
|
45
|
+
*
|
|
46
|
+
* POST /chat/stream → pumpBufferedTurn(...) + live NDJSON
|
|
47
|
+
* GET /chat/stream/:turnId → replayTurnEvents({ fromSeq }) → NDJSON
|
|
48
|
+
*
|
|
49
|
+
* Storage is a structural seam ({@link TurnEventStore}); a D1 implementation
|
|
50
|
+
* ships here because that's what Cloudflare products have (KV is unsuitable:
|
|
51
|
+
* eventually consistent cross-isolate). Per-token deltas would mean hundreds
|
|
52
|
+
* of rows per turn, so consecutive text/reasoning deltas are coalesced within
|
|
53
|
+
* a flush window before they are persisted — replay yields slightly chunkier
|
|
54
|
+
* deltas with identical concatenation.
|
|
55
|
+
*/
|
|
56
|
+
type TurnStatus = 'running' | 'complete' | 'error';
|
|
57
|
+
interface BufferedTurnEvent {
|
|
58
|
+
seq: number;
|
|
59
|
+
/** The serialized event line (JSON string, no trailing newline). */
|
|
60
|
+
event: string;
|
|
61
|
+
}
|
|
62
|
+
interface TurnEventStore {
|
|
63
|
+
append(turnId: string, events: BufferedTurnEvent[]): Promise<void>;
|
|
64
|
+
read(turnId: string, fromSeq: number): Promise<BufferedTurnEvent[]>;
|
|
65
|
+
setStatus(turnId: string, status: TurnStatus): Promise<void>;
|
|
66
|
+
getStatus(turnId: string): Promise<TurnStatus | null>;
|
|
67
|
+
}
|
|
68
|
+
/** Merge consecutive text/reasoning deltas of the same type into one event.
|
|
69
|
+
* Concatenation-preserving: replaying the coalesced stream produces the same
|
|
70
|
+
* accumulated text as the original. */
|
|
71
|
+
declare function coalesceDeltas(events: unknown[]): unknown[];
|
|
72
|
+
interface PumpBufferedTurnOptions {
|
|
73
|
+
source: AsyncIterable<unknown>;
|
|
74
|
+
store: TurnEventStore;
|
|
75
|
+
turnId: string;
|
|
76
|
+
/** Deliver one serialized line (with seq) to the live client. Throwing here
|
|
77
|
+
* (client disconnected) does NOT stop the turn — events keep buffering. */
|
|
78
|
+
write?: (line: string) => Promise<void> | void;
|
|
79
|
+
/** Flush buffered events to the store at most this often. Default 400ms. */
|
|
80
|
+
flushIntervalMs?: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Drive a turn to completion regardless of the live client: every source
|
|
84
|
+
* event is sequence-numbered, delivered to `write` (best-effort), and flushed
|
|
85
|
+
* to the store in coalesced batches. Returns a promise that resolves when the
|
|
86
|
+
* turn finishes — hand it to `ctx.waitUntil` so a disconnect can't kill the
|
|
87
|
+
* turn. Never rejects on client-write failure; a source error marks the turn
|
|
88
|
+
* status 'error' (after flushing what was produced) and rethrows.
|
|
89
|
+
*/
|
|
90
|
+
declare function pumpBufferedTurn(opts: PumpBufferedTurnOptions): Promise<void>;
|
|
91
|
+
interface ReplayTurnEventsOptions {
|
|
92
|
+
store: TurnEventStore;
|
|
93
|
+
turnId: string;
|
|
94
|
+
/** Replay strictly after this sequence number (0 = from the beginning). */
|
|
95
|
+
fromSeq?: number;
|
|
96
|
+
/** Poll cadence while the turn is still running. Default 500ms. */
|
|
97
|
+
pollMs?: number;
|
|
98
|
+
/** Give up following a 'running' turn after this long. Default 120s. */
|
|
99
|
+
timeoutMs?: number;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Yield buffered events after `fromSeq`, then keep polling while the turn is
|
|
103
|
+
* still 'running' until it completes, errors, or times out. Terminates with a
|
|
104
|
+
* final `{seq: -1, event: '{"type":"turn_status",...}'}` marker so clients
|
|
105
|
+
* know why the replay ended.
|
|
106
|
+
*/
|
|
107
|
+
declare function replayTurnEvents(opts: ReplayTurnEventsOptions): AsyncGenerator<BufferedTurnEvent>;
|
|
108
|
+
/** Minimal structural D1 contract (Cloudflare `D1Database` satisfies it). */
|
|
109
|
+
interface D1LikeForTurns {
|
|
110
|
+
prepare(sql: string): {
|
|
111
|
+
bind(...values: unknown[]): {
|
|
112
|
+
run(): Promise<unknown>;
|
|
113
|
+
all<T = Record<string, unknown>>(): Promise<{
|
|
114
|
+
results: T[];
|
|
115
|
+
}>;
|
|
116
|
+
first<T = Record<string, unknown>>(): Promise<T | null>;
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/** Schema for the D1 store — append to the product's migrations. */
|
|
121
|
+
declare const TURN_EVENTS_MIGRATION_SQL = "\nCREATE TABLE IF NOT EXISTS turn_events (\n turnId TEXT NOT NULL,\n seq INTEGER NOT NULL,\n event TEXT NOT NULL,\n PRIMARY KEY (turnId, seq)\n);\nCREATE TABLE IF NOT EXISTS turn_status (\n turnId TEXT PRIMARY KEY,\n status TEXT NOT NULL,\n updatedAt TEXT NOT NULL\n);\n";
|
|
122
|
+
declare function createD1TurnEventStore(db: D1LikeForTurns): TurnEventStore;
|
|
123
|
+
/** In-memory store for tests and keyless local dev. */
|
|
124
|
+
declare function createMemoryTurnEventStore(): TurnEventStore;
|
|
125
|
+
|
|
126
|
+
export { type BufferedTurnEvent, type D1LikeForTurns, type JsonRecord, type PersistedChatMessageForTurn, type PumpBufferedTurnOptions, type ReplayTurnEventsOptions, type ResolvedChatTurn, type StreamEvent, TURN_EVENTS_MIGRATION_SQL, type TurnEventStore, type TurnStatus, asRecord, asString, buildUserTextParts, coalesceDeltas, createD1TurnEventStore, createMemoryTurnEventStore, encodeEvent, finalizeAssistantParts, getPartKey, mergePersistedPart, messageHasTurnId, normalizeClientTurnId, normalizePersistedPart, normalizeTime, normalizeToolEvent, pumpBufferedTurn, replayTurnEvents, resolveChatTurn, resolveToolId, resolveToolName };
|
package/dist/stream/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
+
TURN_EVENTS_MIGRATION_SQL,
|
|
2
3
|
asRecord,
|
|
3
4
|
asString,
|
|
4
5
|
buildUserTextParts,
|
|
6
|
+
coalesceDeltas,
|
|
7
|
+
createD1TurnEventStore,
|
|
8
|
+
createMemoryTurnEventStore,
|
|
5
9
|
encodeEvent,
|
|
6
10
|
finalizeAssistantParts,
|
|
7
11
|
getPartKey,
|
|
@@ -11,14 +15,20 @@ import {
|
|
|
11
15
|
normalizePersistedPart,
|
|
12
16
|
normalizeTime,
|
|
13
17
|
normalizeToolEvent,
|
|
18
|
+
pumpBufferedTurn,
|
|
19
|
+
replayTurnEvents,
|
|
14
20
|
resolveChatTurn,
|
|
15
21
|
resolveToolId,
|
|
16
22
|
resolveToolName
|
|
17
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-SDOT7RNB.js";
|
|
18
24
|
export {
|
|
25
|
+
TURN_EVENTS_MIGRATION_SQL,
|
|
19
26
|
asRecord,
|
|
20
27
|
asString,
|
|
21
28
|
buildUserTextParts,
|
|
29
|
+
coalesceDeltas,
|
|
30
|
+
createD1TurnEventStore,
|
|
31
|
+
createMemoryTurnEventStore,
|
|
22
32
|
encodeEvent,
|
|
23
33
|
finalizeAssistantParts,
|
|
24
34
|
getPartKey,
|
|
@@ -28,6 +38,8 @@ export {
|
|
|
28
38
|
normalizePersistedPart,
|
|
29
39
|
normalizeTime,
|
|
30
40
|
normalizeToolEvent,
|
|
41
|
+
pumpBufferedTurn,
|
|
42
|
+
replayTurnEvents,
|
|
31
43
|
resolveChatTurn,
|
|
32
44
|
resolveToolId,
|
|
33
45
|
resolveToolName
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { b as AppToolContext, f as AppToolTaxonomy, c as AppToolHandlers, e as AppToolProducedEvent, d as AppToolOutcome } from '../types-
|
|
2
|
-
export { A as AddCitationArgs, a as AddCitationResult, R as RenderUiArgs, g as RenderUiResult, S as ScheduleFollowupArgs, h as ScheduleFollowupResult, i as SubmitProposalArgs, j as SubmitProposalResult } from '../types-
|
|
1
|
+
import { b as AppToolContext, f as AppToolTaxonomy, c as AppToolHandlers, e as AppToolProducedEvent, d as AppToolOutcome } from '../types-By4B3K37.js';
|
|
2
|
+
export { A as AddCitationArgs, a as AddCitationResult, R as RenderUiArgs, g as RenderUiResult, S as ScheduleFollowupArgs, h as ScheduleFollowupResult, i as SubmitProposalArgs, j as SubmitProposalResult } from '../types-By4B3K37.js';
|
|
3
3
|
|
|
4
4
|
/** A correctable bad-input error a tool handler throws; the HTTP layer maps it
|
|
5
5
|
* to a 4xx with the code, the runtime layer to a failed tool_result. So the
|
|
@@ -102,6 +102,14 @@ declare function buildAppToolOpenAITools(taxonomy: AppToolTaxonomy): OpenAIFunct
|
|
|
102
102
|
interface DispatchOptions {
|
|
103
103
|
handlers: AppToolHandlers;
|
|
104
104
|
taxonomy: AppToolTaxonomy;
|
|
105
|
+
/** Per-call approval policy. When provided it OVERRIDES the static
|
|
106
|
+
* `taxonomy.regulatedTypes` membership check, so products can gate by
|
|
107
|
+
* cost threshold, environment, or first-use instead of always/never.
|
|
108
|
+
* Fail-closed: a predicate that throws counts as "approval required". */
|
|
109
|
+
needsApproval?: (type: string, args: {
|
|
110
|
+
title: string;
|
|
111
|
+
description: string | null;
|
|
112
|
+
}, ctx: AppToolContext) => boolean | Promise<boolean>;
|
|
105
113
|
/** Called at the real side-effect site for proposals (proposal_created) and
|
|
106
114
|
* generated views (artifact) so a consumer's completion oracle credits
|
|
107
115
|
* persisted state. Omit when produced state isn't tracked. */
|
package/dist/tools/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
handleAppToolRequest,
|
|
9
9
|
readToolArgs,
|
|
10
10
|
verifyCapabilityToken
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-OLCVUGGI.js";
|
|
12
12
|
import {
|
|
13
13
|
APP_TOOL_NAMES,
|
|
14
14
|
ToolInputError,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
dispatchAppTool,
|
|
18
18
|
isAppToolName,
|
|
19
19
|
outcomeStatus
|
|
20
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-QAQBR6KQ.js";
|
|
21
21
|
export {
|
|
22
22
|
APP_TOOL_NAMES,
|
|
23
23
|
DEFAULT_APP_TOOL_PATHS,
|
|
@@ -41,6 +41,10 @@ interface SubmitProposalArgs {
|
|
|
41
41
|
type: string;
|
|
42
42
|
title: string;
|
|
43
43
|
description?: string | null;
|
|
44
|
+
/** Stamped by dispatch from the approval policy (needsApproval predicate or
|
|
45
|
+
* taxonomy.regulatedTypes). Handlers MUST queue (never auto-execute) when
|
|
46
|
+
* true. Products don't set this; dispatch owns it — fail-closed. */
|
|
47
|
+
regulated?: boolean;
|
|
44
48
|
}
|
|
45
49
|
interface SubmitProposalResult {
|
|
46
50
|
proposalId: string;
|
|
@@ -2,6 +2,79 @@ import * as react from 'react';
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { C as CatalogModel } from '../model-catalog-BEAEVDaa.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Client-side chat-stream consumption — the NDJSON parse loop every agent
|
|
7
|
+
* app's chat UI hand-rolls (and breaks). Normalizes the three line shapes the
|
|
8
|
+
* agent-app chat routes emit:
|
|
9
|
+
*
|
|
10
|
+
* {kind:'event', event:{type:'text'|'reasoning'|'tool_call'|'usage', ...}}
|
|
11
|
+
* {kind:'tool_result', toolCallId, toolName, label, outcome}
|
|
12
|
+
* {type:'turn'|'metadata'|'error'|'turn_status', ...} (route-level)
|
|
13
|
+
*
|
|
14
|
+
* Replayed lines carry an extra `seq` — transparently ignored. Works for
|
|
15
|
+
* router-backed and sandbox-backed chats alike: anything producing these
|
|
16
|
+
* lines (live pump, queued follow, resume replay) feeds the same callbacks.
|
|
17
|
+
*/
|
|
18
|
+
interface ChatStreamToolCall {
|
|
19
|
+
toolCallId?: string;
|
|
20
|
+
toolName: string;
|
|
21
|
+
args: Record<string, unknown>;
|
|
22
|
+
}
|
|
23
|
+
interface ChatStreamToolResult {
|
|
24
|
+
toolCallId?: string;
|
|
25
|
+
toolName?: string;
|
|
26
|
+
label?: string;
|
|
27
|
+
outcome: {
|
|
28
|
+
ok: boolean;
|
|
29
|
+
result?: unknown;
|
|
30
|
+
code?: string;
|
|
31
|
+
message?: string;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
interface ChatStreamCallbacks {
|
|
35
|
+
onTurnId?: (turnId: string) => void;
|
|
36
|
+
onText?: (delta: string) => void;
|
|
37
|
+
onReasoning?: (delta: string) => void;
|
|
38
|
+
onToolCall?: (call: ChatStreamToolCall) => void;
|
|
39
|
+
onToolResult?: (result: ChatStreamToolResult) => void;
|
|
40
|
+
onUsage?: (usage: {
|
|
41
|
+
promptTokens: number;
|
|
42
|
+
completionTokens: number;
|
|
43
|
+
}) => void;
|
|
44
|
+
onMetadata?: (data: Record<string, unknown>) => void;
|
|
45
|
+
/** A loop-level error event (the turn failed server-side). */
|
|
46
|
+
onErrorEvent?: (message: string) => void;
|
|
47
|
+
}
|
|
48
|
+
interface ConsumeChatStreamResult {
|
|
49
|
+
turnId: string | null;
|
|
50
|
+
/** True when any text/reasoning/tool activity was received. */
|
|
51
|
+
receivedContent: boolean;
|
|
52
|
+
}
|
|
53
|
+
/** Parse one NDJSON line into the callbacks. Exposed for tests. */
|
|
54
|
+
declare function dispatchChatStreamLine(line: string, cb: ChatStreamCallbacks): {
|
|
55
|
+
turnId?: string;
|
|
56
|
+
receivedContent: boolean;
|
|
57
|
+
};
|
|
58
|
+
/** Drain one NDJSON body into the callbacks. Throws on transport failure
|
|
59
|
+
* (caller decides whether to resume). */
|
|
60
|
+
declare function consumeChatStream(body: ReadableStream<Uint8Array>, cb: ChatStreamCallbacks): Promise<ConsumeChatStreamResult>;
|
|
61
|
+
interface StreamChatOptions {
|
|
62
|
+
/** Start the turn (POST the chat request); must return a streaming Response. */
|
|
63
|
+
start: () => Promise<Response>;
|
|
64
|
+
/** Re-attach to a turn after a transport drop (GET the resume route). */
|
|
65
|
+
resume?: (turnId: string, fromSeq: number) => Promise<Response>;
|
|
66
|
+
callbacks: ChatStreamCallbacks;
|
|
67
|
+
/** Called before a resume replays from 0 so the UI can reset accumulated
|
|
68
|
+
* turn state (text, reasoning, tool chips). */
|
|
69
|
+
onResetForResume?: () => void;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Run one chat turn with automatic single-shot resume: if the transport drops
|
|
73
|
+
* mid-turn and the server announced a turnId, reset and replay the buffered
|
|
74
|
+
* turn. Server-side the turn keeps running either way (queued runner).
|
|
75
|
+
*/
|
|
76
|
+
declare function streamChatTurn(opts: StreamChatOptions): Promise<ConsumeChatStreamResult>;
|
|
77
|
+
|
|
5
78
|
interface ChatMessageMetrics {
|
|
6
79
|
modelUsed?: string;
|
|
7
80
|
promptTokens?: number;
|
|
@@ -37,11 +110,46 @@ interface EffortPickerProps {
|
|
|
37
110
|
/** Reasoning-effort selector pill, styled to match {@link ModelPicker}. Show
|
|
38
111
|
* it only when the selected model `supportsReasoning`. */
|
|
39
112
|
declare function EffortPicker({ value, onChange }: EffortPickerProps): react.JSX.Element;
|
|
113
|
+
/** One step of a retained tool run (e.g. a sandbox command + its output). */
|
|
114
|
+
interface ToolRunStep {
|
|
115
|
+
at: string;
|
|
116
|
+
label: string;
|
|
117
|
+
detail?: string;
|
|
118
|
+
status?: 'ok' | 'error';
|
|
119
|
+
}
|
|
120
|
+
/** A retained tool run keyed by the parent message's toolCallId. The product
|
|
121
|
+
* persists these server-side (fail-closed: only ids its own loop created)
|
|
122
|
+
* and serves them to the drill-in panel. */
|
|
123
|
+
interface ToolRunRecord {
|
|
124
|
+
toolCallId: string;
|
|
125
|
+
toolName: string;
|
|
126
|
+
title: string;
|
|
127
|
+
status: 'running' | 'complete' | 'error';
|
|
128
|
+
steps: ToolRunStep[];
|
|
129
|
+
}
|
|
130
|
+
interface RunDrillInProps {
|
|
131
|
+
run: ToolRunRecord;
|
|
132
|
+
onClose: () => void;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Readonly side panel showing a retained tool run's transcript — the
|
|
136
|
+
* "drill into what the sandbox actually did" view. Follow-ups happen in the
|
|
137
|
+
* main chat, never here.
|
|
138
|
+
*/
|
|
139
|
+
declare function RunDrillIn({ run, onClose }: RunDrillInProps): react.JSX.Element;
|
|
40
140
|
interface ChatToolCallInfo {
|
|
41
141
|
id: string;
|
|
42
142
|
name: string;
|
|
43
143
|
status: 'running' | 'done' | 'error';
|
|
144
|
+
/** The tool outcome (`{ok, result}` shape). When `result.status` is
|
|
145
|
+
* 'queued_for_approval' the chip renders the approval state. */
|
|
146
|
+
result?: unknown;
|
|
44
147
|
}
|
|
148
|
+
/** Extract `{proposalId, status}` from a tool outcome when it is a proposal
|
|
149
|
+
* awaiting human approval; null otherwise. */
|
|
150
|
+
declare function pendingApprovalOf(call: ChatToolCallInfo): {
|
|
151
|
+
proposalId: string;
|
|
152
|
+
} | null;
|
|
45
153
|
interface ChatUiMessage extends ChatMessageMetrics {
|
|
46
154
|
id: string;
|
|
47
155
|
role: 'user' | 'assistant' | 'system';
|
|
@@ -61,6 +169,15 @@ interface ChatMessagesProps {
|
|
|
61
169
|
agentLabel?: string;
|
|
62
170
|
/** Render the trailing "agent is thinking" row. */
|
|
63
171
|
loading?: boolean;
|
|
172
|
+
/** Approve/Reject handlers for proposals awaiting approval. When omitted the
|
|
173
|
+
* chip still shows "awaiting approval" but without action buttons. */
|
|
174
|
+
approval?: ProposalApprovalHandlers;
|
|
175
|
+
/** Make tool chips clickable (e.g. open a {@link RunDrillIn} panel). */
|
|
176
|
+
onToolCallClick?: (call: ChatToolCallInfo, message: ChatUiMessage) => void;
|
|
177
|
+
}
|
|
178
|
+
interface ProposalApprovalHandlers {
|
|
179
|
+
onApprove: (proposalId: string, toolCallId: string) => void | Promise<void>;
|
|
180
|
+
onReject: (proposalId: string, toolCallId: string) => void | Promise<void>;
|
|
64
181
|
}
|
|
65
182
|
/**
|
|
66
183
|
* The message thread: one centered column; user messages are right-aligned
|
|
@@ -68,6 +185,6 @@ interface ChatMessagesProps {
|
|
|
68
185
|
* model id, tokens/sec, and cost, plus a collapsible thinking section and
|
|
69
186
|
* tool-call chips.
|
|
70
187
|
*/
|
|
71
|
-
declare function ChatMessages({ messages, models, renderMarkdown, renderExtras, userLabel, agentLabel, loading, }: ChatMessagesProps): react.JSX.Element;
|
|
188
|
+
declare function ChatMessages({ messages, models, renderMarkdown, renderExtras, userLabel, agentLabel, loading, approval, onToolCallClick, }: ChatMessagesProps): react.JSX.Element;
|
|
72
189
|
|
|
73
|
-
export { type ChatMessageMetrics, ChatMessages, type ChatMessagesProps, type ChatToolCallInfo, type ChatUiMessage, EffortPicker, type EffortPickerProps, ModelPicker, type ModelPickerProps, formatModelCost, formatTokensPerSecond };
|
|
190
|
+
export { type ChatMessageMetrics, ChatMessages, type ChatMessagesProps, type ChatStreamCallbacks, type ChatStreamToolCall, type ChatStreamToolResult, type ChatToolCallInfo, type ChatUiMessage, type ConsumeChatStreamResult, EffortPicker, type EffortPickerProps, ModelPicker, type ModelPickerProps, type ProposalApprovalHandlers, RunDrillIn, type RunDrillInProps, type StreamChatOptions, type ToolRunRecord, type ToolRunStep, consumeChatStream, dispatchChatStreamLine, formatModelCost, formatTokensPerSecond, pendingApprovalOf, streamChatTurn };
|