@cabane/companion 0.6.15 → 0.6.16
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 +87 -41
- package/dist/runtime.js +87 -41
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4918,6 +4918,7 @@ function parseCodexModel(model) {
|
|
|
4918
4918
|
var CABANE_MCP_SERVER3 = "cabane";
|
|
4919
4919
|
var TURN_CONTROL_MCP_SERVER2 = "cabane_companion";
|
|
4920
4920
|
var ACTIVE_CONVERSATION_HEADER4 = "x-cabane-active-conversation";
|
|
4921
|
+
var ENV_ENVELOPE_KEYS = ["CABANE_ENV_TIER", "CABANE_ENV_KEY", "CABANE_ENV_BINDING"];
|
|
4921
4922
|
function buildRunSpec2(req, resumeThreadId, instructionsFile = null) {
|
|
4922
4923
|
const { policy, config } = req;
|
|
4923
4924
|
const directory = req.local.cwd ?? "";
|
|
@@ -5004,6 +5005,12 @@ function buildConfig(req, baseInstructionsFile) {
|
|
|
5004
5005
|
}
|
|
5005
5006
|
const policy = codexToolPolicy(req.policy);
|
|
5006
5007
|
const tmpDir = req.local.env?.TMPDIR;
|
|
5008
|
+
const shellEnv = {};
|
|
5009
|
+
if (tmpDir) shellEnv.TMPDIR = tmpDir;
|
|
5010
|
+
for (const key of ENV_ENVELOPE_KEYS) {
|
|
5011
|
+
const value = req.local.env?.[key];
|
|
5012
|
+
if (value !== void 0) shellEnv[key] = value;
|
|
5013
|
+
}
|
|
5007
5014
|
const gateLockDir = req.local.env?.CABANE_GATE_LOCK_DIR;
|
|
5008
5015
|
return {
|
|
5009
5016
|
mcp_servers,
|
|
@@ -5012,7 +5019,7 @@ function buildConfig(req, baseInstructionsFile) {
|
|
|
5012
5019
|
// becomes Codex's base instructions, and Codex's own environment preamble goes
|
|
5013
5020
|
// with the harness prompt it belonged to.
|
|
5014
5021
|
...baseInstructionsFile ? { model_instructions_file: baseInstructionsFile, include_environment_context: false } : {},
|
|
5015
|
-
...
|
|
5022
|
+
...Object.keys(shellEnv).length ? { shell_environment_policy: { set: shellEnv } } : {},
|
|
5016
5023
|
...policy.permissionProfile ? {
|
|
5017
5024
|
// CT733: named permission profiles are Codex's split-filesystem path.
|
|
5018
5025
|
// `:root = read` preserves coding-mode host reads; the one explicit
|
|
@@ -7581,6 +7588,8 @@ ${reason}`,
|
|
|
7581
7588
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7582
7589
|
event: "settled",
|
|
7583
7590
|
turnId,
|
|
7591
|
+
agentId: payload.agentId,
|
|
7592
|
+
conversationId: payload.conversationId,
|
|
7584
7593
|
ok,
|
|
7585
7594
|
reason
|
|
7586
7595
|
})}
|
|
@@ -7595,50 +7604,63 @@ ${reason}`,
|
|
|
7595
7604
|
}
|
|
7596
7605
|
};
|
|
7597
7606
|
if (prepareHook && hookEnv?.CABANE_TASK_ID) {
|
|
7598
|
-
const proof = await proveWorkspaceTools(request, adapter.name, {
|
|
7599
|
-
...this.opts.workspaceProofFetch ? { fetchImpl: this.opts.workspaceProofFetch } : {},
|
|
7600
|
-
harnessFingerprint: turnContext.runtime
|
|
7601
|
-
});
|
|
7602
7607
|
const checkout = checkoutState(effectiveCwd);
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
);
|
|
7607
|
-
if (effectiveCwd && checkout.ok) {
|
|
7608
|
+
if (!effectiveCwd || !checkout.ok) {
|
|
7609
|
+
const reason = `checkout_missing: ${checkout.reason}; task=${hookEnv.CABANE_TASK_ID}; recovery=re-dispatch this conversation (the prepare hook re-provisions the environment)`;
|
|
7610
|
+
turnLog.error({ checkout: effectiveCwd ?? null, checkoutState: checkout }, reason);
|
|
7608
7611
|
try {
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
taskId: hookEnv.CABANE_TASK_ID,
|
|
7617
|
-
binding: hookEnv.CABANE_TASK_BINDING ?? null,
|
|
7618
|
-
checkout: effectiveCwd,
|
|
7619
|
-
classification: proof.ok ? "ready" : "workspace_tools_missing",
|
|
7620
|
-
failedCapability: proof.failedCapability,
|
|
7621
|
-
workspaceTools: proof,
|
|
7622
|
-
// CT1022: the two fields the environment reaper reads — which turn
|
|
7623
|
-
// this is (so its settle can be matched among interleaved agents)
|
|
7624
|
-
// and how long it may legitimately run (so an unclosed receipt
|
|
7625
|
-
// expires on this turn's real deadline, not the reaper's guess).
|
|
7626
|
-
turnId,
|
|
7627
|
-
totalTimeoutMs
|
|
7628
|
-
})}
|
|
7629
|
-
`,
|
|
7630
|
-
{ mode: 384 }
|
|
7631
|
-
);
|
|
7632
|
-
turnReceiptPath = receiptPath;
|
|
7633
|
-
} catch (error) {
|
|
7612
|
+
await this.opts.api.postTurnMessage(workspaceId, payload.conversationId, {
|
|
7613
|
+
body: `**Couldn't prepare your environment.** ${reason}`,
|
|
7614
|
+
kind: "final",
|
|
7615
|
+
turnId,
|
|
7616
|
+
parentMessageId: payload.messageId
|
|
7617
|
+
});
|
|
7618
|
+
} catch (postErr) {
|
|
7634
7619
|
turnLog.warn(
|
|
7635
|
-
{ err:
|
|
7636
|
-
"dispatcher:
|
|
7620
|
+
{ err: postErr instanceof Error ? postErr.message : String(postErr) },
|
|
7621
|
+
"dispatcher: checkout-missing notice post failed"
|
|
7637
7622
|
);
|
|
7638
7623
|
}
|
|
7624
|
+
return this.concludeBeforeRun(payload, turnLog, startedAt, reason);
|
|
7639
7625
|
}
|
|
7640
|
-
|
|
7641
|
-
|
|
7626
|
+
const receiptPath = join13(effectiveCwd, ".git", "cabane", "readiness.jsonl");
|
|
7627
|
+
const receiptLine = (fields) => `${JSON.stringify({
|
|
7628
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7629
|
+
taskId: hookEnv.CABANE_TASK_ID,
|
|
7630
|
+
binding: hookEnv.CABANE_TASK_BINDING ?? null,
|
|
7631
|
+
checkout: effectiveCwd,
|
|
7632
|
+
// CT1022: the two fields the environment reaper reads — which turn this
|
|
7633
|
+
// is (so its settle can be matched among interleaved agents) and how long
|
|
7634
|
+
// it may legitimately run (so an unclosed receipt expires on this turn's
|
|
7635
|
+
// real deadline, not the reaper's guess).
|
|
7636
|
+
turnId,
|
|
7637
|
+
totalTimeoutMs,
|
|
7638
|
+
// CT1062: WHOSE turn. A task env is shared — between agents, and between
|
|
7639
|
+
// an agent's own sequential conversations — so a reader asking "is a turn
|
|
7640
|
+
// of THIS agent, other than mine, running here?" (the host's run-lock
|
|
7641
|
+
// does, before it lets a second conversation into the tree) can only
|
|
7642
|
+
// answer it if the line says who. An unattributed open line has to count
|
|
7643
|
+
// for everyone, which refuses work that should have been admitted.
|
|
7644
|
+
agentId: payload.agentId,
|
|
7645
|
+
conversationId: payload.conversationId,
|
|
7646
|
+
...fields
|
|
7647
|
+
})}
|
|
7648
|
+
`;
|
|
7649
|
+
try {
|
|
7650
|
+
mkdirSync10(join13(effectiveCwd, ".git", "cabane"), { recursive: true });
|
|
7651
|
+
appendFileSync2(
|
|
7652
|
+
receiptPath,
|
|
7653
|
+
// `starting` is the honest classification before the proof has run. The
|
|
7654
|
+
// line the proof appends below carries the same `turnId`, so a reader
|
|
7655
|
+
// replaying the file sees one turn, not two.
|
|
7656
|
+
receiptLine({ classification: "starting" }),
|
|
7657
|
+
{ mode: 384 }
|
|
7658
|
+
);
|
|
7659
|
+
turnReceiptPath = receiptPath;
|
|
7660
|
+
} catch (error) {
|
|
7661
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
7662
|
+
const reason = `turn_receipt_unwritable: ${detail}; task=${hookEnv.CABANE_TASK_ID}; checkout=${effectiveCwd}; recovery=restore write access to the checkout's .git/cabane, then re-dispatch`;
|
|
7663
|
+
turnLog.error({ err: detail, receiptPath }, reason);
|
|
7642
7664
|
try {
|
|
7643
7665
|
await this.opts.api.postTurnMessage(workspaceId, payload.conversationId, {
|
|
7644
7666
|
body: `**Couldn't prepare your environment.** ${reason}`,
|
|
@@ -7649,13 +7671,37 @@ ${reason}`,
|
|
|
7649
7671
|
} catch (postErr) {
|
|
7650
7672
|
turnLog.warn(
|
|
7651
7673
|
{ err: postErr instanceof Error ? postErr.message : String(postErr) },
|
|
7652
|
-
"dispatcher:
|
|
7674
|
+
"dispatcher: turn-receipt failure notice post failed"
|
|
7653
7675
|
);
|
|
7654
7676
|
}
|
|
7655
7677
|
return this.concludeBeforeRun(payload, turnLog, startedAt, reason);
|
|
7656
7678
|
}
|
|
7679
|
+
const proof = await proveWorkspaceTools(request, adapter.name, {
|
|
7680
|
+
...this.opts.workspaceProofFetch ? { fetchImpl: this.opts.workspaceProofFetch } : {},
|
|
7681
|
+
harnessFingerprint: turnContext.runtime
|
|
7682
|
+
});
|
|
7683
|
+
turnLog[proof.ok ? "info" : "error"](
|
|
7684
|
+
{ workspaceProof: proof, checkout: effectiveCwd },
|
|
7685
|
+
`dispatcher: workspace tool proof ${proof.ok ? "passed" : "failed"}, checkout usable`
|
|
7686
|
+
);
|
|
7687
|
+
try {
|
|
7688
|
+
appendFileSync2(
|
|
7689
|
+
receiptPath,
|
|
7690
|
+
receiptLine({
|
|
7691
|
+
classification: proof.ok ? "ready" : "workspace_tools_missing",
|
|
7692
|
+
failedCapability: proof.failedCapability,
|
|
7693
|
+
workspaceTools: proof
|
|
7694
|
+
}),
|
|
7695
|
+
{ mode: 384 }
|
|
7696
|
+
);
|
|
7697
|
+
} catch (error) {
|
|
7698
|
+
turnLog.warn(
|
|
7699
|
+
{ err: error instanceof Error ? error.message : String(error) },
|
|
7700
|
+
"dispatcher: workspace-proof diagnostic write failed (the turn receipt is open)"
|
|
7701
|
+
);
|
|
7702
|
+
}
|
|
7657
7703
|
if (!proof.ok) {
|
|
7658
|
-
const reason = `workspace_tools_missing: ${proof.failedCapability}; checkout=${effectiveCwd
|
|
7704
|
+
const reason = `workspace_tools_missing: ${proof.failedCapability}; checkout=${effectiveCwd}; runtime=${adapter.name}; recovery=restart the connector after restoring the Cabane workspace tool mount`;
|
|
7659
7705
|
closeTurnReceipt(false, reason);
|
|
7660
7706
|
try {
|
|
7661
7707
|
await this.opts.api.postTurnMessage(workspaceId, payload.conversationId, {
|
package/dist/runtime.js
CHANGED
|
@@ -4571,6 +4571,7 @@ function parseCodexModel(model) {
|
|
|
4571
4571
|
var CABANE_MCP_SERVER3 = "cabane";
|
|
4572
4572
|
var TURN_CONTROL_MCP_SERVER2 = "cabane_companion";
|
|
4573
4573
|
var ACTIVE_CONVERSATION_HEADER4 = "x-cabane-active-conversation";
|
|
4574
|
+
var ENV_ENVELOPE_KEYS = ["CABANE_ENV_TIER", "CABANE_ENV_KEY", "CABANE_ENV_BINDING"];
|
|
4574
4575
|
function buildRunSpec2(req, resumeThreadId, instructionsFile = null) {
|
|
4575
4576
|
const { policy, config } = req;
|
|
4576
4577
|
const directory = req.local.cwd ?? "";
|
|
@@ -4657,6 +4658,12 @@ function buildConfig(req, baseInstructionsFile) {
|
|
|
4657
4658
|
}
|
|
4658
4659
|
const policy = codexToolPolicy(req.policy);
|
|
4659
4660
|
const tmpDir = req.local.env?.TMPDIR;
|
|
4661
|
+
const shellEnv = {};
|
|
4662
|
+
if (tmpDir) shellEnv.TMPDIR = tmpDir;
|
|
4663
|
+
for (const key of ENV_ENVELOPE_KEYS) {
|
|
4664
|
+
const value = req.local.env?.[key];
|
|
4665
|
+
if (value !== void 0) shellEnv[key] = value;
|
|
4666
|
+
}
|
|
4660
4667
|
const gateLockDir = req.local.env?.CABANE_GATE_LOCK_DIR;
|
|
4661
4668
|
return {
|
|
4662
4669
|
mcp_servers,
|
|
@@ -4665,7 +4672,7 @@ function buildConfig(req, baseInstructionsFile) {
|
|
|
4665
4672
|
// becomes Codex's base instructions, and Codex's own environment preamble goes
|
|
4666
4673
|
// with the harness prompt it belonged to.
|
|
4667
4674
|
...baseInstructionsFile ? { model_instructions_file: baseInstructionsFile, include_environment_context: false } : {},
|
|
4668
|
-
...
|
|
4675
|
+
...Object.keys(shellEnv).length ? { shell_environment_policy: { set: shellEnv } } : {},
|
|
4669
4676
|
...policy.permissionProfile ? {
|
|
4670
4677
|
// CT733: named permission profiles are Codex's split-filesystem path.
|
|
4671
4678
|
// `:root = read` preserves coding-mode host reads; the one explicit
|
|
@@ -7234,6 +7241,8 @@ ${reason}`,
|
|
|
7234
7241
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7235
7242
|
event: "settled",
|
|
7236
7243
|
turnId,
|
|
7244
|
+
agentId: payload.agentId,
|
|
7245
|
+
conversationId: payload.conversationId,
|
|
7237
7246
|
ok,
|
|
7238
7247
|
reason
|
|
7239
7248
|
})}
|
|
@@ -7248,50 +7257,63 @@ ${reason}`,
|
|
|
7248
7257
|
}
|
|
7249
7258
|
};
|
|
7250
7259
|
if (prepareHook && hookEnv?.CABANE_TASK_ID) {
|
|
7251
|
-
const proof = await proveWorkspaceTools(request, adapter.name, {
|
|
7252
|
-
...this.opts.workspaceProofFetch ? { fetchImpl: this.opts.workspaceProofFetch } : {},
|
|
7253
|
-
harnessFingerprint: turnContext.runtime
|
|
7254
|
-
});
|
|
7255
7260
|
const checkout = checkoutState(effectiveCwd);
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
);
|
|
7260
|
-
if (effectiveCwd && checkout.ok) {
|
|
7261
|
+
if (!effectiveCwd || !checkout.ok) {
|
|
7262
|
+
const reason = `checkout_missing: ${checkout.reason}; task=${hookEnv.CABANE_TASK_ID}; recovery=re-dispatch this conversation (the prepare hook re-provisions the environment)`;
|
|
7263
|
+
turnLog.error({ checkout: effectiveCwd ?? null, checkoutState: checkout }, reason);
|
|
7261
7264
|
try {
|
|
7262
|
-
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7267
|
-
|
|
7268
|
-
|
|
7269
|
-
taskId: hookEnv.CABANE_TASK_ID,
|
|
7270
|
-
binding: hookEnv.CABANE_TASK_BINDING ?? null,
|
|
7271
|
-
checkout: effectiveCwd,
|
|
7272
|
-
classification: proof.ok ? "ready" : "workspace_tools_missing",
|
|
7273
|
-
failedCapability: proof.failedCapability,
|
|
7274
|
-
workspaceTools: proof,
|
|
7275
|
-
// CT1022: the two fields the environment reaper reads — which turn
|
|
7276
|
-
// this is (so its settle can be matched among interleaved agents)
|
|
7277
|
-
// and how long it may legitimately run (so an unclosed receipt
|
|
7278
|
-
// expires on this turn's real deadline, not the reaper's guess).
|
|
7279
|
-
turnId,
|
|
7280
|
-
totalTimeoutMs
|
|
7281
|
-
})}
|
|
7282
|
-
`,
|
|
7283
|
-
{ mode: 384 }
|
|
7284
|
-
);
|
|
7285
|
-
turnReceiptPath = receiptPath;
|
|
7286
|
-
} catch (error) {
|
|
7265
|
+
await this.opts.api.postTurnMessage(workspaceId, payload.conversationId, {
|
|
7266
|
+
body: `**Couldn't prepare your environment.** ${reason}`,
|
|
7267
|
+
kind: "final",
|
|
7268
|
+
turnId,
|
|
7269
|
+
parentMessageId: payload.messageId
|
|
7270
|
+
});
|
|
7271
|
+
} catch (postErr) {
|
|
7287
7272
|
turnLog.warn(
|
|
7288
|
-
{ err:
|
|
7289
|
-
"dispatcher:
|
|
7273
|
+
{ err: postErr instanceof Error ? postErr.message : String(postErr) },
|
|
7274
|
+
"dispatcher: checkout-missing notice post failed"
|
|
7290
7275
|
);
|
|
7291
7276
|
}
|
|
7277
|
+
return this.concludeBeforeRun(payload, turnLog, startedAt, reason);
|
|
7292
7278
|
}
|
|
7293
|
-
|
|
7294
|
-
|
|
7279
|
+
const receiptPath = join13(effectiveCwd, ".git", "cabane", "readiness.jsonl");
|
|
7280
|
+
const receiptLine = (fields) => `${JSON.stringify({
|
|
7281
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7282
|
+
taskId: hookEnv.CABANE_TASK_ID,
|
|
7283
|
+
binding: hookEnv.CABANE_TASK_BINDING ?? null,
|
|
7284
|
+
checkout: effectiveCwd,
|
|
7285
|
+
// CT1022: the two fields the environment reaper reads — which turn this
|
|
7286
|
+
// is (so its settle can be matched among interleaved agents) and how long
|
|
7287
|
+
// it may legitimately run (so an unclosed receipt expires on this turn's
|
|
7288
|
+
// real deadline, not the reaper's guess).
|
|
7289
|
+
turnId,
|
|
7290
|
+
totalTimeoutMs,
|
|
7291
|
+
// CT1062: WHOSE turn. A task env is shared — between agents, and between
|
|
7292
|
+
// an agent's own sequential conversations — so a reader asking "is a turn
|
|
7293
|
+
// of THIS agent, other than mine, running here?" (the host's run-lock
|
|
7294
|
+
// does, before it lets a second conversation into the tree) can only
|
|
7295
|
+
// answer it if the line says who. An unattributed open line has to count
|
|
7296
|
+
// for everyone, which refuses work that should have been admitted.
|
|
7297
|
+
agentId: payload.agentId,
|
|
7298
|
+
conversationId: payload.conversationId,
|
|
7299
|
+
...fields
|
|
7300
|
+
})}
|
|
7301
|
+
`;
|
|
7302
|
+
try {
|
|
7303
|
+
mkdirSync9(join13(effectiveCwd, ".git", "cabane"), { recursive: true });
|
|
7304
|
+
appendFileSync2(
|
|
7305
|
+
receiptPath,
|
|
7306
|
+
// `starting` is the honest classification before the proof has run. The
|
|
7307
|
+
// line the proof appends below carries the same `turnId`, so a reader
|
|
7308
|
+
// replaying the file sees one turn, not two.
|
|
7309
|
+
receiptLine({ classification: "starting" }),
|
|
7310
|
+
{ mode: 384 }
|
|
7311
|
+
);
|
|
7312
|
+
turnReceiptPath = receiptPath;
|
|
7313
|
+
} catch (error) {
|
|
7314
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
7315
|
+
const reason = `turn_receipt_unwritable: ${detail}; task=${hookEnv.CABANE_TASK_ID}; checkout=${effectiveCwd}; recovery=restore write access to the checkout's .git/cabane, then re-dispatch`;
|
|
7316
|
+
turnLog.error({ err: detail, receiptPath }, reason);
|
|
7295
7317
|
try {
|
|
7296
7318
|
await this.opts.api.postTurnMessage(workspaceId, payload.conversationId, {
|
|
7297
7319
|
body: `**Couldn't prepare your environment.** ${reason}`,
|
|
@@ -7302,13 +7324,37 @@ ${reason}`,
|
|
|
7302
7324
|
} catch (postErr) {
|
|
7303
7325
|
turnLog.warn(
|
|
7304
7326
|
{ err: postErr instanceof Error ? postErr.message : String(postErr) },
|
|
7305
|
-
"dispatcher:
|
|
7327
|
+
"dispatcher: turn-receipt failure notice post failed"
|
|
7306
7328
|
);
|
|
7307
7329
|
}
|
|
7308
7330
|
return this.concludeBeforeRun(payload, turnLog, startedAt, reason);
|
|
7309
7331
|
}
|
|
7332
|
+
const proof = await proveWorkspaceTools(request, adapter.name, {
|
|
7333
|
+
...this.opts.workspaceProofFetch ? { fetchImpl: this.opts.workspaceProofFetch } : {},
|
|
7334
|
+
harnessFingerprint: turnContext.runtime
|
|
7335
|
+
});
|
|
7336
|
+
turnLog[proof.ok ? "info" : "error"](
|
|
7337
|
+
{ workspaceProof: proof, checkout: effectiveCwd },
|
|
7338
|
+
`dispatcher: workspace tool proof ${proof.ok ? "passed" : "failed"}, checkout usable`
|
|
7339
|
+
);
|
|
7340
|
+
try {
|
|
7341
|
+
appendFileSync2(
|
|
7342
|
+
receiptPath,
|
|
7343
|
+
receiptLine({
|
|
7344
|
+
classification: proof.ok ? "ready" : "workspace_tools_missing",
|
|
7345
|
+
failedCapability: proof.failedCapability,
|
|
7346
|
+
workspaceTools: proof
|
|
7347
|
+
}),
|
|
7348
|
+
{ mode: 384 }
|
|
7349
|
+
);
|
|
7350
|
+
} catch (error) {
|
|
7351
|
+
turnLog.warn(
|
|
7352
|
+
{ err: error instanceof Error ? error.message : String(error) },
|
|
7353
|
+
"dispatcher: workspace-proof diagnostic write failed (the turn receipt is open)"
|
|
7354
|
+
);
|
|
7355
|
+
}
|
|
7310
7356
|
if (!proof.ok) {
|
|
7311
|
-
const reason = `workspace_tools_missing: ${proof.failedCapability}; checkout=${effectiveCwd
|
|
7357
|
+
const reason = `workspace_tools_missing: ${proof.failedCapability}; checkout=${effectiveCwd}; runtime=${adapter.name}; recovery=restart the connector after restoring the Cabane workspace tool mount`;
|
|
7312
7358
|
closeTurnReceipt(false, reason);
|
|
7313
7359
|
try {
|
|
7314
7360
|
await this.opts.api.postTurnMessage(workspaceId, payload.conversationId, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cabane/companion",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The Cabane Companion (headless): connect a coding 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",
|