codiedev 0.10.0-beta.1 → 0.10.0-beta.11
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 -5
- package/assets/opencode-plugin.mjs +6 -0
- package/assets/session-key.mjs +48 -0
- package/assets/tui-brand-plugin.tsx +73 -0
- package/dist/backup/cache.js +1 -5
- package/dist/backup/match.js +0 -6
- package/dist/backup/run.js +3 -35
- package/dist/captureExclusions.js +0 -12
- package/dist/captureLog.js +0 -28
- package/dist/captureReadiness.js +0 -58
- package/dist/captureSignals.js +184 -0
- package/dist/cli.js +135 -72
- package/dist/cliSession.js +456 -0
- package/dist/codexHookTrust.js +125 -6
- package/dist/codexLimitScan.js +359 -0
- package/dist/codie.js +77 -130
- package/dist/codieBrandInstall.js +80 -0
- package/dist/codieLauncher.js +76 -79
- package/dist/codieRuntime.js +19 -23
- package/dist/codieRuntimeInstall.js +108 -23
- package/dist/codieUsage.js +181 -0
- package/dist/commands/agentTemplates.generated.js +136 -0
- package/dist/commands/agents.js +1101 -0
- package/dist/commands/agentsSdk.generated.js +7 -0
- package/dist/commands/ask.js +0 -3
- package/dist/commands/capture.js +0 -2
- package/dist/commands/createTicket.js +0 -10
- package/dist/commands/doctor.js +53 -120
- package/dist/commands/evals.js +187 -0
- package/dist/commands/inbox.js +0 -2
- package/dist/commands/library.js +0 -3
- package/dist/commands/pack.js +573 -0
- package/dist/commands/ping.js +0 -2
- package/dist/commands/pull.js +6 -10
- package/dist/commands/push.js +2 -12
- package/dist/commands/search.js +0 -4
- package/dist/commands/send.js +0 -5
- package/dist/commands/share.js +0 -4
- package/dist/commands/shared.js +0 -35
- package/dist/commands/traces.js +344 -0
- package/dist/commands/tracesLabel.js +348 -0
- package/dist/configDir.js +18 -11
- package/dist/connect.js +55 -118
- package/dist/connectFlow.js +35 -9
- package/dist/copilotHooks.js +391 -0
- package/dist/copilotInstallation.js +64 -0
- package/dist/cursorHooks.js +38 -30
- package/dist/cursorLifecycle.js +109 -0
- package/dist/detection.js +0 -30
- package/dist/harnessDirs.js +77 -0
- package/dist/hook.js +256 -445
- package/dist/inboxFormat.js +0 -24
- package/dist/launchContext.js +150 -0
- package/dist/launcher.js +168 -0
- package/dist/limitEvent.js +44 -13
- package/dist/limitEventReporter.js +1 -1
- package/dist/managedPi.js +256 -0
- package/dist/mcp.js +5 -384
- package/dist/nativeSteering.js +24 -0
- package/dist/packs/codie.js +182 -0
- package/dist/packs/harnesses.js +411 -0
- package/dist/packs/hookGate.js +256 -0
- package/dist/packs/install.js +286 -0
- package/dist/packs/manifest.js +126 -0
- package/dist/packs/paths.js +81 -0
- package/dist/packs/shim.js +214 -0
- package/dist/packs/store.js +155 -0
- package/dist/packs/sync.js +170 -0
- package/dist/piHooks.js +216 -0
- package/dist/piRuntime.js +120 -0
- package/dist/repoResolver.js +0 -19
- package/dist/secret.js +0 -3
- package/dist/selfUpdate.js +376 -0
- package/dist/skillMarker.js +23 -0
- package/dist/subagents.js +135 -0
- package/dist/teamSkillContext.js +10 -0
- package/dist/transcriptModels.js +205 -0
- package/dist/upgradeNudge.js +0 -30
- package/dist/utils.js +502 -828
- package/dist/version.js +0 -10
- package/dist/versionCheck.js +0 -33
- package/package.json +8 -9
- package/dist/backup/cache.d.ts +0 -14
- package/dist/backup/match.d.ts +0 -2
- package/dist/backup/run.d.ts +0 -25
- package/dist/captureExclusions.d.ts +0 -30
- package/dist/captureLog.d.ts +0 -20
- package/dist/captureReadiness.d.ts +0 -65
- package/dist/cli.d.ts +0 -16
- package/dist/codexHookTrust.d.ts +0 -34
- package/dist/codie.d.ts +0 -2
- package/dist/codieLauncher.d.ts +0 -53
- package/dist/codieRuntime.d.ts +0 -29
- package/dist/codieRuntimeInstall.d.ts +0 -28
- package/dist/codieStartup.d.ts +0 -26
- package/dist/codieStartup.js +0 -30
- package/dist/commands/ask.d.ts +0 -1
- package/dist/commands/capture.d.ts +0 -14
- package/dist/commands/createTicket.d.ts +0 -27
- package/dist/commands/delete.d.ts +0 -1
- package/dist/commands/doctor.d.ts +0 -1
- package/dist/commands/inbox.d.ts +0 -3
- package/dist/commands/library.d.ts +0 -2
- package/dist/commands/note.d.ts +0 -1
- package/dist/commands/ping.d.ts +0 -1
- package/dist/commands/promote.d.ts +0 -1
- package/dist/commands/promote.js +0 -53
- package/dist/commands/pull.d.ts +0 -2
- package/dist/commands/push.d.ts +0 -33
- package/dist/commands/react.d.ts +0 -2
- package/dist/commands/react.js +0 -40
- package/dist/commands/reverseTicket.d.ts +0 -2
- package/dist/commands/reverseTicket.js +0 -477
- package/dist/commands/search.d.ts +0 -2
- package/dist/commands/security.d.ts +0 -1
- package/dist/commands/security.js +0 -156
- package/dist/commands/send.d.ts +0 -2
- package/dist/commands/share.d.ts +0 -2
- package/dist/commands/shared.d.ts +0 -64
- package/dist/configDir.d.ts +0 -1
- package/dist/connect.d.ts +0 -1
- package/dist/connectFlow.d.ts +0 -13
- package/dist/cursorHooks.d.ts +0 -23
- package/dist/detection.d.ts +0 -30
- package/dist/hook.d.ts +0 -6
- package/dist/inboxFormat.d.ts +0 -38
- package/dist/limitEvent.d.ts +0 -16
- package/dist/limitEventReporter.d.ts +0 -21
- package/dist/mcp.d.ts +0 -12
- package/dist/prUrl.d.ts +0 -9
- package/dist/prUrl.js +0 -33
- package/dist/repoResolver.d.ts +0 -17
- package/dist/secret.d.ts +0 -1
- package/dist/security.d.ts +0 -102
- package/dist/security.js +0 -437
- package/dist/securityDeepScan.d.ts +0 -41
- package/dist/securityDeepScan.js +0 -248
- package/dist/securityDoctor.d.ts +0 -32
- package/dist/securityDoctor.js +0 -63
- package/dist/securityFeature.d.ts +0 -5
- package/dist/securityFeature.js +0 -7
- package/dist/securityInstall.d.ts +0 -63
- package/dist/securityInstall.js +0 -239
- package/dist/securityInventory.d.ts +0 -54
- package/dist/securityInventory.js +0 -556
- package/dist/securityPilot.d.ts +0 -19
- package/dist/securityPilot.js +0 -61
- package/dist/securityPolicy.d.ts +0 -33
- package/dist/securityPolicy.js +0 -188
- package/dist/securitySession.d.ts +0 -6
- package/dist/securitySession.js +0 -72
- package/dist/upgradeNudge.d.ts +0 -25
- package/dist/utils.d.ts +0 -342
- package/dist/version.d.ts +0 -1
- package/dist/versionCheck.d.ts +0 -68
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.CODEX_LIMIT_STATE_PATH = void 0;
|
|
37
|
+
exports.scanCodexRolloutForLimit = scanCodexRolloutForLimit;
|
|
38
|
+
exports.readTailEndingAt = readTailEndingAt;
|
|
39
|
+
exports.findRecentCodexRollouts = findRecentCodexRollouts;
|
|
40
|
+
exports.sessionIdFromRolloutPath = sessionIdFromRolloutPath;
|
|
41
|
+
exports.codexSessionsDir = codexSessionsDir;
|
|
42
|
+
exports.recordCodexLimitReported = recordCodexLimitReported;
|
|
43
|
+
exports.sweepCodexLimits = sweepCodexLimits;
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
const limitEvent_1 = require("./limitEvent");
|
|
47
|
+
const configDir_1 = require("./configDir");
|
|
48
|
+
const harnessDirs_1 = require("./harnessDirs");
|
|
49
|
+
const MARKER = Buffer.from("rate_limit_reached_type");
|
|
50
|
+
const SPEND_MARKER = Buffer.from("spend_control_reached");
|
|
51
|
+
const NEWLINE = 0x0a;
|
|
52
|
+
const DEFAULT_CHUNK_SIZE = 256 * 1024;
|
|
53
|
+
const DEFAULT_MAX_SCAN_BYTES = 16 * 1024 * 1024;
|
|
54
|
+
const DEFAULT_TAIL_BYTES = 64 * 1024;
|
|
55
|
+
function scanCodexRolloutForLimit(filePath, options = {}) {
|
|
56
|
+
const chunkSize = options.chunkSize ?? DEFAULT_CHUNK_SIZE;
|
|
57
|
+
const maxScanBytes = options.maxScanBytes ?? DEFAULT_MAX_SCAN_BYTES;
|
|
58
|
+
let size = 0;
|
|
59
|
+
try {
|
|
60
|
+
size = fs.statSync(filePath).size;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
if (size === 0)
|
|
66
|
+
return null;
|
|
67
|
+
let fd;
|
|
68
|
+
try {
|
|
69
|
+
fd = fs.openSync(filePath, "r");
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
let pos = size;
|
|
76
|
+
let carry = Buffer.alloc(0);
|
|
77
|
+
let scanned = 0;
|
|
78
|
+
while (pos > 0 && scanned < maxScanBytes) {
|
|
79
|
+
const length = Math.min(chunkSize, pos, maxScanBytes - scanned);
|
|
80
|
+
if (length <= 0)
|
|
81
|
+
break;
|
|
82
|
+
pos -= length;
|
|
83
|
+
const chunk = Buffer.allocUnsafe(length);
|
|
84
|
+
const read = fs.readSync(fd, chunk, 0, length, pos);
|
|
85
|
+
scanned += read;
|
|
86
|
+
const window = Buffer.concat([chunk.subarray(0, read), carry]);
|
|
87
|
+
let completeStart = 0;
|
|
88
|
+
if (pos > 0) {
|
|
89
|
+
const firstNewline = window.indexOf(NEWLINE);
|
|
90
|
+
if (firstNewline < 0) {
|
|
91
|
+
carry = window.length > maxScanBytes ? Buffer.alloc(0) : window;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
completeStart = firstNewline + 1;
|
|
95
|
+
carry = window.subarray(0, completeStart);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
carry = Buffer.alloc(0);
|
|
99
|
+
}
|
|
100
|
+
const region = window.subarray(completeStart);
|
|
101
|
+
if (region.indexOf(MARKER) < 0 && region.indexOf(SPEND_MARKER) < 0)
|
|
102
|
+
continue;
|
|
103
|
+
const bounds = [];
|
|
104
|
+
let lineStart = 0;
|
|
105
|
+
for (let index = 0; index < region.length; index += 1) {
|
|
106
|
+
if (region[index] === NEWLINE) {
|
|
107
|
+
bounds.push([lineStart, index + 1]);
|
|
108
|
+
lineStart = index + 1;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (lineStart < region.length)
|
|
112
|
+
bounds.push([lineStart, region.length]);
|
|
113
|
+
for (let index = bounds.length - 1; index >= 0; index -= 1) {
|
|
114
|
+
const [start, end] = bounds[index];
|
|
115
|
+
const event = (0, limitEvent_1.parseCodexLimitEventFromTranscript)(region.subarray(start, end).toString("utf8"));
|
|
116
|
+
if (event)
|
|
117
|
+
return { event, lineEnd: pos + completeStart + end };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
try {
|
|
127
|
+
fs.closeSync(fd);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function readTailEndingAt(filePath, lineEnd, maxBytes = DEFAULT_TAIL_BYTES) {
|
|
134
|
+
let end = lineEnd;
|
|
135
|
+
try {
|
|
136
|
+
end = Math.min(lineEnd, fs.statSync(filePath).size);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return "";
|
|
140
|
+
}
|
|
141
|
+
const start = Math.max(0, end - maxBytes);
|
|
142
|
+
const length = end - start;
|
|
143
|
+
if (length <= 0)
|
|
144
|
+
return "";
|
|
145
|
+
let fd;
|
|
146
|
+
try {
|
|
147
|
+
fd = fs.openSync(filePath, "r");
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return "";
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
const buffer = Buffer.allocUnsafe(length);
|
|
154
|
+
const read = fs.readSync(fd, buffer, 0, length, start);
|
|
155
|
+
const text = buffer.subarray(0, read).toString("utf8");
|
|
156
|
+
if (start === 0)
|
|
157
|
+
return text;
|
|
158
|
+
const newline = text.indexOf("\n");
|
|
159
|
+
return newline === -1 ? "" : text.slice(newline + 1);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
return "";
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
try {
|
|
166
|
+
fs.closeSync(fd);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const DEFAULT_WITHIN_MS = 24 * 3600_000;
|
|
173
|
+
const DEFAULT_MAX_FILES = 12;
|
|
174
|
+
function findRecentCodexRollouts(sessionsDir, options = {}) {
|
|
175
|
+
const withinMs = options.withinMs ?? DEFAULT_WITHIN_MS;
|
|
176
|
+
const maxFiles = options.maxFiles ?? DEFAULT_MAX_FILES;
|
|
177
|
+
const now = options.now ?? Date.now();
|
|
178
|
+
const found = [];
|
|
179
|
+
const walk = (directory, depth) => {
|
|
180
|
+
if (depth > 5)
|
|
181
|
+
return;
|
|
182
|
+
let entries;
|
|
183
|
+
try {
|
|
184
|
+
entries = fs.readdirSync(directory, { withFileTypes: true });
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
for (const entry of entries) {
|
|
190
|
+
const full = path.join(directory, entry.name);
|
|
191
|
+
if (entry.isDirectory()) {
|
|
192
|
+
walk(full, depth + 1);
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (!entry.isFile() || !entry.name.endsWith(".jsonl"))
|
|
196
|
+
continue;
|
|
197
|
+
try {
|
|
198
|
+
const mtime = fs.statSync(full).mtimeMs;
|
|
199
|
+
if (now - mtime > withinMs)
|
|
200
|
+
continue;
|
|
201
|
+
found.push({ file: full, mtime });
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
walk(sessionsDir, 0);
|
|
208
|
+
return found
|
|
209
|
+
.sort((left, right) => right.mtime - left.mtime)
|
|
210
|
+
.slice(0, maxFiles)
|
|
211
|
+
.map((entry) => entry.file);
|
|
212
|
+
}
|
|
213
|
+
function sessionIdFromRolloutPath(filePath) {
|
|
214
|
+
const match = path.basename(filePath).match(/^rollout-.*?T[\d-]+-(.+)\.jsonl$/);
|
|
215
|
+
return match ? match[1] : undefined;
|
|
216
|
+
}
|
|
217
|
+
function codexSessionsDir() {
|
|
218
|
+
return path.join((0, harnessDirs_1.codexHome)(), "sessions");
|
|
219
|
+
}
|
|
220
|
+
exports.CODEX_LIMIT_STATE_PATH = path.join((0, configDir_1.codiedevStateDir)(), "codex-limit-state.json");
|
|
221
|
+
const MAX_STATE_ENTRIES = 500;
|
|
222
|
+
function readSweepState(statePath) {
|
|
223
|
+
let parsed;
|
|
224
|
+
try {
|
|
225
|
+
parsed = JSON.parse(fs.readFileSync(statePath, "utf8"));
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
return { seen: {} };
|
|
229
|
+
}
|
|
230
|
+
const seen = {};
|
|
231
|
+
const raw = parsed.seen;
|
|
232
|
+
if (raw && typeof raw === "object") {
|
|
233
|
+
for (const [file, value] of Object.entries(raw)) {
|
|
234
|
+
const record = value;
|
|
235
|
+
if (typeof record?.size !== "number")
|
|
236
|
+
continue;
|
|
237
|
+
seen[file] = {
|
|
238
|
+
size: record.size,
|
|
239
|
+
mtime: typeof record.mtime === "number" ? record.mtime : -1,
|
|
240
|
+
at: typeof record.at === "number" ? record.at : null,
|
|
241
|
+
t: typeof record.t === "number" ? record.t : 0,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const legacyClean = parsed.clean;
|
|
246
|
+
if (legacyClean && typeof legacyClean === "object") {
|
|
247
|
+
for (const [file, size] of Object.entries(legacyClean)) {
|
|
248
|
+
if (typeof size === "number" && !seen[file])
|
|
249
|
+
seen[file] = { size, mtime: -1, at: null, t: 0 };
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return { seen };
|
|
253
|
+
}
|
|
254
|
+
const PRUNE_AFTER_MS = 7 * 24 * 3600_000;
|
|
255
|
+
function pruneSweepState(state, now) {
|
|
256
|
+
for (const [file, record] of Object.entries(state.seen)) {
|
|
257
|
+
if (now - (record.t ?? 0) < PRUNE_AFTER_MS)
|
|
258
|
+
continue;
|
|
259
|
+
if (!fs.existsSync(file))
|
|
260
|
+
delete state.seen[file];
|
|
261
|
+
}
|
|
262
|
+
const files = Object.keys(state.seen);
|
|
263
|
+
if (files.length <= MAX_STATE_ENTRIES)
|
|
264
|
+
return;
|
|
265
|
+
files
|
|
266
|
+
.sort((left, right) => (state.seen[right].t ?? 0) - (state.seen[left].t ?? 0))
|
|
267
|
+
.slice(MAX_STATE_ENTRIES)
|
|
268
|
+
.forEach((file) => delete state.seen[file]);
|
|
269
|
+
}
|
|
270
|
+
function commitSweepState(statePath, ours, now) {
|
|
271
|
+
const current = readSweepState(statePath);
|
|
272
|
+
for (const [file, record] of Object.entries(ours))
|
|
273
|
+
current.seen[file] = record;
|
|
274
|
+
pruneSweepState(current, now);
|
|
275
|
+
writeSweepState(statePath, current);
|
|
276
|
+
}
|
|
277
|
+
function writeSweepState(statePath, state) {
|
|
278
|
+
const temp = `${statePath}.${process.pid}.tmp`;
|
|
279
|
+
try {
|
|
280
|
+
fs.mkdirSync(path.dirname(statePath), { recursive: true });
|
|
281
|
+
fs.writeFileSync(temp, JSON.stringify(state), "utf8");
|
|
282
|
+
fs.renameSync(temp, statePath);
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
try {
|
|
286
|
+
fs.unlinkSync(temp);
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function fingerprint(filePath) {
|
|
293
|
+
try {
|
|
294
|
+
const stat = fs.statSync(filePath);
|
|
295
|
+
return { size: stat.size, mtime: stat.mtimeMs };
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function recordCodexLimitReported(filePath, at, statePath = exports.CODEX_LIMIT_STATE_PATH) {
|
|
302
|
+
const print = fingerprint(filePath);
|
|
303
|
+
if (!print)
|
|
304
|
+
return;
|
|
305
|
+
commitSweepState(statePath, { [filePath]: { ...print, at, t: Date.now() } }, Date.now());
|
|
306
|
+
}
|
|
307
|
+
const DEFAULT_CANDIDATES = 200;
|
|
308
|
+
const DEFAULT_MAX_SCANS = 64;
|
|
309
|
+
const DEFAULT_DEADLINE_MS = 1_500;
|
|
310
|
+
async function sweepCodexLimits(args) {
|
|
311
|
+
const statePath = args.statePath ?? exports.CODEX_LIMIT_STATE_PATH;
|
|
312
|
+
const state = readSweepState(statePath);
|
|
313
|
+
const files = findRecentCodexRollouts(args.sessionsDir, {
|
|
314
|
+
maxFiles: DEFAULT_CANDIDATES,
|
|
315
|
+
...args.findOptions,
|
|
316
|
+
});
|
|
317
|
+
const now = Date.now();
|
|
318
|
+
const touched = {};
|
|
319
|
+
let budget = args.maxScans ?? DEFAULT_MAX_SCANS;
|
|
320
|
+
const deadline = now + (args.deadlineMs ?? DEFAULT_DEADLINE_MS);
|
|
321
|
+
const pending = [];
|
|
322
|
+
for (const file of files) {
|
|
323
|
+
const print = fingerprint(file);
|
|
324
|
+
if (!print)
|
|
325
|
+
continue;
|
|
326
|
+
const record = state.seen[file];
|
|
327
|
+
if (record && record.size === print.size && record.mtime === print.mtime)
|
|
328
|
+
continue;
|
|
329
|
+
if (budget <= 0 || Date.now() >= deadline)
|
|
330
|
+
break;
|
|
331
|
+
budget -= 1;
|
|
332
|
+
const hit = scanCodexRolloutForLimit(file, args.scanOptions);
|
|
333
|
+
if (!hit) {
|
|
334
|
+
touched[file] = { ...print, at: null, t: now };
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
if (record && record.at === hit.event.at) {
|
|
338
|
+
touched[file] = { ...print, at: record.at, t: now };
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
pending.push({ file, print, hit });
|
|
342
|
+
}
|
|
343
|
+
const results = await Promise.allSettled(pending.map(({ file, hit }) => args.post({
|
|
344
|
+
source: "codex",
|
|
345
|
+
...hit.event,
|
|
346
|
+
sessionId: sessionIdFromRolloutPath(file),
|
|
347
|
+
transcriptTail: readTailEndingAt(file, hit.lineEnd),
|
|
348
|
+
})));
|
|
349
|
+
let posted = 0;
|
|
350
|
+
results.forEach((result, index) => {
|
|
351
|
+
if (result.status !== "fulfilled")
|
|
352
|
+
return;
|
|
353
|
+
const { file, print, hit } = pending[index];
|
|
354
|
+
touched[file] = { ...print, at: hit.event.at, t: now };
|
|
355
|
+
posted += 1;
|
|
356
|
+
});
|
|
357
|
+
commitSweepState(statePath, touched, now);
|
|
358
|
+
return posted;
|
|
359
|
+
}
|
package/dist/codie.js
CHANGED
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
// `codie` — Codiedev's governed coding harness.
|
|
4
|
-
//
|
|
5
|
-
// Ships from the same package as `codiedev` so a developer runs one install and
|
|
6
|
-
// then picks their surface: Claude Code, Codex, and Cursor get session capture
|
|
7
|
-
// via `codiedev connect`; `codie` launches the governed harness against the
|
|
8
|
-
// same token. OpenCode is the embedded engine; all user-facing identity,
|
|
9
|
-
// credentials, models, policy, and capture belong to Codiedev.
|
|
10
|
-
//
|
|
11
|
-
// The engine is downloaded on first run (see codieRuntime.ts) so capture-only
|
|
12
|
-
// users never pay for it.
|
|
13
3
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
4
|
if (k2 === undefined) k2 = k;
|
|
15
5
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -51,10 +41,17 @@ const child_process_1 = require("child_process");
|
|
|
51
41
|
const url_1 = require("url");
|
|
52
42
|
const configDir_1 = require("./configDir");
|
|
53
43
|
const codieLauncher_1 = require("./codieLauncher");
|
|
44
|
+
const codieBrandInstall_1 = require("./codieBrandInstall");
|
|
45
|
+
const codieUsage_1 = require("./codieUsage");
|
|
54
46
|
const codieRuntime_1 = require("./codieRuntime");
|
|
55
47
|
const codieRuntimeInstall_1 = require("./codieRuntimeInstall");
|
|
56
|
-
const codieStartup_1 = require("./codieStartup");
|
|
57
48
|
const upgradeNudge_1 = require("./upgradeNudge");
|
|
49
|
+
const codie_1 = require("./packs/codie");
|
|
50
|
+
const paths_1 = require("./packs/paths");
|
|
51
|
+
const managedPi_1 = require("./managedPi");
|
|
52
|
+
const cliSession_1 = require("./cliSession");
|
|
53
|
+
const CODIE_MIN_TOKEN_VALIDITY_MS = 12 * 60 * 60_000;
|
|
54
|
+
const USAGE_SETTLE_MS = 1200;
|
|
58
55
|
function git(args) {
|
|
59
56
|
const result = (0, child_process_1.spawnSync)("git", args, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
60
57
|
return result.status === 0 ? result.stdout.trim() : "";
|
|
@@ -83,8 +80,6 @@ function existingInlineConfig() {
|
|
|
83
80
|
throw new Error("OPENCODE_CONFIG_CONTENT is not valid JSON");
|
|
84
81
|
}
|
|
85
82
|
}
|
|
86
|
-
// The one credential. `codiedev connect` wrote it; the gateway validates the
|
|
87
|
-
// same userApiTokens row, so there is no second harness token to mint.
|
|
88
83
|
function connectedCodiedevConfig() {
|
|
89
84
|
try {
|
|
90
85
|
return JSON.parse(fs.readFileSync(path.join((0, configDir_1.codiedevStateDir)(), "config.json"), "utf8"));
|
|
@@ -93,40 +88,23 @@ function connectedCodiedevConfig() {
|
|
|
93
88
|
return {};
|
|
94
89
|
}
|
|
95
90
|
}
|
|
96
|
-
function
|
|
97
|
-
// dist/codie.js → ../assets/<name>; src/codie.ts → ../assets/<name>.
|
|
98
|
-
return path.join(__dirname, "..", "assets", name);
|
|
99
|
-
}
|
|
100
|
-
// Stage the home-screen branding plugin. TUI plugins only load from tui.json
|
|
101
|
-
// in the OpenCode config dir, so the packaged file is copied next to the
|
|
102
|
-
// capture plugin and referenced with a relative spec. Best-effort: any
|
|
103
|
-
// failure (e.g. a hand-edited tui.json with comments) leaves the stock logo.
|
|
104
|
-
function installBrandPlugin() {
|
|
91
|
+
function withStarterPacks(existing, approved, catalog) {
|
|
105
92
|
try {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
fs.mkdirSync(pluginDir, { recursive: true });
|
|
111
|
-
const source = fs.readFileSync(assetPath("tui-brand-plugin.tsx"), "utf8");
|
|
112
|
-
const destination = path.join(pluginDir, "codiedev-brand.tsx");
|
|
113
|
-
if (!fs.existsSync(destination) || fs.readFileSync(destination, "utf8") !== source) {
|
|
114
|
-
fs.writeFileSync(destination, source);
|
|
93
|
+
const packs = (0, codie_1.codiePackConfig)((0, paths_1.packsRoot)(), { approvedModels: approved, catalog });
|
|
94
|
+
if (process.env.CODIEDEV_DEBUG) {
|
|
95
|
+
for (const note of packs.notes)
|
|
96
|
+
console.error(`codie: starter pack ${note}`);
|
|
115
97
|
}
|
|
116
|
-
|
|
117
|
-
const existing = fs.existsSync(tuiConfigPath) ? JSON.parse(fs.readFileSync(tuiConfigPath, "utf8")) : {};
|
|
118
|
-
const { config, changed } = (0, codieLauncher_1.withBrandPlugin)(existing);
|
|
119
|
-
if (changed)
|
|
120
|
-
fs.writeFileSync(tuiConfigPath, `${JSON.stringify(config, null, 2)}\n`);
|
|
98
|
+
return (0, codie_1.mergeCodiePackConfig)(existing, packs);
|
|
121
99
|
}
|
|
122
100
|
catch (error) {
|
|
123
|
-
console.error(`codie:
|
|
101
|
+
console.error(`codie: skipping starter packs (${error instanceof Error ? error.message : error})`);
|
|
102
|
+
return existing;
|
|
124
103
|
}
|
|
125
104
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// already-suppressed binary has no known source region and is skipped.
|
|
105
|
+
function assetPath(name) {
|
|
106
|
+
return path.join(__dirname, "..", "assets", name);
|
|
107
|
+
}
|
|
130
108
|
function installBrandWordmark(runtime) {
|
|
131
109
|
try {
|
|
132
110
|
installBrandWordmarkUnsafe(runtime);
|
|
@@ -140,10 +118,6 @@ function installBrandWordmarkUnsafe(runtime) {
|
|
|
140
118
|
const { changed, offset, replacement } = (0, codieLauncher_1.patchBrandWordmark)(binary);
|
|
141
119
|
if (!changed || !replacement)
|
|
142
120
|
return;
|
|
143
|
-
// In-place write (not copy+rename): opencode-ai/bin/opencode.exe and the
|
|
144
|
-
// platform package's binary are hardlinks to one inode, and this keeps them
|
|
145
|
-
// consistent. Restoring the original bytes is a true rollback — identical
|
|
146
|
-
// content revalidates the existing macOS signature.
|
|
147
121
|
const writeAt = (bytes) => {
|
|
148
122
|
const fd = fs.openSync(runtime, "r+");
|
|
149
123
|
try {
|
|
@@ -156,7 +130,6 @@ function installBrandWordmarkUnsafe(runtime) {
|
|
|
156
130
|
const restore = () => writeAt(binary.subarray(offset, offset + replacement.length));
|
|
157
131
|
writeAt(replacement);
|
|
158
132
|
if (process.platform === "darwin") {
|
|
159
|
-
// A modified Mach-O needs a fresh ad-hoc signature or the OS kills it.
|
|
160
133
|
const signed = (0, child_process_1.spawnSync)("codesign", ["--force", "--sign", "-", runtime], { stdio: "ignore" });
|
|
161
134
|
if (signed.status !== 0) {
|
|
162
135
|
restore();
|
|
@@ -186,7 +159,6 @@ async function runNonInteractive(runtime, runtimeArgs, env) {
|
|
|
186
159
|
return;
|
|
187
160
|
}
|
|
188
161
|
catch {
|
|
189
|
-
// Fall back to the direct child if its process group already exited.
|
|
190
162
|
}
|
|
191
163
|
}
|
|
192
164
|
child.kill(signal);
|
|
@@ -196,73 +168,8 @@ async function runNonInteractive(runtime, runtimeArgs, env) {
|
|
|
196
168
|
process.once("SIGINT", forwardInterrupt);
|
|
197
169
|
process.once("SIGTERM", forwardTermination);
|
|
198
170
|
return await new Promise((resolve, reject) => {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
const retainedPrefixBytes = Math.max(...errorPrefixes.map((prefix) => prefix.length)) - 1;
|
|
202
|
-
// OpenCode's generic UnknownError and the adapter's private reason can be
|
|
203
|
-
// delivered in either order — and the generic block can arrive on stdout
|
|
204
|
-
// or stderr. Gate both streams by content, retaining only a possible final
|
|
205
|
-
// error block. Ordinary output stays streaming apart from the few bytes
|
|
206
|
-
// needed to recognize a split prefix.
|
|
207
|
-
const createOutputGate = (write) => {
|
|
208
|
-
let tail = Buffer.alloc(0);
|
|
209
|
-
let possibleError;
|
|
210
|
-
return {
|
|
211
|
-
push(chunk, blocked) {
|
|
212
|
-
if (blocked) {
|
|
213
|
-
if (possibleError)
|
|
214
|
-
possibleError.push(Buffer.from(chunk));
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
if (possibleError) {
|
|
218
|
-
possibleError.push(Buffer.from(chunk));
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
const combined = Buffer.concat([tail, chunk]);
|
|
222
|
-
let errorStart = -1;
|
|
223
|
-
for (const prefix of errorPrefixes) {
|
|
224
|
-
const index = combined.indexOf(prefix);
|
|
225
|
-
if (index >= 0 && (errorStart < 0 || index < errorStart))
|
|
226
|
-
errorStart = index;
|
|
227
|
-
}
|
|
228
|
-
if (errorStart >= 0) {
|
|
229
|
-
if (errorStart > 0)
|
|
230
|
-
write(combined.subarray(0, errorStart));
|
|
231
|
-
possibleError = [combined.subarray(errorStart)];
|
|
232
|
-
tail = Buffer.alloc(0);
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
const flushBytes = Math.max(0, combined.length - retainedPrefixBytes);
|
|
236
|
-
if (flushBytes > 0)
|
|
237
|
-
write(combined.subarray(0, flushBytes));
|
|
238
|
-
tail = combined.subarray(flushBytes);
|
|
239
|
-
},
|
|
240
|
-
finish(blocked) {
|
|
241
|
-
if (tail.length > 0)
|
|
242
|
-
write(tail);
|
|
243
|
-
const heldError = possibleError ? Buffer.concat(possibleError).toString() : "";
|
|
244
|
-
const genericBlockError = heldError.includes("UnknownError") &&
|
|
245
|
-
heldError.includes("Unexpected server error");
|
|
246
|
-
if (heldError && (!blocked || !genericBlockError))
|
|
247
|
-
write(heldError);
|
|
248
|
-
},
|
|
249
|
-
};
|
|
250
|
-
};
|
|
251
|
-
const stdoutGate = createOutputGate((chunk) => process.stdout.write(chunk));
|
|
252
|
-
const stderrGate = createOutputGate((chunk) => process.stderr.write(chunk));
|
|
253
|
-
child.stdout?.on("data", (chunk) => {
|
|
254
|
-
stdoutGate.push(Buffer.from(chunk), Boolean(blockReason));
|
|
255
|
-
});
|
|
256
|
-
child.stderr?.on("data", (chunk) => {
|
|
257
|
-
const text = chunk.toString();
|
|
258
|
-
const reason = (0, codieLauncher_1.extractCodieSecurityBlock)(text);
|
|
259
|
-
if (reason) {
|
|
260
|
-
blockReason = reason;
|
|
261
|
-
signalChild("SIGTERM");
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
stderrGate.push(Buffer.from(chunk), Boolean(blockReason));
|
|
265
|
-
});
|
|
171
|
+
child.stdout?.on("data", (chunk) => process.stdout.write(chunk));
|
|
172
|
+
child.stderr?.on("data", (chunk) => process.stderr.write(chunk));
|
|
266
173
|
child.once("error", (error) => {
|
|
267
174
|
if (child.stdin)
|
|
268
175
|
process.stdin.unpipe(child.stdin);
|
|
@@ -275,38 +182,57 @@ async function runNonInteractive(runtime, runtimeArgs, env) {
|
|
|
275
182
|
process.stdin.unpipe(child.stdin);
|
|
276
183
|
process.removeListener("SIGINT", forwardInterrupt);
|
|
277
184
|
process.removeListener("SIGTERM", forwardTermination);
|
|
278
|
-
stdoutGate.finish(Boolean(blockReason));
|
|
279
|
-
stderrGate.finish(Boolean(blockReason));
|
|
280
|
-
if (blockReason) {
|
|
281
|
-
console.error(`Codie Security blocked this action:\n${blockReason}`);
|
|
282
|
-
}
|
|
283
185
|
resolve(status);
|
|
284
186
|
});
|
|
285
187
|
});
|
|
286
188
|
}
|
|
287
189
|
async function main() {
|
|
288
190
|
(0, codieRuntime_1.assertCodieNodeVersion)(process.versions.node);
|
|
191
|
+
if (!process.env.CODIEDEV_GATEWAY_KEY && !process.env.CODIEDEV_TOKEN) {
|
|
192
|
+
const fresh = await (0, cliSession_1.ensureFreshToken)({ configPath: path.join((0, configDir_1.codiedevStateDir)(), "config.json") }, CODIE_MIN_TOKEN_VALIDITY_MS);
|
|
193
|
+
if (fresh.status === "signed_out") {
|
|
194
|
+
throw new Error("Your Codiedev sign-in has ended. Run `codiedev connect` to sign in again");
|
|
195
|
+
}
|
|
196
|
+
}
|
|
289
197
|
const connected = connectedCodiedevConfig();
|
|
198
|
+
if (!process.env.CODIEDEV_GATEWAY_KEY && !process.env.CODIEDEV_TOKEN && connected.auth) {
|
|
199
|
+
process.env.CODIEDEV_SESSION_CONFIG = path.join((0, configDir_1.codiedevStateDir)(), "config.json");
|
|
200
|
+
process.env.CODIEDEV_CLI_JS = path.join(__dirname, "cli.js");
|
|
201
|
+
process.env.CODIEDEV_NODE = process.execPath;
|
|
202
|
+
}
|
|
290
203
|
const key = process.env.CODIEDEV_GATEWAY_KEY ||
|
|
291
204
|
process.env.CODIEDEV_TOKEN ||
|
|
292
205
|
(typeof connected.token === "string" ? connected.token.trim() : "");
|
|
293
206
|
if (!key) {
|
|
294
207
|
throw new Error("Connect your Codiedev account first with `codiedev connect`");
|
|
295
208
|
}
|
|
296
|
-
// Before anything paints: once the OpenCode engine owns stdio, a prompt is
|
|
297
|
-
// unreadable. A successful in-place upgrade relaunches this command with the
|
|
298
|
-
// new package, so the stale process must stop here.
|
|
299
209
|
const update = await (0, upgradeNudge_1.maybeOfferUpgrade)();
|
|
300
210
|
if (update.relaunched) {
|
|
301
211
|
process.exitCode = update.status ?? 0;
|
|
302
212
|
return;
|
|
303
213
|
}
|
|
304
|
-
const policyRefresh = await (0, codieStartup_1.refreshCodieSecurityPolicy)(connected);
|
|
305
|
-
if (policyRefresh.status === "cached") {
|
|
306
|
-
console.error(`codie: security policy refresh failed; using the cached policy (${policyRefresh.error})`);
|
|
307
|
-
}
|
|
308
214
|
const gatewayUrl = process.env.CODIEDEV_GATEWAY_URL || "https://gateway.codiedev.com/api/v1";
|
|
309
215
|
const catalog = await (0, codieLauncher_1.fetchApprovedCatalog)({ baseUrl: gatewayUrl, key });
|
|
216
|
+
if (process.argv[2] === "--pi") {
|
|
217
|
+
let skillPaths = [];
|
|
218
|
+
try {
|
|
219
|
+
const approved = new Set(catalog.map((model) => (0, codieLauncher_1.bareModel)(model.id)).filter(Boolean));
|
|
220
|
+
skillPaths = (0, codie_1.codiePackConfig)((0, paths_1.packsRoot)(), { approvedModels: approved, catalog }).skillPaths;
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
console.error(`codie: skipping starter packs (${error instanceof Error ? error.message : error})`);
|
|
224
|
+
}
|
|
225
|
+
try {
|
|
226
|
+
process.exitCode = (0, managedPi_1.runManagedPi)({
|
|
227
|
+
args: process.argv.slice(3), key, gatewayUrl, catalog, stateDir: (0, configDir_1.codiedevStateDir)(), skillPaths,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
console.error(`codie: ${error instanceof Error ? error.message : String(error)}`);
|
|
232
|
+
process.exitCode = error instanceof managedPi_1.ManagedPiArgError ? 2 : 1;
|
|
233
|
+
}
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
310
236
|
const parsed = (0, codieLauncher_1.parseCodieArgs)(process.argv.slice(2));
|
|
311
237
|
if (parsed.args.length === 1 && parsed.args[0] === "models") {
|
|
312
238
|
console.log("Codiedev approved models\n");
|
|
@@ -337,8 +263,18 @@ async function main() {
|
|
|
337
263
|
return null;
|
|
338
264
|
}
|
|
339
265
|
},
|
|
266
|
+
isEngine: codieRuntimeInstall_1.isEngineOnDisk,
|
|
340
267
|
}),
|
|
341
268
|
install: (missing) => (0, codieRuntimeInstall_1.installCodieRuntimeOnDisk)(missing, stateDir),
|
|
269
|
+
repair: (unlinked) => {
|
|
270
|
+
console.error("codie: finishing the engine setup npm skipped (opencode-ai's postinstall)…");
|
|
271
|
+
const linked = (0, codieRuntimeInstall_1.linkEngineOnDisk)(unlinked.packageDir);
|
|
272
|
+
if (!linked.ok && linked.detail === codieRuntimeInstall_1.IGNORE_SCRIPTS)
|
|
273
|
+
throw new Error((0, codieRuntimeInstall_1.linkFailure)(linked, unlinked.packageDir));
|
|
274
|
+
if (!linked.ok)
|
|
275
|
+
console.error(`codie: ${(0, codieRuntimeInstall_1.linkFailure)(linked, unlinked.packageDir)} Reinstalling the engine.`);
|
|
276
|
+
return linked.ok;
|
|
277
|
+
},
|
|
342
278
|
confirmUpdate: async (outdated) => {
|
|
343
279
|
console.error("");
|
|
344
280
|
console.error(`Codie harness ${outdated.expectedVersion} is available (you're on ${outdated.currentVersion}).`);
|
|
@@ -352,10 +288,10 @@ async function main() {
|
|
|
352
288
|
});
|
|
353
289
|
const metadataPlugin = (0, url_1.pathToFileURL)(assetPath("opencode-plugin.mjs")).href;
|
|
354
290
|
const capturePlugin = (0, codieLauncher_1.resolveCapturePlugin)({ homeDir: os.homedir(), existsSync: fs.existsSync });
|
|
355
|
-
|
|
291
|
+
(0, codieBrandInstall_1.installTuiPlugin)();
|
|
356
292
|
installBrandWordmark(runtime);
|
|
357
293
|
const config = (0, codieLauncher_1.buildCodieConfig)({
|
|
358
|
-
existing: existingInlineConfig(),
|
|
294
|
+
existing: withStarterPacks(existingInlineConfig(), new Set(catalog.map((model) => (0, codieLauncher_1.bareModel)(model.id)).filter(Boolean)), catalog),
|
|
359
295
|
catalog,
|
|
360
296
|
env: { ...process.env, ...parsed.overrides, CODIEDEV_GATEWAY_URL: gatewayUrl },
|
|
361
297
|
plugins: [capturePlugin, metadataPlugin],
|
|
@@ -371,10 +307,21 @@ async function main() {
|
|
|
371
307
|
};
|
|
372
308
|
const runtimeArgs = (0, codieLauncher_1.withCodieWorkingDirectory)(parsed.args, process.cwd());
|
|
373
309
|
const nonInteractiveRun = runtimeArgs[0] === "run";
|
|
374
|
-
if (nonInteractiveRun)
|
|
375
|
-
env.CODIEDEV_SECURITY_BLOCK_OUTPUT = "marker";
|
|
376
310
|
if (nonInteractiveRun) {
|
|
311
|
+
const reportCost = Boolean(process.stderr.isTTY);
|
|
312
|
+
const startedAt = Date.now();
|
|
313
|
+
if (reportCost) {
|
|
314
|
+
const line = (0, codieUsage_1.formatUsageLine)(await (0, codieUsage_1.fetchCodieUsage)({ baseUrl: gatewayUrl, key }));
|
|
315
|
+
if (line)
|
|
316
|
+
console.error(line);
|
|
317
|
+
}
|
|
377
318
|
process.exitCode = (await runNonInteractive(runtime, runtimeArgs, env)) ?? 1;
|
|
319
|
+
if (reportCost) {
|
|
320
|
+
await new Promise((resolve) => setTimeout(resolve, USAGE_SETTLE_MS));
|
|
321
|
+
const cost = (0, codieUsage_1.formatSessionCostLine)(await (0, codieUsage_1.fetchCodieUsage)({ baseUrl: gatewayUrl, key, sinceMs: startedAt }));
|
|
322
|
+
if (cost)
|
|
323
|
+
console.error(cost);
|
|
324
|
+
}
|
|
378
325
|
return;
|
|
379
326
|
}
|
|
380
327
|
const result = (0, child_process_1.spawnSync)(runtime, runtimeArgs, { stdio: "inherit", env });
|