@sema-agent/core 2.3.0 → 2.5.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 (83) hide show
  1. package/dist/agents/send-message-tool.d.ts +4 -0
  2. package/dist/agents/send-message-tool.js +37 -24
  3. package/dist/agents/subagent.js +279 -128
  4. package/dist/brain/errors.d.ts +1 -0
  5. package/dist/brain/errors.js +14 -0
  6. package/dist/brain/stream-engine.js +3 -3
  7. package/dist/core/auto-compaction.d.ts +2 -0
  8. package/dist/core/auto-compaction.js +2 -1
  9. package/dist/core/context-edit.js +2 -1
  10. package/dist/core/mcp.js +4 -1
  11. package/dist/core/runner/prepare-task.d.ts +5 -0
  12. package/dist/core/runner/prepare-task.js +41 -2
  13. package/dist/core/runner/runtask.js +39 -9
  14. package/dist/core/runner/tool-disclosure.d.ts +1 -0
  15. package/dist/core/runner/tool-disclosure.js +16 -5
  16. package/dist/core/runner/tool-output-projection.js +2 -1
  17. package/dist/core/session-reconcile.d.ts +1 -0
  18. package/dist/core/session-reconcile.js +40 -20
  19. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +37 -0
  20. package/dist/core/store-contracts/checkpoint-store-contract.js +195 -0
  21. package/dist/core/store-contracts/contract-harness.d.ts +6 -0
  22. package/dist/core/store-contracts/contract-harness.js +16 -0
  23. package/dist/core/store-contracts/contract-kit-version.d.ts +1 -0
  24. package/dist/core/store-contracts/contract-kit-version.js +2 -0
  25. package/dist/core/store-contracts/file-snapshot-store-contract.d.ts +3 -0
  26. package/dist/core/store-contracts/file-snapshot-store-contract.js +126 -0
  27. package/dist/core/store-contracts/mailbox-store-contract.d.ts +6 -0
  28. package/dist/core/store-contracts/mailbox-store-contract.js +193 -0
  29. package/dist/core/store-contracts/session-repo-contract.d.ts +3 -0
  30. package/dist/core/store-contracts/session-repo-contract.js +36 -0
  31. package/dist/core/store-contracts/tool-result-store-contract.d.ts +3 -0
  32. package/dist/core/store-contracts/tool-result-store-contract.js +35 -0
  33. package/dist/core/task-notification.d.ts +2 -0
  34. package/dist/core/task-registry-agent.d.ts +6 -0
  35. package/dist/core/task-registry-agent.js +24 -1
  36. package/dist/core/task-registry-monitor.js +6 -6
  37. package/dist/core/task-registry-shared.d.ts +9 -2
  38. package/dist/core/task-registry-shared.js +1 -1
  39. package/dist/core/task-registry.d.ts +8 -0
  40. package/dist/core/task-registry.js +59 -4
  41. package/dist/core/tool-result-store.d.ts +3 -2
  42. package/dist/core/tool-result-store.js +12 -4
  43. package/dist/core/trace.d.ts +7 -0
  44. package/dist/core/types.d.ts +10 -3
  45. package/dist/engine/compaction/compaction.d.ts +5 -0
  46. package/dist/engine/compaction/compaction.js +68 -2
  47. package/dist/engine/compaction/utils.d.ts +6 -0
  48. package/dist/engine/compaction/utils.js +53 -3
  49. package/dist/engine/harness/messages.d.ts +1 -1
  50. package/dist/engine/harness/messages.js +11 -3
  51. package/dist/engine/loop/types.d.ts +2 -0
  52. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -0
  53. package/dist/engine/lsp/node-lsp-manager.js +16 -0
  54. package/dist/engine/session/import-validate.js +30 -1
  55. package/dist/engine/session/session.js +7 -5
  56. package/dist/index.d.ts +8 -0
  57. package/dist/index.js +8 -0
  58. package/dist/internal/harness.d.ts +1 -1
  59. package/dist/internal/harness.js +1 -1
  60. package/dist/orchestration/builtin-workflows.d.ts +1 -1
  61. package/dist/orchestration/builtin-workflows.js +11 -2
  62. package/dist/orchestration/workflow-governance.d.ts +6 -1
  63. package/dist/orchestration/workflow-governance.js +24 -4
  64. package/dist/orchestration/workflow-primitives.js +7 -1
  65. package/dist/orchestration/workflow-types.d.ts +1 -0
  66. package/dist/orchestration/workflow.d.ts +1 -0
  67. package/dist/orchestration/workflow.js +41 -3
  68. package/dist/tools/fs/fs-bash.d.ts +7 -1
  69. package/dist/tools/fs/fs-bash.js +59 -22
  70. package/dist/tools/fs/fs-read.js +22 -11
  71. package/dist/tools/fs/fs-search-tools.js +3 -3
  72. package/dist/tools/fs/fs-shared.d.ts +20 -7
  73. package/dist/tools/fs/fs-shared.js +17 -3
  74. package/dist/tools/fs/fs-write.js +4 -4
  75. package/dist/tools/fs/index.d.ts +2 -0
  76. package/dist/tools/fs/index.js +7 -1
  77. package/dist/tools/fs/repo-map.js +2 -2
  78. package/dist/tools/fs/safety.d.ts +10 -0
  79. package/dist/tools/fs/safety.js +15 -1
  80. package/dist/tools/monitor.js +18 -4
  81. package/dist/tools/web.js +6 -2
  82. package/dist/tools/worktree.js +46 -25
  83. package/package.json +1 -1
@@ -21,6 +21,8 @@ export interface SendMessageToolOptions {
21
21
  senderName?: string;
22
22
  roster?: import("./roster-store.js").RosterStore;
23
23
  siblingRetain?: SubagentRetainLedger;
24
+ parentTaskId?: string;
25
+ parentSessionId?: string;
24
26
  onBackgroundChildEvent?: (event: import("../core/types.js").BackgroundChildEvent) => void;
25
27
  agentStore?: import("../core/background-agent-store.js").BackgroundAgentStore;
26
28
  mailbox?: import("../core/mailbox-store.js").MailboxStore;
@@ -34,6 +36,8 @@ export interface SendMessageToolOptions {
34
36
  details?: unknown;
35
37
  }>;
36
38
  }
39
+ export declare const SEND_MESSAGE_SUMMARY_MAX = 200;
40
+ export declare function clipSendMessageSummary(raw: string): string;
37
41
  export declare function createSendMessageTool(opts: SendMessageToolOptions): import("../core/types.js").AgentTool<Type.TObject<{
38
42
  to: Type.TString;
39
43
  message: Type.TString;
@@ -8,6 +8,12 @@ import { createSubagentResume } from "./subagent.js";
8
8
  export const SEND_MESSAGE_TOOL_NAME = "SendMessage";
9
9
  let uplinkSeqGlobal = Date.now();
10
10
  const UPLINK_RESULT_MAX = 8000;
11
+ export const SEND_MESSAGE_SUMMARY_MAX = 200;
12
+ export function clipSendMessageSummary(raw) {
13
+ return raw.length > SEND_MESSAGE_SUMMARY_MAX
14
+ ? `${raw.slice(0, SEND_MESSAGE_SUMMARY_MAX)} [summary truncated: ${raw.length} chars total]`
15
+ : raw;
16
+ }
11
17
  const TEAMMATE_MESSAGE_TAG = "teammate-message";
12
18
  function frameTeammateMessage(args) {
13
19
  const summaryAttr = args.summary !== undefined ? ` summary="${escapeAttributeValue(args.summary)}"` : "";
@@ -84,6 +90,9 @@ export function createSendMessageTool(opts) {
84
90
  };
85
91
  }
86
92
  const senderId = ctx.taskId ?? opts.owner;
93
+ const [parentTaskId, parentSessionId] = ctx.parentTaskId !== undefined ? [ctx.parentTaskId, ctx.parentSessionId] : [opts.parentTaskId, opts.parentSessionId];
94
+ const senderIsChild = parentTaskId !== undefined || opts.uplink !== undefined || opts.senderName !== undefined || opts.siblingRetain !== undefined;
95
+ const senderLabel = opts.senderName ?? (senderIsChild ? senderId ?? "main" : "main");
87
96
  if (senderId !== undefined && isObserverTaskId(senderId)) {
88
97
  return { content: OBSERVER_SENDMESSAGE_SENDER_REFUSAL, details: { error: "observer_sender" }, isError: true };
89
98
  }
@@ -92,7 +101,7 @@ export function createSendMessageTool(opts) {
92
101
  }
93
102
  if (normalizeAgentName(to) === "main") {
94
103
  if (opts.uplink && senderId !== undefined) {
95
- const uplinkSummaryRaw = typeof a.summary === "string" && a.summary.trim() !== "" ? a.summary.trim().slice(0, 200) : message.slice(0, 80);
104
+ const uplinkSummaryRaw = typeof a.summary === "string" && a.summary.trim() !== "" ? clipSendMessageSummary(a.summary.trim()) : message.slice(0, 80);
96
105
  const fromLabel = opts.senderName !== undefined ? opts.senderName : senderId;
97
106
  try {
98
107
  opts.uplink({
@@ -112,11 +121,7 @@ export function createSendMessageTool(opts) {
112
121
  details: { type: "send-message", status: "uplinked", to: "main", seq: uplinkSeqGlobal },
113
122
  };
114
123
  }
115
- const hasParent = ctx.parentTaskId !== undefined ||
116
- opts.uplink !== undefined ||
117
- opts.senderName !== undefined ||
118
- opts.siblingRetain !== undefined;
119
- if (!hasParent) {
124
+ if (!senderIsChild) {
120
125
  return {
121
126
  content: `You are the main conversation — "main" addresses you. Send to a named agent instead.`,
122
127
  details: { error: "main_is_self", to },
@@ -151,9 +156,9 @@ export function createSendMessageTool(opts) {
151
156
  if (!row)
152
157
  return undefined;
153
158
  if (!canAccessAgentRecord(row, access)) {
154
- if (ctx.parentTaskId === undefined)
159
+ if (parentTaskId === undefined)
155
160
  return undefined;
156
- const parentView = { ...access, owner: ctx.parentTaskId, ...(ctx.parentSessionId !== undefined ? { sessionId: ctx.parentSessionId } : {}) };
161
+ const parentView = { ...access, owner: parentTaskId, ...(parentSessionId !== undefined ? { sessionId: parentSessionId } : {}) };
157
162
  if (!canAccessAgentRecord(row, parentView))
158
163
  return undefined;
159
164
  }
@@ -271,10 +276,10 @@ export function createSendMessageTool(opts) {
271
276
  };
272
277
  }
273
278
  const clipped = message.length > UPLINK_RESULT_MAX ? `${message.slice(0, UPLINK_RESULT_MAX)}\n[message truncated: ${message.length} chars total]` : message;
274
- const t3Summary = typeof a.summary === "string" && a.summary.trim() !== "" ? a.summary.trim().slice(0, 200) : undefined;
275
- const t3From = opts.senderName ?? senderId;
279
+ const t3Summary = typeof a.summary === "string" && a.summary.trim() !== "" ? clipSendMessageSummary(a.summary.trim()) : undefined;
280
+ const t3From = senderLabel;
276
281
  try {
277
- await opts.mailbox.append(scope, handle, { ...(t3From !== undefined ? { from: t3From } : {}), content: t3Summary !== undefined ? `[${t3Summary}] ${clipped}` : clipped, sentAt: now });
282
+ await opts.mailbox.append(scope, handle, { from: t3From, content: t3Summary !== undefined ? `[${t3Summary}] ${clipped}` : clipped, sentAt: now });
278
283
  }
279
284
  catch (e) {
280
285
  await rollback();
@@ -340,8 +345,8 @@ export function createSendMessageTool(opts) {
340
345
  };
341
346
  let idRow = opts.registry.getAccessibleTask(to, access);
342
347
  let resolvedAccess = access;
343
- if (!idRow && ctx.parentTaskId !== undefined) {
344
- const parentView = { ...access, owner: ctx.parentTaskId, ...(ctx.parentSessionId !== undefined ? { sessionId: ctx.parentSessionId } : {}) };
348
+ if (!idRow && parentTaskId !== undefined) {
349
+ const parentView = { ...access, owner: parentTaskId, ...(parentSessionId !== undefined ? { sessionId: parentSessionId } : {}) };
345
350
  const siblingById = opts.registry.getAccessibleTask(to, parentView);
346
351
  if (siblingById) {
347
352
  idRow = siblingById;
@@ -356,8 +361,8 @@ export function createSendMessageTool(opts) {
356
361
  let target = idRow;
357
362
  if (!target) {
358
363
  let byName = opts.registry.resolveBackgroundAgentByName(to, access);
359
- if (byName.status === "not_found" && ctx.parentTaskId !== undefined) {
360
- const parentView = { ...access, owner: ctx.parentTaskId, ...(ctx.parentSessionId !== undefined ? { sessionId: ctx.parentSessionId } : {}) };
364
+ if (byName.status === "not_found" && parentTaskId !== undefined) {
365
+ const parentView = { ...access, owner: parentTaskId, ...(parentSessionId !== undefined ? { sessionId: parentSessionId } : {}) };
361
366
  const sibling = opts.registry.resolveBackgroundAgentByName(to, parentView);
362
367
  if (sibling.status === "found" || sibling.status === "ambiguous") {
363
368
  byName = sibling;
@@ -412,8 +417,8 @@ export function createSendMessageTool(opts) {
412
417
  }
413
418
  if (row.status === "running" || row.status === "pending") {
414
419
  return await withTargetLane(targetLaneKey(access.scope, targetId), async () => {
415
- const s2Summary = typeof a.summary === "string" && a.summary.trim() !== "" ? a.summary.trim().slice(0, 200) : undefined;
416
- const fromLabel = opts.senderName ?? senderId ?? "main";
420
+ const s2Summary = typeof a.summary === "string" && a.summary.trim() !== "" ? clipSendMessageSummary(a.summary.trim()) : undefined;
421
+ const fromLabel = senderLabel;
417
422
  const s2Clipped = message.length > UPLINK_RESULT_MAX
418
423
  ? `${message.slice(0, UPLINK_RESULT_MAX)}\n[message truncated: ${message.length} chars total]`
419
424
  : message;
@@ -444,11 +449,19 @@ export function createSendMessageTool(opts) {
444
449
  isError: true,
445
450
  };
446
451
  }
447
- return {
448
- content: `Message not sent: ${who} just finished (delivery raced its completion). Send again to continue it from its transcript.`,
449
- details: { error: "settle_race", to },
450
- isError: true,
451
- };
452
+ const nowRow = opts.registry.getAccessibleTask(targetId, resolvedAccess);
453
+ const stillLive = nowRow !== undefined && (nowRow.status === "running" || nowRow.status === "pending");
454
+ return stillLive
455
+ ? {
456
+ content: `Message not sent: ${who} is still starting up (it has not begun reading messages yet) — the message was not delivered. Send again shortly.`,
457
+ details: { error: "settle_race", to },
458
+ isError: true,
459
+ }
460
+ : {
461
+ content: `Message not sent: ${who} just finished (delivery raced its completion). Send again to continue it from its transcript.`,
462
+ details: { error: "settle_race", to },
463
+ isError: true,
464
+ };
452
465
  });
453
466
  }
454
467
  if (row.status === "killed") {
@@ -510,8 +523,8 @@ export function createSendMessageTool(opts) {
510
523
  ...(row.rootSessionId !== undefined ? { rowRootSessionId: row.rootSessionId } : {}),
511
524
  ...(opts.notify ? { currentParentNotify: opts.notify } : {}),
512
525
  });
513
- const summary = typeof a.summary === "string" && a.summary.trim() !== "" ? a.summary.trim().slice(0, 200) : undefined;
514
- const fromPrefix = ctx.parentTaskId !== undefined ? `(message from teammate "${opts.senderName ?? senderId ?? "unknown"}")\n` : "";
526
+ const summary = typeof a.summary === "string" && a.summary.trim() !== "" ? clipSendMessageSummary(a.summary.trim()) : undefined;
527
+ const fromPrefix = parentTaskId !== undefined ? `(message from teammate "${opts.senderName ?? senderId ?? "unknown"}")\n` : "";
515
528
  try {
516
529
  const safeSummary = summary !== undefined ? escapeEnvelopeTag(TEAMMATE_MESSAGE_TAG, summary) : undefined;
517
530
  const safeMessage = escapeEnvelopeTag(TEAMMATE_MESSAGE_TAG, message);