@ziggs-ai/agent-sdk 0.6.0 → 0.7.1

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 (44) hide show
  1. package/dist/AgentHost.d.ts +1 -1
  2. package/dist/agent/ClaudeSdkAgent.js +1 -1
  3. package/dist/agent/claudeCognition.js +1 -1
  4. package/dist/agent/claudeSdkProtocol.d.ts +1 -1
  5. package/dist/agent/claudeSdkProtocol.js +4 -3
  6. package/dist/agent/claudeSdkTools.d.ts +3 -2
  7. package/dist/agent/claudeSdkTools.js +48 -11
  8. package/dist/context/routingLabels.js +1 -1
  9. package/dist/index.d.ts +3 -2
  10. package/dist/index.js +3 -2
  11. package/dist/runtime/PromptBuilder.js +13 -6
  12. package/dist/runtime/bootstrapCtx.d.ts +2 -2
  13. package/dist/runtime/bootstrapCtx.js +13 -6
  14. package/dist/runtime/buildOutcome.d.ts +3 -2
  15. package/dist/runtime/buildOutcome.js +46 -26
  16. package/dist/runtime/deriveRespondsToProposals.d.ts +1 -1
  17. package/dist/runtime/deriveRespondsToProposals.js +1 -1
  18. package/dist/runtime/kickoff.js +8 -8
  19. package/dist/runtime/runTurn.js +42 -7
  20. package/dist/runtime/taskBookkeeping.d.ts +35 -0
  21. package/dist/runtime/taskBookkeeping.js +149 -0
  22. package/dist/runtime/taskIntake.js +6 -6
  23. package/dist/server/ZiggsEffectHandler.d.ts +1 -1
  24. package/dist/server/ZiggsEffectHandler.js +9 -5
  25. package/dist/server/agreements/AgreementService.d.ts +13 -0
  26. package/dist/server/agreements/AgreementService.js +16 -1
  27. package/dist/server/inboxLoop.js +13 -0
  28. package/dist/server/tools/index.d.ts +2 -2
  29. package/dist/server/tools/index.js +6 -4
  30. package/dist/server/tools/tier1/protocolRunner.d.ts +2 -2
  31. package/dist/server/tools/tier1/protocolRunner.js +58 -7
  32. package/dist/server/tools/tier1/protocolTools.d.ts +5 -4
  33. package/dist/server/tools/tier1/protocolTools.js +33 -10
  34. package/dist/server/tools/tier2/chatTools.js +1 -1
  35. package/dist/server/tools/tier2/connectionTools.js +2 -2
  36. package/dist/server/tools/tier2/linkTools.d.ts +2 -5
  37. package/dist/server/tools/tier2/linkTools.js +7 -6
  38. package/dist/server/tools/tier2/marketplaceTools.d.ts +1 -1
  39. package/dist/server/tools/tier2/marketplaceTools.js +9 -22
  40. package/dist/tasks/protocolRegistry.d.ts +5 -4
  41. package/dist/tasks/protocolRegistry.js +5 -4
  42. package/dist/tools/recordReport.d.ts +1 -1
  43. package/dist/types.d.ts +36 -8
  44. package/package.json +2 -2
@@ -1,5 +1,18 @@
1
1
  import { defineTool } from '../../../tools/defineTool.js';
2
2
  import { dispatchProtocolOp } from './protocolRunner.js';
3
+ /** ZIG-957 — keep these enums in lockstep with MCP ziggs_agreement_* / ziggs_task_create. */
4
+ const LIFECYCLE_ENUM = ['open', 'time-bound', 'count-bound'];
5
+ const PLAN_REVIEW_TIMING_ENUM = ['with_proposal', 'before_execution'];
6
+ const lifecycleParam = {
7
+ type: 'string',
8
+ enum: [...LIFECYCLE_ENUM],
9
+ description: "Usually inferred: expiresAt → 'time-bound', maxExecutions → 'count-bound', neither → 'open' (standing).",
10
+ };
11
+ const planReviewTimingParam = {
12
+ type: 'string',
13
+ enum: [...PLAN_REVIEW_TIMING_ENUM],
14
+ description: 'When the buyer reviews the plan: with_proposal | before_execution',
15
+ };
3
16
  function handlerFor(operation) {
4
17
  return async (args, ctx) => {
5
18
  const c = ctx;
@@ -19,19 +32,29 @@ function handlerFor(operation) {
19
32
  return result;
20
33
  };
21
34
  }
22
- export const agreementProposeTool = defineTool('agreement_propose', { description: { type: 'string', required: true }, proposedTo: { type: 'string', required: true }, engagementKind: { type: 'string', enum: ['hire', 'service'], description: 'Contract type. Defaults to service when omitted.' }, parentAgreementId: 'string', parentTaskId: 'string', providerId: { type: 'string', description: 'Who does the work — required on direct proposals, forbidden on broadcasts (the claiming agent fills the open side). Pass your own id when YOU are offering to do the work, or the proposedTo id when you are commissioning the RECIPIENT. Naming any other third party requires that party to have a matching published offer. The payer is always derived as the non-providing side.' }, price: 'number', lifecycle: 'string', expiresAt: 'string', maxExecutions: 'number', billing: { type: 'string', enum: ['total', 'per_task'], description: "How price reads: 'total' (default, escrowed and paid at the end) or 'per_task' (a rate settled as each task completes — standing agreements only, and the default for a hire)." }, agreementDescription: 'string', plan: { type: 'object' }, planReviewTiming: 'string', requireMidWorkPlanAck: 'boolean' }, handlerFor('agreement-propose'), { description: 'Propose a contract to a user, agent, or as an open broadcast. Direction is stated, never guessed: providerId = your own id ("I work, you pay") or providerId = proposedTo ("you work, I pay"). Required on direct proposals; omit it only for a broadcast — proposedTo="everyone" (fully public — any agent may claim) or proposedTo="org" (scoped to your org). engagementKind defaults to service. Agreements are STANDING by default (no expiry, unlimited tasks under one agreement); set expiresAt or maxExecutions only when the engagement should end on its own.', isAgreementCreation: true });
23
- export const agreementSubcontractTool = defineTool('agreement_subcontract', { description: { type: 'string', required: true }, executorId: { type: 'string', required: true }, parentAgreementId: { type: 'string', required: true }, parentTaskId: 'string', payerId: 'string', price: 'number', lifecycle: 'string', expiresAt: 'string', maxExecutions: 'number', agreementDescription: 'string', plan: { type: 'object' }, planReviewTiming: 'string', requireMidWorkPlanAck: 'boolean' }, handlerFor('agreement-subcontract'), { description: 'Delegate work to another agent under an existing parent agreement. Requires parentAgreementId.', isAgreementCreation: true });
24
- export const agreementRespondTool = defineTool('agreement_respond', { agreementId: { type: 'string', required: true }, action: { type: 'string', required: true, enum: ['approve', 'reject'] } }, handlerFor('agreement-respond'), { description: 'Approve or reject a pending agreement proposal.' });
25
- export const taskUpdateTool = defineTool('task_update', { taskId: { type: 'string', required: true }, status: { type: 'string', required: true, enum: ['completed', 'failed', 'cancelled'] }, result: 'string' }, handlerFor('task-update'), { description: 'Transition a task to completed, failed, or cancelled. Include a result string for completed tasks.' });
26
- export const agreementCounterProposalTool = defineTool('agreement_counter_proposal', { agreementId: { type: 'string', required: true }, price: 'number', agreementDescription: 'string', expiresAt: 'string', lifecycle: 'string', maxExecutions: 'number', description: 'string', plan: { type: 'object' }, planReviewTiming: 'string', requireMidWorkPlanAck: 'boolean' }, handlerFor('agreement-counter-proposal'), { description: 'Counter a pending proposal with revised terms instead of approving or rejecting. Check status first with agreement_check_proposal.' });
27
- export const agreementCheckProposalTool = defineTool('agreement_check_proposal', { agreementId: { type: 'string', required: true } }, handlerFor('agreement-check-proposal'), { description: 'Read the current proposal status for an agreement (pending, approved, rejected, countered, expired).' });
35
+ export const agreementProposeTool = defineTool('agreement_propose', { description: { type: 'string', required: true }, proposedTo: { type: 'string', required: true }, engagementKind: { type: 'string', enum: ['hire', 'service', 'link'], description: "Contract type. Defaults to service. 'link' proposes a bilateral trust link (no work, no money)." }, parentAgreementId: 'string', parentTaskId: 'string', providerId: { type: 'string', description: 'Who does the work — required on direct proposals. Pass your own id when YOU are offering to do the work, or the proposedTo id when you are commissioning the RECIPIENT (any other third party needs a matching published offer). On a broadcast: omit for a quest (the claimer works, you pay), or pass your own id to publish a standing offer (you work, the claimer pays). The payer is always derived as the non-providing side.' }, price: { type: 'number', description: 'Amount in CENTS — 500 means $5.00. Quote it to a human in the same units the agreement charges.' }, lifecycle: lifecycleParam, expiresAt: 'string', maxExecutions: 'integer', billing: { type: 'string', enum: ['total', 'per_task'], description: "How price reads: 'total' (default, escrowed and paid at the end) or 'per_task' (a rate settled as each task completes — standing agreements only, and the default for a hire)." }, agreementDescription: 'string', plan: { type: 'object' }, planReviewTiming: planReviewTimingParam, requireMidWorkPlanAck: 'boolean' }, handlerFor('agreement-propose'), { description: 'Propose an agreement — direct, broadcast, or link; there are no separate publish tools. Direction is stated, never guessed: providerId = your own id ("I work, you pay") or providerId = proposedTo ("you work, I pay") on direct proposals. Broadcast with proposedTo="everyone" (fully public) or "org" (your org only): no providerId publishes a QUEST any agent may claim; providerId = your own id publishes a STANDING OFFER (claiming is agreement_claim; browsing is marketplace_view). engagementKind "link" with proposedTo = an agent id proposes bilateral trust. engagementKind defaults to service. Agreements are STANDING by default (no expiry, unlimited tasks under one agreement); set expiresAt or maxExecutions only when the engagement should end on its own.', isAgreementCreation: true });
36
+ export const agreementSubcontractTool = defineTool('agreement_subcontract', { description: { type: 'string', required: true }, executorId: { type: 'string', required: true }, parentAgreementId: { type: 'string', required: true }, parentTaskId: 'string', payerId: 'string', price: { type: 'number', description: 'Amount in CENTS — 500 means $5.00. Quote it to a human in the same units the agreement charges.' }, lifecycle: lifecycleParam, expiresAt: 'string', maxExecutions: 'integer', agreementDescription: 'string', plan: { type: 'object' }, planReviewTiming: planReviewTimingParam, requireMidWorkPlanAck: 'boolean' }, handlerFor('agreement-subcontract'), { description: 'Delegate work to another agent under an existing parent agreement. Requires parentAgreementId.', isAgreementCreation: true });
37
+ export const agreementRespondTool = defineTool('agreement_respond', { agreementId: { type: 'string', required: true }, action: { type: 'string', required: true, enum: ['approve', 'reject'] } }, handlerFor('agreement-respond'), { description: 'Approve or reject a pending DIRECT agreement proposal addressed to you. Open broadcasts (quests, standing offers, link invites) have no personal approval slot — claim those with agreement_claim instead, or ignore them to pass.' });
38
+ export const agreementClaimTool = defineTool('agreement_claim', { agreementId: { type: 'string', required: true, description: 'The open agreement to claim (quest / offer / link invite id)' } }, handlerFor('agreement-claim'), { description: 'Claim an open broadcast agreement by id — a quest (you do the work, the publisher pays), a standing offer (you buy, the publisher works), or a link invite (bilateral trust forms immediately). You become the open party and the agreement activates. Find quests/offers with marketplace_view; direct proposals are approved with agreement_respond instead, not claimed.' });
39
+ export const taskSetResultTool = defineTool('task_set_result', {
40
+ taskId: { type: 'string', required: true },
41
+ // ZIG-957: same param name as MCP ziggs_task_set_result / PATCH /tasks/:id/state.
42
+ state: { type: 'string', required: true, enum: ['completed', 'failed', 'cancelled'] },
43
+ // Same object contract as MCP ({ summary, status, links, … }).
44
+ result: {
45
+ type: 'object',
46
+ description: 'Outcome payload (summary, status, links, …). Finished work is the task result — never a chat message.',
47
+ },
48
+ }, handlerFor('task-update'), { description: 'Transition a task to its terminal state — completed, failed, or cancelled — and record the result. Finished work is the task result: set it here as an object ({ summary, status, links }), never as a chat message. Pass state (not status).' });
49
+ export const agreementCounterTool = defineTool('agreement_counter', { agreementId: { type: 'string', required: true }, price: { type: 'number', description: 'Amount in CENTS — 500 means $5.00. Quote it to a human in the same units the agreement charges.' }, agreementDescription: 'string', expiresAt: 'string', lifecycle: lifecycleParam, maxExecutions: 'integer', description: 'string', plan: { type: 'object' }, planReviewTiming: planReviewTimingParam, requireMidWorkPlanAck: 'boolean' }, handlerFor('agreement-counter-proposal'), { description: 'Counter a pending proposal with revised terms instead of approving or rejecting. Check status first with agreement_get.' });
50
+ export const agreementGetTool = defineTool('agreement_get', { agreementId: { type: 'string', required: true } }, handlerFor('agreement-check-proposal'), { description: 'Read the current proposal status for an agreement (pending, approved, rejected, countered, expired).' });
28
51
  export const agreementRevokeTool = defineTool('agreement_revoke', { agreementId: { type: 'string', required: true } }, handlerFor('agreement-revoke'), { description: 'Revoke a pending proposal you created so it can no longer be approved. Use when the user has clearly moved on to a different request before responding to the previous proposal card.' });
29
- export const agreementFulfillTool = defineTool('agreement_fulfill', { agreementId: { type: 'string', required: true } }, handlerFor('agreement-fulfill'), { description: 'END an agreement you provide — permanently. Fulfilling terminates the whole relationship, not one deliverable: every grant it conferred is revoked, its shared space is torn down, and it cannot be reopened. Finished WORK is reported via task_update (the task closes; the agreement stays standing for the next task). Only fulfill when the engagement\'s full scope is delivered and nothing more is expected — never a standing hire that just finished a task.' });
52
+ export const agreementFulfillTool = defineTool('agreement_fulfill', { agreementId: { type: 'string', required: true } }, handlerFor('agreement-fulfill'), { description: 'END an agreement you provide — permanently. Fulfilling terminates the whole relationship, not one deliverable: every grant it conferred is revoked, its shared space is torn down, and it cannot be reopened. Finished WORK is reported via task_set_result (the task closes; the agreement stays standing for the next task). Only fulfill when the engagement\'s full scope is delivered and nothing more is expected — never a standing hire that just finished a task.' });
30
53
  export const taskUpdatePlanStepTool = defineTool('task_update_plan_step', { taskId: { type: 'string', required: true }, stepId: { type: 'string', required: true }, status: { type: 'string', required: true }, result: 'string' }, handlerFor('task-update-plan-step'), { description: "Update the status of a single step within a task's plan." });
31
- export const taskSpawnTool = defineTool('task_spawn', { 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' }, handlerFor('task-spawn'), { 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.' });
54
+ export const taskCreateTool = defineTool('task_create', { 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: planReviewTimingParam, requireMidWorkPlanAck: 'boolean' }, handlerFor('task-spawn'), { description: 'Create 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.' });
32
55
  export const PROTOCOL_TOOLS = [
33
56
  agreementProposeTool, agreementSubcontractTool,
34
- agreementRespondTool, agreementCounterProposalTool, agreementCheckProposalTool, agreementRevokeTool,
57
+ agreementRespondTool, agreementClaimTool, agreementCounterTool, agreementGetTool, agreementRevokeTool,
35
58
  agreementFulfillTool,
36
- taskSpawnTool, taskUpdateTool, taskUpdatePlanStepTool,
59
+ taskCreateTool, taskSetResultTool, taskUpdatePlanStepTool,
37
60
  ];
@@ -1,6 +1,6 @@
1
1
  import { CHAT_CAPABILITIES, openConversationCapability } from '@ziggs-ai/api-client';
2
2
  import { toolFromCapability, toolsFromCapabilities } from '../../../tools/capabilityAdapter.js';
3
- // ZIG-900 / ZIG-956 — open_conversation only (chat listing stays a
3
+ // ZIG-900 / ZIG-956 — chat_open only (chat listing stays a
4
4
  // context-rail read, ZIG-626 rule); defined once in api-client's shared
5
5
  // capability layer.
6
6
  export const openConversationTool = toolFromCapability(openConversationCapability);
@@ -1,9 +1,9 @@
1
1
  import { connectionProxyCapability, requestConnectionCapability, ConnectionsClient, } from '@ziggs-ai/api-client';
2
2
  import { defineTool } from '../../../tools/defineTool.js';
3
3
  import { toolFromCapability } from '../../../tools/capabilityAdapter.js';
4
- // ZIG-956 — connection_proxy / request_connection are shared capability
4
+ // ZIG-956 — connection_proxy / connection_request are shared capability
5
5
  // definitions (api-client). connection_list_grants stays SDK-only: the MCP
6
- // surface folds connection listing into ziggs_list_my_connections (ZIG-893
6
+ // surface folds connection listing into ziggs_connection_list (ZIG-893
7
7
  // allowance in the parity table).
8
8
  export const connectionProxyTool = toolFromCapability(connectionProxyCapability);
9
9
  export const requestConnectionTool = toolFromCapability(requestConnectionCapability);
@@ -1,7 +1,4 @@
1
1
  import type { ToolDefinition } from '../../../tools/defineTool.js';
2
- export declare const requestLinkTool: ToolDefinition;
3
- export declare const createLinkInviteTool: ToolDefinition;
4
- export declare const claimLinkInviteTool: ToolDefinition;
5
- export declare const listLinksTool: ToolDefinition;
6
- export declare const revokeLinkTool: ToolDefinition;
2
+ export declare const linkCreateInviteTool: ToolDefinition;
3
+ export declare const linkListTool: ToolDefinition;
7
4
  export declare const LINK_TOOLS: ToolDefinition[];
@@ -1,12 +1,13 @@
1
- import { LINK_CAPABILITIES, requestLinkCapability, createLinkInviteCapability, claimLinkInviteCapability, listLinksCapability, revokeLinkCapability, } from '@ziggs-ai/api-client';
1
+ import { LINK_CAPABILITIES, createLinkInviteCapability, listLinksCapability, } from '@ziggs-ai/api-client';
2
2
  import { toolFromCapability, toolsFromCapabilities } from '../../../tools/capabilityAdapter.js';
3
3
  // ZIG-898 / ZIG-956 — links are agreements with engagementKind 'link':
4
4
  // bilateral agent-to-agent trust that gives unpublished delegates cross-org
5
5
  // reach. Defined once in api-client's shared capability layer (including the
6
6
  // ZIG-670 linkSummary shaping); this file only adapts them onto the SDK.
7
- export const requestLinkTool = toolFromCapability(requestLinkCapability);
8
- export const createLinkInviteTool = toolFromCapability(createLinkInviteCapability);
9
- export const claimLinkInviteTool = toolFromCapability(claimLinkInviteCapability);
10
- export const listLinksTool = toolFromCapability(listLinksCapability);
11
- export const revokeLinkTool = toolFromCapability(revokeLinkCapability);
7
+ //
8
+ // ZIG-1021/1022 shrank the rail to two tools. The agreement verbs carry the
9
+ // rest: request a direct link with agreement_propose (engagementKind 'link'),
10
+ // claim an invite with agreement_claim, end a link with agreement_revoke.
11
+ export const linkCreateInviteTool = toolFromCapability(createLinkInviteCapability);
12
+ export const linkListTool = toolFromCapability(listLinksCapability);
12
13
  export const LINK_TOOLS = toolsFromCapabilities(LINK_CAPABILITIES);
@@ -1,3 +1,3 @@
1
- import { type ToolDefinition } from '../../../tools/defineTool.js';
1
+ import type { ToolDefinition } from '../../../tools/defineTool.js';
2
2
  export declare const marketplaceViewTool: ToolDefinition;
3
3
  export declare const MARKETPLACE_TOOLS: ToolDefinition[];
@@ -1,22 +1,9 @@
1
- import { defineTool } from '../../../tools/defineTool.js';
2
- import { pullQuests } from '@ziggs-ai/api-client';
3
- // Read-only marketplace access. Publishing an open quest is NOT here: it is the
4
- // tier-1 protocol verb agreement_propose({ proposedTo: "everyone" | "org" }).
5
- // This feed already returns only quests the caller may see — org-scoped quests
6
- // appear here only for members of the quest's org (filtered server-side).
7
- export const marketplaceViewTool = defineTool('marketplace_view', { limit: 'number', since: 'string' }, async (args, ctx) => {
8
- const operatorKey = ctx?.['operatorKey'];
9
- const agentId = ctx?.['agentId'];
10
- if (!operatorKey)
11
- throw new Error('operatorKey missing from tool context');
12
- if (!agentId)
13
- throw new Error('agentId missing from tool context');
14
- const options = {
15
- limit: typeof args['limit'] === 'number' ? args['limit'] : 20,
16
- };
17
- if (args['since'])
18
- options.since = args['since'];
19
- const quests = await pullQuests(options, { operatorKey, agentId });
20
- return { quests, count: quests.length };
21
- }, { description: 'Browse open quests on the marketplace — work buyers have broadcast to willing agents. Returns public quests plus any org-scoped quests in your org. To claim a quest, use agreement_respond on the returned agreementId. To publish your own, use agreement_propose({ proposedTo: "everyone" }) for a public quest or proposedTo: "org" to keep it inside your org.' });
22
- export const MARKETPLACE_TOOLS = [marketplaceViewTool];
1
+ import { MARKETPLACE_CAPABILITIES, marketplaceViewCapability } from '@ziggs-ai/api-client';
2
+ import { toolFromCapability, toolsFromCapabilities } from '../../../tools/capabilityAdapter.js';
3
+ // ZIG-1023 / ZIG-956 — the marketplace read (quests AND standing offers),
4
+ // defined once in api-client's shared capability layer. Publishing is NOT
5
+ // here: it is the tier-1 verb agreement_propose with proposedTo
6
+ // "everyone" | "org" (providerId = own id for an offer, omitted for a quest);
7
+ // claiming is agreement_claim.
8
+ export const marketplaceViewTool = toolFromCapability(marketplaceViewCapability);
9
+ export const MARKETPLACE_TOOLS = toolsFromCapabilities(MARKETPLACE_CAPABILITIES);
@@ -2,11 +2,12 @@ export declare const PROTOCOL_TOOL_TO_OPERATION: Readonly<{
2
2
  readonly agreement_propose: "agreement-propose";
3
3
  readonly agreement_subcontract: "agreement-subcontract";
4
4
  readonly agreement_respond: "agreement-respond";
5
- readonly agreement_counter_proposal: "agreement-counter-proposal";
6
- readonly agreement_check_proposal: "agreement-check-proposal";
5
+ readonly agreement_claim: "agreement-claim";
6
+ readonly agreement_counter: "agreement-counter-proposal";
7
+ readonly agreement_get: "agreement-check-proposal";
7
8
  readonly agreement_revoke: "agreement-revoke";
8
- readonly task_spawn: "task-spawn";
9
- readonly task_update: "task-update";
9
+ readonly task_create: "task-spawn";
10
+ readonly task_set_result: "task-update";
10
11
  readonly task_update_plan_step: "task-update-plan-step";
11
12
  }>;
12
13
  export type ProtocolToolName = keyof typeof PROTOCOL_TOOL_TO_OPERATION;
@@ -2,11 +2,12 @@ export const PROTOCOL_TOOL_TO_OPERATION = Object.freeze({
2
2
  agreement_propose: 'agreement-propose',
3
3
  agreement_subcontract: 'agreement-subcontract',
4
4
  agreement_respond: 'agreement-respond',
5
- agreement_counter_proposal: 'agreement-counter-proposal',
6
- agreement_check_proposal: 'agreement-check-proposal',
5
+ agreement_claim: 'agreement-claim',
6
+ agreement_counter: 'agreement-counter-proposal',
7
+ agreement_get: 'agreement-check-proposal',
7
8
  agreement_revoke: 'agreement-revoke',
8
- task_spawn: 'task-spawn',
9
- task_update: 'task-update',
9
+ task_create: 'task-spawn',
10
+ task_set_result: 'task-update',
10
11
  task_update_plan_step: 'task-update-plan-step',
11
12
  });
12
13
  export const PROTOCOL_TOOL_NAMES = Object.freeze(Object.keys(PROTOCOL_TOOL_TO_OPERATION));
@@ -1,7 +1,7 @@
1
1
  import { type Creds } from '@ziggs-ai/api-client';
2
2
  /**
3
3
  * The canonical report shape (B1 convention — ZIG-561).
4
- * Matches Task.result as set by ziggs_set_task_result.
4
+ * Matches Task.result as set by ziggs_task_set_result.
5
5
  */
6
6
  export interface TaskReport {
7
7
  summary: string;
package/dist/types.d.ts CHANGED
@@ -29,7 +29,7 @@ export interface TaskRef {
29
29
  parentTaskId?: string;
30
30
  executorId?: string;
31
31
  assigneeId?: string | null;
32
- /** Work product set by task_update (safeJsonStringify'd string on the wire). */
32
+ /** Work product set by task_set_result (safeJsonStringify'd string on the wire). */
33
33
  result?: unknown;
34
34
  proposal?: {
35
35
  status?: 'pending' | 'approved' | 'rejected' | 'cancelled';
@@ -70,6 +70,8 @@ export type Outcome = {
70
70
  } | {
71
71
  kind: 'task-closed';
72
72
  status: 'completed' | 'failed';
73
+ /** Task being closed — required to clear only that entry (ZIG-977). */
74
+ taskId?: string;
73
75
  result?: unknown;
74
76
  } | {
75
77
  kind: 'subtask-finished';
@@ -151,23 +153,49 @@ export interface CollectedSubtaskResult {
151
153
  /** task.result from the finishing event; null when the event carried none. */
152
154
  result: unknown;
153
155
  }
156
+ /**
157
+ * Per-assigned-task (or coordinator-lane) bookkeeping under one chat lane.
158
+ * Keyed on Ctx.tasks by taskId (ZIG-977) — task-closed clears only its entry.
159
+ */
160
+ export interface TaskBookkeeping {
161
+ agreementId: string | null;
162
+ /** Spawned-but-unfinished children of this engagement, keyed by child taskId. */
163
+ pendingSubtasks: Record<string, PendingSubtask>;
164
+ /** Finished children of this engagement, arrival order. */
165
+ collectedResults: CollectedSubtaskResult[];
166
+ /** Sub-agreement ids recorded on task-delegated under this engagement. */
167
+ delegatedAgreementIds: string[];
168
+ }
154
169
  /**
155
170
  * Per-lane runtime state. Outcome is "what just happened"; Ctx is "what I know."
156
171
  *
157
- * Persistent identifiers (activeAgreementId, pendingProposalAgreementId,
158
- * pendingSubtasks) survive across outcomes — they're the memory of which
159
- * agreement the agent is currently bound to and which subtasks it's awaiting.
172
+ * Task bookkeeping lives in `tasks` (keyed by taskId). `activeTaskId` /
173
+ * `activeAgreementId` are the focus scalars for prompt + FSM convenience —
174
+ * assigning task B no longer destroys task A's pending/collected state, and
175
+ * closing A leaves B intact (ZIG-977).
160
176
  */
161
177
  export interface Ctx {
162
178
  identity: Identity;
163
- activeAgreementId: string | null;
179
+ /**
180
+ * Open engagements in this lane, keyed by taskId (assigned work) or the
181
+ * reserved coordinator bucket (see LANE_BOOK_KEY) when spawning without an
182
+ * assigned parent task.
183
+ */
184
+ tasks: Record<string, TaskBookkeeping>;
185
+ /** Focus task — most recently assigned; prompts/FSM read this. */
164
186
  activeTaskId: string | null;
187
+ /** Focus agreement — sync'd with tasks[activeTaskId] when a task is focused. */
188
+ activeAgreementId: string | null;
165
189
  pendingProposalAgreementId: string | null;
166
- delegatedAgreementIds: string[];
167
- /** Durable barrier for orchestration: every spawned-but-unfinished subtask, keyed by taskId. */
190
+ /**
191
+ * Aggregate views over `tasks` (all engagements in the lane). Kept in sync by
192
+ * applyOutcomeToCtx / bootstrapCtx so existing workflow `when` guards that
193
+ * read these fields (e.g. motifs awaitingAll) keep working after ZIG-977.
194
+ * Prefer reading `tasks[taskId]` when you need per-task isolation.
195
+ */
168
196
  pendingSubtasks: Record<string, PendingSubtask>;
169
- /** Every finished subtask of the current engagement, arrival order. Synthesis prompts render ALL of these. */
170
197
  collectedResults: CollectedSubtaskResult[];
198
+ delegatedAgreementIds: string[];
171
199
  toolResults: ToolResultEntry[];
172
200
  lastOutcome: Outcome;
173
201
  /** Claude Agent SDK session id for resume across ticks (claude-sdk cognition only). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/agent-sdk",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
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.5.0",
29
+ "@ziggs-ai/api-client": "^0.6.1",
30
30
  "ajv": "^8.17.1",
31
31
  "dotenv": "^17.2.3",
32
32
  "openai": "^4.0.0",