@ziggs-ai/agent-sdk 0.15.0 → 0.17.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.
Files changed (119) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +110 -88
  3. package/dist/{AgentHost.d.ts → Agent.d.ts} +66 -27
  4. package/dist/{AgentHost.js → Agent.js} +221 -119
  5. package/dist/adapters/AnthropicAdapter.d.ts +1 -1
  6. package/dist/adapters/AnthropicAdapter.js +1 -1
  7. package/dist/{agent/ClaudeSdkAgent.d.ts → brain/ClaudeBrain.d.ts} +23 -11
  8. package/dist/{agent/ClaudeSdkAgent.js → brain/ClaudeBrain.js} +145 -95
  9. package/dist/{agent/Agent.d.ts → brain/ZiggsBrain.d.ts} +23 -20
  10. package/dist/{agent/Agent.js → brain/ZiggsBrain.js} +12 -11
  11. package/dist/{agent → brain}/claudeCognition.d.ts +1 -1
  12. package/dist/{agent → brain}/claudeCognition.js +1 -1
  13. package/dist/{agent → brain}/claudeSdkProtocol.d.ts +2 -2
  14. package/dist/{agent → brain}/claudeSdkProtocol.js +2 -2
  15. package/dist/{agent → brain}/claudeSdkTools.d.ts +2 -1
  16. package/dist/{agent → brain}/claudeSdkTools.js +9 -65
  17. package/dist/{agent → brain}/hostedAgentConnection.d.ts +1 -1
  18. package/dist/{agent → brain}/hostedAgentConnection.js +3 -3
  19. package/dist/brain/index.d.ts +6 -6
  20. package/dist/brain/index.js +2 -2
  21. package/dist/brain/onBehalfAgreement.d.ts +51 -0
  22. package/dist/brain/onBehalfAgreement.js +99 -0
  23. package/dist/{agent → brain}/toolManagerToSdkMcp.js +10 -1
  24. package/dist/defineAgent.js +4 -4
  25. package/dist/formatters/HistoryFormatter.js +2 -1
  26. package/dist/index.d.ts +30 -31
  27. package/dist/index.js +24 -25
  28. package/dist/{adapters/McpAdapter.d.ts → mcp/createMcpAgent.d.ts} +16 -15
  29. package/dist/{adapters/McpAdapter.js → mcp/createMcpAgent.js} +54 -40
  30. package/dist/memory/MemoryStore.d.ts +18 -1
  31. package/dist/memory/MemoryStore.js +43 -0
  32. package/dist/{server → platform}/ConnectionPool.d.ts +9 -3
  33. package/dist/{server → platform}/ConnectionPool.js +16 -4
  34. package/dist/{server → platform}/EventQueue.d.ts +1 -1
  35. package/dist/{server → platform}/StateTimers.d.ts +1 -1
  36. package/dist/{server → platform}/StateTimers.js +1 -1
  37. package/dist/{server → platform}/ZiggsEffectHandler.d.ts +4 -4
  38. package/dist/{server → platform}/ZiggsEffectHandler.js +2 -2
  39. package/dist/{server → platform}/agreements/AgreementService.d.ts +10 -1
  40. package/dist/{server → platform}/agreements/AgreementService.js +9 -1
  41. package/dist/{server → platform}/inboxLoop.d.ts +34 -1
  42. package/dist/{server → platform}/inboxLoop.js +122 -14
  43. package/dist/{server → platform}/polls/PollKind.d.ts +4 -7
  44. package/dist/{server → platform}/polls/PollKind.js +3 -6
  45. package/dist/{server → platform}/polls/PollRunner.d.ts +5 -6
  46. package/dist/{server → platform}/polls/PollRunner.js +24 -12
  47. package/dist/platform/polls/declaredPollRunner.d.ts +4 -0
  48. package/dist/platform/polls/declaredPollRunner.js +29 -0
  49. package/dist/{server → platform}/tools/index.d.ts +1 -0
  50. package/dist/{server → platform}/tools/index.js +1 -0
  51. package/dist/{server → platform}/tools/tier1/protocolRunner.js +33 -27
  52. package/dist/{server → platform}/tools/tier1/protocolTools.js +2 -7
  53. package/dist/{server → platform}/tools/tier2/mcpConnectionTools.js +6 -3
  54. package/dist/platform/tools/tier2/taskTools.d.ts +3 -0
  55. package/dist/platform/tools/tier2/taskTools.js +6 -0
  56. package/dist/runtime/bootstrapCtx.d.ts +1 -1
  57. package/dist/runtime/bootstrapCtx.js +1 -1
  58. package/dist/runtime/buildOutcome.d.ts +0 -8
  59. package/dist/runtime/buildOutcome.js +20 -6
  60. package/dist/runtime/kickoff.js +1 -1
  61. package/dist/runtime/runTurn.d.ts +1 -1
  62. package/dist/runtime/runTurn.js +18 -18
  63. package/dist/runtime/validateWorkflow.js +1 -1
  64. package/dist/runtime/wakeOutcome.d.ts +27 -0
  65. package/dist/runtime/wakeOutcome.js +43 -0
  66. package/dist/skills/parseSkill.d.ts +7 -2
  67. package/dist/skills/parseSkill.js +22 -5
  68. package/dist/skills/skillReadReference.d.ts +6 -0
  69. package/dist/skills/skillReadReference.js +27 -0
  70. package/dist/tools/needs.js +2 -2
  71. package/dist/tools/recordReport.d.ts +5 -0
  72. package/dist/tools/recordReport.js +5 -0
  73. package/dist/tools/toolCreds.d.ts +1 -1
  74. package/dist/tools/toolCreds.js +1 -1
  75. package/dist/types.d.ts +3 -3
  76. package/package.json +2 -2
  77. package/dist/server/createHealthServer.d.ts +0 -7
  78. package/dist/server/createHealthServer.js +0 -75
  79. package/dist/server/runLauncher.d.ts +0 -22
  80. package/dist/server/runLauncher.js +0 -160
  81. /package/dist/{agent → brain}/toolManagerToSdkMcp.d.ts +0 -0
  82. /package/dist/{server → platform}/EventQueue.js +0 -0
  83. /package/dist/{server → platform}/OutboxBuffer.d.ts +0 -0
  84. /package/dist/{server → platform}/OutboxBuffer.js +0 -0
  85. /package/dist/{server → platform}/SeenMessages.d.ts +0 -0
  86. /package/dist/{server → platform}/SeenMessages.js +0 -0
  87. /package/dist/{server → platform}/proactive/ProactiveTrigger.d.ts +0 -0
  88. /package/dist/{server → platform}/proactive/ProactiveTrigger.js +0 -0
  89. /package/dist/{server → platform}/requestMatch.d.ts +0 -0
  90. /package/dist/{server → platform}/requestMatch.js +0 -0
  91. /package/dist/{server → platform}/tasks/TaskService.d.ts +0 -0
  92. /package/dist/{server → platform}/tasks/TaskService.js +0 -0
  93. /package/dist/{server → platform}/tasks/index.d.ts +0 -0
  94. /package/dist/{server → platform}/tasks/index.js +0 -0
  95. /package/dist/{server → platform}/telemetryIngest.d.ts +0 -0
  96. /package/dist/{server → platform}/telemetryIngest.js +0 -0
  97. /package/dist/{server → platform}/tools/tier1/protocolRunner.d.ts +0 -0
  98. /package/dist/{server → platform}/tools/tier1/protocolTools.d.ts +0 -0
  99. /package/dist/{server → platform}/tools/tier2/artifactTools.d.ts +0 -0
  100. /package/dist/{server → platform}/tools/tier2/artifactTools.js +0 -0
  101. /package/dist/{server → platform}/tools/tier2/chatTools.d.ts +0 -0
  102. /package/dist/{server → platform}/tools/tier2/chatTools.js +0 -0
  103. /package/dist/{server → platform}/tools/tier2/connectionTools.d.ts +0 -0
  104. /package/dist/{server → platform}/tools/tier2/connectionTools.js +0 -0
  105. /package/dist/{server → platform}/tools/tier2/contextTools.d.ts +0 -0
  106. /package/dist/{server → platform}/tools/tier2/contextTools.js +0 -0
  107. /package/dist/{server → platform}/tools/tier2/discoveryTools.d.ts +0 -0
  108. /package/dist/{server → platform}/tools/tier2/discoveryTools.js +0 -0
  109. /package/dist/{server → platform}/tools/tier2/grantsTools.d.ts +0 -0
  110. /package/dist/{server → platform}/tools/tier2/grantsTools.js +0 -0
  111. /package/dist/{server → platform}/tools/tier2/introductionTools.d.ts +0 -0
  112. /package/dist/{server → platform}/tools/tier2/introductionTools.js +0 -0
  113. /package/dist/{server → platform}/tools/tier2/linkTools.d.ts +0 -0
  114. /package/dist/{server → platform}/tools/tier2/linkTools.js +0 -0
  115. /package/dist/{server → platform}/tools/tier2/marketplaceTools.d.ts +0 -0
  116. /package/dist/{server → platform}/tools/tier2/marketplaceTools.js +0 -0
  117. /package/dist/{server → platform}/tools/tier2/mcpConnectionTools.d.ts +0 -0
  118. /package/dist/{server → platform}/tools/tier2/paymentTools.d.ts +0 -0
  119. /package/dist/{server → platform}/tools/tier2/paymentTools.js +0 -0
package/dist/types.d.ts CHANGED
@@ -502,7 +502,7 @@ export type Effect = {
502
502
  /**
503
503
  * Typed result map. With this shape, `await eff({ kind: 'read-context', .. })`
504
504
  * resolves to `ContextSnapshot`, not a union — the discriminant carries the
505
- * result type. Tests and Server impls implement this map exhaustively.
505
+ * result type. Tests and effect handlers implement this map exhaustively.
506
506
  */
507
507
  export interface EffectResultMap {
508
508
  'read-context': ContextSnapshot;
@@ -520,7 +520,7 @@ export interface EffectResultMap {
520
520
  };
521
521
  }
522
522
  export type EffectResult<K extends EffectKind> = EffectResultMap[K];
523
- /** The single side-channel between Agent and Server. */
523
+ /** The single side-channel between a Brain and its Agent. */
524
524
  export type EffectHandler = <K extends EffectKind>(effect: Extract<Effect, {
525
525
  kind: K;
526
526
  }>) => Promise<EffectResult<K>>;
@@ -563,7 +563,7 @@ export interface DefineAgentInput {
563
563
  [key: string]: unknown;
564
564
  }
565
565
  /**
566
- * Frozen output of defineAgent. Consumed directly by AgentHost / createAgent.
566
+ * Frozen output of defineAgent. Consumed directly by Agent / createAgent.
567
567
  * defineAgent injects ONE default: the agreement-kickoff state `kickingOff`
568
568
  * plus a last-position transition into it, added to states that don't already
569
569
  * handle a proposer-side proposal-resolved/approve outcome (runtime/kickoff.ts).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/agent-sdk",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "description": "Agent framework SDK for building autonomous agents on the Ziggs platform",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -26,7 +26,7 @@
26
26
  "@anthropic-ai/claude-agent-sdk": "^0.3.204",
27
27
  "@anthropic-ai/sdk": "^0.110.0",
28
28
  "@modelcontextprotocol/sdk": "^1.29.0",
29
- "@ziggs-ai/api-client": "0.14.0",
29
+ "@ziggs-ai/api-client": "0.16.0",
30
30
  "ajv": "^8.17.1",
31
31
  "dotenv": "^17.2.3",
32
32
  "openai": "^4.0.0",
@@ -1,7 +0,0 @@
1
- import { type Server } from 'http';
2
- import type { ConnectionPool } from './ConnectionPool.js';
3
- export declare function createHealthServer({ port, label, pool, }?: {
4
- port?: number;
5
- label?: string;
6
- pool?: ConnectionPool;
7
- }): Server;
@@ -1,75 +0,0 @@
1
- import { createServer } from 'http';
2
- import { runtimeLog } from '../shared/runtimeLog.js';
3
- function readJsonBody(req) {
4
- return new Promise((resolve, reject) => {
5
- const chunks = [];
6
- req.on('data', (c) => chunks.push(c));
7
- req.on('end', () => {
8
- try {
9
- const raw = Buffer.concat(chunks).toString('utf8');
10
- resolve(raw ? JSON.parse(raw) : {});
11
- }
12
- catch (err) {
13
- reject(err);
14
- }
15
- });
16
- req.on('error', reject);
17
- });
18
- }
19
- export function createHealthServer({ port = Number(process.env.PORT) || 8080, label = 'agents', pool, } = {}) {
20
- const server = createServer(async (req, res) => {
21
- const url = req.url ?? '/';
22
- const startMatch = url.match(/^\/fleet-start\/([^/?]+)/);
23
- if (req.method === 'POST' && startMatch && pool) {
24
- const agentId = decodeURIComponent(startMatch[1]);
25
- try {
26
- await pool.startAgent(agentId);
27
- res.writeHead(200, { 'Content-Type': 'application/json' });
28
- res.end(JSON.stringify({ ok: true, agentId, active: pool.listActive().includes(agentId) }));
29
- }
30
- catch (err) {
31
- res.writeHead(500, { 'Content-Type': 'application/json' });
32
- res.end(JSON.stringify({ ok: false, error: err.message }));
33
- }
34
- return;
35
- }
36
- if (req.method === 'POST' && url === '/fleet-deliver' && pool) {
37
- try {
38
- const body = await readJsonBody(req);
39
- const agentId = String(body.agentId ?? '');
40
- const chatId = String(body.chatId ?? '');
41
- const text = String(body.text ?? '');
42
- const senderId = String(body.senderId ?? '');
43
- if (!agentId || !chatId || !text || !senderId) {
44
- res.writeHead(400, { 'Content-Type': 'application/json' });
45
- res.end(JSON.stringify({ ok: false, error: 'agentId, chatId, text, senderId required' }));
46
- return;
47
- }
48
- const host = (await pool.startAgent(agentId));
49
- await host.handleMessage(text, {
50
- chatId,
51
- entryType: 'message',
52
- contentType: 'text',
53
- sender: { id: senderId, type: 'USER' },
54
- receiver: { id: agentId, type: 'AGENT' },
55
- });
56
- res.writeHead(200, { 'Content-Type': 'application/json' });
57
- res.end(JSON.stringify({ ok: true, agentId }));
58
- }
59
- catch (err) {
60
- res.writeHead(500, { 'Content-Type': 'application/json' });
61
- res.end(JSON.stringify({ ok: false, error: err.message }));
62
- }
63
- return;
64
- }
65
- if (url === '/health' || url === '/') {
66
- res.writeHead(200);
67
- res.end('ok');
68
- return;
69
- }
70
- res.writeHead(404);
71
- res.end();
72
- });
73
- server.listen(port, () => runtimeLog.info(label, `health server on port ${port}`));
74
- return server;
75
- }
@@ -1,22 +0,0 @@
1
- import { ConnectionPool } from './ConnectionPool.js';
2
- import { type AgentHostOptions } from '../AgentHost.js';
3
- type AgentConfig = AgentHostOptions & {
4
- ownAgentId?: string;
5
- options?: {
6
- ownAgentId?: string;
7
- name?: string;
8
- };
9
- };
10
- interface SingleOptions {
11
- operatorKey?: string;
12
- label?: string;
13
- port?: number | string;
14
- healthServer?: boolean;
15
- onShutdown?: () => Promise<void>;
16
- }
17
- interface FleetOptions extends SingleOptions {
18
- agentMeta?: Record<string, unknown>[];
19
- primary?: AgentConfig | ((pool: ConnectionPool) => AgentConfig);
20
- }
21
- export declare function runLauncher(configOrConfigs: AgentConfig | AgentConfig[], opts?: FleetOptions): Promise<unknown>;
22
- export {};
@@ -1,160 +0,0 @@
1
- import { ConnectionPool } from './ConnectionPool.js';
2
- import { AgentHost } from '../AgentHost.js';
3
- import { createHealthServer } from './createHealthServer.js';
4
- import { boundKeyFleetWarning } from '../shared/operatorKeyClaims.js';
5
- import { runtimeLog } from '../shared/runtimeLog.js';
6
- import { PollRegistry } from './polls/PollKind.js';
7
- import { PollRunner } from './polls/PollRunner.js';
8
- /**
9
- * How long a shutdown waits for in-flight turns after it has stopped taking new
10
- * work. An agent turn is an LLM call, so the old 30s was under the length of the
11
- * work it was meant to protect; the container's stop timeout is what has to be
12
- * larger still, or the drain is cut short by SIGKILL regardless (ECS
13
- * `stopTimeout`, 120s on the fleet task definitions).
14
- */
15
- const DRAIN_TIMEOUT_MS = Number(process.env.FLEET_DRAIN_TIMEOUT_MS) || 90_000;
16
- /**
17
- * Collect the poll kinds the agents themselves ship and start a runner for
18
- * whatever they declared. This lives in the launcher, not in a caller's
19
- * bootstrap file: an agent that declares `polls` and gets no runner sees no
20
- * error and simply never wakes, which is indistinguishable from a quiet source.
21
- * Every launcher path therefore executes polls, or refuses loudly.
22
- */
23
- function startDeclaredPolls(configs, pool, { operatorKey, label }) {
24
- const registry = new PollRegistry();
25
- for (const cfg of configs) {
26
- for (const kind of (cfg.pollKinds ?? [])) {
27
- // Two agents may legitimately share a source; first registration wins and
28
- // a duplicate id is not an error worth killing a fleet launch over.
29
- if (!registry.get(kind.id))
30
- registry.register(kind);
31
- }
32
- }
33
- const runner = new PollRunner({
34
- pool,
35
- registry,
36
- agents: configs,
37
- label: `${label}-polls`,
38
- ...(operatorKey ? { operatorKey } : {}),
39
- });
40
- if (runner.size === 0)
41
- return null;
42
- runner.start();
43
- return runner;
44
- }
45
- export async function runLauncher(configOrConfigs, opts = {}) {
46
- if (Array.isArray(configOrConfigs))
47
- return runFleet(configOrConfigs, opts);
48
- return runSingle(configOrConfigs, opts);
49
- }
50
- async function runSingle(config, { operatorKey, label = 'agent', port = process.env.PORT || 8080, healthServer = true, onShutdown } = {}) {
51
- const effectiveKey = operatorKey ?? process.env.ZIGGS_OPERATOR_KEY;
52
- const decorated = effectiveKey && !config.operatorKey ? { ...config, operatorKey: effectiveKey } : config;
53
- const agent = new AgentHost(decorated);
54
- try {
55
- await agent.connectAsync();
56
- runtimeLog.info(label, `"${agent['options'] ? (agent['options']?.agentId ?? agent['options']?.name) : 'agent'}" connected`);
57
- }
58
- catch (err) {
59
- runtimeLog.warn(label, `Agent failed to connect at startup: ${err.message} — will retry`);
60
- }
61
- const server = healthServer ? createHealthServer({ port: Number(port), label }) : null;
62
- // One agent, so the "pool" is just this host.
63
- const pollRunner = startDeclaredPolls([decorated], { sendTo: (_agentId, text, metadata) => agent.handleMessage(text, metadata ?? {}) }, { label, ...(effectiveKey ? { operatorKey: effectiveKey } : {}) });
64
- process.on('SIGTERM', async () => {
65
- runtimeLog.info(label, 'SIGTERM — shutting down');
66
- pollRunner?.stop();
67
- agent.disconnect();
68
- await agent.drain(DRAIN_TIMEOUT_MS);
69
- try {
70
- await onShutdown?.();
71
- }
72
- catch (err) {
73
- runtimeLog.warn(label, `onShutdown error: ${err.message}`);
74
- }
75
- server?.close();
76
- process.exit(0);
77
- });
78
- return { agent, healthServer: server ?? undefined };
79
- }
80
- async function runFleet(configs, { operatorKey, port = process.env.PORT || 8080, healthServer = true, label = 'launcher', agentMeta, primary: primaryConfig, onShutdown, } = {}) {
81
- const pool = new ConnectionPool();
82
- const effectiveKey = operatorKey ?? process.env.ZIGGS_OPERATOR_KEY;
83
- const decoratedConfigs = effectiveKey
84
- ? configs.map(c => (c.operatorKey ? c : { ...c, operatorKey: effectiveKey }))
85
- : configs;
86
- pool.register(decoratedConfigs, agentMeta);
87
- const server = healthServer ? createHealthServer({ port: Number(port), label, pool }) : null;
88
- let resolvedPrimaryConfig = typeof primaryConfig === 'function'
89
- ? primaryConfig(pool)
90
- : primaryConfig;
91
- if (resolvedPrimaryConfig && effectiveKey && !resolvedPrimaryConfig.operatorKey) {
92
- resolvedPrimaryConfig = { ...resolvedPrimaryConfig, operatorKey: effectiveKey };
93
- }
94
- const controlKey = effectiveKey ?? configs.find(c => c.operatorKey)?.operatorKey ?? resolvedPrimaryConfig?.operatorKey;
95
- if (controlKey) {
96
- // an agent-bound key half-works in a confusing way — say the big
97
- // thing once at startup instead of letting N-1 per-agent loops 403.
98
- const boundWarning = boundKeyFleetWarning(controlKey, pool.size);
99
- if (boundWarning)
100
- runtimeLog.warn(label, boundWarning);
101
- }
102
- let primary = null;
103
- if (resolvedPrimaryConfig) {
104
- primary = new AgentHost(resolvedPrimaryConfig);
105
- try {
106
- await primary.connectAsync();
107
- runtimeLog.info(label, `Primary agent "${resolvedPrimaryConfig.name || resolvedPrimaryConfig.ownAgentId || 'primary'}" connected`);
108
- }
109
- catch (err) {
110
- // Backend may not be ready yet — the inbox long-poll loop retries on
111
- // the next pass. Don't crash the process.
112
- runtimeLog.warn(label, `Primary agent "${resolvedPrimaryConfig.name || resolvedPrimaryConfig.ownAgentId || 'primary'}" failed to connect at startup: ${err.message} — will retry`);
113
- }
114
- }
115
- // Every registered agent connects. There is no roster to consult
116
- // and no reason to defer: an agent this launcher was handed is an agent it
117
- // hosts, and each host's own inbox long-poll is the only wake signal needed.
118
- await pool.connectAll();
119
- const connected = pool.listActive().length;
120
- if (connected < pool.size) {
121
- // Say it loudly and with the number. A launcher that silently hosts fewer
122
- // agents than it was given is exactly how three published, hireable agents
123
- // ran with no host and nothing noticed.
124
- runtimeLog.warn(label, `Only ${connected}/${pool.size} agent(s) connected — the rest are registered but unhosted`);
125
- }
126
- runtimeLog.info(label, `Ready — ${connected}/${pool.size} agent(s) connected`);
127
- const pollRunner = startDeclaredPolls(decoratedConfigs, pool, {
128
- label,
129
- ...(effectiveKey ? { operatorKey: effectiveKey } : {}),
130
- });
131
- process.on('SIGTERM', async () => {
132
- runtimeLog.info(label, 'SIGTERM — shutting down');
133
- // Stop taking new work everywhere first, then wait for what is running.
134
- //
135
- // This used to disconnect and drain only `primary` — which `run.ts` never
136
- // sets, so in the deployed fleet the drain was a no-op on null and the
137
- // process exited straight through `disconnectAll`, killing every in-flight
138
- // turn. A buyer whose request landed mid-rollout got a host that stopped
139
- // mid-sentence and never reported.
140
- //
141
- // Draining before stopping intake is the other half of the same bug: the
142
- // wait is exactly the window in which a host on its way out keeps accepting
143
- // deliveries the incoming host is also being handed.
144
- pollRunner?.stop();
145
- primary?.disconnect?.();
146
- await Promise.all([
147
- pool.shutdown(DRAIN_TIMEOUT_MS),
148
- primary?.drain?.(DRAIN_TIMEOUT_MS) ?? Promise.resolve(),
149
- ]);
150
- try {
151
- await onShutdown?.();
152
- }
153
- catch (err) {
154
- runtimeLog.warn(label, `onShutdown error: ${err.message}`);
155
- }
156
- server?.close();
157
- process.exit(0);
158
- });
159
- return { pool, primary, healthServer: server ?? undefined };
160
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes