@inetafrica/open-claudia 2.14.8 → 3.0.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/.env.example +30 -4
- package/CHANGELOG.md +21 -0
- package/README.md +87 -66
- package/bin/agent.js +44 -18
- package/bin/cli.js +30 -28
- package/bin/dream.js +5 -11
- package/bin/loopback-client.js +29 -5
- package/bin/schedule.js +19 -5
- package/bin/tool.js +23 -5
- package/bot-agent.js +5 -2350
- package/bot.js +105 -7
- package/channels/telegram/adapter.js +6 -1
- package/channels/voice/adapter.js +1 -0
- package/channels/voice/manage.js +43 -5
- package/config-dir.js +3 -11
- package/core/actions.js +149 -40
- package/core/approvals.js +136 -29
- package/core/auth-flow.js +103 -19
- package/core/config-dir.js +19 -0
- package/core/config.js +127 -69
- package/core/doctor.js +111 -57
- package/core/dream.js +219 -62
- package/core/enforcer.js +0 -0
- package/core/entities.js +2 -1
- package/core/fsutil.js +55 -0
- package/core/handlers.js +503 -217
- package/core/ideas.js +2 -1
- package/core/identity.js +8 -11
- package/core/io.js +24 -3
- package/core/jobs.js +589 -72
- package/core/lessons.js +3 -2
- package/core/loopback.js +45 -8
- package/core/memory-mutation-queue.js +241 -0
- package/core/migration-backup.js +1060 -0
- package/core/pack-review.js +295 -88
- package/core/packs.js +4 -3
- package/core/persona.js +2 -1
- package/core/process-tree.js +19 -2
- package/core/provider-migration.js +39 -0
- package/core/provider-status.js +80 -0
- package/core/providers/claude-events.js +117 -0
- package/core/providers/claude-hook.js +114 -0
- package/core/providers/claude.js +296 -0
- package/core/providers/codex-events.js +121 -0
- package/core/providers/codex-hook.js +280 -0
- package/core/providers/codex.js +286 -0
- package/core/providers/contract.js +153 -0
- package/core/providers/env.js +148 -0
- package/core/providers/events.js +170 -0
- package/core/providers/hook-command.js +22 -0
- package/core/providers/index.js +240 -0
- package/core/providers/utility-policy.js +269 -0
- package/core/recall/classic.js +2 -2
- package/core/recall/discoverer.js +71 -22
- package/core/recall/metrics.js +27 -1
- package/core/recall/tuning.js +4 -1
- package/core/recall/warm-walker.js +151 -108
- package/core/recall-filter.js +86 -61
- package/core/router.js +79 -7
- package/core/run-context.js +185 -0
- package/core/runner.js +1415 -1282
- package/core/scheduler.js +515 -210
- package/core/side-chat.js +346 -0
- package/core/state.js +1096 -95
- package/core/subagent.js +72 -98
- package/core/system-prompt.js +462 -279
- package/core/tool-guard.js +73 -39
- package/core/tools.js +22 -5
- package/core/transcripts.js +30 -1
- package/core/usage-log.js +19 -4
- package/core/utility-agent.js +654 -0
- package/core/web-auth.js +29 -13
- package/core/web-sessions.js +78 -0
- package/docs/CHANNEL_DESIGN.md +181 -0
- package/docs/MULTI_CHANNEL_PLAN.md +254 -0
- package/docs/PROVIDER_MIGRATION.md +67 -0
- package/health.js +50 -39
- package/package.json +51 -4
- package/setup.js +198 -38
- package/soul.md +39 -0
- package/test-ability-extraction.js +5 -0
- package/test-approval-async.js +63 -4
- package/test-cursor-removal.js +334 -0
- package/test-delivery-contract.js +88 -0
- package/test-enforcer.js +70 -27
- package/test-fixtures/current-provider-parity.json +132 -0
- package/test-fixtures/fake-agent-cli.js +477 -0
- package/test-fixtures/migrations/claude-only/jobs.json +3 -0
- package/test-fixtures/migrations/claude-only/sessions.json +5 -0
- package/test-fixtures/migrations/claude-only/state.json +5 -0
- package/test-fixtures/migrations/cursor-selected/crons.json +3 -0
- package/test-fixtures/migrations/cursor-selected/jobs.json +3 -0
- package/test-fixtures/migrations/cursor-selected/sessions.json +5 -0
- package/test-fixtures/migrations/cursor-selected/state.json +6 -0
- package/test-fixtures/migrations/dual-provider/jobs.json +3 -0
- package/test-fixtures/migrations/dual-provider/sessions.json +7 -0
- package/test-fixtures/migrations/dual-provider/state.json +10 -0
- package/test-fixtures/migrations/malformed-partial/jobs.json +1 -0
- package/test-fixtures/migrations/malformed-partial/sessions.json +1 -0
- package/test-fixtures/migrations/malformed-partial/sessions.json.bak +3 -0
- package/test-fixtures/migrations/malformed-partial/state.json +1 -0
- package/test-fixtures/migrations/malformed-partial/state.json.bak +5 -0
- package/test-fixtures/migrations/missing-project/jobs.json +3 -0
- package/test-fixtures/migrations/missing-project/sessions.json +3 -0
- package/test-fixtures/migrations/missing-project/state.json +4 -0
- package/test-fixtures/migrations/multi-user/jobs.json +4 -0
- package/test-fixtures/migrations/multi-user/sessions.json +4 -0
- package/test-fixtures/migrations/multi-user/state.json +6 -0
- package/test-fixtures/provider-event-samples.json +17 -0
- package/test-learning-e2e.js +5 -0
- package/test-memory-mutation-queue.js +191 -0
- package/test-provider-boot-matrix.js +399 -0
- package/test-provider-bootstrap.js +158 -0
- package/test-provider-capabilities.js +232 -0
- package/test-provider-claude.js +206 -0
- package/test-provider-codex.js +228 -0
- package/test-provider-compaction.js +371 -0
- package/test-provider-core-prompt.js +264 -0
- package/test-provider-coupling-audit.js +90 -0
- package/test-provider-dream.js +312 -0
- package/test-provider-enforcer.js +252 -0
- package/test-provider-env-isolation.js +150 -0
- package/test-provider-events.js +141 -0
- package/test-provider-fixture.js +332 -0
- package/test-provider-gateway.js +508 -0
- package/test-provider-language.js +89 -0
- package/test-provider-migration-backup.js +424 -0
- package/test-provider-pack-review.js +436 -0
- package/test-provider-parity-e2e.js +537 -0
- package/test-provider-prompt-parity.js +89 -0
- package/test-provider-recall.js +271 -0
- package/test-provider-registry.js +251 -0
- package/test-provider-resume-parity.js +41 -0
- package/test-provider-run-lifecycle.js +349 -0
- package/test-provider-runner.js +271 -0
- package/test-provider-scheduler.js +689 -0
- package/test-provider-session-commands.js +185 -0
- package/test-provider-session-history.js +205 -0
- package/test-provider-side-chat.js +337 -0
- package/test-provider-state-migration.js +316 -0
- package/test-provider-stream-decoder.js +69 -0
- package/test-provider-subagent.js +228 -0
- package/test-provider-tool-hooks.js +360 -0
- package/test-recall-discoverer.js +1 -0
- package/test-recall-engine.js +3 -3
- package/test-recall-evolution.js +18 -0
- package/test-run-lock.js +63 -0
- package/test-runner-watchdog-static.js +16 -8
- package/test-single-runtime.js +35 -0
- package/test-telegram-poll-recovery.js +56 -0
- package/test-tool-guard.js +56 -0
- package/test-tools.js +19 -0
- package/test-unified-identity.js +3 -1
- package/test-usage-accounting.js +92 -20
- package/test-utility-provider-policy.js +486 -0
- package/test-web-sessions.js +74 -0
- package/web.js +159 -45
package/core/subagent.js
CHANGED
|
@@ -1,129 +1,103 @@
|
|
|
1
|
-
|
|
2
|
-
// research or sub-tasks. No session resume, no shared state with the
|
|
3
|
-
// caller's turn — the output is captured as text and returned. The
|
|
4
|
-
// caller (a parent Claude turn invoking the CLI via Bash) decides what
|
|
5
|
-
// to do with the result.
|
|
1
|
+
"use strict";
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
// Compatibility surface for existing focused-task callers. Provider
|
|
4
|
+
// selection, safe prompt transport, lifecycle bounds, and process-tree cleanup
|
|
5
|
+
// all live in core/utility-agent.js; this module keeps the historic
|
|
6
|
+
// spawnSubagent() result shape while callers migrate purpose by purpose.
|
|
11
7
|
|
|
12
|
-
const
|
|
13
|
-
const MAX_OUTPUT_BYTES = 64 * 1024;
|
|
8
|
+
const { MAX_PROCESS_TIMEOUT } = require("./config");
|
|
14
9
|
|
|
10
|
+
const DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;
|
|
15
11
|
const concurrentByChannel = new Map();
|
|
16
12
|
|
|
17
13
|
function buildSubagentSystemPrompt(role) {
|
|
18
14
|
return [
|
|
19
|
-
"You are a sub-agent spawned by
|
|
15
|
+
"You are a sub-agent spawned by Open Claudia for a focused task.",
|
|
20
16
|
"Your reply is captured as raw text and returned to the parent agent — there is no user reading it directly.",
|
|
21
17
|
"Stay focused on the prompt. Be concise. Return findings; do not chat.",
|
|
22
|
-
"You do not have access to the parent
|
|
23
|
-
"
|
|
18
|
+
"You do not have access to the parent chat session, parent temporary files, or loopback send tools.",
|
|
19
|
+
"Work read-only: inspect with provider-native read/search tools and harmless shell queries, but do not change files or start long-running processes.",
|
|
24
20
|
role ? `Role: ${role}` : "",
|
|
25
21
|
].filter(Boolean).join("\n");
|
|
26
22
|
}
|
|
27
23
|
|
|
28
24
|
function trackStart(channelId) {
|
|
29
25
|
if (!channelId) return 0;
|
|
30
|
-
const
|
|
31
|
-
concurrentByChannel.set(channelId,
|
|
32
|
-
return
|
|
26
|
+
const current = concurrentByChannel.get(channelId) || 0;
|
|
27
|
+
concurrentByChannel.set(channelId, current + 1);
|
|
28
|
+
return current + 1;
|
|
33
29
|
}
|
|
34
30
|
|
|
35
31
|
function trackEnd(channelId) {
|
|
36
32
|
if (!channelId) return;
|
|
37
|
-
const
|
|
38
|
-
if (
|
|
39
|
-
else concurrentByChannel.set(channelId,
|
|
33
|
+
const current = concurrentByChannel.get(channelId) || 0;
|
|
34
|
+
if (current <= 1) concurrentByChannel.delete(channelId);
|
|
35
|
+
else concurrentByChannel.set(channelId, current - 1);
|
|
40
36
|
}
|
|
41
37
|
|
|
42
38
|
function concurrentCount(channelId) {
|
|
43
39
|
return concurrentByChannel.get(channelId) || 0;
|
|
44
40
|
}
|
|
45
41
|
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
const role = opts.role || null;
|
|
49
|
-
const channelId = opts.channelId || null;
|
|
50
|
-
const timeoutMs = Math.min(opts.timeoutMs || DEFAULT_TIMEOUT_MS, MAX_PROCESS_TIMEOUT || DEFAULT_TIMEOUT_MS);
|
|
51
|
-
|
|
52
|
-
const count = trackStart(channelId);
|
|
53
|
-
if (count > 3) {
|
|
54
|
-
console.warn(`subagent: ${count} concurrent sub-agents on channel ${channelId}`);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return new Promise((resolve, reject) => {
|
|
58
|
-
const args = ["-p"];
|
|
59
|
-
// Tool restriction. --allowedTools/--disallowedTools take variadic
|
|
60
|
-
// <tools...>, which would greedily swallow the trailing prompt arg — so we
|
|
61
|
-
// pass a single comma-joined token AND place these flags first, where the
|
|
62
|
-
// next arg (--output-format) is itself a flag, which stops the variadic.
|
|
63
|
-
// With --dangerously-skip-permissions on, a whitelist is the structural way
|
|
64
|
-
// to make a sub-agent genuinely read-only (e.g. the dream's introspection).
|
|
65
|
-
if (opts.allowedTools) args.push("--allowedTools", [].concat(opts.allowedTools).join(","));
|
|
66
|
-
if (opts.disallowedTools) args.push("--disallowedTools", [].concat(opts.disallowedTools).join(","));
|
|
67
|
-
// Sub-agents get the same tool-first deny-gate as the main agent (5b) —
|
|
68
|
-
// they also hold no keyring creds (botSubprocessEnv is cred-free).
|
|
69
|
-
try { args.push("--settings", require("./tool-guard").ensureHookSettings()); } catch (e) {}
|
|
70
|
-
args.push(
|
|
71
|
-
"--output-format", opts.json ? "json" : "text",
|
|
72
|
-
"--verbose",
|
|
73
|
-
"--append-system-prompt", opts.systemPrompt || buildSubagentSystemPrompt(role),
|
|
74
|
-
);
|
|
75
|
-
// Permissions. A genuinely read-only sub-agent (e.g. the dream's
|
|
76
|
-
// introspection) must use plan mode — verified to be the ONLY mechanism
|
|
77
|
-
// that blocks writes: --dangerously-skip-permissions OVERRIDES both
|
|
78
|
-
// --allowedTools and --disallowedTools, so a whitelist alone does NOT
|
|
79
|
-
// restrict. Default remains skip-permissions for research sub-agents that
|
|
80
|
-
// legitimately need Bash/Write.
|
|
81
|
-
if (opts.permissionMode) args.push("--permission-mode", opts.permissionMode);
|
|
82
|
-
else args.push("--dangerously-skip-permissions");
|
|
83
|
-
if (opts.model) args.push("--model", opts.model);
|
|
84
|
-
if (opts.effort) args.push("--effort", opts.effort);
|
|
85
|
-
args.push(prompt);
|
|
86
|
-
const env = { ...botSubprocessEnv(), ...claudeSubprocessEnv() };
|
|
87
|
-
const proc = spawn(CLAUDE_PATH, args, { cwd, env, stdio: ["ignore", "pipe", "pipe"] });
|
|
42
|
+
function createSubagentService(dependencies = {}) {
|
|
43
|
+
const runUtility = dependencies.spawnUtilityAgent || require("./utility-agent").spawnUtilityAgent;
|
|
88
44
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
45
|
+
async function spawnSubagent(prompt, opts = {}) {
|
|
46
|
+
const channelId = opts.channelId || null;
|
|
47
|
+
const count = trackStart(channelId);
|
|
48
|
+
if (count > 3) console.warn(`subagent: ${count} concurrent sub-agents on channel ${channelId}`);
|
|
92
49
|
|
|
93
|
-
|
|
94
|
-
if (
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
out += d.toString();
|
|
50
|
+
try {
|
|
51
|
+
if (opts.readOnly === false || opts.permissionMode === "direct") {
|
|
52
|
+
const error = new Error("Open Claudia sub-agents are read-only until provider tool enforcement is verified");
|
|
53
|
+
error.code = "UTILITY_READ_ONLY_REQUIRED";
|
|
54
|
+
throw error;
|
|
99
55
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
56
|
+
const timeoutMs = Math.min(
|
|
57
|
+
Number(opts.timeoutMs || DEFAULT_TIMEOUT_MS),
|
|
58
|
+
MAX_PROCESS_TIMEOUT || DEFAULT_TIMEOUT_MS,
|
|
59
|
+
);
|
|
60
|
+
const result = await runUtility(String(prompt || ""), {
|
|
61
|
+
purpose: "subagent",
|
|
62
|
+
provider: opts.provider == null ? null : opts.provider,
|
|
63
|
+
tier: opts.tier || "medium",
|
|
64
|
+
model: opts.model || null,
|
|
65
|
+
systemPrompt: opts.systemPrompt || buildSubagentSystemPrompt(opts.role || null),
|
|
66
|
+
readOnly: true,
|
|
67
|
+
...(opts.allowedTools !== undefined ? { allowedTools: [].concat(opts.allowedTools) } : {}),
|
|
68
|
+
...(opts.disallowedTools !== undefined ? { disallowedTools: [].concat(opts.disallowedTools) } : {}),
|
|
69
|
+
...(opts.outputSchema ? { outputSchema: opts.outputSchema } : {}),
|
|
70
|
+
...(opts.effort ? { effort: opts.effort } : {}),
|
|
71
|
+
timeoutMs,
|
|
72
|
+
cwd: opts.cwd || process.cwd(),
|
|
73
|
+
signal: opts.signal || null,
|
|
74
|
+
});
|
|
75
|
+
return {
|
|
76
|
+
text: result.text,
|
|
77
|
+
truncated: !!result.truncated,
|
|
78
|
+
stderr: result.stderr || "",
|
|
79
|
+
code: result.exitCode == null ? 0 : result.exitCode,
|
|
80
|
+
provider: result.provider,
|
|
81
|
+
model: result.model,
|
|
82
|
+
tier: result.tier,
|
|
83
|
+
fallbackUsed: !!result.fallbackUsed,
|
|
84
|
+
noTools: result.noTools,
|
|
85
|
+
noProductSideEffects: result.noProductSideEffects,
|
|
86
|
+
};
|
|
87
|
+
} finally {
|
|
117
88
|
trackEnd(channelId);
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return reject(new Error(msg));
|
|
123
|
-
}
|
|
124
|
-
resolve({ text, truncated, stderr: stderrText, code });
|
|
125
|
-
});
|
|
126
|
-
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return { spawnSubagent };
|
|
127
93
|
}
|
|
128
94
|
|
|
129
|
-
|
|
95
|
+
const defaultService = createSubagentService();
|
|
96
|
+
|
|
97
|
+
module.exports = {
|
|
98
|
+
DEFAULT_TIMEOUT_MS,
|
|
99
|
+
buildSubagentSystemPrompt,
|
|
100
|
+
concurrentCount,
|
|
101
|
+
createSubagentService,
|
|
102
|
+
spawnSubagent: defaultService.spawnSubagent,
|
|
103
|
+
};
|