@cabane/companion 0.6.5 → 0.6.7

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
@@ -2827,7 +2827,17 @@ import {
2827
2827
  } from "@anthropic-ai/claude-agent-sdk";
2828
2828
 
2829
2829
  // packages/agent-runtime/src/claude-code/addendum.ts
2830
- var CLAUDE_CODE_ADDENDUM = "";
2830
+ var CLAUDE_CODE_ADDENDUM = [
2831
+ "On this harness the Cabane tools register under MCP prefixes. The workspace tool is",
2832
+ "`mcp__cabane__sdk`; the ancillary tools are `mcp__cabane__list_workspaces`,",
2833
+ "`mcp__cabane__read_binary`, `mcp__cabane__upload`, `mcp__cabane__begin_upload`,",
2834
+ "`mcp__cabane__finalize_upload`, and `mcp__cabane__mint_render_token`; the turn tools are",
2835
+ "`mcp__cabane_companion__ask`, `mcp__cabane_companion__wake_me`,",
2836
+ "`mcp__cabane_companion__summon_agent`, `mcp__cabane_companion__sub_agent`, and",
2837
+ "`mcp__cabane_companion__skip_turn`. Where this prompt names a tool by its bare verb, call",
2838
+ "the prefixed form from your tool list. Your harness's own tools (shell, local file",
2839
+ "read/edit) keep their ordinary names and act on the local machine only."
2840
+ ].join(" ");
2831
2841
 
2832
2842
  // packages/agent-runtime/src/claude-code/policy.ts
2833
2843
  import { z as z9 } from "zod";
@@ -3612,19 +3622,15 @@ function selectAdapter(registry, runtime) {
3612
3622
 
3613
3623
  // packages/agent-runtime/src/opencode/addendum.ts
3614
3624
  var OPENCODE_ADDENDUM = [
3615
- "Your one Cabane workspace tool has a plain name \u2014 `sdk` (you act on the",
3616
- "workspace by writing a TypeScript program and calling `sdk` with it); the",
3617
- "turn-control verbs (`ask`, `wake_me`, `summon_agent`, `skip_turn`) are",
3618
- "plain-named too, as are the few ancillary cabane tools (`list_workspaces`,",
3619
- "`read_binary`, `upload`, `begin_upload`, `finalize_upload`,",
3620
- "`mint_render_token`), and the host tools are plain verbs (`bash`, `read`,",
3621
- "`edit`). There is no `write`/`search`/`edit` CABANE tool here \u2014 those are",
3622
- "`cabane` SDK calls inside your program, not tools (a bare `read`/`edit` is the",
3623
- "HOST tool). If a tool appears in this prompt with an `mcp__\u2026__` prefix, that",
3624
- "prefix is not part of its name \u2014 call the tool by its plain verb. Write your",
3625
- "closing reply as the last thing you say in the turn: you can interleave",
3626
- "narration with tool calls, but only your final message is recorded as the",
3627
- "turn\u2019s reply."
3625
+ "Every tool here goes by its plain name: the workspace tool is `sdk`; the turn tools are",
3626
+ "`ask`, `wake_me`, `summon_agent`, `sub_agent`, `skip_turn`; the ancillary tools are",
3627
+ "`list_workspaces`, `read_binary`, `upload`, `begin_upload`, `finalize_upload`,",
3628
+ "`mint_render_token`; and the host tools are plain verbs too (`bash`, `read`, `edit`). Mind",
3629
+ "the collision: a bare `read` or `edit` is the HOST tool, acting on the local machine \u2014 a",
3630
+ "workspace read is `cabane.files.read` inside an `sdk` program. If a tool ever appears with",
3631
+ "an `mcp__\u2026__` prefix, that prefix is not part of its name here. One more harness fact: you",
3632
+ "can interleave narration with tool calls, but only your final message is recorded as the",
3633
+ "turn's reply \u2014 write your closing answer last."
3628
3634
  ].join(" ");
3629
3635
 
3630
3636
  // packages/agent-runtime/src/opencode/events.ts
@@ -4577,22 +4583,17 @@ var OPENCODE_CONFORMANCE_FIXTURES = [
4577
4583
 
4578
4584
  // packages/agent-runtime/src/codex/addendum.ts
4579
4585
  var CODEX_ADDENDUM = [
4580
- "Your Cabane workspace tool is exposed to Codex as the qualified MCP tool",
4581
- "`mcp__cabane__sdk`. On Codex versions that defer MCP tools, locate it in the",
4582
- "`functions.exec` deferred-tool inventory and invoke that exact qualified tool",
4583
- "from the exec program; do not look for or call a bare top-level `sdk` tool.",
4584
- "If discovery or an invocation fails, report the recorded tool error; never",
4585
- "declare the SDK absent without attempting discovery and invocation. The SDK",
4586
- "call runs a TypeScript program against the ambient `cabane` object. The",
4587
- "turn-control verbs (`ask`, `wake_me`, `summon_agent`, `skip_turn`) are",
4588
- "qualified `mcp__cabane_companion__\u2026` tools (and may be deferred too), as are",
4589
- "the few ancillary cabane tools (`mcp__cabane__list_workspaces`,",
4590
- "`mcp__cabane__read_binary`, the upload tools, `mcp__cabane__mint_render_token`).",
4591
- "There is no Cabane `read`/`write`/`search`/`edit` tool here \u2014 those are `cabane`",
4592
- "SDK calls inside your program, not tools. If a tool appears in this prompt with",
4593
- "an `mcp__\u2026__` prefix, preserve that qualified name. Write your closing reply as",
4594
- "the last thing you say in the turn: you can interleave narration with tool",
4595
- "calls, but only your final message is recorded as the turn\u2019s reply."
4586
+ "Codex surfaces MCP tools under qualified names, and on some versions defers them. The",
4587
+ "workspace tool is `mcp__cabane__sdk` \u2014 if it isn't in your visible tool list, locate it in",
4588
+ "the deferred-tool inventory and invoke that exact qualified name; never conclude the SDK is",
4589
+ "absent without attempting discovery and invocation, and if a call fails, report the recorded",
4590
+ "error. The turn tools are `mcp__cabane_companion__ask` / `wake_me` / `summon_agent` /",
4591
+ "`sub_agent` / `skip_turn`, and the ancillary tools `mcp__cabane__list_workspaces` /",
4592
+ "`read_binary` / `upload` / `begin_upload` / `finalize_upload` / `mint_render_token` \u2014 all",
4593
+ "possibly deferred too. There is no Cabane `read`/`write`/`search` tool \u2014 those are",
4594
+ "`cabane.*` calls inside your program. One more harness fact: you can interleave narration",
4595
+ "with tool calls, but only your final message is recorded as the turn's reply \u2014 write your",
4596
+ "closing answer last."
4596
4597
  ].join(" ");
4597
4598
 
4598
4599
  // packages/agent-runtime/src/codex/events.ts
@@ -6289,7 +6290,7 @@ function createSummonMcpServer(summonState, skipState, askState, subAgentCreate,
6289
6290
  ...askState ? [
6290
6291
  tool(
6291
6292
  ASK_TOOL,
6292
- "Ask a HUMAN a structured question (or a short LIST of them) you need answered to continue, then END your turn \u2014 don't wait for the reply. Use it when you genuinely can't proceed without a person's input (a decision only they can make, a missing fact, a go/no-go). Pass `targetUserId` (a workspace member's user id \u2014 get it from `mcp__cabane__list_members`). Two forms: a SINGLE question \u2014 a `headline` (the actual question as one clear, capitalized sentence ending in `?`, \"Do we go to prod?\") plus a short `question` body for the framing the headline can't hold \u2014 OR, when a plan ends with SEVERAL bounded decisions at once (\"three calls before I build: A? B? C?\"), a `questions` array of 1\u20135 items, each `{ headline, body?, options? }`. **Prefer the list over cramming the extra decisions into prose or dropping them** \u2014 end the turn with one ask carrying every question, never pick one and bury the rest. Each question keeps the same form rules: a one-sentence `headline`, a short `body` frame (NOT a report \u2014 your status, links, and detail go in your REPLY, and the body renders inline markdown only: links/emphasis/inline code, no bulleted lists or headings), and 2\u20134 `options` when the answer is a bounded choice \u2014 for a yes/no go-ahead always pass them, so it's one click, not a typed reply. An option can be a short button label OR a sentence that carries its own context; short/binary sets render as inline buttons, long ones stack full-width. Provide EITHER `question` (single) or `questions` (array), never both. The ask is recorded as a first-class attention item aimed at that person; your final reply carries the surrounding CONTEXT (what you found, why you're stuck), the ask carries the QUESTION(S). An open ask marks you as blocked until EVERY question is answered, so raise one only when you truly can't proceed \u2014 never ceremonially. One ask per turn (last call wins). After asking, stop \u2014 when the person replies addressed to you, the ask resolves and you resume; other people's or agents' messages may wake you but leave it open. Targets a human only; to hand work to another AGENT use summon/dispatch instead.",
6293
+ "Ask a HUMAN a structured question (or a short LIST of them) you need answered to continue, then END your turn \u2014 don't wait for the reply. Use it when you genuinely can't proceed without a person's input (a decision only they can make, a missing fact). Pass `targetUserId` (a workspace member's user id \u2014 get it from `mcp__cabane__list_members`). Two forms: a SINGLE question \u2014 a `headline` (the actual question as one clear, capitalized sentence ending in `?`, \"Do we go to prod?\") plus a short `question` body for the framing the headline can't hold \u2014 OR, when a plan ends with SEVERAL bounded decisions at once, a `questions` array of 1\u20135 items, each `{ headline, body?, options? }`. **Prefer the list over cramming the extra decisions into prose or dropping them** \u2014 end the turn with one ask carrying every question, never pick one and bury the rest. Each question keeps the same form rules: a one-sentence `headline`, a short `body` frame (NOT a report \u2014 your status, links, and detail go in your REPLY, and the body renders inline markdown only: links/emphasis/inline code, no bulleted lists or headings), and 2\u20134 `options` when the answer is a bounded choice \u2014 for a yes/no go-ahead always pass them, so it's one click, not a typed reply. An option can be a short button label or a whole sentence. Provide EITHER `question` (single) or `questions` (array), never both. The ask is a first-class attention item aimed at that person; your final reply carries the surrounding CONTEXT (what you found, why you're stuck), the ask carries the QUESTION(S). An open ask marks you as blocked until EVERY question is answered, so raise one only when you truly can't proceed \u2014 never ceremonially. One ask per turn (last call wins). After asking, stop \u2014 when the person replies addressed to you, the ask resolves and you resume; other people's or agents' messages may wake you but leave it open. Targets a human only; to hand work to another AGENT use summon/dispatch instead.",
6293
6294
  {
6294
6295
  targetUserId: z12.string().uuid().describe("The workspace member (human) to ask \u2014 a user id from `list_members`."),
6295
6296
  question: z12.string().min(1).max(400).optional().describe(
@@ -6396,7 +6397,7 @@ function createSummonMcpServer(summonState, skipState, askState, subAgentCreate,
6396
6397
  ...wakeState ? [
6397
6398
  tool(
6398
6399
  WAKE_ME_TOOL,
6399
- 'Wake yourself later \u2014 end this turn now and be re-dispatched at a time you pick, with a note you write to yourself. Use it for "wait until X": when the thing you need hasn\'t happened yet (a conversation isn\'t done, a PR isn\'t merged, a human hasn\'t answered), arm a wake, end your turn, and you\'re woken later to CHECK \u2014 read the workspace, and either act or re-arm. This is the loop behind "check back in five minutes", "keep checking until {condition}", and a scheduled re-try ("re-send once that agent\'s limit resets"). Ground the delay before you arm it. Almost every wake is short \u2014 seconds to a couple of hours \u2014 waiting on a condition you can name: a session limit resetting, a PR merging, a deploy landing, a throttled dispatch to re-send. Reach past a few hours only when (a) a human asked for that timing, or (b) the wait is pinned to a real external event you can name \u2014 a report that only runs Mondays, a scheduled appointment, a known reset time. A speculative far-future check-in you invented yourself \u2014 "in two weeks I\'ll see whether this feature is used" \u2014 is the one thing not to arm: if no one asked and you can\'t name both what clears the wait and why it takes that long, don\'t arm it \u2014 finish now, or raise an `ask`. Pass EXACTLY ONE of `afterSeconds` (a relative delay \u2014 `300` for five minutes) or `at` (an absolute ISO-8601 timestamp WITH a zone, e.g. `2026-07-16T09:00:00-07:00` \u2014 YOU compute it from a phrase like "tomorrow morning"; the system never parses natural-language time). `note` is a message to your future self \u2014 it becomes the body of the wake message that re-dispatches you, so write the condition to re-check ("check whether CT441 merged yet"). The wake is armed when your turn SETTLES, not now, so the delay counts from the turn ending; one wake per turn (last call wins). This is the sanctioned way to schedule your own continuation \u2014 the ONLY one; never reach for a host cron/scheduler. Guardrails: at least 60s out, at most 14 days; widen the interval as a loop ages (5m \u2192 15m \u2192 1h\u2026) rather than hammering; after many consecutive re-arms with no other activity you\'ll be steered to raise an `ask` to the human instead. If a wake can\'t be armed you\'re re-dispatched with a note explaining why \u2014 never a silent drop.',
6400
+ "Wake yourself later \u2014 end this turn now and be re-dispatched at a time you pick, with a note you write to yourself. Use it for \"wait until X\": when the thing you need hasn't happened yet (a PR isn't merged, a human hasn't answered), arm a wake, end your turn, and you're woken later to CHECK \u2014 read the workspace, and either act or re-arm. Ground the delay before you arm it. Almost every wake is short \u2014 seconds to a couple of hours \u2014 waiting on a condition you can name: a session limit resetting, a PR merging. Reach past a few hours only when (a) a human asked for that timing, or (b) the wait is pinned to a real external event you can name \u2014 a report that only runs Mondays, a known reset time. A speculative far-future check-in you invented yourself is the one thing not to arm: if no one asked and you can't name both what clears the wait and why it takes that long, don't arm it \u2014 finish now, or raise an `ask`. Pass EXACTLY ONE of `afterSeconds` (a relative delay \u2014 `300` for five minutes) or `at` (an absolute ISO-8601 timestamp WITH a zone, e.g. `2026-07-16T09:00:00-07:00` \u2014 YOU compute it from a phrase like \"tomorrow morning\"; the system never parses natural-language time). `note` is a message to your future self \u2014 it becomes the body of the wake message that re-dispatches you, so write the condition to re-check (\"check whether CT441 merged yet\"). The wake is armed when your turn SETTLES, not now, so the delay counts from the turn ending; one wake per turn (last call wins). This is the sanctioned way to schedule your own continuation \u2014 the ONLY one; never reach for a host cron/scheduler. Guardrails: at least 60s out, at most 14 days; widen the interval as a loop ages (5m \u2192 15m \u2192 1h\u2026) rather than hammering; after many consecutive re-arms with no other activity you'll be steered to raise an `ask` to the human instead. If a wake can't be armed you're re-dispatched with a note explaining why \u2014 never a silent drop.",
6400
6401
  {
6401
6402
  afterSeconds: z12.number().int().positive().optional().describe(
6402
6403
  "Relative delay in seconds from when this turn ends (e.g. 300 = five minutes). Provide EITHER this or `at`, not both. Floor 60s, horizon 14 days \u2014 enforced server-side."
@@ -7286,13 +7287,13 @@ ${reason}`,
7286
7287
  const wakeState = createWakeState();
7287
7288
  const subAgentCreate = async (args) => {
7288
7289
  const dispatchTarget = args.agentId ?? payload.agentId;
7289
- const channelId = turnContext.conversation.channelId;
7290
+ const projectId = turnContext.conversation.projectId;
7290
7291
  const { status: status2, body } = await this.opts.api.createSubAgentConversation(
7291
7292
  workspaceId,
7292
7293
  payload.conversationId,
7293
7294
  turnContext.turnToken ?? this.opts.credential,
7294
7295
  {
7295
- ...channelId ? { channelId } : {},
7296
+ ...projectId ? { projectId } : {},
7296
7297
  ...args.title ? { title: args.title } : {},
7297
7298
  body: args.prompt,
7298
7299
  dispatch: dispatchTarget,
package/dist/runtime.js CHANGED
@@ -2480,7 +2480,17 @@ import {
2480
2480
  } from "@anthropic-ai/claude-agent-sdk";
2481
2481
 
2482
2482
  // packages/agent-runtime/src/claude-code/addendum.ts
2483
- var CLAUDE_CODE_ADDENDUM = "";
2483
+ var CLAUDE_CODE_ADDENDUM = [
2484
+ "On this harness the Cabane tools register under MCP prefixes. The workspace tool is",
2485
+ "`mcp__cabane__sdk`; the ancillary tools are `mcp__cabane__list_workspaces`,",
2486
+ "`mcp__cabane__read_binary`, `mcp__cabane__upload`, `mcp__cabane__begin_upload`,",
2487
+ "`mcp__cabane__finalize_upload`, and `mcp__cabane__mint_render_token`; the turn tools are",
2488
+ "`mcp__cabane_companion__ask`, `mcp__cabane_companion__wake_me`,",
2489
+ "`mcp__cabane_companion__summon_agent`, `mcp__cabane_companion__sub_agent`, and",
2490
+ "`mcp__cabane_companion__skip_turn`. Where this prompt names a tool by its bare verb, call",
2491
+ "the prefixed form from your tool list. Your harness's own tools (shell, local file",
2492
+ "read/edit) keep their ordinary names and act on the local machine only."
2493
+ ].join(" ");
2484
2494
 
2485
2495
  // packages/agent-runtime/src/claude-code/policy.ts
2486
2496
  import { z as z9 } from "zod";
@@ -3265,19 +3275,15 @@ function selectAdapter(registry, runtime) {
3265
3275
 
3266
3276
  // packages/agent-runtime/src/opencode/addendum.ts
3267
3277
  var OPENCODE_ADDENDUM = [
3268
- "Your one Cabane workspace tool has a plain name \u2014 `sdk` (you act on the",
3269
- "workspace by writing a TypeScript program and calling `sdk` with it); the",
3270
- "turn-control verbs (`ask`, `wake_me`, `summon_agent`, `skip_turn`) are",
3271
- "plain-named too, as are the few ancillary cabane tools (`list_workspaces`,",
3272
- "`read_binary`, `upload`, `begin_upload`, `finalize_upload`,",
3273
- "`mint_render_token`), and the host tools are plain verbs (`bash`, `read`,",
3274
- "`edit`). There is no `write`/`search`/`edit` CABANE tool here \u2014 those are",
3275
- "`cabane` SDK calls inside your program, not tools (a bare `read`/`edit` is the",
3276
- "HOST tool). If a tool appears in this prompt with an `mcp__\u2026__` prefix, that",
3277
- "prefix is not part of its name \u2014 call the tool by its plain verb. Write your",
3278
- "closing reply as the last thing you say in the turn: you can interleave",
3279
- "narration with tool calls, but only your final message is recorded as the",
3280
- "turn\u2019s reply."
3278
+ "Every tool here goes by its plain name: the workspace tool is `sdk`; the turn tools are",
3279
+ "`ask`, `wake_me`, `summon_agent`, `sub_agent`, `skip_turn`; the ancillary tools are",
3280
+ "`list_workspaces`, `read_binary`, `upload`, `begin_upload`, `finalize_upload`,",
3281
+ "`mint_render_token`; and the host tools are plain verbs too (`bash`, `read`, `edit`). Mind",
3282
+ "the collision: a bare `read` or `edit` is the HOST tool, acting on the local machine \u2014 a",
3283
+ "workspace read is `cabane.files.read` inside an `sdk` program. If a tool ever appears with",
3284
+ "an `mcp__\u2026__` prefix, that prefix is not part of its name here. One more harness fact: you",
3285
+ "can interleave narration with tool calls, but only your final message is recorded as the",
3286
+ "turn's reply \u2014 write your closing answer last."
3281
3287
  ].join(" ");
3282
3288
 
3283
3289
  // packages/agent-runtime/src/opencode/events.ts
@@ -4230,22 +4236,17 @@ var OPENCODE_CONFORMANCE_FIXTURES = [
4230
4236
 
4231
4237
  // packages/agent-runtime/src/codex/addendum.ts
4232
4238
  var CODEX_ADDENDUM = [
4233
- "Your Cabane workspace tool is exposed to Codex as the qualified MCP tool",
4234
- "`mcp__cabane__sdk`. On Codex versions that defer MCP tools, locate it in the",
4235
- "`functions.exec` deferred-tool inventory and invoke that exact qualified tool",
4236
- "from the exec program; do not look for or call a bare top-level `sdk` tool.",
4237
- "If discovery or an invocation fails, report the recorded tool error; never",
4238
- "declare the SDK absent without attempting discovery and invocation. The SDK",
4239
- "call runs a TypeScript program against the ambient `cabane` object. The",
4240
- "turn-control verbs (`ask`, `wake_me`, `summon_agent`, `skip_turn`) are",
4241
- "qualified `mcp__cabane_companion__\u2026` tools (and may be deferred too), as are",
4242
- "the few ancillary cabane tools (`mcp__cabane__list_workspaces`,",
4243
- "`mcp__cabane__read_binary`, the upload tools, `mcp__cabane__mint_render_token`).",
4244
- "There is no Cabane `read`/`write`/`search`/`edit` tool here \u2014 those are `cabane`",
4245
- "SDK calls inside your program, not tools. If a tool appears in this prompt with",
4246
- "an `mcp__\u2026__` prefix, preserve that qualified name. Write your closing reply as",
4247
- "the last thing you say in the turn: you can interleave narration with tool",
4248
- "calls, but only your final message is recorded as the turn\u2019s reply."
4239
+ "Codex surfaces MCP tools under qualified names, and on some versions defers them. The",
4240
+ "workspace tool is `mcp__cabane__sdk` \u2014 if it isn't in your visible tool list, locate it in",
4241
+ "the deferred-tool inventory and invoke that exact qualified name; never conclude the SDK is",
4242
+ "absent without attempting discovery and invocation, and if a call fails, report the recorded",
4243
+ "error. The turn tools are `mcp__cabane_companion__ask` / `wake_me` / `summon_agent` /",
4244
+ "`sub_agent` / `skip_turn`, and the ancillary tools `mcp__cabane__list_workspaces` /",
4245
+ "`read_binary` / `upload` / `begin_upload` / `finalize_upload` / `mint_render_token` \u2014 all",
4246
+ "possibly deferred too. There is no Cabane `read`/`write`/`search` tool \u2014 those are",
4247
+ "`cabane.*` calls inside your program. One more harness fact: you can interleave narration",
4248
+ "with tool calls, but only your final message is recorded as the turn's reply \u2014 write your",
4249
+ "closing answer last."
4249
4250
  ].join(" ");
4250
4251
 
4251
4252
  // packages/agent-runtime/src/codex/events.ts
@@ -5942,7 +5943,7 @@ function createSummonMcpServer(summonState, skipState, askState, subAgentCreate,
5942
5943
  ...askState ? [
5943
5944
  tool(
5944
5945
  ASK_TOOL,
5945
- "Ask a HUMAN a structured question (or a short LIST of them) you need answered to continue, then END your turn \u2014 don't wait for the reply. Use it when you genuinely can't proceed without a person's input (a decision only they can make, a missing fact, a go/no-go). Pass `targetUserId` (a workspace member's user id \u2014 get it from `mcp__cabane__list_members`). Two forms: a SINGLE question \u2014 a `headline` (the actual question as one clear, capitalized sentence ending in `?`, \"Do we go to prod?\") plus a short `question` body for the framing the headline can't hold \u2014 OR, when a plan ends with SEVERAL bounded decisions at once (\"three calls before I build: A? B? C?\"), a `questions` array of 1\u20135 items, each `{ headline, body?, options? }`. **Prefer the list over cramming the extra decisions into prose or dropping them** \u2014 end the turn with one ask carrying every question, never pick one and bury the rest. Each question keeps the same form rules: a one-sentence `headline`, a short `body` frame (NOT a report \u2014 your status, links, and detail go in your REPLY, and the body renders inline markdown only: links/emphasis/inline code, no bulleted lists or headings), and 2\u20134 `options` when the answer is a bounded choice \u2014 for a yes/no go-ahead always pass them, so it's one click, not a typed reply. An option can be a short button label OR a sentence that carries its own context; short/binary sets render as inline buttons, long ones stack full-width. Provide EITHER `question` (single) or `questions` (array), never both. The ask is recorded as a first-class attention item aimed at that person; your final reply carries the surrounding CONTEXT (what you found, why you're stuck), the ask carries the QUESTION(S). An open ask marks you as blocked until EVERY question is answered, so raise one only when you truly can't proceed \u2014 never ceremonially. One ask per turn (last call wins). After asking, stop \u2014 when the person replies addressed to you, the ask resolves and you resume; other people's or agents' messages may wake you but leave it open. Targets a human only; to hand work to another AGENT use summon/dispatch instead.",
5946
+ "Ask a HUMAN a structured question (or a short LIST of them) you need answered to continue, then END your turn \u2014 don't wait for the reply. Use it when you genuinely can't proceed without a person's input (a decision only they can make, a missing fact). Pass `targetUserId` (a workspace member's user id \u2014 get it from `mcp__cabane__list_members`). Two forms: a SINGLE question \u2014 a `headline` (the actual question as one clear, capitalized sentence ending in `?`, \"Do we go to prod?\") plus a short `question` body for the framing the headline can't hold \u2014 OR, when a plan ends with SEVERAL bounded decisions at once, a `questions` array of 1\u20135 items, each `{ headline, body?, options? }`. **Prefer the list over cramming the extra decisions into prose or dropping them** \u2014 end the turn with one ask carrying every question, never pick one and bury the rest. Each question keeps the same form rules: a one-sentence `headline`, a short `body` frame (NOT a report \u2014 your status, links, and detail go in your REPLY, and the body renders inline markdown only: links/emphasis/inline code, no bulleted lists or headings), and 2\u20134 `options` when the answer is a bounded choice \u2014 for a yes/no go-ahead always pass them, so it's one click, not a typed reply. An option can be a short button label or a whole sentence. Provide EITHER `question` (single) or `questions` (array), never both. The ask is a first-class attention item aimed at that person; your final reply carries the surrounding CONTEXT (what you found, why you're stuck), the ask carries the QUESTION(S). An open ask marks you as blocked until EVERY question is answered, so raise one only when you truly can't proceed \u2014 never ceremonially. One ask per turn (last call wins). After asking, stop \u2014 when the person replies addressed to you, the ask resolves and you resume; other people's or agents' messages may wake you but leave it open. Targets a human only; to hand work to another AGENT use summon/dispatch instead.",
5946
5947
  {
5947
5948
  targetUserId: z12.string().uuid().describe("The workspace member (human) to ask \u2014 a user id from `list_members`."),
5948
5949
  question: z12.string().min(1).max(400).optional().describe(
@@ -6049,7 +6050,7 @@ function createSummonMcpServer(summonState, skipState, askState, subAgentCreate,
6049
6050
  ...wakeState ? [
6050
6051
  tool(
6051
6052
  WAKE_ME_TOOL,
6052
- 'Wake yourself later \u2014 end this turn now and be re-dispatched at a time you pick, with a note you write to yourself. Use it for "wait until X": when the thing you need hasn\'t happened yet (a conversation isn\'t done, a PR isn\'t merged, a human hasn\'t answered), arm a wake, end your turn, and you\'re woken later to CHECK \u2014 read the workspace, and either act or re-arm. This is the loop behind "check back in five minutes", "keep checking until {condition}", and a scheduled re-try ("re-send once that agent\'s limit resets"). Ground the delay before you arm it. Almost every wake is short \u2014 seconds to a couple of hours \u2014 waiting on a condition you can name: a session limit resetting, a PR merging, a deploy landing, a throttled dispatch to re-send. Reach past a few hours only when (a) a human asked for that timing, or (b) the wait is pinned to a real external event you can name \u2014 a report that only runs Mondays, a scheduled appointment, a known reset time. A speculative far-future check-in you invented yourself \u2014 "in two weeks I\'ll see whether this feature is used" \u2014 is the one thing not to arm: if no one asked and you can\'t name both what clears the wait and why it takes that long, don\'t arm it \u2014 finish now, or raise an `ask`. Pass EXACTLY ONE of `afterSeconds` (a relative delay \u2014 `300` for five minutes) or `at` (an absolute ISO-8601 timestamp WITH a zone, e.g. `2026-07-16T09:00:00-07:00` \u2014 YOU compute it from a phrase like "tomorrow morning"; the system never parses natural-language time). `note` is a message to your future self \u2014 it becomes the body of the wake message that re-dispatches you, so write the condition to re-check ("check whether CT441 merged yet"). The wake is armed when your turn SETTLES, not now, so the delay counts from the turn ending; one wake per turn (last call wins). This is the sanctioned way to schedule your own continuation \u2014 the ONLY one; never reach for a host cron/scheduler. Guardrails: at least 60s out, at most 14 days; widen the interval as a loop ages (5m \u2192 15m \u2192 1h\u2026) rather than hammering; after many consecutive re-arms with no other activity you\'ll be steered to raise an `ask` to the human instead. If a wake can\'t be armed you\'re re-dispatched with a note explaining why \u2014 never a silent drop.',
6053
+ "Wake yourself later \u2014 end this turn now and be re-dispatched at a time you pick, with a note you write to yourself. Use it for \"wait until X\": when the thing you need hasn't happened yet (a PR isn't merged, a human hasn't answered), arm a wake, end your turn, and you're woken later to CHECK \u2014 read the workspace, and either act or re-arm. Ground the delay before you arm it. Almost every wake is short \u2014 seconds to a couple of hours \u2014 waiting on a condition you can name: a session limit resetting, a PR merging. Reach past a few hours only when (a) a human asked for that timing, or (b) the wait is pinned to a real external event you can name \u2014 a report that only runs Mondays, a known reset time. A speculative far-future check-in you invented yourself is the one thing not to arm: if no one asked and you can't name both what clears the wait and why it takes that long, don't arm it \u2014 finish now, or raise an `ask`. Pass EXACTLY ONE of `afterSeconds` (a relative delay \u2014 `300` for five minutes) or `at` (an absolute ISO-8601 timestamp WITH a zone, e.g. `2026-07-16T09:00:00-07:00` \u2014 YOU compute it from a phrase like \"tomorrow morning\"; the system never parses natural-language time). `note` is a message to your future self \u2014 it becomes the body of the wake message that re-dispatches you, so write the condition to re-check (\"check whether CT441 merged yet\"). The wake is armed when your turn SETTLES, not now, so the delay counts from the turn ending; one wake per turn (last call wins). This is the sanctioned way to schedule your own continuation \u2014 the ONLY one; never reach for a host cron/scheduler. Guardrails: at least 60s out, at most 14 days; widen the interval as a loop ages (5m \u2192 15m \u2192 1h\u2026) rather than hammering; after many consecutive re-arms with no other activity you'll be steered to raise an `ask` to the human instead. If a wake can't be armed you're re-dispatched with a note explaining why \u2014 never a silent drop.",
6053
6054
  {
6054
6055
  afterSeconds: z12.number().int().positive().optional().describe(
6055
6056
  "Relative delay in seconds from when this turn ends (e.g. 300 = five minutes). Provide EITHER this or `at`, not both. Floor 60s, horizon 14 days \u2014 enforced server-side."
@@ -6939,13 +6940,13 @@ ${reason}`,
6939
6940
  const wakeState = createWakeState();
6940
6941
  const subAgentCreate = async (args) => {
6941
6942
  const dispatchTarget = args.agentId ?? payload.agentId;
6942
- const channelId = turnContext.conversation.channelId;
6943
+ const projectId = turnContext.conversation.projectId;
6943
6944
  const { status, body } = await this.opts.api.createSubAgentConversation(
6944
6945
  workspaceId,
6945
6946
  payload.conversationId,
6946
6947
  turnContext.turnToken ?? this.opts.credential,
6947
6948
  {
6948
- ...channelId ? { channelId } : {},
6949
+ ...projectId ? { projectId } : {},
6949
6950
  ...args.title ? { title: args.title } : {},
6950
6951
  body: args.prompt,
6951
6952
  dispatch: dispatchTarget,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cabane/companion",
3
- "version": "0.6.5",
3
+ "version": "0.6.7",
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",