zelari-code 0.1.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/LICENSE +21 -0
- package/README.md +156 -0
- package/bin/zelari-code.js +64 -0
- package/dist/agents/advancedTools.js +115 -0
- package/dist/agents/advancedTools.js.map +1 -0
- package/dist/agents/councilApi.js +375 -0
- package/dist/agents/councilApi.js.map +1 -0
- package/dist/agents/councilDirectives.js +100 -0
- package/dist/agents/councilDirectives.js.map +1 -0
- package/dist/agents/promoteMember.js +210 -0
- package/dist/agents/promoteMember.js.map +1 -0
- package/dist/agents/promptModules.js +139 -0
- package/dist/agents/promptModules.js.map +1 -0
- package/dist/agents/roles.js +281 -0
- package/dist/agents/roles.js.map +1 -0
- package/dist/agents/skills/builtin/debugging.js +248 -0
- package/dist/agents/skills/builtin/debugging.js.map +1 -0
- package/dist/agents/skills/builtin/docs.js +301 -0
- package/dist/agents/skills/builtin/docs.js.map +1 -0
- package/dist/agents/skills/builtin/git-ops.js +301 -0
- package/dist/agents/skills/builtin/git-ops.js.map +1 -0
- package/dist/agents/skills/builtin/planning.js +335 -0
- package/dist/agents/skills/builtin/planning.js.map +1 -0
- package/dist/agents/skills/builtin/refactoring.js +261 -0
- package/dist/agents/skills/builtin/refactoring.js.map +1 -0
- package/dist/agents/skills/builtin/review.js +302 -0
- package/dist/agents/skills/builtin/review.js.map +1 -0
- package/dist/agents/skills/builtin/testing.js +245 -0
- package/dist/agents/skills/builtin/testing.js.map +1 -0
- package/dist/agents/skills.js +272 -0
- package/dist/agents/skills.js.map +1 -0
- package/dist/agents/systemPromptBuilder.js +151 -0
- package/dist/agents/systemPromptBuilder.js.map +1 -0
- package/dist/agents/toolSchemas.js +249 -0
- package/dist/agents/toolSchemas.js.map +1 -0
- package/dist/agents/tools.js +196 -0
- package/dist/agents/tools.js.map +1 -0
- package/dist/agents/vaultTools.js +134 -0
- package/dist/agents/vaultTools.js.map +1 -0
- package/dist/cli/app.js +1823 -0
- package/dist/cli/app.js.map +1 -0
- package/dist/cli/branchManager.js +280 -0
- package/dist/cli/branchManager.js.map +1 -0
- package/dist/cli/compaction.js +63 -0
- package/dist/cli/compaction.js.map +1 -0
- package/dist/cli/components/ChatStream.js +23 -0
- package/dist/cli/components/ChatStream.js.map +1 -0
- package/dist/cli/components/CollapsibleToolOutput.js +38 -0
- package/dist/cli/components/CollapsibleToolOutput.js.map +1 -0
- package/dist/cli/components/Header.js +31 -0
- package/dist/cli/components/Header.js.map +1 -0
- package/dist/cli/components/InputBar.js +9 -0
- package/dist/cli/components/InputBar.js.map +1 -0
- package/dist/cli/components/Sidebar.js +17 -0
- package/dist/cli/components/Sidebar.js.map +1 -0
- package/dist/cli/councilCost.js +81 -0
- package/dist/cli/councilCost.js.map +1 -0
- package/dist/cli/councilDispatcher.js +56 -0
- package/dist/cli/councilDispatcher.js.map +1 -0
- package/dist/cli/councilFeedback.js +164 -0
- package/dist/cli/councilFeedback.js.map +1 -0
- package/dist/cli/crossProviderFailover.js +83 -0
- package/dist/cli/crossProviderFailover.js.map +1 -0
- package/dist/cli/gitOps.js +96 -0
- package/dist/cli/gitOps.js.map +1 -0
- package/dist/cli/grokOAuth.js +375 -0
- package/dist/cli/grokOAuth.js.map +1 -0
- package/dist/cli/keyStore.js +263 -0
- package/dist/cli/keyStore.js.map +1 -0
- package/dist/cli/keyValidator.js +83 -0
- package/dist/cli/keyValidator.js.map +1 -0
- package/dist/cli/main.bundled.js +21428 -0
- package/dist/cli/main.bundled.js.map +7 -0
- package/dist/cli/main.js +72 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/metrics.js +131 -0
- package/dist/cli/metrics.js.map +1 -0
- package/dist/cli/modelDiscovery.js +234 -0
- package/dist/cli/modelDiscovery.js.map +1 -0
- package/dist/cli/modelPricing.js +112 -0
- package/dist/cli/modelPricing.js.map +1 -0
- package/dist/cli/oauthCallbackServer.js +207 -0
- package/dist/cli/oauthCallbackServer.js.map +1 -0
- package/dist/cli/provider/openai-compatible.js +236 -0
- package/dist/cli/provider/openai-compatible.js.map +1 -0
- package/dist/cli/providerConfig.js +210 -0
- package/dist/cli/providerConfig.js.map +1 -0
- package/dist/cli/providerFailover.js +90 -0
- package/dist/cli/providerFailover.js.map +1 -0
- package/dist/cli/refreshRegistry.js +77 -0
- package/dist/cli/refreshRegistry.js.map +1 -0
- package/dist/cli/safety/auditLogger.js +111 -0
- package/dist/cli/safety/auditLogger.js.map +1 -0
- package/dist/cli/safety/sandboxPath.js +62 -0
- package/dist/cli/safety/sandboxPath.js.map +1 -0
- package/dist/cli/safety/shellBlocklist.js +71 -0
- package/dist/cli/safety/shellBlocklist.js.map +1 -0
- package/dist/cli/sessionManager.js +149 -0
- package/dist/cli/sessionManager.js.map +1 -0
- package/dist/cli/skillCache.js +205 -0
- package/dist/cli/skillCache.js.map +1 -0
- package/dist/cli/skillHistory.js +178 -0
- package/dist/cli/skillHistory.js.map +1 -0
- package/dist/cli/skillSuggest.js +132 -0
- package/dist/cli/skillSuggest.js.map +1 -0
- package/dist/cli/slashCommands.js +431 -0
- package/dist/cli/slashCommands.js.map +1 -0
- package/dist/cli/toolRegistry.js +187 -0
- package/dist/cli/toolRegistry.js.map +1 -0
- package/dist/cli/updater.js +157 -0
- package/dist/cli/updater.js.map +1 -0
- package/dist/main/core/AgentHarness.js +345 -0
- package/dist/main/core/AgentHarness.js.map +1 -0
- package/dist/main/core/providerStream.js +99 -0
- package/dist/main/core/providerStream.js.map +1 -0
- package/dist/main/core/sessionJsonl.js +99 -0
- package/dist/main/core/sessionJsonl.js.map +1 -0
- package/dist/main/core/tools/auditLog.js +26 -0
- package/dist/main/core/tools/auditLog.js.map +1 -0
- package/dist/main/core/tools/builtin/filesystem.js +110 -0
- package/dist/main/core/tools/builtin/filesystem.js.map +1 -0
- package/dist/main/core/tools/builtin/search.js +56 -0
- package/dist/main/core/tools/builtin/search.js.map +1 -0
- package/dist/main/core/tools/builtin/shell.js +51 -0
- package/dist/main/core/tools/builtin/shell.js.map +1 -0
- package/dist/main/core/tools/registry.js +71 -0
- package/dist/main/core/tools/registry.js.map +1 -0
- package/dist/main/core/tools/toolTypes.js +8 -0
- package/dist/main/core/tools/toolTypes.js.map +1 -0
- package/dist/main/core/tools/zodBridge.js +48 -0
- package/dist/main/core/tools/zodBridge.js.map +1 -0
- package/dist/shared/eventBus.js +104 -0
- package/dist/shared/eventBus.js.map +1 -0
- package/dist/shared/events.js +73 -0
- package/dist/shared/events.js.map +1 -0
- package/dist/shared/index.js +8 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/types/context.js +3 -0
- package/dist/types/context.js.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/knowledge.js +2 -0
- package/dist/types/knowledge.js.map +1 -0
- package/dist/types/systemTypes.js +10 -0
- package/dist/types/systemTypes.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providerConfig.js","sourceRoot":"","sources":["../../src/cli/providerConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* providerFailover — wraps two OpenAI-compatible providers so the second
|
|
3
|
+
* is tried when the first yields transient errors (Task B.4).
|
|
4
|
+
*
|
|
5
|
+
* Behavior:
|
|
6
|
+
* - Stream events from `primary` first
|
|
7
|
+
* - On the FIRST transient failure (network error OR HTTP 5xx),
|
|
8
|
+
* close the primary stream and switch to `fallback`
|
|
9
|
+
* - On a 4xx error (auth, bad request) do NOT failover — surface the
|
|
10
|
+
* error to the caller; these are programming/auth issues that won't
|
|
11
|
+
* be fixed by retrying against a different provider
|
|
12
|
+
* - On a normal `finish` event, the fallback is NEVER tried
|
|
13
|
+
*
|
|
14
|
+
* "First failure" means we DON'T keep retrying the primary. If you want
|
|
15
|
+
* N retries, write your own retry loop outside.
|
|
16
|
+
*
|
|
17
|
+
* @see docs/plans/2026-06-29-anathema-coder-v3-B.md
|
|
18
|
+
*/
|
|
19
|
+
const DEFAULT_IS_TRANSIENT = (delta) => delta.kind === 'error';
|
|
20
|
+
/**
|
|
21
|
+
* Wraps two ProviderStreamFn instances with first-failure failover.
|
|
22
|
+
* Returns a new ProviderStreamFn — pass this to AgentHarness.
|
|
23
|
+
*/
|
|
24
|
+
export function providerFailover(options) {
|
|
25
|
+
const isTransient = options.isTransientFailure ?? DEFAULT_IS_TRANSIENT;
|
|
26
|
+
// Task J.1 (v3-J) — when a label is provided, the [failover] messages
|
|
27
|
+
// include it so the user can see which provider the system switched to.
|
|
28
|
+
// When absent, messages are byte-identical to v3-G (backward-compat).
|
|
29
|
+
const primaryFailedMsg = options.fallbackLabel
|
|
30
|
+
? `[failover] primary failed, switching to ${options.fallbackLabel}`
|
|
31
|
+
: '[failover] primary failed, switching to fallback';
|
|
32
|
+
const primaryThrewMsg = options.fallbackLabel
|
|
33
|
+
? `[failover] primary threw, switching to ${options.fallbackLabel}: `
|
|
34
|
+
: '[failover] primary threw: ';
|
|
35
|
+
const fallbackFailedMsg = options.fallbackLabel
|
|
36
|
+
? `[failover] fallback (${options.fallbackLabel}) also failed: `
|
|
37
|
+
: '[failover] fallback also failed: ';
|
|
38
|
+
return async function* (params) {
|
|
39
|
+
const triedFallback = { value: false };
|
|
40
|
+
try {
|
|
41
|
+
for await (const delta of options.primary(params)) {
|
|
42
|
+
if (isTransient(delta)) {
|
|
43
|
+
// Forward the original error to the caller so they see what
|
|
44
|
+
// happened, then announce the failover and bail out.
|
|
45
|
+
yield delta;
|
|
46
|
+
triedFallback.value = true;
|
|
47
|
+
yield {
|
|
48
|
+
kind: 'error',
|
|
49
|
+
message: primaryFailedMsg,
|
|
50
|
+
};
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
yield delta;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
// Network-level throw (fetch rejection, etc.) → also failover.
|
|
58
|
+
triedFallback.value = true;
|
|
59
|
+
yield {
|
|
60
|
+
kind: 'error',
|
|
61
|
+
message: `${primaryThrewMsg}${err instanceof Error ? err.message : String(err)}`,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (triedFallback.value) {
|
|
65
|
+
try {
|
|
66
|
+
for await (const delta of options.fallback(params)) {
|
|
67
|
+
yield delta;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
yield {
|
|
72
|
+
kind: 'error',
|
|
73
|
+
message: `${fallbackFailedMsg}${err instanceof Error ? err.message : String(err)}`,
|
|
74
|
+
};
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Convenience: filter a ProviderStreamFn's deltas to check what kinds it
|
|
82
|
+
* emits. Useful for tests / debugging.
|
|
83
|
+
*/
|
|
84
|
+
export async function collectDeltas(fn, params) {
|
|
85
|
+
const out = [];
|
|
86
|
+
for await (const d of fn(params))
|
|
87
|
+
out.push(d);
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=providerFailover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providerFailover.js","sourceRoot":"","sources":["../../src/cli/providerFailover.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAwBH,MAAM,oBAAoB,GAAG,CAAC,KAAoB,EAAW,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;AAEvF;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAwB;IACvD,MAAM,WAAW,GAAG,OAAO,CAAC,kBAAkB,IAAI,oBAAoB,CAAC;IACvE,sEAAsE;IACtE,wEAAwE;IACxE,sEAAsE;IACtE,MAAM,gBAAgB,GAAG,OAAO,CAAC,aAAa;QAC5C,CAAC,CAAC,2CAA2C,OAAO,CAAC,aAAa,EAAE;QACpE,CAAC,CAAC,kDAAkD,CAAC;IACvD,MAAM,eAAe,GAAG,OAAO,CAAC,aAAa;QAC3C,CAAC,CAAC,0CAA0C,OAAO,CAAC,aAAa,IAAI;QACrE,CAAC,CAAC,4BAA4B,CAAC;IACjC,MAAM,iBAAiB,GAAG,OAAO,CAAC,aAAa;QAC7C,CAAC,CAAC,wBAAwB,OAAO,CAAC,aAAa,iBAAiB;QAChE,CAAC,CAAC,mCAAmC,CAAC;IACxC,OAAO,KAAK,SAAS,CAAC,EAAE,MAAM;QAC5B,MAAM,aAAa,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QACvC,IAAI,CAAC;YACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClD,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;oBACvB,4DAA4D;oBAC5D,qDAAqD;oBACrD,MAAM,KAAK,CAAC;oBACZ,aAAa,CAAC,KAAK,GAAG,IAAI,CAAC;oBAC3B,MAAM;wBACJ,IAAI,EAAE,OAAO;wBACb,OAAO,EAAE,gBAAgB;qBAC1B,CAAC;oBACF,MAAM;gBACR,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,+DAA+D;YAC/D,aAAa,CAAC,KAAK,GAAG,IAAI,CAAC;YAC3B,MAAM;gBACJ,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,GAAG,eAAe,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;aACjF,CAAC;QACJ,CAAC;QACD,IAAI,aAAa,CAAC,KAAK,EAAE,CAAC;YACxB,IAAI,CAAC;gBACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBACnD,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM;oBACJ,IAAI,EAAE,OAAO;oBACb,OAAO,EAAE,GAAG,iBAAiB,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;iBACnF,CAAC;gBACF,OAAO;YACT,CAAC;QACH,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,EAAoB,EACpB,MAAuC;IAEvC,MAAM,GAAG,GAAoB,EAAE,CAAC;IAChC,IAAI,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC;QAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9C,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* refreshRegistry — pluggable per-provider token refresh impls (v3-F).
|
|
3
|
+
*
|
|
4
|
+
* Why: v3-D hard-wired refresh support for Grok only. Other providers (MiniMax,
|
|
5
|
+
* GLM) ship static API keys today and have no public OAuth endpoint. When that
|
|
6
|
+
* changes, callers want to add a refresh impl without touching keyStore or the
|
|
7
|
+
* auto-refresh path in `resolveApiKeyWithMeta`.
|
|
8
|
+
*
|
|
9
|
+
* Design:
|
|
10
|
+
* - A simple `Map<ProviderName, RefreshImpl>` plus helpers.
|
|
11
|
+
* - The default impl for `grok` is registered at module import time via
|
|
12
|
+
* `registerDefaultRefreshImpls()` (idempotent — safe to call multiple times).
|
|
13
|
+
* - `getRefreshImpl(id)` returns the registered impl OR `null`. Callers are
|
|
14
|
+
* responsible for the "no impl" branch — typically log + return stale token.
|
|
15
|
+
* - `registerRefreshImpl(id, impl)` lets tests and future providers inject
|
|
16
|
+
* custom impls without depending on this module's internals.
|
|
17
|
+
*
|
|
18
|
+
* The adapter for Grok (`grokRefreshAdapter`) bridges the
|
|
19
|
+
* `(providerId, refreshToken) => Promise<{...}>` shape required by `RefreshImpl`
|
|
20
|
+
* with `refreshGrokToken`'s `{clientId, refreshToken}` shape. It pulls
|
|
21
|
+
* `GROK_OAUTH_CLIENT_ID` from env at call time (so tests can mutate it).
|
|
22
|
+
*
|
|
23
|
+
* @see electron/cli/keyStore.ts (RefreshImpl type, resolveApiKeyWithMeta)
|
|
24
|
+
* @see docs/plans/2026-06-29-anathema-coder-v3-F.md
|
|
25
|
+
*/
|
|
26
|
+
import { refreshGrokToken } from './grokOAuth.js';
|
|
27
|
+
const registry = new Map();
|
|
28
|
+
/**
|
|
29
|
+
* Register a refresh impl for a provider. Overwrites any previous impl.
|
|
30
|
+
* Pass `null` or use `unregisterRefreshImpl` to remove.
|
|
31
|
+
*/
|
|
32
|
+
export function registerRefreshImpl(id, impl) {
|
|
33
|
+
if (impl === null) {
|
|
34
|
+
registry.delete(id);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
registry.set(id, impl);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Remove a refresh impl. No-op if not registered. */
|
|
41
|
+
export function unregisterRefreshImpl(id) {
|
|
42
|
+
registry.delete(id);
|
|
43
|
+
}
|
|
44
|
+
/** Look up a refresh impl. Returns `null` if no impl is registered. */
|
|
45
|
+
export function getRefreshImpl(id) {
|
|
46
|
+
return registry.get(id) ?? null;
|
|
47
|
+
}
|
|
48
|
+
/** Return all registered provider ids (useful for /provider status). */
|
|
49
|
+
export function listRefreshImpls() {
|
|
50
|
+
return Array.from(registry.keys());
|
|
51
|
+
}
|
|
52
|
+
/** Test-only helper: wipe the registry. Production code should not call this. */
|
|
53
|
+
export function clearRefreshRegistry() {
|
|
54
|
+
registry.clear();
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Adapter from `refreshGrokToken({clientId, refreshToken})` to the generic
|
|
58
|
+
* `RefreshImpl(providerId, refreshToken)` shape. Reads GROK_OAUTH_CLIENT_ID
|
|
59
|
+
* from env at call time so tests can override.
|
|
60
|
+
*/
|
|
61
|
+
export const grokRefreshAdapter = async (_providerId, refreshToken) => {
|
|
62
|
+
const clientId = process.env.GROK_OAUTH_CLIENT_ID;
|
|
63
|
+
if (!clientId || clientId.trim().length === 0) {
|
|
64
|
+
throw new Error('Missing GROK_OAUTH_CLIENT_ID env var');
|
|
65
|
+
}
|
|
66
|
+
return refreshGrokToken({ clientId, refreshToken });
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Register the built-in default impls. Idempotent — calling multiple times
|
|
70
|
+
* is a no-op once registered. Called at module init from keyStore.
|
|
71
|
+
*/
|
|
72
|
+
export function registerDefaultRefreshImpls() {
|
|
73
|
+
if (!registry.has('grok')) {
|
|
74
|
+
registry.set('grok', grokRefreshAdapter);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=refreshRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refreshRegistry.js","sourceRoot":"","sources":["../../src/cli/refreshRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAmBlD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA6B,CAAC;AAEtD;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAgB,EAAE,IAAwB;IAC5E,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACtB,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACzB,CAAC;AACH,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,qBAAqB,CAAC,EAAgB;IACpD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AACtB,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,cAAc,CAAC,EAAgB;IAC7C,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;AAClC,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,gBAAgB;IAC9B,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,oBAAoB;IAClC,QAAQ,CAAC,KAAK,EAAE,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAgB,KAAK,EAClD,WAAW,EACX,YAAY,EACZ,EAAE;IACF,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAClD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,gBAAgB,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,2BAA2B;IACzC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* auditLogger — append-only JSONL log of every tool invocation.
|
|
3
|
+
*
|
|
4
|
+
* Task A2 of AnathemaCoder v3-A. Persists to
|
|
5
|
+
* `~/.tmp/anathema-coder/audit.jsonl` by default (override via
|
|
6
|
+
* ANATHEMA_AUDIT_LOG env). Each entry is one line of JSON with:
|
|
7
|
+
* ts, sessionId, tool, args (summary), ok, resultSummary, durationMs, error?
|
|
8
|
+
*
|
|
9
|
+
* @see docs/plans/2026-06-29-anathema-coder-v3.md (Task A2)
|
|
10
|
+
*/
|
|
11
|
+
import { promises as fs } from 'node:fs';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import os from 'node:os';
|
|
14
|
+
export class AuditLogger {
|
|
15
|
+
logPath;
|
|
16
|
+
writeQueue = Promise.resolve();
|
|
17
|
+
constructor(logPath) {
|
|
18
|
+
this.logPath = logPath ?? defaultAuditPath();
|
|
19
|
+
}
|
|
20
|
+
/** Path to the JSONL file. */
|
|
21
|
+
get path() {
|
|
22
|
+
return this.logPath;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Append one entry to the log. Serialized through a queue so concurrent
|
|
26
|
+
* invocations do not interleave their writes.
|
|
27
|
+
*/
|
|
28
|
+
async append(entry) {
|
|
29
|
+
const line = JSON.stringify(entry) + '\n';
|
|
30
|
+
this.writeQueue = this.writeQueue.then(async () => {
|
|
31
|
+
await fs.mkdir(path.dirname(this.logPath), { recursive: true });
|
|
32
|
+
await fs.appendFile(this.logPath, line, 'utf-8');
|
|
33
|
+
});
|
|
34
|
+
return this.writeQueue;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Run a tool invocation and write an audit entry capturing the result.
|
|
38
|
+
* Returns the tool result unchanged so callers can compose it as
|
|
39
|
+
* `const r = await audit.runTool({ tool: 'bash', args: {...}, sessionId, fn })`.
|
|
40
|
+
*/
|
|
41
|
+
async runTool(params) {
|
|
42
|
+
const start = Date.now();
|
|
43
|
+
let ok = true;
|
|
44
|
+
let error;
|
|
45
|
+
let resultSummary = '';
|
|
46
|
+
try {
|
|
47
|
+
const result = await params.fn();
|
|
48
|
+
resultSummary = (params.summarize?.(result) ?? safeStringify(result)).slice(0, 200);
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
ok = false;
|
|
53
|
+
error = err instanceof Error ? err.message : String(err);
|
|
54
|
+
resultSummary = (params.summarizeError?.(err) ?? error).slice(0, 200);
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
const entry = {
|
|
59
|
+
ts: new Date(start).toISOString(),
|
|
60
|
+
sessionId: params.sessionId,
|
|
61
|
+
tool: params.tool,
|
|
62
|
+
args: redactArgs(params.args),
|
|
63
|
+
ok,
|
|
64
|
+
resultSummary,
|
|
65
|
+
durationMs: Date.now() - start,
|
|
66
|
+
...(error !== undefined ? { error } : {}),
|
|
67
|
+
};
|
|
68
|
+
// Fire-and-forget: do not block the caller on disk I/O, but still
|
|
69
|
+
// serialize writes through the queue.
|
|
70
|
+
void this.append(entry).catch((err) => {
|
|
71
|
+
// Best-effort logging — never throw from inside the finally.
|
|
72
|
+
console.error('[auditLogger] failed to append entry:', err);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function defaultAuditPath() {
|
|
78
|
+
const override = process.env.ANATHEMA_AUDIT_LOG;
|
|
79
|
+
if (override && override.trim().length > 0)
|
|
80
|
+
return override;
|
|
81
|
+
return path.join(os.tmpdir(), 'zelari-code', 'audit.jsonl');
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Redact sensitive args (anything that looks like an API key or secret)
|
|
85
|
+
* before writing to the audit log. Conservative: replaces long random
|
|
86
|
+
* strings and env-var-style 'key' / 'apiKey' fields.
|
|
87
|
+
*/
|
|
88
|
+
function redactArgs(args) {
|
|
89
|
+
const redacted = {};
|
|
90
|
+
for (const [k, v] of Object.entries(args)) {
|
|
91
|
+
if (/(api[_-]?key|secret|token|password)/i.test(k) && typeof v === 'string') {
|
|
92
|
+
redacted[k] = '***';
|
|
93
|
+
}
|
|
94
|
+
else if (typeof v === 'string' && v.length > 64) {
|
|
95
|
+
redacted[k] = v.slice(0, 60) + '…';
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
redacted[k] = v;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return redacted;
|
|
102
|
+
}
|
|
103
|
+
function safeStringify(value) {
|
|
104
|
+
try {
|
|
105
|
+
return typeof value === 'string' ? value : JSON.stringify(value);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return String(value);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=auditLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auditLogger.js","sourceRoot":"","sources":["../../../src/cli/safety/auditLogger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sandboxPath — enforce that filesystem tool paths stay inside an allowed
|
|
3
|
+
* root directory (default: process.cwd()).
|
|
4
|
+
*
|
|
5
|
+
* Prevents the agent from escaping its working directory by using
|
|
6
|
+
* `..` segments or absolute paths outside the sandbox.
|
|
7
|
+
*
|
|
8
|
+
* Task A2 of AnathemaCoder v3-A.
|
|
9
|
+
*
|
|
10
|
+
* @see docs/plans/2026-06-29-anathema-coder-v3.md (Task A2)
|
|
11
|
+
*/
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
export class SandboxViolationError extends Error {
|
|
14
|
+
attemptedPath;
|
|
15
|
+
resolvedPath;
|
|
16
|
+
constructor(message, attemptedPath, resolvedPath) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.attemptedPath = attemptedPath;
|
|
19
|
+
this.resolvedPath = resolvedPath;
|
|
20
|
+
this.name = 'SandboxViolationError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Resolve a user-supplied path against an allowed root, throwing
|
|
25
|
+
* SandboxViolationError if the result escapes the root.
|
|
26
|
+
*
|
|
27
|
+
* - Absolute paths are taken as-is but must be inside the root.
|
|
28
|
+
* - Relative paths are joined to the root.
|
|
29
|
+
* - Symlink resolution is the caller's responsibility (the FS tool
|
|
30
|
+
* resolves on read/write); this function only checks textual containment
|
|
31
|
+
* after normalization.
|
|
32
|
+
*/
|
|
33
|
+
export function resolveSandboxedPath(userPath, options = {}) {
|
|
34
|
+
if (typeof userPath !== 'string' || userPath.length === 0) {
|
|
35
|
+
throw new SandboxViolationError('Empty path', userPath, '');
|
|
36
|
+
}
|
|
37
|
+
const root = path.resolve(options.root ?? process.cwd());
|
|
38
|
+
const resolved = path.isAbsolute(userPath)
|
|
39
|
+
? path.resolve(userPath)
|
|
40
|
+
: path.resolve(root, userPath);
|
|
41
|
+
// Normalize for comparison: ensure trailing separator for prefix check
|
|
42
|
+
// so `/foo/bar` does not match `/foo/barbaz`.
|
|
43
|
+
const rootWithSep = root.endsWith(path.sep) ? root : root + path.sep;
|
|
44
|
+
if (resolved !== root && !resolved.startsWith(rootWithSep)) {
|
|
45
|
+
throw new SandboxViolationError(`Path escapes sandbox root: ${userPath} → ${resolved} (root: ${root})`, userPath, resolved);
|
|
46
|
+
}
|
|
47
|
+
return resolved;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Lightweight check that does NOT throw — returns true if the path
|
|
51
|
+
* would be allowed by resolveSandboxedPath.
|
|
52
|
+
*/
|
|
53
|
+
export function isPathInsideSandbox(userPath, options = {}) {
|
|
54
|
+
try {
|
|
55
|
+
resolveSandboxedPath(userPath, options);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=sandboxPath.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandboxPath.js","sourceRoot":"","sources":["../../../src/cli/safety/sandboxPath.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAG5B;IACA;IAHlB,YACE,OAAe,EACC,aAAqB,EACrB,YAAoB;QAEpC,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,kBAAa,GAAb,aAAa,CAAQ;QACrB,iBAAY,GAAZ,YAAY,CAAQ;QAGpC,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAgB,EAChB,UAA6B,EAAE;IAE/B,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,qBAAqB,CAAC,YAAY,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QACxC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;QACxB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAEjC,uEAAuE;IACvE,8CAA8C;IAC9C,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC;IACrE,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,qBAAqB,CAC7B,8BAA8B,QAAQ,MAAM,QAAQ,WAAW,IAAI,GAAG,EACtE,QAAQ,EACR,QAAQ,CACT,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,UAA6B,EAAE;IAE/B,IAAI,CAAC;QACH,oBAAoB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* shellBlocklist — reject shell commands that look destructive or that
|
|
3
|
+
* exfiltrate data.
|
|
4
|
+
*
|
|
5
|
+
* Task A2 of AnathemaCoder v3-A.
|
|
6
|
+
*
|
|
7
|
+
* @see docs/plans/2026-06-29-anathema-coder-v3.md (Task A2)
|
|
8
|
+
*/
|
|
9
|
+
export class ShellBlockedError extends Error {
|
|
10
|
+
reason;
|
|
11
|
+
pattern;
|
|
12
|
+
constructor(message, reason, pattern) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.reason = reason;
|
|
15
|
+
this.pattern = pattern;
|
|
16
|
+
this.name = 'ShellBlockedError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Default blocklist. Conservative: prefers false positives over letting
|
|
21
|
+
* the agent destroy the user's machine.
|
|
22
|
+
*/
|
|
23
|
+
const DEFAULT_RULES = [
|
|
24
|
+
// Recursive destructive on root-ish paths. Match `rm` followed by 1-3
|
|
25
|
+
// single-letter flag clusters (e.g. -rf, -fr, -r, -f) and a root path.
|
|
26
|
+
{ pattern: /\brm\s+(?:-[a-z]+\s+){1,3}\/\s*$/, reason: 'rm -rf /' },
|
|
27
|
+
{ pattern: /\brm\s+(?:-[a-z]+\s+){1,3}\/etc\b/, reason: 'rm -rf /etc' },
|
|
28
|
+
{ pattern: /\brm\s+(?:-[a-z]+\s+){1,3}\/boot\b/, reason: 'rm -rf /boot' },
|
|
29
|
+
{ pattern: /\brm\s+(?:-[a-z]+\s+){1,3}\/usr\b/, reason: 'rm -rf /usr' },
|
|
30
|
+
// Disk wipe
|
|
31
|
+
{ pattern: /\bmkfs(?:\.[a-z0-9]+)?\s+\/dev\//, reason: 'mkfs on device' },
|
|
32
|
+
{ pattern: /\bdd\s+.*of=\/dev\//, reason: 'dd to device' },
|
|
33
|
+
// Fork bomb
|
|
34
|
+
{ pattern: /:\(\)\s*\{\s*:\|:&\s*\}/, reason: 'fork bomb' },
|
|
35
|
+
// Network exfiltration / arbitrary download
|
|
36
|
+
{ pattern: /\bcurl\s+[^|]*\|\s*(?:sudo\s+)?(?:ba)?sh/, reason: 'curl | sh' },
|
|
37
|
+
{ pattern: /\bwget\s+[^|]*\|\s*(?:sudo\s+)?(?:ba)?sh/, reason: 'wget | sh' },
|
|
38
|
+
// Privilege escalation without explicit user intent
|
|
39
|
+
{ pattern: /\bsudo\s+/, reason: 'sudo without explicit consent' },
|
|
40
|
+
// System file overwrites
|
|
41
|
+
{ pattern: />\s*\/etc\//, reason: 'redirect to /etc' },
|
|
42
|
+
{ pattern: />\s*\/boot\//, reason: 'redirect to /boot' },
|
|
43
|
+
{ pattern: />\s*\/usr\//, reason: 'redirect to /usr' },
|
|
44
|
+
];
|
|
45
|
+
/**
|
|
46
|
+
* Test a shell command against the blocklist.
|
|
47
|
+
* Returns null if allowed, or a BlockRule describing why it was blocked.
|
|
48
|
+
*/
|
|
49
|
+
export function findBlockedReason(command, rules = DEFAULT_RULES) {
|
|
50
|
+
if (typeof command !== 'string' || command.length === 0)
|
|
51
|
+
return null;
|
|
52
|
+
for (const rule of rules) {
|
|
53
|
+
if (rule.pattern.test(command)) {
|
|
54
|
+
return rule;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Throw ShellBlockedError if the command matches any blocklist pattern.
|
|
61
|
+
* Otherwise return normally.
|
|
62
|
+
*/
|
|
63
|
+
export function assertShellAllowed(command) {
|
|
64
|
+
const blocked = findBlockedReason(command);
|
|
65
|
+
if (blocked) {
|
|
66
|
+
throw new ShellBlockedError(`Shell command blocked: ${blocked.reason}`, blocked.reason, blocked.pattern.source);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** Expose the default rules for testing/introspection. */
|
|
70
|
+
export const DEFAULT_BLOCK_RULES = DEFAULT_RULES;
|
|
71
|
+
//# sourceMappingURL=shellBlocklist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellBlocklist.js","sourceRoot":"","sources":["../../../src/cli/safety/shellBlocklist.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAGxB;IACA;IAHlB,YACE,OAAe,EACC,MAAc,EACd,OAAe;QAE/B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,WAAM,GAAN,MAAM,CAAQ;QACd,YAAO,GAAP,OAAO,CAAQ;QAG/B,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AASD;;;GAGG;AACH,MAAM,aAAa,GAAgB;IACjC,sEAAsE;IACtE,uEAAuE;IACvE,EAAE,OAAO,EAAE,kCAAkC,EAAE,MAAM,EAAE,UAAU,EAAE;IACnE,EAAE,OAAO,EAAE,mCAAmC,EAAE,MAAM,EAAE,aAAa,EAAE;IACvE,EAAE,OAAO,EAAE,oCAAoC,EAAE,MAAM,EAAE,cAAc,EAAE;IACzE,EAAE,OAAO,EAAE,mCAAmC,EAAE,MAAM,EAAE,aAAa,EAAE;IACvE,YAAY;IACZ,EAAE,OAAO,EAAE,kCAAkC,EAAE,MAAM,EAAE,gBAAgB,EAAE;IACzE,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,EAAE,cAAc,EAAE;IAC1D,YAAY;IACZ,EAAE,OAAO,EAAE,yBAAyB,EAAE,MAAM,EAAE,WAAW,EAAE;IAC3D,4CAA4C;IAC5C,EAAE,OAAO,EAAE,0CAA0C,EAAE,MAAM,EAAE,WAAW,EAAE;IAC5E,EAAE,OAAO,EAAE,0CAA0C,EAAE,MAAM,EAAE,WAAW,EAAE;IAC5E,oDAAoD;IACpD,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,+BAA+B,EAAE;IACjE,yBAAyB;IACzB,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,kBAAkB,EAAE;IACtD,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,mBAAmB,EAAE;IACxD,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,kBAAkB,EAAE;CACvD,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAe,EACf,QAAqB,aAAa;IAElC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACrE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC3C,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,IAAI,iBAAiB,CACzB,0BAA0B,OAAO,CAAC,MAAM,EAAE,EAC1C,OAAO,CAAC,MAAM,EACd,OAAO,CAAC,OAAO,CAAC,MAAM,CACvB,CAAC;IACJ,CAAC;AACH,CAAC;AAED,0DAA0D;AAC1D,MAAM,CAAC,MAAM,mBAAmB,GAAG,aAAa,CAAC"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sessionManager — CLI session lifecycle helpers.
|
|
3
|
+
*
|
|
4
|
+
* Wraps the JSONL sidecar writer (`electron/main/core/sessionJsonl.ts`) with
|
|
5
|
+
* filesystem helpers for the CLI:
|
|
6
|
+
*
|
|
7
|
+
* - resolve base directory (`~/.tmp/anathema-coder/sessions/`, overridable
|
|
8
|
+
* via `ANATHEMA_SESSIONS_DIR`)
|
|
9
|
+
* - track the "current" session via a small text file (`current.txt`,
|
|
10
|
+
* overridable via `ANATHEMA_CURRENT_SESSION_FILE`)
|
|
11
|
+
* - list past sessions sorted by mtime desc
|
|
12
|
+
* - load a session's events from JSONL
|
|
13
|
+
*
|
|
14
|
+
* Pure node:fs — no Electron deps, browser-importable for jsdom tests.
|
|
15
|
+
*
|
|
16
|
+
* @see docs/plans/2026-06-28-zelari-code.md (Task 14.10)
|
|
17
|
+
*/
|
|
18
|
+
import { promises as fs, existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync, statSync } from 'node:fs';
|
|
19
|
+
import path from 'node:path';
|
|
20
|
+
import os from 'node:os';
|
|
21
|
+
import { randomUUID } from 'node:crypto';
|
|
22
|
+
import { readSession } from '../main/core/sessionJsonl.js';
|
|
23
|
+
/** Resolve the base directory where session JSONL files live. */
|
|
24
|
+
export function getSessionBaseDir() {
|
|
25
|
+
return process.env.ANATHEMA_SESSIONS_DIR
|
|
26
|
+
?? path.join(os.homedir(), '.tmp', 'zelari-code', 'sessions');
|
|
27
|
+
}
|
|
28
|
+
/** Resolve the file used to track the current session id. */
|
|
29
|
+
export function getCurrentSessionFile() {
|
|
30
|
+
return process.env.ANATHEMA_CURRENT_SESSION_FILE
|
|
31
|
+
?? path.join(os.homedir(), '.tmp', 'zelari-code', 'current.txt');
|
|
32
|
+
}
|
|
33
|
+
/** Ensure the base directory exists. Creates parent dirs as needed. */
|
|
34
|
+
export async function ensureSessionDir() {
|
|
35
|
+
await fs.mkdir(getSessionBaseDir(), { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
/** Read the current session id from disk. Returns null if missing/empty. */
|
|
38
|
+
export function getCurrentSessionId() {
|
|
39
|
+
const file = getCurrentSessionFile();
|
|
40
|
+
if (!existsSync(file))
|
|
41
|
+
return null;
|
|
42
|
+
try {
|
|
43
|
+
const content = readFileSync(file, 'utf-8').trim();
|
|
44
|
+
return content.length > 0 ? content : null;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Write the current session id to disk. Creates parent dirs as needed. */
|
|
51
|
+
export function setCurrentSessionId(id) {
|
|
52
|
+
const file = getCurrentSessionFile();
|
|
53
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
54
|
+
writeFileSync(file, id, 'utf-8');
|
|
55
|
+
}
|
|
56
|
+
/** Remove the current session marker (does not delete the JSONL file). */
|
|
57
|
+
export function clearCurrentSessionId() {
|
|
58
|
+
const file = getCurrentSessionFile();
|
|
59
|
+
try {
|
|
60
|
+
unlinkSync(file);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
if (err.code !== 'ENOENT')
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** File used to track the currently active branch (Task 17.2). */
|
|
68
|
+
export function getCurrentBranchFile() {
|
|
69
|
+
return process.env.ANATHEMA_CURRENT_BRANCH_FILE
|
|
70
|
+
?? path.join(path.dirname(getCurrentSessionFile()), 'currentBranch.txt');
|
|
71
|
+
}
|
|
72
|
+
/** Read the current branch name. Returns null if no branch is active. */
|
|
73
|
+
export function getCurrentBranch() {
|
|
74
|
+
const file = getCurrentBranchFile();
|
|
75
|
+
if (!existsSync(file))
|
|
76
|
+
return null;
|
|
77
|
+
try {
|
|
78
|
+
const content = readFileSync(file, 'utf-8').trim();
|
|
79
|
+
return content.length > 0 ? content : null;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** Set the current branch name (used after `/checkout <name>`). */
|
|
86
|
+
export function setCurrentBranch(name) {
|
|
87
|
+
const file = getCurrentBranchFile();
|
|
88
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
89
|
+
writeFileSync(file, name, 'utf-8');
|
|
90
|
+
}
|
|
91
|
+
/** Clear the current branch marker (used after `/branch <name>` on main). */
|
|
92
|
+
export function clearCurrentBranch() {
|
|
93
|
+
const file = getCurrentBranchFile();
|
|
94
|
+
try {
|
|
95
|
+
unlinkSync(file);
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
if (err.code !== 'ENOENT')
|
|
99
|
+
throw err;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** Generate a new session UUID. */
|
|
103
|
+
export function newSessionId() {
|
|
104
|
+
return randomUUID();
|
|
105
|
+
}
|
|
106
|
+
/** List all sessions in the base directory, sorted by mtime desc. */
|
|
107
|
+
export async function listSessions() {
|
|
108
|
+
const baseDir = getSessionBaseDir();
|
|
109
|
+
let entries;
|
|
110
|
+
try {
|
|
111
|
+
entries = await fs.readdir(baseDir);
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
if (err.code === 'ENOENT')
|
|
115
|
+
return [];
|
|
116
|
+
throw err;
|
|
117
|
+
}
|
|
118
|
+
const results = [];
|
|
119
|
+
for (const entry of entries) {
|
|
120
|
+
if (!entry.endsWith('.jsonl'))
|
|
121
|
+
continue;
|
|
122
|
+
const id = entry.replace(/\.jsonl$/, '');
|
|
123
|
+
const filePath = path.join(baseDir, entry);
|
|
124
|
+
try {
|
|
125
|
+
const events = await readSession(filePath);
|
|
126
|
+
let firstTs = 0;
|
|
127
|
+
let lastTs = 0;
|
|
128
|
+
for (const e of events) {
|
|
129
|
+
if (firstTs === 0 || e.ts < firstTs)
|
|
130
|
+
firstTs = e.ts;
|
|
131
|
+
if (e.ts > lastTs)
|
|
132
|
+
lastTs = e.ts;
|
|
133
|
+
}
|
|
134
|
+
const mtimeMs = statSync(filePath).mtimeMs;
|
|
135
|
+
results.push({ id, eventCount: events.length, firstTs, lastTs, mtimeMs, filePath });
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
// Skip unreadable sessions.
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
results.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
142
|
+
return results;
|
|
143
|
+
}
|
|
144
|
+
/** Load all events from a session's JSONL file by id. */
|
|
145
|
+
export async function loadSessionEvents(id) {
|
|
146
|
+
const filePath = path.join(getSessionBaseDir(), `${id}.jsonl`);
|
|
147
|
+
return readSession(filePath);
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=sessionManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionManager.js","sourceRoot":"","sources":["../../src/cli/sessionManager.ts"],"names":[],"mappings":"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"}
|