@ziggs-ai/agent-sdk 0.33.1 → 0.34.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 +8 -1
- package/README.md +7 -3
- package/dist/Agent.d.ts +10 -2
- package/dist/Agent.js +15 -36
- package/dist/platform/ConnectionPool.d.ts +8 -6
- package/dist/platform/ConnectionPool.js +18 -32
- package/dist/platform/inboxLoop.d.ts +12 -2
- package/dist/platform/inboxLoop.js +26 -5
- package/dist/pricing/fleetEvalFree.js +0 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -15,7 +15,14 @@
|
|
|
15
15
|
### Fixed
|
|
16
16
|
|
|
17
17
|
- Hosted Claude agents can discover and invoke the access explanation tool named by their recovery instructions.
|
|
18
|
-
-
|
|
18
|
+
- `disconnect(timeoutMs)` is bounded and resolves once the inbox host lease is
|
|
19
|
+
released: an idle long-poll is cancelled at once, a pass in flight gets up to
|
|
20
|
+
the bound to acknowledge what it finished, and a pass that outlasts the bound
|
|
21
|
+
loses the lease anyway so the next host is handed what was not acknowledged.
|
|
22
|
+
`drain()` waits on the event queue only. A pool no longer refuses to start a
|
|
23
|
+
replacement host with "retry after its current delivery completes": the
|
|
24
|
+
replacement starts once the previous host's lease is released, and
|
|
25
|
+
`shutdown(timeoutMs)` spends one budget across stopping intake and draining.
|
|
19
26
|
|
|
20
27
|
- `agreement_subcontract` sends the terms the model stated. With no end date
|
|
21
28
|
and no task count the server writes a standing sub-agreement, as it does
|
package/README.md
CHANGED
|
@@ -47,14 +47,18 @@ const agent = createAgent({
|
|
|
47
47
|
await agent.connectAsync();
|
|
48
48
|
|
|
49
49
|
// When your process shuts down:
|
|
50
|
-
// agent.disconnect();
|
|
50
|
+
// await agent.disconnect();
|
|
51
51
|
// await agent.drain();
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
The identity must already exist on Ziggs and the operator key must authorize it.
|
|
55
55
|
`connectAsync()` starts outbound delivery; network failures retry inside the
|
|
56
|
-
inbox loop. It is safe to call again while connected. `disconnect()`
|
|
57
|
-
polling and clears state timers
|
|
56
|
+
inbox loop. It is safe to call again while connected. `disconnect(timeoutMs)`
|
|
57
|
+
stops new polling and clears state timers, lets the inbox pass in flight
|
|
58
|
+
acknowledge what it finished, then releases the inbox host lease; a pass that
|
|
59
|
+
outlasts the bound (30 s by default) loses the lease anyway, and the next host
|
|
60
|
+
is handed what was not acknowledged. `drain()` waits for queued and active
|
|
61
|
+
wakes.
|
|
58
62
|
|
|
59
63
|
The Claude brain’s default wake timeout is five minutes; the Ziggs brain’s is
|
|
60
64
|
two minutes. `tickTimeoutMs` overrides either. Legacy `cognition: 'fsm' |
|
package/dist/Agent.d.ts
CHANGED
|
@@ -256,7 +256,6 @@ export declare class Agent {
|
|
|
256
256
|
private stateTimers;
|
|
257
257
|
/** The per-agent inbox long-poll loop — this agent's sole wake source. */
|
|
258
258
|
private inboxLoop;
|
|
259
|
-
private inboxStopping;
|
|
260
259
|
private inboxLoopEnabled;
|
|
261
260
|
private started;
|
|
262
261
|
private pollRunner;
|
|
@@ -419,7 +418,16 @@ export declare class Agent {
|
|
|
419
418
|
wakeTaskAssignment(taskId: string, options?: {
|
|
420
419
|
fromInbox?: boolean;
|
|
421
420
|
}): Promise<void>;
|
|
422
|
-
|
|
421
|
+
/**
|
|
422
|
+
* Stop taking work. Timers and polls stop at once; the inbox loop cancels
|
|
423
|
+
* an idle long-poll and lets a pass already handed to this host finish and
|
|
424
|
+
* acknowledge, then releases the host lease — within `timeoutMs`. A pass
|
|
425
|
+
* that outlasts the bound does not keep the lease: it is released anyway
|
|
426
|
+
* and the next host is handed what was not acknowledged. Resolves once the
|
|
427
|
+
* lease is released either way. In-flight wakes keep running in the event
|
|
428
|
+
* queue; `drain()` is what waits for those.
|
|
429
|
+
*/
|
|
430
|
+
disconnect(timeoutMs?: number): Promise<void>;
|
|
423
431
|
/**
|
|
424
432
|
* Waits for in-flight ticks to finish. Call before process.exit() on SIGTERM.
|
|
425
433
|
* A timeout is returned, not thrown — the caller names it (lab verdict, fleet
|
package/dist/Agent.js
CHANGED
|
@@ -33,7 +33,7 @@ import { ArtifactsClient, ConnectionsClient, ContextReadClient, TelemetryClient,
|
|
|
33
33
|
import { normalizeNeeds, unmetNeeds, unmetNeedsMessage, } from './tools/needs.js';
|
|
34
34
|
import { TaskService } from './platform/tasks/TaskService.js';
|
|
35
35
|
import { AgreementService } from './platform/agreements/AgreementService.js';
|
|
36
|
-
import { runInboxLoop } from './platform/inboxLoop.js';
|
|
36
|
+
import { INBOX_STOP_TIMEOUT_MS, runInboxLoop } from './platform/inboxLoop.js';
|
|
37
37
|
import { requestExactMatch } from './platform/requestMatch.js';
|
|
38
38
|
import { SeenMessages } from './platform/SeenMessages.js';
|
|
39
39
|
import { runtimeLog } from './shared/runtimeLog.js';
|
|
@@ -219,7 +219,6 @@ export class Agent {
|
|
|
219
219
|
stateTimers;
|
|
220
220
|
/** The per-agent inbox long-poll loop — this agent's sole wake source. */
|
|
221
221
|
inboxLoop = null;
|
|
222
|
-
inboxStopping = null;
|
|
223
222
|
inboxLoopEnabled;
|
|
224
223
|
started = false;
|
|
225
224
|
pollRunner;
|
|
@@ -1446,16 +1445,6 @@ export class Agent {
|
|
|
1446
1445
|
return this.options.agentId || null;
|
|
1447
1446
|
}
|
|
1448
1447
|
async connectAsync(_timeout) {
|
|
1449
|
-
if (this.started)
|
|
1450
|
-
return this;
|
|
1451
|
-
// Reconnecting must not race the previous loop's final lease release.
|
|
1452
|
-
if (this.inboxStopping) {
|
|
1453
|
-
await this.inboxStopping;
|
|
1454
|
-
this.inboxStopping = null;
|
|
1455
|
-
}
|
|
1456
|
-
// Another reconnect may have resumed from the same retirement promise.
|
|
1457
|
-
// Everything below starts synchronously, so rechecking prevents a second
|
|
1458
|
-
// inbox loop from replacing the handle of the one that just started.
|
|
1459
1448
|
if (this.started)
|
|
1460
1449
|
return this;
|
|
1461
1450
|
// Start the per-agent inbox long-poll loop — the agent's sole wake source.
|
|
@@ -1556,40 +1545,30 @@ export class Agent {
|
|
|
1556
1545
|
chatId: sessionId,
|
|
1557
1546
|
}, laneKey);
|
|
1558
1547
|
}
|
|
1559
|
-
|
|
1548
|
+
/**
|
|
1549
|
+
* Stop taking work. Timers and polls stop at once; the inbox loop cancels
|
|
1550
|
+
* an idle long-poll and lets a pass already handed to this host finish and
|
|
1551
|
+
* acknowledge, then releases the host lease — within `timeoutMs`. A pass
|
|
1552
|
+
* that outlasts the bound does not keep the lease: it is released anyway
|
|
1553
|
+
* and the next host is handed what was not acknowledged. Resolves once the
|
|
1554
|
+
* lease is released either way. In-flight wakes keep running in the event
|
|
1555
|
+
* queue; `drain()` is what waits for those.
|
|
1556
|
+
*/
|
|
1557
|
+
async disconnect(timeoutMs = INBOX_STOP_TIMEOUT_MS) {
|
|
1560
1558
|
this.started = false;
|
|
1561
1559
|
this.pollRunner?.stop();
|
|
1562
1560
|
this.stateTimers.clearAll();
|
|
1563
|
-
|
|
1564
|
-
this.inboxStopping = this.inboxLoop.stop();
|
|
1561
|
+
const loop = this.inboxLoop;
|
|
1565
1562
|
this.inboxLoop = null;
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
return Promise.resolve();
|
|
1563
|
+
if (loop)
|
|
1564
|
+
await loop.stop(timeoutMs);
|
|
1569
1565
|
}
|
|
1570
1566
|
/**
|
|
1571
1567
|
* Waits for in-flight ticks to finish. Call before process.exit() on SIGTERM.
|
|
1572
1568
|
* A timeout is returned, not thrown — the caller names it (lab verdict, fleet
|
|
1573
1569
|
* shutdown log) instead of EventQueue printing a stray warning.
|
|
1574
1570
|
*/
|
|
1575
|
-
|
|
1576
|
-
const deadline = Date.now() + Math.max(0, timeoutMs);
|
|
1577
|
-
if (this.inboxStopping) {
|
|
1578
|
-
let timer;
|
|
1579
|
-
const stopped = await Promise.race([
|
|
1580
|
-
this.inboxStopping.then(() => true),
|
|
1581
|
-
new Promise((resolve) => { timer = setTimeout(() => resolve(false), Math.max(0, timeoutMs)); }),
|
|
1582
|
-
]).finally(() => clearTimeout(timer));
|
|
1583
|
-
if (!stopped) {
|
|
1584
|
-
const queue = await this.eventQueue.waitForIdle(0);
|
|
1585
|
-
return { ...queue, idle: false, timedOut: true, timeoutMs,
|
|
1586
|
-
busyLanes: [...queue.busyLanes, { laneKey: 'inbox-shutdown', queued: 0, processing: true }] };
|
|
1587
|
-
}
|
|
1588
|
-
this.inboxStopping = null;
|
|
1589
|
-
}
|
|
1590
|
-
const result = await this.eventQueue.waitForIdle(Math.max(0, deadline - Date.now()));
|
|
1591
|
-
return { ...result, timeoutMs };
|
|
1592
|
-
}
|
|
1571
|
+
drain(timeoutMs = 30_000) { return this.eventQueue.waitForIdle(timeoutMs); }
|
|
1593
1572
|
registerTool(tool) { return this.toolManager.register(tool); }
|
|
1594
1573
|
isConnected() { return this.started && (!this.inboxLoopEnabled || (this.inboxLoop?.running ?? false)); }
|
|
1595
1574
|
/**
|
|
@@ -17,8 +17,7 @@ export declare class ConnectionPool {
|
|
|
17
17
|
private readonly manager;
|
|
18
18
|
private readonly configs;
|
|
19
19
|
private readonly hosts;
|
|
20
|
-
private
|
|
21
|
-
private shutdownGeneration;
|
|
20
|
+
private stopTimeoutMs;
|
|
22
21
|
private readonly responseListeners;
|
|
23
22
|
/**
|
|
24
23
|
* Register N agent configs. Nothing connects until `connectAll()`. A config
|
|
@@ -47,12 +46,15 @@ export declare class ConnectionPool {
|
|
|
47
46
|
* is already live and polling the same inboxes, so that window is where one
|
|
48
47
|
* delivery gets handled twice: two hosts, one request, two answers.
|
|
49
48
|
*
|
|
50
|
-
* `disconnect()`
|
|
51
|
-
*
|
|
52
|
-
*
|
|
49
|
+
* `disconnect()` stops the inbox loop and timers, lets the pass in flight
|
|
50
|
+
* acknowledge what it finished, and releases the host lease — all inside
|
|
51
|
+
* the bound; in-flight ticks live in each host's event queue, which is what
|
|
52
|
+
* `drain()` waits on. One budget covers both, so a fleet on a 120s stop
|
|
53
|
+
* clock is not asked to wait twice.
|
|
53
54
|
*
|
|
54
55
|
* A host that cannot finish inside `timeoutMs` is left behind rather than
|
|
55
|
-
* holding up the rest — the caller is on a shutdown clock of its own.
|
|
56
|
+
* holding up the rest — the caller is on a shutdown clock of its own. Its
|
|
57
|
+
* lease is released regardless, so the replacement can host at once.
|
|
56
58
|
*/
|
|
57
59
|
shutdown(timeoutMs?: number): Promise<void>;
|
|
58
60
|
/**
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { ConnectionManager } from '@ziggs-ai/api-client';
|
|
17
17
|
import { createAgent } from '../Agent.js';
|
|
18
|
+
import { INBOX_STOP_TIMEOUT_MS } from './inboxLoop.js';
|
|
18
19
|
import { runtimeLog } from '../shared/runtimeLog.js';
|
|
19
20
|
export class ConnectionPool {
|
|
20
21
|
manager = new ConnectionManager();
|
|
@@ -23,12 +24,9 @@ export class ConnectionPool {
|
|
|
23
24
|
// open/close callbacks and does not expose them, and re-reading one through
|
|
24
25
|
// `startAgent` after a stop would reconnect the agent we are shutting down.
|
|
25
26
|
hosts = new Map();
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
// Invalidate replacements already waiting on a retiring host when shutdown
|
|
30
|
-
// starts. They are not in the manager's active set yet, so stopAll misses them.
|
|
31
|
-
shutdownGeneration = 0;
|
|
27
|
+
// How long a stopping host may spend acknowledging its pass in flight before
|
|
28
|
+
// its lease is released anyway. `shutdown()` sets it to the caller's budget.
|
|
29
|
+
stopTimeoutMs = INBOX_STOP_TIMEOUT_MS;
|
|
32
30
|
// Listeners enqueued by requestFrom — drained on outbound send-message effects.
|
|
33
31
|
responseListeners = new Map();
|
|
34
32
|
/**
|
|
@@ -51,17 +49,6 @@ export class ConnectionPool {
|
|
|
51
49
|
}
|
|
52
50
|
this.configs.set(agentId, config);
|
|
53
51
|
this.manager.register(agentId, async () => {
|
|
54
|
-
const generation = this.shutdownGeneration;
|
|
55
|
-
const retiring = this.retiringHosts.get(agentId);
|
|
56
|
-
if (retiring) {
|
|
57
|
-
const result = await retiring.drain();
|
|
58
|
-
if (generation !== this.shutdownGeneration) {
|
|
59
|
-
throw new Error(`Pool shut down while agent "${agentId}" was waiting for its previous host`);
|
|
60
|
-
}
|
|
61
|
-
if (!result.idle)
|
|
62
|
-
throw new Error(`Agent "${agentId}" is still finishing shutdown; retry after its current delivery completes`);
|
|
63
|
-
this.retiringHosts.delete(agentId);
|
|
64
|
-
}
|
|
65
52
|
const cfg = this.configs.get(agentId);
|
|
66
53
|
const originalTap = cfg.effectTap;
|
|
67
54
|
const pool = this;
|
|
@@ -81,8 +68,9 @@ export class ConnectionPool {
|
|
|
81
68
|
runtimeLog.debug('ConnectionPool', `connected "${agentId}"`);
|
|
82
69
|
return host;
|
|
83
70
|
}, async (host) => {
|
|
84
|
-
|
|
85
|
-
|
|
71
|
+
// Resolves once the host's lease is released, so a replacement
|
|
72
|
+
// started next cannot share the inbox with a host still acking.
|
|
73
|
+
await host.disconnect(this.stopTimeoutMs);
|
|
86
74
|
this.hosts.delete(agentId);
|
|
87
75
|
runtimeLog.debug('ConnectionPool', `disconnected "${agentId}"`);
|
|
88
76
|
}, metaByAgentId.get(agentId));
|
|
@@ -126,26 +114,24 @@ export class ConnectionPool {
|
|
|
126
114
|
* is already live and polling the same inboxes, so that window is where one
|
|
127
115
|
* delivery gets handled twice: two hosts, one request, two answers.
|
|
128
116
|
*
|
|
129
|
-
* `disconnect()`
|
|
130
|
-
*
|
|
131
|
-
*
|
|
117
|
+
* `disconnect()` stops the inbox loop and timers, lets the pass in flight
|
|
118
|
+
* acknowledge what it finished, and releases the host lease — all inside
|
|
119
|
+
* the bound; in-flight ticks live in each host's event queue, which is what
|
|
120
|
+
* `drain()` waits on. One budget covers both, so a fleet on a 120s stop
|
|
121
|
+
* clock is not asked to wait twice.
|
|
132
122
|
*
|
|
133
123
|
* A host that cannot finish inside `timeoutMs` is left behind rather than
|
|
134
|
-
* holding up the rest — the caller is on a shutdown clock of its own.
|
|
124
|
+
* holding up the rest — the caller is on a shutdown clock of its own. Its
|
|
125
|
+
* lease is released regardless, so the replacement can host at once.
|
|
135
126
|
*/
|
|
136
127
|
async shutdown(timeoutMs = 30_000) {
|
|
137
|
-
|
|
138
|
-
const hosts = [...
|
|
128
|
+
const deadline = Date.now() + timeoutMs;
|
|
129
|
+
const hosts = [...this.hosts.values()];
|
|
130
|
+
this.stopTimeoutMs = timeoutMs;
|
|
139
131
|
await this.manager.stopAll();
|
|
140
132
|
await Promise.all(hosts.map(async (host) => {
|
|
141
133
|
try {
|
|
142
|
-
const result = await host.drain(
|
|
143
|
-
if (result?.idle) {
|
|
144
|
-
for (const [id, retiring] of this.retiringHosts) {
|
|
145
|
-
if (retiring === host)
|
|
146
|
-
this.retiringHosts.delete(id);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
134
|
+
const result = await host.drain(Math.max(0, deadline - Date.now()));
|
|
149
135
|
if (result?.timedOut) {
|
|
150
136
|
runtimeLog.warn('ConnectionPool', `drain timed out after ${timeoutMs}ms: ${result.queuedEvents} event(s) queued, ${result.busyLanes.length} busy lane(s)`);
|
|
151
137
|
}
|
|
@@ -71,8 +71,16 @@ export declare function pollInboxOnce(deps: InboxLoopDeps, waitSeconds?: number,
|
|
|
71
71
|
signal?: AbortSignal;
|
|
72
72
|
}): Promise<InboxPassResult>;
|
|
73
73
|
export interface InboxLoopHandle {
|
|
74
|
-
/**
|
|
75
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Stop reading. An idle long-poll is cancelled at once; a pass already
|
|
76
|
+
* handed to the host runs on so it can acknowledge what it finished, and
|
|
77
|
+
* the host lease is released after that. A pass still running when
|
|
78
|
+
* `timeoutMs` is up does not hold the lease: it is released anyway, and the
|
|
79
|
+
* next host is handed whatever was not acknowledged. Resolves `true` when
|
|
80
|
+
* the pass finished inside the bound, `false` when the lease was released
|
|
81
|
+
* out from under it.
|
|
82
|
+
*/
|
|
83
|
+
stop(timeoutMs?: number): Promise<boolean>;
|
|
76
84
|
/** True while the loop is running. */
|
|
77
85
|
readonly running: boolean;
|
|
78
86
|
/**
|
|
@@ -91,6 +99,8 @@ export interface InboxLoopHandle {
|
|
|
91
99
|
}
|
|
92
100
|
/** Count held windows so retries can back off without discarding mail. */
|
|
93
101
|
export declare function heldPassAfter(prev: number, pass: Pick<InboxPassResult, 'acked' | 'failures' | 'truncated'>): number;
|
|
102
|
+
/** How long `stop()` waits for a pass in flight before releasing the lease anyway. */
|
|
103
|
+
export declare const INBOX_STOP_TIMEOUT_MS = 30000;
|
|
94
104
|
/**
|
|
95
105
|
* Run {@link pollInboxOnce} forever (until stopped). Each iteration long-polls
|
|
96
106
|
* for `waitSeconds`; a passing envelope returns instantly, an empty one holds.
|
|
@@ -390,6 +390,18 @@ function sleep(ms, signal) {
|
|
|
390
390
|
signal?.addEventListener('abort', finish, { once: true });
|
|
391
391
|
});
|
|
392
392
|
}
|
|
393
|
+
/** How long `stop()` waits for a pass in flight before releasing the lease anyway. */
|
|
394
|
+
export const INBOX_STOP_TIMEOUT_MS = 30_000;
|
|
395
|
+
/** Resolves `true` when `promise` settles within `ms`, `false` otherwise. The timer never outlives the answer. */
|
|
396
|
+
function withinMs(promise, ms) {
|
|
397
|
+
return new Promise((resolve) => {
|
|
398
|
+
const timer = setTimeout(() => resolve(false), Math.max(0, ms));
|
|
399
|
+
promise.then(() => true, () => true).then((settled) => {
|
|
400
|
+
clearTimeout(timer);
|
|
401
|
+
resolve(settled);
|
|
402
|
+
});
|
|
403
|
+
});
|
|
404
|
+
}
|
|
393
405
|
/**
|
|
394
406
|
* Run {@link pollInboxOnce} forever (until stopped). Each iteration long-polls
|
|
395
407
|
* for `waitSeconds`; a passing envelope returns instantly, an empty one holds.
|
|
@@ -412,6 +424,10 @@ export function runInboxLoop(deps, opts = {}) {
|
|
|
412
424
|
let lastAttemptAt = null;
|
|
413
425
|
let first = true;
|
|
414
426
|
const shutdown = new AbortController();
|
|
427
|
+
// One DELETE, whichever gets there first: the loop's own exit, or a stop
|
|
428
|
+
// that ran out of patience with the pass in flight.
|
|
429
|
+
let released = null;
|
|
430
|
+
const releaseOnce = () => (released ??= releaseInboxHostBestEffort(deps));
|
|
415
431
|
const main = (async () => {
|
|
416
432
|
while (running) {
|
|
417
433
|
try {
|
|
@@ -447,7 +463,7 @@ export function runInboxLoop(deps, opts = {}) {
|
|
|
447
463
|
}
|
|
448
464
|
}
|
|
449
465
|
})();
|
|
450
|
-
const done = main.finally(
|
|
466
|
+
const done = main.finally(releaseOnce);
|
|
451
467
|
return {
|
|
452
468
|
get running() {
|
|
453
469
|
return running;
|
|
@@ -458,12 +474,17 @@ export function runInboxLoop(deps, opts = {}) {
|
|
|
458
474
|
get lastAttemptAt() {
|
|
459
475
|
return lastAttemptAt;
|
|
460
476
|
},
|
|
461
|
-
async stop() {
|
|
477
|
+
async stop(timeoutMs = INBOX_STOP_TIMEOUT_MS) {
|
|
462
478
|
running = false;
|
|
463
|
-
// Cancel an idle long-poll
|
|
464
|
-
//
|
|
479
|
+
// Cancel an idle long-poll; a pass already handed to the host keeps
|
|
480
|
+
// going so it can acknowledge what it finished before the lease goes.
|
|
465
481
|
shutdown.abort();
|
|
466
|
-
await done;
|
|
482
|
+
const finished = await withinMs(done, timeoutMs);
|
|
483
|
+
if (!finished) {
|
|
484
|
+
warn(label, `inbox pass still running after ${timeoutMs}ms — releasing the host lease now; what it has not acknowledged is redelivered to the next host`);
|
|
485
|
+
await releaseOnce();
|
|
486
|
+
}
|
|
487
|
+
return finished;
|
|
467
488
|
},
|
|
468
489
|
};
|
|
469
490
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ziggs-ai/agent-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.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.284",
|
|
27
27
|
"@anthropic-ai/sdk": "^0.110.0",
|
|
28
28
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
29
|
-
"@ziggs-ai/api-client": "0.
|
|
29
|
+
"@ziggs-ai/api-client": "0.33.0",
|
|
30
30
|
"ajv": "^8.17.1",
|
|
31
31
|
"dotenv": "^17.2.3",
|
|
32
32
|
"openai": "^4.0.0",
|