@jungjaehoon/mama-os 0.24.2 → 0.26.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 (160) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +46 -23
  3. package/dist/agent/agent-loop.d.ts.map +1 -1
  4. package/dist/agent/agent-loop.js +10 -0
  5. package/dist/agent/agent-loop.js.map +1 -1
  6. package/dist/agent/code-act/constants.js +2 -2
  7. package/dist/agent/code-act/host-bridge.d.ts.map +1 -1
  8. package/dist/agent/code-act/host-bridge.js +91 -4
  9. package/dist/agent/code-act/host-bridge.js.map +1 -1
  10. package/dist/agent/code-act/tool-policy.d.ts +3 -1
  11. package/dist/agent/code-act/tool-policy.d.ts.map +1 -1
  12. package/dist/agent/code-act/tool-policy.js +3 -1
  13. package/dist/agent/code-act/tool-policy.js.map +1 -1
  14. package/dist/agent/code-act/type-definition-generator.d.ts.map +1 -1
  15. package/dist/agent/code-act/type-definition-generator.js +2 -4
  16. package/dist/agent/code-act/type-definition-generator.js.map +1 -1
  17. package/dist/agent/context-compile-service.d.ts +2 -0
  18. package/dist/agent/context-compile-service.d.ts.map +1 -1
  19. package/dist/agent/context-compile-service.js +26 -7
  20. package/dist/agent/context-compile-service.js.map +1 -1
  21. package/dist/agent/drive-tools.d.ts +53 -0
  22. package/dist/agent/drive-tools.d.ts.map +1 -0
  23. package/dist/agent/drive-tools.js +261 -0
  24. package/dist/agent/drive-tools.js.map +1 -0
  25. package/dist/agent/gateway-tool-executor.d.ts +3 -0
  26. package/dist/agent/gateway-tool-executor.d.ts.map +1 -1
  27. package/dist/agent/gateway-tool-executor.js +362 -19
  28. package/dist/agent/gateway-tool-executor.js.map +1 -1
  29. package/dist/agent/gateway-tools.md +9 -3
  30. package/dist/agent/tool-registry.d.ts.map +1 -1
  31. package/dist/agent/tool-registry.js +38 -3
  32. package/dist/agent/tool-registry.js.map +1 -1
  33. package/dist/agent/types.d.ts +45 -6
  34. package/dist/agent/types.d.ts.map +1 -1
  35. package/dist/agent/types.js.map +1 -1
  36. package/dist/api/operator-tasks-handler.d.ts.map +1 -1
  37. package/dist/api/operator-tasks-handler.js +23 -1
  38. package/dist/api/operator-tasks-handler.js.map +1 -1
  39. package/dist/cli/commands/start.d.ts +7 -3
  40. package/dist/cli/commands/start.d.ts.map +1 -1
  41. package/dist/cli/commands/start.js +113 -65
  42. package/dist/cli/commands/start.js.map +1 -1
  43. package/dist/cli/config/types.d.ts.map +1 -1
  44. package/dist/cli/config/types.js +7 -3
  45. package/dist/cli/config/types.js.map +1 -1
  46. package/dist/cli/runtime/agent-loop-init.d.ts +2 -0
  47. package/dist/cli/runtime/agent-loop-init.d.ts.map +1 -1
  48. package/dist/cli/runtime/agent-loop-init.js +37 -12
  49. package/dist/cli/runtime/agent-loop-init.js.map +1 -1
  50. package/dist/cli/runtime/api-routes-init.js +3 -3
  51. package/dist/cli/runtime/api-routes-init.js.map +1 -1
  52. package/dist/cli/runtime/envelope-bootstrap.d.ts.map +1 -1
  53. package/dist/cli/runtime/envelope-bootstrap.js +8 -1
  54. package/dist/cli/runtime/envelope-bootstrap.js.map +1 -1
  55. package/dist/cli/runtime/temporal-init.d.ts +28 -0
  56. package/dist/cli/runtime/temporal-init.d.ts.map +1 -0
  57. package/dist/cli/runtime/temporal-init.js +74 -0
  58. package/dist/cli/runtime/temporal-init.js.map +1 -0
  59. package/dist/connectors/drive/index.d.ts +1 -1
  60. package/dist/connectors/drive/index.d.ts.map +1 -1
  61. package/dist/connectors/drive/index.js +100 -56
  62. package/dist/connectors/drive/index.js.map +1 -1
  63. package/dist/connectors/framework/gws-utils.d.ts +3 -0
  64. package/dist/connectors/framework/gws-utils.d.ts.map +1 -1
  65. package/dist/connectors/framework/gws-utils.js +17 -0
  66. package/dist/connectors/framework/gws-utils.js.map +1 -1
  67. package/dist/db/migrations/operator-task-temporal.d.ts +8 -0
  68. package/dist/db/migrations/operator-task-temporal.d.ts.map +1 -0
  69. package/dist/db/migrations/operator-task-temporal.js +209 -0
  70. package/dist/db/migrations/operator-task-temporal.js.map +1 -0
  71. package/dist/envelope/enforcer.d.ts.map +1 -1
  72. package/dist/envelope/enforcer.js +24 -9
  73. package/dist/envelope/enforcer.js.map +1 -1
  74. package/dist/envelope/reactive-config.d.ts +1 -1
  75. package/dist/envelope/reactive-config.d.ts.map +1 -1
  76. package/dist/envelope/reactive-config.js +10 -2
  77. package/dist/envelope/reactive-config.js.map +1 -1
  78. package/dist/envelope/types.d.ts +1 -1
  79. package/dist/envelope/types.d.ts.map +1 -1
  80. package/dist/envelope/types.js.map +1 -1
  81. package/dist/gateways/message-router.d.ts +1 -0
  82. package/dist/gateways/message-router.d.ts.map +1 -1
  83. package/dist/gateways/message-router.js +7 -1
  84. package/dist/gateways/message-router.js.map +1 -1
  85. package/dist/gateways/telegram-media.d.ts +28 -0
  86. package/dist/gateways/telegram-media.d.ts.map +1 -0
  87. package/dist/gateways/telegram-media.js +165 -0
  88. package/dist/gateways/telegram-media.js.map +1 -0
  89. package/dist/gateways/telegram-response-presenter.d.ts +31 -0
  90. package/dist/gateways/telegram-response-presenter.d.ts.map +1 -0
  91. package/dist/gateways/telegram-response-presenter.js +153 -0
  92. package/dist/gateways/telegram-response-presenter.js.map +1 -0
  93. package/dist/gateways/telegram.d.ts +10 -3
  94. package/dist/gateways/telegram.d.ts.map +1 -1
  95. package/dist/gateways/telegram.js +174 -90
  96. package/dist/gateways/telegram.js.map +1 -1
  97. package/dist/gateways/types.d.ts +4 -2
  98. package/dist/gateways/types.d.ts.map +1 -1
  99. package/dist/multi-agent/dashboard-agent-persona.d.ts.map +1 -1
  100. package/dist/multi-agent/dashboard-agent-persona.js +9 -4
  101. package/dist/multi-agent/dashboard-agent-persona.js.map +1 -1
  102. package/dist/operator/action-verifier.d.ts +23 -0
  103. package/dist/operator/action-verifier.d.ts.map +1 -1
  104. package/dist/operator/action-verifier.js +76 -0
  105. package/dist/operator/action-verifier.js.map +1 -1
  106. package/dist/operator/board-reconcile.d.ts.map +1 -1
  107. package/dist/operator/board-reconcile.js +3 -0
  108. package/dist/operator/board-reconcile.js.map +1 -1
  109. package/dist/operator/board-slot-instructions.d.ts +3 -3
  110. package/dist/operator/board-slot-instructions.d.ts.map +1 -1
  111. package/dist/operator/board-slot-instructions.js +17 -8
  112. package/dist/operator/board-slot-instructions.js.map +1 -1
  113. package/dist/operator/briefs.d.ts.map +1 -1
  114. package/dist/operator/briefs.js +3 -0
  115. package/dist/operator/briefs.js.map +1 -1
  116. package/dist/operator/task-ledger.d.ts +134 -8
  117. package/dist/operator/task-ledger.d.ts.map +1 -1
  118. package/dist/operator/task-ledger.js +1166 -65
  119. package/dist/operator/task-ledger.js.map +1 -1
  120. package/dist/operator/task-temporal.d.ts +21 -0
  121. package/dist/operator/task-temporal.d.ts.map +1 -0
  122. package/dist/operator/task-temporal.js +111 -0
  123. package/dist/operator/task-temporal.js.map +1 -0
  124. package/dist/operator/temporal-effect.d.ts +62 -0
  125. package/dist/operator/temporal-effect.d.ts.map +1 -0
  126. package/dist/operator/temporal-effect.js +71 -0
  127. package/dist/operator/temporal-effect.js.map +1 -0
  128. package/dist/operator/temporal-reconcile.d.ts +48 -0
  129. package/dist/operator/temporal-reconcile.d.ts.map +1 -0
  130. package/dist/operator/temporal-reconcile.js +215 -0
  131. package/dist/operator/temporal-reconcile.js.map +1 -0
  132. package/dist/operator/temporal-runtime.d.ts +54 -0
  133. package/dist/operator/temporal-runtime.d.ts.map +1 -0
  134. package/dist/operator/temporal-runtime.js +110 -0
  135. package/dist/operator/temporal-runtime.js.map +1 -0
  136. package/dist/operator/temporal-worker.d.ts +19 -0
  137. package/dist/operator/temporal-worker.d.ts.map +1 -0
  138. package/dist/operator/temporal-worker.js +105 -0
  139. package/dist/operator/temporal-worker.js.map +1 -0
  140. package/dist/operator/worker-run.d.ts +6 -2
  141. package/dist/operator/worker-run.d.ts.map +1 -1
  142. package/dist/operator/worker-run.js +14 -0
  143. package/dist/operator/worker-run.js.map +1 -1
  144. package/dist/operator/workorder-consumer.d.ts +27 -10
  145. package/dist/operator/workorder-consumer.d.ts.map +1 -1
  146. package/dist/operator/workorder-consumer.js +195 -14
  147. package/dist/operator/workorder-consumer.js.map +1 -1
  148. package/dist/operator/workorder-hooks.d.ts +3 -0
  149. package/dist/operator/workorder-hooks.d.ts.map +1 -1
  150. package/dist/operator/workorder-hooks.js +23 -0
  151. package/dist/operator/workorder-hooks.js.map +1 -1
  152. package/dist/operator/workorder-publishers.d.ts +10 -1
  153. package/dist/operator/workorder-publishers.d.ts.map +1 -1
  154. package/dist/operator/workorder-publishers.js +40 -3
  155. package/dist/operator/workorder-publishers.js.map +1 -1
  156. package/package.json +1 -1
  157. package/public/ui/assets/{index-OSgiwL24.js → index-BDXDGEV6.js} +15 -15
  158. package/public/ui/assets/index-po2tN0xq.css +1 -0
  159. package/public/ui/index.html +2 -2
  160. package/public/ui/assets/index-CKOJQYXA.css +0 -1
@@ -61,6 +61,8 @@ const mama_core_1 = require("@jungjaehoon/mama-core");
61
61
  const security_monitor_js_1 = require("../security/security-monitor.js");
62
62
  const secret_filter_js_1 = require("../memory/secret-filter.js");
63
63
  const scope_context_js_1 = require("../memory/scope-context.js");
64
+ const drive_tools_js_1 = require("./drive-tools.js");
65
+ const untrusted_content_js_1 = require("../utils/untrusted-content.js");
64
66
  const types_js_1 = require("./types.js");
65
67
  const sqlite_js_1 = __importDefault(require("../sqlite.js"));
66
68
  const mama_tool_handlers_js_1 = require("./mama-tool-handlers.js");
@@ -74,6 +76,61 @@ const managed_agent_validation_js_1 = require("./managed-agent-validation.js");
74
76
  const delegation_executor_js_1 = require("./delegation-executor.js");
75
77
  const index_js_1 = require("../envelope/index.js");
76
78
  const wiki_publish_adapter_js_1 = require("../wiki-artifacts/wiki-publish-adapter.js");
79
+ function serializeTaskToolRecord(task) {
80
+ return {
81
+ ...task,
82
+ due_at: task.dueAt === null ? null : new Date(task.dueAt).toISOString(),
83
+ deadline_offset_minutes: task.deadlineOffsetMinutes,
84
+ temporal_epoch: task.temporalEpoch,
85
+ temporal_reconciled_occurrence_key: task.temporalReconciledOccurrenceKey,
86
+ last_temporal_checked_at: task.lastTemporalCheckedAt,
87
+ next_temporal_check_at: task.nextTemporalCheckAt,
88
+ last_temporal_attempt_id: task.lastTemporalAttemptId,
89
+ temporal_state: task.temporalState,
90
+ };
91
+ }
92
+ function temporalContextPacketBinding(context) {
93
+ return `temporal:${context.taskId}:${context.generationKey}`;
94
+ }
95
+ function bindTemporalContextPacketTask(context, task) {
96
+ if (typeof task !== 'string' || task.trim().length === 0) {
97
+ const error = new Error('task is required.');
98
+ error.code = 'context_compile_input_invalid';
99
+ throw error;
100
+ }
101
+ return `${temporalContextPacketBinding(context)}\n${task}`;
102
+ }
103
+ function temporalIdentifierRef(value) {
104
+ return `sha256:${(0, crypto_1.createHash)('sha256').update(value).digest('hex')}`;
105
+ }
106
+ function temporalPacketRawSourcesWithinBoundSource(context, sourceRefs) {
107
+ const rawRefs = sourceRefs.filter((value) => typeof value === 'object' &&
108
+ value !== null &&
109
+ !Array.isArray(value) &&
110
+ value.kind === 'raw');
111
+ if (!context.sourceChannel) {
112
+ return rawRefs.length === 0;
113
+ }
114
+ return rawRefs.every((ref) => {
115
+ const eventMatches = !context.sourceEventId ||
116
+ [ref.raw_id, ref.source_id].some((value) => typeof value === 'string' && temporalIdentifierRef(value) === context.sourceEventId);
117
+ const channelMatches = !context.sourceChannel ||
118
+ (typeof ref.connector === 'string' &&
119
+ typeof ref.channel_id === 'string' &&
120
+ temporalIdentifierRef(`${ref.connector}:${ref.channel_id}`) === context.sourceChannel);
121
+ return eventMatches && channelMatches;
122
+ });
123
+ }
124
+ function temporalPacketReferencesBoundSource(context, sourceRefs) {
125
+ const hasRawReference = sourceRefs.some((value) => typeof value === 'object' &&
126
+ value !== null &&
127
+ !Array.isArray(value) &&
128
+ value.kind === 'raw');
129
+ if (context.sourceEventId || context.sourceChannel) {
130
+ return hasRawReference && temporalPacketRawSourcesWithinBoundSource(context, sourceRefs);
131
+ }
132
+ return temporalPacketRawSourcesWithinBoundSource(context, sourceRefs);
133
+ }
77
134
  const { DebugLogger } = debugLogger;
78
135
  const securityLogger = new DebugLogger('SecurityAudit');
79
136
  const TRUTHY_ENV_VALUES = new Set(['1', 'true', 'yes', 'on']);
@@ -114,6 +171,48 @@ const MEMORY_SCOPE_AUDIT_TOOLS = new Set([
114
171
  'mama_add',
115
172
  'mama_ingest',
116
173
  ]);
174
+ const TEMPORAL_WRITE_TOOLS = new Set([
175
+ 'mama_save',
176
+ 'context_compile',
177
+ 'mama_update',
178
+ 'mama_add',
179
+ 'mama_ingest',
180
+ 'report_publish',
181
+ 'report_request',
182
+ 'workorder_request',
183
+ 'wiki_publish',
184
+ 'obsidian',
185
+ 'task_create',
186
+ 'task_update',
187
+ 'contract_no_update',
188
+ 'task_temporal_reconcile',
189
+ 'Write',
190
+ 'Bash',
191
+ 'discord_send',
192
+ 'slack_send',
193
+ 'telegram_send',
194
+ 'webchat_send',
195
+ 'delegate',
196
+ 'os_add_bot',
197
+ 'os_set_permissions',
198
+ 'os_set_model',
199
+ 'os_restart_bot',
200
+ 'os_stop_bot',
201
+ 'agent_update',
202
+ 'agent_create',
203
+ 'viewer_navigate',
204
+ 'viewer_notify',
205
+ 'save_integration_token',
206
+ 'browser_navigate',
207
+ 'browser_screenshot',
208
+ 'browser_click',
209
+ 'browser_type',
210
+ 'browser_scroll',
211
+ 'browser_evaluate',
212
+ 'browser_pdf',
213
+ 'browser_close',
214
+ 'agent_test',
215
+ ]);
117
216
  const MEMORY_READ_PERMISSION_BEFORE_ENVELOPE_TOOLS = new Set([
118
217
  'mama_save',
119
218
  'mama_search',
@@ -271,6 +370,7 @@ const VALID_TOOLS = tool_registry_js_1.ToolRegistry.getValidToolNames();
271
370
  const SENSITIVE_KEYS = ['token', 'bot_token', 'app_token', 'api_token', 'api_key', 'secret'];
272
371
  const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
273
372
  class GatewayToolExecutor {
373
+ driveTools = new drive_tools_js_1.DriveToolService();
274
374
  mamaApi = null;
275
375
  mamaDbPath;
276
376
  sessionStore;
@@ -284,6 +384,7 @@ class GatewayToolExecutor {
284
384
  envelopeIssuanceMode;
285
385
  metricsStore;
286
386
  contextCompileService;
387
+ temporalContextPacketLookup;
287
388
  currentContext = null;
288
389
  memoryAgentProcessManager = null;
289
390
  agentProcessManager = null;
@@ -378,6 +479,8 @@ class GatewayToolExecutor {
378
479
  sourceMessageRef: executionContext?.sourceMessageRef,
379
480
  modelRunId: executionContext?.modelRunId ?? null,
380
481
  gatewayCallId: executionContext?.gatewayCallId,
482
+ workorderAttemptId: executionContext?.workorderAttemptId,
483
+ temporalWorkContext: executionContext?.temporalWorkContext,
381
484
  signal: executionContext?.signal,
382
485
  parentToolName: executionContext?.parentToolName,
383
486
  backgroundTasks: executionContext?.backgroundTasks,
@@ -412,6 +515,10 @@ class GatewayToolExecutor {
412
515
  sourceMessageRef: active.sourceMessageRef ?? fallback.sourceMessageRef,
413
516
  modelRunId: active.modelRunId ?? fallback.modelRunId,
414
517
  gatewayCallId: active.gatewayCallId ?? fallback.gatewayCallId,
518
+ // Never merged from fallback - attempt identity is issued for one claimed run only.
519
+ workorderAttemptId: active.workorderAttemptId,
520
+ // Never merged from fallback - temporal authority belongs to one claimed run only.
521
+ temporalWorkContext: active.temporalWorkContext,
415
522
  signal: active.signal,
416
523
  parentToolName: active.parentToolName ?? fallback.parentToolName,
417
524
  backgroundTasks: active.backgroundTasks ?? fallback.backgroundTasks,
@@ -448,6 +555,23 @@ class GatewayToolExecutor {
448
555
  const activeContext = this.normalizeExecutionContext(executionContext);
449
556
  return this.executionContextStorage.run(activeContext, fn);
450
557
  }
558
+ requireActiveTemporalAuthority(toolName) {
559
+ const context = this.getExecutionState().temporalWorkContext;
560
+ if (toolName === 'task_temporal_reconcile' && !context) {
561
+ throw new types_js_1.AgentError('task_temporal_reconcile requires an active host-issued temporal work context', 'WORKORDER_SUPERSEDED', undefined, false);
562
+ }
563
+ if (!context)
564
+ return null;
565
+ if (!this.taskLedger) {
566
+ throw new types_js_1.AgentError('Temporal work authority cannot be checked because the task ledger is unavailable', 'WORKORDER_SUPERSEDED', undefined, false);
567
+ }
568
+ try {
569
+ return this.taskLedger.assertTemporalWorkContextActive(context);
570
+ }
571
+ catch {
572
+ throw new types_js_1.AgentError('Temporal workorder authority is no longer active', 'WORKORDER_SUPERSEDED', undefined, false);
573
+ }
574
+ }
451
575
  setCurrentAgentContext(agentId, source, channelId) {
452
576
  this.currentAgentId = agentId;
453
577
  this.currentSource = source;
@@ -599,6 +723,20 @@ class GatewayToolExecutor {
599
723
  this.envelopeIssuanceMode = options.envelopeIssuanceMode ?? 'enabled';
600
724
  this.metricsStore = options.metricsStore ?? null;
601
725
  this.contextCompileService = options.contextCompileService;
726
+ this.temporalContextPacketLookup =
727
+ options.temporalContextPacketLookup ??
728
+ (async (input) => {
729
+ const packet = (0, mama_core_1.getContextPacketForTrustedUse)(await getContextPacketLookupAdapter(), input);
730
+ if (!packet)
731
+ return null;
732
+ return {
733
+ packet_id: packet.packet_id,
734
+ task: packet.task,
735
+ packet_json: packet.packet_json,
736
+ source_refs: packet.source_refs,
737
+ created_at: packet.created_at,
738
+ };
739
+ });
602
740
  this.wikiPublishAdapter = options.wikiPublishAdapter ?? null;
603
741
  this.browserTool = (0, browser_tool_js_1.getBrowserTool)({
604
742
  screenshotDir: (0, path_1.join)(process.env.HOME || '', '.mama', 'workspace', 'media', 'outbound'),
@@ -798,10 +936,8 @@ class GatewayToolExecutor {
798
936
  this.logEnvelopeActivity(ctx, 'envelope_violation', toolName, err.message);
799
937
  const denial = {
800
938
  success: false,
801
- error: err.message,
939
+ error: `[${err.code}] Envelope policy denied this tool call`,
802
940
  code: err.code,
803
- envelope_hash: ctx.envelope.envelope_hash,
804
- ...err.metadata,
805
941
  };
806
942
  return denial;
807
943
  }
@@ -893,43 +1029,79 @@ class GatewayToolExecutor {
893
1029
  const gatewayCallId = baseCtx.gatewayCallId ?? `gw_${(0, crypto_1.randomUUID)().replace(/-/g, '')}`;
894
1030
  const ctx = { ...baseCtx, gatewayCallId };
895
1031
  const effectiveInput = this.applyEnvelopeScopedReadDefaults(toolName, input, ctx);
896
- const scopeAudit = this.computeScopeAuditFields(toolName, effectiveInput, ctx);
1032
+ const computedScopeAudit = this.computeScopeAuditFields(toolName, effectiveInput, ctx);
1033
+ const scopeAudit = ctx.temporalWorkContext
1034
+ ? {
1035
+ requestedScopes: null,
1036
+ envelopeScopesSnapshot: null,
1037
+ mismatch: computedScopeAudit.mismatch,
1038
+ }
1039
+ : {
1040
+ ...computedScopeAudit,
1041
+ requestedScopes: digestRequestedScopesForAudit(computedScopeAudit.requestedScopes),
1042
+ };
1043
+ if (ctx.temporalWorkContext && TEMPORAL_WRITE_TOOLS.has(toolName)) {
1044
+ await this.executionContextStorage.run(ctx, async () => {
1045
+ this.requireActiveTemporalAuthority(toolName);
1046
+ });
1047
+ }
897
1048
  const traceState = await this.beginTraceIfNeeded(ctx, gatewayCallId);
898
1049
  const activeCtx = traceState ? { ...ctx, modelRunId: traceState.modelRunId } : ctx;
899
1050
  let result;
1051
+ let auditResult;
900
1052
  try {
901
- result = await this.executionContextStorage.run(activeCtx, () => this.executeWithEnvelopeAndPermissions(toolName, effectiveInput, gatewayCallId));
1053
+ const rawResult = await this.executionContextStorage.run(activeCtx, () => this.executeWithEnvelopeAndPermissions(toolName, effectiveInput, gatewayCallId));
1054
+ if (activeCtx.temporalWorkContext &&
1055
+ toolName !== 'task_temporal_reconcile' &&
1056
+ toolName !== 'code_act') {
1057
+ await this.executionContextStorage.run(activeCtx, async () => {
1058
+ this.requireActiveTemporalAuthority(toolName);
1059
+ });
1060
+ }
1061
+ const shouldSanitizeAuditFailure = Boolean(activeCtx.temporalWorkContext) ||
1062
+ toolName === 'context_compile' ||
1063
+ toolName === 'code_act';
1064
+ auditResult = shouldSanitizeAuditFailure
1065
+ ? sanitizeGatewayFailureResult(rawResult, Boolean(activeCtx.temporalWorkContext))
1066
+ : rawResult;
1067
+ result = activeCtx.temporalWorkContext ? auditResult : rawResult;
902
1068
  activeCtx.signal?.throwIfAborted();
903
1069
  }
904
1070
  catch (error) {
905
- await this.appendToolTraceIfNeeded(traceState, activeCtx, toolName, undefined, Date.now() - startedAt, gatewayCallId, error).catch((appendError) => {
1071
+ const shouldSanitizeAuditFailure = Boolean(activeCtx.temporalWorkContext) ||
1072
+ toolName === 'context_compile' ||
1073
+ toolName === 'code_act';
1074
+ const auditError = shouldSanitizeAuditFailure
1075
+ ? sanitizeGatewayError(error, Boolean(activeCtx.temporalWorkContext))
1076
+ : error;
1077
+ await this.appendToolTraceIfNeeded(traceState, activeCtx, toolName, undefined, Date.now() - startedAt, gatewayCallId, auditError).catch((appendError) => {
906
1078
  securityLogger.warn('[model-run] failed to append failed tool trace before finalization', appendError);
907
1079
  });
908
- await this.failDirectModelRunIfNeeded(traceState, toolName, error).catch((finalizationError) => {
1080
+ await this.failDirectModelRunIfNeeded(traceState, toolName, auditError).catch((finalizationError) => {
909
1081
  securityLogger.warn('[model-run] failed to finalize failed direct model run', finalizationError);
910
1082
  });
911
- this.logGatewayToolCall(activeCtx, toolName, undefined, Date.now() - startedAt, scopeAudit, gatewayCallId, error);
1083
+ this.logGatewayToolCall(activeCtx, toolName, undefined, Date.now() - startedAt, scopeAudit, gatewayCallId, auditError);
912
1084
  if (scopeAudit.mismatch) {
913
1085
  this.alarmScopeMismatch(activeCtx, toolName);
914
1086
  }
915
- throw error;
1087
+ throw activeCtx.temporalWorkContext ? auditError : error;
916
1088
  }
917
1089
  try {
918
1090
  try {
919
- await this.appendToolTraceIfNeeded(traceState, activeCtx, toolName, result, Date.now() - startedAt, gatewayCallId);
1091
+ await this.appendToolTraceIfNeeded(traceState, activeCtx, toolName, auditResult, Date.now() - startedAt, gatewayCallId);
920
1092
  }
921
1093
  finally {
922
- await this.completeDirectModelRunIfNeeded(traceState, toolName, result);
1094
+ await this.completeDirectModelRunIfNeeded(traceState, toolName, auditResult);
923
1095
  }
924
1096
  }
925
1097
  catch (postRunError) {
926
- this.logGatewayToolCall(activeCtx, toolName, result, Date.now() - startedAt, scopeAudit, gatewayCallId, postRunError);
1098
+ this.logGatewayToolCall(activeCtx, toolName, auditResult, Date.now() - startedAt, scopeAudit, gatewayCallId, postRunError);
927
1099
  if (scopeAudit.mismatch) {
928
1100
  this.alarmScopeMismatch(activeCtx, toolName);
929
1101
  }
930
1102
  throw postRunError;
931
1103
  }
932
- this.logGatewayToolCall(activeCtx, toolName, result, Date.now() - startedAt, scopeAudit, gatewayCallId);
1104
+ this.logGatewayToolCall(activeCtx, toolName, auditResult, Date.now() - startedAt, scopeAudit, gatewayCallId);
933
1105
  if (scopeAudit.mismatch) {
934
1106
  this.alarmScopeMismatch(activeCtx, toolName);
935
1107
  }
@@ -1277,6 +1449,9 @@ class GatewayToolExecutor {
1277
1449
  gateway_call_id: gatewayCallId,
1278
1450
  ...(resultCode ? { code: resultCode } : {}),
1279
1451
  ...(ctx?.parentToolName ? { parent: ctx.parentToolName } : {}),
1452
+ ...(ctx?.workorderAttemptId !== undefined
1453
+ ? { workorder_attempt_id: ctx.workorderAttemptId }
1454
+ : {}),
1280
1455
  },
1281
1456
  });
1282
1457
  }
@@ -1317,6 +1492,13 @@ class GatewayToolExecutor {
1317
1492
  if (!VALID_TOOLS.includes(toolName)) {
1318
1493
  throw new types_js_1.AgentError(`Unknown tool: ${toolName}. Valid tools: ${VALID_TOOLS.join(', ')}`, 'UNKNOWN_TOOL', undefined, false);
1319
1494
  }
1495
+ if (toolName.startsWith('drive_') &&
1496
+ this.getExecutionState().agentContext?.roleName !== 'owner_console') {
1497
+ return {
1498
+ success: false,
1499
+ error: 'Permission denied: Google Drive tools are restricted to owner_console.',
1500
+ };
1501
+ }
1320
1502
  // Structurally disallowed tools are per-call policy carried by the execution
1321
1503
  // context (a shared executor serves many agents with different blocks).
1322
1504
  const activeDisallowed = this.getExecutionState()?.disallowedGatewayTools;
@@ -1337,6 +1519,7 @@ class GatewayToolExecutor {
1337
1519
  };
1338
1520
  }
1339
1521
  }
1522
+ this.requireActiveTemporalAuthority(toolName);
1340
1523
  const envelopeDenied = this.enforceEnvelopeForToolCall(toolName, input);
1341
1524
  if (envelopeDenied) {
1342
1525
  return envelopeDenied;
@@ -1365,6 +1548,31 @@ class GatewayToolExecutor {
1365
1548
  return await this.executeSlackSend(input);
1366
1549
  case 'telegram_send':
1367
1550
  return await this.executeTelegramSend(input);
1551
+ case 'drive_list_drives':
1552
+ return {
1553
+ success: true,
1554
+ result: (0, drive_tools_js_1.asUntrustedDriveEvidence)(await this.driveTools.listDrives()),
1555
+ };
1556
+ case 'drive_browse':
1557
+ return {
1558
+ success: true,
1559
+ result: (0, drive_tools_js_1.asUntrustedDriveEvidence)(await this.driveTools.browse(input)),
1560
+ };
1561
+ case 'drive_find_folder':
1562
+ return {
1563
+ success: true,
1564
+ result: (0, drive_tools_js_1.asUntrustedDriveEvidence)(await this.driveTools.findFolder(input)),
1565
+ };
1566
+ case 'drive_download':
1567
+ return {
1568
+ success: true,
1569
+ result: (0, drive_tools_js_1.asUntrustedDriveEvidence)(await this.driveTools.download(input)),
1570
+ };
1571
+ case 'drive_upload':
1572
+ return {
1573
+ success: true,
1574
+ result: (0, drive_tools_js_1.asUntrustedDriveEvidence)(await this.driveTools.upload(input)),
1575
+ };
1368
1576
  // Browser tools
1369
1577
  case 'browser_navigate':
1370
1578
  return await this.executeBrowserNavigate(input);
@@ -1752,6 +1960,14 @@ class GatewayToolExecutor {
1752
1960
  if (!slotsInput || typeof slotsInput !== 'object') {
1753
1961
  throw new types_js_1.AgentError('report_publish requires slots object', 'TOOL_ERROR', undefined, false);
1754
1962
  }
1963
+ if (this.getExecutionState().temporalWorkContext) {
1964
+ const slotNames = Object.keys(slotsInput);
1965
+ if (slotNames.length !== 1 ||
1966
+ slotNames[0] !== 'pipeline' ||
1967
+ typeof slotsInput.pipeline !== 'string') {
1968
+ throw new types_js_1.AgentError('Temporal report_publish accepts exactly the host-derived pipeline slot', 'TOOL_ERROR', undefined, false);
1969
+ }
1970
+ }
1755
1971
  // Stage-2 shadow seam: a per-run capture override takes precedence
1756
1972
  // over the global singleton (capture runs never touch the live store).
1757
1973
  const activePublisher = this.getExecutionState().reportPublisherOverride ?? this.reportPublisher;
@@ -1926,16 +2142,29 @@ class GatewayToolExecutor {
1926
2142
  if (!this.taskLedger) {
1927
2143
  return { success: false, error: 'Task ledger not configured' };
1928
2144
  }
2145
+ const temporalContext = this.getExecutionState().temporalWorkContext;
2146
+ if (temporalContext) {
2147
+ const boundTask = this.taskLedger.getById(temporalContext.taskId);
2148
+ if (!boundTask) {
2149
+ throw new types_js_1.AgentError('Host-bound temporal owner task is unavailable', 'WORKORDER_SUPERSEDED', undefined, false);
2150
+ }
2151
+ return {
2152
+ success: true,
2153
+ tasks: [serializeTaskToolRecord(boundTask)],
2154
+ };
2155
+ }
1929
2156
  const listInput = input;
1930
2157
  return {
1931
2158
  success: true,
1932
- tasks: this.taskLedger.list({
2159
+ tasks: this.taskLedger
2160
+ .list({
1933
2161
  status: listInput.status,
1934
2162
  channel: listInput.channel,
1935
2163
  search: listInput.search,
1936
2164
  limit: listInput.limit,
1937
2165
  order: listInput.order ?? 'deadline_priority',
1938
- }),
2166
+ })
2167
+ .map(serializeTaskToolRecord),
1939
2168
  };
1940
2169
  }
1941
2170
  case 'task_create': {
@@ -1944,7 +2173,7 @@ class GatewayToolExecutor {
1944
2173
  }
1945
2174
  return {
1946
2175
  success: true,
1947
- task: this.taskLedger.create(input),
2176
+ task: serializeTaskToolRecord(this.taskLedger.create(input)),
1948
2177
  };
1949
2178
  }
1950
2179
  case 'task_update': {
@@ -1959,7 +2188,59 @@ class GatewayToolExecutor {
1959
2188
  }
1960
2189
  return {
1961
2190
  success: true,
1962
- task: this.taskLedger.update(id, patch),
2191
+ task: serializeTaskToolRecord(this.taskLedger.update(id, patch)),
2192
+ };
2193
+ }
2194
+ case 'task_temporal_reconcile': {
2195
+ if (!this.taskLedger) {
2196
+ return { success: false, error: 'Task ledger not configured' };
2197
+ }
2198
+ const context = this.getExecutionState().temporalWorkContext;
2199
+ if (!context) {
2200
+ throw new types_js_1.AgentError('task_temporal_reconcile requires trusted temporal context', 'WORKORDER_SUPERSEDED', undefined, false);
2201
+ }
2202
+ const contextPacketId = input.context_packet_id;
2203
+ if (typeof contextPacketId !== 'string' || contextPacketId.trim().length === 0) {
2204
+ throw new types_js_1.AgentError('task_temporal_reconcile requires a fresh context_packet_id', 'TOOL_ERROR', undefined, false);
2205
+ }
2206
+ const executionState = this.getExecutionState();
2207
+ if (!executionState.envelope || !executionState.modelRunId) {
2208
+ throw new types_js_1.AgentError('task_temporal_reconcile evidence requires an active envelope and model run', 'TOOL_ERROR', undefined, false);
2209
+ }
2210
+ const packet = await this.temporalContextPacketLookup({
2211
+ packetId: contextPacketId,
2212
+ envelopeHash: executionState.envelope.envelope_hash,
2213
+ callerModelRunId: executionState.modelRunId,
2214
+ });
2215
+ if (!packet || packet.packet_id !== contextPacketId) {
2216
+ throw new types_js_1.AgentError('task_temporal_reconcile context packet is unavailable', 'TOOL_ERROR', undefined, false);
2217
+ }
2218
+ const attempt = this.taskLedger.inspectTemporalAttempt(context.attemptId);
2219
+ if (!Number.isSafeInteger(packet.created_at) ||
2220
+ packet.created_at < attempt.workOrder.updatedAt) {
2221
+ throw new types_js_1.AgentError('task_temporal_reconcile context packet predates the active attempt', 'TOOL_ERROR', undefined, false);
2222
+ }
2223
+ const effectInput = input;
2224
+ if (effectInput.outcome !== 'deferred' &&
2225
+ (!Array.isArray(packet.source_refs) || packet.source_refs.length === 0)) {
2226
+ throw new types_js_1.AgentError('task_temporal_reconcile requires source-backed fresh evidence', 'TOOL_ERROR', undefined, false);
2227
+ }
2228
+ if (!packet.task.startsWith(`${temporalContextPacketBinding(context)}\n`) ||
2229
+ (effectInput.outcome === 'deferred'
2230
+ ? Array.isArray(packet.source_refs) &&
2231
+ packet.source_refs.length > 0 &&
2232
+ !temporalPacketReferencesBoundSource(context, packet.source_refs)
2233
+ : !temporalPacketReferencesBoundSource(context, packet.source_refs))) {
2234
+ throw new types_js_1.AgentError('task_temporal_reconcile context packet is not bound to the active task source', 'TOOL_ERROR', undefined, false);
2235
+ }
2236
+ const evidence = {
2237
+ contextPacketId,
2238
+ contextPacketSha256: (0, crypto_1.createHash)('sha256').update(packet.packet_json).digest('hex'),
2239
+ };
2240
+ const { context_packet_id: _contextPacketId, ...trustedEffectInput } = effectInput;
2241
+ return {
2242
+ success: true,
2243
+ receipt: this.taskLedger.applyTemporalEffect(context, trustedEffectInput, evidence),
1963
2244
  };
1964
2245
  }
1965
2246
  case 'schedule_upcoming': {
@@ -3229,6 +3510,7 @@ class GatewayToolExecutor {
3229
3510
  try {
3230
3511
  policy = projectCodeActToolPolicy({
3231
3512
  tier,
3513
+ roleName: state.agentContext?.roleName,
3232
3514
  role: state.agentContext?.role,
3233
3515
  disallowedTools: state.disallowedGatewayTools,
3234
3516
  requestedAllowedTools: input.allowedTools,
@@ -3251,12 +3533,25 @@ class GatewayToolExecutor {
3251
3533
  parentToolName: 'code_act',
3252
3534
  };
3253
3535
  const bridge = new HostBridge(this, this.roleManager, nestedExecutionContext);
3536
+ let usedUntrustedDriveEvidence = false;
3537
+ bridge.onToolUse = (toolName, _toolInput, result) => {
3538
+ if (result !== undefined && toolName.startsWith('drive_') && toolName !== 'drive_upload') {
3539
+ usedUntrustedDriveEvidence = true;
3540
+ }
3541
+ };
3254
3542
  bridge.injectInto(sandbox, policy.names);
3255
3543
  const result = await sandbox.execute(input.code);
3544
+ const successfulMessage = JSON.stringify({
3545
+ value: result.value,
3546
+ logs: result.logs,
3547
+ metrics: result.metrics,
3548
+ });
3256
3549
  return {
3257
3550
  success: result.success,
3258
3551
  message: result.success
3259
- ? JSON.stringify({ value: result.value, logs: result.logs, metrics: result.metrics })
3552
+ ? usedUntrustedDriveEvidence
3553
+ ? (0, untrusted_content_js_1.wrapUntrustedContent)('google-drive-code-act', successfulMessage)
3554
+ : successfulMessage
3260
3555
  : `Code-Act error: ${result.error?.message || 'Unknown error'}`,
3261
3556
  };
3262
3557
  }
@@ -3423,13 +3718,26 @@ class GatewayToolExecutor {
3423
3718
  };
3424
3719
  }
3425
3720
  try {
3721
+ const temporalContext = ctx.temporalWorkContext;
3722
+ const effectiveInput = temporalContext
3723
+ ? { ...input, task: bindTemporalContextPacketTask(temporalContext, input.task) }
3724
+ : input;
3426
3725
  const result = await this.contextCompileService.compileAndPersistContext({
3427
3726
  caller: 'gateway',
3428
3727
  envelope: ctx.envelope,
3429
3728
  modelRunId: ctx.modelRunId ?? null,
3430
- input,
3729
+ input: effectiveInput,
3431
3730
  signal: ctx.signal,
3731
+ beforePersist: temporalContext
3732
+ ? () => {
3733
+ this.requireActiveTemporalAuthority('context_compile');
3734
+ }
3735
+ : undefined,
3432
3736
  });
3737
+ if (temporalContext &&
3738
+ !temporalPacketRawSourcesWithinBoundSource(temporalContext, result.packet.source_refs)) {
3739
+ throw new Error('context_compile packet exceeds the active temporal task source');
3740
+ }
3433
3741
  return {
3434
3742
  success: true,
3435
3743
  packet: result.packet,
@@ -3565,6 +3873,15 @@ function isMemoryScope(value) {
3565
3873
  function memoryScopeKey(scope) {
3566
3874
  return `${scope.kind}:${scope.id}`;
3567
3875
  }
3876
+ function digestRequestedScopesForAudit(scopes) {
3877
+ if (!scopes) {
3878
+ return null;
3879
+ }
3880
+ return scopes.map((scope) => ({
3881
+ kind: scope.kind,
3882
+ id: `sha256:${(0, crypto_1.createHash)('sha256').update(scope.id).digest('hex')}`,
3883
+ }));
3884
+ }
3568
3885
  function getFailureMessage(result) {
3569
3886
  if (!result || result.success !== false) {
3570
3887
  return undefined;
@@ -3573,4 +3890,30 @@ function getFailureMessage(result) {
3573
3890
  const message = record.error ?? record.message ?? 'Tool returned success:false';
3574
3891
  return String(message);
3575
3892
  }
3893
+ function gatewayFailureRef(value, temporal) {
3894
+ const digest = (0, crypto_1.createHash)('sha256').update(value).digest('hex');
3895
+ const label = temporal ? 'temporal_tool_failed' : 'gateway_tool_failed';
3896
+ return `${label};sha256=${digest};length=${value.length}`;
3897
+ }
3898
+ function sanitizeGatewayFailureResult(result, temporal) {
3899
+ const failure = getFailureMessage(result);
3900
+ if (!failure) {
3901
+ return result;
3902
+ }
3903
+ const record = result;
3904
+ return {
3905
+ success: false,
3906
+ error: gatewayFailureRef(failure, temporal),
3907
+ ...(typeof record.code === 'string' ? { code: record.code } : {}),
3908
+ };
3909
+ }
3910
+ function sanitizeGatewayError(error, temporal) {
3911
+ const message = error instanceof Error ? error.message : String(error);
3912
+ if (error instanceof types_js_1.AgentError) {
3913
+ return new types_js_1.AgentError(error.code === 'WORKORDER_SUPERSEDED'
3914
+ ? 'Temporal workorder authority is no longer active'
3915
+ : gatewayFailureRef(message, temporal), error.code, undefined, error.retryable);
3916
+ }
3917
+ return new Error(gatewayFailureRef(message, temporal));
3918
+ }
3576
3919
  //# sourceMappingURL=gateway-tool-executor.js.map