@ziggs-ai/agent-sdk 0.24.1 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/dist/Agent.d.ts +6 -0
- package/dist/Agent.js +40 -7
- package/dist/brain/ClaudeBrain.d.ts +8 -0
- package/dist/brain/ClaudeBrain.js +32 -2
- package/dist/brain/claudeCognition.js +24 -1
- package/dist/brain/claudeSdkProtocol.d.ts +1 -1
- package/dist/brain/claudeSdkProtocol.js +5 -1
- package/dist/brain/claudeSdkTools.js +9 -46
- package/dist/brain/hostedToolSurface.d.ts +14 -0
- package/dist/brain/hostedToolSurface.js +207 -0
- package/dist/brain/wakeGate.d.ts +48 -0
- package/dist/brain/wakeGate.js +76 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/ingress/normalizeIncoming.d.ts +2 -0
- package/dist/ingress/normalizeIncoming.js +1 -0
- package/dist/platform/ZiggsEffectHandler.d.ts +1 -1
- package/dist/platform/ZiggsEffectHandler.js +1 -1
- package/dist/platform/inboxLoop.d.ts +3 -13
- package/dist/platform/inboxLoop.js +66 -115
- package/dist/platform/tools/index.d.ts +1 -1
- package/dist/platform/tools/index.js +1 -1
- package/dist/platform/tools/tier2/contextTools.d.ts +1 -0
- package/dist/platform/tools/tier2/contextTools.js +2 -1
- package/dist/runtime/PromptBuilder.js +2 -18
- package/dist/runtime/buildOutcome.d.ts +8 -0
- package/dist/runtime/buildOutcome.js +1 -14
- package/dist/types.d.ts +2 -0
- package/package.json +2 -2
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the hosted Claude brain mounts into the model.
|
|
3
|
+
*
|
|
4
|
+
* The MCP door already lists only the everyday set plus a catalog. This is
|
|
5
|
+
* that same cut for the in-process brain: everyday SDK tools stay loaded by
|
|
6
|
+
* name, agent-owned tools stay loaded by name, and every other Ziggs platform
|
|
7
|
+
* tool is named by `tools` and called through `tool_read` or `tool_write`.
|
|
8
|
+
* The tools stay registered on the ToolManager — the FSM brain and the
|
|
9
|
+
* dispatcher both call them — they just stop riding every wake as schemas.
|
|
10
|
+
*/
|
|
11
|
+
import { EVERYDAY_SDK_TOOLS, annotationForSdkTool } from '@ziggs-ai/api-client';
|
|
12
|
+
import { defineTool, toolName } from '../tools/defineTool.js';
|
|
13
|
+
/**
|
|
14
|
+
* Platform tools written by hand, not as a shared capability. Their lane is
|
|
15
|
+
* what the dispatcher uses; a name here is also a platform name, so it leaves
|
|
16
|
+
* the model block unless it is in the everyday set.
|
|
17
|
+
*/
|
|
18
|
+
const HAND_LANE = {
|
|
19
|
+
context_snapshot: 'read-only',
|
|
20
|
+
chat_send: 'write',
|
|
21
|
+
wake_at: 'write',
|
|
22
|
+
agreement_propose: 'write',
|
|
23
|
+
agreement_subcontract: 'write',
|
|
24
|
+
agreement_respond: 'write',
|
|
25
|
+
agreement_counter: 'write',
|
|
26
|
+
agreement_get: 'read-only',
|
|
27
|
+
agreement_revoke: 'destructive',
|
|
28
|
+
agreement_fulfill: 'write',
|
|
29
|
+
task_set_result: 'write',
|
|
30
|
+
task_update_plan_step: 'write',
|
|
31
|
+
task_create: 'write',
|
|
32
|
+
task_replace_plan: 'write',
|
|
33
|
+
mcp_tools_list: 'read-only',
|
|
34
|
+
mcp_tool_call: 'write',
|
|
35
|
+
connection_list_grants: 'read-only',
|
|
36
|
+
};
|
|
37
|
+
const EVERYDAY = new Set(EVERYDAY_SDK_TOOLS);
|
|
38
|
+
const CATALOG_NAMES = ['tools', 'tool_read', 'tool_write'];
|
|
39
|
+
const CATALOG = new Set(CATALOG_NAMES);
|
|
40
|
+
export function hostedToolLane(name) {
|
|
41
|
+
const hand = HAND_LANE[name];
|
|
42
|
+
if (hand)
|
|
43
|
+
return hand;
|
|
44
|
+
const annotation = annotationForSdkTool(name);
|
|
45
|
+
if (annotation === 'read-only' || annotation === 'destructive')
|
|
46
|
+
return annotation;
|
|
47
|
+
return 'write';
|
|
48
|
+
}
|
|
49
|
+
function isPlatform(name) {
|
|
50
|
+
return name in HAND_LANE || annotationForSdkTool(name) !== undefined;
|
|
51
|
+
}
|
|
52
|
+
/** A Ziggs platform tool the model reaches through the catalog, not by schema. */
|
|
53
|
+
export function isHostedCatalogOnly(name) {
|
|
54
|
+
return isPlatform(name) && !EVERYDAY.has(name);
|
|
55
|
+
}
|
|
56
|
+
function oneLine(description, name) {
|
|
57
|
+
const text = String(description ?? name).replace(/\s+/g, ' ').trim();
|
|
58
|
+
const sentence = text.split(/(?<=\.)\s/)[0] ?? text;
|
|
59
|
+
return sentence.length > 180 ? `${sentence.slice(0, 177)}...` : sentence;
|
|
60
|
+
}
|
|
61
|
+
function callLine(name, lane, native) {
|
|
62
|
+
if (lane === 'destructive') {
|
|
63
|
+
return `call it by name only: ${name}; the dispatchers refuse it`;
|
|
64
|
+
}
|
|
65
|
+
const dispatcher = lane === 'read-only' ? 'tool_read' : 'tool_write';
|
|
66
|
+
if (native) {
|
|
67
|
+
return `call it by name: ${name}; ${dispatcher} { tool: "${name}", args } also works`;
|
|
68
|
+
}
|
|
69
|
+
return `call via ${dispatcher} { tool, args }`;
|
|
70
|
+
}
|
|
71
|
+
function rowFor(tool) {
|
|
72
|
+
const name = toolName(tool) ?? '';
|
|
73
|
+
const lane = hostedToolLane(name);
|
|
74
|
+
const native = !isHostedCatalogOnly(name);
|
|
75
|
+
return {
|
|
76
|
+
name,
|
|
77
|
+
line: oneLine(tool.schema.function['description'], name),
|
|
78
|
+
readOnly: lane === 'read-only',
|
|
79
|
+
native,
|
|
80
|
+
call: callLine(name, lane, native),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function refuseWrongLane(name, lane, via) {
|
|
84
|
+
if (lane === 'destructive') {
|
|
85
|
+
throw new Error(`${name} cannot be called through ${via}: it is irreversible, and it is loaded directly so the call names what it does. Call ${name} by name.`);
|
|
86
|
+
}
|
|
87
|
+
const readOnly = lane === 'read-only';
|
|
88
|
+
const askedRead = via === 'tool_read';
|
|
89
|
+
if (readOnly === askedRead)
|
|
90
|
+
return;
|
|
91
|
+
throw new Error(readOnly
|
|
92
|
+
? `${name} is read-only: call it with tool_read { tool, args }, not tool_write.`
|
|
93
|
+
: `${name} changes state: call it with tool_write { tool, args }, not tool_read.`);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The Claude bridge does not call a tool's handler. It emits `tool-call`, and
|
|
97
|
+
* the effect handler looks the name up on the ToolManager. A catalog call has
|
|
98
|
+
* to go back through that same effect so the target still gets the timeline,
|
|
99
|
+
* the write keys, and the wake scope. A direct executor is only for a caller
|
|
100
|
+
* that has no effect handler (a schema probe, a unit test).
|
|
101
|
+
*/
|
|
102
|
+
async function callCatalogTarget(name, payload, ctx, execute) {
|
|
103
|
+
const eff = ctx.eff;
|
|
104
|
+
const sessionId = typeof ctx.chatId === 'string' ? ctx.chatId
|
|
105
|
+
: typeof ctx.sessionId === 'string' ? ctx.sessionId
|
|
106
|
+
: undefined;
|
|
107
|
+
if (typeof eff === 'function' && sessionId) {
|
|
108
|
+
const result = await eff({
|
|
109
|
+
kind: 'tool-call',
|
|
110
|
+
sessionId,
|
|
111
|
+
name,
|
|
112
|
+
args: payload,
|
|
113
|
+
senderId: typeof ctx.senderId === 'string' ? ctx.senderId : undefined,
|
|
114
|
+
senderType: typeof ctx.senderType === 'string' ? ctx.senderType : undefined,
|
|
115
|
+
onBehalfOfAgreementId: typeof ctx.onBehalfOfAgreementId === 'string' ? ctx.onBehalfOfAgreementId : undefined,
|
|
116
|
+
serviceAgreementId: typeof ctx.serviceAgreementId === 'string' ? ctx.serviceAgreementId : undefined,
|
|
117
|
+
runId: typeof ctx.runId === 'string' ? ctx.runId : undefined,
|
|
118
|
+
writeKeys: ctx.writeKeys,
|
|
119
|
+
memory: ctx.memory,
|
|
120
|
+
});
|
|
121
|
+
const settled = result;
|
|
122
|
+
if (settled && settled.ok === false)
|
|
123
|
+
throw new Error(settled.error ?? `${name} failed`);
|
|
124
|
+
if (settled && 'ok' in settled)
|
|
125
|
+
return settled.result;
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
if (!execute)
|
|
129
|
+
throw new Error('hosted catalog has no executor');
|
|
130
|
+
return execute(name, payload, ctx);
|
|
131
|
+
}
|
|
132
|
+
function catalogTools(present, execute) {
|
|
133
|
+
const list = () => [...present.values()].map(rowFor).sort((a, b) => a.name.localeCompare(b.name));
|
|
134
|
+
const toolsTool = defineTool('tools', {
|
|
135
|
+
search: {
|
|
136
|
+
type: 'string',
|
|
137
|
+
description: 'Filter by name or the one-line description. Omit to list every tool.',
|
|
138
|
+
},
|
|
139
|
+
describe: {
|
|
140
|
+
type: 'array',
|
|
141
|
+
items: { type: 'string' },
|
|
142
|
+
description: 'Tool names whose full schema you want before calling them.',
|
|
143
|
+
},
|
|
144
|
+
}, async (args) => {
|
|
145
|
+
const describe = Array.isArray(args.describe) ? args.describe.map(String) : [];
|
|
146
|
+
if (describe.length > 0) {
|
|
147
|
+
return describe.map((name) => {
|
|
148
|
+
const tool = present.get(name);
|
|
149
|
+
if (!tool) {
|
|
150
|
+
return { name, error: `No such tool: ${name}. Call tools for the full list of names.` };
|
|
151
|
+
}
|
|
152
|
+
return { ...rowFor(tool), schema: tool.schema.function };
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
const q = typeof args.search === 'string' ? args.search.toLowerCase() : '';
|
|
156
|
+
return list().filter((row) => !q || row.name.includes(q) || row.line.toLowerCase().includes(q));
|
|
157
|
+
}, {
|
|
158
|
+
description: 'Every Ziggs tool that exists: name plus one line. A handful are already loaded by name; the rest are called through tool_read or tool_write. Pass describe with tool names to get their full schemas. Nothing is hidden.',
|
|
159
|
+
});
|
|
160
|
+
const dispatch = (via) => async (args, ctx) => {
|
|
161
|
+
const name = typeof args.tool === 'string' ? args.tool : '';
|
|
162
|
+
if (!name || !present.has(name)) {
|
|
163
|
+
throw new Error(`No such tool: ${name || '(missing)'}. Call tools for the full list of names.`);
|
|
164
|
+
}
|
|
165
|
+
refuseWrongLane(name, hostedToolLane(name), via);
|
|
166
|
+
const payload = args.args && typeof args.args === 'object' && !Array.isArray(args.args)
|
|
167
|
+
? args.args
|
|
168
|
+
: {};
|
|
169
|
+
return callCatalogTarget(name, payload, ctx, execute);
|
|
170
|
+
};
|
|
171
|
+
const toolRead = defineTool('tool_read', {
|
|
172
|
+
tool: { type: 'string', required: true, description: 'Read-only tool name from tools.' },
|
|
173
|
+
args: { type: 'object', description: 'Arguments for that tool, as its schema defines them.' },
|
|
174
|
+
}, dispatch('tool_read'), {
|
|
175
|
+
description: 'Call a read-only Ziggs tool by name. A tool that writes is refused here and pointed at tool_write. Look it up with tools describe=[name] first when you do not already know its parameters. The result is exactly what the tool itself returns.',
|
|
176
|
+
});
|
|
177
|
+
const toolWrite = defineTool('tool_write', {
|
|
178
|
+
tool: { type: 'string', required: true, description: 'Writing tool name from tools.' },
|
|
179
|
+
args: { type: 'object', description: 'Arguments for that tool, as its schema defines them.' },
|
|
180
|
+
}, dispatch('tool_write'), {
|
|
181
|
+
description: 'Call a Ziggs tool that creates or changes something, by name. Read-only tools are refused here and pointed at tool_read. Irreversible tools (agreement_revoke) are called by their own name only — this dispatcher refuses them. Look the tool up with tools describe=[name] first when you do not already know its parameters.',
|
|
182
|
+
});
|
|
183
|
+
return [toolsTool, toolRead, toolWrite];
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* The tool block the hosted model is shown.
|
|
187
|
+
*
|
|
188
|
+
* `execute` runs a catalog call through the ToolManager. Omit it when only
|
|
189
|
+
* the schemas are being priced — the dispatchers then refuse to run.
|
|
190
|
+
*/
|
|
191
|
+
export function hostedModelTools(all, execute) {
|
|
192
|
+
const present = new Map();
|
|
193
|
+
for (const tool of all) {
|
|
194
|
+
const name = toolName(tool);
|
|
195
|
+
if (!name || CATALOG.has(name))
|
|
196
|
+
continue;
|
|
197
|
+
present.set(name, tool);
|
|
198
|
+
}
|
|
199
|
+
const visible = [];
|
|
200
|
+
for (const [name, tool] of present) {
|
|
201
|
+
if (isHostedCatalogOnly(name))
|
|
202
|
+
continue;
|
|
203
|
+
visible.push(tool);
|
|
204
|
+
}
|
|
205
|
+
visible.push(...catalogTools(present, execute));
|
|
206
|
+
return visible;
|
|
207
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { RawEvent } from '../runtime/buildOutcome.js';
|
|
2
|
+
/**
|
|
3
|
+
* The wake gate: ask the backend whether chat messages need a
|
|
4
|
+
* model turn before the Claude brain starts one.
|
|
5
|
+
*
|
|
6
|
+
* The backend asks Jev (TypeSafe's System One model) one Choice — "asks this
|
|
7
|
+
* agent to act now" or "context to read later" — and answers `wake: false`
|
|
8
|
+
* only on a confident "context". The key lives there, not here: hosts run on
|
|
9
|
+
* customers' machines.
|
|
10
|
+
*/
|
|
11
|
+
export interface WakeGateMessage {
|
|
12
|
+
text: string;
|
|
13
|
+
senderId?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface WakeGateRequest {
|
|
16
|
+
messages: WakeGateMessage[];
|
|
17
|
+
agreementId?: string;
|
|
18
|
+
chatId?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface WakeGateAnswer {
|
|
21
|
+
wake: boolean;
|
|
22
|
+
/** `act` | `context` | `unsure` | `off`, as the backend decided. */
|
|
23
|
+
how?: string;
|
|
24
|
+
confidence?: number;
|
|
25
|
+
}
|
|
26
|
+
/** Null means "no answer": the caller wakes as it always has. */
|
|
27
|
+
export type AskWakeGate = (req: WakeGateRequest) => Promise<WakeGateAnswer | null>;
|
|
28
|
+
/**
|
|
29
|
+
* The messages this wake may ask about, or null when it may not ask at all.
|
|
30
|
+
*
|
|
31
|
+
* Only a wake made entirely of chat speech with text is asked about. Anything
|
|
32
|
+
* else in the batch — a task result, an agreement lifecycle event, a notice —
|
|
33
|
+
* wakes as today, decided here in code before Jev is involved: an assigned
|
|
34
|
+
* task, a control request (pause, stop) and a proposal naming this agent must
|
|
35
|
+
* never be skipped, and none of them is a `message`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function gateableMessages(event: RawEvent | undefined): WakeGateMessage[] | null;
|
|
38
|
+
/** The agreement the wake names, for the cost record. First one wins. */
|
|
39
|
+
export declare function wakeAgreementId(event: RawEvent | undefined): string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* The default gate: `POST /internal/wake-gate` with the agent's operator key.
|
|
42
|
+
* Any failure — network, timeout, a refusal, a body without `wake` — is null,
|
|
43
|
+
* so a backend that predates the route costs one 404 and changes nothing.
|
|
44
|
+
*/
|
|
45
|
+
export declare function backendWakeGate(creds: {
|
|
46
|
+
operatorKey: string;
|
|
47
|
+
agentId: string;
|
|
48
|
+
}): AskWakeGate;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { buildOperatorHeaders, getBackendUrl } from '@ziggs-ai/api-client';
|
|
2
|
+
import { getBatchEvents } from '../context/batch.js';
|
|
3
|
+
import { runtimeLog } from '../shared/runtimeLog.js';
|
|
4
|
+
/** Longer than Jev's own 4s budget on the server, shorter than a turn is worth waiting for. */
|
|
5
|
+
const TIMEOUT_MS = 6000;
|
|
6
|
+
/**
|
|
7
|
+
* The messages this wake may ask about, or null when it may not ask at all.
|
|
8
|
+
*
|
|
9
|
+
* Only a wake made entirely of chat speech with text is asked about. Anything
|
|
10
|
+
* else in the batch — a task result, an agreement lifecycle event, a notice —
|
|
11
|
+
* wakes as today, decided here in code before Jev is involved: an assigned
|
|
12
|
+
* task, a control request (pause, stop) and a proposal naming this agent must
|
|
13
|
+
* never be skipped, and none of them is a `message`.
|
|
14
|
+
*/
|
|
15
|
+
export function gateableMessages(event) {
|
|
16
|
+
const events = getBatchEvents(event);
|
|
17
|
+
if (events.length === 0)
|
|
18
|
+
return null;
|
|
19
|
+
const out = [];
|
|
20
|
+
for (const ev of events) {
|
|
21
|
+
if (!ev || ev.type !== 'message')
|
|
22
|
+
return null;
|
|
23
|
+
const text = typeof ev.text === 'string' ? ev.text.trim() : '';
|
|
24
|
+
if (!text)
|
|
25
|
+
return null;
|
|
26
|
+
out.push({
|
|
27
|
+
text,
|
|
28
|
+
...(typeof ev.senderId === 'string' && ev.senderId ? { senderId: ev.senderId } : {}),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
/** The agreement the wake names, for the cost record. First one wins. */
|
|
34
|
+
export function wakeAgreementId(event) {
|
|
35
|
+
for (const ev of getBatchEvents(event)) {
|
|
36
|
+
const id = ev?.agreementId;
|
|
37
|
+
if (typeof id === 'string' && id)
|
|
38
|
+
return id;
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The default gate: `POST /internal/wake-gate` with the agent's operator key.
|
|
44
|
+
* Any failure — network, timeout, a refusal, a body without `wake` — is null,
|
|
45
|
+
* so a backend that predates the route costs one 404 and changes nothing.
|
|
46
|
+
*/
|
|
47
|
+
export function backendWakeGate(creds) {
|
|
48
|
+
return async (req) => {
|
|
49
|
+
if (!creds.operatorKey)
|
|
50
|
+
return null;
|
|
51
|
+
try {
|
|
52
|
+
const res = await fetch(`${getBackendUrl()}/internal/wake-gate`, {
|
|
53
|
+
method: 'POST',
|
|
54
|
+
headers: {
|
|
55
|
+
...buildOperatorHeaders(creds.operatorKey, creds.agentId),
|
|
56
|
+
'Content-Type': 'application/json',
|
|
57
|
+
},
|
|
58
|
+
body: JSON.stringify(req),
|
|
59
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
60
|
+
});
|
|
61
|
+
if (!res.ok) {
|
|
62
|
+
await res.body?.cancel().catch(() => undefined);
|
|
63
|
+
runtimeLog.warn('wakeGate', `wake gate answered ${res.status} — waking as usual`);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const data = (await res.json().catch(() => null));
|
|
67
|
+
if (!data || typeof data.wake !== 'boolean')
|
|
68
|
+
return null;
|
|
69
|
+
return data;
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
runtimeLog.warn('wakeGate', `wake gate unreachable (${err?.name ?? 'error'}) — waking as usual`);
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -67,8 +67,10 @@ export { HistoryFormatter, historyFormatter, AgreementFormatter, agreementFormat
|
|
|
67
67
|
export { ProactiveTrigger } from './platform/proactive/ProactiveTrigger.js';
|
|
68
68
|
export { PollRegistry, declaredPolls, type PollBinding, type PollContext, type PollKind, type PollResult, } from './platform/polls/PollKind.js';
|
|
69
69
|
export { PollRunner, type PollRunnerOptions, type WakeTarget } from './platform/polls/PollRunner.js';
|
|
70
|
-
export { PROTOCOL_TOOLS, agreementProposeTool, agreementSubcontractTool, agreementRespondTool, agreementClaimTool, agreementCounterTool, agreementGetTool, agreementRevokeTool, agreementFulfillTool, taskCreateTool, taskSetResultTool, taskUpdatePlanStepTool, dispatchProtocolOp, PAYMENT_TOOLS, paymentBalanceTool, CONNECTION_TOOLS, connectionProxyTool, connectionListGrantsTool, requestConnectionTool, MCP_CONNECTION_TOOLS, mcpToolCallTool, mcpToolsListTool, DISCOVERY_TOOLS, agentSearchTool, agentGetTool, MARKETPLACE_TOOLS, marketplaceViewTool, CONTEXT_TOOLS, contextReadTool, contextRequestTool, contextDelegateTool, contextExpandReachTool, contextDiscoverGrantableTool, GRANTS_TOOLS, listGrantsTool, PLAN_TOOLS, taskReplacePlanTool, LINK_TOOLS, linkProposeTool, linkListTool, INTRODUCTION_TOOLS, introductionMintTool, introductionRedeemTool, introductionListTool, introductionRevokeTool, ARTIFACT_TOOLS, recordArtifactTool, CHAT_TOOLS, openConversationTool, } from './platform/tools/index.js';
|
|
70
|
+
export { PROTOCOL_TOOLS, agreementProposeTool, agreementSubcontractTool, agreementRespondTool, agreementClaimTool, agreementCounterTool, agreementGetTool, agreementRevokeTool, agreementFulfillTool, taskCreateTool, taskSetResultTool, taskUpdatePlanStepTool, dispatchProtocolOp, PAYMENT_TOOLS, paymentBalanceTool, CONNECTION_TOOLS, connectionProxyTool, connectionListGrantsTool, requestConnectionTool, MCP_CONNECTION_TOOLS, mcpToolCallTool, mcpToolsListTool, DISCOVERY_TOOLS, agentSearchTool, agentGetTool, MARKETPLACE_TOOLS, marketplaceViewTool, CONTEXT_TOOLS, contextReadTool, contextRequestTool, accessRequestTool, contextDelegateTool, contextExpandReachTool, contextDiscoverGrantableTool, GRANTS_TOOLS, listGrantsTool, PLAN_TOOLS, taskReplacePlanTool, LINK_TOOLS, linkProposeTool, linkListTool, INTRODUCTION_TOOLS, introductionMintTool, introductionRedeemTool, introductionListTool, introductionRevokeTool, ARTIFACT_TOOLS, recordArtifactTool, CHAT_TOOLS, openConversationTool, } from './platform/tools/index.js';
|
|
71
71
|
export { CLAUDE_SDK_TOOLS } from './brain/claudeSdkTools.js';
|
|
72
|
+
export { hostedModelTools, isHostedCatalogOnly, hostedToolLane } from './brain/hostedToolSurface.js';
|
|
73
|
+
export type { HostedToolExecute } from './brain/hostedToolSurface.js';
|
|
72
74
|
export { PROTOCOL_TOOL_NAMES, PROTOCOL_TOOL_TO_OPERATION, mapProtocolToolToOperation, isProtocolToolName } from './tasks/protocolRegistry.js';
|
|
73
75
|
export { InMemoryStore, FileMemoryStore } from './memory/MemoryStore.js';
|
|
74
76
|
export type { MemoryStore } from './memory/MemoryStore.js';
|
package/dist/index.js
CHANGED
|
@@ -79,10 +79,11 @@ export {
|
|
|
79
79
|
// Tier 1 — protocol grammar (framework-managed via taskTools).
|
|
80
80
|
PROTOCOL_TOOLS, agreementProposeTool, agreementSubcontractTool, agreementRespondTool, agreementClaimTool, agreementCounterTool, agreementGetTool, agreementRevokeTool, agreementFulfillTool, taskCreateTool, taskSetResultTool, taskUpdatePlanStepTool, dispatchProtocolOp,
|
|
81
81
|
// Tier 2 — opt-in capability bundles (spread into `tools:`).
|
|
82
|
-
PAYMENT_TOOLS, paymentBalanceTool, CONNECTION_TOOLS, connectionProxyTool, connectionListGrantsTool, requestConnectionTool, MCP_CONNECTION_TOOLS, mcpToolCallTool, mcpToolsListTool, DISCOVERY_TOOLS, agentSearchTool, agentGetTool, MARKETPLACE_TOOLS, marketplaceViewTool, CONTEXT_TOOLS, contextReadTool, contextRequestTool, contextDelegateTool, contextExpandReachTool, contextDiscoverGrantableTool, GRANTS_TOOLS, listGrantsTool, PLAN_TOOLS, taskReplacePlanTool, LINK_TOOLS, linkProposeTool, linkListTool, INTRODUCTION_TOOLS, introductionMintTool, introductionRedeemTool, introductionListTool, introductionRevokeTool, ARTIFACT_TOOLS, recordArtifactTool, CHAT_TOOLS, openConversationTool, } from './platform/tools/index.js';
|
|
82
|
+
PAYMENT_TOOLS, paymentBalanceTool, CONNECTION_TOOLS, connectionProxyTool, connectionListGrantsTool, requestConnectionTool, MCP_CONNECTION_TOOLS, mcpToolCallTool, mcpToolsListTool, DISCOVERY_TOOLS, agentSearchTool, agentGetTool, MARKETPLACE_TOOLS, marketplaceViewTool, CONTEXT_TOOLS, contextReadTool, contextRequestTool, accessRequestTool, contextDelegateTool, contextExpandReachTool, contextDiscoverGrantableTool, GRANTS_TOOLS, listGrantsTool, PLAN_TOOLS, taskReplacePlanTool, LINK_TOOLS, linkProposeTool, linkListTool, INTRODUCTION_TOOLS, introductionMintTool, introductionRedeemTool, introductionListTool, introductionRevokeTool, ARTIFACT_TOOLS, recordArtifactTool, CHAT_TOOLS, openConversationTool, } from './platform/tools/index.js';
|
|
83
83
|
// The always-on toolset for the hosted Claude cognition (parity guard
|
|
84
84
|
// reads this as part of the real SDK registry).
|
|
85
85
|
export { CLAUDE_SDK_TOOLS } from './brain/claudeSdkTools.js';
|
|
86
|
+
export { hostedModelTools, isHostedCatalogOnly, hostedToolLane } from './brain/hostedToolSurface.js';
|
|
86
87
|
export { PROTOCOL_TOOL_NAMES, PROTOCOL_TOOL_TO_OPERATION, mapProtocolToolToOperation, isProtocolToolName } from './tasks/protocolRegistry.js';
|
|
87
88
|
export { InMemoryStore, FileMemoryStore } from './memory/MemoryStore.js';
|
|
88
89
|
export { classifyIncomingEvent } from './context/classifyEnvelope.js';
|
|
@@ -5,6 +5,7 @@ export interface NormalizedEvent {
|
|
|
5
5
|
senderId?: string;
|
|
6
6
|
senderType?: string;
|
|
7
7
|
receiverId?: string;
|
|
8
|
+
assigneeId?: string;
|
|
8
9
|
/**
|
|
9
10
|
* Backend per-delivery id of the chat row this event came from. The one
|
|
10
11
|
* field of the event that is identical on live push and on catch-up
|
|
@@ -58,6 +59,7 @@ interface WireMetadata {
|
|
|
58
59
|
};
|
|
59
60
|
/** Inbox rewrite: assigned mail is this agent's even when the chat row names a human. */
|
|
60
61
|
receiverId?: string;
|
|
62
|
+
assigneeId?: string;
|
|
61
63
|
task?: WireTask;
|
|
62
64
|
service?: {
|
|
63
65
|
conversationAgreementId?: string;
|
|
@@ -113,6 +113,7 @@ export function normalizeIncomingEvent({ text, metadata = {} }) {
|
|
|
113
113
|
senderId: metadata.sender?.id,
|
|
114
114
|
senderType,
|
|
115
115
|
receiverId: receiverId || undefined,
|
|
116
|
+
assigneeId: typeof metadata.assigneeId === 'string' ? metadata.assigneeId : undefined,
|
|
116
117
|
messageId: typeof metadata.messageId === 'string' && metadata.messageId ? metadata.messageId : undefined,
|
|
117
118
|
timestamp: Date.now(),
|
|
118
119
|
...(entryType ? { entryType } : {}),
|
|
@@ -36,7 +36,7 @@ export interface ZiggsEffectDeps {
|
|
|
36
36
|
contextReadClient: ContextReadClient;
|
|
37
37
|
taskService: TaskService;
|
|
38
38
|
agreementService: AgreementService;
|
|
39
|
-
messageSender: (text: string, receiverId: string | undefined, sessionId: string, messageId?: string, conversationAgreementId?: string) => Promise<unknown>;
|
|
39
|
+
messageSender: (text: string, receiverId: string | undefined, sessionId: string, messageId?: string, conversationAgreementId?: string, underAgreementId?: string, taskId?: string) => Promise<unknown>;
|
|
40
40
|
/** Sends a streaming chunk to a client. Called per-token during stream-text effects. */
|
|
41
41
|
chunkSender?: (sessionId: string, receiverId: string, text: string, messageId: string) => void;
|
|
42
42
|
toolManager: ToolManager;
|
|
@@ -313,7 +313,7 @@ export function createZiggsEffectHandler(deps) {
|
|
|
313
313
|
});
|
|
314
314
|
}
|
|
315
315
|
case 'send-message': {
|
|
316
|
-
const sent = await deps.messageSender(effect.text, effect.receiverId, effect.sessionId, effect.messageId, effect.conversationAgreementId);
|
|
316
|
+
const sent = await deps.messageSender(effect.text, effect.receiverId, effect.sessionId, effect.messageId, effect.conversationAgreementId, effect.underAgreementId, effect.taskId);
|
|
317
317
|
outbox.track(effect.sessionId, { text: effect.text, receiverId: effect.receiverId });
|
|
318
318
|
// Carry the send's own report back to whoever asked for the send. A
|
|
319
319
|
// sender that cannot see where its message went cannot tell a delivered
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type InboxChatNews, type
|
|
1
|
+
import { type InboxChatNews, type InboxRequestRef, type InboxTaskRef, type Creds } from '@ziggs-ai/api-client';
|
|
2
2
|
import { SeenMessages } from './SeenMessages.js';
|
|
3
3
|
/**
|
|
4
4
|
* Per-agent inbox long-poll loop (delivery law, phase 4). This is the ONLY way
|
|
@@ -60,19 +60,13 @@ export interface InboxPassResult {
|
|
|
60
60
|
* the wake — it does not buy a canned answer.
|
|
61
61
|
*/
|
|
62
62
|
export declare function chatsInWakeOrder(chats: InboxChatNews[]): InboxChatNews[];
|
|
63
|
-
/**
|
|
64
|
-
* The one hire a chat's assigned deliveries name, or null when the room
|
|
65
|
-
* has none or more than one. Memory (and acting-for) treat "several
|
|
66
|
-
* customers in one room" as the shared section.
|
|
67
|
-
*/
|
|
68
|
-
export declare function soleHireAgreementIdForChat(deliveries: readonly Pick<InboxDeliveryRef, 'chatId' | 'agreementId' | 'assigneeId'>[], chatId: string, ownAgentId: string): string | null;
|
|
69
63
|
/**
|
|
70
64
|
* One long-poll pass: hold up to `waitSeconds` for new inbox content, then read
|
|
71
65
|
* the deltas, deliver them into the host, and ack. Returns what it delivered.
|
|
72
66
|
* Reused each iteration of {@link runInboxLoop}; also usable as a single catch-up
|
|
73
67
|
* read (`waitSeconds: 0`) at bootstrap.
|
|
74
68
|
*/
|
|
75
|
-
export declare function pollInboxOnce(deps: InboxLoopDeps, waitSeconds?: number,
|
|
69
|
+
export declare function pollInboxOnce(deps: InboxLoopDeps, waitSeconds?: number, _opts?: {
|
|
76
70
|
forceAck?: boolean;
|
|
77
71
|
}): Promise<InboxPassResult>;
|
|
78
72
|
export interface InboxLoopHandle {
|
|
@@ -94,11 +88,7 @@ export interface InboxLoopHandle {
|
|
|
94
88
|
*/
|
|
95
89
|
readonly lastAttemptAt: number | null;
|
|
96
90
|
}
|
|
97
|
-
/**
|
|
98
|
-
* How many consecutive passes have refused to advance the watermark.
|
|
99
|
-
* A capped envelope used to reset the counter (zero handover failures),
|
|
100
|
-
* so `forceAck` never fired on the one hold that lasts forever.
|
|
101
|
-
*/
|
|
91
|
+
/** Count held windows so retries can back off without discarding mail. */
|
|
102
92
|
export declare function heldPassAfter(prev: number, pass: Pick<InboxPassResult, 'acked' | 'failures' | 'truncated'>): number;
|
|
103
93
|
/**
|
|
104
94
|
* Run {@link pollInboxOnce} forever (until stopped). Each iteration long-polls
|