@jungjaehoon/mama-os 0.20.1 → 0.22.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/CHANGELOG.md +31 -0
- package/README.md +12 -4
- package/dist/agent/agent-loop.d.ts.map +1 -1
- package/dist/agent/agent-loop.js +76 -11
- 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 +88 -3
- package/dist/agent/code-act/host-bridge.js.map +1 -1
- package/dist/agent/codex-mcp-process.d.ts +1 -0
- package/dist/agent/codex-mcp-process.d.ts.map +1 -1
- package/dist/agent/codex-mcp-process.js +3 -2
- package/dist/agent/codex-mcp-process.js.map +1 -1
- package/dist/agent/gateway-tool-executor.d.ts +24 -11
- package/dist/agent/gateway-tool-executor.d.ts.map +1 -1
- package/dist/agent/gateway-tool-executor.js +349 -30
- package/dist/agent/gateway-tool-executor.js.map +1 -1
- package/dist/agent/gateway-tools.md +7 -2
- package/dist/agent/model-runner.d.ts +8 -0
- package/dist/agent/model-runner.d.ts.map +1 -1
- package/dist/agent/model-runner.js.map +1 -1
- package/dist/agent/os-agent-capabilities.md +13 -12
- package/dist/agent/persistent-cli-adapter.d.ts +6 -0
- package/dist/agent/persistent-cli-adapter.d.ts.map +1 -1
- package/dist/agent/persistent-cli-adapter.js +21 -10
- package/dist/agent/persistent-cli-adapter.js.map +1 -1
- package/dist/agent/tool-registry.d.ts.map +1 -1
- package/dist/agent/tool-registry.js +33 -2
- package/dist/agent/tool-registry.js.map +1 -1
- package/dist/agent/types.d.ts +30 -2
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/api/graph-api.d.ts.map +1 -1
- package/dist/api/graph-api.js +78 -5
- package/dist/api/graph-api.js.map +1 -1
- package/dist/api/index.d.ts +8 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +18 -12
- package/dist/api/index.js.map +1 -1
- package/dist/api/operator-handler.d.ts +19 -0
- package/dist/api/operator-handler.d.ts.map +1 -0
- package/dist/api/operator-handler.js +106 -0
- package/dist/api/operator-handler.js.map +1 -0
- package/dist/api/operator-summary.d.ts +3 -0
- package/dist/api/operator-summary.d.ts.map +1 -0
- package/dist/api/operator-summary.js +72 -0
- package/dist/api/operator-summary.js.map +1 -0
- package/dist/api/operator-tasks-handler.d.ts +7 -0
- package/dist/api/operator-tasks-handler.d.ts.map +1 -0
- package/dist/api/operator-tasks-handler.js +165 -0
- package/dist/api/operator-tasks-handler.js.map +1 -0
- package/dist/api/report-handler.d.ts +7 -0
- package/dist/api/report-handler.d.ts.map +1 -1
- package/dist/api/report-handler.js +30 -0
- package/dist/api/report-handler.js.map +1 -1
- package/dist/api/report-persistence.d.ts +17 -0
- package/dist/api/report-persistence.d.ts.map +1 -0
- package/dist/api/report-persistence.js +91 -0
- package/dist/api/report-persistence.js.map +1 -0
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +402 -250
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/config/config-manager.d.ts.map +1 -1
- package/dist/cli/config/config-manager.js +93 -55
- package/dist/cli/config/config-manager.js.map +1 -1
- package/dist/cli/config/types.d.ts +17 -2
- package/dist/cli/config/types.d.ts.map +1 -1
- package/dist/cli/config/types.js +4 -0
- package/dist/cli/config/types.js.map +1 -1
- package/dist/cli/runtime/agent-loop-init.d.ts +3 -1
- package/dist/cli/runtime/agent-loop-init.d.ts.map +1 -1
- package/dist/cli/runtime/agent-loop-init.js +16 -7
- package/dist/cli/runtime/agent-loop-init.js.map +1 -1
- package/dist/cli/runtime/api-routes-init.d.ts.map +1 -1
- package/dist/cli/runtime/api-routes-init.js +503 -259
- 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 +12 -7
- package/dist/cli/runtime/api-server-init.js.map +1 -1
- package/dist/cli/runtime/connector-init.d.ts +19 -1
- package/dist/cli/runtime/connector-init.d.ts.map +1 -1
- package/dist/cli/runtime/connector-init.js +32 -2
- package/dist/cli/runtime/connector-init.js.map +1 -1
- package/dist/cli/runtime/gateway-init.d.ts.map +1 -1
- package/dist/cli/runtime/gateway-init.js +3 -1
- package/dist/cli/runtime/gateway-init.js.map +1 -1
- package/dist/cli/runtime/memory-agent-init.d.ts +2 -1
- package/dist/cli/runtime/memory-agent-init.d.ts.map +1 -1
- package/dist/cli/runtime/memory-agent-init.js +15 -3
- package/dist/cli/runtime/memory-agent-init.js.map +1 -1
- package/dist/cli/runtime/message-router-config.d.ts +4 -0
- package/dist/cli/runtime/message-router-config.d.ts.map +1 -0
- package/dist/cli/runtime/message-router-config.js +11 -0
- package/dist/cli/runtime/message-router-config.js.map +1 -0
- package/dist/cli/runtime/scheduler-init.d.ts.map +1 -1
- package/dist/cli/runtime/scheduler-init.js +12 -12
- package/dist/cli/runtime/scheduler-init.js.map +1 -1
- package/dist/connectors/framework/polling-scheduler.d.ts.map +1 -1
- package/dist/connectors/framework/polling-scheduler.js +53 -2
- package/dist/connectors/framework/polling-scheduler.js.map +1 -1
- package/dist/connectors/framework/types.d.ts +8 -0
- package/dist/connectors/framework/types.d.ts.map +1 -1
- package/dist/connectors/kagemusha/query-tools.d.ts.map +1 -1
- package/dist/connectors/kagemusha/query-tools.js +14 -3
- package/dist/connectors/kagemusha/query-tools.js.map +1 -1
- package/dist/connectors/slack/index.d.ts.map +1 -1
- package/dist/connectors/slack/index.js +3 -1
- package/dist/connectors/slack/index.js.map +1 -1
- package/dist/connectors/trello/index.d.ts.map +1 -1
- package/dist/connectors/trello/index.js +6 -2
- package/dist/connectors/trello/index.js.map +1 -1
- package/dist/db/agent-store.d.ts +5 -0
- package/dist/db/agent-store.d.ts.map +1 -1
- package/dist/db/agent-store.js +6 -3
- package/dist/db/agent-store.js.map +1 -1
- package/dist/db/migrations/agent-activity-tool-name.d.ts +8 -0
- package/dist/db/migrations/agent-activity-tool-name.d.ts.map +1 -0
- package/dist/db/migrations/agent-activity-tool-name.js +24 -0
- package/dist/db/migrations/agent-activity-tool-name.js.map +1 -0
- package/dist/db/migrations/wiki-artifacts.d.ts +3 -0
- package/dist/db/migrations/wiki-artifacts.d.ts.map +1 -0
- package/dist/db/migrations/wiki-artifacts.js +24 -0
- package/dist/db/migrations/wiki-artifacts.js.map +1 -0
- package/dist/envelope/run-guard.d.ts +10 -0
- package/dist/envelope/run-guard.d.ts.map +1 -0
- package/dist/envelope/run-guard.js +19 -0
- package/dist/envelope/run-guard.js.map +1 -0
- package/dist/gateways/message-router.d.ts.map +1 -1
- package/dist/gateways/message-router.js +15 -3
- package/dist/gateways/message-router.js.map +1 -1
- package/dist/gateways/types.d.ts +4 -0
- package/dist/gateways/types.d.ts.map +1 -1
- package/dist/multi-agent/agent-event-bus.d.ts +14 -0
- package/dist/multi-agent/agent-event-bus.d.ts.map +1 -1
- package/dist/multi-agent/agent-event-bus.js +34 -0
- package/dist/multi-agent/agent-event-bus.js.map +1 -1
- package/dist/multi-agent/conductor-persona.js +2 -2
- package/dist/multi-agent/dashboard-agent-persona.d.ts +6 -2
- package/dist/multi-agent/dashboard-agent-persona.d.ts.map +1 -1
- package/dist/multi-agent/dashboard-agent-persona.js +65 -32
- package/dist/multi-agent/dashboard-agent-persona.js.map +1 -1
- package/dist/multi-agent/memory-agent-persona.d.ts +1 -1
- package/dist/multi-agent/memory-agent-persona.d.ts.map +1 -1
- package/dist/multi-agent/memory-agent-persona.js +25 -4
- package/dist/multi-agent/memory-agent-persona.js.map +1 -1
- package/dist/multi-agent/runtime-process.d.ts +4 -2
- package/dist/multi-agent/runtime-process.d.ts.map +1 -1
- package/dist/multi-agent/runtime-process.js +7 -4
- package/dist/multi-agent/runtime-process.js.map +1 -1
- package/dist/multi-agent/types.d.ts +1 -1
- package/dist/multi-agent/wiki-agent-persona.d.ts +7 -1
- package/dist/multi-agent/wiki-agent-persona.d.ts.map +1 -1
- package/dist/multi-agent/wiki-agent-persona.js +82 -68
- package/dist/multi-agent/wiki-agent-persona.js.map +1 -1
- package/dist/operator/action-verifier.d.ts +50 -0
- package/dist/operator/action-verifier.d.ts.map +1 -0
- package/dist/operator/action-verifier.js +68 -0
- package/dist/operator/action-verifier.js.map +1 -0
- package/dist/operator/board-reconcile.d.ts +62 -0
- package/dist/operator/board-reconcile.d.ts.map +1 -0
- package/dist/operator/board-reconcile.js +160 -0
- package/dist/operator/board-reconcile.js.map +1 -0
- package/dist/operator/board-slot-instructions.d.ts +26 -0
- package/dist/operator/board-slot-instructions.d.ts.map +1 -0
- package/dist/operator/board-slot-instructions.js +76 -0
- package/dist/operator/board-slot-instructions.js.map +1 -0
- package/dist/operator/connector-delta-repo.d.ts +33 -0
- package/dist/operator/connector-delta-repo.d.ts.map +1 -0
- package/dist/operator/connector-delta-repo.js +0 -0
- package/dist/operator/connector-delta-repo.js.map +1 -0
- package/dist/operator/mama-memory-port.d.ts +13 -0
- package/dist/operator/mama-memory-port.d.ts.map +1 -0
- package/dist/operator/mama-memory-port.js +35 -0
- package/dist/operator/mama-memory-port.js.map +1 -0
- package/dist/operator/operator-interfaces.d.ts +136 -0
- package/dist/operator/operator-interfaces.d.ts.map +1 -0
- package/dist/operator/operator-interfaces.js +15 -0
- package/dist/operator/operator-interfaces.js.map +1 -0
- package/dist/operator/operator-trigger-loop.d.ts +119 -0
- package/dist/operator/operator-trigger-loop.d.ts.map +1 -0
- package/dist/operator/operator-trigger-loop.js +267 -0
- package/dist/operator/operator-trigger-loop.js.map +1 -0
- package/dist/operator/report-run.d.ts +78 -0
- package/dist/operator/report-run.d.ts.map +1 -0
- package/dist/operator/report-run.js +141 -0
- package/dist/operator/report-run.js.map +1 -0
- package/dist/operator/report-scheduler.d.ts +66 -0
- package/dist/operator/report-scheduler.d.ts.map +1 -0
- package/dist/operator/report-scheduler.js +135 -0
- package/dist/operator/report-scheduler.js.map +1 -0
- package/dist/operator/situation-report.d.ts +90 -0
- package/dist/operator/situation-report.d.ts.map +1 -0
- package/dist/operator/situation-report.js +221 -0
- package/dist/operator/situation-report.js.map +1 -0
- package/dist/operator/task-ledger.d.ts +96 -0
- package/dist/operator/task-ledger.d.ts.map +1 -0
- package/dist/operator/task-ledger.js +277 -0
- package/dist/operator/task-ledger.js.map +1 -0
- package/dist/operator/trigger-author.d.ts +45 -0
- package/dist/operator/trigger-author.d.ts.map +1 -0
- package/dist/operator/trigger-author.js +217 -0
- package/dist/operator/trigger-author.js.map +1 -0
- package/dist/operator/trigger-evolve.d.ts +31 -0
- package/dist/operator/trigger-evolve.d.ts.map +1 -0
- package/dist/operator/trigger-evolve.js +51 -0
- package/dist/operator/trigger-evolve.js.map +1 -0
- package/dist/operator/trigger-fire.d.ts +29 -0
- package/dist/operator/trigger-fire.d.ts.map +1 -0
- package/dist/operator/trigger-fire.js +41 -0
- package/dist/operator/trigger-fire.js.map +1 -0
- package/dist/operator/trigger-matcher.d.ts +19 -0
- package/dist/operator/trigger-matcher.d.ts.map +1 -0
- package/dist/operator/trigger-matcher.js +61 -0
- package/dist/operator/trigger-matcher.js.map +1 -0
- package/dist/operator/trigger-registry.d.ts +36 -0
- package/dist/operator/trigger-registry.d.ts.map +1 -0
- package/dist/operator/trigger-registry.js +135 -0
- package/dist/operator/trigger-registry.js.map +1 -0
- package/dist/operator/trigger-review.d.ts +23 -0
- package/dist/operator/trigger-review.d.ts.map +1 -0
- package/dist/operator/trigger-review.js +127 -0
- package/dist/operator/trigger-review.js.map +1 -0
- package/dist/operator/trigger-types.d.ts +84 -0
- package/dist/operator/trigger-types.d.ts.map +1 -0
- package/dist/operator/trigger-types.js +14 -0
- package/dist/operator/trigger-types.js.map +1 -0
- package/dist/scheduler/cron-worker.d.ts.map +1 -1
- package/dist/scheduler/cron-worker.js +3 -1
- package/dist/scheduler/cron-worker.js.map +1 -1
- package/dist/security/security-monitor.d.ts.map +1 -1
- package/dist/security/security-monitor.js +1 -0
- package/dist/security/security-monitor.js.map +1 -1
- package/dist/wiki/obsidian-writer.d.ts +1 -1
- package/dist/wiki/obsidian-writer.d.ts.map +1 -1
- package/dist/wiki/obsidian-writer.js +67 -27
- package/dist/wiki/obsidian-writer.js.map +1 -1
- package/dist/wiki/path-safety.d.ts +2 -0
- package/dist/wiki/path-safety.d.ts.map +1 -0
- package/dist/wiki/path-safety.js +40 -0
- package/dist/wiki/path-safety.js.map +1 -0
- package/dist/wiki/types.d.ts +4 -2
- package/dist/wiki/types.d.ts.map +1 -1
- package/dist/wiki/types.js +1 -1
- package/dist/wiki/types.js.map +1 -1
- package/dist/wiki-artifacts/normalization.d.ts +8 -0
- package/dist/wiki-artifacts/normalization.d.ts.map +1 -0
- package/dist/wiki-artifacts/normalization.js +41 -0
- package/dist/wiki-artifacts/normalization.js.map +1 -0
- package/dist/wiki-artifacts/types.d.ts +52 -0
- package/dist/wiki-artifacts/types.d.ts.map +1 -0
- package/dist/wiki-artifacts/types.js +3 -0
- package/dist/wiki-artifacts/types.js.map +1 -0
- package/dist/wiki-artifacts/wiki-publish-adapter.d.ts +14 -0
- package/dist/wiki-artifacts/wiki-publish-adapter.d.ts.map +1 -0
- package/dist/wiki-artifacts/wiki-publish-adapter.js +71 -0
- package/dist/wiki-artifacts/wiki-publish-adapter.js.map +1 -0
- package/package.json +5 -3
- package/public/ui/assets/index-CKOJQYXA.css +1 -0
- package/public/ui/assets/index-OSgiwL24.js +62 -0
- package/public/ui/index.html +14 -0
- package/public/ui/theme-init.js +20 -0
- package/public/viewer/js/utils/api.js +2 -2
- package/public/viewer/src/utils/api.ts +9 -2
- package/public/viewer/sw.js +1 -1
- package/public/viewer/viewer.html +17 -27
|
@@ -65,6 +65,7 @@ const index_js_2 = require("../../gateways/index.js");
|
|
|
65
65
|
const graph_api_js_1 = require("../../api/graph-api.js");
|
|
66
66
|
const sqlite_js_1 = __importDefault(require("../../sqlite.js"));
|
|
67
67
|
const node_fs_1 = require("node:fs");
|
|
68
|
+
const node_path_1 = require("node:path");
|
|
68
69
|
const minimatch_1 = require("minimatch");
|
|
69
70
|
const ui_command_handler_js_1 = require("../../api/ui-command-handler.js");
|
|
70
71
|
const agent_store_js_1 = require("../../db/agent-store.js");
|
|
@@ -85,6 +86,7 @@ const api_routes_init_js_1 = require("../runtime/api-routes-init.js");
|
|
|
85
86
|
const server_start_js_1 = require("../runtime/server-start.js");
|
|
86
87
|
const shutdown_js_1 = require("../runtime/shutdown.js");
|
|
87
88
|
const envelope_bootstrap_js_1 = require("../runtime/envelope-bootstrap.js");
|
|
89
|
+
const message_router_config_js_1 = require("../runtime/message-router-config.js");
|
|
88
90
|
const reactive_config_js_1 = require("../../envelope/reactive-config.js");
|
|
89
91
|
const scope_context_js_1 = require("../../memory/scope-context.js");
|
|
90
92
|
const types_js_1 = require("../config/types.js");
|
|
@@ -103,6 +105,9 @@ const CODE_ACT_MUTATION_TOOLS = new Set([
|
|
|
103
105
|
'mama_ingest',
|
|
104
106
|
'report_publish',
|
|
105
107
|
'wiki_publish',
|
|
108
|
+
'task_create',
|
|
109
|
+
'task_update',
|
|
110
|
+
'contract_no_update',
|
|
106
111
|
]);
|
|
107
112
|
function isTruthyEnvValue(value) {
|
|
108
113
|
return value !== undefined && TRUTHY_ENV_VALUES.has(value.trim().toLowerCase());
|
|
@@ -498,9 +503,17 @@ async function runAgentLoop(config, options = {}) {
|
|
|
498
503
|
}
|
|
499
504
|
const agentLoopBackend = runtimeBackend === 'codex' || runtimeBackend === 'codex-mcp' ? 'codex-mcp' : 'claude';
|
|
500
505
|
// Initialize main agent loop + client (reasoning state is closure-scoped inside)
|
|
501
|
-
const { agentLoop, agentLoopClient } = (0, agent_loop_init_js_1.initMainAgentLoop)(config, oauthManager, db, metricsStore, agentLoopBackend,
|
|
506
|
+
const { agentLoop, agentLoopClient } = (0, agent_loop_init_js_1.initMainAgentLoop)(config, oauthManager, db, metricsStore, agentLoopBackend, toolExecutor, {
|
|
507
|
+
...options,
|
|
508
|
+
envelopeIssuanceMode: envelopeBootstrap.metadata.issuance,
|
|
509
|
+
});
|
|
502
510
|
// ── Phase 3: MAMA Core API ────────────────────────────────────────────────
|
|
503
511
|
const { mamaApi, mamaApiClient, connectorExtractionFn } = await (0, mama_core_init_js_1.initMamaCore)(config);
|
|
512
|
+
// Wire the boot MAMA API onto the shared executor so it never lazily builds a
|
|
513
|
+
// SECOND API/adapter stack against the same DB (initializeMAMAApi). This also
|
|
514
|
+
// lets the memory agent fold into the shared executor (Task 7) instead of
|
|
515
|
+
// carrying its own private instance just for this API.
|
|
516
|
+
toolExecutor.setMamaApi(mamaApi);
|
|
504
517
|
// getAdapter is still used directly in this file for DB queries after initDB has run
|
|
505
518
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
506
519
|
const { getAdapter } = require('@jungjaehoon/mama-core/db-manager');
|
|
@@ -510,12 +523,10 @@ async function runAgentLoop(config, options = {}) {
|
|
|
510
523
|
toolExecutor.setContextCompileService(contextCompileService);
|
|
511
524
|
agentLoop.setContextCompileService(contextCompileService);
|
|
512
525
|
// ── Phase 4: Memory Agent + MessageRouter ─────────────────────────────────
|
|
513
|
-
const messageRouter = new index_js_2.MessageRouter(sessionStore, agentLoopClient, mamaApiClient,
|
|
514
|
-
backend: runtimeBackend,
|
|
515
|
-
}, envelopeBootstrap.envelopeConfig, envelopeBootstrap.envelopeAuthority);
|
|
526
|
+
const messageRouter = new index_js_2.MessageRouter(sessionStore, agentLoopClient, mamaApiClient, (0, message_router_config_js_1.resolveMessageRouterConfig)(config, runtimeBackend), envelopeBootstrap.envelopeConfig, envelopeBootstrap.envelopeAuthority);
|
|
516
527
|
messageRouter.setSessionsDb(db);
|
|
517
528
|
// validationService wired after creation (Phase 5 below)
|
|
518
|
-
const { memoryAgentLoop } = await (0, memory_agent_init_js_1.initMemoryAgent)(oauthManager, config, mamaApi, mamaApiClient, messageRouter, agentLoopBackend);
|
|
529
|
+
const { memoryAgentLoop } = await (0, memory_agent_init_js_1.initMemoryAgent)(oauthManager, config, mamaApi, mamaApiClient, messageRouter, agentLoopBackend, toolExecutor);
|
|
519
530
|
// ── Phase 5: Graph Handler + Embedding ────────────────────────────────────
|
|
520
531
|
// Create singleton UI command queue for Agent↔Viewer communication
|
|
521
532
|
const uiCommandQueue = new ui_command_handler_js_1.UICommandQueue();
|
|
@@ -537,134 +548,132 @@ async function runAgentLoop(config, options = {}) {
|
|
|
537
548
|
agentLoop.setUICommandQueue(uiCommandQueue);
|
|
538
549
|
// Wire up Code-Act executor for POST /api/code-act endpoint
|
|
539
550
|
// Always register: Dashboard/Wiki agents use code-act via MCP → HTTP proxy
|
|
540
|
-
{
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
allowed_destinations: [],
|
|
576
|
-
},
|
|
577
|
-
tier: codeActTier,
|
|
578
|
-
budget: { wall_seconds: wallSeconds },
|
|
579
|
-
expires_at: new Date(Date.now() + wallSeconds * 1000 + 30_000).toISOString(),
|
|
580
|
-
});
|
|
581
|
-
const roleName = `code_act_${codeActAgentId}`;
|
|
582
|
-
const role = codeActRole;
|
|
583
|
-
const agentContext = {
|
|
584
|
-
source: 'watch',
|
|
585
|
-
platform: 'cli',
|
|
586
|
-
roleName,
|
|
587
|
-
role,
|
|
588
|
-
session: {
|
|
589
|
-
sessionId: `api:code-act:${instanceId}`,
|
|
590
|
-
channelId: 'api:code-act',
|
|
591
|
-
startedAt: new Date(),
|
|
592
|
-
},
|
|
593
|
-
capabilities: ['code_act'],
|
|
594
|
-
limitations: codeActReadOnly ? ['Code-Act read-only mode: memory writes disabled'] : [],
|
|
595
|
-
tier: codeActTier,
|
|
596
|
-
backend: 'claude',
|
|
597
|
-
};
|
|
598
|
-
executionContext = {
|
|
599
|
-
agentContext,
|
|
600
|
-
agentId: codeActAgentId,
|
|
601
|
-
source: 'watch',
|
|
602
|
-
channelId: 'api:code-act',
|
|
603
|
-
envelope,
|
|
604
|
-
executionSurface: 'code_act',
|
|
605
|
-
};
|
|
606
|
-
}
|
|
607
|
-
const parentRun = bindCodeActParentModelRun(getAdapter(), executionContext, {
|
|
608
|
-
inputSnapshotRef: `code-act:${instanceId}`,
|
|
609
|
-
inputRefs: {
|
|
610
|
-
tool: 'code_act',
|
|
611
|
-
source: 'api',
|
|
612
|
-
channel_id: 'api:code-act',
|
|
613
|
-
read_only: codeActReadOnly,
|
|
551
|
+
graphHandlerOptions.executeCodeAct = async (code, codeActContext) => {
|
|
552
|
+
const { CodeActSandbox, HostBridge } = await import('../../agent/code-act/index.js');
|
|
553
|
+
const sandbox = new CodeActSandbox();
|
|
554
|
+
const resolvedCodeActPolicy = resolveCodeActAgentPolicy(codeActContext, config.multi_agent?.agents, config.multi_agent?.default_agent || 'conductor');
|
|
555
|
+
if (resolvedCodeActPolicy.error) {
|
|
556
|
+
return { success: false, error: resolvedCodeActPolicy.error };
|
|
557
|
+
}
|
|
558
|
+
const codeActAgentId = resolvedCodeActPolicy.agentId;
|
|
559
|
+
const codeActPolicy = resolvedCodeActPolicy.policy ?? {};
|
|
560
|
+
const codeActRole = buildCodeActRole(codeActPolicy);
|
|
561
|
+
const codeActReadOnly = isTruthyEnvValue(process.env.MAMA_CODE_ACT_READ_ONLY);
|
|
562
|
+
const codeActTier = codeActReadOnly ? 3 : 2;
|
|
563
|
+
const instanceId = (0, node_crypto_1.randomUUID)();
|
|
564
|
+
let executionContext = null;
|
|
565
|
+
if (envelopeBootstrap.envelopeAuthority && envelopeBootstrap.metadata.issuance !== 'off') {
|
|
566
|
+
const projectId = (0, reactive_config_js_1.resolveReactiveProjectRoot)(config, process.env);
|
|
567
|
+
const projectRef = { kind: 'project', id: projectId };
|
|
568
|
+
const memoryScopes = resolveCodeActMemoryScopes((0, scope_context_js_1.deriveMemoryScopes)({
|
|
569
|
+
source: 'watch',
|
|
570
|
+
channelId: 'api:code-act',
|
|
571
|
+
userId: 'api',
|
|
572
|
+
projectId,
|
|
573
|
+
}), getAdapter());
|
|
574
|
+
const wallSeconds = Math.min(Math.max(Math.floor((config.timeouts?.agent_ms ?? 300_000) / 1000), 1), 300);
|
|
575
|
+
const envelope = envelopeBootstrap.envelopeAuthority.buildAndPersist({
|
|
576
|
+
agent_id: codeActAgentId,
|
|
577
|
+
instance_id: instanceId,
|
|
578
|
+
source: 'watch',
|
|
579
|
+
channel_id: 'api:code-act',
|
|
580
|
+
trigger_context: { user_text: '<api-code-act invocation>' },
|
|
581
|
+
scope: {
|
|
582
|
+
project_refs: [projectRef],
|
|
583
|
+
raw_connectors: codeActRawConnectors,
|
|
584
|
+
memory_scopes: memoryScopes,
|
|
585
|
+
allowed_destinations: [],
|
|
614
586
|
},
|
|
587
|
+
tier: codeActTier,
|
|
588
|
+
budget: { wall_seconds: wallSeconds },
|
|
589
|
+
expires_at: new Date(Date.now() + wallSeconds * 1000 + 30_000).toISOString(),
|
|
615
590
|
});
|
|
616
|
-
|
|
617
|
-
const
|
|
618
|
-
const
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
591
|
+
const roleName = `code_act_${codeActAgentId}`;
|
|
592
|
+
const role = codeActRole;
|
|
593
|
+
const agentContext = {
|
|
594
|
+
source: 'watch',
|
|
595
|
+
platform: 'cli',
|
|
596
|
+
roleName,
|
|
597
|
+
role,
|
|
598
|
+
session: {
|
|
599
|
+
sessionId: `api:code-act:${instanceId}`,
|
|
600
|
+
channelId: 'api:code-act',
|
|
601
|
+
startedAt: new Date(),
|
|
602
|
+
},
|
|
603
|
+
capabilities: ['code_act'],
|
|
604
|
+
limitations: codeActReadOnly ? ['Code-Act read-only mode: memory writes disabled'] : [],
|
|
605
|
+
tier: codeActTier,
|
|
606
|
+
backend: runtimeBackend,
|
|
631
607
|
};
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
608
|
+
executionContext = {
|
|
609
|
+
agentContext,
|
|
610
|
+
agentId: codeActAgentId,
|
|
611
|
+
source: 'watch',
|
|
612
|
+
channelId: 'api:code-act',
|
|
613
|
+
envelope,
|
|
614
|
+
executionSurface: 'code_act',
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
const parentRun = bindCodeActParentModelRun(getAdapter(), executionContext, {
|
|
618
|
+
inputSnapshotRef: `code-act:${instanceId}`,
|
|
619
|
+
inputRefs: {
|
|
620
|
+
tool: 'code_act',
|
|
621
|
+
source: 'api',
|
|
622
|
+
channel_id: 'api:code-act',
|
|
623
|
+
read_only: codeActReadOnly,
|
|
624
|
+
},
|
|
625
|
+
});
|
|
626
|
+
executionContext = parentRun.executionContext;
|
|
627
|
+
const bridge = new HostBridge(toolExecutor, new role_manager_js_1.RoleManager({ rolesConfig: config.roles ?? types_js_1.DEFAULT_ROLES }), executionContext);
|
|
628
|
+
const toolCalls = [];
|
|
629
|
+
bridge.onToolUse = (toolName, input, result) => {
|
|
630
|
+
if (result !== undefined) {
|
|
631
|
+
toolCalls.push({ name: toolName, input });
|
|
632
|
+
if (CODE_ACT_MUTATION_TOOLS.has(toolName)) {
|
|
633
|
+
codeActLogger.warn('[CodeAct] mutation tool call', {
|
|
634
|
+
toolName,
|
|
635
|
+
success: Boolean(result.success),
|
|
636
|
+
readOnly: codeActReadOnly,
|
|
637
|
+
envelopeHash: executionContext?.envelope?.envelope_hash ?? null,
|
|
638
|
+
});
|
|
639
|
+
}
|
|
655
640
|
}
|
|
656
641
|
};
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
642
|
+
const previousRoutingContext = toolExecutor.getCurrentAgentRoutingContext();
|
|
643
|
+
try {
|
|
644
|
+
// Set default agent context for /api/code-act calls (Conductor, tiered sandbox).
|
|
645
|
+
// Per-request executionContext carries envelope data; this routing context is legacy fallback.
|
|
646
|
+
toolExecutor.setCurrentAgentContext(codeActAgentId, 'api', 'code-act');
|
|
647
|
+
bridge.injectInto(sandbox, codeActTier, codeActRole);
|
|
648
|
+
const result = await sandbox.execute(code);
|
|
649
|
+
finalizeCodeActParentModelRun(getAdapter(), parentRun.modelRunId, result);
|
|
650
|
+
return {
|
|
651
|
+
success: result.success,
|
|
652
|
+
value: result.value,
|
|
653
|
+
logs: result.logs,
|
|
654
|
+
error: result.error?.message,
|
|
655
|
+
metrics: result.metrics,
|
|
656
|
+
toolCalls,
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
catch (error) {
|
|
660
|
+
failCodeActParentModelRun(getAdapter(), parentRun.modelRunId, error);
|
|
661
|
+
throw error;
|
|
662
|
+
}
|
|
663
|
+
finally {
|
|
664
|
+
toolExecutor.restoreCurrentAgentRoutingContext(previousRoutingContext);
|
|
665
|
+
}
|
|
666
|
+
};
|
|
667
|
+
// Pre-warm Code-Act WASM module for fast first execution
|
|
668
|
+
(async () => {
|
|
669
|
+
try {
|
|
670
|
+
const { CodeActSandbox } = await import('../../agent/code-act/index.js');
|
|
671
|
+
await CodeActSandbox.warmup();
|
|
672
|
+
}
|
|
673
|
+
catch (err) {
|
|
674
|
+
console.warn('[CodeAct] WASM warmup failed (non-fatal):', err);
|
|
675
|
+
}
|
|
676
|
+
})();
|
|
668
677
|
const graphHandler = (0, graph_api_js_1.createGraphHandler)(graphHandlerOptions);
|
|
669
678
|
// Seed initial agent versions from config (version 1 for new agents)
|
|
670
679
|
// initAgentTables is idempotent (CREATE IF NOT EXISTS) — safe to call before apiServer
|
|
@@ -675,134 +684,83 @@ async function runAgentLoop(config, options = {}) {
|
|
|
675
684
|
toolExecutor.setValidationService(validationService);
|
|
676
685
|
messageRouter.setValidationService(validationService);
|
|
677
686
|
agentLoop.setValidationService(validationService);
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
687
|
+
// Ensure current primary system agents exist in config. Legacy self-paced
|
|
688
|
+
// dashboard/wiki agents are opt-in and must not be backfilled here.
|
|
689
|
+
if (!config.multi_agent) {
|
|
690
|
+
config.multi_agent = (0, config_manager_js_1.getDefaultMultiAgentConfig)();
|
|
691
|
+
}
|
|
692
|
+
if (!config.multi_agent.agents) {
|
|
693
|
+
config.multi_agent.agents = {};
|
|
694
|
+
}
|
|
695
|
+
const osAgents = {
|
|
696
|
+
'os-agent': {
|
|
697
|
+
name: 'OS Agent',
|
|
698
|
+
display_name: '🖥️ OS Agent',
|
|
699
|
+
trigger_prefix: '!os',
|
|
700
|
+
persona_file: '~/.mama/personas/os-agent.md',
|
|
701
|
+
tier: 1,
|
|
702
|
+
backend: runtimeBackend,
|
|
703
|
+
model: config.agent.model,
|
|
704
|
+
can_delegate: true,
|
|
705
|
+
enabled: true,
|
|
706
|
+
},
|
|
707
|
+
memory: {
|
|
708
|
+
name: 'Memory Agent',
|
|
709
|
+
display_name: '🧠 Memory',
|
|
710
|
+
trigger_prefix: '!memory',
|
|
711
|
+
persona_file: '~/.mama/personas/memory.md',
|
|
712
|
+
tier: 3,
|
|
713
|
+
backend: runtimeBackend,
|
|
714
|
+
model: config.agent.model,
|
|
715
|
+
can_delegate: false,
|
|
716
|
+
enabled: true,
|
|
717
|
+
},
|
|
718
|
+
};
|
|
719
|
+
let osAgentsAdded = false;
|
|
720
|
+
for (const [id, cfg] of Object.entries(osAgents)) {
|
|
721
|
+
if (!config.multi_agent.agents[id]) {
|
|
722
|
+
config.multi_agent.agents[id] = cfg;
|
|
723
|
+
osAgentsAdded = true;
|
|
685
724
|
}
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
backend: runtimeBackend,
|
|
694
|
-
model: config.agent.model,
|
|
695
|
-
can_delegate: true,
|
|
696
|
-
enabled: true,
|
|
697
|
-
},
|
|
698
|
-
memory: {
|
|
699
|
-
name: 'Memory Agent',
|
|
700
|
-
display_name: '🧠 Memory',
|
|
701
|
-
trigger_prefix: '!memory',
|
|
702
|
-
persona_file: '~/.mama/personas/memory.md',
|
|
703
|
-
tier: 3,
|
|
704
|
-
backend: runtimeBackend,
|
|
705
|
-
model: config.agent.model,
|
|
706
|
-
can_delegate: false,
|
|
707
|
-
enabled: true,
|
|
708
|
-
},
|
|
709
|
-
'dashboard-agent': {
|
|
710
|
-
name: 'Dashboard Agent',
|
|
711
|
-
display_name: '📊 Dashboard',
|
|
712
|
-
trigger_prefix: '!dashboard',
|
|
713
|
-
persona_file: '~/.mama/personas/dashboard.md',
|
|
714
|
-
tier: 2,
|
|
715
|
-
backend: runtimeBackend,
|
|
716
|
-
model: config.agent.model,
|
|
717
|
-
can_delegate: false,
|
|
718
|
-
enabled: true,
|
|
719
|
-
useCodeAct: true,
|
|
720
|
-
tool_permissions: {
|
|
721
|
-
allowed: ['Read', 'Grep', 'Glob', 'code_act'],
|
|
722
|
-
blocked: ['Bash', 'Write', 'Edit', 'Agent', 'WebSearch', 'WebFetch'],
|
|
723
|
-
},
|
|
724
|
-
gateway_tool_permissions: {
|
|
725
|
-
allowed: ['mama_search', 'context_compile', 'agent_notices', 'report_publish'],
|
|
726
|
-
blocked: [],
|
|
727
|
-
},
|
|
728
|
-
},
|
|
729
|
-
};
|
|
730
|
-
const wikiConfig = config.wiki;
|
|
731
|
-
if (wikiConfig?.enabled) {
|
|
732
|
-
osAgents['wiki-agent'] = {
|
|
733
|
-
name: 'Wiki Agent',
|
|
734
|
-
display_name: '📚 Wiki',
|
|
735
|
-
trigger_prefix: '!wiki',
|
|
736
|
-
persona_file: '~/.mama/personas/wiki.md',
|
|
737
|
-
tier: 2,
|
|
738
|
-
backend: runtimeBackend,
|
|
739
|
-
model: config.agent.model,
|
|
740
|
-
can_delegate: false,
|
|
741
|
-
enabled: true,
|
|
742
|
-
useCodeAct: true,
|
|
743
|
-
tool_permissions: {
|
|
744
|
-
allowed: ['Read', 'Grep', 'Glob', 'code_act'],
|
|
745
|
-
blocked: ['Bash', 'Write', 'Edit', 'Agent', 'WebSearch', 'WebFetch'],
|
|
746
|
-
},
|
|
747
|
-
gateway_tool_permissions: {
|
|
748
|
-
allowed: [
|
|
749
|
-
'mama_search',
|
|
750
|
-
'context_compile',
|
|
751
|
-
'agent_notices',
|
|
752
|
-
'case_list',
|
|
753
|
-
'case_assemble',
|
|
754
|
-
'obsidian',
|
|
755
|
-
'wiki_publish',
|
|
756
|
-
],
|
|
757
|
-
blocked: [],
|
|
758
|
-
},
|
|
759
|
-
};
|
|
725
|
+
}
|
|
726
|
+
// Persist to config.yaml so /api/agents sees them too
|
|
727
|
+
if (osAgentsAdded) {
|
|
728
|
+
try {
|
|
729
|
+
const { saveConfig } = await import('../config/config-manager.js');
|
|
730
|
+
await saveConfig(config);
|
|
731
|
+
console.log('✓ OS agents added to config.yaml');
|
|
760
732
|
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
if (!config.multi_agent.agents[id]) {
|
|
764
|
-
config.multi_agent.agents[id] = cfg;
|
|
765
|
-
osAgentsAdded = true;
|
|
766
|
-
}
|
|
733
|
+
catch {
|
|
734
|
+
/* non-fatal — runtime config still has them */
|
|
767
735
|
}
|
|
768
|
-
|
|
769
|
-
|
|
736
|
+
}
|
|
737
|
+
const agents = config.multi_agent.agents;
|
|
738
|
+
for (const [id, cfg] of Object.entries(agents)) {
|
|
739
|
+
if (!(0, agent_store_js_1.getLatestVersion)(db, id)) {
|
|
740
|
+
let personaText = null;
|
|
770
741
|
try {
|
|
771
|
-
const
|
|
772
|
-
|
|
773
|
-
|
|
742
|
+
const pPath = (0, config_manager_js_1.expandPath)(cfg.persona_file);
|
|
743
|
+
if ((0, node_fs_1.existsSync)(pPath))
|
|
744
|
+
personaText = (0, node_fs_1.readFileSync)(pPath, 'utf-8');
|
|
774
745
|
}
|
|
775
746
|
catch {
|
|
776
|
-
/*
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
const agents = config.multi_agent.agents;
|
|
780
|
-
for (const [id, cfg] of Object.entries(agents)) {
|
|
781
|
-
if (!(0, agent_store_js_1.getLatestVersion)(db, id)) {
|
|
782
|
-
let personaText = null;
|
|
783
|
-
try {
|
|
784
|
-
const pPath = (0, config_manager_js_1.expandPath)(cfg.persona_file);
|
|
785
|
-
if ((0, node_fs_1.existsSync)(pPath))
|
|
786
|
-
personaText = (0, node_fs_1.readFileSync)(pPath, 'utf-8');
|
|
787
|
-
}
|
|
788
|
-
catch {
|
|
789
|
-
/* ignore */
|
|
790
|
-
}
|
|
791
|
-
(0, agent_store_js_1.createAgentVersion)(db, {
|
|
792
|
-
agent_id: id,
|
|
793
|
-
snapshot: { model: cfg.model, tier: cfg.tier, backend: cfg.backend },
|
|
794
|
-
persona_text: personaText,
|
|
795
|
-
change_note: 'Initial version (migrated from config.yaml)',
|
|
796
|
-
});
|
|
747
|
+
/* ignore */
|
|
797
748
|
}
|
|
749
|
+
(0, agent_store_js_1.createAgentVersion)(db, {
|
|
750
|
+
agent_id: id,
|
|
751
|
+
snapshot: { model: cfg.model, tier: cfg.tier, backend: cfg.backend },
|
|
752
|
+
persona_text: personaText,
|
|
753
|
+
change_note: 'Initial version (migrated from config.yaml)',
|
|
754
|
+
});
|
|
798
755
|
}
|
|
799
|
-
console.log(`✓ Agent versions seeded (${Object.keys(agents).length} agents)`);
|
|
800
756
|
}
|
|
757
|
+
console.log(`✓ Agent versions seeded (${Object.keys(agents).length} agents)`);
|
|
801
758
|
await (0, utilities_js_1.startEmbeddingServerIfAvailable)(messageRouter, sessionStore, graphHandler);
|
|
802
759
|
// ── Phase 6: Cron Scheduler ───────────────────────────────────────────────
|
|
803
760
|
const { scheduler, cronWorker, cronEmitter } = (0, scheduler_init_js_1.initCronScheduler)(config);
|
|
804
761
|
// ── Phase 7: Gateways ────────────────────────────────────────────────────
|
|
805
|
-
const
|
|
762
|
+
const gatewayInit = await (0, gateway_init_js_1.initGateways)(config, messageRouter, toolExecutor, agentLoop, runtimeBackend, db);
|
|
763
|
+
const { discordGateway, slackGateway, telegramGateway, gateways } = gatewayInit;
|
|
806
764
|
// ── Phase 8: Gateway Wiring ──────────────────────────────────────────────
|
|
807
765
|
const { pluginLoader } = await (0, gateway_wiring_js_1.wireGateways)({
|
|
808
766
|
config,
|
|
@@ -829,11 +787,14 @@ async function runAgentLoop(config, options = {}) {
|
|
|
829
787
|
// If no Discord/Slack handler wired the delegate tool, create standalone
|
|
830
788
|
// DelegationManager + AgentProcessManager so delegate() works from any path
|
|
831
789
|
// (Viewer, Telegram, iMessage, Terminal).
|
|
832
|
-
const
|
|
833
|
-
|
|
834
|
-
|
|
790
|
+
const fallbackMultiAgentConfig = config.multi_agent;
|
|
791
|
+
const hasSystemRunAgents = Boolean(fallbackMultiAgentConfig?.agents?.['dashboard-agent'] ||
|
|
792
|
+
fallbackMultiAgentConfig?.agents?.['wiki-agent']);
|
|
793
|
+
if (fallbackMultiAgentConfig &&
|
|
794
|
+
!toolExecutor.getAgentProcessManager() &&
|
|
795
|
+
(fallbackMultiAgentConfig.enabled || hasSystemRunAgents)) {
|
|
835
796
|
const { AgentProcessManager } = await import('../../multi-agent/agent-process-manager.js');
|
|
836
|
-
const pm = new AgentProcessManager(
|
|
797
|
+
const pm = new AgentProcessManager(fallbackMultiAgentConfig, buildSystemAgentProcessDefaults(config), {
|
|
837
798
|
backend: runtimeBackend,
|
|
838
799
|
model: config.agent.model,
|
|
839
800
|
});
|
|
@@ -850,9 +811,9 @@ async function runAgentLoop(config, options = {}) {
|
|
|
850
811
|
toolExecutor.setRestartMultiAgentAgent(graphHandlerOptions.restartMultiAgentAgent);
|
|
851
812
|
agentLoop.setApplyMultiAgentConfig(graphHandlerOptions.applyMultiAgentConfig);
|
|
852
813
|
agentLoop.setRestartMultiAgentAgent(graphHandlerOptions.restartMultiAgentAgent);
|
|
853
|
-
if (
|
|
814
|
+
if (fallbackMultiAgentConfig.enabled && !toolExecutor.hasDelegateSupport()) {
|
|
854
815
|
const { DelegationManager } = await import('../../multi-agent/delegation-manager.js');
|
|
855
|
-
const agentConfigs = Object.entries(
|
|
816
|
+
const agentConfigs = Object.entries(fallbackMultiAgentConfig.agents || {}).map(([id, cfg]) => ({
|
|
856
817
|
id,
|
|
857
818
|
...cfg,
|
|
858
819
|
}));
|
|
@@ -875,7 +836,43 @@ async function runAgentLoop(config, options = {}) {
|
|
|
875
836
|
}
|
|
876
837
|
// ── Phase 9: Heartbeat + Connectors ──────────────────────────────────────
|
|
877
838
|
const { heartbeatScheduler, tokenKeepAlive, healthWarningInterval } = (0, scheduler_init_js_1.initHeartbeat)(config, agentLoop, discordGateway, scheduler, healthCheckService);
|
|
878
|
-
|
|
839
|
+
// M2.4 freshness: the connector sink nudges the trigger loop when a poll indexes new rows. The
|
|
840
|
+
// loop is constructed AFTER initConnectors (below), so hand initConnectors a stable forwarder now
|
|
841
|
+
// and point it at the loop once it exists. Null until then -> nudge no-ops (no loop = nothing to
|
|
842
|
+
// wake), which preserves today's behavior when MAMA_TRIGGER_LOOP is unset.
|
|
843
|
+
const triggerLoopNudge = { current: null };
|
|
844
|
+
// M8: board-reconcile feed. The trigger loop is built BEFORE the event bus
|
|
845
|
+
// exists (initApiServer), so it emits through this mutable sink (same
|
|
846
|
+
// pattern as triggerLoopNudge above).
|
|
847
|
+
const channelDeltaSink = {
|
|
848
|
+
current: null,
|
|
849
|
+
};
|
|
850
|
+
// Operator DB + native task ledger (M8): wired UNCONDITIONALLY -- the task
|
|
851
|
+
// tools are standard gateway tools and must work even when the trigger loop
|
|
852
|
+
// is off (review finding on #142). Single handle, closed once at shutdown.
|
|
853
|
+
const operatorDbPath = (0, config_manager_js_1.expandPath)('~/.mama/operator/triggers.db');
|
|
854
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(operatorDbPath), { recursive: true });
|
|
855
|
+
const operatorDb = new sqlite_js_1.default(operatorDbPath);
|
|
856
|
+
try {
|
|
857
|
+
const { TaskLedger } = await import('../../operator/task-ledger.js');
|
|
858
|
+
toolExecutor.setTaskLedger(new TaskLedger(operatorDb));
|
|
859
|
+
}
|
|
860
|
+
catch (err) {
|
|
861
|
+
// Fail loud, but do not leak the handle on a failed boot.
|
|
862
|
+
operatorDb.close();
|
|
863
|
+
throw err;
|
|
864
|
+
}
|
|
865
|
+
gateways.push({
|
|
866
|
+
stop: async () => {
|
|
867
|
+
try {
|
|
868
|
+
operatorDb.close();
|
|
869
|
+
}
|
|
870
|
+
catch {
|
|
871
|
+
/* already closed */
|
|
872
|
+
}
|
|
873
|
+
},
|
|
874
|
+
});
|
|
875
|
+
const { rawStoreForApi, enabledConnectorNames, connectorSchedulerStop } = await (0, connector_init_js_1.initConnectors)(connectorExtractionFn, { nudge: () => triggerLoopNudge.current?.() });
|
|
879
876
|
codeActRawConnectors = resolveCodeActRawConnectors(enabledConnectorNames);
|
|
880
877
|
// Inject rawStore into tool executor for agent_test connector data access
|
|
881
878
|
if (rawStoreForApi) {
|
|
@@ -886,6 +883,160 @@ async function runAgentLoop(config, options = {}) {
|
|
|
886
883
|
if (connectorSchedulerStop) {
|
|
887
884
|
gateways.push({ stop: () => Promise.resolve(connectorSchedulerStop()) });
|
|
888
885
|
}
|
|
886
|
+
// ── Trigger loop (M1, flag-gated, additive): agent-evolved triggers on the live stream ──
|
|
887
|
+
// Runs ONLY with MAMA_TRIGGER_LOOP=1. Placed after initConnectors (which feeds
|
|
888
|
+
// connector_event_index) and after mama-core initDB. Read-only: recall/surface/log.
|
|
889
|
+
if (process.env.MAMA_TRIGGER_LOOP === '1') {
|
|
890
|
+
// Component isolation (PR #119 review): a trigger-loop bootstrap failure (bad import,
|
|
891
|
+
// DB permission, registry constructor) must not abort the whole daemon before Phase
|
|
892
|
+
// 10/11 - the gateways/viewer/agent serve independently of this optional leg. The
|
|
893
|
+
// failure is still surfaced LOUDLY below (console.error), never swallowed silently.
|
|
894
|
+
try {
|
|
895
|
+
const { OperatorTriggerLoop } = await import('../../operator/operator-trigger-loop.js');
|
|
896
|
+
const { ConnectorDeltaRepo } = await import('../../operator/connector-delta-repo.js');
|
|
897
|
+
const { TriggerRegistry } = await import('../../operator/trigger-registry.js');
|
|
898
|
+
const { createMamaMemoryPort } = await import('../../operator/mama-memory-port.js');
|
|
899
|
+
const { askAgentCLI } = await import('../../operator/trigger-author.js');
|
|
900
|
+
const { reviewTriggerCLI } = await import('../../operator/trigger-review.js');
|
|
901
|
+
const { ReportScheduler, FileReportScheduleStore, parseReportHours } = await import('../../operator/report-scheduler.js');
|
|
902
|
+
const { createPersonaReportAsk, OPERATOR_REPORT_SESSION_KEY } = await import('../../operator/report-run.js');
|
|
903
|
+
const { OPERATOR_FULL_REPORT_TAG } = await import('../../operator/situation-report.js');
|
|
904
|
+
const { buildBoardPublishLines } = await import('../../operator/board-slot-instructions.js');
|
|
905
|
+
const triggerRegistry = new TriggerRegistry(operatorDb);
|
|
906
|
+
// Owner-report leg (M1.5): destination chat comes from env (~/.mama/start.sh),
|
|
907
|
+
// never source. No chat configured or no telegram gateway -> loop stays read-only.
|
|
908
|
+
const reportChatId = process.env.MAMA_TRIGGER_LOOP_REPORT_CHAT || '';
|
|
909
|
+
const reportOutput = reportChatId && telegramGateway
|
|
910
|
+
? { send: (text) => telegramGateway.sendMessage(reportChatId, text) }
|
|
911
|
+
: undefined;
|
|
912
|
+
// Scheduled full-report leg (M2): local hours from env (~/.mama/start.sh), never source.
|
|
913
|
+
// Empty/absent -> [] -> leg off. Requires the same telegram sink as the digest leg.
|
|
914
|
+
const fullReportHours = parseReportHours(process.env.MAMA_TRIGGER_LOOP_FULL_REPORT_HOURS || '');
|
|
915
|
+
const reportScheduler = fullReportHours.length > 0 && reportOutput
|
|
916
|
+
? new ReportScheduler(fullReportHours, new FileReportScheduleStore((0, config_manager_js_1.expandPath)('~/.mama/operator/report-schedule-state.json')))
|
|
917
|
+
: undefined;
|
|
918
|
+
const triggerLoop = new OperatorTriggerLoop({
|
|
919
|
+
delta: new ConnectorDeltaRepo(getAdapter(), (0, config_manager_js_1.expandPath)('~/.mama/operator/trigger-loop-cursors.json')),
|
|
920
|
+
memory: createMamaMemoryPort(),
|
|
921
|
+
registry: triggerRegistry,
|
|
922
|
+
onChannelDelta: (channelKey, lines) => channelDeltaSink.current?.(channelKey, lines),
|
|
923
|
+
askAgent: askAgentCLI,
|
|
924
|
+
// M2.2: reports go through the daemon's persona agent (system prompt, pinned model,
|
|
925
|
+
// session lanes) instead of the bare CLI - report tone comes from generation inputs.
|
|
926
|
+
// JSON tasks (authoring/review) stay on the bare CLI for reliable parsing.
|
|
927
|
+
// M3 (GAP1+GAP2): run reports in a dedicated persona session lane so the multi-turn gather
|
|
928
|
+
// loop is isolated from chat and continuous across cadences (runWithContent honors
|
|
929
|
+
// options.sessionKey - agent-loop.ts:879, no agent-loop internal change). Gateway
|
|
930
|
+
// 'model_tool' executions are envelope-gated (gateway-tool-executor.ts:252-256) and
|
|
931
|
+
// issuance defaults to 'enabled' (envelope-bootstrap.ts:28-30), so each report carries a
|
|
932
|
+
// per-run scoped envelope (mirrors the code-act issuance at start.ts:1834-1865); without it
|
|
933
|
+
// every call is denied with code 'envelope_missing'. Then audit the gateway tools the agent
|
|
934
|
+
// actually EXECUTED: a full report that executed NO gateway gather tool is logged loudly
|
|
935
|
+
// (no-fallback), and every write (mama_save) is logged (observability).
|
|
936
|
+
reportAsk: createPersonaReportAsk({
|
|
937
|
+
issueEnvelope: envelopeBootstrap.envelopeAuthority && envelopeBootstrap.metadata.issuance !== 'off'
|
|
938
|
+
? async () => {
|
|
939
|
+
const projectId = (0, reactive_config_js_1.resolveReactiveProjectRoot)(config, process.env);
|
|
940
|
+
// A report run is multi-turn (each turn may take up to agent_ms).
|
|
941
|
+
// The TTL must cover the RUN, not one request - otherwise every
|
|
942
|
+
// long gather structurally outlives its envelope and all
|
|
943
|
+
// end-of-run writes die '[expired]' (9 observed pre-fix).
|
|
944
|
+
const wallSeconds = Math.min(Math.max(Number(process.env.MAMA_REPORT_WALL_SECONDS) || 900, 60), 1800);
|
|
945
|
+
return envelopeBootstrap.envelopeAuthority.buildAndPersist({
|
|
946
|
+
agent_id: 'operator-report',
|
|
947
|
+
instance_id: (0, node_crypto_1.randomUUID)(),
|
|
948
|
+
// 'operator' is not a member of EnvelopeSource (envelope/types.ts is a closed
|
|
949
|
+
// union); 'watch' is the daemon-internal source used by the mirrored code-act
|
|
950
|
+
// issuance (start.ts:1834-1865). This field is issuing-source metadata only -
|
|
951
|
+
// enforcement authorizes on scope.memory_scopes (which cover the operator:report
|
|
952
|
+
// run below), never on envelope.source (gateway-tool-executor.ts:1421,1511,1590).
|
|
953
|
+
source: 'watch',
|
|
954
|
+
channel_id: 'report',
|
|
955
|
+
trigger_context: { user_text: '<operator scheduled report>' },
|
|
956
|
+
scope: {
|
|
957
|
+
// Reads: the enabled raw connectors (kagemusha_* gathers) + memory scopes
|
|
958
|
+
// covering mama_recall/mama_save. allowed_destinations stays [] - NO new
|
|
959
|
+
// send surface (constraint 2).
|
|
960
|
+
project_refs: [{ kind: 'project', id: projectId }],
|
|
961
|
+
raw_connectors: codeActRawConnectors,
|
|
962
|
+
memory_scopes: resolveCodeActMemoryScopes((0, scope_context_js_1.deriveMemoryScopes)({ source: 'operator', channelId: 'report', projectId }), getAdapter()),
|
|
963
|
+
allowed_destinations: [],
|
|
964
|
+
},
|
|
965
|
+
tier: 2, // write tier: the report may mama_save (matches code-act write tier)
|
|
966
|
+
budget: { wall_seconds: wallSeconds },
|
|
967
|
+
expires_at: new Date(Date.now() + wallSeconds * 1000 + 30_000).toISOString(),
|
|
968
|
+
});
|
|
969
|
+
}
|
|
970
|
+
: undefined,
|
|
971
|
+
run: async (prompt, envelope) => {
|
|
972
|
+
const result = await agentLoop.runWithContent([{ type: 'text', text: prompt }], {
|
|
973
|
+
sessionKey: OPERATOR_REPORT_SESSION_KEY,
|
|
974
|
+
source: 'operator',
|
|
975
|
+
channelId: 'report',
|
|
976
|
+
// Stateless report lane: each run starts on a fresh session so the
|
|
977
|
+
// continuous session no longer accumulates every run's gather dumps
|
|
978
|
+
// (measured 146s -> 521s growth over 3 days). Continuity comes from
|
|
979
|
+
// the storage layer (self-gather + mama_recall + report store).
|
|
980
|
+
freshSession: true,
|
|
981
|
+
...(envelope ? { envelope } : {}),
|
|
982
|
+
});
|
|
983
|
+
return { response: result.response, history: result.history };
|
|
984
|
+
},
|
|
985
|
+
log: (line) => console.log(line),
|
|
986
|
+
fullReportTag: OPERATOR_FULL_REPORT_TAG,
|
|
987
|
+
}),
|
|
988
|
+
review: (trigger, context) => reviewTriggerCLI(trigger, context),
|
|
989
|
+
output: reportOutput,
|
|
990
|
+
reportScheduler,
|
|
991
|
+
// M2.3: the scheduled full report self-gathers via the persona agent's gateway tools
|
|
992
|
+
// (the Kagemusha lesson: a reporter with tools has substance; a window summary alone
|
|
993
|
+
// reports "quiet" whenever polling is between batches).
|
|
994
|
+
fullReportSelfGather: ({ lastSuccessIso }) => [
|
|
995
|
+
'kagemusha_overview() for room/task/message counts',
|
|
996
|
+
'kagemusha_tasks({}) for the open task board, plus kagemusha_tasks({ status: "review" }) for items awaiting review (status values must be real board statuses like pending/in_progress/review - invented labels match nothing)',
|
|
997
|
+
lastSuccessIso
|
|
998
|
+
? `kagemusha_entities({ activeOnly: true }) for active channels, then kagemusha_messages({ channelId, since: "${lastSuccessIso}" }) on the busiest 2-3 - since is the last successful report; do NOT widen it`
|
|
999
|
+
: 'kagemusha_entities({ activeOnly: true }) for active channels, then kagemusha_messages({ channelId }) on the busiest 2-3 (since defaults to the last 7 days; pass an ISO-8601 timestamp like since: "2026-07-09T00:00:00Z" to narrow it - never a phrase like "24h ago")',
|
|
1000
|
+
'mama_recall(query) for memory relevant to what you find',
|
|
1001
|
+
'schedule_upcoming({ days: 14 }) for upcoming calendar events -- cross-check task deadlines against them',
|
|
1002
|
+
],
|
|
1003
|
+
// Kagemusha dual output: the same scheduled run updates the /ui operator board
|
|
1004
|
+
// slots via report_publish, then writes the plain-text owner report.
|
|
1005
|
+
fullReportBoardLines: buildBoardPublishLines(),
|
|
1006
|
+
config: {
|
|
1007
|
+
tickMs: Number(process.env.MAMA_TRIGGER_LOOP_TICK_MS || 60_000),
|
|
1008
|
+
drainLimit: Number(process.env.MAMA_TRIGGER_LOOP_DRAIN_LIMIT || 200),
|
|
1009
|
+
authorEveryNTicks: Number(process.env.MAMA_TRIGGER_LOOP_AUTHOR_EVERY || 30),
|
|
1010
|
+
reviewEveryNTicks: Number(process.env.MAMA_TRIGGER_LOOP_REVIEW_EVERY || 240),
|
|
1011
|
+
authorWindowSize: 50,
|
|
1012
|
+
reportEveryNTicks: Number(process.env.MAMA_TRIGGER_LOOP_REPORT_EVERY || 15),
|
|
1013
|
+
nudgeDebounceMs: Number(process.env.MAMA_TRIGGER_LOOP_NUDGE_DEBOUNCE_MS || 15_000),
|
|
1014
|
+
},
|
|
1015
|
+
log: (line) => console.log(line),
|
|
1016
|
+
});
|
|
1017
|
+
if (reportOutput) {
|
|
1018
|
+
console.log('✓ Trigger loop owner-report leg enabled (telegram)');
|
|
1019
|
+
}
|
|
1020
|
+
if (reportScheduler) {
|
|
1021
|
+
console.log(`✓ Trigger loop scheduled full-report leg enabled (local hours: ${fullReportHours.join(', ')})`);
|
|
1022
|
+
}
|
|
1023
|
+
const stopTriggerLoop = triggerLoop.start();
|
|
1024
|
+
// M2.4: point the connector sink's forwarder at this loop now that it exists.
|
|
1025
|
+
triggerLoopNudge.current = () => triggerLoop.nudge();
|
|
1026
|
+
gateways.push({
|
|
1027
|
+
stop: async () => {
|
|
1028
|
+
triggerLoopNudge.current = null;
|
|
1029
|
+
stopTriggerLoop();
|
|
1030
|
+
// The shared operator DB handle is closed by the unconditional stop
|
|
1031
|
+
// hook above (single owner); nothing to close here.
|
|
1032
|
+
},
|
|
1033
|
+
});
|
|
1034
|
+
console.log('✓ Trigger loop enabled (MAMA_TRIGGER_LOOP=1, read-only surface mode)');
|
|
1035
|
+
}
|
|
1036
|
+
catch (error) {
|
|
1037
|
+
console.error('[trigger-loop] FAILED to start - daemon continues WITHOUT the trigger loop. Fix and restart:', error);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
889
1040
|
// ── Phase 10: API Server + Routes ────────────────────────────────────────
|
|
890
1041
|
const { apiServer, eventBus } = await (0, api_server_init_js_1.initApiServer)({
|
|
891
1042
|
config,
|
|
@@ -901,6 +1052,7 @@ async function runAgentLoop(config, options = {}) {
|
|
|
901
1052
|
envelopeAuthority: envelopeBootstrap.envelopeAuthority,
|
|
902
1053
|
contextCompileService,
|
|
903
1054
|
});
|
|
1055
|
+
channelDeltaSink.current = (channelKey, lines) => eventBus.emit({ type: 'operator:channel-delta', channelKey, lines });
|
|
904
1056
|
await (0, api_routes_init_js_1.registerApiRoutes)({
|
|
905
1057
|
config,
|
|
906
1058
|
apiServer,
|