agent-composer 0.3.0 → 0.4.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.
Files changed (181) hide show
  1. package/README.md +495 -180
  2. package/composer.config.schema.json +206 -2
  3. package/dist/cli/cleanup.d.ts +24 -0
  4. package/dist/cli/cleanup.js +151 -0
  5. package/dist/cli/cleanup.js.map +1 -0
  6. package/dist/cli/doctor.d.ts +12 -0
  7. package/dist/cli/doctor.js +244 -4
  8. package/dist/cli/doctor.js.map +1 -1
  9. package/dist/cli/goal.d.ts +28 -0
  10. package/dist/cli/goal.js +251 -0
  11. package/dist/cli/goal.js.map +1 -0
  12. package/dist/cli/help.d.ts +3 -0
  13. package/dist/cli/help.js +31 -0
  14. package/dist/cli/help.js.map +1 -0
  15. package/dist/cli/init.d.ts +5 -0
  16. package/dist/cli/init.js +116 -21
  17. package/dist/cli/init.js.map +1 -1
  18. package/dist/cli/initArgs.d.ts +16 -0
  19. package/dist/cli/initArgs.js +19 -0
  20. package/dist/cli/initArgs.js.map +1 -0
  21. package/dist/cli/installGitHook.d.ts +7 -0
  22. package/dist/cli/installGitHook.js +61 -0
  23. package/dist/cli/installGitHook.js.map +1 -0
  24. package/dist/cli/mode.d.ts +6 -0
  25. package/dist/cli/mode.js +25 -0
  26. package/dist/cli/mode.js.map +1 -0
  27. package/dist/cli/status.d.ts +105 -0
  28. package/dist/cli/status.js +400 -0
  29. package/dist/cli/status.js.map +1 -0
  30. package/dist/config/env.d.ts +1 -1
  31. package/dist/config/modes.d.ts +10 -0
  32. package/dist/config/modes.js +26 -0
  33. package/dist/config/modes.js.map +1 -0
  34. package/dist/config/oracleRole.d.ts +10 -0
  35. package/dist/config/oracleRole.js +11 -0
  36. package/dist/config/oracleRole.js.map +1 -0
  37. package/dist/config/schema.d.ts +246 -0
  38. package/dist/config/schema.js +127 -2
  39. package/dist/config/schema.js.map +1 -1
  40. package/dist/evolve/reflection.d.ts +9 -0
  41. package/dist/evolve/reflection.js +14 -0
  42. package/dist/evolve/reflection.js.map +1 -1
  43. package/dist/evolve/runner.d.ts +2 -1
  44. package/dist/evolve/runner.js +2 -1
  45. package/dist/evolve/runner.js.map +1 -1
  46. package/dist/index.js +115 -6
  47. package/dist/index.js.map +1 -1
  48. package/dist/providers/AnthropicCompatibleProvider.d.ts +13 -1
  49. package/dist/providers/AnthropicCompatibleProvider.js +115 -9
  50. package/dist/providers/AnthropicCompatibleProvider.js.map +1 -1
  51. package/dist/providers/CLIProvider.d.ts +23 -1
  52. package/dist/providers/CLIProvider.js +283 -65
  53. package/dist/providers/CLIProvider.js.map +1 -1
  54. package/dist/providers/IProvider.d.ts +13 -0
  55. package/dist/providers/SpendGuardProvider.d.ts +32 -0
  56. package/dist/providers/SpendGuardProvider.js +98 -0
  57. package/dist/providers/SpendGuardProvider.js.map +1 -0
  58. package/dist/registry.d.ts +5 -2
  59. package/dist/registry.js +17 -2
  60. package/dist/registry.js.map +1 -1
  61. package/dist/server/activeRuns.d.ts +17 -0
  62. package/dist/server/activeRuns.js +114 -0
  63. package/dist/server/activeRuns.js.map +1 -0
  64. package/dist/server/codexLifecycleRunner.d.ts +29 -0
  65. package/dist/server/codexLifecycleRunner.js +188 -0
  66. package/dist/server/codexLifecycleRunner.js.map +1 -0
  67. package/dist/server/configMutation.d.ts +22 -0
  68. package/dist/server/configMutation.js +121 -0
  69. package/dist/server/configMutation.js.map +1 -0
  70. package/dist/server/handoffContext.d.ts +1 -0
  71. package/dist/server/handoffContext.js +12 -0
  72. package/dist/server/handoffContext.js.map +1 -0
  73. package/dist/server/progress.d.ts +24 -0
  74. package/dist/server/progress.js +109 -0
  75. package/dist/server/progress.js.map +1 -0
  76. package/dist/server/toolDescriptions.d.ts +60 -0
  77. package/dist/server/toolDescriptions.js +134 -0
  78. package/dist/server/toolDescriptions.js.map +1 -0
  79. package/dist/server.d.ts +19 -21
  80. package/dist/server.js +90 -330
  81. package/dist/server.js.map +1 -1
  82. package/dist/tools/audit.d.ts +2 -0
  83. package/dist/tools/audit.js +66 -0
  84. package/dist/tools/audit.js.map +1 -0
  85. package/dist/tools/code.d.ts +2 -0
  86. package/dist/tools/code.js +160 -0
  87. package/dist/tools/code.js.map +1 -0
  88. package/dist/tools/codexLifecycle.d.ts +2 -0
  89. package/dist/tools/codexLifecycle.js +206 -0
  90. package/dist/tools/codexLifecycle.js.map +1 -0
  91. package/dist/tools/config.d.ts +2 -0
  92. package/dist/tools/config.js +183 -0
  93. package/dist/tools/config.js.map +1 -0
  94. package/dist/tools/context.d.ts +31 -0
  95. package/dist/tools/context.js +2 -0
  96. package/dist/tools/context.js.map +1 -0
  97. package/dist/tools/goal.d.ts +2 -0
  98. package/dist/tools/goal.js +159 -0
  99. package/dist/tools/goal.js.map +1 -0
  100. package/dist/tools/handoff.d.ts +2 -0
  101. package/dist/tools/handoff.js +57 -0
  102. package/dist/tools/handoff.js.map +1 -0
  103. package/dist/tools/oracle.d.ts +2 -0
  104. package/dist/tools/oracle.js +248 -0
  105. package/dist/tools/oracle.js.map +1 -0
  106. package/dist/tools/research.d.ts +2 -0
  107. package/dist/tools/research.js +51 -0
  108. package/dist/tools/research.js.map +1 -0
  109. package/dist/tools/review.d.ts +2 -0
  110. package/dist/tools/review.js +233 -0
  111. package/dist/tools/review.js.map +1 -0
  112. package/dist/tools/route.d.ts +2 -0
  113. package/dist/tools/route.js +69 -0
  114. package/dist/tools/route.js.map +1 -0
  115. package/dist/tools/session.d.ts +2 -0
  116. package/dist/tools/session.js +37 -0
  117. package/dist/tools/session.js.map +1 -0
  118. package/dist/tools/status.d.ts +2 -0
  119. package/dist/tools/status.js +34 -0
  120. package/dist/tools/status.js.map +1 -0
  121. package/dist/tools/workflow.d.ts +2 -0
  122. package/dist/tools/workflow.js +27 -0
  123. package/dist/tools/workflow.js.map +1 -0
  124. package/dist/util/applyFileBlocks.d.ts +18 -0
  125. package/dist/util/applyFileBlocks.js +163 -0
  126. package/dist/util/applyFileBlocks.js.map +1 -0
  127. package/dist/util/asyncControl.d.ts +14 -0
  128. package/dist/util/asyncControl.js +106 -0
  129. package/dist/util/asyncControl.js.map +1 -0
  130. package/dist/util/auditLog.d.ts +56 -0
  131. package/dist/util/auditLog.js +232 -0
  132. package/dist/util/auditLog.js.map +1 -0
  133. package/dist/util/codexLifecycle.d.ts +55 -0
  134. package/dist/util/codexLifecycle.js +102 -0
  135. package/dist/util/codexLifecycle.js.map +1 -0
  136. package/dist/util/codexLifecycleJob.d.ts +209 -0
  137. package/dist/util/codexLifecycleJob.js +360 -0
  138. package/dist/util/codexLifecycleJob.js.map +1 -0
  139. package/dist/util/composerDisabled.d.ts +6 -0
  140. package/dist/util/composerDisabled.js +27 -0
  141. package/dist/util/composerDisabled.js.map +1 -0
  142. package/dist/util/dispatchHint.d.ts +5 -3
  143. package/dist/util/dispatchHint.js +62 -2
  144. package/dist/util/dispatchHint.js.map +1 -1
  145. package/dist/util/goal.d.ts +132 -0
  146. package/dist/util/goal.js +616 -0
  147. package/dist/util/goal.js.map +1 -0
  148. package/dist/util/goalReport.d.ts +51 -0
  149. package/dist/util/goalReport.js +164 -0
  150. package/dist/util/goalReport.js.map +1 -0
  151. package/dist/util/jobPolling.d.ts +9 -0
  152. package/dist/util/jobPolling.js +17 -0
  153. package/dist/util/jobPolling.js.map +1 -0
  154. package/dist/util/oracleJob.d.ts +66 -0
  155. package/dist/util/oracleJob.js +295 -0
  156. package/dist/util/oracleJob.js.map +1 -0
  157. package/dist/util/oracleLock.d.ts +38 -0
  158. package/dist/util/oracleLock.js +182 -0
  159. package/dist/util/oracleLock.js.map +1 -0
  160. package/dist/util/reviewDiff.d.ts +8 -0
  161. package/dist/util/reviewDiff.js +29 -0
  162. package/dist/util/reviewDiff.js.map +1 -0
  163. package/dist/util/reviewJob.d.ts +57 -0
  164. package/dist/util/reviewJob.js +207 -0
  165. package/dist/util/reviewJob.js.map +1 -0
  166. package/dist/util/workflowPlan.d.ts +24 -0
  167. package/dist/util/workflowPlan.js +49 -0
  168. package/dist/util/workflowPlan.js.map +1 -0
  169. package/package.json +8 -1
  170. package/plugin/composer-mastermind/commands/evolve.md +4 -0
  171. package/plugin/composer-mastermind/hooks/boundary_guard.sh +43 -2
  172. package/plugin/composer-mastermind/hooks/codex_warm_review.sh +161 -9
  173. package/plugin/composer-mastermind/hooks/learn.sh +172 -32
  174. package/plugin/composer-mastermind/hooks/precommit_codex_review.sh +430 -62
  175. package/plugin/composer-mastermind/plugin.json +1 -1
  176. package/plugin/composer-mastermind/skills/composer-mastermind/SKILL.md +190 -4
  177. package/scripts/composer-oracle-router-safe.sh +47 -0
  178. package/scripts/composer-statusline-segment.mjs +40 -0
  179. package/scripts/oracle-codex-handoff-safe.sh +49 -0
  180. package/scripts/oracle-plan-mcp.sh +66 -0
  181. package/scripts/oracle-pro-safe.sh +471 -0
@@ -0,0 +1,98 @@
1
+ /** Thrown when a priced call is blocked by spendAuthorization (deny mode or a cap). */
2
+ export class SpendLimitError extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = "SpendLimitError";
6
+ }
7
+ }
8
+ /** Mutable, registry-scoped accumulator of estimated USD spend for the session. */
9
+ export class SpendLedger {
10
+ #spentUsd = 0;
11
+ get spentUsd() {
12
+ return this.#spentUsd;
13
+ }
14
+ add(usd) {
15
+ if (Number.isFinite(usd) && usd > 0)
16
+ this.#spentUsd += usd;
17
+ }
18
+ }
19
+ // Rough public list prices (USD per 1M tokens). Estimates only — the guard is a
20
+ // conservative ceiling, not an accountant. Unknown models fall back to a
21
+ // deliberately high default so an unrecognized model is more likely to trip a
22
+ // cap than to silently overspend.
23
+ const PRICE_TABLE = [
24
+ { match: /glm/i, price: { inPerMTok: 0.6, outPerMTok: 2.2 } },
25
+ { match: /haiku/i, price: { inPerMTok: 1, outPerMTok: 5 } },
26
+ { match: /sonnet/i, price: { inPerMTok: 3, outPerMTok: 15 } },
27
+ { match: /opus/i, price: { inPerMTok: 15, outPerMTok: 75 } },
28
+ ];
29
+ const DEFAULT_PRICE = { inPerMTok: 3, outPerMTok: 15 };
30
+ const CHARS_PER_TOKEN = 4;
31
+ const DEFAULT_MAX_OUTPUT_TOKENS = 4096;
32
+ function priceFor(model) {
33
+ for (const entry of PRICE_TABLE) {
34
+ if (entry.match.test(model))
35
+ return entry.price;
36
+ }
37
+ return DEFAULT_PRICE;
38
+ }
39
+ function estimateUsd(model, tokensIn, tokensOut) {
40
+ const price = priceFor(model);
41
+ return (tokensIn / 1_000_000) * price.inPerMTok + (tokensOut / 1_000_000) * price.outPerMTok;
42
+ }
43
+ /**
44
+ * Decorator that enforces spendAuthorization on a priced inner provider.
45
+ * - mode "deny": blocks every call.
46
+ * - maxUsdPerCall: blocks if the worst-case (maxTokens) estimate exceeds the cap.
47
+ * - maxUsdPerSession: blocks if the running ledger + this call's estimate exceeds the cap.
48
+ * After a successful call, the ledger is incremented by the ACTUAL token cost
49
+ * (from the provider's reported usage) when available, else the estimate.
50
+ */
51
+ export class SpendGuardProvider {
52
+ inner;
53
+ auth;
54
+ ledger;
55
+ defaultMaxTokens;
56
+ id;
57
+ modelLabel;
58
+ constructor(inner, auth, ledger, defaultMaxTokens) {
59
+ this.inner = inner;
60
+ this.auth = auth;
61
+ this.ledger = ledger;
62
+ this.defaultMaxTokens = defaultMaxTokens;
63
+ this.id = inner.id;
64
+ this.modelLabel = inner.modelLabel;
65
+ }
66
+ healthCheck() {
67
+ return this.inner.healthCheck();
68
+ }
69
+ async execute(input) {
70
+ if (this.auth.mode === "deny") {
71
+ throw new SpendLimitError(`Priced provider '${this.modelLabel}' blocked: spendAuthorization.mode="deny".`);
72
+ }
73
+ const inputChars = (input.prompt?.length ?? 0) + (input.context?.length ?? 0);
74
+ const estTokensIn = Math.ceil(inputChars / CHARS_PER_TOKEN);
75
+ const estTokensOut = typeof input.maxTokens === "number" && input.maxTokens > 0
76
+ ? input.maxTokens
77
+ : typeof this.defaultMaxTokens === "number" && this.defaultMaxTokens > 0
78
+ ? this.defaultMaxTokens
79
+ : DEFAULT_MAX_OUTPUT_TOKENS;
80
+ const estCallUsd = estimateUsd(this.modelLabel, estTokensIn, estTokensOut);
81
+ if (this.auth.maxUsdPerCall !== undefined && estCallUsd > this.auth.maxUsdPerCall) {
82
+ throw new SpendLimitError(`Estimated $${estCallUsd.toFixed(4)} for this '${this.modelLabel}' call exceeds maxUsdPerCall $${this.auth.maxUsdPerCall}.`);
83
+ }
84
+ if (this.auth.maxUsdPerSession !== undefined &&
85
+ this.ledger.spentUsd + estCallUsd > this.auth.maxUsdPerSession) {
86
+ throw new SpendLimitError(`Estimated session spend $${(this.ledger.spentUsd + estCallUsd).toFixed(4)} would exceed maxUsdPerSession $${this.auth.maxUsdPerSession} (already $${this.ledger.spentUsd.toFixed(4)}).`);
87
+ }
88
+ const output = await this.inner.execute(input);
89
+ const actualTokensIn = output.tokensIn ?? estTokensIn;
90
+ const actualTokensOut = output.tokensOut ?? estTokensOut;
91
+ this.ledger.add(estimateUsd(this.modelLabel, actualTokensIn, actualTokensOut));
92
+ return output;
93
+ }
94
+ }
95
+ export function isPricedProvider(id) {
96
+ return id === "anthropic" || id === "openai_compatible";
97
+ }
98
+ //# sourceMappingURL=SpendGuardProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpendGuardProvider.js","sourceRoot":"","sources":["../../src/providers/SpendGuardProvider.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@ import type { ComposerConfig, RoleName } from "./config/schema.js";
5
5
  * nor composer.config.json role.model are provided. Tracks the current
6
6
  * GLM family release (z.ai Anthropic-compat endpoint).
7
7
  */
8
- export declare const DEFAULT_ANTHROPIC_MODEL = "glm-5.1";
8
+ export declare const DEFAULT_ANTHROPIC_MODEL = "glm-5.2";
9
9
  export declare class ProviderNotImplementedError extends Error {
10
10
  constructor(providerId: string);
11
11
  }
@@ -13,9 +13,12 @@ export declare class ProviderConfigError extends Error {
13
13
  constructor(providerId: string, field: string);
14
14
  }
15
15
  export declare class ProviderRegistry {
16
- private readonly config;
16
+ private config;
17
17
  private readonly cache;
18
+ private readonly spendLedger;
18
19
  constructor(config: ComposerConfig);
20
+ setConfig(config: ComposerConfig): void;
19
21
  getProviderForRole(role: RoleName): IProvider;
22
+ private maybeGuard;
20
23
  private buildProvider;
21
24
  }
package/dist/registry.js CHANGED
@@ -6,12 +6,13 @@
6
6
  import { MockProvider } from "./providers/MockProvider.js";
7
7
  import { AnthropicCompatibleProvider } from "./providers/AnthropicCompatibleProvider.js";
8
8
  import { CLIProvider } from "./providers/CLIProvider.js";
9
+ import { SpendGuardProvider, SpendLedger, isPricedProvider } from "./providers/SpendGuardProvider.js";
9
10
  /**
10
11
  * Wave 3 Step 4 — fallback when neither process.env.ANTHROPIC_MODEL
11
12
  * nor composer.config.json role.model are provided. Tracks the current
12
13
  * GLM family release (z.ai Anthropic-compat endpoint).
13
14
  */
14
- export const DEFAULT_ANTHROPIC_MODEL = "glm-5.1";
15
+ export const DEFAULT_ANTHROPIC_MODEL = "glm-5.2";
15
16
  export class ProviderNotImplementedError extends Error {
16
17
  constructor(providerId) {
17
18
  super(`Provider '${providerId}' is not wired. Composer ships 'mock', 'anthropic', and 'cli' adapters; 'openai_compatible' is YAGNI until needed.`);
@@ -27,9 +28,16 @@ export class ProviderConfigError extends Error {
27
28
  export class ProviderRegistry {
28
29
  config;
29
30
  cache = new Map();
31
+ spendLedger = new SpendLedger();
30
32
  constructor(config) {
31
33
  this.config = config;
32
34
  }
35
+ setConfig(config) {
36
+ if (config === this.config)
37
+ return;
38
+ this.config = config;
39
+ this.cache.clear();
40
+ }
33
41
  getProviderForRole(role) {
34
42
  const cached = this.cache.get(role);
35
43
  if (cached)
@@ -38,10 +46,16 @@ export class ProviderRegistry {
38
46
  if (!rc) {
39
47
  throw new ProviderConfigError(role, "role not configured in composer.config.json roles");
40
48
  }
41
- const created = this.buildProvider(rc);
49
+ const created = this.maybeGuard(this.buildProvider(rc), rc.maxTokens);
42
50
  this.cache.set(role, created);
43
51
  return created;
44
52
  }
53
+ maybeGuard(provider, defaultMaxTokens) {
54
+ const auth = this.config.spendAuthorization;
55
+ if (!auth || !isPricedProvider(provider.id))
56
+ return provider;
57
+ return new SpendGuardProvider(provider, auth, this.spendLedger, defaultMaxTokens);
58
+ }
45
59
  buildProvider(roleConfig) {
46
60
  switch (roleConfig.provider) {
47
61
  case "mock":
@@ -76,6 +90,7 @@ export class ProviderRegistry {
76
90
  cli: roleConfig.cli,
77
91
  model: roleConfig.model,
78
92
  timeoutMs: roleConfig.timeoutMs,
93
+ totalWallClockMs: roleConfig.totalWallClockMs,
79
94
  maxBuffer: roleConfig.maxBuffer,
80
95
  retries: roleConfig.retries,
81
96
  maxResultChars: roleConfig.maxResultChars,
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export interface ActiveRun {
2
+ id: number;
3
+ tool: string;
4
+ providerLabel?: string;
5
+ providerRole?: string;
6
+ startedAt: string;
7
+ }
8
+ export interface ActiveRunTracker {
9
+ start(input: {
10
+ tool: string;
11
+ providerRole?: string;
12
+ providerLabel?: string;
13
+ }): number;
14
+ finish(id: number): void;
15
+ list(): ActiveRun[];
16
+ }
17
+ export declare function createActiveRunTracker(): ActiveRunTracker;
@@ -0,0 +1,114 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { COMPOSER_STATE_DIR_ENV } from "../util/codexLifecycleJob.js";
5
+ const ACTIVE_RUN_TTL_MS_ENV = "COMPOSER_ACTIVE_RUN_TTL_MS";
6
+ const DEFAULT_STALE_RUN_TTL_MS = 2 * 60 * 60_000;
7
+ const STALE_RUN_TTL_MS = resolvePositiveEnvMs(ACTIVE_RUN_TTL_MS_ENV, DEFAULT_STALE_RUN_TTL_MS);
8
+ let persistQueue = Promise.resolve();
9
+ export function createActiveRunTracker() {
10
+ let nextId = 1;
11
+ const runs = new Map();
12
+ prunePersistedActiveRuns(STALE_RUN_TTL_MS);
13
+ return {
14
+ start({ tool, providerRole, providerLabel }) {
15
+ const id = nextId++;
16
+ runs.set(id, {
17
+ id,
18
+ tool,
19
+ providerRole,
20
+ providerLabel,
21
+ startedAt: new Date().toISOString(),
22
+ });
23
+ persistActiveRuns([...runs.values()]);
24
+ return id;
25
+ },
26
+ finish(id) {
27
+ runs.delete(id);
28
+ persistActiveRuns([...runs.values()]);
29
+ },
30
+ list() {
31
+ return [...runs.values()];
32
+ },
33
+ };
34
+ }
35
+ function persistActiveRuns(runs) {
36
+ persistQueue = persistQueue
37
+ .catch(() => { })
38
+ .then(() => persistActiveRunsAsync(runs))
39
+ .catch(() => {
40
+ // Statusline persistence is advisory only.
41
+ });
42
+ }
43
+ async function persistActiveRunsAsync(runs) {
44
+ const stateDir = composerStateDir();
45
+ await fs.promises.mkdir(stateDir, { recursive: true, mode: 0o700 });
46
+ const filePath = path.join(stateDir, "active-runs.json");
47
+ const tmpPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
48
+ const payload = activeRunPayload(runs);
49
+ try {
50
+ await fs.promises.writeFile(tmpPath, `${JSON.stringify(payload, null, 2)}\n`, {
51
+ encoding: "utf8",
52
+ mode: 0o600,
53
+ flag: "wx",
54
+ });
55
+ await fs.promises.rename(tmpPath, filePath);
56
+ }
57
+ catch (error) {
58
+ await fs.promises.rm(tmpPath, { force: true }).catch(() => { });
59
+ throw error;
60
+ }
61
+ }
62
+ function prunePersistedActiveRuns(ttlMs) {
63
+ persistQueue = persistQueue
64
+ .catch(() => { })
65
+ .then(() => prunePersistedActiveRunsAsync(ttlMs))
66
+ .catch(() => {
67
+ // Statusline persistence is advisory only.
68
+ });
69
+ }
70
+ async function prunePersistedActiveRunsAsync(ttlMs) {
71
+ const filePath = path.join(composerStateDir(), "active-runs.json");
72
+ const raw = await fs.promises.readFile(filePath, "utf8").catch(() => undefined);
73
+ if (raw === undefined)
74
+ return;
75
+ const parsed = JSON.parse(raw);
76
+ if (!Array.isArray(parsed))
77
+ return;
78
+ const cutoff = Date.now() - ttlMs;
79
+ const fresh = parsed.filter((entry) => {
80
+ if (!entry || typeof entry !== "object")
81
+ return false;
82
+ const candidate = entry;
83
+ if (typeof candidate.tool !== "string" || typeof candidate.startedAt !== "string") {
84
+ return false;
85
+ }
86
+ const startedAtMs = Date.parse(candidate.startedAt);
87
+ return Number.isFinite(startedAtMs) && startedAtMs >= cutoff;
88
+ });
89
+ if (fresh.length === parsed.length)
90
+ return;
91
+ await persistActiveRunsAsync(fresh);
92
+ }
93
+ function activeRunPayload(runs) {
94
+ return runs.map(({ tool, providerLabel, providerRole, startedAt }) => ({
95
+ tool,
96
+ ...(providerLabel ? { providerLabel } : {}),
97
+ ...(providerRole ? { providerRole } : {}),
98
+ startedAt,
99
+ }));
100
+ }
101
+ function composerStateDir() {
102
+ const override = process.env[COMPOSER_STATE_DIR_ENV]?.trim();
103
+ if (override)
104
+ return path.resolve(override);
105
+ return path.join(os.homedir(), ".composer", "state");
106
+ }
107
+ function resolvePositiveEnvMs(envName, fallbackMs) {
108
+ const raw = process.env[envName]?.trim();
109
+ if (!raw)
110
+ return fallbackMs;
111
+ const parsed = Number(raw);
112
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallbackMs;
113
+ }
114
+ //# sourceMappingURL=activeRuns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activeRuns.js","sourceRoot":"","sources":["../../src/server/activeRuns.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { type CodexLifecycleJob } from "../util/codexLifecycleJob.js";
2
+ import { type CodexLifecycleFallback, type RoleName } from "../config/schema.js";
3
+ import type { ProviderRegistry } from "../registry.js";
4
+ export interface RunCodexLifecycleJobInput {
5
+ root: string;
6
+ registry: ProviderRegistry;
7
+ job: CodexLifecycleJob;
8
+ prompt: string;
9
+ context?: string;
10
+ handoffPath?: string;
11
+ projectDir?: string;
12
+ signal?: AbortSignal;
13
+ fallback?: CodexLifecycleFallback;
14
+ maxTotalMs?: number;
15
+ roleTimeoutMs?: Partial<Record<RoleName, number>>;
16
+ onProgress?: (update: {
17
+ phase?: string;
18
+ detail?: string;
19
+ }) => void;
20
+ }
21
+ export declare function runCodexLifecycleJob(input: RunCodexLifecycleJobInput): Promise<CodexLifecycleJob>;
22
+ export declare function lifecycleProviderRoles(fallback: CodexLifecycleFallback | undefined): RoleName[];
23
+ export declare function lifecycleExecutionTarget(role: RoleName, targetRoot: string): {
24
+ cwd: string;
25
+ projectDir?: string;
26
+ readOnly?: boolean;
27
+ cleanup: () => void;
28
+ };
29
+ export declare function codexLifecyclePrompt(job: CodexLifecycleJob, prompt: string, role: RoleName): string;
@@ -0,0 +1,188 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { resolveProjectDir } from "../util/applyFileBlocks.js";
5
+ import { contextWithHandoff } from "./handoffContext.js";
6
+ import { classifyCodexLifecycleUnavailable, updateCodexLifecycleJob, } from "../util/codexLifecycleJob.js";
7
+ import { DEFAULT_CODEX_LIFECYCLE_TOTAL_WALL_CLOCK_MS, } from "../config/schema.js";
8
+ import { createDeadlineSignal, isAbortError, } from "../util/asyncControl.js";
9
+ const DEFAULT_RESEARCHER_TIMEOUT_MS = 180_000;
10
+ const DEFAULT_CODER_TIMEOUT_MS = 300_000;
11
+ const DEFAULT_REVIEWER_TIMEOUT_MS = 300_000;
12
+ const DEFAULT_CODER_CLI_TIMEOUT_MS = 240_000;
13
+ export async function runCodexLifecycleJob(input) {
14
+ const targetRoot = resolveProjectDir(input.projectDir, input.root);
15
+ let job = updateCodexLifecycleJob(input.root, input.job, {
16
+ status: "running",
17
+ startedAt: new Date().toISOString(),
18
+ });
19
+ const roles = lifecycleProviderRoles(input.fallback);
20
+ let lastError;
21
+ let lastReason = "unknown";
22
+ const maxTotalMs = resolvePositiveMs(input.maxTotalMs, DEFAULT_CODEX_LIFECYCLE_TOTAL_WALL_CLOCK_MS);
23
+ const deadline = createDeadlineSignal("composer_codex_lifecycle_run total_wall_clock_ms", maxTotalMs, input.signal);
24
+ try {
25
+ for (const role of roles) {
26
+ try {
27
+ deadline.throwIfAborted();
28
+ }
29
+ catch (error) {
30
+ return finishStoppedLifecycleJob(input.root, job, error);
31
+ }
32
+ const attemptStartedAt = new Date().toISOString();
33
+ const executionTarget = lifecycleExecutionTarget(role, targetRoot);
34
+ const attemptTimeoutMs = Math.max(1, Math.min(resolveRoleTimeoutMs(input.roleTimeoutMs?.[role], defaultRoleTimeoutMs(role)), deadline.remainingMs()));
35
+ const attemptSignal = createDeadlineSignal(`composer_codex_lifecycle_run ${role}`, attemptTimeoutMs, deadline.signal);
36
+ try {
37
+ const provider = input.registry.getProviderForRole(role);
38
+ const result = await provider.execute({
39
+ prompt: codexLifecyclePrompt(job, input.prompt, role),
40
+ context: contextWithHandoff(input.root, input.context, input.handoffPath),
41
+ cwd: executionTarget.cwd,
42
+ projectDir: executionTarget.projectDir,
43
+ readOnly: executionTarget.readOnly,
44
+ model: input.job.model,
45
+ onProgress: input.onProgress,
46
+ signal: attemptSignal.signal,
47
+ });
48
+ attemptSignal.throwIfAborted();
49
+ deadline.throwIfAborted();
50
+ job = updateCodexLifecycleJob(input.root, job, {
51
+ status: "succeeded",
52
+ completedAt: new Date().toISOString(),
53
+ resultText: result.text,
54
+ providerRole: role,
55
+ fallbackUsed: role === "coderCli" ? undefined : role,
56
+ attempts: [
57
+ ...job.attempts,
58
+ {
59
+ role,
60
+ status: "succeeded",
61
+ startedAt: attemptStartedAt,
62
+ completedAt: new Date().toISOString(),
63
+ },
64
+ ],
65
+ });
66
+ return job;
67
+ }
68
+ catch (error) {
69
+ lastError = error;
70
+ lastReason = classifyCodexLifecycleUnavailable(error);
71
+ job = updateCodexLifecycleJob(input.root, job, {
72
+ attempts: [
73
+ ...job.attempts,
74
+ {
75
+ role,
76
+ status: "unavailable",
77
+ startedAt: attemptStartedAt,
78
+ completedAt: new Date().toISOString(),
79
+ unavailableReason: lastReason,
80
+ error: error instanceof Error ? error.message : String(error),
81
+ },
82
+ ],
83
+ });
84
+ if (deadline.signal.aborted || input.signal?.aborted || isAbortError(error)) {
85
+ return finishStoppedLifecycleJob(input.root, job, error);
86
+ }
87
+ try {
88
+ deadline.throwIfAborted();
89
+ }
90
+ catch (deadlineError) {
91
+ return finishStoppedLifecycleJob(input.root, job, deadlineError);
92
+ }
93
+ }
94
+ finally {
95
+ attemptSignal.cleanup();
96
+ executionTarget.cleanup();
97
+ }
98
+ }
99
+ job = updateCodexLifecycleJob(input.root, job, {
100
+ status: "unavailable",
101
+ completedAt: new Date().toISOString(),
102
+ error: lastError instanceof Error ? lastError.message : String(lastError),
103
+ unavailableReason: lastReason,
104
+ resultText: `Lifecycle providers unavailable (${lastReason}) and no fallback provider succeeded. ` +
105
+ "Coco should continue optional lifecycle work without treating this as a policy skip; " +
106
+ "forced gates must fail closed in their own hook.",
107
+ });
108
+ return job;
109
+ }
110
+ finally {
111
+ deadline.cleanup();
112
+ }
113
+ }
114
+ function resolvePositiveMs(value, fallbackMs) {
115
+ return typeof value === "number" && Number.isFinite(value) && value > 0
116
+ ? value
117
+ : fallbackMs;
118
+ }
119
+ function resolveRoleTimeoutMs(configuredTimeoutMs, fallbackMs) {
120
+ return resolvePositiveMs(configuredTimeoutMs, fallbackMs);
121
+ }
122
+ function defaultRoleTimeoutMs(role) {
123
+ switch (role) {
124
+ case "researcher":
125
+ return DEFAULT_RESEARCHER_TIMEOUT_MS;
126
+ case "coderCli":
127
+ return DEFAULT_CODER_CLI_TIMEOUT_MS;
128
+ case "coder":
129
+ return DEFAULT_CODER_TIMEOUT_MS;
130
+ case "reviewer":
131
+ case "reviewerClaude":
132
+ case "oraclePlanner":
133
+ return DEFAULT_REVIEWER_TIMEOUT_MS;
134
+ }
135
+ }
136
+ function finishStoppedLifecycleJob(root, job, error) {
137
+ const unavailableReason = classifyCodexLifecycleUnavailable(error);
138
+ return updateCodexLifecycleJob(root, job, {
139
+ status: "failed",
140
+ completedAt: new Date().toISOString(),
141
+ error: error instanceof Error ? error.message : String(error),
142
+ unavailableReason,
143
+ resultText: `Lifecycle run stopped (${unavailableReason}).`,
144
+ });
145
+ }
146
+ export function lifecycleProviderRoles(fallback) {
147
+ const roles = ["coderCli"];
148
+ if (fallback?.enabled) {
149
+ for (const role of fallback.order) {
150
+ if (!roles.includes(role))
151
+ roles.push(role);
152
+ }
153
+ }
154
+ return roles;
155
+ }
156
+ export function lifecycleExecutionTarget(role, targetRoot) {
157
+ if (role === "coderCli") {
158
+ return {
159
+ cwd: targetRoot,
160
+ projectDir: targetRoot,
161
+ readOnly: true,
162
+ cleanup: () => { },
163
+ };
164
+ }
165
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "composer-lifecycle-readonly-"));
166
+ return {
167
+ cwd: tempDir,
168
+ cleanup: () => fs.rmSync(tempDir, { recursive: true, force: true }),
169
+ };
170
+ }
171
+ export function codexLifecyclePrompt(job, prompt, role) {
172
+ return [
173
+ "You are a Composer lifecycle companion participating in a checkpoint.",
174
+ `Event: ${job.event}`,
175
+ `Job ID: ${job.jobId}`,
176
+ `Execution: ${job.execution}`,
177
+ `Provider role: ${role}`,
178
+ "",
179
+ "Return a concise result for Coco to merge back into the main development loop.",
180
+ "Do not silently mutate files in this lifecycle companion pass.",
181
+ "If code changes are needed, provide findings, file references, and patch guidance instead.",
182
+ "Use this structure: Verdict, Findings, Suggested next actions, Checks.",
183
+ "",
184
+ "Lifecycle task:",
185
+ prompt,
186
+ ].join("\n");
187
+ }
188
+ //# sourceMappingURL=codexLifecycleRunner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codexLifecycleRunner.js","sourceRoot":"","sources":["../../src/server/codexLifecycleRunner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export type ConfigScope = "active" | "project" | "global";
2
+ export interface ComposerConfigTarget {
3
+ scope: ConfigScope;
4
+ path: string;
5
+ }
6
+ export declare function resolveComposerConfigTarget(root: string, configuredPath: string | undefined, scope: ConfigScope): ComposerConfigTarget;
7
+ export declare function applyComposerConfigPatch(before: Record<string, unknown>, patch: {
8
+ codexLifecycle?: unknown;
9
+ codexReview?: unknown;
10
+ oracle?: {
11
+ enabled?: boolean;
12
+ defaultMode?: string;
13
+ requireExplicitTag?: boolean;
14
+ };
15
+ }): Record<string, unknown>;
16
+ export declare function assertSafeConfigWriteTarget(root: string, target: ComposerConfigTarget): void;
17
+ export declare function writeConfigFileAtomically(filePath: string, content: string): void;
18
+ export declare function isGlobalComposerConfigPath(filePath: string): boolean;
19
+ export declare function cloneJsonObject(value: Record<string, unknown>): Record<string, unknown>;
20
+ export declare function readRecord(value: unknown): Record<string, unknown>;
21
+ export declare function deepMergeRecords(target: Record<string, unknown>, patch: Record<string, unknown>): Record<string, unknown>;
22
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;