@buoy-gg/agent-core 7.0.33
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/LICENSE +58 -0
- package/README.md +42 -0
- package/lib/commonjs/blocks/receipts.js +702 -0
- package/lib/commonjs/blocks/receipts.js.map +1 -0
- package/lib/commonjs/blocks/types.js +119 -0
- package/lib/commonjs/blocks/types.js.map +1 -0
- package/lib/commonjs/blocks/uiTool.js +994 -0
- package/lib/commonjs/blocks/uiTool.js.map +1 -0
- package/lib/commonjs/catalog/catalog.g.js +4044 -0
- package/lib/commonjs/catalog/catalog.g.js.map +1 -0
- package/lib/commonjs/catalog/catalog.source.json +4956 -0
- package/lib/commonjs/catalog/snapshotReads.js +256 -0
- package/lib/commonjs/catalog/snapshotReads.js.map +1 -0
- package/lib/commonjs/catalog/toProviderTools.js +107 -0
- package/lib/commonjs/catalog/toProviderTools.js.map +1 -0
- package/lib/commonjs/catalog/validateParams.js +129 -0
- package/lib/commonjs/catalog/validateParams.js.map +1 -0
- package/lib/commonjs/context/buildContextPack.js +141 -0
- package/lib/commonjs/context/buildContextPack.js.map +1 -0
- package/lib/commonjs/effects/ledger.js +229 -0
- package/lib/commonjs/effects/ledger.js.map +1 -0
- package/lib/commonjs/engine/effectFor.js +95 -0
- package/lib/commonjs/engine/effectFor.js.map +1 -0
- package/lib/commonjs/engine/runAgentTurn.js +667 -0
- package/lib/commonjs/engine/runAgentTurn.js.map +1 -0
- package/lib/commonjs/engine/systemPrompt.js +86 -0
- package/lib/commonjs/engine/systemPrompt.js.map +1 -0
- package/lib/commonjs/index.js +288 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/policy/labels.js +303 -0
- package/lib/commonjs/policy/labels.js.map +1 -0
- package/lib/commonjs/policy/policy.js +143 -0
- package/lib/commonjs/policy/policy.js.map +1 -0
- package/lib/commonjs/policy/redact.js +135 -0
- package/lib/commonjs/policy/redact.js.map +1 -0
- package/lib/commonjs/providers/anthropic.js +272 -0
- package/lib/commonjs/providers/anthropic.js.map +1 -0
- package/lib/commonjs/providers/openai.js +193 -0
- package/lib/commonjs/providers/openai.js.map +1 -0
- package/lib/commonjs/providers/sse.js +104 -0
- package/lib/commonjs/providers/sse.js.map +1 -0
- package/lib/commonjs/providers/types.js +6 -0
- package/lib/commonjs/providers/types.js.map +1 -0
- package/lib/commonjs/session.js +173 -0
- package/lib/commonjs/session.js.map +1 -0
- package/lib/commonjs/types.js +2 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/blocks/receipts.js +696 -0
- package/lib/module/blocks/receipts.js.map +1 -0
- package/lib/module/blocks/types.js +113 -0
- package/lib/module/blocks/types.js.map +1 -0
- package/lib/module/blocks/uiTool.js +987 -0
- package/lib/module/blocks/uiTool.js.map +1 -0
- package/lib/module/catalog/catalog.g.js +4040 -0
- package/lib/module/catalog/catalog.g.js.map +1 -0
- package/lib/module/catalog/catalog.source.json +4956 -0
- package/lib/module/catalog/snapshotReads.js +252 -0
- package/lib/module/catalog/snapshotReads.js.map +1 -0
- package/lib/module/catalog/toProviderTools.js +101 -0
- package/lib/module/catalog/toProviderTools.js.map +1 -0
- package/lib/module/catalog/validateParams.js +124 -0
- package/lib/module/catalog/validateParams.js.map +1 -0
- package/lib/module/context/buildContextPack.js +138 -0
- package/lib/module/context/buildContextPack.js.map +1 -0
- package/lib/module/effects/ledger.js +223 -0
- package/lib/module/effects/ledger.js.map +1 -0
- package/lib/module/engine/effectFor.js +91 -0
- package/lib/module/engine/effectFor.js.map +1 -0
- package/lib/module/engine/runAgentTurn.js +663 -0
- package/lib/module/engine/runAgentTurn.js.map +1 -0
- package/lib/module/engine/systemPrompt.js +82 -0
- package/lib/module/engine/systemPrompt.js.map +1 -0
- package/lib/module/index.js +30 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/policy/labels.js +296 -0
- package/lib/module/policy/labels.js.map +1 -0
- package/lib/module/policy/policy.js +137 -0
- package/lib/module/policy/policy.js.map +1 -0
- package/lib/module/policy/redact.js +128 -0
- package/lib/module/policy/redact.js.map +1 -0
- package/lib/module/providers/anthropic.js +268 -0
- package/lib/module/providers/anthropic.js.map +1 -0
- package/lib/module/providers/openai.js +189 -0
- package/lib/module/providers/openai.js.map +1 -0
- package/lib/module/providers/sse.js +99 -0
- package/lib/module/providers/sse.js.map +1 -0
- package/lib/module/providers/types.js +4 -0
- package/lib/module/providers/types.js.map +1 -0
- package/lib/module/session.js +168 -0
- package/lib/module/session.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/blocks/receipts.d.ts +32 -0
- package/lib/typescript/blocks/receipts.d.ts.map +1 -0
- package/lib/typescript/blocks/types.d.ts +576 -0
- package/lib/typescript/blocks/types.d.ts.map +1 -0
- package/lib/typescript/blocks/uiTool.d.ts +15 -0
- package/lib/typescript/blocks/uiTool.d.ts.map +1 -0
- package/lib/typescript/catalog/catalog.g.d.ts +11 -0
- package/lib/typescript/catalog/catalog.g.d.ts.map +1 -0
- package/lib/typescript/catalog/snapshotReads.d.ts +37 -0
- package/lib/typescript/catalog/snapshotReads.d.ts.map +1 -0
- package/lib/typescript/catalog/toProviderTools.d.ts +52 -0
- package/lib/typescript/catalog/toProviderTools.d.ts.map +1 -0
- package/lib/typescript/catalog/validateParams.d.ts +33 -0
- package/lib/typescript/catalog/validateParams.d.ts.map +1 -0
- package/lib/typescript/context/buildContextPack.d.ts +32 -0
- package/lib/typescript/context/buildContextPack.d.ts.map +1 -0
- package/lib/typescript/effects/ledger.d.ts +119 -0
- package/lib/typescript/effects/ledger.d.ts.map +1 -0
- package/lib/typescript/engine/effectFor.d.ts +21 -0
- package/lib/typescript/engine/effectFor.d.ts.map +1 -0
- package/lib/typescript/engine/runAgentTurn.d.ts +140 -0
- package/lib/typescript/engine/runAgentTurn.d.ts.map +1 -0
- package/lib/typescript/engine/systemPrompt.d.ts +49 -0
- package/lib/typescript/engine/systemPrompt.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +29 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/policy/labels.d.ts +10 -0
- package/lib/typescript/policy/labels.d.ts.map +1 -0
- package/lib/typescript/policy/policy.d.ts +106 -0
- package/lib/typescript/policy/policy.d.ts.map +1 -0
- package/lib/typescript/policy/redact.d.ts +37 -0
- package/lib/typescript/policy/redact.d.ts.map +1 -0
- package/lib/typescript/providers/anthropic.d.ts +22 -0
- package/lib/typescript/providers/anthropic.d.ts.map +1 -0
- package/lib/typescript/providers/openai.d.ts +19 -0
- package/lib/typescript/providers/openai.d.ts.map +1 -0
- package/lib/typescript/providers/sse.d.ts +18 -0
- package/lib/typescript/providers/sse.d.ts.map +1 -0
- package/lib/typescript/providers/types.d.ts +129 -0
- package/lib/typescript/providers/types.d.ts.map +1 -0
- package/lib/typescript/session.d.ts +58 -0
- package/lib/typescript/session.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +119 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog -> provider tool definitions.
|
|
3
|
+
*
|
|
4
|
+
* WHY ONE TOOL PER BUOY TOOL, NOT ONE PER ACTION: tool-selection accuracy
|
|
5
|
+
* degrades past roughly 30-50 tools. Buoy has ~179 actions across 22 tools, so
|
|
6
|
+
* a 1:1 mapping is far past the point where the model starts picking wrong.
|
|
7
|
+
* Each Buoy tool therefore becomes ONE provider tool whose `action` property is
|
|
8
|
+
* an enum, with the per-action summaries folded into that enum's description.
|
|
9
|
+
*
|
|
10
|
+
* `params` stays an open object at the provider boundary — a discriminated
|
|
11
|
+
* union across 179 branches is unusable by any model and unreadable by a human.
|
|
12
|
+
* The real per-action schema is enforced one layer in, by `validateParams`,
|
|
13
|
+
* which returns a structured error the model can correct on the next turn.
|
|
14
|
+
* That is strictly stronger than the MCP server's `z.record(z.unknown())`,
|
|
15
|
+
* which validates nothing.
|
|
16
|
+
*/
|
|
17
|
+
import type { ToolDescriptor } from "../types";
|
|
18
|
+
/** Provider-agnostic tool definition; the adapters reshape it per protocol. */
|
|
19
|
+
export interface ProviderTool {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: "object";
|
|
24
|
+
properties: Record<string, unknown>;
|
|
25
|
+
required: string[];
|
|
26
|
+
additionalProperties: boolean;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export declare function toProviderToolName(toolId: string): string;
|
|
30
|
+
/** Reverse of {@link toProviderToolName}, resolved against the live catalog. */
|
|
31
|
+
export declare function fromProviderToolName(name: string, catalog: ToolDescriptor[]): string | undefined;
|
|
32
|
+
export interface ToProviderToolsOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Tool ids actually dispatchable on this device, from `listToolActions()`.
|
|
35
|
+
* A tool the app didn't install must not be offered — the model will
|
|
36
|
+
* otherwise spend a turn calling something that can only fail.
|
|
37
|
+
*/
|
|
38
|
+
availableToolIds?: string[];
|
|
39
|
+
/** Available action names per tool, when the host can supply them. */
|
|
40
|
+
availableActions?: Record<string, string[]>;
|
|
41
|
+
/** `__DEV__ === false`. Drives the release annotations and filtering. */
|
|
42
|
+
isRelease?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Drop actions that cannot work in this build instead of annotating them.
|
|
45
|
+
* Default false: an annotated-but-present action lets the model explain the
|
|
46
|
+
* limitation to the user, which is more useful than silently having no way
|
|
47
|
+
* to talk about it.
|
|
48
|
+
*/
|
|
49
|
+
hideUnavailable?: boolean;
|
|
50
|
+
}
|
|
51
|
+
export declare function toProviderTools(catalog: ToolDescriptor[], opts?: ToProviderToolsOptions): ProviderTool[];
|
|
52
|
+
//# sourceMappingURL=toProviderTools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toProviderTools.d.ts","sourceRoot":"","sources":["../../../src/catalog/toProviderTools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAoB,cAAc,EAAE,MAAM,UAAU,CAAC;AAEjE,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,oBAAoB,EAAE,OAAO,CAAC;KAC/B,CAAC;CACH;AASD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,gFAAgF;AAChF,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc,EAAE,GACxB,MAAM,GAAG,SAAS,CAEpB;AAmBD,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5C,yEAAyE;IACzE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,cAAc,EAAE,EACzB,IAAI,GAAE,sBAA2B,GAChC,YAAY,EAAE,CAiEhB"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A deliberately small JSON Schema validator.
|
|
3
|
+
*
|
|
4
|
+
* Buoy's adapters validate nothing — every handler takes `params?: unknown` and
|
|
5
|
+
* hand-casts (`(params as { id?: string })?.id`), so a wrong shape becomes an
|
|
6
|
+
* undefined read, and an LLM omitting an optional flag can do real damage:
|
|
7
|
+
* `zustand.setState` defaults `replace ?? true`, so calling it without
|
|
8
|
+
* `replace` REPLACES the entire store rather than merging it.
|
|
9
|
+
*
|
|
10
|
+
* So the agent validates before it dispatches. The point is not spec
|
|
11
|
+
* compliance — it is that a rejection comes back to the model as a readable
|
|
12
|
+
* error naming the expected schema, which it can fix on the next turn. That is
|
|
13
|
+
* why this covers exactly the subset `JsonSchema` describes and nothing more:
|
|
14
|
+
* a rule the validator silently skips is a rule that isn't enforced.
|
|
15
|
+
*/
|
|
16
|
+
import type { JsonSchema } from "../types";
|
|
17
|
+
export interface ValidationResult {
|
|
18
|
+
ok: boolean;
|
|
19
|
+
errors: string[];
|
|
20
|
+
}
|
|
21
|
+
export declare function validateParams(params: unknown, schema: JsonSchema): ValidationResult;
|
|
22
|
+
/**
|
|
23
|
+
* Fill in documented defaults the model left out.
|
|
24
|
+
*
|
|
25
|
+
* This is the counter-measure to the omitted-flag class of bug. Several Buoy
|
|
26
|
+
* actions invert the usual assumption — `focus-inspector.setTracking` reads
|
|
27
|
+
* `params?.enabled !== false`, so calling it with `{}` turns tracking ON — and
|
|
28
|
+
* the catalog records the real default. Applying it explicitly means the model
|
|
29
|
+
* omitting a flag produces the documented behaviour rather than the accidental
|
|
30
|
+
* one.
|
|
31
|
+
*/
|
|
32
|
+
export declare function applyDefaults(params: unknown, schema: JsonSchema): Record<string, unknown>;
|
|
33
|
+
//# sourceMappingURL=validateParams.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateParams.d.ts","sourceRoot":"","sources":["../../../src/catalog/validateParams.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AA6FD,wBAAgB,cAAc,CAC5B,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,UAAU,GACjB,gBAAgB,CAMlB;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,UAAU,GACjB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOzB"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The grounding digest — "here is what this app looks like".
|
|
3
|
+
*
|
|
4
|
+
* Composed entirely from readers that already exist. Most Buoy adapters ship a
|
|
5
|
+
* compact action written explicitly for a remote driver (`listQueries`,
|
|
6
|
+
* `listStores`, `listAtoms`, `getState`, `async.getAllKeys`), and those are
|
|
7
|
+
* exactly the right size: measured on a live idle device the whole digest is
|
|
8
|
+
* ~5.7KB (~1.5K tokens) covering routes, env, query keys, redux slices,
|
|
9
|
+
* zustand stores, jotai atoms, storage keys and API hosts.
|
|
10
|
+
*
|
|
11
|
+
* What this does NOT do, and why:
|
|
12
|
+
* - No `getSnapshot('query')`. It returns the full dehydrated cache — 8.3KB for
|
|
13
|
+
* ten queries in that same measurement, growing with every cached payload.
|
|
14
|
+
* `listQueries` covers the same ground in 1.8KB.
|
|
15
|
+
* - No console. It is the fattest payload in the system at ~1.1KB per entry
|
|
16
|
+
* with up to 1000 retained; a naive "include recent logs" is a 1MB prompt.
|
|
17
|
+
* - No values, only shapes and keys. `includeValues`/`includeData` are
|
|
18
|
+
* unbounded on the action path — no adapter applies a size guard — and the
|
|
19
|
+
* whole point of the digest is to tell the model where to look, not to
|
|
20
|
+
* pre-fetch everything it might want.
|
|
21
|
+
*/
|
|
22
|
+
import type { DispatchFn, SnapshotFn } from "../types";
|
|
23
|
+
export interface BuildContextInput {
|
|
24
|
+
dispatch: DispatchFn;
|
|
25
|
+
/** Needed by the snapshot-only probes (routes, env). */
|
|
26
|
+
readSnapshot?: SnapshotFn;
|
|
27
|
+
/** Tool ids actually present, so we do not probe what cannot answer. */
|
|
28
|
+
availableToolIds: string[];
|
|
29
|
+
availableActions?: Record<string, string[]>;
|
|
30
|
+
}
|
|
31
|
+
export declare function buildContextDigest({ dispatch, readSnapshot, availableToolIds, availableActions, }: BuildContextInput): Promise<Record<string, unknown>>;
|
|
32
|
+
//# sourceMappingURL=buildContextPack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildContextPack.d.ts","sourceRoot":"","sources":["../../../src/context/buildContextPack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAiHvD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,UAAU,CAAC;IACrB,wDAAwD;IACxD,YAAY,CAAC,EAAE,UAAU,CAAC;IAC1B,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC7C;AAED,wBAAsB,kBAAkB,CAAC,EACvC,QAAQ,EACR,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,GACjB,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAsCtD"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The effect ledger — what the agent changed, and how to put it back.
|
|
3
|
+
*
|
|
4
|
+
* Ask Buoy runs mutations immediately rather than asking first, so "undo" has
|
|
5
|
+
* to be real. The model is Scenarios' `AppliedEffect` / `revertEffects`
|
|
6
|
+
* (packages/scenarios/src/engine.ts:238-272), with two deliberate departures,
|
|
7
|
+
* both fixing gaps that engine documents in itself:
|
|
8
|
+
*
|
|
9
|
+
* 1. STORAGE IS ACTUALLY REVERSIBLE HERE. Scenarios classifies storage writes
|
|
10
|
+
* as unrecoverable because it never captured the prior value. An agent can:
|
|
11
|
+
* it reads the key before it writes, so undo restores the old value exactly,
|
|
12
|
+
* and removes the key when it did not exist before.
|
|
13
|
+
* 2. THE COUNT TELLS THE TRUTH. Scenarios' banner counts transients as
|
|
14
|
+
* "changes" and then silently no-ops on them at revert. Here reversible and
|
|
15
|
+
* one-shot effects are counted separately and the banner says both, because
|
|
16
|
+
* a user who taps Undo and sees "4 changes" become nothing changed learns
|
|
17
|
+
* not to trust the banner.
|
|
18
|
+
*
|
|
19
|
+
* Undo runs in REVERSE order — a later write to the same key must be undone
|
|
20
|
+
* before the earlier one, or the earlier value is the one that survives.
|
|
21
|
+
*/
|
|
22
|
+
import type { DispatchFn } from "../types";
|
|
23
|
+
export type AppliedEffect = {
|
|
24
|
+
kind: "network-override";
|
|
25
|
+
ruleId: string;
|
|
26
|
+
label: string;
|
|
27
|
+
} | {
|
|
28
|
+
kind: "impersonation";
|
|
29
|
+
label: string;
|
|
30
|
+
} | {
|
|
31
|
+
kind: "storage-write";
|
|
32
|
+
toolId: string;
|
|
33
|
+
action: string;
|
|
34
|
+
key: string;
|
|
35
|
+
/**
|
|
36
|
+
* The MMKV instance the key lives in. Every `mmkv.*` action is scoped to
|
|
37
|
+
* a registered instance, so an undo that omits it writes nowhere.
|
|
38
|
+
*/
|
|
39
|
+
instanceId?: string;
|
|
40
|
+
/** The value before this write; undefined when the key did not exist. */
|
|
41
|
+
before?: string;
|
|
42
|
+
/**
|
|
43
|
+
* The value this write set, so undo can tell whether the key still
|
|
44
|
+
* holds OUR value. Another writer (an MCP session, the desktop, the app
|
|
45
|
+
* itself) landing in between must not be silently clobbered by a
|
|
46
|
+
* restore of the old value.
|
|
47
|
+
*/
|
|
48
|
+
wrote?: string;
|
|
49
|
+
/** The action that removes the key, for the did-not-exist case. */
|
|
50
|
+
removeAction?: string;
|
|
51
|
+
label: string;
|
|
52
|
+
} | {
|
|
53
|
+
kind: "state-write";
|
|
54
|
+
toolId: string;
|
|
55
|
+
action: string;
|
|
56
|
+
label: string;
|
|
57
|
+
} | {
|
|
58
|
+
kind: "transient";
|
|
59
|
+
label: string;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Whether Undo can actually put this effect back. THE one place the answer
|
|
63
|
+
* lives: the bar, the sync snapshot and `revertOne` all agree through it.
|
|
64
|
+
* `state-write` is a wipe or a store write with no captured prior state —
|
|
65
|
+
* the ledger records it so the user can see it happened, and it is
|
|
66
|
+
* PERMANENT. Counting it as undoable made the bar promise "1 undoable" and
|
|
67
|
+
* then fail with "can't be undone automatically" on tap.
|
|
68
|
+
*/
|
|
69
|
+
export declare function isReversible(effect: AppliedEffect): boolean;
|
|
70
|
+
export interface LedgerEntry {
|
|
71
|
+
id: string;
|
|
72
|
+
at: number;
|
|
73
|
+
toolId: string;
|
|
74
|
+
action: string;
|
|
75
|
+
effect: AppliedEffect;
|
|
76
|
+
/** Set once undone, so the banner can grey the row rather than drop it. */
|
|
77
|
+
undoneAt?: number;
|
|
78
|
+
undoError?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface RevertOutcome {
|
|
81
|
+
reverted: number;
|
|
82
|
+
failed: {
|
|
83
|
+
label: string;
|
|
84
|
+
error: string;
|
|
85
|
+
}[];
|
|
86
|
+
/** One-shot effects that were never reversible. Reported, not hidden. */
|
|
87
|
+
skippedTransients: number;
|
|
88
|
+
}
|
|
89
|
+
export declare class EffectLedger {
|
|
90
|
+
private entries;
|
|
91
|
+
private listeners;
|
|
92
|
+
record(toolId: string, action: string, effect: AppliedEffect): LedgerEntry;
|
|
93
|
+
list(): LedgerEntry[];
|
|
94
|
+
/** New array identity for the snapshot after entries were mutated in place. */
|
|
95
|
+
private touch;
|
|
96
|
+
/** Not-yet-undone entries that Undo can actually deliver on. Agrees with
|
|
97
|
+
* `isReversible` — it used to include state-writes, which revertOne refuses,
|
|
98
|
+
* so the two disagreed about the one fact they both exist to answer. */
|
|
99
|
+
reversible(): LedgerEntry[];
|
|
100
|
+
/** Not-yet-undone one-shots. Counted separately so the banner is honest. */
|
|
101
|
+
transients(): LedgerEntry[];
|
|
102
|
+
isEmpty(): boolean;
|
|
103
|
+
subscribe(fn: () => void): () => void;
|
|
104
|
+
clear(): void;
|
|
105
|
+
/**
|
|
106
|
+
* Reconcile the ledger after a change was reverted OUTSIDE `revertOne` —
|
|
107
|
+
* the model deleting the override it created, a block button's Delete, a
|
|
108
|
+
* stopImpersonation call. Without this the create entry stays "undoable"
|
|
109
|
+
* and Undo later fails against a rule that no longer exists, which reads
|
|
110
|
+
* as the banner lying.
|
|
111
|
+
*/
|
|
112
|
+
noteExternalRevert(toolId: string, action: string, params: Record<string, unknown>): void;
|
|
113
|
+
private emit;
|
|
114
|
+
/** Undo one entry. Returns an error string, or undefined on success. */
|
|
115
|
+
revertOne(entry: LedgerEntry, dispatch: DispatchFn): Promise<string | undefined>;
|
|
116
|
+
/** Undo everything still outstanding, newest first. */
|
|
117
|
+
revertAll(dispatch: DispatchFn): Promise<RevertOutcome>;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=ledger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../../../src/effects/ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACxC;IACE,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf,GACD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAE3D;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,aAAa,CAAC;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3C,yEAAyE;IACzE,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAID,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,SAAS,CAAyB;IAE1C,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,WAAW;IAiB1E,IAAI,IAAI,WAAW,EAAE;IAIrB,+EAA+E;IAC/E,OAAO,CAAC,KAAK;IAKb;;4EAEwE;IACxE,UAAU,IAAI,WAAW,EAAE;IAI3B,4EAA4E;IAC5E,UAAU,IAAI,WAAW,EAAE;IAI3B,OAAO,IAAI,OAAO;IAIlB,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAKrC,KAAK,IAAI,IAAI;IAKb;;;;;;OAMG;IACH,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAyBzF,OAAO,CAAC,IAAI;IAUZ,wEAAwE;IAClE,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAqEtF,uDAAuD;IACjD,SAAS,CAAC,QAAQ,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC;CAgB9D"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn a completed mutation into a ledger entry.
|
|
3
|
+
*
|
|
4
|
+
* The shape is Scenarios' `extractEffect`, but the classification here is much
|
|
5
|
+
* more conservative, because auditing the catalog's undo claims found almost
|
|
6
|
+
* all of them unsound: the information needed to reverse a call usually does
|
|
7
|
+
* not survive the call. So an effect is only marked reversible when THIS
|
|
8
|
+
* module can point at the exact input the reversal needs.
|
|
9
|
+
*
|
|
10
|
+
* Everything else becomes `state-write` (changed something, no automatic
|
|
11
|
+
* inverse) or `transient` (one-shot). Both are shown to the user as such. A
|
|
12
|
+
* banner that says "4 changes" and then reverses one of them is worse than a
|
|
13
|
+
* banner that admits three of them are permanent.
|
|
14
|
+
*/
|
|
15
|
+
import type { ActionDescriptor } from "../types";
|
|
16
|
+
import type { AppliedEffect } from "../effects/ledger";
|
|
17
|
+
export declare function effectFor(toolId: string, descriptor: ActionDescriptor, params: Record<string, unknown>, result: unknown, before: {
|
|
18
|
+
had: boolean;
|
|
19
|
+
value?: string;
|
|
20
|
+
} | undefined): AppliedEffect | undefined;
|
|
21
|
+
//# sourceMappingURL=effectFor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effectFor.d.ts","sourceRoot":"","sources":["../../../src/engine/effectFor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,gBAAgB,EAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,MAAM,EAAE,OAAO,EACf,MAAM,EAAE;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GACnD,aAAa,GAAG,SAAS,CAwD3B"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One turn: user sentence in, tool calls and an answer out.
|
|
3
|
+
*
|
|
4
|
+
* The loop is deliberately explicit rather than clever, because every step of
|
|
5
|
+
* it encodes something that bites otherwise:
|
|
6
|
+
*
|
|
7
|
+
* - Validation happens BEFORE dispatch and a failure comes back as a readable
|
|
8
|
+
* tool_result, not an exception. Buoy's adapters validate nothing, so a
|
|
9
|
+
* wrong shape becomes an undefined read deep inside a tool — and an LLM
|
|
10
|
+
* omitting `replace` on `zustand.setState` replaces the entire store.
|
|
11
|
+
* - `app.reloadApp` is TERMINAL. It returns before the reload fires and then
|
|
12
|
+
* kills the JS realm; anything queued behind it dies with the conversation.
|
|
13
|
+
* - Results are truncated before they are sent. `dispatchToolAction` bypasses
|
|
14
|
+
* the 8MB wire cap that protects the broker path, so an in-app agent can
|
|
15
|
+
* receive a 50MB object and then try to feed it to a token-metered model.
|
|
16
|
+
* - Steps and wall-clock are capped, because a model that misreads a result
|
|
17
|
+
* will otherwise retry the same call until the user closes the sheet.
|
|
18
|
+
*/
|
|
19
|
+
import type { DispatchFn, SnapshotFn, ToolDescriptor } from "../types";
|
|
20
|
+
import type { AgentMessage, Provider } from "../providers/types";
|
|
21
|
+
import { EffectLedger } from "../effects/ledger";
|
|
22
|
+
import { type AskBuoyPolicy } from "../policy/policy";
|
|
23
|
+
import { type Block } from "../blocks/types";
|
|
24
|
+
export type TurnEvent = {
|
|
25
|
+
type: "text";
|
|
26
|
+
delta: string;
|
|
27
|
+
} | {
|
|
28
|
+
type: "tool-start";
|
|
29
|
+
id: string;
|
|
30
|
+
toolId: string;
|
|
31
|
+
action: string;
|
|
32
|
+
/** Short human title — "Open /bag". */
|
|
33
|
+
label: string;
|
|
34
|
+
/** The catalog sentence, for a row the user expands. */
|
|
35
|
+
description: string;
|
|
36
|
+
} | {
|
|
37
|
+
type: "tool-end";
|
|
38
|
+
id: string;
|
|
39
|
+
ok: boolean;
|
|
40
|
+
summary: string;
|
|
41
|
+
}
|
|
42
|
+
/** A block to render — a receipt from a tool result, or a model-authored block. */
|
|
43
|
+
| {
|
|
44
|
+
type: "block";
|
|
45
|
+
block: Block;
|
|
46
|
+
forToolCallId?: string;
|
|
47
|
+
}
|
|
48
|
+
/** An Ask block ended the turn; the user's answer will be the next user message. */
|
|
49
|
+
| {
|
|
50
|
+
type: "awaiting-user";
|
|
51
|
+
blockId: string;
|
|
52
|
+
} | {
|
|
53
|
+
type: "approval-required";
|
|
54
|
+
id: string;
|
|
55
|
+
toolId: string;
|
|
56
|
+
action: string;
|
|
57
|
+
label: string;
|
|
58
|
+
description: string;
|
|
59
|
+
reason: string;
|
|
60
|
+
} | {
|
|
61
|
+
type: "error";
|
|
62
|
+
message: string;
|
|
63
|
+
}
|
|
64
|
+
/** Token usage for one provider request, when the provider reports it. */
|
|
65
|
+
| {
|
|
66
|
+
type: "usage";
|
|
67
|
+
input: number;
|
|
68
|
+
output: number;
|
|
69
|
+
} | {
|
|
70
|
+
type: "done";
|
|
71
|
+
};
|
|
72
|
+
export interface RunTurnInput {
|
|
73
|
+
provider: Provider;
|
|
74
|
+
catalog: ToolDescriptor[];
|
|
75
|
+
messages: AgentMessage[];
|
|
76
|
+
system: string;
|
|
77
|
+
model: string;
|
|
78
|
+
maxTokens: number;
|
|
79
|
+
dispatch: DispatchFn;
|
|
80
|
+
/**
|
|
81
|
+
* Reads a tool's snapshot for the reserved `getSnapshot` action. Absent on a
|
|
82
|
+
* host that has no snapshot access; the action then fails with a plain reason
|
|
83
|
+
* rather than silently returning nothing.
|
|
84
|
+
*/
|
|
85
|
+
readSnapshot?: SnapshotFn;
|
|
86
|
+
/** `storage key -> owning live store`, from the grounding. See `annotate`. */
|
|
87
|
+
storeKeyOwners?: Record<string, string>;
|
|
88
|
+
ledger: EffectLedger;
|
|
89
|
+
policy: AskBuoyPolicy;
|
|
90
|
+
isRelease: boolean;
|
|
91
|
+
/** Live tool ids from `listToolActions()`, so absent tools are never offered. */
|
|
92
|
+
availableToolIds?: string[];
|
|
93
|
+
availableActions?: Record<string, string[]>;
|
|
94
|
+
/** Resolves once the user taps Approve/Reject on a pending call. */
|
|
95
|
+
requestApproval?: (input: {
|
|
96
|
+
id: string;
|
|
97
|
+
toolId: string;
|
|
98
|
+
action: string;
|
|
99
|
+
label: string;
|
|
100
|
+
description: string;
|
|
101
|
+
reason: string;
|
|
102
|
+
}) => Promise<boolean>;
|
|
103
|
+
signal?: AbortSignal;
|
|
104
|
+
}
|
|
105
|
+
export declare function runAgentTurn(input: RunTurnInput): AsyncGenerator<TurnEvent, AgentMessage[], void>;
|
|
106
|
+
export interface GatedActionInput {
|
|
107
|
+
toolId: string;
|
|
108
|
+
action: string;
|
|
109
|
+
params?: Record<string, unknown>;
|
|
110
|
+
dispatch: DispatchFn;
|
|
111
|
+
ledger: EffectLedger;
|
|
112
|
+
policy: AskBuoyPolicy;
|
|
113
|
+
isRelease: boolean;
|
|
114
|
+
/** Defaults to the built-in catalog. */
|
|
115
|
+
catalog?: ToolDescriptor[];
|
|
116
|
+
}
|
|
117
|
+
export type GatedActionOutcome = {
|
|
118
|
+
ok: true;
|
|
119
|
+
result: unknown;
|
|
120
|
+
} | {
|
|
121
|
+
ok: false;
|
|
122
|
+
error: string;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* One human-initiated action through EVERY gate the model's calls go through:
|
|
126
|
+
* catalog lookup, param validation, policy, pre-read, effect ledger.
|
|
127
|
+
*
|
|
128
|
+
* This exists for block buttons. The `buoy_ui` schema promises the model that
|
|
129
|
+
* a dispatch button runs "with the same policy and undo as if you called it",
|
|
130
|
+
* and the first implementation called `dispatchToolAction` raw — no deny list,
|
|
131
|
+
* no release refusal, no ledger entry. One tap on a model-authored button was
|
|
132
|
+
* an invisible, ungoverned, unundoable mutation. Route every button through
|
|
133
|
+
* here so the promise is true.
|
|
134
|
+
*
|
|
135
|
+
* `needs-approval` is treated as approved: the human's tap on the button IS
|
|
136
|
+
* the approval. Deny lists, read-only mode and release refusals still stand —
|
|
137
|
+
* a button must never reach further than the model could.
|
|
138
|
+
*/
|
|
139
|
+
export declare function runGatedAction(input: GatedActionInput): Promise<GatedActionOutcome>;
|
|
140
|
+
//# sourceMappingURL=runAgentTurn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runAgentTurn.d.ts","sourceRoot":"","sources":["../../../src/engine/runAgentTurn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAoB,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAKzF,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAwB,MAAM,oBAAoB,CAAC;AACvF,OAAO,EAAE,YAAY,EAAgB,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAK5E,OAAO,EAAc,KAAK,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAOzD,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/B;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;CACrB,GACD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAChE,mFAAmF;GACjF;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,KAAK,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE;AACzD,oFAAoF;GAClF;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC1C;IACE,IAAI,EAAE,mBAAmB,CAAC;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AACpC,0EAA0E;GACxE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErB,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,UAAU,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,UAAU,CAAC;IAC1B,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5C,oEAAoE;IACpE,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE;QACxB,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;KAChB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAwDD,wBAAuB,YAAY,CACjC,KAAK,EAAE,YAAY,GAClB,cAAc,CAAC,SAAS,EAAE,YAAY,EAAE,EAAE,IAAI,CAAC,CA+UjD;AA8BD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,QAAQ,EAAE,UAAU,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,wCAAwC;IACxC,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;CAC5B;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC7B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjC;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAuCzF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The system prompt.
|
|
3
|
+
*
|
|
4
|
+
* Everything Buoy wants the model to know lives HERE, never in a tool result.
|
|
5
|
+
* Claude is trained to discount instructions found inside `tool_result` blocks
|
|
6
|
+
* — that is the prompt-injection defence working as designed — so policy text
|
|
7
|
+
* smuggled in alongside data may be ignored outright or flagged as an attack.
|
|
8
|
+
* Instructions belong in the system prompt or a following user turn.
|
|
9
|
+
*
|
|
10
|
+
* The prompt is also where the release-build truth is stated. The tool
|
|
11
|
+
* descriptions carry per-action annotations, but a model reading 22 tool
|
|
12
|
+
* descriptions benefits from being told the rule once, up front.
|
|
13
|
+
*/
|
|
14
|
+
import type { ToolDescriptor } from "../types";
|
|
15
|
+
export interface ContextPack {
|
|
16
|
+
/** Plain-English annotations from the app author. The highest-value input. */
|
|
17
|
+
notes?: string[];
|
|
18
|
+
/**
|
|
19
|
+
* Exact shapes of the objects the agent may WRITE, as `name -> shape text`.
|
|
20
|
+
* Paste the real type; nothing parses it, it is handed to the model as
|
|
21
|
+
* written.
|
|
22
|
+
*
|
|
23
|
+
* types: { CartLine: "{ lineId: string; itemId: string; qty: number }" }
|
|
24
|
+
*
|
|
25
|
+
* WHY THIS EXISTS SEPARATELY FROM `notes`. Reading a live instance is the
|
|
26
|
+
* better source of a shape — it cannot go stale — and the prompt tells the
|
|
27
|
+
* model to prefer it. But there is nothing to read when the collection is
|
|
28
|
+
* EMPTY, which is exactly when someone asks for the first cart line, and no
|
|
29
|
+
* amount of runtime grounding fixes that: the digest is names-only by
|
|
30
|
+
* design, and an empty array has no shape. A note saying "item id = 123"
|
|
31
|
+
* tells the model the id and nothing about the object it belongs in.
|
|
32
|
+
*/
|
|
33
|
+
types?: Record<string, string>;
|
|
34
|
+
/** Auto-derived digest of what this app looks like at runtime. */
|
|
35
|
+
digest?: Record<string, unknown>;
|
|
36
|
+
/** Anything else the app wants to say to the model. */
|
|
37
|
+
extra?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface SystemPromptInput {
|
|
40
|
+
catalog: ToolDescriptor[];
|
|
41
|
+
context?: ContextPack;
|
|
42
|
+
isRelease: boolean;
|
|
43
|
+
readOnly: boolean;
|
|
44
|
+
requireApproval: string[];
|
|
45
|
+
appName?: string;
|
|
46
|
+
platform?: string;
|
|
47
|
+
}
|
|
48
|
+
export declare function buildSystemPrompt(input: SystemPromptInput): string;
|
|
49
|
+
//# sourceMappingURL=systemPrompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systemPrompt.d.ts","sourceRoot":"","sources":["../../../src/engine/systemPrompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,WAAW,WAAW;IAC1B,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CA2FlE"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @buoy-gg/agent-core — the brain behind Ask Buoy.
|
|
3
|
+
*
|
|
4
|
+
* Headless on purpose: no React, no react-native, no Node built-ins. The only
|
|
5
|
+
* thing it needs from a host is a `dispatch(toolId, action, params)` function,
|
|
6
|
+
* which is why the same core runs on a device (`dispatchToolAction` from
|
|
7
|
+
* `@buoy-gg/shared-ui`) and in Buoy Desktop (`callDevToolAction` over the
|
|
8
|
+
* broker) without a rewrite.
|
|
9
|
+
*/
|
|
10
|
+
export type { ActionDescriptor, ActionEffect, DispatchFn, JsonSchema, ReleaseBehavior, SnapshotFn, ToolDescriptor, UndoSpec, } from "./types";
|
|
11
|
+
export { CATALOG, CATALOG_ACTION_COUNT, CATALOG_TOOL_COUNT } from "./catalog/catalog.g";
|
|
12
|
+
export { fromProviderToolName, toProviderToolName, toProviderTools, type ProviderTool, type ToProviderToolsOptions, } from "./catalog/toProviderTools";
|
|
13
|
+
export { applyDefaults, validateParams, type ValidationResult, } from "./catalog/validateParams";
|
|
14
|
+
export { projectSnapshot, SNAPSHOT_ACTION } from "./catalog/snapshotReads";
|
|
15
|
+
export { createAnthropicProvider } from "./providers/anthropic";
|
|
16
|
+
export { createOpenAIProvider } from "./providers/openai";
|
|
17
|
+
export type { AgentMessage, Provider, ProviderConfig, ProviderRequest, StreamEvent, TokenUsage, ToolCall, ToolResult, } from "./providers/types";
|
|
18
|
+
export { runAgentTurn, runGatedAction, type GatedActionInput, type GatedActionOutcome, type RunTurnInput, type TurnEvent, } from "./engine/runAgentTurn";
|
|
19
|
+
export { buildSystemPrompt, type ContextPack, type SystemPromptInput, } from "./engine/systemPrompt";
|
|
20
|
+
export { buildContextDigest, type BuildContextInput } from "./context/buildContextPack";
|
|
21
|
+
export { EffectLedger, isReversible, type AppliedEffect, type LedgerEntry, type RevertOutcome, } from "./effects/ledger";
|
|
22
|
+
export { humanise, titleCall, toolTitle } from "./policy/labels";
|
|
23
|
+
export * from "./blocks/types";
|
|
24
|
+
export { UI_TOOL_NAME, UI_PARAMS, uiProviderTool, buildUiBlock } from "./blocks/uiTool";
|
|
25
|
+
export { projectReceipt, shallowDiff, type ReceiptInput } from "./blocks/receipts";
|
|
26
|
+
export { decide, describeCall, DEFAULT_REQUIRE_APPROVAL, resolveRequireApproval, type AllowRule, type AskBuoyPolicy, type Decision, } from "./policy/policy";
|
|
27
|
+
export { redact, registerSelfEndpoint, isSelfTraffic, stripSelfTraffic, } from "./policy/redact";
|
|
28
|
+
export { createAskBuoySession, type AskBuoySession, type AskBuoySessionConfig } from "./session";
|
|
29
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,UAAU,EACV,eAAe,EACf,UAAU,EACV,cAAc,EACd,QAAQ,GACT,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,KAAK,YAAY,EACjB,KAAK,sBAAsB,GAC5B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,aAAa,EACb,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE3E,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,YAAY,EACV,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,eAAe,EACf,WAAW,EACX,UAAU,EACV,QAAQ,EACR,UAAU,GACX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,YAAY,EACZ,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,SAAS,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,iBAAiB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAExF,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,GACnB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjE,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACxF,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,EACL,MAAM,EACN,YAAY,EACZ,wBAAwB,EACxB,sBAAsB,EACtB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,QAAQ,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,MAAM,EACN,oBAAoB,EACpB,aAAa,EACb,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** The display name of a tool: "Routes", "Zustand", "React Query". */
|
|
2
|
+
export declare function toolTitle(toolId: string): string;
|
|
3
|
+
/** `getStoreState` → "Get store state"; `async.getItem` → "Get item". */
|
|
4
|
+
export declare function humanise(action: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* A short, present-tense title for a call — the thing a transcript row, a
|
|
7
|
+
* ledger row and an approval card all show first.
|
|
8
|
+
*/
|
|
9
|
+
export declare function titleCall(toolId: string, action: string, params: Record<string, unknown>): string;
|
|
10
|
+
//# sourceMappingURL=labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../../../src/policy/labels.ts"],"names":[],"mappings":"AA+MA,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEhD;AAgCD,yEAAyE;AACzE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAO/C;AAaD;;;GAGG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAoBR"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the agent is allowed to do, decided before dispatch.
|
|
3
|
+
*
|
|
4
|
+
* The default: reads and writes auto-run — the banner plus the effect ledger
|
|
5
|
+
* keep the user in control — but DESTRUCTIVE actions need a human tap unless
|
|
6
|
+
* the app explicitly passes `requireApproval: []`. Auto-running wipes proved
|
|
7
|
+
* too sharp in live evals (five destructive calls in one confused turn), and
|
|
8
|
+
* the approval gate is also the blast-radius control if injected text in a
|
|
9
|
+
* tool result ever steers the model.
|
|
10
|
+
*
|
|
11
|
+
* The one thing the policy layer will not do is let the agent report success
|
|
12
|
+
* for an action that cannot work in this build. Several Buoy actions return
|
|
13
|
+
* `{ok:true}` and do nothing once `__DEV__` is false — `upsertOverrideRule`
|
|
14
|
+
* persists a rule the engine never consults — and a QA tester who files a bug
|
|
15
|
+
* against data that was never applied is a worse outcome than no agent at all.
|
|
16
|
+
* So `release !== "works"` is refused BEFORE dispatch, with the reason handed
|
|
17
|
+
* back to the model as the tool result, and `unknown` fails closed.
|
|
18
|
+
*/
|
|
19
|
+
import type { ActionDescriptor, ActionEffect } from "../types";
|
|
20
|
+
/**
|
|
21
|
+
* One allow rule. A call is permitted when it matches ANY rule; every field a
|
|
22
|
+
* rule specifies must match. So a support seat that may impersonate and look
|
|
23
|
+
* at anything, and nothing else, is two rules:
|
|
24
|
+
*
|
|
25
|
+
* allow: [{ effect: "read" }, { toolId: "impersonate" }]
|
|
26
|
+
*/
|
|
27
|
+
export interface AllowRule {
|
|
28
|
+
toolId?: string;
|
|
29
|
+
action?: string;
|
|
30
|
+
effect?: ActionEffect;
|
|
31
|
+
}
|
|
32
|
+
export interface AskBuoyPolicy {
|
|
33
|
+
/**
|
|
34
|
+
* Effect classes that need a human tap before they run. Default
|
|
35
|
+
* `["destructive"]` — wipes and resets wait for approval. Pass `[]`
|
|
36
|
+
* explicitly for full auto-run.
|
|
37
|
+
*/
|
|
38
|
+
requireApproval?: ActionEffect[];
|
|
39
|
+
/**
|
|
40
|
+
* Specific calls that ALWAYS need a tap, on top of `requireApproval` —
|
|
41
|
+
* "impersonation asks first" is `[{ toolId: "impersonate", action:
|
|
42
|
+
* "startImpersonation" }]` without putting every write behind a card.
|
|
43
|
+
*/
|
|
44
|
+
requireApprovalFor?: {
|
|
45
|
+
toolId: string;
|
|
46
|
+
action?: string;
|
|
47
|
+
}[];
|
|
48
|
+
/**
|
|
49
|
+
* Allow-list. When set, anything matching NO rule is refused — the shape
|
|
50
|
+
* for a scoped seat, instead of enumerating denials across ~190 actions.
|
|
51
|
+
* `deny` still wins over `allow`.
|
|
52
|
+
*/
|
|
53
|
+
allow?: AllowRule[];
|
|
54
|
+
/** Refuse these outright, whatever the model asks for. */
|
|
55
|
+
deny?: {
|
|
56
|
+
toolId: string;
|
|
57
|
+
action?: string;
|
|
58
|
+
}[];
|
|
59
|
+
/** Read-only mode: nothing that changes state, at all. */
|
|
60
|
+
readOnly?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Let the model read SecureStore VALUES (`storage.secure.get` /
|
|
63
|
+
* `secure.snapshot`). Off by default: those values are tokens and secrets
|
|
64
|
+
* by definition, and they would travel to the configured model endpoint.
|
|
65
|
+
* Key NAMES are always readable.
|
|
66
|
+
*/
|
|
67
|
+
secureReads?: boolean;
|
|
68
|
+
/** Cap on model->tool->model round trips in one turn. */
|
|
69
|
+
maxSteps?: number;
|
|
70
|
+
}
|
|
71
|
+
/** The one place the approval default lives; `decide` and the system prompt both resolve through it. */
|
|
72
|
+
export declare const DEFAULT_REQUIRE_APPROVAL: ActionEffect[];
|
|
73
|
+
export declare function resolveRequireApproval(policy: AskBuoyPolicy): ActionEffect[];
|
|
74
|
+
export type Decision = {
|
|
75
|
+
verdict: "allow";
|
|
76
|
+
} | {
|
|
77
|
+
verdict: "needs-approval";
|
|
78
|
+
reason: string;
|
|
79
|
+
} | {
|
|
80
|
+
verdict: "refuse";
|
|
81
|
+
reason: string;
|
|
82
|
+
};
|
|
83
|
+
export interface DecideInput {
|
|
84
|
+
descriptor: ActionDescriptor;
|
|
85
|
+
toolId: string;
|
|
86
|
+
policy: AskBuoyPolicy;
|
|
87
|
+
/** `__DEV__ === false` for this bundle. */
|
|
88
|
+
isRelease: boolean;
|
|
89
|
+
}
|
|
90
|
+
export declare function decide({ descriptor, toolId, policy, isRelease, }: DecideInput): Decision;
|
|
91
|
+
/**
|
|
92
|
+
* A short, domain-flavoured title for what a call will do — the first line of
|
|
93
|
+
* a transcript row, a ledger row and an approval card.
|
|
94
|
+
*
|
|
95
|
+
* The raw tool payload is deliberately NOT what gets shown. A QA person cannot
|
|
96
|
+
* evaluate `redux_dispatch({type:'SET_ENTITLEMENTS', payload:{...}})`, and an
|
|
97
|
+
* approval prompt nobody can read is a rubber stamp, which is worse than no
|
|
98
|
+
* prompt because it looks like oversight.
|
|
99
|
+
*
|
|
100
|
+
* Nor is the catalog `summary`: that sentence is written for the model and
|
|
101
|
+
* ran to three lines in a phone-width row before it was cut off. The phrasing
|
|
102
|
+
* lives in ./labels.ts; the catalog sentence travels separately on the event
|
|
103
|
+
* as `description`, for a row the user chooses to expand.
|
|
104
|
+
*/
|
|
105
|
+
export declare function describeCall(toolId: string, descriptor: ActionDescriptor, params: Record<string, unknown>): string;
|
|
106
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../../src/policy/policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG/D;;;;;;GAMG;AACH,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,eAAe,CAAC,EAAE,YAAY,EAAE,CAAC;IACjC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3D;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IACpB,0DAA0D;IAC1D,IAAI,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7C,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wGAAwG;AACxG,eAAO,MAAM,wBAAwB,EAAE,YAAY,EAAoB,CAAC;AAExE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,GAAG,YAAY,EAAE,CAE5E;AAED,MAAM,MAAM,QAAQ,GAChB;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GACpB;IAAE,OAAO,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,OAAO,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1C,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,gBAAgB,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,aAAa,CAAC;IACtB,2CAA2C;IAC3C,SAAS,EAAE,OAAO,CAAC;CACpB;AAKD,wBAAgB,MAAM,CAAC,EACrB,UAAU,EACV,MAAM,EACN,MAAM,EACN,SAAS,GACV,EAAE,WAAW,GAAG,QAAQ,CAuExB;AAoBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,gBAAgB,EAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAER"}
|