@adia-ai/agent 0.8.26

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/frame.js ADDED
@@ -0,0 +1,43 @@
1
+ /**
2
+ * frameClientMessage / shouldRunTurn — law 6: framed client-message turns.
3
+ *
4
+ * The session is a plain serializable turn array (session.ts); every
5
+ * surface action, function/tool result, and validation rejection re-enters
6
+ * the loop as a *distinct natural-language user turn* through this ONE
7
+ * framing function — never scattered ad-hoc string-building at call sites.
8
+ *
9
+ * Silent-apply kinds (a data-model echo, an action-response ack the caller
10
+ * already consumed) never construct a turn at all: `shouldRunTurn` gates
11
+ * them out BEFORE framing is attempted, and `frameClientMessage` itself
12
+ * THROWS if handed one directly — a should-not-run message is
13
+ * unconstructable as a turn, not merely skipped. This mirrors the wire's
14
+ * own three-arm client vocabulary (action / error / functionResponse) one
15
+ * level up, in plain language the model reads as a user turn.
16
+ */
17
+ const SILENT_APPLY_KINDS = new Set(['dataModelUpdate', 'ack']);
18
+ /** Gate BEFORE framing: false means this message applies silently and must
19
+ * never reach `frameClientMessage`. */
20
+ export function shouldRunTurn(msg) {
21
+ return !SILENT_APPLY_KINDS.has(msg.kind);
22
+ }
23
+ /** Maps one client-message arm to its pinned natural-language user turn.
24
+ * Deterministic — same input, same string, always — so golden tests can
25
+ * pin the exact wording. Throws for any kind `shouldRunTurn` rejects. */
26
+ export function frameClientMessage(msg) {
27
+ switch (msg.kind) {
28
+ case 'surfaceAction':
29
+ return `The user triggered the ${msg.action} action on surface ${msg.surfaceId} with context ${JSON.stringify(msg.context ?? null)}.`;
30
+ case 'functionResult':
31
+ return `The function ${msg.call} returned: ${JSON.stringify(msg.value)}.`;
32
+ case 'validationRejection':
33
+ return `The previous surface was rejected (${msg.code}): ${msg.message}. Emit a corrected surface.`;
34
+ case 'dataModelUpdate':
35
+ case 'ack':
36
+ throw new Error(`frameClientMessage: "${msg.kind}" is silent-apply — gate with shouldRunTurn() before framing`);
37
+ default: {
38
+ const unreachable = msg;
39
+ throw new Error(`frameClientMessage: unknown kind "${unreachable.kind}"`);
40
+ }
41
+ }
42
+ }
43
+ //# sourceMappingURL=frame.js.map
package/frame.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame.js","sourceRoot":"","sources":["src/frame.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAkBH,MAAM,kBAAkB,GAAuC,IAAI,GAAG,CAAC,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC,CAAC;AAEnG;wCACwC;AACxC,MAAM,UAAU,aAAa,CAAC,GAAkB;IAC9C,OAAO,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3C,CAAC;AAED;;0EAE0E;AAC1E,MAAM,UAAU,kBAAkB,CAAC,GAAkB;IACnD,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,eAAe;YAClB,OAAO,0BAA0B,GAAG,CAAC,MAAM,sBAAsB,GAAG,CAAC,SAAS,iBAAiB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC;QAExI,KAAK,gBAAgB;YACnB,OAAO,gBAAgB,GAAG,CAAC,IAAI,cAAc,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;QAE5E,KAAK,qBAAqB;YACxB,OAAO,sCAAsC,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,OAAO,6BAA6B,CAAC;QAEtG,KAAK,iBAAiB,CAAC;QACvB,KAAK,KAAK;YACR,MAAM,IAAI,KAAK,CACb,wBAAwB,GAAG,CAAC,IAAI,8DAA8D,CAC/F,CAAC;QAEJ,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,WAAW,GAAU,GAAG,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,qCAAsC,WAA6B,CAAC,IAAI,GAAG,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC;AACH,CAAC"}
package/index.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @adia-ai/agent — composable chat-agent harness for AdiaUI.
3
+ *
4
+ * Assemble an agent from four declared parts on top of @adia-ai/llm:
5
+ * prompt layers, tools, workflows, resources. Owns the tool-call loop,
6
+ * the serializable Session, and the one shared event reducer.
7
+ */
8
+ export { createAgent } from './agent.js';
9
+ export type { Agent, AgentConfig, SendOpts } from './agent.js';
10
+ export { promptLayer, composeSystem } from './prompt.js';
11
+ export type { PromptLayer, ComposedSystem } from './prompt.js';
12
+ export { defineTool, executeTool, checkInput, toSpecs } from './tools.js';
13
+ export type { ToolDef, ToolContext, ToolOutcome } from './tools.js';
14
+ export { defineWorkflow, runWorkflow } from './workflow.js';
15
+ export type { Workflow, WorkflowStep, WorkflowContext, WorkflowResult } from './workflow.js';
16
+ export { defineResource } from './resource.js';
17
+ export type { ResourceDef } from './resource.js';
18
+ export { createIntegrationRegistry, resolveIntegrations, buildToolDispatch, MAX_INTEGRATIONS } from './integrations.js';
19
+ export type { IntegrationManifest, IntegrationRegistry, IntegrationContext, ResolvedIntegrations } from './integrations.js';
20
+ export { createSession, toJSON, fromJSON } from './session.js';
21
+ export type { Session, Msg, Draft } from './session.js';
22
+ export { reduce, reduceAll, PROGRESS_STAGES, isProgressStage } from './events.js';
23
+ export type { AgentEvent, ProgressStage } from './events.js';
24
+ export { frameClientMessage, shouldRunTurn } from './frame.js';
25
+ export type { ClientMessage } from './frame.js';
26
+ export { scriptClient } from './stub.js';
27
+ export type { ScriptedTurn, ScriptClient } from './stub.js';
28
+ //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1E,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5D,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACxH,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC5H,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC/D,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAClF,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC/D,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC"}
package/index.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @adia-ai/agent — composable chat-agent harness for AdiaUI.
3
+ *
4
+ * Assemble an agent from four declared parts on top of @adia-ai/llm:
5
+ * prompt layers, tools, workflows, resources. Owns the tool-call loop,
6
+ * the serializable Session, and the one shared event reducer.
7
+ */
8
+ export { createAgent } from './agent.js';
9
+ export { promptLayer, composeSystem } from './prompt.js';
10
+ export { defineTool, executeTool, checkInput, toSpecs } from './tools.js';
11
+ export { defineWorkflow, runWorkflow } from './workflow.js';
12
+ export { defineResource } from './resource.js';
13
+ export { createIntegrationRegistry, resolveIntegrations, buildToolDispatch, MAX_INTEGRATIONS } from './integrations.js';
14
+ export { createSession, toJSON, fromJSON } from './session.js';
15
+ export { reduce, reduceAll, PROGRESS_STAGES, isProgressStage } from './events.js';
16
+ export { frameClientMessage, shouldRunTurn } from './frame.js';
17
+ export { scriptClient } from './stub.js';
18
+ //# sourceMappingURL=index.js.map
package/index.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1E,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAExH,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAElF,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Integrations — the tier-2 (machine-callable) tool registry.
3
+ *
4
+ * CHAT-HARNESS law 5 draws a line between two different things that both
5
+ * end up as prompt/tool material: config-level tool ENTRIES (tier 1, prose,
6
+ * no schema, live in L2) and machine-callable INTEGRATIONS (tier 2, this
7
+ * module) — a typed manifest with a real JSON-Schema input, boot-time
8
+ * fail-fast registration, and schema-validated dispatch. `defineTool` in
9
+ * ./tools.js is the tier-2 wire shape this module compiles down to.
10
+ *
11
+ * An IntegrationManifest carries three INDEPENDENT facts, never conflated:
12
+ * - `id` — enablement vocabulary (what a persona's entry list or a
13
+ * settings UI toggles on/off; stable across renames).
14
+ * - `tool.name` — the wire name the MODEL calls (goes on the ToolSpec).
15
+ * - `label` — the DISPLAY name a human sees in a picker or a dropped-
16
+ * integration notice.
17
+ * Renaming a tool's wire name (a prompt-engineering concern) must never
18
+ * silently re-enable or disable it; renaming its display label must never
19
+ * touch dispatch. Keeping them apart is the whole point of the type.
20
+ *
21
+ * The pipeline is three pure stages:
22
+ * register → boot-fail-fast (throws — a bad manifest never reaches
23
+ * runtime)
24
+ * resolve → per-request, per-persona: enabledIds ∩ registry, capped,
25
+ * unprovisioned serverKey manifests DROPPED (never a
26
+ * mid-turn failure — a missing key degrades to "not
27
+ * offered" and is reported back for UI display)
28
+ * buildDispatch → the ONE place a resolved manifest becomes a ToolDef,
29
+ * closing over the env-var NAME (never the key value) so
30
+ * the key is read fresh at call time and never serialized
31
+ * onto the manifest object or persisted anywhere.
32
+ *
33
+ * Law 8: when a second (server-side) host consumes this registry — a proxy
34
+ * or worker dispatching tool calls outside the browser — the env-var
35
+ * resolution and the drop-on-unprovisioned rule this module owns must
36
+ * extract to a shared place in THAT change, not be hand-duplicated. Nothing
37
+ * here assumes a browser; `env` is passed in, never read from a global.
38
+ */
39
+ import { type ToolContext, type ToolDef } from './tools.js';
40
+ export interface IntegrationManifest {
41
+ /** Enablement vocabulary — what a persona/settings UI toggles. */
42
+ id: string;
43
+ tool: {
44
+ /** The wire name the model calls. Independent of `id` and `label`. */
45
+ name: string;
46
+ description?: string;
47
+ inputSchema: Record<string, unknown>;
48
+ };
49
+ /** Display name for a human (picker, dropped-integration notice). */
50
+ label: string;
51
+ auth?: {
52
+ kind: 'serverKey';
53
+ envKey: string;
54
+ } | {
55
+ kind: 'none';
56
+ };
57
+ execute: (input: Record<string, unknown>, ctx: IntegrationContext) => unknown | Promise<unknown>;
58
+ }
59
+ /** ToolContext plus the resolved server key for THIS dispatch — present
60
+ * only when `auth.kind === 'serverKey'` and the env var was set (an unset
61
+ * one never reaches here: resolveIntegrations already dropped it). */
62
+ export interface IntegrationContext extends ToolContext {
63
+ key?: string;
64
+ }
65
+ export interface IntegrationRegistry {
66
+ /** Boot-fail-fast: throws on a duplicate id, a duplicate tool.name, an
67
+ * inputSchema outside checkInput's supported subset, or a serverKey auth
68
+ * with a missing/empty envKey. Returns the manifest on success. */
69
+ register(manifest: IntegrationManifest): IntegrationManifest;
70
+ get(id: string): IntegrationManifest | undefined;
71
+ list(): IntegrationManifest[];
72
+ }
73
+ export declare function createIntegrationRegistry(): IntegrationRegistry;
74
+ /** Documented cap — resolveIntegrations never hands more than this many
75
+ * manifests to one dispatch, regardless of how many a persona enables. */
76
+ export declare const MAX_INTEGRATIONS = 16;
77
+ export interface ResolvedIntegrations {
78
+ resolved: IntegrationManifest[];
79
+ /** Enabled-but-unusable manifests, reported (not thrown) for UI display —
80
+ * a dropped manifest degrades to "not offered", never a mid-turn error. */
81
+ dropped: Array<{
82
+ id: string;
83
+ reason: string;
84
+ }>;
85
+ }
86
+ /** enabledIds ∩ registry, capped at MAX_INTEGRATIONS, then any serverKey
87
+ * manifest whose env var is unset in `env` is dropped (reason reported).
88
+ * Order matches the contract's own wording: intersect → cap → drop, so a
89
+ * persona enabling more than the cap never sees a key-provisioning check
90
+ * applied to an integration it wouldn't have gotten a slot for anyway. */
91
+ export declare function resolveIntegrations(registry: IntegrationRegistry, enabledIds: string[], env: Record<string, string | undefined>): ResolvedIntegrations;
92
+ /** The ONE place resolved manifests become `{ tools: ToolDef[] }` for
93
+ * AgentConfig. Each ToolDef's `execute` closes over `env` and the auth's
94
+ * envKey NAME only — the key VALUE is read fresh from `env` at call time,
95
+ * never stored on the manifest, never serialized. Schema validation is
96
+ * NOT repeated here: `executeTool` (tools.js, driving every ToolDef
97
+ * through the loop) already runs `checkInput` before invoking `execute` —
98
+ * wrapping it again here would check twice for one call. Zero resolved
99
+ * manifests returns `{}` (no `tools` key at all), so an agent with no
100
+ * integrations enabled produces the exact same AgentConfig, and the same
101
+ * outbound request, as one that never knew integrations existed (law 2). */
102
+ export declare function buildToolDispatch(resolved: IntegrationManifest[], env: Record<string, string | undefined>): {
103
+ tools: ToolDef[];
104
+ } | Record<string, never>;
105
+ //# sourceMappingURL=integrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["src/integrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAc,KAAK,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAExE,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE;QACJ,sEAAsE;QACtE,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACtC,CAAC;IACF,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAChE,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,kBAAkB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAClG;AAED;;uEAEuE;AACvE,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC;;wEAEoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,GAAG,mBAAmB,CAAC;IAC7D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAAC;IACjD,IAAI,IAAI,mBAAmB,EAAE,CAAC;CAC/B;AAyCD,wBAAgB,yBAAyB,IAAI,mBAAmB,CAoC/D;AAED;2EAC2E;AAC3E,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC;gFAC4E;IAC5E,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAED;;;;2EAI2E;AAC3E,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,mBAAmB,EAC7B,UAAU,EAAE,MAAM,EAAE,EACpB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACtC,oBAAoB,CAyBtB;AAED;;;;;;;;;6EAS6E;AAC7E,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACtC;IAAE,KAAK,EAAE,OAAO,EAAE,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAY9C"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Integrations — the tier-2 (machine-callable) tool registry.
3
+ *
4
+ * CHAT-HARNESS law 5 draws a line between two different things that both
5
+ * end up as prompt/tool material: config-level tool ENTRIES (tier 1, prose,
6
+ * no schema, live in L2) and machine-callable INTEGRATIONS (tier 2, this
7
+ * module) — a typed manifest with a real JSON-Schema input, boot-time
8
+ * fail-fast registration, and schema-validated dispatch. `defineTool` in
9
+ * ./tools.js is the tier-2 wire shape this module compiles down to.
10
+ *
11
+ * An IntegrationManifest carries three INDEPENDENT facts, never conflated:
12
+ * - `id` — enablement vocabulary (what a persona's entry list or a
13
+ * settings UI toggles on/off; stable across renames).
14
+ * - `tool.name` — the wire name the MODEL calls (goes on the ToolSpec).
15
+ * - `label` — the DISPLAY name a human sees in a picker or a dropped-
16
+ * integration notice.
17
+ * Renaming a tool's wire name (a prompt-engineering concern) must never
18
+ * silently re-enable or disable it; renaming its display label must never
19
+ * touch dispatch. Keeping them apart is the whole point of the type.
20
+ *
21
+ * The pipeline is three pure stages:
22
+ * register → boot-fail-fast (throws — a bad manifest never reaches
23
+ * runtime)
24
+ * resolve → per-request, per-persona: enabledIds ∩ registry, capped,
25
+ * unprovisioned serverKey manifests DROPPED (never a
26
+ * mid-turn failure — a missing key degrades to "not
27
+ * offered" and is reported back for UI display)
28
+ * buildDispatch → the ONE place a resolved manifest becomes a ToolDef,
29
+ * closing over the env-var NAME (never the key value) so
30
+ * the key is read fresh at call time and never serialized
31
+ * onto the manifest object or persisted anywhere.
32
+ *
33
+ * Law 8: when a second (server-side) host consumes this registry — a proxy
34
+ * or worker dispatching tool calls outside the browser — the env-var
35
+ * resolution and the drop-on-unprovisioned rule this module owns must
36
+ * extract to a shared place in THAT change, not be hand-duplicated. Nothing
37
+ * here assumes a browser; `env` is passed in, never read from a global.
38
+ */
39
+ import { defineTool } from './tools.js';
40
+ const TOP_LEVEL_ALLOWED = new Set(['type', 'properties', 'required', 'description']);
41
+ const PROPERTY_ALLOWED = new Set(['type', 'enum', 'description']);
42
+ /** checkInput (tools.js) only reads top-level `required` / per-property
43
+ * `type` / per-property `enum`. Anything else in the schema (oneOf, $ref,
44
+ * pattern, items, nested objects, additionalProperties…) would silently
45
+ * never be enforced — so registration rejects it instead of shipping a
46
+ * manifest whose declared contract lies about what's actually checked. */
47
+ function unsupportedSchemaFeature(schema) {
48
+ if (!schema || typeof schema !== 'object' || Array.isArray(schema)) {
49
+ return 'inputSchema must be an object';
50
+ }
51
+ for (const key of Object.keys(schema)) {
52
+ if (!TOP_LEVEL_ALLOWED.has(key)) {
53
+ return `uses unsupported top-level keyword "${key}" (checkInput only supports type/properties/required)`;
54
+ }
55
+ }
56
+ if ('required' in schema && !Array.isArray(schema['required'])) {
57
+ return '"required" must be an array of strings';
58
+ }
59
+ if ('properties' in schema) {
60
+ const properties = schema['properties'];
61
+ if (!properties || typeof properties !== 'object' || Array.isArray(properties)) {
62
+ return '"properties" must be an object';
63
+ }
64
+ for (const [name, prop] of Object.entries(properties)) {
65
+ if (!prop || typeof prop !== 'object' || Array.isArray(prop)) {
66
+ return `property "${name}" schema must be an object`;
67
+ }
68
+ for (const key of Object.keys(prop)) {
69
+ if (!PROPERTY_ALLOWED.has(key)) {
70
+ return `property "${name}" uses unsupported keyword "${key}" (checkInput only supports type/enum)`;
71
+ }
72
+ }
73
+ }
74
+ }
75
+ return null;
76
+ }
77
+ export function createIntegrationRegistry() {
78
+ const byId = new Map();
79
+ const toolNameOwner = new Map();
80
+ return {
81
+ register(manifest) {
82
+ if (byId.has(manifest.id)) {
83
+ throw new Error(`createIntegrationRegistry: duplicate integration id "${manifest.id}"`);
84
+ }
85
+ const existingOwner = toolNameOwner.get(manifest.tool.name);
86
+ if (existingOwner) {
87
+ throw new Error(`createIntegrationRegistry: duplicate tool name "${manifest.tool.name}" — ` +
88
+ `already registered by integration "${existingOwner}" (integration "${manifest.id}")`);
89
+ }
90
+ const schemaProblem = unsupportedSchemaFeature(manifest.tool.inputSchema);
91
+ if (schemaProblem) {
92
+ throw new Error(`createIntegrationRegistry "${manifest.id}": inputSchema ${schemaProblem}`);
93
+ }
94
+ if (manifest.auth?.kind === 'serverKey' && !manifest.auth.envKey) {
95
+ throw new Error(`createIntegrationRegistry "${manifest.id}": auth.envKey is required and non-empty for kind "serverKey"`);
96
+ }
97
+ byId.set(manifest.id, manifest);
98
+ toolNameOwner.set(manifest.tool.name, manifest.id);
99
+ return manifest;
100
+ },
101
+ get(id) {
102
+ return byId.get(id);
103
+ },
104
+ list() {
105
+ return [...byId.values()];
106
+ },
107
+ };
108
+ }
109
+ /** Documented cap — resolveIntegrations never hands more than this many
110
+ * manifests to one dispatch, regardless of how many a persona enables. */
111
+ export const MAX_INTEGRATIONS = 16;
112
+ /** enabledIds ∩ registry, capped at MAX_INTEGRATIONS, then any serverKey
113
+ * manifest whose env var is unset in `env` is dropped (reason reported).
114
+ * Order matches the contract's own wording: intersect → cap → drop, so a
115
+ * persona enabling more than the cap never sees a key-provisioning check
116
+ * applied to an integration it wouldn't have gotten a slot for anyway. */
117
+ export function resolveIntegrations(registry, enabledIds, env) {
118
+ const intersected = [];
119
+ const seen = new Set();
120
+ for (const id of enabledIds) {
121
+ if (seen.has(id))
122
+ continue;
123
+ seen.add(id);
124
+ const manifest = registry.get(id);
125
+ if (manifest)
126
+ intersected.push(manifest);
127
+ }
128
+ const capped = intersected.slice(0, MAX_INTEGRATIONS);
129
+ const resolved = [];
130
+ const dropped = [];
131
+ for (const manifest of capped) {
132
+ if (manifest.auth?.kind === 'serverKey' && !env[manifest.auth.envKey]) {
133
+ dropped.push({
134
+ id: manifest.id,
135
+ reason: `unprovisioned: env var "${manifest.auth.envKey}" is not set`,
136
+ });
137
+ continue;
138
+ }
139
+ resolved.push(manifest);
140
+ }
141
+ return { resolved, dropped };
142
+ }
143
+ /** The ONE place resolved manifests become `{ tools: ToolDef[] }` for
144
+ * AgentConfig. Each ToolDef's `execute` closes over `env` and the auth's
145
+ * envKey NAME only — the key VALUE is read fresh from `env` at call time,
146
+ * never stored on the manifest, never serialized. Schema validation is
147
+ * NOT repeated here: `executeTool` (tools.js, driving every ToolDef
148
+ * through the loop) already runs `checkInput` before invoking `execute` —
149
+ * wrapping it again here would check twice for one call. Zero resolved
150
+ * manifests returns `{}` (no `tools` key at all), so an agent with no
151
+ * integrations enabled produces the exact same AgentConfig, and the same
152
+ * outbound request, as one that never knew integrations existed (law 2). */
153
+ export function buildToolDispatch(resolved, env) {
154
+ if (!resolved.length)
155
+ return {};
156
+ const tools = resolved.map(manifest => defineTool({
157
+ name: manifest.tool.name,
158
+ ...(manifest.tool.description ? { description: manifest.tool.description } : {}),
159
+ inputSchema: manifest.tool.inputSchema,
160
+ execute: (input, ctx) => {
161
+ const key = manifest.auth?.kind === 'serverKey' ? env[manifest.auth.envKey] : undefined;
162
+ return manifest.execute(input, key !== undefined ? { ...ctx, key } : ctx);
163
+ },
164
+ }));
165
+ return { tools };
166
+ }
167
+ //# sourceMappingURL=integrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrations.js","sourceRoot":"","sources":["src/integrations.ts"],"names":[],"mappings":"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"}
package/loop.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The turn loop — stream → tool_use → execute → tool_result → continue.
3
+ *
4
+ * One agent.send() = one runLoop(). Each round streams a model response;
5
+ * tool calls are executed (gated by onToolCall when provided) and fed back
6
+ * as tool_result parts, then the loop re-enters. A round with no tool calls
7
+ * is the final round: the loop emits `done` and returns.
8
+ *
9
+ * Bounded by maxToolRounds: on exhaustion the loop emits `done` with the
10
+ * synthetic stopReason 'max_tool_rounds' (loop-level signal, not a
11
+ * provider value — the adapter-level never-normalize rule is untouched).
12
+ *
13
+ * The loop maintains its OWN working message list; the caller's Session is
14
+ * never mutated here (reduce() is the single session writer). The events
15
+ * this generator yields, folded through reduce(), reconstruct exactly the
16
+ * messages the loop appended internally — one contract, two consumers.
17
+ *
18
+ * Progress markers (law 3): the loop emits ONLY the stages it genuinely
19
+ * reaches — `sent` before every provider call, `retry` before a call that
20
+ * repeats a round after tool feedback (i.e. round > 0), `tool` before each
21
+ * tool executes, `done` right before the terminal `done` event on both
22
+ * exit paths. The other vocabulary entries (`started`/`reasoning`/
23
+ * `content`/`validating`) belong to signals this loop doesn't independently
24
+ * observe today — inventing an emission point for them would violate the
25
+ * honesty guard, so they stay declared-but-unemitted here.
26
+ */
27
+ import type { ChatOpts, LLMClient, ToolUse } from '@adia-ai/llm';
28
+ import type { AgentEvent } from './events.js';
29
+ import type { Msg } from './session.js';
30
+ import { type ToolContext, type ToolDef } from './tools.js';
31
+ export interface LoopOpts {
32
+ client: LLMClient;
33
+ /** Per-call ChatOpts overrides (model, system, cache, temperature…). */
34
+ chat?: Partial<ChatOpts>;
35
+ tools: ToolDef[];
36
+ maxToolRounds: number;
37
+ /** Gate every tool call before it executes. Return false to deny — the
38
+ * model receives an isError tool_result and the loop continues. The
39
+ * caller owns escalation (same contract as validate-and-repair). */
40
+ onToolCall?: (call: ToolUse, ctx: ToolContext) => boolean | Promise<boolean>;
41
+ ctx: ToolContext;
42
+ }
43
+ export declare function runLoop(messages: Msg[], opts: LoopOpts): AsyncGenerator<AgentEvent>;
44
+ //# sourceMappingURL=loop.d.ts.map
package/loop.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["src/loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAQ,OAAO,EAAgB,MAAM,cAAc,CAAC;AACrF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAwB,KAAK,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAElF,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,SAAS,CAAC;IAClB,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB;;yEAEqE;IACrE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7E,GAAG,EAAE,WAAW,CAAC;CAClB;AAED,wBAAuB,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,GAAG,cAAc,CAAC,UAAU,CAAC,CA2F1F"}
package/loop.js ADDED
@@ -0,0 +1,120 @@
1
+ /**
2
+ * The turn loop — stream → tool_use → execute → tool_result → continue.
3
+ *
4
+ * One agent.send() = one runLoop(). Each round streams a model response;
5
+ * tool calls are executed (gated by onToolCall when provided) and fed back
6
+ * as tool_result parts, then the loop re-enters. A round with no tool calls
7
+ * is the final round: the loop emits `done` and returns.
8
+ *
9
+ * Bounded by maxToolRounds: on exhaustion the loop emits `done` with the
10
+ * synthetic stopReason 'max_tool_rounds' (loop-level signal, not a
11
+ * provider value — the adapter-level never-normalize rule is untouched).
12
+ *
13
+ * The loop maintains its OWN working message list; the caller's Session is
14
+ * never mutated here (reduce() is the single session writer). The events
15
+ * this generator yields, folded through reduce(), reconstruct exactly the
16
+ * messages the loop appended internally — one contract, two consumers.
17
+ *
18
+ * Progress markers (law 3): the loop emits ONLY the stages it genuinely
19
+ * reaches — `sent` before every provider call, `retry` before a call that
20
+ * repeats a round after tool feedback (i.e. round > 0), `tool` before each
21
+ * tool executes, `done` right before the terminal `done` event on both
22
+ * exit paths. The other vocabulary entries (`started`/`reasoning`/
23
+ * `content`/`validating`) belong to signals this loop doesn't independently
24
+ * observe today — inventing an emission point for them would violate the
25
+ * honesty guard, so they stay declared-but-unemitted here.
26
+ */
27
+ import { executeTool, toSpecs } from './tools.js';
28
+ export async function* runLoop(messages, opts) {
29
+ const working = [...messages];
30
+ const total = { input: 0, output: 0, cacheCreation: 0, cacheRead: 0 };
31
+ const specs = toSpecs(opts.tools);
32
+ const byName = new Map(opts.tools.map(t => [t.name, t]));
33
+ for (let round = 0; round < opts.maxToolRounds; round++) {
34
+ let text = '';
35
+ let stopReason = 'end';
36
+ const calls = [];
37
+ if (round > 0)
38
+ yield { type: 'progress', stage: 'retry' };
39
+ yield { type: 'progress', stage: 'sent' };
40
+ const stream = opts.client.stream({
41
+ ...opts.chat,
42
+ messages: working,
43
+ ...(specs.length ? { tools: specs } : {}),
44
+ ...(opts.ctx.signal ? { signal: opts.ctx.signal } : {}),
45
+ });
46
+ for await (const chunk of stream) {
47
+ if (chunk.type === 'text') {
48
+ text = chunk.snapshot;
49
+ yield { type: 'text', text: chunk.text, snapshot: chunk.snapshot };
50
+ }
51
+ else if (chunk.type === 'thinking') {
52
+ yield { type: 'thinking', text: chunk.text };
53
+ }
54
+ else if (chunk.type === 'tool_use') {
55
+ calls.push({ id: chunk.id, name: chunk.name, input: chunk.input });
56
+ yield { type: 'tool_use', id: chunk.id, name: chunk.name, input: chunk.input };
57
+ }
58
+ else if (chunk.type === 'done') {
59
+ stopReason = chunk.stopReason;
60
+ // The adapter's done.text is authoritative — a client emitting
61
+ // empty snapshots on word chunks still yields the full final text.
62
+ if (chunk.text)
63
+ text = chunk.text;
64
+ total.input += chunk.usage.input;
65
+ total.output += chunk.usage.output;
66
+ total.cacheCreation = (total.cacheCreation ?? 0) + (chunk.usage.cacheCreation ?? 0);
67
+ total.cacheRead = (total.cacheRead ?? 0) + (chunk.usage.cacheRead ?? 0);
68
+ }
69
+ else if (chunk.type === 'error') {
70
+ yield { type: 'error', error: chunk.error };
71
+ return;
72
+ }
73
+ }
74
+ if (!calls.length) {
75
+ yield { type: 'progress', stage: 'done' };
76
+ yield { type: 'done', text, usage: total, stopReason };
77
+ return;
78
+ }
79
+ // Assistant turn: text (when present) + the tool_use parts, then one
80
+ // tool message carrying every result — mirrors reduce()'s folding.
81
+ const assistantParts = [
82
+ ...(text ? [{ type: 'text', text }] : []),
83
+ ...calls.map(c => ({ type: 'tool_use', id: c.id, name: c.name, input: c.input })),
84
+ ];
85
+ working.push({ role: 'assistant', content: assistantParts });
86
+ const resultParts = [];
87
+ for (const call of calls) {
88
+ yield { type: 'progress', stage: 'tool' };
89
+ const tool = byName.get(call.name);
90
+ let outcome;
91
+ if (!tool) {
92
+ outcome = { output: `Unknown tool "${call.name}"`, isError: true };
93
+ }
94
+ else if (opts.onToolCall && (await opts.onToolCall(call, opts.ctx)) === false) {
95
+ outcome = { output: `Tool call "${call.name}" denied`, isError: true };
96
+ }
97
+ else {
98
+ outcome = await executeTool(tool, call.input, opts.ctx);
99
+ }
100
+ resultParts.push({
101
+ type: 'tool_result',
102
+ toolUseId: call.id,
103
+ name: call.name,
104
+ content: outcome.output,
105
+ ...(outcome.isError ? { isError: true } : {}),
106
+ });
107
+ yield {
108
+ type: 'tool_result',
109
+ id: call.id,
110
+ name: call.name,
111
+ output: outcome.output,
112
+ ...(outcome.isError ? { isError: true } : {}),
113
+ };
114
+ }
115
+ working.push({ role: 'tool', content: resultParts });
116
+ }
117
+ yield { type: 'progress', stage: 'done' };
118
+ yield { type: 'done', text: '', usage: total, stopReason: 'max_tool_rounds' };
119
+ }
120
+ //# sourceMappingURL=loop.js.map
package/loop.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["src/loop.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@adia-ai/agent",
3
+ "version": "0.8.26",
4
+ "description": "Composable chat-agent harness — assemble an agent from four declared parts (prompt layers, tools, workflows, resources) on top of @adia-ai/llm. Owns the tool-call loop, the session model, and the one shared event reducer. Works in browser and Node.",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./index.d.ts",
9
+ "import": "./index.js",
10
+ "default": "./index.js"
11
+ },
12
+ "./package.json": "./package.json"
13
+ },
14
+ "files": [
15
+ "*.js",
16
+ "*.d.ts",
17
+ "*.d.ts.map",
18
+ "*.js.map",
19
+ "README.md",
20
+ "CHANGELOG.md",
21
+ "!**/*.test.js"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsc --build tsconfig.build.json",
25
+ "prepublishOnly": "npm run build"
26
+ },
27
+ "dependencies": {
28
+ "@adia-ai/llm": "^0.8.0"
29
+ },
30
+ "sideEffects": false,
31
+ "publishConfig": {
32
+ "access": "public",
33
+ "registry": "https://registry.npmjs.org"
34
+ },
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/adiahealth/gen-ui-kit.git",
38
+ "directory": "packages/agent"
39
+ },
40
+ "license": "MIT"
41
+ }