@cabane/companion 0.6.51 → 0.6.53

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 CHANGED
@@ -232,6 +232,9 @@ function realAccountHome() {
232
232
  }
233
233
  return realHomeCache;
234
234
  }
235
+ function agentCompanionHome() {
236
+ return join(cabaneDir(), "agent-home");
237
+ }
235
238
  function cabaneDir() {
236
239
  const dir2 = join(process.env.CABANE_COMPANION_HOME || homedir(), ".cabane");
237
240
  if (process.env.VITEST) {
@@ -5530,6 +5533,7 @@ function readToolItem(item, eventType) {
5530
5533
  if (type === "mcp_tool_call") {
5531
5534
  const tool2 = str(item.tool) ?? "tool";
5532
5535
  const server = str(item.server);
5536
+ const result = readMcpResult(item.result);
5533
5537
  return {
5534
5538
  id,
5535
5539
  // A cabane tool reads best as its bare verb (`read`); a non-cabane server's
@@ -5537,7 +5541,7 @@ function readToolItem(item, eventType) {
5537
5541
  name: server && server !== "cabane" ? `${server}.${tool2}` : tool2,
5538
5542
  input: item.arguments,
5539
5543
  status: toStatus(item.status),
5540
- ...item.status === "completed" ? { result: readMcpResult(item.result) } : item.status === "failed" ? { result: readMcpError(item.error) } : {}
5544
+ ...item.status === "completed" ? { result } : item.status === "failed" ? { result: hasMcpReceipt(result) ? result : readMcpError(item.error) } : {}
5541
5545
  };
5542
5546
  }
5543
5547
  if (type === "web_search") {
@@ -5577,9 +5581,38 @@ function toStatus(v) {
5577
5581
  }
5578
5582
  function readMcpResult(result) {
5579
5583
  const rec2 = asRecord2(result);
5580
- if (rec2 && "content" in rec2) return rec2.content;
5584
+ if (!rec2) return result;
5585
+ if (hasOnlyNonTextContentBlocks(rec2.content)) return rec2.content;
5586
+ if (rec2.structured_content !== void 0 && rec2.structured_content !== null) {
5587
+ return rec2.structured_content;
5588
+ }
5589
+ if (rec2.structuredContent !== void 0 && rec2.structuredContent !== null) {
5590
+ return rec2.structuredContent;
5591
+ }
5592
+ if ("content" in rec2) return rec2.content;
5581
5593
  return result;
5582
5594
  }
5595
+ function hasOnlyNonTextContentBlocks(content) {
5596
+ if (!Array.isArray(content) || content.length === 0) return false;
5597
+ let sawTypedBlock = false;
5598
+ for (const raw of content) {
5599
+ const block = asRecord2(raw);
5600
+ const type = block && str(block.type);
5601
+ if (!type) continue;
5602
+ sawTypedBlock = true;
5603
+ if (type === "text" && typeof block?.text === "string" && block.text.trim().length > 0) {
5604
+ return false;
5605
+ }
5606
+ }
5607
+ return sawTypedBlock;
5608
+ }
5609
+ function hasMcpReceipt(result) {
5610
+ if (result === void 0 || result === null) return false;
5611
+ if (typeof result === "string") return result.trim().length > 0;
5612
+ if (Array.isArray(result)) return result.length > 0;
5613
+ if (typeof result === "object") return Object.keys(result).length > 0;
5614
+ return true;
5615
+ }
5583
5616
  function readMcpError(error) {
5584
5617
  const rec2 = asRecord2(error);
5585
5618
  return rec2 && str(rec2.message) || "error";
@@ -6103,6 +6136,25 @@ var errorItem = (id, message) => ({
6103
6136
  type: "item.completed",
6104
6137
  item: { id, type: "error", message }
6105
6138
  });
6139
+ var SDK_SUCCESS = { ok: true, result: { source: "native" }, logs: "", truncated: false };
6140
+ var SDK_FAILURE = {
6141
+ ok: false,
6142
+ result: null,
6143
+ preview: '{"rows":[1,2,3]}',
6144
+ logs: "",
6145
+ truncated: false,
6146
+ error: { kind: "output_too_large", bytes: 169167, limit: 65536 },
6147
+ warnings: [],
6148
+ committed: {
6149
+ calls: [
6150
+ {
6151
+ method: "conversations.update",
6152
+ args: { id: "conv-1", opts: { title: "Renamed before failure" } }
6153
+ }
6154
+ ]
6155
+ },
6156
+ inFlight: null
6157
+ };
6106
6158
  var sessionEvent3 = (threadId, cwd = DIR2, degraded = false, promptFingerprint = fingerprintPrompt(PROMPT)) => ({
6107
6159
  type: "session",
6108
6160
  state: encodeSession3({ threadId, cwd, promptFingerprint }),
@@ -6182,6 +6234,194 @@ var CODEX_CONFORMANCE_FIXTURES = [
6182
6234
  { type: "result", ok: true }
6183
6235
  ]
6184
6236
  },
6237
+ {
6238
+ // CT1211: recorded SDK success shape. Codex exposes the text compatibility
6239
+ // copy and the native object together; normalization must keep the object.
6240
+ name: "MCP success prefers native structured content",
6241
+ request: makeRequest3(),
6242
+ nativeStream: [
6243
+ threadStarted(NEW_THREAD_ID),
6244
+ toolFrame("item.started", {
6245
+ id: "sdk-success",
6246
+ type: "mcp_tool_call",
6247
+ server: "cabane",
6248
+ tool: "sdk",
6249
+ arguments: { code: 'return { source: "native" }' },
6250
+ status: "in_progress"
6251
+ }),
6252
+ toolFrame("item.completed", {
6253
+ id: "sdk-success",
6254
+ type: "mcp_tool_call",
6255
+ server: "cabane",
6256
+ tool: "sdk",
6257
+ arguments: { code: 'return { source: "native" }' },
6258
+ status: "completed",
6259
+ result: {
6260
+ content: [{ type: "text", text: JSON.stringify(SDK_SUCCESS) }],
6261
+ structured_content: SDK_SUCCESS
6262
+ }
6263
+ }),
6264
+ turnCompleted()
6265
+ ],
6266
+ expected: [
6267
+ sessionEvent3(NEW_THREAD_ID),
6268
+ {
6269
+ type: "tool",
6270
+ id: "sdk-success",
6271
+ name: "sdk",
6272
+ phase: "start",
6273
+ summary: "",
6274
+ input: { code: 'return { source: "native" }' }
6275
+ },
6276
+ {
6277
+ type: "tool",
6278
+ id: "sdk-success",
6279
+ name: "sdk",
6280
+ phase: "done",
6281
+ summary: "",
6282
+ input: { code: 'return { source: "native" }' },
6283
+ result: SDK_SUCCESS
6284
+ },
6285
+ { type: "result", ok: true }
6286
+ ]
6287
+ },
6288
+ {
6289
+ // CT1211 incident shape: MCP `isError` keeps the failed phase, while the raw
6290
+ // camel-case structured payload survives instead of the generic `error` token.
6291
+ name: "failed SDK call preserves structured receipt while remaining error phase",
6292
+ request: makeRequest3(),
6293
+ nativeStream: [
6294
+ threadStarted(NEW_THREAD_ID),
6295
+ toolFrame("item.started", {
6296
+ id: "sdk-failed",
6297
+ type: "mcp_tool_call",
6298
+ server: "cabane",
6299
+ tool: "sdk",
6300
+ arguments: { code: "return largeResult" },
6301
+ status: "in_progress"
6302
+ }),
6303
+ toolFrame("item.completed", {
6304
+ id: "sdk-failed",
6305
+ type: "mcp_tool_call",
6306
+ server: "cabane",
6307
+ tool: "sdk",
6308
+ arguments: { code: "return largeResult" },
6309
+ status: "failed",
6310
+ result: {
6311
+ content: [{ type: "text", text: JSON.stringify(SDK_FAILURE) }],
6312
+ structuredContent: SDK_FAILURE,
6313
+ isError: true
6314
+ },
6315
+ error: { message: "error" }
6316
+ }),
6317
+ turnCompleted()
6318
+ ],
6319
+ expected: [
6320
+ sessionEvent3(NEW_THREAD_ID),
6321
+ {
6322
+ type: "tool",
6323
+ id: "sdk-failed",
6324
+ name: "sdk",
6325
+ phase: "start",
6326
+ summary: "",
6327
+ input: { code: "return largeResult" }
6328
+ },
6329
+ {
6330
+ type: "tool",
6331
+ id: "sdk-failed",
6332
+ name: "sdk",
6333
+ phase: "error",
6334
+ summary: "",
6335
+ input: { code: "return largeResult" },
6336
+ result: SDK_FAILURE
6337
+ },
6338
+ { type: "result", ok: true }
6339
+ ]
6340
+ },
6341
+ {
6342
+ // A transport/tool failure has no MCP result payload and still uses the real
6343
+ // adapter error message. CT1211 must not replace this fallback with `undefined`.
6344
+ name: "failed MCP call without result keeps error message fallback",
6345
+ request: makeRequest3(),
6346
+ nativeStream: [
6347
+ threadStarted(NEW_THREAD_ID),
6348
+ toolFrame("item.completed", {
6349
+ id: "mcp-failed",
6350
+ type: "mcp_tool_call",
6351
+ server: "other",
6352
+ tool: "lookup",
6353
+ arguments: { q: "receipt" },
6354
+ status: "failed",
6355
+ result: { content: [], isError: true },
6356
+ error: { message: "connection closed" }
6357
+ }),
6358
+ turnCompleted()
6359
+ ],
6360
+ expected: [
6361
+ sessionEvent3(NEW_THREAD_ID),
6362
+ {
6363
+ type: "tool",
6364
+ id: "mcp-failed",
6365
+ name: "other.lookup",
6366
+ phase: "start",
6367
+ summary: "receipt",
6368
+ input: { q: "receipt" }
6369
+ },
6370
+ {
6371
+ type: "tool",
6372
+ id: "mcp-failed",
6373
+ name: "other.lookup",
6374
+ phase: "error",
6375
+ summary: "receipt",
6376
+ input: { q: "receipt" },
6377
+ result: "connection closed"
6378
+ },
6379
+ { type: "result", ok: true }
6380
+ ]
6381
+ },
6382
+ {
6383
+ // CT1147 stays intact when a connector includes structured metadata beside an
6384
+ // image-only MCP response: no image/base64 payload enters activity receipts.
6385
+ name: "image-only MCP result remains empty despite structured metadata",
6386
+ request: makeRequest3(),
6387
+ nativeStream: [
6388
+ threadStarted(NEW_THREAD_ID),
6389
+ toolFrame("item.completed", {
6390
+ id: "mcp-image",
6391
+ type: "mcp_tool_call",
6392
+ server: "other",
6393
+ tool: "render",
6394
+ arguments: {},
6395
+ status: "completed",
6396
+ result: {
6397
+ content: [{ type: "image", data: "base64-bytes", mimeType: "image/png" }],
6398
+ structured_content: { image: "base64-bytes" }
6399
+ }
6400
+ }),
6401
+ turnCompleted()
6402
+ ],
6403
+ expected: [
6404
+ sessionEvent3(NEW_THREAD_ID),
6405
+ {
6406
+ type: "tool",
6407
+ id: "mcp-image",
6408
+ name: "other.render",
6409
+ phase: "start",
6410
+ summary: "",
6411
+ input: {}
6412
+ },
6413
+ {
6414
+ type: "tool",
6415
+ id: "mcp-image",
6416
+ name: "other.render",
6417
+ phase: "done",
6418
+ summary: "",
6419
+ input: {},
6420
+ result: [{ type: "image", data: "base64-bytes", mimeType: "image/png" }]
6421
+ },
6422
+ { type: "result", ok: true }
6423
+ ]
6424
+ },
6185
6425
  {
6186
6426
  // A streaming tool whose args arrive on a later snapshot: `item.started` carries
6187
6427
  // empty args, `item.updated` fills them, `item.completed` finishes. The `start`
@@ -8010,7 +8250,8 @@ ${reason}`,
8010
8250
  }
8011
8251
  const turnEnv = {
8012
8252
  ...hookEnv,
8013
- CABANE_HOST_ACCESS: turnContext.policy.hostFs ? "1" : "0"
8253
+ CABANE_HOST_ACCESS: turnContext.policy.hostFs ? "1" : "0",
8254
+ CABANE_COMPANION_HOME: agentCompanionHome()
8014
8255
  };
8015
8256
  const key = runKey(payload.conversationId, payload.agentId);
8016
8257
  const abortController = new AbortController();
package/dist/runtime.js CHANGED
@@ -224,6 +224,9 @@ function realAccountHome() {
224
224
  }
225
225
  return realHomeCache;
226
226
  }
227
+ function agentCompanionHome() {
228
+ return join(cabaneDir(), "agent-home");
229
+ }
227
230
  function cabaneDir() {
228
231
  const dir2 = join(process.env.CABANE_COMPANION_HOME || homedir(), ".cabane");
229
232
  if (process.env.VITEST) {
@@ -5029,6 +5032,7 @@ function readToolItem(item, eventType) {
5029
5032
  if (type === "mcp_tool_call") {
5030
5033
  const tool2 = str(item.tool) ?? "tool";
5031
5034
  const server = str(item.server);
5035
+ const result = readMcpResult(item.result);
5032
5036
  return {
5033
5037
  id,
5034
5038
  // A cabane tool reads best as its bare verb (`read`); a non-cabane server's
@@ -5036,7 +5040,7 @@ function readToolItem(item, eventType) {
5036
5040
  name: server && server !== "cabane" ? `${server}.${tool2}` : tool2,
5037
5041
  input: item.arguments,
5038
5042
  status: toStatus(item.status),
5039
- ...item.status === "completed" ? { result: readMcpResult(item.result) } : item.status === "failed" ? { result: readMcpError(item.error) } : {}
5043
+ ...item.status === "completed" ? { result } : item.status === "failed" ? { result: hasMcpReceipt(result) ? result : readMcpError(item.error) } : {}
5040
5044
  };
5041
5045
  }
5042
5046
  if (type === "web_search") {
@@ -5076,9 +5080,38 @@ function toStatus(v) {
5076
5080
  }
5077
5081
  function readMcpResult(result) {
5078
5082
  const rec = asRecord2(result);
5079
- if (rec && "content" in rec) return rec.content;
5083
+ if (!rec) return result;
5084
+ if (hasOnlyNonTextContentBlocks(rec.content)) return rec.content;
5085
+ if (rec.structured_content !== void 0 && rec.structured_content !== null) {
5086
+ return rec.structured_content;
5087
+ }
5088
+ if (rec.structuredContent !== void 0 && rec.structuredContent !== null) {
5089
+ return rec.structuredContent;
5090
+ }
5091
+ if ("content" in rec) return rec.content;
5080
5092
  return result;
5081
5093
  }
5094
+ function hasOnlyNonTextContentBlocks(content) {
5095
+ if (!Array.isArray(content) || content.length === 0) return false;
5096
+ let sawTypedBlock = false;
5097
+ for (const raw of content) {
5098
+ const block = asRecord2(raw);
5099
+ const type = block && str(block.type);
5100
+ if (!type) continue;
5101
+ sawTypedBlock = true;
5102
+ if (type === "text" && typeof block?.text === "string" && block.text.trim().length > 0) {
5103
+ return false;
5104
+ }
5105
+ }
5106
+ return sawTypedBlock;
5107
+ }
5108
+ function hasMcpReceipt(result) {
5109
+ if (result === void 0 || result === null) return false;
5110
+ if (typeof result === "string") return result.trim().length > 0;
5111
+ if (Array.isArray(result)) return result.length > 0;
5112
+ if (typeof result === "object") return Object.keys(result).length > 0;
5113
+ return true;
5114
+ }
5082
5115
  function readMcpError(error) {
5083
5116
  const rec = asRecord2(error);
5084
5117
  return rec && str(rec.message) || "error";
@@ -5602,6 +5635,25 @@ var errorItem = (id, message) => ({
5602
5635
  type: "item.completed",
5603
5636
  item: { id, type: "error", message }
5604
5637
  });
5638
+ var SDK_SUCCESS = { ok: true, result: { source: "native" }, logs: "", truncated: false };
5639
+ var SDK_FAILURE = {
5640
+ ok: false,
5641
+ result: null,
5642
+ preview: '{"rows":[1,2,3]}',
5643
+ logs: "",
5644
+ truncated: false,
5645
+ error: { kind: "output_too_large", bytes: 169167, limit: 65536 },
5646
+ warnings: [],
5647
+ committed: {
5648
+ calls: [
5649
+ {
5650
+ method: "conversations.update",
5651
+ args: { id: "conv-1", opts: { title: "Renamed before failure" } }
5652
+ }
5653
+ ]
5654
+ },
5655
+ inFlight: null
5656
+ };
5605
5657
  var sessionEvent3 = (threadId, cwd = DIR2, degraded = false, promptFingerprint = fingerprintPrompt(PROMPT)) => ({
5606
5658
  type: "session",
5607
5659
  state: encodeSession3({ threadId, cwd, promptFingerprint }),
@@ -5681,6 +5733,194 @@ var CODEX_CONFORMANCE_FIXTURES = [
5681
5733
  { type: "result", ok: true }
5682
5734
  ]
5683
5735
  },
5736
+ {
5737
+ // CT1211: recorded SDK success shape. Codex exposes the text compatibility
5738
+ // copy and the native object together; normalization must keep the object.
5739
+ name: "MCP success prefers native structured content",
5740
+ request: makeRequest3(),
5741
+ nativeStream: [
5742
+ threadStarted(NEW_THREAD_ID),
5743
+ toolFrame("item.started", {
5744
+ id: "sdk-success",
5745
+ type: "mcp_tool_call",
5746
+ server: "cabane",
5747
+ tool: "sdk",
5748
+ arguments: { code: 'return { source: "native" }' },
5749
+ status: "in_progress"
5750
+ }),
5751
+ toolFrame("item.completed", {
5752
+ id: "sdk-success",
5753
+ type: "mcp_tool_call",
5754
+ server: "cabane",
5755
+ tool: "sdk",
5756
+ arguments: { code: 'return { source: "native" }' },
5757
+ status: "completed",
5758
+ result: {
5759
+ content: [{ type: "text", text: JSON.stringify(SDK_SUCCESS) }],
5760
+ structured_content: SDK_SUCCESS
5761
+ }
5762
+ }),
5763
+ turnCompleted()
5764
+ ],
5765
+ expected: [
5766
+ sessionEvent3(NEW_THREAD_ID),
5767
+ {
5768
+ type: "tool",
5769
+ id: "sdk-success",
5770
+ name: "sdk",
5771
+ phase: "start",
5772
+ summary: "",
5773
+ input: { code: 'return { source: "native" }' }
5774
+ },
5775
+ {
5776
+ type: "tool",
5777
+ id: "sdk-success",
5778
+ name: "sdk",
5779
+ phase: "done",
5780
+ summary: "",
5781
+ input: { code: 'return { source: "native" }' },
5782
+ result: SDK_SUCCESS
5783
+ },
5784
+ { type: "result", ok: true }
5785
+ ]
5786
+ },
5787
+ {
5788
+ // CT1211 incident shape: MCP `isError` keeps the failed phase, while the raw
5789
+ // camel-case structured payload survives instead of the generic `error` token.
5790
+ name: "failed SDK call preserves structured receipt while remaining error phase",
5791
+ request: makeRequest3(),
5792
+ nativeStream: [
5793
+ threadStarted(NEW_THREAD_ID),
5794
+ toolFrame("item.started", {
5795
+ id: "sdk-failed",
5796
+ type: "mcp_tool_call",
5797
+ server: "cabane",
5798
+ tool: "sdk",
5799
+ arguments: { code: "return largeResult" },
5800
+ status: "in_progress"
5801
+ }),
5802
+ toolFrame("item.completed", {
5803
+ id: "sdk-failed",
5804
+ type: "mcp_tool_call",
5805
+ server: "cabane",
5806
+ tool: "sdk",
5807
+ arguments: { code: "return largeResult" },
5808
+ status: "failed",
5809
+ result: {
5810
+ content: [{ type: "text", text: JSON.stringify(SDK_FAILURE) }],
5811
+ structuredContent: SDK_FAILURE,
5812
+ isError: true
5813
+ },
5814
+ error: { message: "error" }
5815
+ }),
5816
+ turnCompleted()
5817
+ ],
5818
+ expected: [
5819
+ sessionEvent3(NEW_THREAD_ID),
5820
+ {
5821
+ type: "tool",
5822
+ id: "sdk-failed",
5823
+ name: "sdk",
5824
+ phase: "start",
5825
+ summary: "",
5826
+ input: { code: "return largeResult" }
5827
+ },
5828
+ {
5829
+ type: "tool",
5830
+ id: "sdk-failed",
5831
+ name: "sdk",
5832
+ phase: "error",
5833
+ summary: "",
5834
+ input: { code: "return largeResult" },
5835
+ result: SDK_FAILURE
5836
+ },
5837
+ { type: "result", ok: true }
5838
+ ]
5839
+ },
5840
+ {
5841
+ // A transport/tool failure has no MCP result payload and still uses the real
5842
+ // adapter error message. CT1211 must not replace this fallback with `undefined`.
5843
+ name: "failed MCP call without result keeps error message fallback",
5844
+ request: makeRequest3(),
5845
+ nativeStream: [
5846
+ threadStarted(NEW_THREAD_ID),
5847
+ toolFrame("item.completed", {
5848
+ id: "mcp-failed",
5849
+ type: "mcp_tool_call",
5850
+ server: "other",
5851
+ tool: "lookup",
5852
+ arguments: { q: "receipt" },
5853
+ status: "failed",
5854
+ result: { content: [], isError: true },
5855
+ error: { message: "connection closed" }
5856
+ }),
5857
+ turnCompleted()
5858
+ ],
5859
+ expected: [
5860
+ sessionEvent3(NEW_THREAD_ID),
5861
+ {
5862
+ type: "tool",
5863
+ id: "mcp-failed",
5864
+ name: "other.lookup",
5865
+ phase: "start",
5866
+ summary: "receipt",
5867
+ input: { q: "receipt" }
5868
+ },
5869
+ {
5870
+ type: "tool",
5871
+ id: "mcp-failed",
5872
+ name: "other.lookup",
5873
+ phase: "error",
5874
+ summary: "receipt",
5875
+ input: { q: "receipt" },
5876
+ result: "connection closed"
5877
+ },
5878
+ { type: "result", ok: true }
5879
+ ]
5880
+ },
5881
+ {
5882
+ // CT1147 stays intact when a connector includes structured metadata beside an
5883
+ // image-only MCP response: no image/base64 payload enters activity receipts.
5884
+ name: "image-only MCP result remains empty despite structured metadata",
5885
+ request: makeRequest3(),
5886
+ nativeStream: [
5887
+ threadStarted(NEW_THREAD_ID),
5888
+ toolFrame("item.completed", {
5889
+ id: "mcp-image",
5890
+ type: "mcp_tool_call",
5891
+ server: "other",
5892
+ tool: "render",
5893
+ arguments: {},
5894
+ status: "completed",
5895
+ result: {
5896
+ content: [{ type: "image", data: "base64-bytes", mimeType: "image/png" }],
5897
+ structured_content: { image: "base64-bytes" }
5898
+ }
5899
+ }),
5900
+ turnCompleted()
5901
+ ],
5902
+ expected: [
5903
+ sessionEvent3(NEW_THREAD_ID),
5904
+ {
5905
+ type: "tool",
5906
+ id: "mcp-image",
5907
+ name: "other.render",
5908
+ phase: "start",
5909
+ summary: "",
5910
+ input: {}
5911
+ },
5912
+ {
5913
+ type: "tool",
5914
+ id: "mcp-image",
5915
+ name: "other.render",
5916
+ phase: "done",
5917
+ summary: "",
5918
+ input: {},
5919
+ result: [{ type: "image", data: "base64-bytes", mimeType: "image/png" }]
5920
+ },
5921
+ { type: "result", ok: true }
5922
+ ]
5923
+ },
5684
5924
  {
5685
5925
  // A streaming tool whose args arrive on a later snapshot: `item.started` carries
5686
5926
  // empty args, `item.updated` fills them, `item.completed` finishes. The `start`
@@ -7509,7 +7749,8 @@ ${reason}`,
7509
7749
  }
7510
7750
  const turnEnv = {
7511
7751
  ...hookEnv,
7512
- CABANE_HOST_ACCESS: turnContext.policy.hostFs ? "1" : "0"
7752
+ CABANE_HOST_ACCESS: turnContext.policy.hostFs ? "1" : "0",
7753
+ CABANE_COMPANION_HOME: agentCompanionHome()
7513
7754
  };
7514
7755
  const key = runKey(payload.conversationId, payload.agentId);
7515
7756
  const abortController = new AbortController();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cabane/companion",
3
- "version": "0.6.51",
3
+ "version": "0.6.53",
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",