aiwcli 0.13.8 → 0.15.1
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 +11 -1
- package/dist/commands/launch.d.ts +8 -0
- package/dist/commands/launch.js +96 -5
- package/dist/templates/_shared/.claude/skills/codex/SKILL.md +42 -0
- package/dist/templates/_shared/.claude/skills/codex/prompt.md +30 -0
- package/dist/templates/_shared/lib-ts/agent-exec/backends/headless.ts +33 -0
- package/dist/templates/_shared/lib-ts/agent-exec/backends/index.ts +6 -0
- package/dist/templates/_shared/lib-ts/agent-exec/backends/tmux.ts +145 -0
- package/dist/templates/_shared/lib-ts/agent-exec/base-agent.ts +229 -0
- package/dist/templates/_shared/lib-ts/agent-exec/execution-backend.ts +50 -0
- package/dist/templates/_shared/lib-ts/agent-exec/index.ts +6 -0
- package/dist/templates/_shared/lib-ts/agent-exec/structured-output.ts +166 -0
- package/dist/templates/_shared/lib-ts/base/cli-args.ts +287 -0
- package/dist/templates/_shared/lib-ts/base/inference.ts +53 -47
- package/dist/templates/_shared/lib-ts/base/models.ts +16 -0
- package/dist/templates/_shared/lib-ts/base/preflight.ts +98 -0
- package/dist/templates/_shared/lib-ts/base/state-io.ts +1 -1
- package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +4 -3
- package/dist/templates/_shared/lib-ts/base/tmux-driver.ts +381 -0
- package/dist/templates/_shared/lib-ts/base/utils.ts +8 -0
- package/dist/templates/_shared/lib-ts/context/context-formatter.ts +35 -11
- package/dist/templates/_shared/lib-ts/context/context-store.ts +3 -0
- package/dist/templates/_shared/lib-ts/types.ts +17 -0
- package/dist/templates/_shared/scripts/status_line.ts +93 -47
- package/dist/templates/_shared/skills/prompt-codex/CLAUDE.md +71 -0
- package/dist/templates/_shared/skills/prompt-codex/scripts/launch-codex.ts +387 -0
- package/dist/templates/_shared/skills/prompt-codex/scripts/watch-codex.ts +257 -0
- package/dist/templates/cc-native/.claude/settings.json +121 -1
- package/dist/templates/cc-native/_cc-native/CLAUDE.md +73 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/CLAUDE.md +70 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +9 -133
- package/dist/templates/cc-native/_cc-native/lib-ts/settings.ts +120 -43
- package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +1 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +66 -12
- package/dist/templates/cc-native/_cc-native/plan-review/lib/agent-selection.ts +5 -4
- package/dist/templates/cc-native/_cc-native/plan-review/lib/orchestrator.ts +4 -4
- package/dist/templates/cc-native/_cc-native/plan-review/lib/preflight.ts +14 -80
- package/dist/templates/cc-native/_cc-native/plan-review/lib/review-pipeline.ts +16 -13
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/agent.ts +19 -7
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/base/base-agent.ts +4 -215
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/index.ts +1 -1
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/claude-agent.ts +9 -39
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/codex-agent.ts +19 -22
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/gemini-agent.ts +2 -1
- package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/orchestrator-claude-agent.ts +65 -36
- package/oclif.manifest.json +21 -3
- package/package.json +1 -1
|
@@ -13,14 +13,15 @@ import { execFileSync } from "node:child_process";
|
|
|
13
13
|
import * as fs from "node:fs";
|
|
14
14
|
import { homedir } from "node:os";
|
|
15
15
|
import * as path from "node:path";
|
|
16
|
+
import type { ContextState } from "../lib-ts/types.js";
|
|
16
17
|
|
|
17
18
|
// PAI infrastructure imports — graceful fallback when libs aren't available
|
|
18
19
|
let CONTEXT_BASELINE_TOKENS = 22_600;
|
|
19
|
-
let getContextBySessionId: (id: string) =>
|
|
20
|
+
let getContextBySessionId: (id: string, root?: string) => ContextState | null =
|
|
20
21
|
() => null;
|
|
21
|
-
let getContext: (id: string) =>
|
|
22
|
-
let loadState: (id: string) =>
|
|
23
|
-
let saveState: (id: string, state:
|
|
22
|
+
let getContext: (id: string, root?: string) => ContextState | null = () => null;
|
|
23
|
+
let loadState: (id: string, root?: string) => ContextState | null = () => null;
|
|
24
|
+
let saveState: (id: string, state: ContextState) => void = () => {};
|
|
24
25
|
let findLatestPlan: (contextId: string) => string | null = () => null;
|
|
25
26
|
|
|
26
27
|
try {
|
|
@@ -59,41 +60,60 @@ const CACHE_DIR = path.join(OUTPUT_DIR, "cache");
|
|
|
59
60
|
const STATUSLINE_CACHE = path.join(CACHE_DIR, ".statusline-cache.json");
|
|
60
61
|
|
|
61
62
|
// ---------------------------------------------------------------------------
|
|
62
|
-
//
|
|
63
|
+
// Color level detection (truecolor → 256-color → basic 16 → none)
|
|
63
64
|
// ---------------------------------------------------------------------------
|
|
64
|
-
|
|
65
|
+
type ColorLevel = 0 | 1 | 2 | 3;
|
|
66
|
+
|
|
67
|
+
function detectColorLevel(): ColorLevel {
|
|
68
|
+
if (process.env.NO_COLOR) return 0;
|
|
69
|
+
const fc = process.env.FORCE_COLOR;
|
|
70
|
+
if (fc !== undefined) return Math.min(3, Math.max(0, parseInt(fc, 10) || 0)) as ColorLevel;
|
|
71
|
+
const ct = process.env.COLORTERM ?? "";
|
|
72
|
+
if (ct === "truecolor" || ct === "24bit") return 3;
|
|
73
|
+
if ((process.env.TERM ?? "").includes("256color")) return 2;
|
|
74
|
+
return 1;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const COLOR_LEVEL = detectColorLevel();
|
|
78
|
+
|
|
79
|
+
function fg(r: number, g: number, b: number, x256: number, b16: number): string {
|
|
80
|
+
if (COLOR_LEVEL === 0) return "";
|
|
81
|
+
if (COLOR_LEVEL === 3) return `\u001B[38;2;${r};${g};${b}m`;
|
|
82
|
+
if (COLOR_LEVEL === 2) return `\u001B[38;5;${x256}m`;
|
|
83
|
+
return `\u001B[${b16}m`;
|
|
84
|
+
}
|
|
65
85
|
|
|
66
|
-
const RESET =
|
|
86
|
+
const RESET = COLOR_LEVEL === 0 ? "" : "\u001B[0m";
|
|
67
87
|
|
|
68
88
|
// Structural
|
|
69
|
-
const SLATE_300 =
|
|
70
|
-
const SLATE_400 =
|
|
71
|
-
const SLATE_500 =
|
|
72
|
-
const SLATE_600 =
|
|
89
|
+
const SLATE_300 = fg(203, 213, 225, 188, 37);
|
|
90
|
+
const SLATE_400 = fg(148, 163, 184, 146, 37);
|
|
91
|
+
const SLATE_500 = fg(100, 116, 139, 103, 90);
|
|
92
|
+
const SLATE_600 = fg(71, 85, 105, 240, 90);
|
|
73
93
|
|
|
74
94
|
// Semantic
|
|
75
|
-
const EMERALD =
|
|
76
|
-
const ROSE =
|
|
77
|
-
const AMBER =
|
|
95
|
+
const EMERALD = fg(74, 222, 128, 79, 92);
|
|
96
|
+
const ROSE = fg(251, 113, 133, 211, 91);
|
|
97
|
+
const AMBER = fg(251, 191, 36, 221, 93);
|
|
78
98
|
|
|
79
99
|
// Context colors
|
|
80
|
-
const CTX_PRIMARY =
|
|
81
|
-
const CTX_SECONDARY =
|
|
82
|
-
const CTX_ACCENT =
|
|
83
|
-
const CTX_BUCKET_EMPTY =
|
|
100
|
+
const CTX_PRIMARY = fg(129, 140, 248, 147, 94);
|
|
101
|
+
const CTX_SECONDARY = fg(165, 180, 252, 153, 94);
|
|
102
|
+
const CTX_ACCENT = fg(139, 92, 246, 141, 35);
|
|
103
|
+
const CTX_BUCKET_EMPTY = fg(75, 82, 95, 239, 90);
|
|
84
104
|
|
|
85
105
|
// Git colors
|
|
86
|
-
const GIT_PRIMARY =
|
|
87
|
-
const GIT_VALUE =
|
|
88
|
-
const GIT_DIR =
|
|
89
|
-
const GIT_CLEAN =
|
|
90
|
-
const GIT_MODIFIED =
|
|
91
|
-
const GIT_ADDED =
|
|
92
|
-
const GIT_STASH =
|
|
93
|
-
const GIT_AGE_FRESH =
|
|
94
|
-
const GIT_AGE_RECENT =
|
|
95
|
-
const GIT_AGE_STALE =
|
|
96
|
-
const GIT_AGE_OLD =
|
|
106
|
+
const GIT_PRIMARY = fg(56, 189, 248, 81, 96);
|
|
107
|
+
const GIT_VALUE = fg(186, 230, 253, 195, 96);
|
|
108
|
+
const GIT_DIR = fg(147, 197, 253, 153, 94);
|
|
109
|
+
const GIT_CLEAN = fg(125, 211, 252, 117, 96);
|
|
110
|
+
const GIT_MODIFIED = fg(96, 165, 250, 111, 94);
|
|
111
|
+
const GIT_ADDED = fg(59, 130, 246, 75, 34);
|
|
112
|
+
const GIT_STASH = fg(165, 180, 252, 153, 94);
|
|
113
|
+
const GIT_AGE_FRESH = fg(125, 211, 252, 117, 96);
|
|
114
|
+
const GIT_AGE_RECENT = fg(96, 165, 250, 111, 94);
|
|
115
|
+
const GIT_AGE_STALE = fg(59, 130, 246, 75, 34);
|
|
116
|
+
const GIT_AGE_OLD = fg(99, 102, 241, 105, 35);
|
|
97
117
|
|
|
98
118
|
// ---------------------------------------------------------------------------
|
|
99
119
|
// Display modes
|
|
@@ -127,7 +147,7 @@ function getDisplayMode(width: number): string {
|
|
|
127
147
|
// ---------------------------------------------------------------------------
|
|
128
148
|
|
|
129
149
|
function getBucketColor(pos: number, maxPos: number): string {
|
|
130
|
-
if (
|
|
150
|
+
if (COLOR_LEVEL === 0) return "";
|
|
131
151
|
const pct = Math.floor((pos * 100) / maxPos);
|
|
132
152
|
|
|
133
153
|
let b: number;
|
|
@@ -150,7 +170,17 @@ function getBucketColor(pos: number, maxPos: number): string {
|
|
|
150
170
|
b = 60 + Math.floor(((68 - 60) * t) / 34);
|
|
151
171
|
}
|
|
152
172
|
|
|
153
|
-
return `\u001B[38;2;${r};${g};${b}m`;
|
|
173
|
+
if (COLOR_LEVEL === 3) return `\u001B[38;2;${r};${g};${b}m`;
|
|
174
|
+
if (COLOR_LEVEL === 2) {
|
|
175
|
+
const ri = Math.round(r / 51);
|
|
176
|
+
const gi = Math.round(g / 51);
|
|
177
|
+
const bi = Math.round(b / 51);
|
|
178
|
+
return `\u001B[38;5;${16 + 36 * ri + 6 * gi + bi}m`;
|
|
179
|
+
}
|
|
180
|
+
// Level 1: three-band semantic mapping
|
|
181
|
+
if (pct <= 33) return `\u001B[92m`; // bright green
|
|
182
|
+
if (pct <= 66) return `\u001B[93m`; // bright yellow
|
|
183
|
+
return `\u001B[91m`; // bright red
|
|
154
184
|
}
|
|
155
185
|
|
|
156
186
|
// ---------------------------------------------------------------------------
|
|
@@ -299,7 +329,7 @@ function renderContext(
|
|
|
299
329
|
line =
|
|
300
330
|
`${CTX_PRIMARY}\u25C9${RESET} ${CTX_ACCENT}${shortModel}${RESET} ` +
|
|
301
331
|
`${SLATE_600}\u2502${RESET} ` +
|
|
302
|
-
`${bar} ${pctColor}${contextPct}%${RESET} ${SLATE_500}(${contextK}k)${RESET}`;
|
|
332
|
+
`${bar} ${pctColor}${contextPct}%${RESET} ${SLATE_500}(${contextK}k/${maxK}k)${RESET}`;
|
|
303
333
|
|
|
304
334
|
break;
|
|
305
335
|
}
|
|
@@ -590,7 +620,7 @@ function findActivePlanFile(): string | null {
|
|
|
590
620
|
function renderContextManager(
|
|
591
621
|
mode: string,
|
|
592
622
|
contextId: string,
|
|
593
|
-
contextState:
|
|
623
|
+
contextState: ContextState | null,
|
|
594
624
|
): string {
|
|
595
625
|
// Strip YYMMDD-HHMM- timestamp prefix from context ID for display
|
|
596
626
|
let displayId = contextId.replace(/^\d{6}-\d{4}-/, "");
|
|
@@ -620,7 +650,7 @@ function renderContextManager(
|
|
|
620
650
|
if (isPlanning) {
|
|
621
651
|
const label = mode === "nano" ? "Plan" : "Planning";
|
|
622
652
|
modeBadge = ` ${SLATE_600}\u2502${RESET} ${CTX_SECONDARY}Mode:${RESET} ${AMBER}${label}${RESET}`;
|
|
623
|
-
} else if (stateMode === "
|
|
653
|
+
} else if (stateMode === "has_staged_work") {
|
|
624
654
|
const label = mode === "nano" ? "Ready" : "Plan Ready";
|
|
625
655
|
modeBadge = ` ${SLATE_600}\u2502${RESET} ${CTX_SECONDARY}Mode:${RESET} ${EMERALD}${label}${RESET}`;
|
|
626
656
|
} else if (stateMode === "active") {
|
|
@@ -634,7 +664,7 @@ function renderContextManager(
|
|
|
634
664
|
planFilePath = activePlanFile;
|
|
635
665
|
} else if (statePlanPath) {
|
|
636
666
|
planFilePath = statePlanPath;
|
|
637
|
-
} else if (stateMode === "
|
|
667
|
+
} else if (stateMode === "has_staged_work" || stateMode === "active") {
|
|
638
668
|
try {
|
|
639
669
|
planFilePath = findLatestPlan(contextId) ?? null;
|
|
640
670
|
} catch {
|
|
@@ -717,7 +747,7 @@ function resolveContextId(sessionId: string): string | null {
|
|
|
717
747
|
const context = getContextBySessionId(sessionId);
|
|
718
748
|
if (context) {
|
|
719
749
|
if (!cache.sessions) cache.sessions = {};
|
|
720
|
-
const ctxId =
|
|
750
|
+
const ctxId = context.id;
|
|
721
751
|
cache.sessions[sessionId] = { context_id: ctxId };
|
|
722
752
|
saveCache(cache);
|
|
723
753
|
return ctxId;
|
|
@@ -730,9 +760,9 @@ function resolveContextId(sessionId: string): string | null {
|
|
|
730
760
|
return null;
|
|
731
761
|
}
|
|
732
762
|
|
|
733
|
-
function loadContextState(contextId: string):
|
|
763
|
+
function loadContextState(contextId: string): ContextState | null {
|
|
734
764
|
try {
|
|
735
|
-
return loadState(contextId)
|
|
765
|
+
return loadState(contextId);
|
|
736
766
|
} catch {
|
|
737
767
|
return null;
|
|
738
768
|
}
|
|
@@ -743,12 +773,12 @@ function writeContextWindow(
|
|
|
743
773
|
contextWindowData: Record<string, unknown>,
|
|
744
774
|
): void {
|
|
745
775
|
try {
|
|
746
|
-
const state = getContext(contextId)
|
|
776
|
+
const state = getContext(contextId);
|
|
747
777
|
if (state) {
|
|
748
|
-
if (!state.last_session) state.last_session = {};
|
|
749
|
-
state.last_session.context_remaining_pct =
|
|
778
|
+
if (!state.last_session) state.last_session = { session_id: undefined, saved_at: undefined, save_reason: undefined, transcript_path: undefined };
|
|
779
|
+
(state.last_session as Record<string, unknown>).context_remaining_pct =
|
|
750
780
|
contextWindowData.remaining_percentage;
|
|
751
|
-
saveState(contextId, state
|
|
781
|
+
saveState(contextId, state);
|
|
752
782
|
}
|
|
753
783
|
} catch {
|
|
754
784
|
/* ignore */
|
|
@@ -759,11 +789,28 @@ function writeContextWindow(
|
|
|
759
789
|
// Main
|
|
760
790
|
// ---------------------------------------------------------------------------
|
|
761
791
|
|
|
792
|
+
/** Shape of the JSON payload piped to status_line.ts via stdin */
|
|
793
|
+
interface StatusLineInput {
|
|
794
|
+
session_id?: string;
|
|
795
|
+
model?: { display_name?: string };
|
|
796
|
+
workspace?: { project_dir?: string };
|
|
797
|
+
context_window?: {
|
|
798
|
+
current_usage?: {
|
|
799
|
+
cache_read_input_tokens?: number;
|
|
800
|
+
input_tokens?: number;
|
|
801
|
+
cache_creation_input_tokens?: number;
|
|
802
|
+
output_tokens?: number;
|
|
803
|
+
};
|
|
804
|
+
context_window_size?: number;
|
|
805
|
+
used_percentage?: number;
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
|
|
762
809
|
function main(): void {
|
|
763
810
|
// Read JSON from stdin
|
|
764
|
-
let inputData:
|
|
811
|
+
let inputData: StatusLineInput;
|
|
765
812
|
try {
|
|
766
|
-
inputData = JSON.parse(fs.readFileSync(0, "utf-8"));
|
|
813
|
+
inputData = JSON.parse(fs.readFileSync(0, "utf-8")) as StatusLineInput;
|
|
767
814
|
} catch {
|
|
768
815
|
inputData = {};
|
|
769
816
|
}
|
|
@@ -775,8 +822,7 @@ function main(): void {
|
|
|
775
822
|
// Extract input fields
|
|
776
823
|
const sessionId = inputData.session_id ?? "";
|
|
777
824
|
const modelName = inputData.model?.display_name ?? "unknown";
|
|
778
|
-
const
|
|
779
|
-
const currentDir: string = workspace.project_dir ?? process.cwd();
|
|
825
|
+
const currentDir: string = inputData.workspace?.project_dir ?? process.cwd();
|
|
780
826
|
const dirName = path.basename(currentDir);
|
|
781
827
|
|
|
782
828
|
// Context window data
|
|
@@ -795,7 +841,7 @@ function main(): void {
|
|
|
795
841
|
const contextUsed = totalInput + outputTokens + CONTEXT_BASELINE_TOKENS;
|
|
796
842
|
|
|
797
843
|
if (usedPct !== undefined && usedPct !== null) {
|
|
798
|
-
contextPct = Math.floor(usedPct);
|
|
844
|
+
contextPct = Math.floor(usedPct as number);
|
|
799
845
|
} else {
|
|
800
846
|
contextPct =
|
|
801
847
|
contextMax > 0 ? Math.floor((contextUsed * 100) / contextMax) : 0;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Prompt Codex Skill
|
|
2
|
+
|
|
3
|
+
Launch Codex CLI in a tmux pane and inject a prompt into its REPL.
|
|
4
|
+
|
|
5
|
+
## Directory Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
prompt-codex/
|
|
9
|
+
├── CLAUDE.md ← This file
|
|
10
|
+
└── scripts/
|
|
11
|
+
├── launch-codex.ts ← CLI entry point
|
|
12
|
+
└── watch-codex.ts ← Capture watcher and summarizer
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Script: launch-codex.ts
|
|
16
|
+
|
|
17
|
+
**Usage:**
|
|
18
|
+
```bash
|
|
19
|
+
bun .aiwcli/_shared/skills/prompt-codex/scripts/launch-codex.ts [--model <tier|id>] [--sandbox <sandbox-mode>] [--full-auto] plan
|
|
20
|
+
bun .aiwcli/_shared/skills/prompt-codex/scripts/launch-codex.ts [--model <tier|id>] [--sandbox <sandbox-mode>] [--full-auto] --file <path>
|
|
21
|
+
bun .aiwcli/_shared/skills/prompt-codex/scripts/launch-codex.ts [--model <tier|id>] [--sandbox <sandbox-mode>] [--full-auto] <inline text...>
|
|
22
|
+
bun .aiwcli/_shared/skills/prompt-codex/scripts/launch-codex.ts [--model <tier|id>] [--sandbox <sandbox-mode>] [--full-auto] [--capture] <mode>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Args:**
|
|
26
|
+
- `plan` — discover active plan via context system, inject into Codex REPL
|
|
27
|
+
- `--file <path>` — inject file contents into Codex REPL
|
|
28
|
+
- `<text...>` — join remaining args as inline prompt, write to temp file, inject
|
|
29
|
+
- `--model <alias|tier|id>` — Aliases: `spark` → `gpt-5.3-codex-spark`, `codex` → `gpt-5.3-codex`, `gpt` → `gpt-5.2`. Tiers: `fast`/`standard`/`smart` (resolved via `resolveModelForProvider()`). Or any full model ID. Aliases are checked first (local `CODEX_ALIASES` constant in `launch-codex.ts`), then tiers, then pass-through. Omitted = Codex default.
|
|
30
|
+
- `--sandbox <mode>` — `read-only`, `workspace-write`, or `danger-full-access`. Default is `danger-full-access` for implementation handoffs.
|
|
31
|
+
- `--no-yolo` — Disable YOLO mode (on by default). YOLO maps to Codex CLI's `--dangerously-bypass-approvals-and-sandbox`. Use `--no-yolo` to restore normal approval prompts.
|
|
32
|
+
- `--capture` — Best-effort session capture. On success, prints:
|
|
33
|
+
- `CODEX_CAPTURE_PANE=<pane_id>`
|
|
34
|
+
- `CODEX_CAPTURE_SESSION_ID=<session_id>`
|
|
35
|
+
- `CODEX_CAPTURE_SESSION_FILE=<session_file>`
|
|
36
|
+
These are consumed by the skill prompt to run `watch-codex.ts` as a background task.
|
|
37
|
+
|
|
38
|
+
**Plan discovery order:**
|
|
39
|
+
1. `CLAUDE_SESSION_ID` env → `getContextBySessionId()` → `findLatestPlan(contextId)`
|
|
40
|
+
2. Fallback: scan `_output/contexts/*/plans/*.md` by mtime (inline, no `_cc-native` import)
|
|
41
|
+
|
|
42
|
+
**Dependencies (all from `_shared/lib-ts/`):**
|
|
43
|
+
- `base/tmux-driver.ts` — `launchDriverInTmuxOrFallback()`, `getTmuxAvailability()`
|
|
44
|
+
- `base/cli-args.ts` — `resolveCodexModel()`, `codexReplSpec()`, `buildCliInvocation()`, `isCodexSandbox()`
|
|
45
|
+
- `base/logger.ts` — `logDebug()`, `logWarn()` (injection diagnostics)
|
|
46
|
+
- `context/context-store.ts` — `getContextBySessionId()`
|
|
47
|
+
- `context/context-formatter.ts` — `buildExternalAgentContext()` (orientation header for Codex)
|
|
48
|
+
- `context/plan-manager.ts` — `findLatestPlan()`
|
|
49
|
+
|
|
50
|
+
**Design decisions:**
|
|
51
|
+
- Always creates a new tmux pane (no pane reuse/tracking)
|
|
52
|
+
- No exec fallback — REPL mode requires tmux
|
|
53
|
+
- `_shared` only — never imports from `_cc-native`
|
|
54
|
+
- Temp file cleanup after injection confirmed
|
|
55
|
+
|
|
56
|
+
## Script: watch-codex.ts
|
|
57
|
+
|
|
58
|
+
**Usage:**
|
|
59
|
+
```bash
|
|
60
|
+
bun .aiwcli/_shared/skills/prompt-codex/scripts/watch-codex.ts <pane_id> <session_id> <session_file>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Behavior:**
|
|
64
|
+
- Polls tmux until `<pane_id>` closes
|
|
65
|
+
- Primary: parses `<session_file>` transcript and summarizes via Spark (`inference()` + `CODEX_MODELS.spark`)
|
|
66
|
+
- Fallback: runs `codex exec resume <session_id>` if transcript summarization fails
|
|
67
|
+
- Final fallback: emits concise transcript lines directly from `<session_file>`
|
|
68
|
+
|
|
69
|
+
**Resilience policy:**
|
|
70
|
+
- Capture path is best-effort and never blocks Codex launch
|
|
71
|
+
- Watcher exits cleanly on poll/summary/parse failures with fallback text
|