@monoes/monomindcli 2.10.10 → 2.10.14
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/.claude/commands/mastermind/brain.md +14 -14
- package/.claude/commands/mastermind/help.md +2 -2
- package/.claude/commands/mastermind/master.md +24 -19
- package/.claude/commands/mastermind/memory.md +8 -8
- package/.claude/commands/mastermind/monoswarm.md +4 -4
- package/.claude/commands/mastermind.md +7 -7
- package/.claude/commands/truth/start.md +3 -3
- package/.claude/helpers/handlers/gates-handler.cjs +13 -1
- package/.claude/skills/mastermind/SKILL.md +7 -16
- package/.claude/skills/mastermind-debug/SKILL.md +3 -3
- package/.claude/skills/mastermind-design/SKILL.md +2 -0
- package/.claude/skills/mastermind-execute/SKILL.md +66 -11
- package/.claude/skills/mastermind-idea/SKILL.md +9 -2
- package/.claude/skills/mastermind-intake/SKILL.md +31 -7
- package/.claude/skills/mastermind-issue-detail/SKILL.md +70 -16
- package/.claude/skills/mastermind-issues/SKILL.md +111 -16
- package/.claude/skills/mastermind-liveness/SKILL.md +96 -26
- package/.claude/skills/mastermind-my-issues/SKILL.md +40 -8
- package/.claude/skills/mastermind-org/SKILL.md +2 -0
- package/.claude/skills/mastermind-plan/SKILL.md +7 -16
- package/.claude/skills/mastermind-plan-to-tasks/SKILL.md +132 -24
- package/.claude/skills/mastermind-protocol/SKILL.md +33 -22
- package/.claude/skills/mastermind-runorg/SKILL.md +22 -3
- package/.claude/skills/mastermind-skill-builder/SKILL.md +1 -1
- package/.claude/skills/mastermind-tasks/SKILL.md +5 -0
- package/.claude/skills/mastermind-techport/SKILL.md +1 -1
- package/.claude/skills/monodesign/scripts/detector/engines/browser/drivers.mjs +56 -15
- package/.claude/skills/performance-analysis/SKILL.md +1 -1
- package/.claude/skills/verification-quality/SKILL.md +2 -3
- package/README.md +2 -2
- package/dist/src/commands/doc.js +2 -2
- package/dist/src/commands/doc.js.map +1 -1
- package/dist/src/commands/doctor-project-checks.d.ts.map +1 -1
- package/dist/src/commands/doctor-project-checks.js +45 -2
- package/dist/src/commands/doctor-project-checks.js.map +1 -1
- package/dist/src/commands/memory-crud.d.ts.map +1 -1
- package/dist/src/commands/memory-crud.js +13 -2
- package/dist/src/commands/memory-crud.js.map +1 -1
- package/dist/src/commands/memory.js +1 -1
- package/dist/src/commands/memory.js.map +1 -1
- package/dist/src/commands/monograph.d.ts.map +1 -1
- package/dist/src/commands/monograph.js +11 -4
- package/dist/src/commands/monograph.js.map +1 -1
- package/dist/src/commands/org-observe.d.ts.map +1 -1
- package/dist/src/commands/org-observe.js +56 -6
- package/dist/src/commands/org-observe.js.map +1 -1
- package/dist/src/commands/org.d.ts +26 -0
- package/dist/src/commands/org.d.ts.map +1 -1
- package/dist/src/commands/org.js +144 -28
- package/dist/src/commands/org.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +10 -9
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/settings-generator.d.ts.map +1 -1
- package/dist/src/init/settings-generator.js.map +1 -1
- package/dist/src/init/upgrade.d.ts.map +1 -1
- package/dist/src/init/upgrade.js +29 -0
- package/dist/src/init/upgrade.js.map +1 -1
- package/dist/src/init/write-codex.d.ts.map +1 -1
- package/dist/src/init/write-codex.js.map +1 -1
- package/dist/src/knowledge/document-pipeline.d.ts +5 -0
- package/dist/src/knowledge/document-pipeline.d.ts.map +1 -1
- package/dist/src/knowledge/document-pipeline.js +32 -16
- package/dist/src/knowledge/document-pipeline.js.map +1 -1
- package/dist/src/mcp-tools/hooks-routing.d.ts +9 -0
- package/dist/src/mcp-tools/hooks-routing.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-routing.js +12 -1
- package/dist/src/mcp-tools/hooks-routing.js.map +1 -1
- package/dist/src/mcp-tools/knowledge-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/knowledge-tools.js +105 -13
- package/dist/src/mcp-tools/knowledge-tools.js.map +1 -1
- package/dist/src/mcp-tools/memory-tools.d.ts +13 -0
- package/dist/src/mcp-tools/memory-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/memory-tools.js +257 -31
- package/dist/src/mcp-tools/memory-tools.js.map +1 -1
- package/dist/src/mcp-tools/monograph/health-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph/health-tools.js +99 -42
- package/dist/src/mcp-tools/monograph/health-tools.js.map +1 -1
- package/dist/src/mcp-tools/monograph/impact-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph/impact-tools.js +123 -51
- package/dist/src/mcp-tools/monograph/impact-tools.js.map +1 -1
- package/dist/src/mcp-tools/monograph/query-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph/query-tools.js +113 -96
- package/dist/src/mcp-tools/monograph/query-tools.js.map +1 -1
- package/dist/src/mcp-tools/monograph/shared.d.ts +37 -4
- package/dist/src/mcp-tools/monograph/shared.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph/shared.js +75 -56
- package/dist/src/mcp-tools/monograph/shared.js.map +1 -1
- package/dist/src/memory/memory-bridge.d.ts +60 -1
- package/dist/src/memory/memory-bridge.d.ts.map +1 -1
- package/dist/src/memory/memory-bridge.js +172 -42
- package/dist/src/memory/memory-bridge.js.map +1 -1
- package/dist/src/memory/memory-kg.d.ts +495 -28
- package/dist/src/memory/memory-kg.d.ts.map +1 -1
- package/dist/src/memory/memory-kg.js +2186 -251
- package/dist/src/memory/memory-kg.js.map +1 -1
- package/dist/src/memory/query-router.d.ts +51 -0
- package/dist/src/memory/query-router.d.ts.map +1 -1
- package/dist/src/memory/query-router.js +38 -2
- package/dist/src/memory/query-router.js.map +1 -1
- package/dist/src/orgrt/agent-exec.d.ts.map +1 -1
- package/dist/src/orgrt/agent-exec.js +7 -0
- package/dist/src/orgrt/agent-exec.js.map +1 -1
- package/dist/src/orgrt/agent-runner.d.ts +26 -1
- package/dist/src/orgrt/agent-runner.d.ts.map +1 -1
- package/dist/src/orgrt/agent-runner.js +73 -22
- package/dist/src/orgrt/agent-runner.js.map +1 -1
- package/dist/src/orgrt/antigravity-runner.d.ts +1 -1
- package/dist/src/orgrt/antigravity-runner.d.ts.map +1 -1
- package/dist/src/orgrt/antigravity-runner.js +36 -19
- package/dist/src/orgrt/antigravity-runner.js.map +1 -1
- package/dist/src/orgrt/approvals.d.ts +26 -2
- package/dist/src/orgrt/approvals.d.ts.map +1 -1
- package/dist/src/orgrt/approvals.js +67 -7
- package/dist/src/orgrt/approvals.js.map +1 -1
- package/dist/src/orgrt/broker.d.ts +21 -2
- package/dist/src/orgrt/broker.d.ts.map +1 -1
- package/dist/src/orgrt/broker.js +56 -8
- package/dist/src/orgrt/broker.js.map +1 -1
- package/dist/src/orgrt/bus.d.ts +8 -0
- package/dist/src/orgrt/bus.d.ts.map +1 -1
- package/dist/src/orgrt/bus.js +27 -0
- package/dist/src/orgrt/bus.js.map +1 -1
- package/dist/src/orgrt/checkpoint-ops.d.ts.map +1 -1
- package/dist/src/orgrt/checkpoint-ops.js +15 -5
- package/dist/src/orgrt/checkpoint-ops.js.map +1 -1
- package/dist/src/orgrt/checkpoint.d.ts +42 -4
- package/dist/src/orgrt/checkpoint.d.ts.map +1 -1
- package/dist/src/orgrt/checkpoint.js +75 -4
- package/dist/src/orgrt/checkpoint.js.map +1 -1
- package/dist/src/orgrt/codex-runner.d.ts +1 -1
- package/dist/src/orgrt/codex-runner.d.ts.map +1 -1
- package/dist/src/orgrt/codex-runner.js +50 -23
- package/dist/src/orgrt/codex-runner.js.map +1 -1
- package/dist/src/orgrt/copilot-runner.d.ts +24 -2
- package/dist/src/orgrt/copilot-runner.d.ts.map +1 -1
- package/dist/src/orgrt/copilot-runner.js +257 -157
- package/dist/src/orgrt/copilot-runner.js.map +1 -1
- package/dist/src/orgrt/cross-org.d.ts +10 -3
- package/dist/src/orgrt/cross-org.d.ts.map +1 -1
- package/dist/src/orgrt/cross-org.js +225 -10
- package/dist/src/orgrt/cross-org.js.map +1 -1
- package/dist/src/orgrt/crush-runner.d.ts +22 -2
- package/dist/src/orgrt/crush-runner.d.ts.map +1 -1
- package/dist/src/orgrt/crush-runner.js +227 -120
- package/dist/src/orgrt/crush-runner.js.map +1 -1
- package/dist/src/orgrt/daemon.d.ts +77 -7
- package/dist/src/orgrt/daemon.d.ts.map +1 -1
- package/dist/src/orgrt/daemon.js +989 -385
- package/dist/src/orgrt/daemon.js.map +1 -1
- package/dist/src/orgrt/decisions.d.ts +2 -2
- package/dist/src/orgrt/decisions.d.ts.map +1 -1
- package/dist/src/orgrt/decisions.js +90 -18
- package/dist/src/orgrt/decisions.js.map +1 -1
- package/dist/src/orgrt/grok-runner.d.ts +29 -3
- package/dist/src/orgrt/grok-runner.d.ts.map +1 -1
- package/dist/src/orgrt/grok-runner.js +286 -150
- package/dist/src/orgrt/grok-runner.js.map +1 -1
- package/dist/src/orgrt/kimicode-runner.d.ts +5 -5
- package/dist/src/orgrt/kimicode-runner.d.ts.map +1 -1
- package/dist/src/orgrt/kimicode-runner.js +53 -32
- package/dist/src/orgrt/kimicode-runner.js.map +1 -1
- package/dist/src/orgrt/mailbox.d.ts +15 -0
- package/dist/src/orgrt/mailbox.d.ts.map +1 -1
- package/dist/src/orgrt/mailbox.js +29 -1
- package/dist/src/orgrt/mailbox.js.map +1 -1
- package/dist/src/orgrt/migrate.d.ts.map +1 -1
- package/dist/src/orgrt/migrate.js +8 -5
- package/dist/src/orgrt/migrate.js.map +1 -1
- package/dist/src/orgrt/opencode-runner.d.ts +1 -1
- package/dist/src/orgrt/opencode-runner.d.ts.map +1 -1
- package/dist/src/orgrt/opencode-runner.js +29 -3
- package/dist/src/orgrt/opencode-runner.js.map +1 -1
- package/dist/src/orgrt/org-memory.d.ts +19 -3
- package/dist/src/orgrt/org-memory.d.ts.map +1 -1
- package/dist/src/orgrt/org-memory.js +110 -38
- package/dist/src/orgrt/org-memory.js.map +1 -1
- package/dist/src/orgrt/pi-rpc-runner.d.ts +3 -1
- package/dist/src/orgrt/pi-rpc-runner.d.ts.map +1 -1
- package/dist/src/orgrt/pi-rpc-runner.js +35 -3
- package/dist/src/orgrt/pi-rpc-runner.js.map +1 -1
- package/dist/src/orgrt/pi-runner.d.ts +25 -2
- package/dist/src/orgrt/pi-runner.d.ts.map +1 -1
- package/dist/src/orgrt/pi-runner.js +271 -152
- package/dist/src/orgrt/pi-runner.js.map +1 -1
- package/dist/src/orgrt/policy.d.ts +1 -0
- package/dist/src/orgrt/policy.d.ts.map +1 -1
- package/dist/src/orgrt/policy.js +199 -39
- package/dist/src/orgrt/policy.js.map +1 -1
- package/dist/src/orgrt/provider.d.ts +4 -0
- package/dist/src/orgrt/provider.d.ts.map +1 -1
- package/dist/src/orgrt/provider.js +16 -0
- package/dist/src/orgrt/provider.js.map +1 -1
- package/dist/src/orgrt/qwen-rpc-runner.d.ts +3 -1
- package/dist/src/orgrt/qwen-rpc-runner.d.ts.map +1 -1
- package/dist/src/orgrt/qwen-rpc-runner.js +35 -3
- package/dist/src/orgrt/qwen-rpc-runner.js.map +1 -1
- package/dist/src/orgrt/qwen-runner.d.ts +30 -3
- package/dist/src/orgrt/qwen-runner.d.ts.map +1 -1
- package/dist/src/orgrt/qwen-runner.js +282 -142
- package/dist/src/orgrt/qwen-runner.js.map +1 -1
- package/dist/src/orgrt/role-slot.d.ts +88 -0
- package/dist/src/orgrt/role-slot.d.ts.map +1 -0
- package/dist/src/orgrt/role-slot.js +133 -0
- package/dist/src/orgrt/role-slot.js.map +1 -0
- package/dist/src/orgrt/runtime-options.d.ts +17 -0
- package/dist/src/orgrt/runtime-options.d.ts.map +1 -0
- package/dist/src/orgrt/runtime-options.js +32 -0
- package/dist/src/orgrt/runtime-options.js.map +1 -0
- package/dist/src/orgrt/scheduler-integration.d.ts +11 -0
- package/dist/src/orgrt/scheduler-integration.d.ts.map +1 -1
- package/dist/src/orgrt/scheduler-integration.js +75 -17
- package/dist/src/orgrt/scheduler-integration.js.map +1 -1
- package/dist/src/orgrt/scheduler.d.ts +4 -0
- package/dist/src/orgrt/scheduler.d.ts.map +1 -1
- package/dist/src/orgrt/scheduler.js +7 -1
- package/dist/src/orgrt/scheduler.js.map +1 -1
- package/dist/src/orgrt/server.d.ts +8 -3
- package/dist/src/orgrt/server.d.ts.map +1 -1
- package/dist/src/orgrt/server.js +48 -13
- package/dist/src/orgrt/server.js.map +1 -1
- package/dist/src/orgrt/session.d.ts +26 -2
- package/dist/src/orgrt/session.d.ts.map +1 -1
- package/dist/src/orgrt/session.js +98 -4
- package/dist/src/orgrt/session.js.map +1 -1
- package/dist/src/orgrt/task-dag.d.ts +5 -0
- package/dist/src/orgrt/task-dag.d.ts.map +1 -1
- package/dist/src/orgrt/task-dag.js +41 -0
- package/dist/src/orgrt/task-dag.js.map +1 -1
- package/dist/src/orgrt/test-loop.js +2 -2
- package/dist/src/orgrt/test-loop.js.map +1 -1
- package/dist/src/orgrt/types.d.ts +14 -2
- package/dist/src/orgrt/types.d.ts.map +1 -1
- package/dist/src/orgrt/types.js +15 -1
- package/dist/src/orgrt/types.js.map +1 -1
- package/dist/src/orgrt/vercel-runner.d.ts.map +1 -1
- package/dist/src/orgrt/vercel-runner.js +4 -0
- package/dist/src/orgrt/vercel-runner.js.map +1 -1
- package/dist/src/ui/routes-org.mjs +27 -7
- package/dist/src/ui/server.mjs +82 -48
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/dist/src/ui/data/mastermind-sessions.json +0 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/** Fold only the SUPPLIED override fields onto `current`; every omitted
|
|
2
|
+
* field keeps its current effective value (including across repeated
|
|
3
|
+
* replacements — `current` is always the slot's effectiveRole, never the
|
|
4
|
+
* original org-definition role, so this naturally persists overrides
|
|
5
|
+
* through however many replacements have already happened). */
|
|
6
|
+
export function mergeEffectiveRoleConfig(current, overrides) {
|
|
7
|
+
const merged = {
|
|
8
|
+
...current,
|
|
9
|
+
...(overrides.runtime !== undefined ? { runtime: overrides.runtime } : {}),
|
|
10
|
+
};
|
|
11
|
+
if (overrides.model !== undefined || overrides.providerName !== undefined) {
|
|
12
|
+
merged.adapter_config = {
|
|
13
|
+
...current.adapter_config,
|
|
14
|
+
...(overrides.model !== undefined ? { model: overrides.model } : {}),
|
|
15
|
+
...(overrides.providerName !== undefined ? { provider: overrides.providerName } : {}),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return merged;
|
|
19
|
+
}
|
|
20
|
+
/** The role's per-incarnation token ceiling when org_respawn_role omits
|
|
21
|
+
* `budgetTokens`: reuse the SAME allocator startup uses (daemon.ts's
|
|
22
|
+
* perRoleBudget computation), not the older even-split-only
|
|
23
|
+
* roleTokenBudget() helper. A role with its own budget_tokens override
|
|
24
|
+
* always gets that value; otherwise the remaining org budget (after
|
|
25
|
+
* subtracting every override) is split evenly across every role WITHOUT
|
|
26
|
+
* an override. */
|
|
27
|
+
export function computeReplacementBudget(def, roleId) {
|
|
28
|
+
const role = def.roles.find((r) => r.id === roleId);
|
|
29
|
+
if (!role)
|
|
30
|
+
throw new Error(`computeReplacementBudget: unknown role "${roleId}"`);
|
|
31
|
+
if (role.budget_tokens != null)
|
|
32
|
+
return role.budget_tokens;
|
|
33
|
+
const orgBudgetTokens = def.run_config.budget_tokens ?? 1_000_000;
|
|
34
|
+
const overriddenTokenSum = def.roles.reduce((sum, r) => sum + (r.budget_tokens ?? 0), 0);
|
|
35
|
+
const unoverriddenRoleCount = def.roles.filter((r) => r.budget_tokens == null).length;
|
|
36
|
+
return unoverriddenRoleCount > 0
|
|
37
|
+
? Math.max(0, Math.floor((orgBudgetTokens - overriddenTokenSum) / unoverriddenRoleCount))
|
|
38
|
+
: 0;
|
|
39
|
+
}
|
|
40
|
+
const RUNTIME_KINDS = new Set([
|
|
41
|
+
'claude',
|
|
42
|
+
'kimicode',
|
|
43
|
+
'opencode',
|
|
44
|
+
'vercel',
|
|
45
|
+
'codex',
|
|
46
|
+
'antigravity',
|
|
47
|
+
'grok',
|
|
48
|
+
'qwen',
|
|
49
|
+
'crush',
|
|
50
|
+
'copilot',
|
|
51
|
+
'pi',
|
|
52
|
+
'pi-rpc',
|
|
53
|
+
'qwen-rpc',
|
|
54
|
+
]);
|
|
55
|
+
function boundedString(value, max) {
|
|
56
|
+
if (typeof value !== 'string')
|
|
57
|
+
return null;
|
|
58
|
+
const trimmed = value.trim();
|
|
59
|
+
if (!trimmed || trimmed.length > max)
|
|
60
|
+
return null;
|
|
61
|
+
return trimmed;
|
|
62
|
+
}
|
|
63
|
+
/** Validate and bound every field of an org_respawn_role call before any
|
|
64
|
+
* state change or preflight is attempted. See the design doc's "Validation
|
|
65
|
+
* rules" — limits chosen there: roleId 128, reason 1000, briefing 20000. */
|
|
66
|
+
export function validateRespawnInput(input) {
|
|
67
|
+
const raw = (input ?? {});
|
|
68
|
+
const roleId = boundedString(raw.roleId, 128);
|
|
69
|
+
if (!roleId)
|
|
70
|
+
return { ok: false, error: 'roleId is required (1-128 characters)' };
|
|
71
|
+
const reason = boundedString(raw.reason, 1000);
|
|
72
|
+
if (!reason)
|
|
73
|
+
return { ok: false, error: 'reason is required (1-1000 characters)' };
|
|
74
|
+
const briefing = boundedString(raw.briefing, 20_000);
|
|
75
|
+
if (!briefing)
|
|
76
|
+
return { ok: false, error: 'briefing is required (1-20000 characters)' };
|
|
77
|
+
let runtime;
|
|
78
|
+
if (raw.runtime !== undefined) {
|
|
79
|
+
if (typeof raw.runtime !== 'string' || !RUNTIME_KINDS.has(raw.runtime)) {
|
|
80
|
+
return { ok: false, error: `runtime must be one of: ${[...RUNTIME_KINDS].join(', ')}` };
|
|
81
|
+
}
|
|
82
|
+
runtime = raw.runtime;
|
|
83
|
+
}
|
|
84
|
+
let model;
|
|
85
|
+
if (raw.model !== undefined) {
|
|
86
|
+
const m = boundedString(raw.model, 256);
|
|
87
|
+
if (!m)
|
|
88
|
+
return { ok: false, error: 'model must be a non-empty string (max 256 characters)' };
|
|
89
|
+
model = m;
|
|
90
|
+
}
|
|
91
|
+
let providerName;
|
|
92
|
+
if (raw.providerName !== undefined) {
|
|
93
|
+
const p = boundedString(raw.providerName, 128);
|
|
94
|
+
if (!p)
|
|
95
|
+
return { ok: false, error: 'providerName must be a non-empty string (max 128 characters)' };
|
|
96
|
+
providerName = p;
|
|
97
|
+
}
|
|
98
|
+
let budgetTokens;
|
|
99
|
+
if (raw.budgetTokens !== undefined) {
|
|
100
|
+
const b = raw.budgetTokens;
|
|
101
|
+
if (typeof b !== 'number' || !Number.isSafeInteger(b) || b <= 0) {
|
|
102
|
+
return { ok: false, error: 'budgetTokens must be a positive integer' };
|
|
103
|
+
}
|
|
104
|
+
budgetTokens = b;
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
ok: true,
|
|
108
|
+
value: { roleId, reason, briefing, runtime, model, providerName, budgetTokens },
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/** Audit/status-safe view of a role's runtime config — never includes
|
|
112
|
+
* role.provider (which may carry apiKey/authToken/baseUrl). */
|
|
113
|
+
export function redactRoleConfig(role) {
|
|
114
|
+
const out = {};
|
|
115
|
+
if (role.runtime)
|
|
116
|
+
out.runtime = role.runtime;
|
|
117
|
+
if (role.adapter_config?.model)
|
|
118
|
+
out.model = role.adapter_config.model;
|
|
119
|
+
if (role.adapter_config?.provider)
|
|
120
|
+
out.providerName = role.adapter_config.provider;
|
|
121
|
+
return out;
|
|
122
|
+
}
|
|
123
|
+
export function buildRespawnReceipt(slot, maxRespawns, success, extra = {}) {
|
|
124
|
+
return {
|
|
125
|
+
success,
|
|
126
|
+
roleId: '',
|
|
127
|
+
generation: slot.generation,
|
|
128
|
+
respawnCount: slot.respawnCount,
|
|
129
|
+
respawnsRemaining: Math.max(0, maxRespawns - slot.respawnCount),
|
|
130
|
+
...extra,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=role-slot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-slot.js","sourceRoot":"","sources":["../../../src/orgrt/role-slot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface RuntimeOption {
|
|
2
|
+
id: string;
|
|
3
|
+
available: boolean;
|
|
4
|
+
binary?: string;
|
|
5
|
+
version?: string;
|
|
6
|
+
installHint?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface NamedProviderOption {
|
|
9
|
+
name: string;
|
|
10
|
+
defaultModel?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface RuntimeOptionsReceipt {
|
|
13
|
+
runtimes: RuntimeOption[];
|
|
14
|
+
namedProviders: NamedProviderOption[];
|
|
15
|
+
}
|
|
16
|
+
export declare function buildRuntimeOptions(searchFrom?: string): Promise<RuntimeOptionsReceipt>;
|
|
17
|
+
//# sourceMappingURL=runtime-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-options.d.ts","sourceRoot":"","sources":["../../../src/orgrt/runtime-options.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,cAAc,EAAE,mBAAmB,EAAE,CAAC;CACvC;AAED,wBAAsB,mBAAmB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAsB7F"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// packages/@monomind/cli/src/orgrt/runtime-options.ts
|
|
2
|
+
/** Data source for the org_list_runtime_options tool. Read-only: wraps
|
|
3
|
+
* runner-registry.ts's install/version detection and provider.ts's named
|
|
4
|
+
* provider config, applying the in-process-runtime correction and
|
|
5
|
+
* credential redaction the design calls for. See
|
|
6
|
+
* docs/mastermind/specs/2026-09-07-org-runtime-role-respawn-design.md. */
|
|
7
|
+
import { listConfiguredProviders } from './provider.js';
|
|
8
|
+
import { RUNNER_SPECS, scanInstalled } from './runner-registry.js';
|
|
9
|
+
export async function buildRuntimeOptions(searchFrom) {
|
|
10
|
+
const scan = await scanInstalled();
|
|
11
|
+
const specById = new Map(RUNNER_SPECS.map((s) => [s.id, s]));
|
|
12
|
+
const runtimes = scan.agents.map((entry) => {
|
|
13
|
+
const spec = specById.get(entry.id);
|
|
14
|
+
// In-process runtimes (spec.binary === null, e.g. vercel) have nothing to
|
|
15
|
+
// find on PATH — scanInstalled's installed:false for them is a false
|
|
16
|
+
// negative ("not installed"), not a real unavailability signal.
|
|
17
|
+
const available = spec?.binary === null ? true : entry.installed;
|
|
18
|
+
return {
|
|
19
|
+
id: entry.id,
|
|
20
|
+
available,
|
|
21
|
+
...(entry.binary ? { binary: entry.binary } : {}),
|
|
22
|
+
...(entry.version ? { version: entry.version } : {}),
|
|
23
|
+
...(entry.install_hint ? { installHint: entry.install_hint } : {}),
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
const namedProviders = listConfiguredProviders(searchFrom).map((p) => ({
|
|
27
|
+
name: p.name,
|
|
28
|
+
...(p.model ? { defaultModel: p.model } : {}),
|
|
29
|
+
}));
|
|
30
|
+
return { runtimes, namedProviders };
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=runtime-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-options.js","sourceRoot":"","sources":["../../../src/orgrt/runtime-options.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD;;;;2EAI2E;AAC3E,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAoBnE,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,UAAmB;IAC3D,MAAM,IAAI,GAAG,MAAM,aAAa,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAoB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAC1D,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAyC,CAAC,CAAC;QAC3E,0EAA0E;QAC1E,qEAAqE;QACrE,gEAAgE;QAChE,MAAM,SAAS,GAAG,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;QACjE,OAAO;YACL,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,SAAS;YACT,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjD,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpD,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnE,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,MAAM,cAAc,GAA0B,uBAAuB,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5F,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9C,CAAC,CAAC,CAAC;IACJ,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;AACtC,CAAC"}
|
|
@@ -16,4 +16,15 @@ export declare function scheduleBossRestart(daemon: OrgDaemon, name: string): vo
|
|
|
16
16
|
* before capacity returns; `running` is compared by identity, not `name`,
|
|
17
17
|
* so a stale retry can never spawn into a different run. */
|
|
18
18
|
export declare function scheduleDeferredSpawn(daemon: OrgDaemon, name: string, running: RunningOrg, role: OrgRole, spawnRole: (role: OrgRole) => void): void;
|
|
19
|
+
/** Bug 4: a role deferred because the org is already at its
|
|
20
|
+
* run_config.max_concurrent_agents ceiling isn't abandoned either — poll
|
|
21
|
+
* until a slot frees up (another role in this org ends, crashes, or is
|
|
22
|
+
* stopped — activeRoleCount() recomputes live each check, so nothing here
|
|
23
|
+
* needs to explicitly track "a slot freed") and spawn it then. Same shape as
|
|
24
|
+
* scheduleDeferredSpawn's host-resource-pressure case, just gated on the
|
|
25
|
+
* org's own concurrency cap instead of waitForCapacity(). Bails quietly if
|
|
26
|
+
* the org is stopped (or restarted under the same name) before a slot
|
|
27
|
+
* frees; `running` is compared by identity, not `name`, so a stale retry can
|
|
28
|
+
* never spawn into a different run. */
|
|
29
|
+
export declare function scheduleConcurrencyDeferredSpawn(daemon: OrgDaemon, name: string, running: RunningOrg, role: OrgRole, spawnRole: (role: OrgRole) => void): void;
|
|
19
30
|
//# sourceMappingURL=scheduler-integration.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler-integration.d.ts","sourceRoot":"","sources":["../../../src/orgrt/scheduler-integration.ts"],"names":[],"mappings":"AAKA,OAAO,
|
|
1
|
+
{"version":3,"file":"scheduler-integration.d.ts","sourceRoot":"","sources":["../../../src/orgrt/scheduler-integration.ts"],"names":[],"mappings":"AAKA,OAAO,EAAmB,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAE1E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAuC1C;6EAC6E;AAC7E,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAW9D;AAED;;;;qCAIqC;AACrC,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAuDzE;AAED;;;;;6DAK6D;AAC7D,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,UAAU,EACnB,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GACjC,IAAI,CAyCN;AAED;;;;;;;;;wCASwC;AACxC,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,UAAU,EACnB,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GACjC,IAAI,CA4CN"}
|
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
// packages/@monomind/cli/src/orgrt/scheduler-integration.ts
|
|
2
2
|
// Extracted from daemon.ts — auto-wake, boss restart, deferred role spawns.
|
|
3
3
|
import { waitForCapacity } from '../utils/resource-governor.js';
|
|
4
|
-
import {
|
|
5
|
-
import { OrgDaemon } from './daemon.js';
|
|
4
|
+
import { pushMessage } from './cross-org.js';
|
|
5
|
+
import { activeRoleCount, OrgDaemon } from './daemon.js';
|
|
6
6
|
import { drainInbox } from './inbox.js';
|
|
7
|
+
/** Shared by scheduleDeferredSpawn and scheduleConcurrencyDeferredSpawn: spawn
|
|
8
|
+
* the role now that its gate has cleared, then deliver any messages queued
|
|
9
|
+
* for it while it was deferred (drained BEFORE spawning to avoid a race with
|
|
10
|
+
* messages arriving during the spawn window). */
|
|
11
|
+
async function spawnNowAndDrain(daemon, name, running, role, spawnRole) {
|
|
12
|
+
const queued = drainInbox(daemon.root, name);
|
|
13
|
+
spawnRole(role);
|
|
14
|
+
for (const msg of queued) {
|
|
15
|
+
const agent = running.agents.get(msg.toRole);
|
|
16
|
+
if (agent && !agent.mailbox.isClosed) {
|
|
17
|
+
running.bus.emit({
|
|
18
|
+
type: 'xorg',
|
|
19
|
+
from: msg.fromQualified,
|
|
20
|
+
to: `${name}:${msg.toRole}`,
|
|
21
|
+
subject: msg.subject,
|
|
22
|
+
msg: msg.body,
|
|
23
|
+
});
|
|
24
|
+
await pushMessage(daemon, name, running, msg.toRole, msg.fromQualified, msg.subject, msg.body, `inbox-${msg.ts}-${Math.random().toString(36).slice(2, 8)}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
7
28
|
/** Start an offline org in the background so queued messages get drained.
|
|
8
29
|
* Fire-and-forget — errors are logged but don't propagate to the sender. */
|
|
9
30
|
export function autoWake(daemon, name) {
|
|
@@ -95,21 +116,7 @@ export function scheduleDeferredSpawn(daemon, name, running, role, spawnRole) {
|
|
|
95
116
|
});
|
|
96
117
|
// Drain messages queued while the role was deferred BEFORE spawning
|
|
97
118
|
// to prevent race condition where messages arrive during spawn window
|
|
98
|
-
|
|
99
|
-
spawnRole(role);
|
|
100
|
-
for (const msg of queued) {
|
|
101
|
-
const agent = running.agents.get(msg.toRole);
|
|
102
|
-
if (agent && !agent.mailbox.isClosed) {
|
|
103
|
-
running.bus.emit({
|
|
104
|
-
type: 'xorg',
|
|
105
|
-
from: msg.fromQualified,
|
|
106
|
-
to: `${name}:${msg.toRole}`,
|
|
107
|
-
subject: msg.subject,
|
|
108
|
-
msg: msg.body,
|
|
109
|
-
});
|
|
110
|
-
agent.mailbox.push(mailBody(daemon.root, name, running, `[message from ${msg.fromQualified}] subject: ${msg.subject}`, msg.body, `inbox-${msg.ts}-${Math.random().toString(36).slice(2, 8)}`));
|
|
111
|
-
}
|
|
112
|
-
}
|
|
119
|
+
await spawnNowAndDrain(daemon, name, running, role, spawnRole);
|
|
113
120
|
return;
|
|
114
121
|
}
|
|
115
122
|
running.bus.emit({
|
|
@@ -131,4 +138,55 @@ export function scheduleDeferredSpawn(daemon, name, running, role, spawnRole) {
|
|
|
131
138
|
});
|
|
132
139
|
})().catch((err) => console.error(`org ${name}: deferred spawn of "${role.id}" failed:`, err instanceof Error ? err.message : err));
|
|
133
140
|
}
|
|
141
|
+
/** Bug 4: a role deferred because the org is already at its
|
|
142
|
+
* run_config.max_concurrent_agents ceiling isn't abandoned either — poll
|
|
143
|
+
* until a slot frees up (another role in this org ends, crashes, or is
|
|
144
|
+
* stopped — activeRoleCount() recomputes live each check, so nothing here
|
|
145
|
+
* needs to explicitly track "a slot freed") and spawn it then. Same shape as
|
|
146
|
+
* scheduleDeferredSpawn's host-resource-pressure case, just gated on the
|
|
147
|
+
* org's own concurrency cap instead of waitForCapacity(). Bails quietly if
|
|
148
|
+
* the org is stopped (or restarted under the same name) before a slot
|
|
149
|
+
* frees; `running` is compared by identity, not `name`, so a stale retry can
|
|
150
|
+
* never spawn into a different run. */
|
|
151
|
+
export function scheduleConcurrencyDeferredSpawn(daemon, name, running, role, spawnRole) {
|
|
152
|
+
const MAX_ATTEMPTS = 180; // ~15 min at 5s intervals before giving up loudly
|
|
153
|
+
const POLL_MS = 5_000;
|
|
154
|
+
(async () => {
|
|
155
|
+
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
156
|
+
await new Promise((resolve) => {
|
|
157
|
+
const t = setTimeout(resolve, POLL_MS);
|
|
158
|
+
t.unref?.();
|
|
159
|
+
});
|
|
160
|
+
if (daemon.orgs.get(name) !== running)
|
|
161
|
+
return; // org stopped/restarted — abandon quietly
|
|
162
|
+
const limit = running.def.run_config.max_concurrent_agents;
|
|
163
|
+
if (limit == null || activeRoleCount(running) < limit) {
|
|
164
|
+
running.bus.emit({
|
|
165
|
+
type: 'audit',
|
|
166
|
+
from: role.id,
|
|
167
|
+
reason: 'concurrency-recovered',
|
|
168
|
+
msg: `a concurrency slot freed up after ${attempt} retr${attempt === 1 ? 'y' : 'ies'} — spawning deferred role "${role.id}"`,
|
|
169
|
+
});
|
|
170
|
+
await spawnNowAndDrain(daemon, name, running, role, spawnRole);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
running.bus.emit({
|
|
174
|
+
type: 'audit',
|
|
175
|
+
from: role.id,
|
|
176
|
+
reason: 'concurrency-limit',
|
|
177
|
+
msg: `still at the max_concurrent_agents ceiling (attempt ${attempt}/${MAX_ATTEMPTS}) — retrying "${role.id}" spawn`,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
const missing = daemon.abandoned.get(name) ?? new Set();
|
|
181
|
+
missing.add(role.id);
|
|
182
|
+
daemon.abandoned.set(name, missing);
|
|
183
|
+
daemon.persistState(name, 'running', running.run);
|
|
184
|
+
running.bus.emit({
|
|
185
|
+
type: 'audit',
|
|
186
|
+
from: role.id,
|
|
187
|
+
reason: 'concurrency-abandoned',
|
|
188
|
+
msg: `giving up spawning "${role.id}" after ${MAX_ATTEMPTS} retries at the max_concurrent_agents ceiling — org will run without this role until manually restarted`,
|
|
189
|
+
});
|
|
190
|
+
})().catch((err) => console.error(`org ${name}: concurrency-deferred spawn of "${role.id}" failed:`, err instanceof Error ? err.message : err));
|
|
191
|
+
}
|
|
134
192
|
//# sourceMappingURL=scheduler-integration.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler-integration.js","sourceRoot":"","sources":["../../../src/orgrt/scheduler-integration.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,4EAA4E;AAE5E,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"scheduler-integration.js","sourceRoot":"","sources":["../../../src/orgrt/scheduler-integration.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,4EAA4E;AAE5E,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,SAAS,EAAmB,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGxC;;;kDAGkD;AAClD,KAAK,UAAU,gBAAgB,CAC7B,MAAiB,EACjB,IAAY,EACZ,OAAmB,EACnB,IAAa,EACb,SAAkC;IAElC,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7C,SAAS,CAAC,IAAI,CAAC,CAAC;IAChB,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,GAAG,CAAC,aAAa;gBACvB,EAAE,EAAE,GAAG,IAAI,IAAI,GAAG,CAAC,MAAM,EAAE;gBAC3B,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,GAAG,EAAE,GAAG,CAAC,IAAI;aACd,CAAC,CAAC;YACH,MAAM,WAAW,CACf,MAAM,EACN,IAAI,EACJ,OAAO,EACP,GAAG,CAAC,MAAM,EACV,GAAG,CAAC,aAAa,EACjB,GAAG,CAAC,OAAO,EACX,GAAG,CAAC,IAAI,EACR,SAAS,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAC5D,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED;6EAC6E;AAC7E,MAAM,UAAU,QAAQ,CAAC,MAAiB,EAAE,IAAY;IACtD,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IAC7D,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACxB,MAAM;SACH,QAAQ,CAAC,IAAI,CAAC;SACd,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACb,OAAO,CAAC,KAAK,CAAC,kBAAkB,IAAI,WAAW,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7F,CAAC,CAAC;SACD,OAAO,CAAC,GAAG,EAAE;QACZ,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;qCAIqC;AACrC,MAAM,UAAU,mBAAmB,CAAC,MAAiB,EAAE,IAAY;IACjE,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IACrE,MAAM,KAAK,GAAG,MAAM,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC;IACvC,IAAI,KAAK,IAAI,SAAS,CAAC,iBAAiB,EAAE,CAAC;QACzC,GAAG,EAAE,IAAI,CAAC;YACR,IAAI,EAAE,OAAO;YACb,MAAM,EAAE,wBAAwB;YAChC,GAAG,EAAE,4BAA4B,KAAK,uDAAuD;SAC9F,CAAC,CAAC;QACH,wEAAwE;QACxE,uEAAuE;QACvE,4DAA4D;QAC5D,sEAAsE;QACtE,oEAAoE;QACpE,4CAA4C;QAC5C,MAAM;aACH,OAAO,CAAC,IAAI,CAAC;aACb,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CACb,OAAO,CAAC,KAAK,CACX,OAAO,IAAI,8CAA8C,EACzD,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACzC,CACF,CAAC;QACJ,OAAO;IACT,CAAC;IACD,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,oBAAoB,IAAI,SAAS,CAAC,uBAAuB,CAAC;IAC9F,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7E,MAAM,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IAC9C,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,GAAG,EAAE,IAAI,CAAC;QACR,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,cAAc;QACtB,GAAG,EAAE,6DAA6D,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,cAAc,KAAK,GAAG,CAAC,IAAI,SAAS,CAAC,iBAAiB,GAAG;KACtJ,CAAC,CAAC;IACH,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE;QACxB,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC,CAAC,oBAAoB;QACtB,MAAM;aACH,OAAO,CAAC,IAAI,CAAC;aACb,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;aACtE,IAAI,CAAC,GAAG,EAAE;YACT,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC/B,OAAO,CAAC,KAAK,CACX,OAAO,IAAI,6BAA6B,EACxC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACzC,CAAC;QACJ,CAAC,CAAC,CAAC;IACP,CAAC,EAAE,OAAO,CAAC,CAAC;IACX,CAA4B,CAAC,KAAK,EAAE,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;6DAK6D;AAC7D,MAAM,UAAU,qBAAqB,CACnC,MAAiB,EACjB,IAAY,EACZ,OAAmB,EACnB,IAAa,EACb,SAAkC;IAElC,MAAM,YAAY,GAAG,CAAC,CAAC,CAAC,8CAA8C;IACtE,CAAC,KAAK,IAAI,EAAE;QACV,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,YAAY,EAAE,OAAO,EAAE,EAAE,CAAC;YACzD,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;YACjD,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,OAAO;gBAAE,OAAO,CAAC,0CAA0C;YACzF,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;oBACf,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,IAAI,CAAC,EAAE;oBACb,MAAM,EAAE,oBAAoB;oBAC5B,GAAG,EAAE,6BAA6B,OAAO,QAAQ,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,8BAA8B,IAAI,CAAC,EAAE,GAAG;iBACrH,CAAC,CAAC;gBACH,oEAAoE;gBACpE,sEAAsE;gBACtE,MAAM,gBAAgB,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;gBAC/D,OAAO;YACT,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,IAAI,CAAC,EAAE;gBACb,MAAM,EAAE,mBAAmB;gBAC3B,GAAG,EAAE,iCAAiC,OAAO,IAAI,YAAY,iBAAiB,IAAI,CAAC,EAAE,YAAY,MAAM,CAAC,MAAM,EAAE;aACjH,CAAC,CAAC;QACL,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,EAAU,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrB,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACpC,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,IAAI,CAAC,EAAE;YACb,MAAM,EAAE,oBAAoB;YAC5B,GAAG,EAAE,uBAAuB,IAAI,CAAC,EAAE,WAAW,YAAY,oEAAoE;SAC/H,CAAC,CAAC;IACL,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CACjB,OAAO,CAAC,KAAK,CACX,OAAO,IAAI,wBAAwB,IAAI,CAAC,EAAE,WAAW,EACrD,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACzC,CACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;wCASwC;AACxC,MAAM,UAAU,gCAAgC,CAC9C,MAAiB,EACjB,IAAY,EACZ,OAAmB,EACnB,IAAa,EACb,SAAkC;IAElC,MAAM,YAAY,GAAG,GAAG,CAAC,CAAC,kDAAkD;IAC5E,MAAM,OAAO,GAAG,KAAK,CAAC;IACtB,CAAC,KAAK,IAAI,EAAE;QACV,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,YAAY,EAAE,OAAO,EAAE,EAAE,CAAC;YACzD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBAClC,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACtC,CAA4B,CAAC,KAAK,EAAE,EAAE,CAAC;YAC1C,CAAC,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,OAAO;gBAAE,OAAO,CAAC,0CAA0C;YACzF,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,qBAAqB,CAAC;YAC3D,IAAI,KAAK,IAAI,IAAI,IAAI,eAAe,CAAC,OAAO,CAAC,GAAG,KAAK,EAAE,CAAC;gBACtD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;oBACf,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,IAAI,CAAC,EAAE;oBACb,MAAM,EAAE,uBAAuB;oBAC/B,GAAG,EAAE,qCAAqC,OAAO,QAAQ,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,8BAA8B,IAAI,CAAC,EAAE,GAAG;iBAC7H,CAAC,CAAC;gBACH,MAAM,gBAAgB,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;gBAC/D,OAAO;YACT,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,IAAI,CAAC,EAAE;gBACb,MAAM,EAAE,mBAAmB;gBAC3B,GAAG,EAAE,uDAAuD,OAAO,IAAI,YAAY,iBAAiB,IAAI,CAAC,EAAE,SAAS;aACrH,CAAC,CAAC;QACL,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,EAAU,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrB,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACpC,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,IAAI,CAAC,EAAE;YACb,MAAM,EAAE,uBAAuB;YAC/B,GAAG,EAAE,uBAAuB,IAAI,CAAC,EAAE,WAAW,YAAY,yGAAyG;SACpK,CAAC,CAAC;IACL,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CACjB,OAAO,CAAC,KAAK,CACX,OAAO,IAAI,oCAAoC,IAAI,CAAC,EAAE,WAAW,EACjE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CACzC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -4,6 +4,10 @@ export declare function parseSchedule(s: string | number | null | undefined): nu
|
|
|
4
4
|
export declare class OrgScheduler {
|
|
5
5
|
private runFn;
|
|
6
6
|
private timers;
|
|
7
|
+
/** Current interval per org. A catch-up fired from an old run's `finally`
|
|
8
|
+
* reads this rather than the intervalMs its closure captured, so an org
|
|
9
|
+
* rescheduled mid-run gets its new interval, not the replaced one. */
|
|
10
|
+
private intervals;
|
|
7
11
|
private running;
|
|
8
12
|
/** Orgs whose tick arrived mid-run. A dropped tick meant an org that overruns
|
|
9
13
|
* its interval — a 200m cycle on a 2h schedule — idled until the *next*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../../src/orgrt/scheduler.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAOlF;AAED,+GAA+G;AAC/G,qBAAa,YAAY;
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../../src/orgrt/scheduler.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAOlF;AAED,+GAA+G;AAC/G,qBAAa,YAAY;IAcX,OAAO,CAAC,KAAK;IAbzB,OAAO,CAAC,MAAM,CAAqD;IACnE;;2EAEuE;IACvE,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,OAAO,CAAqB;IACpC;;;;oFAIgF;IAChF,OAAO,CAAC,OAAO,CAAqB;IAEpC,YAAoB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,EAAI;IAElF;;;;;;8BAM0B;IAC1B,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,UAAQ,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAiDnF;IAED,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMzB;IAED,IAAI,IAAI,IAAI,CAEX;CACF"}
|
|
@@ -15,6 +15,10 @@ export function parseSchedule(s) {
|
|
|
15
15
|
export class OrgScheduler {
|
|
16
16
|
runFn;
|
|
17
17
|
timers = new Map();
|
|
18
|
+
/** Current interval per org. A catch-up fired from an old run's `finally`
|
|
19
|
+
* reads this rather than the intervalMs its closure captured, so an org
|
|
20
|
+
* rescheduled mid-run gets its new interval, not the replaced one. */
|
|
21
|
+
intervals = new Map();
|
|
18
22
|
running = new Set();
|
|
19
23
|
/** Orgs whose tick arrived mid-run. A dropped tick meant an org that overruns
|
|
20
24
|
* its interval — a 200m cycle on a 2h schedule — idled until the *next*
|
|
@@ -34,6 +38,7 @@ export class OrgScheduler {
|
|
|
34
38
|
* everything at once. */
|
|
35
39
|
add(name, intervalMs, runNow = false, sinceLastRunMs) {
|
|
36
40
|
this.remove(name);
|
|
41
|
+
this.intervals.set(name, intervalMs);
|
|
37
42
|
const fire = async () => {
|
|
38
43
|
if (this.running.has(name)) {
|
|
39
44
|
this.pending.add(name);
|
|
@@ -41,7 +46,7 @@ export class OrgScheduler {
|
|
|
41
46
|
} // catch up when it ends
|
|
42
47
|
this.running.add(name);
|
|
43
48
|
try {
|
|
44
|
-
await this.runFn(name, intervalMs);
|
|
49
|
+
await this.runFn(name, this.intervals.get(name) ?? intervalMs);
|
|
45
50
|
}
|
|
46
51
|
catch (err) {
|
|
47
52
|
console.error(`[org-scheduler] ${name}: scheduled run failed:`, err);
|
|
@@ -88,6 +93,7 @@ export class OrgScheduler {
|
|
|
88
93
|
if (t)
|
|
89
94
|
clearInterval(t);
|
|
90
95
|
this.timers.delete(name);
|
|
96
|
+
this.intervals.delete(name);
|
|
91
97
|
this.pending.delete(name); // an unscheduled org has no tick to catch up on
|
|
92
98
|
}
|
|
93
99
|
stop() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../../src/orgrt/scheduler.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAEhD,4EAA4E;AAC5E,MAAM,UAAU,aAAa,CAAC,CAAqC;IACjE,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,CAAC,GAAG,MAAM,CAAC;IAC7C,MAAM,CAAC,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7C,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;AAC7E,CAAC;AAED,+GAA+G;AAC/G,MAAM,OAAO,YAAY;
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../../src/orgrt/scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,10 @@ import type { OrgDaemon } from './daemon.js';
|
|
|
2
2
|
export interface OrgServer {
|
|
3
3
|
port: number;
|
|
4
4
|
close: () => void;
|
|
5
|
-
|
|
5
|
+
/** Authorizes the human-decision routes (approvals, gates, answers, human
|
|
6
|
+
* messages) and, as a superset, everything else. Never published to the
|
|
7
|
+
* broker registry — see broker.ts's defaultOperatorDir(). */
|
|
8
|
+
operatorCredential: string;
|
|
6
9
|
}
|
|
7
10
|
export interface ServerOpts {
|
|
8
11
|
/** Filter tool audit events by tool name or decision (allow|deny) */
|
|
@@ -13,6 +16,8 @@ export interface ServerOpts {
|
|
|
13
16
|
}
|
|
14
17
|
/** Minimal HTTP listener for cross-process org message delivery.
|
|
15
18
|
* Binds an ephemeral port (pass 0) so the daemon can register it with the broker.
|
|
16
|
-
*
|
|
17
|
-
|
|
19
|
+
* Two credentials gate requests: each hosted org's agent credential (published
|
|
20
|
+
* via the broker; unlocks delivery/status routes) and the operator credential
|
|
21
|
+
* (generated here unless supplied; unlocks OPERATOR_ROUTES as well). */
|
|
22
|
+
export declare function startOrgServer(daemon: OrgDaemon, port?: number, operatorCredential?: string): Promise<OrgServer>;
|
|
18
23
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/orgrt/server.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/orgrt/server.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB;;kEAE8D;IAC9D,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAcD,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,WAAW,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;KAAE,CAAC;CAC9D;AAwCD;;;;yEAIyE;AACzE,wBAAsB,cAAc,CAClC,MAAM,EAAE,SAAS,EACjB,IAAI,SAAI,EACR,kBAAkB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,SAAS,CAAC,CAmOpB"}
|
package/dist/src/orgrt/server.js
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
// monolean: stripped to xdeliver-only — live UI, WS fanout, and redundant REST
|
|
3
3
|
// endpoints deleted; the control server at :4242 handles all of those.
|
|
4
4
|
import http from 'node:http';
|
|
5
|
+
/** Routes that act with HUMAN authority. Only the operator credential unlocks
|
|
6
|
+
* them; a per-org agent credential (the one in the broker registry, readable
|
|
7
|
+
* by every org process and agent subprocess on the machine) gets 403 so a role
|
|
8
|
+
* can never approve its own gates. */
|
|
9
|
+
const OPERATOR_ROUTES = new Set([
|
|
10
|
+
'/api/set-approval',
|
|
11
|
+
'/api/resolve-gate',
|
|
12
|
+
'/api/answer-question',
|
|
13
|
+
'/api/human-message',
|
|
14
|
+
]);
|
|
5
15
|
const MAX_BODY = 1_000_000; // 1MB — prevents OOM from oversized POSTs
|
|
6
16
|
/** Parse a JSON POST body with a size guard. Rejects oversized or malformed bodies. */
|
|
7
17
|
function parseBody(req) {
|
|
@@ -40,22 +50,34 @@ function json(res, status, data) {
|
|
|
40
50
|
}
|
|
41
51
|
/** Minimal HTTP listener for cross-process org message delivery.
|
|
42
52
|
* Binds an ephemeral port (pass 0) so the daemon can register it with the broker.
|
|
43
|
-
*
|
|
44
|
-
|
|
53
|
+
* Two credentials gate requests: each hosted org's agent credential (published
|
|
54
|
+
* via the broker; unlocks delivery/status routes) and the operator credential
|
|
55
|
+
* (generated here unless supplied; unlocks OPERATOR_ROUTES as well). */
|
|
56
|
+
export async function startOrgServer(daemon, port = 0, operatorCredential) {
|
|
45
57
|
const { randomUUID, timingSafeEqual } = await import('node:crypto');
|
|
46
|
-
const
|
|
58
|
+
const operatorCred = operatorCredential ?? randomUUID();
|
|
47
59
|
// SEC-2: timing-safe credential comparison. The previous `!==` compared
|
|
48
60
|
// header-supplied bytes against the secret byte-for-byte and short-circuited
|
|
49
61
|
// on the first mismatched character — a remote attacker could time the
|
|
50
62
|
// response to recover the secret one byte at a time. Buffer.from + length
|
|
51
63
|
// gate + timingSafeEqual runs in constant time.
|
|
52
|
-
const
|
|
64
|
+
const safeEq = (supplied, expected) => {
|
|
53
65
|
const a = Buffer.from(String(supplied ?? ''));
|
|
54
|
-
const b = Buffer.from(
|
|
66
|
+
const b = Buffer.from(expected);
|
|
55
67
|
if (a.length !== b.length)
|
|
56
68
|
return false;
|
|
57
69
|
return timingSafeEqual(a, b);
|
|
58
70
|
};
|
|
71
|
+
const isOperator = (supplied) => safeEq(supplied, operatorCred);
|
|
72
|
+
/** Operator, or any org currently hosted by this daemon. */
|
|
73
|
+
const isAgentOrOperator = (supplied) => {
|
|
74
|
+
if (isOperator(supplied))
|
|
75
|
+
return true;
|
|
76
|
+
for (const org of daemon.orgs.values())
|
|
77
|
+
if (org.credential && safeEq(supplied, org.credential))
|
|
78
|
+
return true;
|
|
79
|
+
return false;
|
|
80
|
+
};
|
|
59
81
|
// SEC-3: DNS-rebinding / cross-origin defence. Mirrors ui/server.mjs's
|
|
60
82
|
// _allowedHosts + Origin allow-list. Default to loopback; override via env
|
|
61
83
|
// for users running the daemon behind a port-forwarder or in a container.
|
|
@@ -89,7 +111,7 @@ export async function startOrgServer(daemon, port = 0, credential) {
|
|
|
89
111
|
const corsOrigin = allowedOrigin(req.headers.origin);
|
|
90
112
|
// SSE endpoint for live bus event streaming (dashboard integration)
|
|
91
113
|
if (req.method === 'GET' && req.url === '/api/events') {
|
|
92
|
-
if (!
|
|
114
|
+
if (!isAgentOrOperator(req.headers['x-monomind-cred'])) {
|
|
93
115
|
json(res, 401, { ok: false, error: 'unauthorized' });
|
|
94
116
|
return;
|
|
95
117
|
}
|
|
@@ -110,7 +132,7 @@ export async function startOrgServer(daemon, port = 0, credential) {
|
|
|
110
132
|
}
|
|
111
133
|
// GET endpoint for org status snapshot (dashboard initial load)
|
|
112
134
|
if (req.method === 'GET' && req.url?.startsWith('/api/status')) {
|
|
113
|
-
if (!
|
|
135
|
+
if (!isAgentOrOperator(req.headers['x-monomind-cred'])) {
|
|
114
136
|
json(res, 401, { ok: false, error: 'unauthorized' });
|
|
115
137
|
return;
|
|
116
138
|
}
|
|
@@ -123,20 +145,26 @@ export async function startOrgServer(daemon, port = 0, credential) {
|
|
|
123
145
|
res.end('not found');
|
|
124
146
|
return;
|
|
125
147
|
}
|
|
126
|
-
// Auth gate —
|
|
127
|
-
|
|
148
|
+
// Auth gate — every POST needs a credential this daemon recognizes, and
|
|
149
|
+
// the human-decision routes need the operator credential specifically.
|
|
150
|
+
const supplied = req.headers['x-monomind-cred'];
|
|
151
|
+
if (!isAgentOrOperator(supplied)) {
|
|
128
152
|
json(res, 401, { ok: false, error: 'unauthorized' });
|
|
129
153
|
return;
|
|
130
154
|
}
|
|
155
|
+
if (OPERATOR_ROUTES.has(req.url ?? '') && !isOperator(supplied)) {
|
|
156
|
+
json(res, 403, { ok: false, error: 'forbidden: operator credential required' });
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
131
159
|
(async () => {
|
|
132
160
|
const payload = await parseBody(req);
|
|
133
161
|
if (req.url === '/api/xdeliver') {
|
|
134
|
-
const { toOrg, toRole, fromOrg, fromRole, subject, body: b, } = payload;
|
|
162
|
+
const { toOrg, toRole, fromOrg, fromRole, fromCredential, subject, body: b, } = payload;
|
|
135
163
|
if (!toOrg || !toRole || !fromOrg || !fromRole) {
|
|
136
164
|
json(res, 400, { ok: false, error: 'toOrg, toRole, fromOrg, fromRole are required' });
|
|
137
165
|
return;
|
|
138
166
|
}
|
|
139
|
-
const result = daemon.receiveRemote(toOrg, toRole, `${fromOrg}:${fromRole}`, subject ?? '', b ?? '');
|
|
167
|
+
const result = await daemon.receiveRemote(toOrg, toRole, `${fromOrg}:${fromRole}`, subject ?? '', b ?? '', fromCredential);
|
|
140
168
|
json(res, result.ok ? 200 : 404, result);
|
|
141
169
|
}
|
|
142
170
|
else if (req.url === '/api/human-message') {
|
|
@@ -190,7 +218,14 @@ export async function startOrgServer(daemon, port = 0, credential) {
|
|
|
190
218
|
// users running inside containers / port-forwarders that genuinely need
|
|
191
219
|
// remote connections.
|
|
192
220
|
const bindHost = process.env.MONOMIND_ORG_SERVER_HOST ?? '127.0.0.1';
|
|
193
|
-
await new Promise((
|
|
221
|
+
await new Promise((resolve, reject) => {
|
|
222
|
+
const onError = (err) => reject(err);
|
|
223
|
+
server.once('error', onError);
|
|
224
|
+
server.listen(port, bindHost, () => {
|
|
225
|
+
server.removeListener('error', onError);
|
|
226
|
+
resolve();
|
|
227
|
+
});
|
|
228
|
+
});
|
|
194
229
|
const actual = server.address().port;
|
|
195
230
|
actualPort = actual;
|
|
196
231
|
// Wire bus events from all running orgs to SSE clients
|
|
@@ -215,7 +250,7 @@ export async function startOrgServer(daemon, port = 0, credential) {
|
|
|
215
250
|
sseClients.clear();
|
|
216
251
|
server.close();
|
|
217
252
|
},
|
|
218
|
-
|
|
253
|
+
operatorCredential: operatorCred,
|
|
219
254
|
};
|
|
220
255
|
}
|
|
221
256
|
//# sourceMappingURL=server.js.map
|