@ziggs-ai/agent-sdk 0.1.9 → 0.1.11

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.
@@ -32,6 +32,7 @@ interface ProtocolPayload {
32
32
  parentAgreementId?: string;
33
33
  parentTaskId?: string;
34
34
  taskId?: string;
35
+ stepId?: string;
35
36
  assigneeId?: string;
36
37
  status?: string;
37
38
  result?: unknown;
@@ -97,12 +98,20 @@ export async function dispatchProtocolOp(
97
98
  planReviewTiming: payload.planReviewTiming,
98
99
  requireMidWorkPlanAck: payload.requireMidWorkPlanAck,
99
100
  assigneeId: payload.assigneeId,
101
+ inputArtifactIds: Array.isArray(payload.inputArtifactIds)
102
+ ? (payload.inputArtifactIds as string[])
103
+ : undefined,
100
104
  });
101
105
  case 'task-update':
102
106
  if (!payload.taskId || !payload.status) return null;
103
107
  return taskService.updateState(payload.taskId, normalizeState(payload.status) as Parameters<typeof taskService.updateState>[1], payload.result);
108
+ case 'task-update-plan-step':
109
+ if (!payload.taskId) throw new Error('task-update-plan-step requires `taskId`');
110
+ if (!payload.stepId) throw new Error('task-update-plan-step requires `stepId`');
111
+ if (!payload.status) throw new Error('task-update-plan-step requires `status`');
112
+ return taskService.updatePlanStep(payload.taskId, payload.stepId, payload.status, payload.result);
104
113
  default:
105
- return null;
114
+ throw new Error(`Unknown protocol operation: ${operation}`);
106
115
  }
107
116
  }
108
117
 
@@ -87,7 +87,7 @@ export const taskUpdatePlanStepTool: ToolDefinition = defineTool(
87
87
 
88
88
  export const taskSpawnTool: ToolDefinition = defineTool(
89
89
  'task_spawn',
90
- { agreementId: { type: 'string', required: true }, description: { type: 'string', required: true }, parentTaskId: 'string', assigneeId: { type: 'string', description: 'Explicitly hand this task to one specific agent (e.g. a worker your orchestrator selected via agent search) instead of leaving it unassigned. Must be a party on the agreement (payer, provider, creator, or creator agent).' }, plan: { type: 'object' }, planReviewTiming: 'string', requireMidWorkPlanAck: 'boolean' },
90
+ { agreementId: { type: 'string', required: true }, description: { type: 'string', required: true }, parentTaskId: 'string', assigneeId: { type: 'string', description: 'Explicitly hand this task to one specific agent (e.g. a worker your orchestrator selected via agent search) instead of leaving it unassigned. Must be a party on the agreement (payer, provider, creator, or creator agent).' }, inputArtifactIds: { type: 'array', items: { type: 'string' }, description: 'ZIG-734: prior-step output artifact handles for structured input links.' }, plan: { type: 'object' }, planReviewTiming: 'string', requireMidWorkPlanAck: 'boolean' },
91
91
  handlerFor('task-spawn'),
92
92
  { description: 'Spawn a new task under an existing approved agreement. Use when the contract is already in place. Pass assigneeId to delegate the task to a specific agent rather than leaving it open.' },
93
93
  );
@@ -121,14 +121,8 @@ export const paymentIssueGrantTool: ToolDefinition = defineTool('payment_issue_g
121
121
  issueGrantHandler,
122
122
  );
123
123
 
124
- /** @deprecated Use payment_issue_grant */
125
- export const paymentIssueTokenTool: ToolDefinition = defineTool('payment_issue_token',
126
- { holderId: { type: 'string', required: true }, maxAmount: 'number', dailyBudget: 'number', allowedRecipients: ['string'], expiresInSeconds: 'number' },
127
- issueGrantHandler,
128
- );
129
-
130
124
  const attenuateGrantHandler = async (args: AnyObj, ctx: Ctx) => {
131
- const grantId = (args['grantId'] || args['tokenId']) as string;
125
+ const grantId = args['grantId'] as string;
132
126
  if (!grantId) throw new Error('grantId is required');
133
127
  if (!args['holderId']) throw new Error('holderId is required');
134
128
  try {
@@ -144,14 +138,8 @@ export const paymentAttenuateGrantTool: ToolDefinition = defineTool('payment_att
144
138
  attenuateGrantHandler,
145
139
  );
146
140
 
147
- /** @deprecated Use payment_attenuate_grant */
148
- export const paymentAttenuateTokenTool: ToolDefinition = defineTool('payment_attenuate_token',
149
- { tokenId: { type: 'string', required: true }, holderId: { type: 'string', required: true }, maxAmount: 'number', dailyBudget: 'number', allowedRecipients: ['string'], expiresInSeconds: 'number' },
150
- attenuateGrantHandler,
151
- );
152
-
153
141
  const revokeGrantHandler = async (args: AnyObj, ctx: Ctx) => {
154
- const grantId = (args['grantId'] || args['tokenId']) as string;
142
+ const grantId = args['grantId'] as string;
155
143
  if (!grantId) throw new Error('grantId is required');
156
144
  try {
157
145
  const result = await clientFor(ctx).revokeGrant(grantId) as AnyObj;
@@ -164,12 +152,6 @@ export const paymentRevokeGrantTool: ToolDefinition = defineTool('payment_revoke
164
152
  revokeGrantHandler,
165
153
  );
166
154
 
167
- /** @deprecated Use payment_revoke_grant */
168
- export const paymentRevokeTokenTool: ToolDefinition = defineTool('payment_revoke_token',
169
- { tokenId: { type: 'string', required: true } },
170
- revokeGrantHandler,
171
- );
172
-
173
155
  const listGrantsHandler = async (_args: AnyObj, ctx: Ctx) => {
174
156
  try {
175
157
  const result = await clientFor(ctx).listGrants();
@@ -181,11 +163,6 @@ export const paymentListGrantsTool: ToolDefinition = defineTool('payment_list_gr
181
163
  listGrantsHandler,
182
164
  );
183
165
 
184
- /** @deprecated Use payment_list_grants */
185
- export const paymentListTokensTool: ToolDefinition = defineTool('payment_list_tokens', {},
186
- listGrantsHandler,
187
- );
188
-
189
166
  export const PAYMENT_TOOLS: ToolDefinition[] = [
190
167
  paymentBalanceTool, paymentTransferTool, paymentWaitForApprovalTool,
191
168
  paymentHoldTool, paymentReleaseTool, paymentResolveWalletTool,
package/src/types.ts CHANGED
@@ -26,6 +26,10 @@ export interface TaskRef {
26
26
  state?: string;
27
27
  description?: string;
28
28
  parentTaskId?: string;
29
+ executorId?: string;
30
+ assigneeId?: string | null;
31
+ /** Work product set by task_update (safeJsonStringify'd string on the wire). */
32
+ result?: unknown;
29
33
  proposal?: { status?: 'pending' | 'approved' | 'rejected' | 'cancelled' };
30
34
  proposedToIsYou?: boolean;
31
35
  providerIsYou?: boolean;
@@ -43,7 +47,7 @@ export interface ProposalRef {
43
47
  export type OutcomeKind =
44
48
  | 'enter'
45
49
  | 'wait'
46
- | 'timeout'
50
+ | 'state-timeout'
47
51
  | 'message-sent'
48
52
  | 'message-received'
49
53
  | 'task-assigned'
@@ -59,7 +63,7 @@ export type OutcomeKind =
59
63
  export type Outcome =
60
64
  | { kind: 'enter' }
61
65
  | { kind: 'wait' }
62
- | { kind: 'timeout' }
66
+ | { kind: 'state-timeout'; state: string; waitedMs: number }
63
67
  | { kind: 'message-sent'; text?: string; receiverId?: string }
64
68
  | { kind: 'message-received'; text?: string; senderId?: string; senderType?: string }
65
69
  | { kind: 'task-assigned'; task: TaskRef }
@@ -67,7 +71,20 @@ export type Outcome =
67
71
  | { kind: 'task-closed'; status: 'completed' | 'failed'; result?: unknown }
68
72
  | { kind: 'subtask-finished'; status: 'completed' | 'failed'; task: TaskRef; result?: unknown }
69
73
  | { kind: 'proposal-made'; proposal: ProposalRef }
70
- | { kind: 'proposal-resolved'; action: 'approve' | 'reject'; proposal: ProposalRef }
74
+ | {
75
+ kind: 'proposal-resolved';
76
+ action: 'approve' | 'reject';
77
+ proposal: ProposalRef;
78
+ /**
79
+ * True when THIS agent made the proposal being resolved. Computed in
80
+ * AgentMachine._handleFrame by matching proposal.agreementId against
81
+ * ctx.pendingProposalAgreementId BEFORE applyOutcomeToCtx clears it —
82
+ * wire frames carry no trustworthy proposer field (agreement_lifecycle
83
+ * drops `parties` at ingress, and parties.creator is a principal id,
84
+ * not an agentId). Drives the injected agreement-kickoff default.
85
+ */
86
+ proposedByMe: boolean;
87
+ }
71
88
  | { kind: 'tool-result'; tool: string; result: unknown }
72
89
  | {
73
90
  kind: 'error';
@@ -109,11 +126,26 @@ export interface ToolResultEntry {
109
126
  error?: string;
110
127
  }
111
128
 
129
+ export interface PendingSubtask {
130
+ /** Executor the task was placed with; null only when the spawn result carried
131
+ * no executor identity (open/broadcast agreement task not yet claimed). */
132
+ agentId: string | null;
133
+ spawnedAt: number;
134
+ }
135
+
136
+ export interface CollectedSubtaskResult {
137
+ taskId: string;
138
+ agentId: string | null;
139
+ status: 'completed' | 'failed';
140
+ /** task.result from the finishing event; null when the event carried none. */
141
+ result: unknown;
142
+ }
143
+
112
144
  /**
113
145
  * Per-lane runtime state. Outcome is "what just happened"; Ctx is "what I know."
114
146
  *
115
147
  * Persistent identifiers (activeAgreementId, pendingProposalAgreementId,
116
- * delegatedTaskIds) survive across outcomes — they're the memory of which
148
+ * pendingSubtasks) survive across outcomes — they're the memory of which
117
149
  * agreement the agent is currently bound to and which subtasks it's awaiting.
118
150
  */
119
151
  export interface Ctx {
@@ -124,7 +156,10 @@ export interface Ctx {
124
156
  activeTaskId: string | null;
125
157
  pendingProposalAgreementId: string | null;
126
158
  delegatedAgreementIds: string[];
127
- delegatedTaskIds: string[];
159
+ /** Durable barrier for orchestration: every spawned-but-unfinished subtask, keyed by taskId. */
160
+ pendingSubtasks: Record<string, PendingSubtask>;
161
+ /** Every finished subtask of the current engagement, arrival order. Synthesis prompts render ALL of these. */
162
+ collectedResults: CollectedSubtaskResult[];
128
163
 
129
164
  // Per-turn working memory
130
165
  toolResults: ToolResultEntry[];
@@ -182,6 +217,17 @@ export interface Transition {
182
217
 
183
218
  export interface ParkedState {
184
219
  kind: 'parked';
220
+ /**
221
+ * Liveness timer. When the machine settles in this state and no event
222
+ * arrives on the lane within timeoutMs, the host wakes the lane with a
223
+ * { kind: 'state-timeout', state, waitedMs } outcome so a transition can
224
+ * route to a recovery/nudge state. If no transition matches, the machine
225
+ * parks loudly (runtimeLog.error) and the timer is NOT re-armed. Countdown
226
+ * starts when the tick settles and resets on any event for the lane.
227
+ * In-memory only: lost on process restart; re-armed by the next real event
228
+ * that ticks the lane.
229
+ */
230
+ timeoutMs?: number;
185
231
  transitions: Transition[];
186
232
  }
187
233
 
@@ -389,11 +435,14 @@ export interface DefineAgentInput {
389
435
 
390
436
  /**
391
437
  * Frozen output of defineAgent. Consumed directly by AgentHost / createAgent.
392
- * No mutation — defineAgent validates and returns; injection of defaults is
393
- * the workflow author's responsibility (visible spread of `thinkingDefaults`).
438
+ * defineAgent injects ONE default: the agreement-kickoff state `kickingOff`
439
+ * plus a last-position transition into it, added to states that don't already
440
+ * handle a proposer-side proposal-resolved/approve outcome (runtime/kickoff.ts).
441
+ * `wait` defaults remain the author's visible spread of `thinkingDefaults`.
394
442
  */
395
443
  export interface AgentConfig {
396
444
  openaiKey: string | undefined;
445
+ anthropicKey: string | undefined;
397
446
  operatorKey?: string;
398
447
  agentId: string;
399
448
  description: string;