aiwcli 0.15.7 → 0.17.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/README.md +106 -1125
- package/bin/run.js +0 -4
- package/dist/capabilities/installation/control-plane/clear-command.d.ts +2 -0
- package/dist/capabilities/installation/control-plane/clear-command.js +32 -3
- package/dist/capabilities/installation/control-plane/init-command.js +2 -2
- package/dist/capabilities/launch/contracts.d.ts +39 -4
- package/dist/capabilities/launch/control-plane/execute-launch.js +158 -119
- package/dist/capabilities/launch/runtime-core/launch-decisions.d.ts +82 -0
- package/dist/capabilities/launch/runtime-core/launch-decisions.js +202 -0
- package/dist/commands/branch.d.ts +1 -1
- package/dist/commands/branch.js +1 -1
- package/dist/commands/launch.d.ts +0 -5
- package/dist/commands/launch.js +2 -37
- package/dist/lib/config.js +1 -2
- package/dist/lib/context/context-store.js +28 -2
- package/dist/lib/core-installer.d.ts +1 -1
- package/dist/lib/core-installer.js +6 -27
- package/dist/lib/debug.d.ts +0 -10
- package/dist/lib/debug.js +0 -10
- package/dist/lib/env-sanitizer.d.ts +25 -0
- package/dist/lib/env-sanitizer.js +46 -0
- package/dist/lib/errors.d.ts +0 -13
- package/dist/lib/errors.js +0 -15
- package/dist/lib/git-exclude-manager.js +1 -1
- package/dist/lib/hooks/context-monitor-logic.d.ts +6 -0
- package/dist/lib/hooks/context-monitor-logic.js +25 -0
- package/dist/lib/hooks/hook-utils.js +11 -0
- package/dist/lib/hooks/prompt-binding-logic.d.ts +7 -0
- package/dist/lib/hooks/prompt-binding-logic.js +50 -0
- package/dist/lib/hooks/session-end-logic.js +2 -14
- package/dist/lib/install-state.js +6 -13
- package/dist/lib/json-io.d.ts +12 -0
- package/dist/lib/json-io.js +30 -0
- package/dist/lib/multiplexer.d.ts +43 -35
- package/dist/lib/multiplexer.js +21 -2
- package/dist/lib/multiplexers/psmux.d.ts +14 -34
- package/dist/lib/multiplexers/psmux.js +70 -130
- package/dist/lib/multiplexers/tmux.d.ts +11 -19
- package/dist/lib/multiplexers/tmux.js +79 -120
- package/dist/lib/multiplexers/wezterm.d.ts +38 -0
- package/dist/lib/multiplexers/wezterm.js +225 -0
- package/dist/lib/mux-utils.d.ts +4 -3
- package/dist/lib/mux-utils.js +7 -13
- package/dist/lib/prompt-file-manager.d.ts +23 -0
- package/dist/lib/prompt-file-manager.js +41 -0
- package/dist/lib/runtime/agent-launcher.d.ts +67 -0
- package/dist/lib/runtime/agent-launcher.js +262 -0
- package/dist/lib/runtime/aiw-cli.d.ts +2 -0
- package/dist/lib/runtime/aiw-cli.js +3 -1
- package/dist/lib/runtime/cli-args.d.ts +5 -2
- package/dist/lib/runtime/cli-args.js +18 -3
- package/dist/lib/runtime/inference.js +3 -14
- package/dist/lib/runtime/models.d.ts +6 -0
- package/dist/lib/runtime/models.js +6 -0
- package/dist/lib/runtime/state-io.d.ts +2 -1
- package/dist/lib/runtime/state-io.js +9 -4
- package/dist/lib/runtime/utils.d.ts +8 -0
- package/dist/lib/runtime/utils.js +31 -1
- package/dist/lib/schemas.d.ts +250 -0
- package/dist/lib/schemas.js +216 -0
- package/dist/lib/sentinel-manager.d.ts +32 -0
- package/dist/lib/sentinel-manager.js +62 -0
- package/dist/lib/sentinel-wrapper.d.ts +1 -0
- package/dist/lib/sentinel-wrapper.js +12 -3
- package/dist/lib/settings-hierarchy.js +3 -20
- package/dist/lib/shell-adapters/bash-adapter.d.ts +18 -0
- package/dist/lib/shell-adapters/bash-adapter.js +69 -0
- package/dist/lib/shell-adapters/index.d.ts +5 -0
- package/dist/lib/shell-adapters/index.js +7 -0
- package/dist/lib/shell-adapters/powershell-adapter.d.ts +18 -0
- package/dist/lib/shell-adapters/powershell-adapter.js +62 -0
- package/dist/lib/shell-adapters/shell-adapter.d.ts +45 -0
- package/dist/lib/shell-adapters/shell-adapter.js +5 -0
- package/dist/lib/spawn-errors.d.ts +3 -0
- package/dist/lib/spawn-errors.js +15 -1
- package/dist/lib/spinner.d.ts +0 -5
- package/dist/lib/spinner.js +0 -16
- package/dist/lib/template-installer.d.ts +10 -0
- package/dist/lib/template-installer.js +4 -4
- package/dist/lib/terminal-strategy.d.ts +1 -0
- package/dist/lib/terminal-strategy.js +12 -6
- package/dist/lib/terminal.d.ts +7 -5
- package/dist/lib/terminal.js +42 -19
- package/dist/lib/tmux-primitives.d.ts +0 -2
- package/dist/lib/tmux-primitives.js +0 -4
- package/dist/lib/tmux-session.js +2 -1
- package/dist/lib/windsurf-hooks-hierarchy.js +6 -23
- package/dist/platform/launch.d.ts +2 -1
- package/dist/platform/launch.js +1 -0
- package/dist/templates/CLAUDE.md +0 -1
- package/dist/templates/cc-native/.claude/settings.json +0 -10
- package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +11 -4
- package/dist/templates/cc-native/_cc-native/cc-native.config.json +3 -7
- package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +26 -47
- package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +7 -9
- package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_write.ts +2 -3
- package/dist/templates/cc-native/_cc-native/hooks/mark_questions_asked.ts +2 -2
- package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +0 -25
- package/dist/templates/cc-native/_cc-native/hooks/validate_task_prompt.ts +4 -4
- package/dist/templates/cc-native/_cc-native/lib-ts/.mocharc.json +9 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/aggregate-agents.test.ts +118 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/artifacts.test.ts +234 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/cc-native-state.test.ts +170 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/cli-output-parser.test.ts +73 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/config.test.ts +64 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/constants.test.ts +40 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/debug.test.ts +42 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/exports.test.ts +58 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/helpers.ts +107 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/hooks/add-plan-context.hook.test.ts +97 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/hooks/plan-questions.hook.test.ts +81 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/hooks/plan-review.hook.test.ts +71 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/json-parser.test.ts +99 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/orchestrator-agent.test.ts +288 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/orchestrator.test.ts +48 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/reviewers.test.ts +32 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/state.test.ts +124 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/verdict.test.ts +93 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/agent-selection.ts +163 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/aggregate-agents.ts +6 -14
- package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/format.ts +597 -599
- package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/index.ts +26 -26
- package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/tracker.ts +106 -107
- package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/write.ts +118 -119
- package/dist/templates/cc-native/_cc-native/lib-ts/artifacts.ts +21 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +16 -15
- package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +132 -10
- package/dist/templates/cc-native/_cc-native/lib-ts/constants.ts +6 -6
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/corroboration.ts +119 -119
- package/dist/templates/cc-native/_cc-native/lib-ts/debug.ts +1 -2
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/graduation.ts +132 -132
- package/dist/templates/cc-native/_cc-native/lib-ts/index.ts +88 -86
- package/dist/templates/cc-native/_cc-native/lib-ts/json-parser.ts +5 -6
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/orchestrator.ts +70 -70
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/output-builder.ts +130 -121
- package/dist/templates/cc-native/_cc-native/lib-ts/package-lock.json +1679 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/package.json +24 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/plan-discovery.ts +4 -4
- package/dist/templates/cc-native/_cc-native/lib-ts/plan-enhancement.ts +1 -6
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/plan-questions.ts +101 -101
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/review-pipeline.ts +511 -543
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/__tests__/agent-providers.test.ts +262 -0
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/agent.ts +71 -85
- package/dist/templates/{core/lib-ts/agent-exec → cc-native/_cc-native/lib-ts/reviewers/base}/base-agent.ts +138 -152
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/index.ts +12 -12
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/claude-agent.ts +66 -57
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/codex-agent.ts +185 -200
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/gemini-agent.ts +39 -40
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/orchestrator-claude-agent.ts +196 -224
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/schemas.ts +201 -201
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/types.ts +21 -23
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/__tests__/hyde.test.ts +365 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/__tests__/ollama-client.test.ts +223 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/embedding-indexer.ts +12 -16
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/hyde.ts +3 -2
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/index.ts +31 -31
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/logger.ts +6 -7
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/ollama-client.ts +7 -9
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/retrieval-pipeline.ts +14 -17
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-indexer.ts +37 -41
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-loader.ts +33 -43
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-searcher.ts +20 -20
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/types.ts +8 -9
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/vector-store.ts +3 -4
- package/dist/templates/cc-native/_cc-native/lib-ts/settings.ts +50 -126
- package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +19 -21
- package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +13 -88
- package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/verdict.ts +72 -72
- package/dist/templates/cc-native/_cc-native/plan-review/CLAUDE.md +35 -0
- package/dist/templates/cc-native/_cc-native/plan-review/lib/agent-selection.ts +1 -1
- package/dist/templates/cc-native/_cc-native/scripts/council_debate.ts +242 -0
- package/dist/templates/cc-native/_cc-native/scripts/council_debate_simple.ts +294 -0
- package/dist/templates/cc-native/_cc-native/{plan-review/workflows → workflows}/specdev.md +9 -9
- package/dist/templates/core/.claude/skills/codex/SKILL.md +25 -0
- package/dist/templates/core/.claude/skills/devin/SKILL.md +25 -0
- package/dist/templates/core/.claude/skills/handoff/SKILL.md +11 -0
- package/dist/templates/core/.claude/skills/handoff-resume/SKILL.md +11 -0
- package/dist/templates/core/.claude/skills/meta-plan/SKILL.md +13 -0
- package/dist/templates/core/.codex/skills/codex/SKILL.md +13 -0
- package/dist/templates/core/.codex/skills/devin/SKILL.md +19 -0
- package/dist/templates/core/.codex/skills/handoff/SKILL.md +11 -0
- package/dist/templates/core/.codex/skills/handoff-resume/SKILL.md +11 -0
- package/dist/templates/core/.codex/{workflows/meta-plan.md → skills/meta-plan/SKILL.md} +6 -0
- package/dist/templates/core/{.cognition → .devin}/AGENTS.md +2 -2
- package/dist/templates/core/.devin/skills/codex/SKILL.md +19 -0
- package/dist/templates/core/.devin/skills/devin/SKILL.md +13 -0
- package/dist/templates/core/.devin/skills/handoff/SKILL.md +11 -0
- package/dist/templates/core/.devin/skills/handoff-resume/SKILL.md +11 -0
- package/dist/templates/core/.devin/skills/meta-plan/SKILL.md +13 -0
- package/dist/templates/core/.windsurf/workflows/handoff-resume.md +9 -0
- package/dist/templates/core/hooks-ts/archive_plan.ts +1 -21
- package/dist/templates/core/hooks-ts/file-suggestion.ts +1 -19
- package/dist/templates/core/hooks-ts/pre_compact.ts +5 -18
- package/dist/templates/core/lib-ts/context/context-store.ts +29 -2
- package/dist/templates/core/lib-ts/hooks/hook-utils.ts +11 -0
- package/dist/templates/core/lib-ts/hooks/session-end-logic.ts +2 -13
- package/dist/templates/core/lib-ts/runtime/agent-launcher.ts +74 -0
- package/dist/templates/core/lib-ts/runtime/aiw-cli.ts +4 -2
- package/dist/templates/core/lib-ts/runtime/cli-args.ts +18 -4
- package/dist/templates/core/lib-ts/runtime/inference.ts +3 -15
- package/dist/templates/core/lib-ts/runtime/models.ts +7 -0
- package/dist/templates/core/lib-ts/runtime/state-io.ts +9 -4
- package/dist/templates/core/lib-ts/runtime/utils.ts +30 -1
- package/dist/templates/core/lib-ts/schemas.ts +233 -0
- package/dist/templates/core/scripts/resolve-run.ts +34 -2
- package/dist/templates/core/scripts/status_line.ts +1 -1
- package/dist/templates/core/skills/codex/CLAUDE.md +9 -4
- package/dist/templates/core/skills/codex/SKILL.md +6 -0
- package/dist/templates/core/skills/codex/lib/codex-watcher.ts +3 -10
- package/dist/templates/core/skills/codex/scripts/launch-codex.ts +26 -26
- package/dist/templates/core/skills/devin/CLAUDE.md +63 -6
- package/dist/templates/core/skills/devin/lib/devin-watcher.ts +116 -96
- package/dist/templates/core/skills/devin/scripts/launch-devin.ts +22 -21
- package/dist/templates/core/skills/handoff-system/CLAUDE.md +1 -1
- package/oclif.manifest.json +4 -4
- package/package.json +4 -4
- package/dist/lib/base-command.d.ts +0 -1
- package/dist/lib/base-command.js +0 -1
- package/dist/lib/env-compat.d.ts +0 -18
- package/dist/lib/env-compat.js +0 -23
- package/dist/lib/launch-options.d.ts +0 -1
- package/dist/lib/launch-options.js +0 -1
- package/dist/lib/stdin.d.ts +0 -48
- package/dist/lib/stdin.js +0 -60
- package/dist/templates/cc-native/_cc-native/CLAUDE.md +0 -73
- package/dist/templates/cc-native/_cc-native/artifacts/CLAUDE.md +0 -64
- package/dist/templates/cc-native/_cc-native/lib-ts/CLAUDE.md +0 -70
- package/dist/templates/cc-native/_cc-native/plan-review/CODING-STANDARDS-CHECKLIST.md +0 -75
- package/dist/templates/cc-native/_cc-native/plan-review/agents/CLAUDE.md +0 -143
- package/dist/templates/cc-native/_cc-native/plan-review/agents/PLAN-ORCHESTRATOR.md +0 -213
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-questions/PLAN-QUESTIONER.md +0 -70
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-EVOLUTION.md +0 -62
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-PATTERNS.md +0 -61
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-STRUCTURE.md +0 -62
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ASSUMPTION-TRACER.md +0 -56
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/CLARITY-AUDITOR.md +0 -53
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-FEASIBILITY.md +0 -66
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-GAPS.md +0 -70
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-ORDERING.md +0 -62
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/CONSTRAINT-VALIDATOR.md +0 -72
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DESIGN-ADR-VALIDATOR.md +0 -61
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DESIGN-SCALE-MATCHER.md +0 -64
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DEVILS-ADVOCATE.md +0 -56
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DOCUMENTATION-PHILOSOPHY.md +0 -86
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/HANDOFF-READINESS.md +0 -59
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/HIDDEN-COMPLEXITY.md +0 -58
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/INCREMENTAL-DELIVERY.md +0 -66
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-DEPENDENCY.md +0 -62
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-FMEA.md +0 -66
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-PREMORTEM.md +0 -71
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-REVERSIBILITY.md +0 -74
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SCOPE-BOUNDARY.md +0 -77
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SIMPLICITY-GUARDIAN.md +0 -62
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SKEPTIC.md +0 -68
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-BEHAVIOR-AUDITOR.md +0 -61
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-CHARACTERIZATION.md +0 -71
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-FIRST-VALIDATOR.md +0 -61
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-PYRAMID-ANALYZER.md +0 -61
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TRADEOFF-COSTS.md +0 -67
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TRADEOFF-STAKEHOLDERS.md +0 -65
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/VERIFY-COVERAGE.md +0 -74
- package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/VERIFY-STRENGTH.md +0 -69
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/base/base-agent.ts +0 -7
- package/dist/templates/core/.codex/workflows/codex.md +0 -17
- package/dist/templates/core/.codex/workflows/handoff.md +0 -5
- package/dist/templates/core/lib-ts/agent-exec/backends/headless.ts +0 -34
- package/dist/templates/core/lib-ts/agent-exec/backends/index.ts +0 -6
- package/dist/templates/core/lib-ts/agent-exec/backends/tmux.ts +0 -148
- package/dist/templates/core/lib-ts/agent-exec/execution-backend.ts +0 -50
- package/dist/templates/core/lib-ts/agent-exec/index.ts +0 -6
- package/dist/templates/core/lib-ts/agent-exec/structured-output.ts +0 -165
- /package/dist/templates/core/{.cognition → .devin}/config.json +0 -0
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
import { logInfo, logWarn, logError, setContextPath } from "../runtime/logger.js";
|
|
24
24
|
import { readStateJson, writeStateJson } from "../runtime/state-io.js";
|
|
25
25
|
import { nowIso, generateContextId } from "../runtime/utils.js";
|
|
26
|
+
import { IndexFileSchema } from "../schemas.js";
|
|
26
27
|
import type { ContextState, IndexFile, IndexEntry, Mode } from "../types.js";
|
|
27
28
|
|
|
28
29
|
const INDEX_VERSION = "3.0";
|
|
@@ -81,8 +82,14 @@ function loadIndex(projectRoot?: string): IndexFile {
|
|
|
81
82
|
if (fs.existsSync(indexPath)) {
|
|
82
83
|
try {
|
|
83
84
|
const raw = fs.readFileSync(indexPath, "utf8");
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
const data = JSON.parse(raw);
|
|
86
|
+
const validated = IndexFileSchema.safeParse(data);
|
|
87
|
+
if (!validated.success) {
|
|
88
|
+
logWarn("context_store", `Index schema validation failed, recreating: ${validated.error.message}`);
|
|
89
|
+
} else {
|
|
90
|
+
_indexCache = data as IndexFile;
|
|
91
|
+
return _indexCache;
|
|
92
|
+
}
|
|
86
93
|
} catch (error: unknown) {
|
|
87
94
|
logWarn("context_store", `Failed to read index, recreating: ${error}`);
|
|
88
95
|
}
|
|
@@ -313,11 +320,31 @@ export function getAllContexts(
|
|
|
313
320
|
const ctxMap = index.contexts;
|
|
314
321
|
|
|
315
322
|
if (ctxMap && typeof ctxMap === "object" && Object.keys(ctxMap).length > 0) {
|
|
323
|
+
const orphanIds: string[] = [];
|
|
316
324
|
for (const cid of Object.keys(ctxMap)) {
|
|
317
325
|
const state = loadState(cid, projectRoot);
|
|
318
326
|
if (state && (!status || state.status === status)) {
|
|
319
327
|
results.push(state);
|
|
328
|
+
} else if (!state) {
|
|
329
|
+
orphanIds.push(cid);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (orphanIds.length > 0) {
|
|
334
|
+
logWarn(
|
|
335
|
+
"context_store",
|
|
336
|
+
`Index references ${orphanIds.length} missing context(s): ${orphanIds.join(", ")}. Auto-repairing index.`
|
|
337
|
+
);
|
|
338
|
+
const idx = loadIndex(projectRoot);
|
|
339
|
+
for (const cid of orphanIds) {
|
|
340
|
+
delete idx.contexts[cid];
|
|
341
|
+
if (idx.sessions) {
|
|
342
|
+
for (const [sid, target] of Object.entries(idx.sessions)) {
|
|
343
|
+
if (target === cid) delete idx.sessions[sid];
|
|
344
|
+
}
|
|
345
|
+
}
|
|
320
346
|
}
|
|
347
|
+
saveIndex(idx, projectRoot);
|
|
321
348
|
}
|
|
322
349
|
} else {
|
|
323
350
|
// Fallback: scan folders
|
|
@@ -9,6 +9,7 @@ import * as fs from "node:fs";
|
|
|
9
9
|
import { getContextBySessionId, maybeActivate } from "../context/context-store.js";
|
|
10
10
|
import { getProjectRoot } from "../runtime/constants.js";
|
|
11
11
|
import { logDebug, logWarn, hookLog, setSessionId, getContextPath as _getContextPath } from "../runtime/logger.js";
|
|
12
|
+
import { HookInputSchema } from "../schemas.js";
|
|
12
13
|
import type { ContextState, HookInput, HookOutput, PermissionRequestOutput } from "../types.js";
|
|
13
14
|
|
|
14
15
|
// Re-export logger functions for convenience (matches Python hook_utils re-exports)
|
|
@@ -161,6 +162,11 @@ export function loadHookInput(): HookInput | null {
|
|
|
161
162
|
if (!inputData) return null;
|
|
162
163
|
|
|
163
164
|
const result = JSON.parse(inputData) as Record<string, unknown>;
|
|
165
|
+
const validated = HookInputSchema.safeParse(result);
|
|
166
|
+
if (!validated.success) {
|
|
167
|
+
logWarn("hook_utils", `Hook input schema validation failed: ${validated.error.message}`);
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
164
170
|
if (result && typeof result === "object") {
|
|
165
171
|
_lastHookEvent = readStringField(result, "hook_event_name");
|
|
166
172
|
_lastToolName = readStringField(result, "tool_name");
|
|
@@ -533,6 +539,11 @@ function _earlyReadInput(prefetchedInput?: Record<string, unknown>): void {
|
|
|
533
539
|
const inputData = fs.readFileSync(0, "utf8").trim();
|
|
534
540
|
if (inputData) {
|
|
535
541
|
const parsed = JSON.parse(inputData) as Record<string, unknown>;
|
|
542
|
+
const validated = HookInputSchema.safeParse(parsed);
|
|
543
|
+
if (!validated.success) {
|
|
544
|
+
logWarn("hook_utils", `Early input schema validation failed: ${validated.error.message}`);
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
536
547
|
if (parsed && typeof parsed === "object") {
|
|
537
548
|
_prefetchedInput = parsed;
|
|
538
549
|
_lastHookEvent = readStringField(parsed, "hook_event_name");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as crypto from "node:crypto";
|
|
2
2
|
|
|
3
|
+
import { determineArtifactType } from "../context/context-store.js";
|
|
3
4
|
import {
|
|
4
5
|
extractPlanAnchors,
|
|
5
6
|
generatePlanId,
|
|
@@ -18,18 +19,6 @@ function formatArchiveTimestamp(date: Date): string {
|
|
|
18
19
|
);
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
function resolveArtifactType(state: ContextState): "plan" | "handoff" | null {
|
|
22
|
-
if (state.next_artifact_type) return state.next_artifact_type;
|
|
23
|
-
|
|
24
|
-
const hasPlan = Boolean(state.plan_path && state.plan_hash);
|
|
25
|
-
const hasHandoff = Boolean(state.handoff_path);
|
|
26
|
-
|
|
27
|
-
if (hasPlan && hasHandoff) return "plan";
|
|
28
|
-
if (hasPlan) return "plan";
|
|
29
|
-
if (hasHandoff) return "handoff";
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
22
|
export function computePlanFallback(
|
|
34
23
|
state: ContextState,
|
|
35
24
|
planContent: string,
|
|
@@ -54,7 +43,7 @@ export function shouldStage(
|
|
|
54
43
|
state: ContextState,
|
|
55
44
|
permissionMode: string,
|
|
56
45
|
): boolean {
|
|
57
|
-
const artifactType =
|
|
46
|
+
const artifactType = determineArtifactType(state);
|
|
58
47
|
const canStage = state.mode === "active" || permissionMode === "plan";
|
|
59
48
|
return Boolean(artifactType && canStage && !state.work_consumed);
|
|
60
49
|
}
|
|
@@ -43,10 +43,72 @@ export function sleep(ms: number): Promise<void> {
|
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Print to stderr (shared by agent launch scripts).
|
|
48
|
+
*/
|
|
49
|
+
export function eprint(...args: unknown[]): void {
|
|
50
|
+
process.stderr.write(args.map(String).join(" ") + "\n");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Best-effort cleanup of a sentinel directory.
|
|
55
|
+
*/
|
|
56
|
+
export function cleanupSentinel(sentinelPath: string | null | undefined): void {
|
|
57
|
+
if (!sentinelPath) return;
|
|
58
|
+
try {
|
|
59
|
+
const dir = path.dirname(sentinelPath);
|
|
60
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
61
|
+
} catch { /* best-effort */ }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Case-sensitive (or case-insensitive on Windows) path comparison.
|
|
66
|
+
*/
|
|
67
|
+
export function samePath(a: string, b: string): boolean {
|
|
68
|
+
const left = path.resolve(a);
|
|
69
|
+
const right = path.resolve(b);
|
|
70
|
+
if (process.platform === "win32") {
|
|
71
|
+
return left.toLowerCase() === right.toLowerCase();
|
|
72
|
+
}
|
|
73
|
+
return left === right;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Heuristic check for LLM output that isn't a real summary.
|
|
78
|
+
*/
|
|
79
|
+
export function looksLikeBadSummary(output: string): boolean {
|
|
80
|
+
const normalized = output.toLowerCase();
|
|
81
|
+
return (
|
|
82
|
+
normalized.includes("don't see") ||
|
|
83
|
+
normalized.includes("no output") ||
|
|
84
|
+
normalized.includes("could you provide") ||
|
|
85
|
+
normalized.includes("paste")
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Return a deterministic summary file path for a given agent prefix + task ID.
|
|
91
|
+
* Callers can advertise this path before the session finishes so consumers
|
|
92
|
+
* know where to look for the summary once it's written.
|
|
93
|
+
*/
|
|
94
|
+
export function getWellKnownSummaryPath(
|
|
95
|
+
prefix: string,
|
|
96
|
+
taskId: string,
|
|
97
|
+
projectRoot?: string,
|
|
98
|
+
): string {
|
|
99
|
+
const sessionKey = projectRoot
|
|
100
|
+
? path.basename(projectRoot)
|
|
101
|
+
: "unknown";
|
|
102
|
+
const dir = path.join(os.tmpdir(), "aiw-agent-output", sessionKey);
|
|
103
|
+
return path.join(dir, `${prefix}-${taskId}.md`).replaceAll("\\", "/");
|
|
104
|
+
}
|
|
105
|
+
|
|
46
106
|
export function persistSummary(
|
|
47
107
|
summary: string,
|
|
48
108
|
prefix: string,
|
|
49
109
|
sessionId?: string,
|
|
110
|
+
taskId?: string,
|
|
111
|
+
projectRoot?: string,
|
|
50
112
|
): string | null {
|
|
51
113
|
try {
|
|
52
114
|
const suffix = sessionId
|
|
@@ -57,6 +119,18 @@ export function persistSummary(
|
|
|
57
119
|
`${prefix}-summary-${Date.now()}-${suffix}.md`,
|
|
58
120
|
);
|
|
59
121
|
fs.writeFileSync(filePath, summary, "utf8");
|
|
122
|
+
|
|
123
|
+
// Also write to the well-known path for deterministic discovery.
|
|
124
|
+
if (taskId) {
|
|
125
|
+
try {
|
|
126
|
+
const wkPath = getWellKnownSummaryPath(prefix, taskId, projectRoot);
|
|
127
|
+
fs.mkdirSync(path.dirname(wkPath), { recursive: true });
|
|
128
|
+
fs.writeFileSync(wkPath, summary, "utf8");
|
|
129
|
+
} catch {
|
|
130
|
+
logWarn("agent-launcher", "Failed to write well-known summary path");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
60
134
|
return filePath.replaceAll("\\", "/");
|
|
61
135
|
} catch (error) {
|
|
62
136
|
logWarn("agent-launcher", `Failed to persist summary: ${String(error)}`);
|
|
@@ -27,6 +27,8 @@ function resolveAiwBin(cwd?: string): string {
|
|
|
27
27
|
export interface AiwLaunchOptions {
|
|
28
28
|
/** Launch codex instead of claude. */
|
|
29
29
|
codex?: boolean;
|
|
30
|
+
/** Launch devin instead of claude. */
|
|
31
|
+
devin?: boolean;
|
|
30
32
|
/** Working directory. */
|
|
31
33
|
cwd?: string;
|
|
32
34
|
/** Extra env vars to inject. */
|
|
@@ -61,6 +63,7 @@ export async function aiwLaunch(options: AiwLaunchOptions): Promise<AiwLaunchRes
|
|
|
61
63
|
const args = ["launch"];
|
|
62
64
|
|
|
63
65
|
if (options.codex) args.push("--codex");
|
|
66
|
+
if (options.devin) args.push("--devin");
|
|
64
67
|
if (options.wait) args.push("--wait");
|
|
65
68
|
args.push("--json");
|
|
66
69
|
if (options.split) args.push("--split", options.split);
|
|
@@ -87,7 +90,7 @@ function parseJsonResult(result: ExecResult): AiwLaunchResult {
|
|
|
87
90
|
return {
|
|
88
91
|
launched: Boolean(parsed.launched),
|
|
89
92
|
backend: String(parsed.backend ?? "exec"),
|
|
90
|
-
paneId: parsed.paneId ?? null,
|
|
93
|
+
paneId: parsed.handle ?? parsed.paneId ?? null,
|
|
91
94
|
sentinelPath: parsed.sentinelPath ?? null,
|
|
92
95
|
exitCode: typeof parsed.exitCode === "number" ? parsed.exitCode : null,
|
|
93
96
|
reason: parsed.reason ?? null,
|
|
@@ -103,4 +106,3 @@ function parseJsonResult(result: ExecResult): AiwLaunchResult {
|
|
|
103
106
|
};
|
|
104
107
|
}
|
|
105
108
|
}
|
|
106
|
-
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* platform quoting, model tier resolution, and env setup.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { CLAUDE_MODELS, CODEX_MODELS } from "./models.js";
|
|
7
|
+
import { CLAUDE_MODELS, CODEX_MODELS, DEVIN_MODELS } from "./models.js";
|
|
8
8
|
import type { PreflightCommandConfig } from "./preflight.js";
|
|
9
9
|
import { getInternalSubprocessEnv, shellQuoteWin } from "./subprocess-utils.js";
|
|
10
10
|
|
|
@@ -15,7 +15,7 @@ import { getInternalSubprocessEnv, shellQuoteWin } from "./subprocess-utils.js";
|
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
16
16
|
|
|
17
17
|
export type InvocationMode = "structured" | "print" | "preflight";
|
|
18
|
-
export type CliProvider = "claude" | "codex";
|
|
18
|
+
export type CliProvider = "claude" | "codex" | "devin";
|
|
19
19
|
export type ModelTier = "fast" | "standard" | "smart";
|
|
20
20
|
|
|
21
21
|
const VALID_SANDBOXES = ["read-only", "workspace-write", "danger-full-access"] as const;
|
|
@@ -71,6 +71,12 @@ export const CODEX_MODEL_TIERS: Record<ModelTier, string> = {
|
|
|
71
71
|
smart: CODEX_MODELS.codex,
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
+
export const DEVIN_MODEL_TIERS: Record<ModelTier, string> = {
|
|
75
|
+
fast: DEVIN_MODELS.sonnet,
|
|
76
|
+
standard: DEVIN_MODELS.swe,
|
|
77
|
+
smart: DEVIN_MODELS.opus,
|
|
78
|
+
};
|
|
79
|
+
|
|
74
80
|
export const TIER_TIMEOUTS: Record<ModelTier, number> = {
|
|
75
81
|
fast: 15,
|
|
76
82
|
standard: 30,
|
|
@@ -91,7 +97,9 @@ export function resolveModelForProvider(
|
|
|
91
97
|
provider: CliProvider,
|
|
92
98
|
): string {
|
|
93
99
|
if (!isModelTier(model)) return model;
|
|
94
|
-
|
|
100
|
+
if (provider === "codex") return CODEX_MODEL_TIERS[model];
|
|
101
|
+
if (provider === "devin") return DEVIN_MODEL_TIERS[model];
|
|
102
|
+
return MODEL_TIERS[model];
|
|
95
103
|
}
|
|
96
104
|
|
|
97
105
|
export function getTierTimeout(tier: ModelTier): number {
|
|
@@ -104,6 +112,12 @@ export function resolveCodexModel(input: string): string {
|
|
|
104
112
|
return input;
|
|
105
113
|
}
|
|
106
114
|
|
|
115
|
+
/** Resolve a Devin model: tier resolution + pass-through. No aliases (those are skill-specific). */
|
|
116
|
+
export function resolveDevinModel(input: string): string {
|
|
117
|
+
if (isModelTier(input)) return DEVIN_MODEL_TIERS[input as ModelTier];
|
|
118
|
+
return input;
|
|
119
|
+
}
|
|
120
|
+
|
|
107
121
|
// ---------------------------------------------------------------------------
|
|
108
122
|
// Core Builder
|
|
109
123
|
// ---------------------------------------------------------------------------
|
|
@@ -286,4 +300,4 @@ export function preflightCommandConfig(provider: CliProvider): PreflightCommandC
|
|
|
286
300
|
};
|
|
287
301
|
}
|
|
288
302
|
|
|
289
|
-
export {CLAUDE_MODELS, CODEX_MODELS} from "./models.js";
|
|
303
|
+
export {CLAUDE_MODELS, CODEX_MODELS, DEVIN_MODELS} from "./models.js";
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { execFileSync } from "node:child_process";
|
|
8
8
|
|
|
9
9
|
import { logDebug, logWarn } from "./logger.js";
|
|
10
|
-
import {
|
|
10
|
+
import { filterStopWords } from "./stop-words.js";
|
|
11
11
|
import type { InferenceResult } from "../types.js";
|
|
12
12
|
import {
|
|
13
13
|
buildCliInvocation,
|
|
@@ -143,7 +143,7 @@ export function generateSemanticSummary(
|
|
|
143
143
|
summary = summary.replace(/[.!?]+$/, "");
|
|
144
144
|
|
|
145
145
|
// Filter stop words
|
|
146
|
-
summary = filterStopWords(summary);
|
|
146
|
+
summary = filterStopWords(summary).toLowerCase();
|
|
147
147
|
|
|
148
148
|
const words = summary.split(/\s+/);
|
|
149
149
|
if (words.length < 6 || words.length > 12) return null;
|
|
@@ -193,7 +193,7 @@ Respond with ONLY a JSON object: {"slug": "your 8-12 word phrase here"}`;
|
|
|
193
193
|
*/
|
|
194
194
|
export function generateContextIdSlug(
|
|
195
195
|
prompt: string,
|
|
196
|
-
timeout =
|
|
196
|
+
timeout = 8,
|
|
197
197
|
): string | null {
|
|
198
198
|
const truncated = prompt.slice(0, 500);
|
|
199
199
|
|
|
@@ -341,16 +341,4 @@ export async function codexInferAsync(
|
|
|
341
341
|
};
|
|
342
342
|
}
|
|
343
343
|
|
|
344
|
-
/**
|
|
345
|
-
* Filter stop words from text.
|
|
346
|
-
* See SPEC.md §6.4
|
|
347
|
-
*/
|
|
348
|
-
function filterStopWords(text: string): string {
|
|
349
|
-
return text
|
|
350
|
-
.toLowerCase()
|
|
351
|
-
.split(/\s+/)
|
|
352
|
-
.filter((w) => !STOP_WORDS.has(w) && w.length > 1)
|
|
353
|
-
.join(" ");
|
|
354
|
-
}
|
|
355
|
-
|
|
356
344
|
|
|
@@ -10,6 +10,7 @@ import path from "node:path";
|
|
|
10
10
|
import { atomicWrite } from "./atomic-write.js";
|
|
11
11
|
import { getContextDir } from "./constants.js";
|
|
12
12
|
import { logWarn } from "./logger.js";
|
|
13
|
+
import { ContextStateSchema } from "../schemas.js";
|
|
13
14
|
import type { ContextState, Mode } from "../types.js";
|
|
14
15
|
|
|
15
16
|
/** Mode migration from legacy context_manager values. */
|
|
@@ -34,12 +35,13 @@ interface LegacyStateData {
|
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
37
|
* Serialize a ContextState for JSON output.
|
|
37
|
-
* Omits
|
|
38
|
+
* Omits undefined keys but preserves null (semantically meaningful in the schema).
|
|
39
|
+
* Keeps false, 0, empty string, and empty arrays.
|
|
38
40
|
*/
|
|
39
41
|
export function toDict(state: ContextState): Record<string, unknown> {
|
|
40
42
|
const result: Record<string, unknown> = {};
|
|
41
43
|
for (const [key, value] of Object.entries(state)) {
|
|
42
|
-
if (value !==
|
|
44
|
+
if (value !== undefined) {
|
|
43
45
|
result[key] = value;
|
|
44
46
|
}
|
|
45
47
|
}
|
|
@@ -121,6 +123,11 @@ export function readStateJson(
|
|
|
121
123
|
const raw = fs.readFileSync(sp, "utf8");
|
|
122
124
|
const data = JSON.parse(raw) as Record<string, unknown>;
|
|
123
125
|
migrateConsumedFlags(data); // Migrate before dictToState
|
|
126
|
+
const parsed = ContextStateSchema.safeParse(data);
|
|
127
|
+
if (!parsed.success) {
|
|
128
|
+
logWarn("state_io", `Schema validation failed for '${contextId}': ${parsed.error.message}`);
|
|
129
|
+
// Fail-open: still attempt to reconstruct state from raw data
|
|
130
|
+
}
|
|
124
131
|
return dictToState(data);
|
|
125
132
|
} catch (error: unknown) {
|
|
126
133
|
logWarn("state_io", `Failed to read state.json for '${contextId}': ${error}`);
|
|
@@ -138,8 +145,6 @@ export function writeStateJson(
|
|
|
138
145
|
projectRoot?: string,
|
|
139
146
|
): [boolean, string | null] {
|
|
140
147
|
const sp = statePath(contextId, projectRoot);
|
|
141
|
-
const dir = path.dirname(sp);
|
|
142
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
143
148
|
|
|
144
149
|
const content = JSON.stringify(toDict(state), null, 2);
|
|
145
150
|
// fsync: false — state.json is reconstructable from context folder contents
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
* See SPEC.md §14.2, §14.3
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import * as fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
|
|
6
9
|
import { sanitizeTitle } from "./constants.js";
|
|
7
10
|
import { logDebug, logError, logWarn } from "./logger.js";
|
|
8
11
|
import { STOP_WORDS } from "./stop-words.js";
|
|
@@ -110,7 +113,7 @@ export function generateSlug(
|
|
|
110
113
|
// Tier 1: AI inference via generateContextIdSlug (sync — uses execFileSync)
|
|
111
114
|
try {
|
|
112
115
|
// eslint-disable-next-line @typescript-eslint/no-require-imports, no-undef
|
|
113
|
-
const { generateContextIdSlug } = require("./inference
|
|
116
|
+
const { generateContextIdSlug } = require("./inference");
|
|
114
117
|
const aiSlug = generateContextIdSlug(text);
|
|
115
118
|
if (aiSlug) {
|
|
116
119
|
const filteredWords = aiSlug
|
|
@@ -191,3 +194,29 @@ export function generateContextId(
|
|
|
191
194
|
return `${baseId}-${counter}`;
|
|
192
195
|
}
|
|
193
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Get .md files in a directory sorted by mtime (newest first).
|
|
199
|
+
*/
|
|
200
|
+
export function getMdFilesByMtime(dir: string): string[] {
|
|
201
|
+
try {
|
|
202
|
+
if (!fs.existsSync(dir)) return [];
|
|
203
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
204
|
+
return entries
|
|
205
|
+
.filter(e => e.isFile() && e.name.endsWith(".md"))
|
|
206
|
+
.map(e => {
|
|
207
|
+
const fullPath = path.join(dir, e.name);
|
|
208
|
+
const stat = fs.statSync(fullPath);
|
|
209
|
+
return { path: fullPath, mtime: stat.mtimeMs };
|
|
210
|
+
})
|
|
211
|
+
.sort((a, b) => b.mtime - a.mtime)
|
|
212
|
+
.map(f => f.path);
|
|
213
|
+
} catch { return []; }
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Get the most recently modified .md file in a directory.
|
|
218
|
+
*/
|
|
219
|
+
export function mostRecentMd(dir: string): string | null {
|
|
220
|
+
return getMdFilesByMtime(dir)[0] ?? null;
|
|
221
|
+
}
|
|
222
|
+
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schemas mirroring types.ts for runtime validation at JSON.parse boundaries.
|
|
3
|
+
* All object schemas use .passthrough() to preserve method-specific extension fields.
|
|
4
|
+
* See types.ts for corresponding TypeScript interfaces.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
|
|
9
|
+
// §1.1
|
|
10
|
+
export const ModeSchema = z.enum(["active", "has_staged_work", "idle"]);
|
|
11
|
+
|
|
12
|
+
// §1.2
|
|
13
|
+
export const GitStateSchema = z
|
|
14
|
+
.object({
|
|
15
|
+
branch: z.string().optional(),
|
|
16
|
+
last_commit_short: z.string().optional(),
|
|
17
|
+
uncommitted_files: z.array(z.string()).optional(),
|
|
18
|
+
})
|
|
19
|
+
.passthrough();
|
|
20
|
+
|
|
21
|
+
export const LastSessionSchema = z
|
|
22
|
+
.object({
|
|
23
|
+
context_remaining_pct: z.number().optional(),
|
|
24
|
+
context_warnings_fired: z.array(z.number()).optional(),
|
|
25
|
+
git_state: GitStateSchema.optional(),
|
|
26
|
+
save_reason: z.string().optional(),
|
|
27
|
+
saved_at: z.string().optional(),
|
|
28
|
+
session_id: z.string().optional(),
|
|
29
|
+
transcript_path: z.string().optional(),
|
|
30
|
+
})
|
|
31
|
+
.passthrough();
|
|
32
|
+
|
|
33
|
+
// §1.3
|
|
34
|
+
export const TaskSchema = z
|
|
35
|
+
.object({
|
|
36
|
+
active_form: z.string(),
|
|
37
|
+
completed_at: z.string().nullable(),
|
|
38
|
+
created_at: z.string(),
|
|
39
|
+
description: z.string(),
|
|
40
|
+
evidence: z.string(),
|
|
41
|
+
files_changed: z.array(z.string()),
|
|
42
|
+
id: z.string(),
|
|
43
|
+
session_id: z.string().optional(),
|
|
44
|
+
status: z.enum(["blocked", "completed", "in_progress", "pending"]),
|
|
45
|
+
subject: z.string(),
|
|
46
|
+
work_summary: z.string(),
|
|
47
|
+
})
|
|
48
|
+
.passthrough();
|
|
49
|
+
|
|
50
|
+
// §1.1 (continued)
|
|
51
|
+
export const ContextStateSchema = z
|
|
52
|
+
.object({
|
|
53
|
+
created_at: z.string(),
|
|
54
|
+
handoff_consumed: z.boolean().optional(), // deprecated
|
|
55
|
+
handoff_path: z.string().nullable().optional(),
|
|
56
|
+
id: z.string(),
|
|
57
|
+
last_active: z.string(),
|
|
58
|
+
last_session: LastSessionSchema.nullable().optional(),
|
|
59
|
+
method: z.string(),
|
|
60
|
+
mode: ModeSchema,
|
|
61
|
+
next_artifact_type: z.enum(["handoff", "plan"]).nullable().optional(),
|
|
62
|
+
plan_anchors: z.array(z.string()).optional(),
|
|
63
|
+
plan_consumed: z.boolean().optional(), // deprecated
|
|
64
|
+
plan_hash: z.string().nullable().optional(),
|
|
65
|
+
plan_hash_consumed: z.string().nullable().optional(),
|
|
66
|
+
plan_id: z.string().nullable().optional(),
|
|
67
|
+
plan_path: z.string().nullable().optional(),
|
|
68
|
+
plan_signature: z.string().nullable().optional(),
|
|
69
|
+
session_ids: z.array(z.string()).optional(),
|
|
70
|
+
status: z.enum(["active", "completed"]),
|
|
71
|
+
summary: z.string(),
|
|
72
|
+
tags: z.array(z.string()).optional(),
|
|
73
|
+
tasks: z.array(TaskSchema).optional(),
|
|
74
|
+
work_consumed: z.boolean().optional(),
|
|
75
|
+
})
|
|
76
|
+
.passthrough();
|
|
77
|
+
|
|
78
|
+
// §1.4
|
|
79
|
+
export const IndexEntrySchema = z
|
|
80
|
+
.object({
|
|
81
|
+
last_active: z.string(),
|
|
82
|
+
mode: z.string(),
|
|
83
|
+
summary: z.string(),
|
|
84
|
+
})
|
|
85
|
+
.passthrough();
|
|
86
|
+
|
|
87
|
+
export const IndexFileSchema = z
|
|
88
|
+
.object({
|
|
89
|
+
contexts: z.record(z.string(), IndexEntrySchema),
|
|
90
|
+
sessions: z.record(z.string(), z.string()),
|
|
91
|
+
updated_at: z.string(),
|
|
92
|
+
version: z.literal("3.0"),
|
|
93
|
+
})
|
|
94
|
+
.passthrough();
|
|
95
|
+
|
|
96
|
+
// §1.5
|
|
97
|
+
export const LogEntrySchema = z
|
|
98
|
+
.object({
|
|
99
|
+
component: z.string().optional(),
|
|
100
|
+
data: z.unknown().optional(),
|
|
101
|
+
hook: z.string(),
|
|
102
|
+
level: z.enum(["debug", "error", "info", "warn"]),
|
|
103
|
+
msg: z.string(),
|
|
104
|
+
tb: z.string().optional(),
|
|
105
|
+
ts: z.string(),
|
|
106
|
+
})
|
|
107
|
+
.passthrough();
|
|
108
|
+
|
|
109
|
+
// §1.6
|
|
110
|
+
export const HookInputSchema = z
|
|
111
|
+
.object({
|
|
112
|
+
context_window: z
|
|
113
|
+
.object({
|
|
114
|
+
context_window_size: z.number().optional(),
|
|
115
|
+
current_usage: z
|
|
116
|
+
.object({
|
|
117
|
+
cache_creation_input_tokens: z.number().optional(),
|
|
118
|
+
cache_read_input_tokens: z.number().optional(),
|
|
119
|
+
input_tokens: z.number().optional(),
|
|
120
|
+
output_tokens: z.number().optional(),
|
|
121
|
+
})
|
|
122
|
+
.passthrough()
|
|
123
|
+
.optional(),
|
|
124
|
+
})
|
|
125
|
+
.passthrough()
|
|
126
|
+
.optional(),
|
|
127
|
+
cwd: z.string().optional(),
|
|
128
|
+
hook_event_name: z.string(),
|
|
129
|
+
permission_mode: z.string().optional(),
|
|
130
|
+
session_id: z.string().optional(),
|
|
131
|
+
source: z.string().optional(),
|
|
132
|
+
tool_input: z.record(z.string(), z.unknown()).optional(),
|
|
133
|
+
tool_name: z.string().optional(),
|
|
134
|
+
tool_result: z.string().optional(),
|
|
135
|
+
transcript_path: z.string().optional(),
|
|
136
|
+
})
|
|
137
|
+
.passthrough();
|
|
138
|
+
|
|
139
|
+
// §1.7
|
|
140
|
+
export const HookOutputSchema = z
|
|
141
|
+
.object({
|
|
142
|
+
decision: z.literal("block").optional(),
|
|
143
|
+
hookSpecificOutput: z
|
|
144
|
+
.object({
|
|
145
|
+
additionalContext: z.string().optional(),
|
|
146
|
+
hookEventName: z.string().optional(),
|
|
147
|
+
permissionDecision: z.enum(["allow", "ask", "deny"]).optional(),
|
|
148
|
+
permissionDecisionReason: z.string().optional(),
|
|
149
|
+
updatedInput: z.record(z.string(), z.unknown()).optional(),
|
|
150
|
+
})
|
|
151
|
+
.passthrough()
|
|
152
|
+
.optional(),
|
|
153
|
+
reason: z.string().optional(),
|
|
154
|
+
})
|
|
155
|
+
.passthrough();
|
|
156
|
+
|
|
157
|
+
// §1.7b
|
|
158
|
+
export const PermissionRequestOutputSchema = z
|
|
159
|
+
.object({
|
|
160
|
+
decision: z.object({
|
|
161
|
+
behavior: z.enum(["allow", "deny"]),
|
|
162
|
+
message: z.string().optional(),
|
|
163
|
+
updatedInput: z.record(z.string(), z.unknown()).optional(),
|
|
164
|
+
updatedPermissions: z.record(z.string(), z.unknown()).optional(),
|
|
165
|
+
}),
|
|
166
|
+
})
|
|
167
|
+
.passthrough();
|
|
168
|
+
|
|
169
|
+
// §1.8
|
|
170
|
+
export const InferenceResultSchema = z
|
|
171
|
+
.object({
|
|
172
|
+
error: z.string().optional(),
|
|
173
|
+
latency_ms: z.number(),
|
|
174
|
+
output: z.string(),
|
|
175
|
+
success: z.boolean(),
|
|
176
|
+
})
|
|
177
|
+
.passthrough();
|
|
178
|
+
|
|
179
|
+
// §1.9
|
|
180
|
+
export const HandoffDocumentSchema = z
|
|
181
|
+
.object({
|
|
182
|
+
active_tasks: z.array(TaskSchema),
|
|
183
|
+
completed_tasks_this_session: z.array(z.object({ subject: z.string() }).passthrough()),
|
|
184
|
+
context_folder: z.string(),
|
|
185
|
+
context_id: z.string(),
|
|
186
|
+
context_summary: z.string(),
|
|
187
|
+
created_at: z.string(),
|
|
188
|
+
events_log_path: z.string(),
|
|
189
|
+
file_path: z.string().nullable(),
|
|
190
|
+
important_notes: z.array(z.string()),
|
|
191
|
+
next_steps: z.array(z.string()),
|
|
192
|
+
plan_path: z.string().nullable(),
|
|
193
|
+
reason: z.string(),
|
|
194
|
+
session_id: z.string(),
|
|
195
|
+
work_summary: z.string(),
|
|
196
|
+
})
|
|
197
|
+
.passthrough();
|
|
198
|
+
|
|
199
|
+
// §1.10
|
|
200
|
+
export const HandoffSectionsSchema = z
|
|
201
|
+
.object({
|
|
202
|
+
completedWork: z.string().nullable(),
|
|
203
|
+
context: z.string().nullable(),
|
|
204
|
+
deadEnds: z.string().nullable(),
|
|
205
|
+
decisions: z.string().nullable(),
|
|
206
|
+
index: z.string().nullable(),
|
|
207
|
+
pending: z.string().nullable(),
|
|
208
|
+
plan: z.string().nullable(),
|
|
209
|
+
})
|
|
210
|
+
.passthrough();
|
|
211
|
+
|
|
212
|
+
// §1.11
|
|
213
|
+
export const CaretCommandSchema = z
|
|
214
|
+
.object({
|
|
215
|
+
ends: z.array(z.string()),
|
|
216
|
+
new_context_desc: z.string().nullable(),
|
|
217
|
+
remaining_prompt: z.string(),
|
|
218
|
+
select: z.string().nullable(),
|
|
219
|
+
})
|
|
220
|
+
.passthrough();
|
|
221
|
+
|
|
222
|
+
// §1.13
|
|
223
|
+
export const AgentConfigSchema = z
|
|
224
|
+
.object({
|
|
225
|
+
categories: z.array(z.string()),
|
|
226
|
+
description: z.string(),
|
|
227
|
+
focus: z.string(),
|
|
228
|
+
model: z.string(),
|
|
229
|
+
name: z.string(),
|
|
230
|
+
provider: z.string(),
|
|
231
|
+
system_prompt: z.string(),
|
|
232
|
+
})
|
|
233
|
+
.passthrough();
|