@ziggs-ai/agent-sdk 0.42.0 → 0.42.2

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 CHANGED
@@ -32,6 +32,8 @@
32
32
 
33
33
  ## Unreleased
34
34
 
35
+ - Expose the shared `task_delegate` capability on the hosted agent surface for recursive task assignments and approved artifact returns.
36
+
35
37
  ## 0.41.2
36
38
 
37
39
  ## 0.41.1
package/dist/Agent.d.ts CHANGED
@@ -300,6 +300,12 @@ export declare class Agent {
300
300
  private carryExecutionState;
301
301
  /** Runtime control is a task fact, never model-interpreted message text. */
302
302
  private taskExecutionControl;
303
+ /**
304
+ * Control on an assignment the inbox will not run yet. No wake follows, so a
305
+ * resume is acknowledged here too once no run of the task is live; the wake
306
+ * path that would otherwise answer it never comes while the delivery is blocked.
307
+ */
308
+ private observeBlockedTaskControl;
303
309
  private acknowledgeExecutionControl;
304
310
  /**
305
311
  * Handler for a resource change (artifact created, task state transition,
package/dist/Agent.js CHANGED
@@ -522,8 +522,10 @@ export class Agent {
522
522
  if (!this.taskService)
523
523
  return null;
524
524
  let task;
525
+ // Host control observation is separate from task work. Only execution state
526
+ // leaves this method; a stopped work context cannot observe its own stop.
525
527
  try {
526
- task = await this.taskService.getTask(taskId);
528
+ task = await withWorkExecution(undefined, () => this.taskService.getTask(taskId));
527
529
  }
528
530
  catch (error) {
529
531
  // Unreadable is not a hold. The wake filter still drops a frame whose
@@ -537,6 +539,17 @@ export class Agent {
537
539
  return null;
538
540
  return { blocked: task.state === 'cancelled' || (task.state === 'active' && task.control?.action === 'pause'), closed: task.state === 'cancelled', control: task.control };
539
541
  }
542
+ /**
543
+ * Control on an assignment the inbox will not run yet. No wake follows, so a
544
+ * resume is acknowledged here too once no run of the task is live; the wake
545
+ * path that would otherwise answer it never comes while the delivery is blocked.
546
+ */
547
+ async observeBlockedTaskControl(taskId) {
548
+ const execution = await this.taskExecutionControl(taskId);
549
+ const idleResume = execution?.control?.action === 'resume' && !this.activeTaskRuns.get(taskId)?.size;
550
+ if (execution?.blocked || idleResume)
551
+ await this.acknowledgeExecutionControl(taskId, execution?.control);
552
+ }
540
553
  async acknowledgeExecutionControl(taskId, control) {
541
554
  if (control?.status !== 'requested')
542
555
  return;
@@ -1612,6 +1625,7 @@ export class Agent {
1612
1625
  onResourceEvent: (event) => {
1613
1626
  return this.handleResourceEvent(event);
1614
1627
  },
1628
+ onTaskControlCheck: (taskId) => this.observeBlockedTaskControl(taskId),
1615
1629
  // work delivered by the inbox's task channel, not by a chat
1616
1630
  // row — this is what reaches a task under a chat-less agreement or one
1617
1631
  // the agent assigned to itself.
@@ -1,5 +1,5 @@
1
1
  import { type ToolDefinition } from '../tools/defineTool.js';
2
- import { cancelTaskTool, listTasksTool } from '../platform/tools/tier2/taskTools.js';
2
+ import { cancelTaskTool, listTasksTool, delegateTaskTool } from '../platform/tools/tier2/taskTools.js';
3
3
  import type { EffectHandler, DeliveryWriteKeys } from '../types.js';
4
4
  import type { MemoryStore } from '../memory/MemoryStore.js';
5
5
  export interface ClaudeSdkToolContext extends Record<string, unknown> {
@@ -25,5 +25,5 @@ export interface ClaudeSdkToolContext extends Record<string, unknown> {
25
25
  }
26
26
  export declare const contextSnapshotTool: ToolDefinition;
27
27
  export declare const chatSendTool: ToolDefinition;
28
- export { listTasksTool, cancelTaskTool };
28
+ export { listTasksTool, cancelTaskTool, delegateTaskTool };
29
29
  export declare const CLAUDE_SDK_TOOLS: ToolDefinition[];
@@ -5,7 +5,7 @@ import { credsFromToolContext } from '../tools/toolCreds.js';
5
5
  import { sendChatMessage, presentSendResult } from '@ziggs-ai/api-client';
6
6
  import { defineTool } from '../tools/defineTool.js';
7
7
  import { listGrantsTool } from '../platform/tools/tier2/grantsTools.js';
8
- import { cancelTaskTool, listTasksTool } from '../platform/tools/tier2/taskTools.js';
8
+ import { cancelTaskTool, listTasksTool, delegateTaskTool } from '../platform/tools/tier2/taskTools.js';
9
9
  import { CHAT_TOOLS } from '../platform/tools/tier2/chatTools.js';
10
10
  // default message-history cap. An uncapped snapshot returns the whole
11
11
  // chat — in a delegation chat that accumulates notification rows, every wake's
@@ -168,13 +168,14 @@ export const chatSendTool = defineTool('chat_send', {
168
168
  // task_list IS here: MCP delegates have ziggs_task_list; the hosted
169
169
  // Claude surface previously had no way to enumerate its own open tasks (reads
170
170
  // were prompt-injected only). Same GET /tasks capability as the MCP tool.
171
- export { listTasksTool, cancelTaskTool };
171
+ export { listTasksTool, cancelTaskTool, delegateTaskTool };
172
172
  export const CLAUDE_SDK_TOOLS = [
173
173
  contextSnapshotTool,
174
174
  chatSendTool,
175
175
  listGrantsTool,
176
176
  listTasksTool,
177
177
  cancelTaskTool,
178
+ delegateTaskTool,
178
179
  // store-claim providers must open the buyer chat from the default
179
180
  // Claude surface (chat_open was tier-2 / email-agent opt-in only).
180
181
  ...CHAT_TOOLS,
@@ -32,6 +32,8 @@ export interface InboxLoopDeps {
32
32
  * public request burns a full Claude turn per published supplier.
33
33
  */
34
34
  onRequest?: (request: InboxRequestRef) => Promise<void>;
35
+ /** Host-only control observation for blocked task assignments; never a model wake. */
36
+ onTaskControlCheck?: (taskId: string) => Promise<void>;
35
37
  label?: string;
36
38
  }
37
39
  export interface InboxPassResult {
@@ -205,6 +205,20 @@ export async function pollInboxOnce(deps, waitSeconds = 0, opts = {}) {
205
205
  if (blocked) {
206
206
  log(label, `${blocked} assignment(s) cannot run yet (no access or execution refused); left pending for the server to offer again`);
207
207
  }
208
+ if (deps.onTaskControlCheck) {
209
+ const blockedTasks = new Set([
210
+ ...envelope.deliveries.filter(d => mine(d) && d.kind === 'task-state' && d.executionBlocked && !d.outOfReach).map(d => d.resourceId),
211
+ ...(envelope.tasksAwaitingMe ?? []).filter(t => t.executionBlocked).map(t => t.taskId),
212
+ ]);
213
+ for (const taskId of blockedTasks) {
214
+ try {
215
+ await deps.onTaskControlCheck(taskId);
216
+ }
217
+ catch (error) {
218
+ warn(label, `task control observation failed for ${taskId}: ${error.message}`);
219
+ }
220
+ }
221
+ }
208
222
  const handledSoFar = new Set();
209
223
  const acknowledged = new Set();
210
224
  // A handled id the server would not settle (it lost access mid-wake) stays
@@ -24,7 +24,7 @@ export { PAYMENT_TOOLS, paymentBalanceTool } from './tier2/paymentTools.js';
24
24
  export { CONNECTION_TOOLS, connectionProxyTool, connectionListGrantsTool, requestConnectionTool, } from './tier2/connectionTools.js';
25
25
  export { CONTEXT_TOOLS, contextReadTool, accessRequestTool, contextDelegateTool, contextExpandReachTool, contextDiscoverGrantableTool, } from './tier2/contextTools.js';
26
26
  export { GRANTS_TOOLS, listGrantsTool } from './tier2/grantsTools.js';
27
- export { TASK_TOOLS, listTasksTool, cancelTaskTool } from './tier2/taskTools.js';
27
+ export { TASK_TOOLS, listTasksTool, cancelTaskTool, delegateTaskTool } from './tier2/taskTools.js';
28
28
  export { PLAN_TOOLS, taskReplacePlanTool } from './tier2/planTools.js';
29
29
  export { LINK_TOOLS, linkProposeTool, linkListTool, } from './tier2/linkTools.js';
30
30
  export { INTRODUCTION_TOOLS, introductionMintTool, introductionRedeemTool, introductionListTool, introductionRevokeTool, } from './tier2/introductionTools.js';
@@ -28,7 +28,7 @@ export { CONTEXT_TOOLS, contextReadTool, accessRequestTool, contextDelegateTool,
28
28
  // one grant lister across every rail (retires context_discover +
29
29
  // payment_list_grants). Always-available on the hosted agent — see CLAUDE_SDK_TOOLS.
30
30
  export { GRANTS_TOOLS, listGrantsTool } from './tier2/grantsTools.js';
31
- export { TASK_TOOLS, listTasksTool, cancelTaskTool } from './tier2/taskTools.js';
31
+ export { TASK_TOOLS, listTasksTool, cancelTaskTool, delegateTaskTool } from './tier2/taskTools.js';
32
32
  export { PLAN_TOOLS, taskReplacePlanTool } from './tier2/planTools.js';
33
33
  // links (agreements with engagementKind 'link') — cross-org reach.
34
34
  ///1022: the rail is two tools; propose/claim/revoke ride the
@@ -1,4 +1,5 @@
1
1
  import type { ToolDefinition } from '../../../tools/defineTool.js';
2
2
  export declare const listTasksTool: ToolDefinition;
3
+ export declare const delegateTaskTool: ToolDefinition;
3
4
  export declare const cancelTaskTool: ToolDefinition;
4
5
  export declare const TASK_TOOLS: ToolDefinition[];
@@ -1,7 +1,8 @@
1
- import { cancelTaskCapability, listTasksCapability, TASK_CAPABILITIES } from '@ziggs-ai/api-client';
1
+ import { delegateTaskCapability, cancelTaskCapability, listTasksCapability, TASK_CAPABILITIES } from '@ziggs-ai/api-client';
2
2
  import { toolFromCapability, toolsFromCapabilities } from '../../../tools/capabilityAdapter.js';
3
3
  // GET /tasks, defined once in api-client. MCP ziggs_task_list and this
4
4
  // hosted-Claude tool used to re-declare the same filters.
5
5
  export const listTasksTool = toolFromCapability(listTasksCapability);
6
+ export const delegateTaskTool = toolFromCapability(delegateTaskCapability);
6
7
  export const cancelTaskTool = toolFromCapability(cancelTaskCapability);
7
8
  export const TASK_TOOLS = toolsFromCapabilities(TASK_CAPABILITIES);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/agent-sdk",
3
- "version": "0.42.0",
3
+ "version": "0.42.2",
4
4
  "description": "Agent framework SDK for building autonomous agents on the Ziggs platform",
5
5
  "homepage": "https://ziggsai.com/docs",
6
6
  "bugs": {
@@ -30,8 +30,8 @@
30
30
  "@anthropic-ai/claude-agent-sdk": "^0.3.284",
31
31
  "@anthropic-ai/sdk": "^0.110.0",
32
32
  "@modelcontextprotocol/sdk": "^1.29.0",
33
- "@ziggs-ai/api-client": "0.38.0",
34
- "@ziggs-ai/contracts": "^0.32.0",
33
+ "@ziggs-ai/api-client": "0.38.2",
34
+ "@ziggs-ai/contracts": "^0.33.1",
35
35
  "ajv": "^8.17.1",
36
36
  "dotenv": "^17.2.3",
37
37
  "openai": "^4.0.0",