@jungjaehoon/mama-os 0.36.0 → 0.37.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.
- package/dist/agent/agent-loop.d.ts +2 -1
- package/dist/agent/agent-loop.d.ts.map +1 -1
- package/dist/agent/agent-loop.js +17 -12
- package/dist/agent/agent-loop.js.map +1 -1
- package/dist/agent/code-act/host-bridge.d.ts.map +1 -1
- package/dist/agent/code-act/host-bridge.js +27 -2
- package/dist/agent/code-act/host-bridge.js.map +1 -1
- package/dist/agent/code-act/type-definition-generator.d.ts.map +1 -1
- package/dist/agent/code-act/type-definition-generator.js +3 -1
- package/dist/agent/code-act/type-definition-generator.js.map +1 -1
- package/dist/agent/context-compile-service.d.ts +2 -0
- package/dist/agent/context-compile-service.d.ts.map +1 -1
- package/dist/agent/context-compile-service.js +1 -1
- package/dist/agent/context-compile-service.js.map +1 -1
- package/dist/agent/drive-tools.d.ts +27 -1
- package/dist/agent/drive-tools.d.ts.map +1 -1
- package/dist/agent/drive-tools.js +68 -2
- package/dist/agent/drive-tools.js.map +1 -1
- package/dist/agent/gateway-tool-executor.d.ts +11 -6
- package/dist/agent/gateway-tool-executor.d.ts.map +1 -1
- package/dist/agent/gateway-tool-executor.js +210 -37
- package/dist/agent/gateway-tool-executor.js.map +1 -1
- package/dist/agent/gateway-tools.md +2 -2
- package/dist/agent/tool-registry.js +2 -2
- package/dist/agent/tool-registry.js.map +1 -1
- package/dist/agent/types.d.ts +15 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/api/report-handler.d.ts +9 -5
- package/dist/api/report-handler.d.ts.map +1 -1
- package/dist/api/report-handler.js +26 -13
- package/dist/api/report-handler.js.map +1 -1
- package/dist/api/report-persistence.d.ts.map +1 -1
- package/dist/api/report-persistence.js +6 -3
- package/dist/api/report-persistence.js.map +1 -1
- package/dist/api/runtime-status-handler.d.ts +1 -0
- package/dist/api/runtime-status-handler.d.ts.map +1 -1
- package/dist/api/runtime-status-handler.js +1 -0
- package/dist/api/runtime-status-handler.js.map +1 -1
- package/dist/cli/commands/start.d.ts +14 -20
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +207 -248
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/status.d.ts +6 -0
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +89 -0
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/config/types.d.ts +0 -21
- package/dist/cli/config/types.d.ts.map +1 -1
- package/dist/cli/config/types.js +0 -7
- package/dist/cli/config/types.js.map +1 -1
- package/dist/cli/index.js +2 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/runtime/agent-loop-init.d.ts +2 -2
- package/dist/cli/runtime/agent-loop-init.d.ts.map +1 -1
- package/dist/cli/runtime/agent-loop-init.js +3 -3
- package/dist/cli/runtime/agent-loop-init.js.map +1 -1
- package/dist/cli/runtime/api-routes-init.d.ts +7 -1
- package/dist/cli/runtime/api-routes-init.d.ts.map +1 -1
- package/dist/cli/runtime/api-routes-init.js +99 -38
- package/dist/cli/runtime/api-routes-init.js.map +1 -1
- package/dist/cli/runtime/api-server-init.d.ts.map +1 -1
- package/dist/cli/runtime/api-server-init.js +3 -0
- package/dist/cli/runtime/api-server-init.js.map +1 -1
- package/dist/gateways/message-router.js +10 -10
- package/dist/gateways/message-router.js.map +1 -1
- package/dist/gateways/telegram.d.ts +2 -2
- package/dist/gateways/telegram.d.ts.map +1 -1
- package/dist/gateways/telegram.js +13 -7
- package/dist/gateways/telegram.js.map +1 -1
- package/dist/multi-agent/agent-event-bus.d.ts +0 -5
- package/dist/multi-agent/agent-event-bus.d.ts.map +1 -1
- package/dist/multi-agent/agent-event-bus.js.map +1 -1
- package/dist/operator/action-verifier.d.ts +2 -0
- package/dist/operator/action-verifier.d.ts.map +1 -1
- package/dist/operator/action-verifier.js +3 -2
- package/dist/operator/action-verifier.js.map +1 -1
- package/dist/operator/board-reconcile.d.ts +2 -2
- package/dist/operator/board-reconcile.d.ts.map +1 -1
- package/dist/operator/board-reconcile.js +10 -2
- package/dist/operator/board-reconcile.js.map +1 -1
- package/dist/operator/board-refresh-gate.d.ts +34 -0
- package/dist/operator/board-refresh-gate.d.ts.map +1 -0
- package/dist/operator/board-refresh-gate.js +82 -0
- package/dist/operator/board-refresh-gate.js.map +1 -0
- package/dist/operator/briefs.d.ts.map +1 -1
- package/dist/operator/briefs.js +92 -4
- package/dist/operator/briefs.js.map +1 -1
- package/dist/operator/operator-trigger-loop.d.ts +7 -22
- package/dist/operator/operator-trigger-loop.d.ts.map +1 -1
- package/dist/operator/operator-trigger-loop.js +33 -34
- package/dist/operator/operator-trigger-loop.js.map +1 -1
- package/dist/operator/owner-event-effects.d.ts +34 -0
- package/dist/operator/owner-event-effects.d.ts.map +1 -0
- package/dist/operator/owner-event-effects.js +131 -0
- package/dist/operator/owner-event-effects.js.map +1 -0
- package/dist/operator/{conductor-inbox.d.ts → owner-event-inbox.d.ts} +23 -12
- package/dist/operator/owner-event-inbox.d.ts.map +1 -0
- package/dist/operator/{conductor-inbox.js → owner-event-inbox.js} +97 -40
- package/dist/operator/owner-event-inbox.js.map +1 -0
- package/dist/operator/owner-event-loop.d.ts +59 -0
- package/dist/operator/owner-event-loop.d.ts.map +1 -0
- package/dist/operator/owner-event-loop.js +141 -0
- package/dist/operator/owner-event-loop.js.map +1 -0
- package/dist/operator/owner-event-outcome.d.ts +30 -0
- package/dist/operator/owner-event-outcome.d.ts.map +1 -0
- package/dist/operator/owner-event-outcome.js +108 -0
- package/dist/operator/owner-event-outcome.js.map +1 -0
- package/dist/operator/owner-event-policy.d.ts +20 -0
- package/dist/operator/owner-event-policy.d.ts.map +1 -0
- package/dist/operator/owner-event-policy.js +50 -0
- package/dist/operator/owner-event-policy.js.map +1 -0
- package/dist/operator/owner-event-prompt.d.ts +10 -0
- package/dist/operator/owner-event-prompt.d.ts.map +1 -0
- package/dist/operator/owner-event-prompt.js +63 -0
- package/dist/operator/owner-event-prompt.js.map +1 -0
- package/dist/operator/task-ledger.d.ts +2 -0
- package/dist/operator/task-ledger.d.ts.map +1 -1
- package/dist/operator/task-ledger.js +12 -1
- package/dist/operator/task-ledger.js.map +1 -1
- package/dist/operator/trigger-matcher.d.ts.map +1 -1
- package/dist/operator/trigger-matcher.js +4 -1
- package/dist/operator/trigger-matcher.js.map +1 -1
- package/dist/operator/trigger-registry.d.ts +1 -1
- package/dist/operator/trigger-registry.d.ts.map +1 -1
- package/dist/operator/trigger-registry.js +2 -2
- package/dist/operator/trigger-registry.js.map +1 -1
- package/dist/operator/trigger-types.d.ts +2 -0
- package/dist/operator/trigger-types.d.ts.map +1 -1
- package/dist/operator/workorder-hooks.d.ts +14 -0
- package/dist/operator/workorder-hooks.d.ts.map +1 -1
- package/dist/operator/workorder-hooks.js +64 -0
- package/dist/operator/workorder-hooks.js.map +1 -1
- package/dist/operator/workorder-publishers.d.ts +14 -4
- package/dist/operator/workorder-publishers.d.ts.map +1 -1
- package/dist/operator/workorder-publishers.js +51 -13
- package/dist/operator/workorder-publishers.js.map +1 -1
- package/dist/package-version.d.ts +3 -0
- package/dist/package-version.d.ts.map +1 -0
- package/dist/package-version.js +18 -0
- package/dist/package-version.js.map +1 -0
- package/package.json +2 -2
- package/public/viewer/js/modules/system.js +1 -0
- package/public/viewer/src/modules/system.ts +2 -0
- package/dist/operator/board-reground.d.ts +0 -19
- package/dist/operator/board-reground.d.ts.map +0 -1
- package/dist/operator/board-reground.js +0 -31
- package/dist/operator/board-reground.js.map +0 -1
- package/dist/operator/conductor-inbox.d.ts.map +0 -1
- package/dist/operator/conductor-inbox.js.map +0 -1
- package/dist/operator/conductor-session.d.ts +0 -55
- package/dist/operator/conductor-session.d.ts.map +0 -1
- package/dist/operator/conductor-session.js +0 -110
- package/dist/operator/conductor-session.js.map +0 -1
- package/dist/operator/conductor.d.ts +0 -69
- package/dist/operator/conductor.d.ts.map +0 -1
- package/dist/operator/conductor.js +0 -90
- package/dist/operator/conductor.js.map +0 -1
|
@@ -85,6 +85,9 @@ const DEFAULT_PRIVATE_CONNECTOR_POLICY = (0, private_connector_policy_js_1.resol
|
|
|
85
85
|
config: {},
|
|
86
86
|
enabledNames: [],
|
|
87
87
|
});
|
|
88
|
+
function isReportPublishResult(value) {
|
|
89
|
+
return value !== undefined && !Array.isArray(value);
|
|
90
|
+
}
|
|
88
91
|
function serializeTaskToolRecord(task) {
|
|
89
92
|
return {
|
|
90
93
|
...task,
|
|
@@ -404,12 +407,16 @@ class GatewayToolExecutor {
|
|
|
404
407
|
this.obsidianVaultName = vaultName ?? null;
|
|
405
408
|
}
|
|
406
409
|
taskLedger = null;
|
|
410
|
+
ownerEventEffectLedger = null;
|
|
407
411
|
setTaskLedger(ledger) {
|
|
408
412
|
this.taskLedger = ledger;
|
|
409
413
|
}
|
|
410
414
|
getTaskLedger() {
|
|
411
415
|
return this.taskLedger;
|
|
412
416
|
}
|
|
417
|
+
setOwnerEventEffectLedger(ledger) {
|
|
418
|
+
this.ownerEventEffectLedger = ledger;
|
|
419
|
+
}
|
|
413
420
|
agentEventBus = null;
|
|
414
421
|
setAgentEventBus(bus) {
|
|
415
422
|
this.agentEventBus = bus;
|
|
@@ -457,6 +464,7 @@ class GatewayToolExecutor {
|
|
|
457
464
|
workorderAttemptId: executionContext?.workorderAttemptId,
|
|
458
465
|
temporalWorkContext: executionContext?.temporalWorkContext,
|
|
459
466
|
causeEventIds: executionContext?.causeEventIds,
|
|
467
|
+
ownerEventEffects: executionContext?.ownerEventEffects,
|
|
460
468
|
signal: executionContext?.signal,
|
|
461
469
|
parentToolName: executionContext?.parentToolName,
|
|
462
470
|
backgroundTasks: executionContext?.backgroundTasks,
|
|
@@ -495,9 +503,12 @@ class GatewayToolExecutor {
|
|
|
495
503
|
// Never merged from fallback - temporal authority belongs to one claimed run only.
|
|
496
504
|
temporalWorkContext: active.temporalWorkContext,
|
|
497
505
|
causeEventIds: active.causeEventIds,
|
|
506
|
+
ownerEventEffects: active.ownerEventEffects,
|
|
498
507
|
signal: active.signal,
|
|
499
508
|
parentToolName: active.parentToolName ?? fallback.parentToolName,
|
|
500
509
|
backgroundTasks: active.backgroundTasks ?? fallback.backgroundTasks,
|
|
510
|
+
// Never merged from fallback - one snapshot belongs to one gateway call only.
|
|
511
|
+
channelGrantSnapshot: active.channelGrantSnapshot,
|
|
501
512
|
// Never merged from fallback - blocks are strictly per-call.
|
|
502
513
|
disallowedGatewayTools: active.disallowedGatewayTools,
|
|
503
514
|
};
|
|
@@ -851,7 +862,7 @@ class GatewayToolExecutor {
|
|
|
851
862
|
}
|
|
852
863
|
try {
|
|
853
864
|
this.envelopeEnforcer.check(ctx.envelope, toolName, enforcementInput, {
|
|
854
|
-
readScopeMirror: this.readScopeMirrorFor(toolName, ctx.envelope),
|
|
865
|
+
readScopeMirror: this.readScopeMirrorFor(toolName, ctx.envelope, ctx.channelGrantSnapshot),
|
|
855
866
|
});
|
|
856
867
|
return undefined;
|
|
857
868
|
}
|
|
@@ -951,7 +962,10 @@ class GatewayToolExecutor {
|
|
|
951
962
|
const baseCtx = this.mergeWithFallbackExecutionContext(this.executionContextStorage.getStore());
|
|
952
963
|
baseCtx.signal?.throwIfAborted();
|
|
953
964
|
const gatewayCallId = baseCtx.gatewayCallId ?? `gw_${(0, crypto_1.randomUUID)().replace(/-/g, '')}`;
|
|
954
|
-
const
|
|
965
|
+
const channelGrantSnapshot = baseCtx.envelope && index_js_1.MIRROR_READABLE_TOOLS.has(toolName)
|
|
966
|
+
? snapshotChannelGrant(this.channelGrantProvider)
|
|
967
|
+
: undefined;
|
|
968
|
+
const ctx = { ...baseCtx, gatewayCallId, channelGrantSnapshot };
|
|
955
969
|
const effectiveInput = this.applyEnvelopeScopedReadDefaults(toolName, input, ctx);
|
|
956
970
|
const computedScopeAudit = this.computeScopeAuditFields(toolName, effectiveInput, ctx);
|
|
957
971
|
const scopeAudit = ctx.temporalWorkContext
|
|
@@ -1008,7 +1022,7 @@ class GatewayToolExecutor {
|
|
|
1008
1022
|
await this.failDirectModelRunIfNeeded(traceState, toolName, auditError).catch((finalizationError) => {
|
|
1009
1023
|
securityLogger.warn('[model-run] failed to finalize failed direct model run', finalizationError);
|
|
1010
1024
|
});
|
|
1011
|
-
this.logGatewayToolCall(activeCtx, toolName, undefined, Date.now() - startedAt, scopeAudit, gatewayCallId, auditError);
|
|
1025
|
+
this.logGatewayToolCall(activeCtx, toolName, undefined, Date.now() - startedAt, scopeAudit, gatewayCallId, this.gatewayTraceDetails(toolName, undefined), auditError);
|
|
1012
1026
|
if (scopeAudit.mismatch) {
|
|
1013
1027
|
this.alarmScopeMismatch(activeCtx, toolName);
|
|
1014
1028
|
}
|
|
@@ -1023,13 +1037,13 @@ class GatewayToolExecutor {
|
|
|
1023
1037
|
}
|
|
1024
1038
|
}
|
|
1025
1039
|
catch (postRunError) {
|
|
1026
|
-
this.logGatewayToolCall(activeCtx, toolName, auditResult, Date.now() - startedAt, scopeAudit, gatewayCallId, postRunError);
|
|
1040
|
+
this.logGatewayToolCall(activeCtx, toolName, auditResult, Date.now() - startedAt, scopeAudit, gatewayCallId, this.gatewayTraceDetails(toolName, auditResult), postRunError);
|
|
1027
1041
|
if (scopeAudit.mismatch) {
|
|
1028
1042
|
this.alarmScopeMismatch(activeCtx, toolName);
|
|
1029
1043
|
}
|
|
1030
1044
|
throw postRunError;
|
|
1031
1045
|
}
|
|
1032
|
-
this.logGatewayToolCall(activeCtx, toolName, auditResult, Date.now() - startedAt, scopeAudit, gatewayCallId);
|
|
1046
|
+
this.logGatewayToolCall(activeCtx, toolName, auditResult, Date.now() - startedAt, scopeAudit, gatewayCallId, this.gatewayTraceDetails(toolName, auditResult));
|
|
1033
1047
|
if (scopeAudit.mismatch) {
|
|
1034
1048
|
this.alarmScopeMismatch(activeCtx, toolName);
|
|
1035
1049
|
}
|
|
@@ -1187,7 +1201,9 @@ class GatewayToolExecutor {
|
|
|
1187
1201
|
return { requestedScopes, envelopeScopesSnapshot, mismatch: 0 };
|
|
1188
1202
|
}
|
|
1189
1203
|
if (!requestedScopes || requestedScopes.length === 0) {
|
|
1190
|
-
|
|
1204
|
+
const requestedScopeValue = input.scopes;
|
|
1205
|
+
if (toolName === 'context_compile' &&
|
|
1206
|
+
(requestedScopeValue === undefined || Array.isArray(requestedScopeValue))) {
|
|
1191
1207
|
return { requestedScopes, envelopeScopesSnapshot, mismatch: 0 };
|
|
1192
1208
|
}
|
|
1193
1209
|
return {
|
|
@@ -1196,7 +1212,11 @@ class GatewayToolExecutor {
|
|
|
1196
1212
|
mismatch: envelopeScopesSnapshot.length > 0 ? 1 : 0,
|
|
1197
1213
|
};
|
|
1198
1214
|
}
|
|
1199
|
-
const
|
|
1215
|
+
const effectiveAuditAllowance = [
|
|
1216
|
+
...envelopeScopesSnapshot,
|
|
1217
|
+
...(this.readScopeMirrorFor(toolName, ctx.envelope, ctx.channelGrantSnapshot) ?? []),
|
|
1218
|
+
];
|
|
1219
|
+
const envelopeScopeKeys = new Set(effectiveAuditAllowance.map(memoryScopeKey));
|
|
1200
1220
|
const hasOutOfEnvelopeScope = requestedScopes.some((scope) => !envelopeScopeKeys.has(memoryScopeKey(scope)));
|
|
1201
1221
|
return {
|
|
1202
1222
|
requestedScopes,
|
|
@@ -1243,7 +1263,7 @@ class GatewayToolExecutor {
|
|
|
1243
1263
|
const envelopeScopes = ctx.envelope
|
|
1244
1264
|
? [
|
|
1245
1265
|
...ctx.envelope.scope.memory_scopes,
|
|
1246
|
-
...(
|
|
1266
|
+
...(this.readScopeMirrorFor(toolName, ctx.envelope, ctx.channelGrantSnapshot) ?? []),
|
|
1247
1267
|
]
|
|
1248
1268
|
: null;
|
|
1249
1269
|
const allowedScopes = envelopeScopes ?? this.deriveMemoryScopesFromActiveContext(ctx) ?? [];
|
|
@@ -1290,15 +1310,14 @@ class GatewayToolExecutor {
|
|
|
1290
1310
|
}
|
|
1291
1311
|
/**
|
|
1292
1312
|
* The grant-mirror READ allowance for memory tools (see mirrorReadScopes):
|
|
1293
|
-
* computed
|
|
1294
|
-
*
|
|
1295
|
-
* readable on the next call, mid-envelope included.
|
|
1313
|
+
* computed from the gateway-call snapshot, so every authority check agrees
|
|
1314
|
+
* within one call while the next call observes a fresh live grant.
|
|
1296
1315
|
*/
|
|
1297
|
-
readScopeMirrorFor(toolName, envelope) {
|
|
1298
|
-
if (!index_js_1.MIRROR_READABLE_TOOLS.has(toolName)) {
|
|
1316
|
+
readScopeMirrorFor(toolName, envelope, channelGrantSnapshot) {
|
|
1317
|
+
if (!index_js_1.MIRROR_READABLE_TOOLS.has(toolName) || !channelGrantSnapshot) {
|
|
1299
1318
|
return undefined;
|
|
1300
1319
|
}
|
|
1301
|
-
return (0, read_js_1.mirrorReadScopes)(envelope,
|
|
1320
|
+
return (0, read_js_1.mirrorReadScopes)(envelope, channelGrantSnapshot);
|
|
1302
1321
|
}
|
|
1303
1322
|
applyEnvelopeScopedReadDefaults(toolName, input, ctx) {
|
|
1304
1323
|
// Memory read tools must inherit envelope scopes consistently when the
|
|
@@ -1340,7 +1359,7 @@ class GatewayToolExecutor {
|
|
|
1340
1359
|
// READ defaulting: identity scopes plus the grant mirror, so an omitted
|
|
1341
1360
|
// scopes arg recalls everything this run is ALLOWED to read instead of
|
|
1342
1361
|
// silently less than the enforcer would accept.
|
|
1343
|
-
const mirror = (
|
|
1362
|
+
const mirror = this.readScopeMirrorFor(toolName, ctx.envelope, ctx.channelGrantSnapshot) ?? [];
|
|
1344
1363
|
const seen = new Set(ctx.envelope.scope.memory_scopes.map((scope) => `${scope.kind}:${scope.id}`));
|
|
1345
1364
|
return {
|
|
1346
1365
|
...scopedInput,
|
|
@@ -1433,7 +1452,7 @@ class GatewayToolExecutor {
|
|
|
1433
1452
|
typeof candidate.reasoning === 'string' &&
|
|
1434
1453
|
candidate.reasoning.length > 0);
|
|
1435
1454
|
}
|
|
1436
|
-
logGatewayToolCall(ctx, toolName, result, durationMs, scopeAudit, gatewayCallId, error) {
|
|
1455
|
+
logGatewayToolCall(ctx, toolName, result, durationMs, scopeAudit, gatewayCallId, toolDetails, error) {
|
|
1437
1456
|
try {
|
|
1438
1457
|
if (!this.sessionsDb) {
|
|
1439
1458
|
return;
|
|
@@ -1467,6 +1486,7 @@ class GatewayToolExecutor {
|
|
|
1467
1486
|
...(ctx?.workorderAttemptId !== undefined
|
|
1468
1487
|
? { workorder_attempt_id: ctx.workorderAttemptId }
|
|
1469
1488
|
: {}),
|
|
1489
|
+
...toolDetails,
|
|
1470
1490
|
},
|
|
1471
1491
|
});
|
|
1472
1492
|
}
|
|
@@ -1474,6 +1494,16 @@ class GatewayToolExecutor {
|
|
|
1474
1494
|
securityLogger.warn('[envelope] gateway audit log failed (non-fatal)', logErr);
|
|
1475
1495
|
}
|
|
1476
1496
|
}
|
|
1497
|
+
gatewayTraceDetails(toolName, result) {
|
|
1498
|
+
if (toolName !== 'report_publish')
|
|
1499
|
+
return {};
|
|
1500
|
+
const slotIds = result?.acceptedSlotIds;
|
|
1501
|
+
if (!Array.isArray(slotIds) || slotIds.some((slotId) => typeof slotId !== 'string'))
|
|
1502
|
+
return {};
|
|
1503
|
+
// Audit only the structural slot identity. Board HTML/content must never
|
|
1504
|
+
// enter gateway trace details.
|
|
1505
|
+
return { report_slot_ids: [...slotIds].sort() };
|
|
1506
|
+
}
|
|
1477
1507
|
alarmScopeMismatch(ctx, toolName) {
|
|
1478
1508
|
try {
|
|
1479
1509
|
this.metricsStore?.record({
|
|
@@ -1643,11 +1673,73 @@ class GatewayToolExecutor {
|
|
|
1643
1673
|
success: true,
|
|
1644
1674
|
result: (0, drive_tools_js_1.asUntrustedDriveEvidence)(await this.driveTools.download(input, this.getExecutionState().signal)),
|
|
1645
1675
|
};
|
|
1646
|
-
case 'drive_upload':
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1676
|
+
case 'drive_upload': {
|
|
1677
|
+
const uploadInput = input;
|
|
1678
|
+
const state = this.getExecutionState();
|
|
1679
|
+
const sourceMessageRef = state.sourceMessageRef;
|
|
1680
|
+
if (!sourceMessageRef?.startsWith('owner-event:')) {
|
|
1681
|
+
return {
|
|
1682
|
+
success: true,
|
|
1683
|
+
result: (0, drive_tools_js_1.asUntrustedDriveEvidence)(await this.driveTools.upload(uploadInput)),
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
const effect = this.requireOwnerEventEffect(uploadInput.effect_key, 'drive_upload');
|
|
1687
|
+
const ledger = this.requireOwnerEventEffectLedger();
|
|
1688
|
+
const occurrence = `${sourceMessageRef}:drive:${effect.actionKey}`;
|
|
1689
|
+
let reservation = ledger.inspect(effect.batchId, effect.actionKey, 'drive_upload');
|
|
1690
|
+
if (reservation?.state === 'confirmed') {
|
|
1691
|
+
if (!reservation.result) {
|
|
1692
|
+
throw new Error('Confirmed Drive upload is missing its durable result');
|
|
1693
|
+
}
|
|
1694
|
+
return { success: true, result: (0, drive_tools_js_1.asUntrustedDriveEvidence)(reservation.result) };
|
|
1695
|
+
}
|
|
1696
|
+
if (!reservation) {
|
|
1697
|
+
// Local validation and the read-only marker lookup are safely retryable.
|
|
1698
|
+
// Do them before the durable transition that means a create may have escaped.
|
|
1699
|
+
const preparation = await this.driveTools.prepareUpload(uploadInput, occurrence);
|
|
1700
|
+
reservation = ledger.begin(effect.batchId, effect.actionKey, 'drive_upload', {
|
|
1701
|
+
folderId: preparation.prepared.folderId,
|
|
1702
|
+
fileName: preparation.prepared.fileName,
|
|
1703
|
+
});
|
|
1704
|
+
if (reservation.state === 'confirmed') {
|
|
1705
|
+
if (!reservation.result) {
|
|
1706
|
+
throw new Error('Confirmed Drive upload is missing its durable result');
|
|
1707
|
+
}
|
|
1708
|
+
return { success: true, result: (0, drive_tools_js_1.asUntrustedDriveEvidence)(reservation.result) };
|
|
1709
|
+
}
|
|
1710
|
+
if (reservation.state === 'execute' && preparation.existing) {
|
|
1711
|
+
ledger.confirm(effect.batchId, effect.actionKey, 'drive_upload', preparation.existing);
|
|
1712
|
+
return {
|
|
1713
|
+
success: true,
|
|
1714
|
+
result: (0, drive_tools_js_1.asUntrustedDriveEvidence)(preparation.existing),
|
|
1715
|
+
};
|
|
1716
|
+
}
|
|
1717
|
+
if (reservation.state === 'execute') {
|
|
1718
|
+
try {
|
|
1719
|
+
const result = await this.driveTools.transmitPreparedUpload(preparation.prepared);
|
|
1720
|
+
ledger.confirm(effect.batchId, effect.actionKey, 'drive_upload', result);
|
|
1721
|
+
return { success: true, result: (0, drive_tools_js_1.asUntrustedDriveEvidence)(result) };
|
|
1722
|
+
}
|
|
1723
|
+
catch (error) {
|
|
1724
|
+
ledger.markUnknown(effect.batchId, effect.actionKey, 'drive_upload', error instanceof Error ? error.message : String(error));
|
|
1725
|
+
throw error;
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
const folderId = reservation.intent.folderId;
|
|
1730
|
+
if (typeof folderId !== 'string') {
|
|
1731
|
+
throw new Error('Owner-event Drive reservation has invalid durable intent');
|
|
1732
|
+
}
|
|
1733
|
+
try {
|
|
1734
|
+
const result = await this.driveTools.recoverUpload(folderId, occurrence);
|
|
1735
|
+
ledger.confirm(effect.batchId, effect.actionKey, 'drive_upload', result);
|
|
1736
|
+
return { success: true, result: (0, drive_tools_js_1.asUntrustedDriveEvidence)(result) };
|
|
1737
|
+
}
|
|
1738
|
+
catch (error) {
|
|
1739
|
+
ledger.markUnknown(effect.batchId, effect.actionKey, 'drive_upload', error instanceof Error ? error.message : String(error));
|
|
1740
|
+
throw error;
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1651
1743
|
// Browser tools
|
|
1652
1744
|
case 'os_get_config':
|
|
1653
1745
|
return await this.executeGetConfig(input);
|
|
@@ -1771,11 +1863,28 @@ class GatewayToolExecutor {
|
|
|
1771
1863
|
}
|
|
1772
1864
|
}
|
|
1773
1865
|
if (this.reportPublisher) {
|
|
1774
|
-
this.reportPublisher(slotsInput);
|
|
1775
|
-
|
|
1866
|
+
const publication = this.reportPublisher(slotsInput);
|
|
1867
|
+
// Backward compatibility: older injected publishers return void
|
|
1868
|
+
// or the exact changed slot array. Production distinguishes slots
|
|
1869
|
+
// accepted as present from slots whose HTML actually changed.
|
|
1870
|
+
const acceptedSlotIds = Array.isArray(publication)
|
|
1871
|
+
? [...new Set(publication)].sort()
|
|
1872
|
+
: isReportPublishResult(publication)
|
|
1873
|
+
? [...new Set(publication.acceptedSlotIds)].sort()
|
|
1874
|
+
: Object.keys(slotsInput).sort();
|
|
1875
|
+
const changedSlotIds = Array.isArray(publication)
|
|
1876
|
+
? [...acceptedSlotIds]
|
|
1877
|
+
: isReportPublishResult(publication)
|
|
1878
|
+
? [...new Set(publication.changedSlotIds)].sort()
|
|
1879
|
+
: [...acceptedSlotIds];
|
|
1880
|
+
if (acceptedSlotIds.length === 0) {
|
|
1881
|
+
throw new types_js_1.AgentError('Report publisher accepted no slots', 'TOOL_ERROR', undefined, false);
|
|
1882
|
+
}
|
|
1776
1883
|
return {
|
|
1777
1884
|
success: true,
|
|
1778
|
-
|
|
1885
|
+
acceptedSlotIds,
|
|
1886
|
+
changedSlotIds,
|
|
1887
|
+
message: `Dashboard report accepted: ${acceptedSlotIds.join(', ')} (${acceptedSlotIds.length} accepted, ${changedSlotIds.length} changed)`,
|
|
1779
1888
|
};
|
|
1780
1889
|
}
|
|
1781
1890
|
throw new types_js_1.AgentError('Report publisher not configured', 'TOOL_ERROR', undefined, false);
|
|
@@ -2747,7 +2856,7 @@ class GatewayToolExecutor {
|
|
|
2747
2856
|
* Execute telegram_send tool - Send message/file to Telegram chat
|
|
2748
2857
|
*/
|
|
2749
2858
|
async executeTelegramSend(input) {
|
|
2750
|
-
const { chat_id, message, file_path, sticker_emotion } = input;
|
|
2859
|
+
const { chat_id, message, file_path, sticker_emotion, delivery_key } = input;
|
|
2751
2860
|
if (!chat_id) {
|
|
2752
2861
|
return { success: false, error: 'chat_id is required' };
|
|
2753
2862
|
}
|
|
@@ -2755,21 +2864,56 @@ class GatewayToolExecutor {
|
|
|
2755
2864
|
return { success: false, error: 'Telegram gateway not configured' };
|
|
2756
2865
|
}
|
|
2757
2866
|
const sourceMessageRef = this.getExecutionState().sourceMessageRef;
|
|
2867
|
+
const ownerEvent = sourceMessageRef?.startsWith('owner-event:') === true;
|
|
2868
|
+
const deliveryVariant = sticker_emotion
|
|
2869
|
+
? 'sticker'
|
|
2870
|
+
: file_path
|
|
2871
|
+
? TELEGRAM_PHOTO_EXTENSIONS.has((0, path_1.extname)(file_path).toLowerCase())
|
|
2872
|
+
? 'image'
|
|
2873
|
+
: 'file'
|
|
2874
|
+
: 'text';
|
|
2875
|
+
let ownerEffect = null;
|
|
2876
|
+
let ownerLedger = null;
|
|
2877
|
+
try {
|
|
2878
|
+
if (ownerEvent) {
|
|
2879
|
+
ownerEffect = this.requireOwnerEventEffect(delivery_key, 'telegram_send');
|
|
2880
|
+
ownerLedger = this.requireOwnerEventEffectLedger();
|
|
2881
|
+
const reservation = ownerLedger.begin(ownerEffect.batchId, ownerEffect.actionKey, 'telegram_send', { chatId: chat_id, variant: deliveryVariant });
|
|
2882
|
+
if (reservation.state === 'confirmed')
|
|
2883
|
+
return { success: true };
|
|
2884
|
+
if (reservation.intent.chatId !== chat_id) {
|
|
2885
|
+
return {
|
|
2886
|
+
success: false,
|
|
2887
|
+
error: 'owner-event Telegram target differs from the host-reserved destination',
|
|
2888
|
+
};
|
|
2889
|
+
}
|
|
2890
|
+
if (reservation.intent.variant !== deliveryVariant) {
|
|
2891
|
+
return {
|
|
2892
|
+
success: false,
|
|
2893
|
+
error: 'owner-event Telegram retry must use the originally reserved delivery variant',
|
|
2894
|
+
};
|
|
2895
|
+
}
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2898
|
+
catch (error) {
|
|
2899
|
+
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
2900
|
+
}
|
|
2758
2901
|
const idempotencyKey = sourceMessageRef
|
|
2759
|
-
?
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2902
|
+
? ownerEvent
|
|
2903
|
+
? `${sourceMessageRef}:telegram:${delivery_key}`
|
|
2904
|
+
: (0, crypto_1.createHash)('sha256')
|
|
2905
|
+
.update(JSON.stringify([
|
|
2906
|
+
sourceMessageRef,
|
|
2907
|
+
chat_id,
|
|
2908
|
+
message ?? null,
|
|
2909
|
+
file_path ?? null,
|
|
2910
|
+
sticker_emotion ?? null,
|
|
2911
|
+
]))
|
|
2912
|
+
.digest('hex')
|
|
2768
2913
|
: undefined;
|
|
2769
2914
|
try {
|
|
2770
2915
|
if (sticker_emotion) {
|
|
2771
|
-
await (this.telegramGateway.sendStickerFromActiveTurn?.(chat_id, sticker_emotion) ??
|
|
2772
|
-
this.telegramGateway.sendSticker(chat_id, sticker_emotion));
|
|
2916
|
+
await (this.telegramGateway.sendStickerFromActiveTurn?.(chat_id, sticker_emotion, idempotencyKey) ?? this.telegramGateway.sendSticker(chat_id, sticker_emotion, idempotencyKey));
|
|
2773
2917
|
}
|
|
2774
2918
|
else if (file_path) {
|
|
2775
2919
|
const safePath = resolvePrivateWorkspaceFile(file_path);
|
|
@@ -2820,12 +2964,36 @@ class GatewayToolExecutor {
|
|
|
2820
2964
|
error: 'Either message, file_path, or sticker_emotion is required',
|
|
2821
2965
|
};
|
|
2822
2966
|
}
|
|
2967
|
+
if (ownerEffect && ownerLedger) {
|
|
2968
|
+
ownerLedger.confirm(ownerEffect.batchId, ownerEffect.actionKey, 'telegram_send', null);
|
|
2969
|
+
}
|
|
2823
2970
|
return { success: true };
|
|
2824
2971
|
}
|
|
2825
2972
|
catch (err) {
|
|
2973
|
+
if (ownerEffect && ownerLedger) {
|
|
2974
|
+
ownerLedger.markUnknown(ownerEffect.batchId, ownerEffect.actionKey, 'telegram_send', err instanceof Error ? err.message : String(err));
|
|
2975
|
+
}
|
|
2826
2976
|
return { success: false, error: `Failed to send to Telegram: ${err}` };
|
|
2827
2977
|
}
|
|
2828
2978
|
}
|
|
2979
|
+
requireOwnerEventEffect(actionKey, toolName) {
|
|
2980
|
+
const state = this.getExecutionState();
|
|
2981
|
+
const authority = state.ownerEventEffects;
|
|
2982
|
+
if (!authority || state.sourceMessageRef !== `owner-event:${authority.batchId}`) {
|
|
2983
|
+
throw new Error(`owner-event ${toolName} requires host-issued effect authority`);
|
|
2984
|
+
}
|
|
2985
|
+
const expectedKey = authority.effectKeys[toolName];
|
|
2986
|
+
if (actionKey !== expectedKey) {
|
|
2987
|
+
throw new Error(`owner-event ${toolName} requires the host-issued ${toolName} key ${expectedKey}`);
|
|
2988
|
+
}
|
|
2989
|
+
return { batchId: authority.batchId, actionKey };
|
|
2990
|
+
}
|
|
2991
|
+
requireOwnerEventEffectLedger() {
|
|
2992
|
+
if (!this.ownerEventEffectLedger) {
|
|
2993
|
+
throw new Error('owner-event external effects are disabled without the durable effect ledger');
|
|
2994
|
+
}
|
|
2995
|
+
return this.ownerEventEffectLedger;
|
|
2996
|
+
}
|
|
2829
2997
|
/**
|
|
2830
2998
|
* Execute os_get_config tool - Get current configuration
|
|
2831
2999
|
* Masks sensitive data for non-viewer sources
|
|
@@ -3279,7 +3447,7 @@ class GatewayToolExecutor {
|
|
|
3279
3447
|
// back excerpts from every other channel of the connector. Citation would then be
|
|
3280
3448
|
// strictly wider than reading, which is the one thing this path must never be.
|
|
3281
3449
|
const citationChannels = ctx.envelope
|
|
3282
|
-
? (0, read_js_1.narrowGrantToEnvelope)(
|
|
3450
|
+
? (0, read_js_1.narrowGrantToEnvelope)(ctx.channelGrantSnapshot ?? {}, {
|
|
3283
3451
|
connectors,
|
|
3284
3452
|
scopes: ctx.envelope.scope.memory_scopes ?? [],
|
|
3285
3453
|
})
|
|
@@ -3424,6 +3592,7 @@ class GatewayToolExecutor {
|
|
|
3424
3592
|
caller: 'gateway',
|
|
3425
3593
|
envelope: ctx.envelope,
|
|
3426
3594
|
modelRunId: ctx.modelRunId ?? null,
|
|
3595
|
+
channelGrantSnapshot: ctx.channelGrantSnapshot,
|
|
3427
3596
|
input: effectiveInput,
|
|
3428
3597
|
signal: ctx.signal,
|
|
3429
3598
|
beforePersist: temporalContext
|
|
@@ -3545,6 +3714,10 @@ function getContextPacketIdForTrustedProvenance(input) {
|
|
|
3545
3714
|
function dedupeSourceRefs(refs) {
|
|
3546
3715
|
return [...new Set(refs)];
|
|
3547
3716
|
}
|
|
3717
|
+
function snapshotChannelGrant(provider) {
|
|
3718
|
+
const liveGrant = provider();
|
|
3719
|
+
return Object.fromEntries(Object.entries(liveGrant).map(([connector, channels]) => [connector, [...channels]]));
|
|
3720
|
+
}
|
|
3548
3721
|
function normalizeMemoryScopes(value) {
|
|
3549
3722
|
if (!Array.isArray(value) || value.length === 0) {
|
|
3550
3723
|
return null;
|