@cabane/companion 0.6.189 → 0.6.190
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/dist/cli.js +68 -33
- package/dist/runtime.js +68 -33
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5972,6 +5972,10 @@ var init_transport2 = __esm({
|
|
|
5972
5972
|
});
|
|
5973
5973
|
|
|
5974
5974
|
// packages/agent-runtime/src/codex/index.ts
|
|
5975
|
+
function isMissingRollout(err) {
|
|
5976
|
+
const message2 = err instanceof Error ? err.message : String(err);
|
|
5977
|
+
return /no rollout found for thread id/i.test(message2);
|
|
5978
|
+
}
|
|
5975
5979
|
function createCodexAdapter(deps = {}) {
|
|
5976
5980
|
const transport = deps.transport ?? (deps.enabled ? createSdkCodexTransport({ ...deps.apiKey ? { apiKey: deps.apiKey } : {} }) : null);
|
|
5977
5981
|
return {
|
|
@@ -5990,8 +5994,8 @@ function createCodexAdapter(deps = {}) {
|
|
|
5990
5994
|
}
|
|
5991
5995
|
const directory = req.local.cwd ?? "";
|
|
5992
5996
|
const decision = decideResume3(req.session, directory);
|
|
5993
|
-
|
|
5994
|
-
|
|
5997
|
+
let resumeThreadId = "resume" in decision ? decision.resume : null;
|
|
5998
|
+
let threadUsageBaseline = "resume" in decision ? decision.usageBaseline : null;
|
|
5995
5999
|
if ("fresh" in decision && decision.reason === "cwd_mismatch") {
|
|
5996
6000
|
deps.onWarn?.(
|
|
5997
6001
|
"codex adapter: stored session directory no longer matches the current environment \u2014 starting a fresh thread (SJ527-analogue guard)",
|
|
@@ -6056,38 +6060,69 @@ function createCodexAdapter(deps = {}) {
|
|
|
6056
6060
|
}
|
|
6057
6061
|
if (signal.aborted) return;
|
|
6058
6062
|
}
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
model
|
|
6063
|
-
|
|
6063
|
+
for (; ; ) {
|
|
6064
|
+
const spec = buildRunSpec2(req, resumeThreadId, threadStanding, images?.paths ?? []);
|
|
6065
|
+
if (spec.model === null) {
|
|
6066
|
+
deps.onWarn?.("Codex is using its default model because no model was resolved", {
|
|
6067
|
+
model: req.config.model
|
|
6068
|
+
});
|
|
6069
|
+
}
|
|
6070
|
+
let emitted = false;
|
|
6071
|
+
try {
|
|
6072
|
+
const result = await transport.run(spec, signal);
|
|
6073
|
+
if (signal.aborted) return;
|
|
6074
|
+
for await (const event of decodeCodexStream(result.events, {
|
|
6075
|
+
signal,
|
|
6076
|
+
cwd: req.local.cwd,
|
|
6077
|
+
resumedThreadId: resumeThreadId,
|
|
6078
|
+
degraded,
|
|
6079
|
+
// Which segments the thread carries once this turn lands. A segment sent is that one —
|
|
6080
|
+
// the later copy is what the model reads. One withheld is what the thread had. Read off
|
|
6081
|
+
// the spec, so the record can't disagree with what was sent.
|
|
6082
|
+
promptFingerprint: spec.preamble.core ? spec.fingerprints.core : threadStanding?.core ?? null,
|
|
6083
|
+
conversationFingerprint: spec.preamble.conversation ? spec.fingerprints.conversation : threadStanding?.conversation ?? null,
|
|
6084
|
+
compactions,
|
|
6085
|
+
// What the thread held before this turn, for the write at `thread.started`.
|
|
6086
|
+
heldStanding: {
|
|
6087
|
+
promptFingerprint: threadStanding?.core ?? null,
|
|
6088
|
+
conversationFingerprint: threadStanding?.conversation ?? null,
|
|
6089
|
+
compactions: threadStanding ? compactions : null
|
|
6090
|
+
},
|
|
6091
|
+
storedState: req.session,
|
|
6092
|
+
usageBaseline: threadUsageBaseline,
|
|
6093
|
+
// Codex reports no model in-stream, so record what the thread was started with (null on the
|
|
6094
|
+
// default token). Same for the reasoning effort.
|
|
6095
|
+
resolvedModel: spec.model,
|
|
6096
|
+
resolvedReasoningEffort: spec.modelReasoningEffort ?? null
|
|
6097
|
+
})) {
|
|
6098
|
+
emitted = true;
|
|
6099
|
+
yield event;
|
|
6100
|
+
}
|
|
6101
|
+
return;
|
|
6102
|
+
} catch (err) {
|
|
6103
|
+
if (resumeThreadId === null || emitted || signal.aborted || !isMissingRollout(err)) {
|
|
6104
|
+
throw err;
|
|
6105
|
+
}
|
|
6106
|
+
deps.onWarn?.(
|
|
6107
|
+
"codex adapter: the stored thread has no rollout on this host \u2014 starting a fresh thread",
|
|
6108
|
+
{ threadId: resumeThreadId }
|
|
6109
|
+
);
|
|
6110
|
+
resumeThreadId = null;
|
|
6111
|
+
threadUsageBaseline = null;
|
|
6112
|
+
threadStanding = null;
|
|
6113
|
+
compactions = 0;
|
|
6114
|
+
req = { ...req, session: null };
|
|
6115
|
+
degraded = true;
|
|
6116
|
+
if (hooks?.fresh) {
|
|
6117
|
+
const recomposed = await hooks.fresh("session_start_failed");
|
|
6118
|
+
if (signal.aborted) return;
|
|
6119
|
+
if (recomposed) {
|
|
6120
|
+
req = { ...req, ...recomposed, session: null };
|
|
6121
|
+
degraded = false;
|
|
6122
|
+
}
|
|
6123
|
+
}
|
|
6124
|
+
}
|
|
6064
6125
|
}
|
|
6065
|
-
const result = await transport.run(spec, signal);
|
|
6066
|
-
if (signal.aborted) return;
|
|
6067
|
-
yield* decodeCodexStream(result.events, {
|
|
6068
|
-
signal,
|
|
6069
|
-
cwd: req.local.cwd,
|
|
6070
|
-
resumedThreadId: resumeThreadId,
|
|
6071
|
-
degraded,
|
|
6072
|
-
// Which segments the thread carries once this turn lands. A segment sent is that one —
|
|
6073
|
-
// the later copy is what the model reads. One withheld is what the thread had. Read off
|
|
6074
|
-
// the spec, so the record can't disagree with what was sent.
|
|
6075
|
-
promptFingerprint: spec.preamble.core ? spec.fingerprints.core : threadStanding?.core ?? null,
|
|
6076
|
-
conversationFingerprint: spec.preamble.conversation ? spec.fingerprints.conversation : threadStanding?.conversation ?? null,
|
|
6077
|
-
compactions,
|
|
6078
|
-
// What the thread held before this turn, for the write at `thread.started`.
|
|
6079
|
-
heldStanding: {
|
|
6080
|
-
promptFingerprint: threadStanding?.core ?? null,
|
|
6081
|
-
conversationFingerprint: threadStanding?.conversation ?? null,
|
|
6082
|
-
compactions: threadStanding ? compactions : null
|
|
6083
|
-
},
|
|
6084
|
-
storedState: req.session,
|
|
6085
|
-
usageBaseline: threadUsageBaseline,
|
|
6086
|
-
// Codex reports no model in-stream, so record what the thread was started with (null on the
|
|
6087
|
-
// default token). Same for the reasoning effort.
|
|
6088
|
-
resolvedModel: spec.model,
|
|
6089
|
-
resolvedReasoningEffort: spec.modelReasoningEffort ?? null
|
|
6090
|
-
});
|
|
6091
6126
|
} finally {
|
|
6092
6127
|
if (images) {
|
|
6093
6128
|
try {
|
package/dist/runtime.js
CHANGED
|
@@ -6158,6 +6158,10 @@ function createSdkCodexTransport(opts = {}) {
|
|
|
6158
6158
|
}
|
|
6159
6159
|
|
|
6160
6160
|
// packages/agent-runtime/src/codex/index.ts
|
|
6161
|
+
function isMissingRollout(err) {
|
|
6162
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
6163
|
+
return /no rollout found for thread id/i.test(message);
|
|
6164
|
+
}
|
|
6161
6165
|
function createCodexAdapter(deps = {}) {
|
|
6162
6166
|
const transport = deps.transport ?? (deps.enabled ? createSdkCodexTransport({ ...deps.apiKey ? { apiKey: deps.apiKey } : {} }) : null);
|
|
6163
6167
|
return {
|
|
@@ -6176,8 +6180,8 @@ function createCodexAdapter(deps = {}) {
|
|
|
6176
6180
|
}
|
|
6177
6181
|
const directory = req.local.cwd ?? "";
|
|
6178
6182
|
const decision = decideResume3(req.session, directory);
|
|
6179
|
-
|
|
6180
|
-
|
|
6183
|
+
let resumeThreadId = "resume" in decision ? decision.resume : null;
|
|
6184
|
+
let threadUsageBaseline = "resume" in decision ? decision.usageBaseline : null;
|
|
6181
6185
|
if ("fresh" in decision && decision.reason === "cwd_mismatch") {
|
|
6182
6186
|
deps.onWarn?.(
|
|
6183
6187
|
"codex adapter: stored session directory no longer matches the current environment \u2014 starting a fresh thread (SJ527-analogue guard)",
|
|
@@ -6242,38 +6246,69 @@ function createCodexAdapter(deps = {}) {
|
|
|
6242
6246
|
}
|
|
6243
6247
|
if (signal.aborted) return;
|
|
6244
6248
|
}
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
model
|
|
6249
|
-
|
|
6249
|
+
for (; ; ) {
|
|
6250
|
+
const spec = buildRunSpec2(req, resumeThreadId, threadStanding, images?.paths ?? []);
|
|
6251
|
+
if (spec.model === null) {
|
|
6252
|
+
deps.onWarn?.("Codex is using its default model because no model was resolved", {
|
|
6253
|
+
model: req.config.model
|
|
6254
|
+
});
|
|
6255
|
+
}
|
|
6256
|
+
let emitted = false;
|
|
6257
|
+
try {
|
|
6258
|
+
const result = await transport.run(spec, signal);
|
|
6259
|
+
if (signal.aborted) return;
|
|
6260
|
+
for await (const event of decodeCodexStream(result.events, {
|
|
6261
|
+
signal,
|
|
6262
|
+
cwd: req.local.cwd,
|
|
6263
|
+
resumedThreadId: resumeThreadId,
|
|
6264
|
+
degraded,
|
|
6265
|
+
// Which segments the thread carries once this turn lands. A segment sent is that one —
|
|
6266
|
+
// the later copy is what the model reads. One withheld is what the thread had. Read off
|
|
6267
|
+
// the spec, so the record can't disagree with what was sent.
|
|
6268
|
+
promptFingerprint: spec.preamble.core ? spec.fingerprints.core : threadStanding?.core ?? null,
|
|
6269
|
+
conversationFingerprint: spec.preamble.conversation ? spec.fingerprints.conversation : threadStanding?.conversation ?? null,
|
|
6270
|
+
compactions,
|
|
6271
|
+
// What the thread held before this turn, for the write at `thread.started`.
|
|
6272
|
+
heldStanding: {
|
|
6273
|
+
promptFingerprint: threadStanding?.core ?? null,
|
|
6274
|
+
conversationFingerprint: threadStanding?.conversation ?? null,
|
|
6275
|
+
compactions: threadStanding ? compactions : null
|
|
6276
|
+
},
|
|
6277
|
+
storedState: req.session,
|
|
6278
|
+
usageBaseline: threadUsageBaseline,
|
|
6279
|
+
// Codex reports no model in-stream, so record what the thread was started with (null on the
|
|
6280
|
+
// default token). Same for the reasoning effort.
|
|
6281
|
+
resolvedModel: spec.model,
|
|
6282
|
+
resolvedReasoningEffort: spec.modelReasoningEffort ?? null
|
|
6283
|
+
})) {
|
|
6284
|
+
emitted = true;
|
|
6285
|
+
yield event;
|
|
6286
|
+
}
|
|
6287
|
+
return;
|
|
6288
|
+
} catch (err) {
|
|
6289
|
+
if (resumeThreadId === null || emitted || signal.aborted || !isMissingRollout(err)) {
|
|
6290
|
+
throw err;
|
|
6291
|
+
}
|
|
6292
|
+
deps.onWarn?.(
|
|
6293
|
+
"codex adapter: the stored thread has no rollout on this host \u2014 starting a fresh thread",
|
|
6294
|
+
{ threadId: resumeThreadId }
|
|
6295
|
+
);
|
|
6296
|
+
resumeThreadId = null;
|
|
6297
|
+
threadUsageBaseline = null;
|
|
6298
|
+
threadStanding = null;
|
|
6299
|
+
compactions = 0;
|
|
6300
|
+
req = { ...req, session: null };
|
|
6301
|
+
degraded = true;
|
|
6302
|
+
if (hooks?.fresh) {
|
|
6303
|
+
const recomposed = await hooks.fresh("session_start_failed");
|
|
6304
|
+
if (signal.aborted) return;
|
|
6305
|
+
if (recomposed) {
|
|
6306
|
+
req = { ...req, ...recomposed, session: null };
|
|
6307
|
+
degraded = false;
|
|
6308
|
+
}
|
|
6309
|
+
}
|
|
6310
|
+
}
|
|
6250
6311
|
}
|
|
6251
|
-
const result = await transport.run(spec, signal);
|
|
6252
|
-
if (signal.aborted) return;
|
|
6253
|
-
yield* decodeCodexStream(result.events, {
|
|
6254
|
-
signal,
|
|
6255
|
-
cwd: req.local.cwd,
|
|
6256
|
-
resumedThreadId: resumeThreadId,
|
|
6257
|
-
degraded,
|
|
6258
|
-
// Which segments the thread carries once this turn lands. A segment sent is that one —
|
|
6259
|
-
// the later copy is what the model reads. One withheld is what the thread had. Read off
|
|
6260
|
-
// the spec, so the record can't disagree with what was sent.
|
|
6261
|
-
promptFingerprint: spec.preamble.core ? spec.fingerprints.core : threadStanding?.core ?? null,
|
|
6262
|
-
conversationFingerprint: spec.preamble.conversation ? spec.fingerprints.conversation : threadStanding?.conversation ?? null,
|
|
6263
|
-
compactions,
|
|
6264
|
-
// What the thread held before this turn, for the write at `thread.started`.
|
|
6265
|
-
heldStanding: {
|
|
6266
|
-
promptFingerprint: threadStanding?.core ?? null,
|
|
6267
|
-
conversationFingerprint: threadStanding?.conversation ?? null,
|
|
6268
|
-
compactions: threadStanding ? compactions : null
|
|
6269
|
-
},
|
|
6270
|
-
storedState: req.session,
|
|
6271
|
-
usageBaseline: threadUsageBaseline,
|
|
6272
|
-
// Codex reports no model in-stream, so record what the thread was started with (null on the
|
|
6273
|
-
// default token). Same for the reasoning effort.
|
|
6274
|
-
resolvedModel: spec.model,
|
|
6275
|
-
resolvedReasoningEffort: spec.modelReasoningEffort ?? null
|
|
6276
|
-
});
|
|
6277
6312
|
} finally {
|
|
6278
6313
|
if (images) {
|
|
6279
6314
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cabane/companion",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.190",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The Cabane Companion (headless): connect an agent on your machine to your Cabane workspace as a responder — drive work against your own codebase, files, and MCP servers without putting any of it in Cabane.",
|
|
6
6
|
"license": "UNLICENSED",
|