@khalilgharbaoui/opencode-claude-code-plugin 0.50.0 → 0.52.0

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/index.d.ts CHANGED
@@ -335,6 +335,9 @@ type OpenCodeHooks = {
335
335
  };
336
336
  type OpenCodePlugin = (input: unknown, options?: Record<string, unknown>) => Promise<OpenCodeHooks>;
337
337
 
338
+ /** Account name -> group name. Empty is never stored; `null` means no guard. */
339
+ type AccountGroups = Readonly<Record<string, string>>;
340
+
338
341
  type LogLevel = "debug" | "info" | "notice" | "warn" | "error";
339
342
  type LogMode = "silent" | "debug";
340
343
 
@@ -390,6 +393,16 @@ interface ClaudeCodeConfig {
390
393
  */
391
394
  accountInProcess?: boolean;
392
395
  accountFailover?: AccountFailoverMode;
396
+ /**
397
+ * The resolved `accountGroups` guard, or null for "no guard". Resolved once
398
+ * by `createClaudeCode` from the user's option, so every turn reads a value
399
+ * that has already been validated and warned about (h #g226).
400
+ */
401
+ accountGroups?: AccountGroups | null;
402
+ /** See `ClaudeCodeProviderSettings.subagentDispatch`. */
403
+ subagentDispatch?: SubagentDispatchMode;
404
+ /** See `ClaudeCodeProviderSettings.subagentDispatchCrossGroup`. */
405
+ subagentDispatchCrossGroup?: boolean;
393
406
  providerID?: string;
394
407
  skipPermissions?: boolean;
395
408
  /**
@@ -483,6 +496,8 @@ type WebSearchRouting = "claude" | "disabled" | (string & {});
483
496
  * behaviour, where the turn ends with the rate-limit error.
484
497
  */
485
498
  type AccountFailoverMode = "ask" | "off";
499
+ /** `subagentDispatch`. Unset behaves as `"off"`; see the option's own note. */
500
+ type SubagentDispatchMode = "ask" | "off";
486
501
  interface ClaudeCodeProviderSettings {
487
502
  cliPath?: string;
488
503
  /** Internal: set by the opencode 2 entrypoint. See `ClaudeCodeConfig.hostApi`. */
@@ -531,6 +546,64 @@ interface ClaudeCodeProviderSettings {
531
546
  * error. See README "Account failover".
532
547
  */
533
548
  accountFailover?: AccountFailoverMode;
549
+ /**
550
+ * Which accounts may see each other's conversations. A map from an account
551
+ * name in `accounts` to a group name, e.g. `{ "appical": "work" }`.
552
+ *
553
+ * **Off unless set**, and unset is the default: with no map, or an empty one,
554
+ * every account behaves as one group and nothing about today's behaviour
555
+ * changes. Every account not named here, `default` included, is in one
556
+ * implicit group, so naming the one account that must stay apart is the whole
557
+ * configuration.
558
+ *
559
+ * When it is set, the plugin only ever moves a conversation between accounts
560
+ * in the SAME group: the by-hand switch (picking a model under another
561
+ * account's provider), the account-switch form, the override that form sets,
562
+ * and `crossAccountResume`. A switch ACROSS groups sends the other account
563
+ * nothing at all, not the Claude transcript and not a text replay of the
564
+ * thread either, because the replay is the same history by another route. The
565
+ * turn there starts fresh with only the current message and says so once, in
566
+ * one `▌ **account group:**` note naming both accounts. The conversation is
567
+ * left intact on the account it was on, so switching back continues it.
568
+ *
569
+ * The switch form offers only accounts in the limited account's own group,
570
+ * and with none left it behaves as a single-account install does.
571
+ *
572
+ * An account name that is not in `accounts` is a typo, so it is ignored with
573
+ * one WARN rather than silently creating a group that guards nothing. The
574
+ * resolved map is printed in the startup block and in
575
+ * `/claude-code-doctor`, names only.
576
+ */
577
+ accountGroups?: Record<string, string>;
578
+ /**
579
+ * Ask, before a proxied `task` or `task_batch` dispatch reaches opencode,
580
+ * how the subagents it is about to start should run: which model, which
581
+ * reasoning effort, and which Claude account.
582
+ *
583
+ * `"off"` by default, and unset behaves as `"off"`: with it unset the
584
+ * dispatch is handed to opencode exactly as it is today, no form is raised
585
+ * and nothing is recorded.
586
+ *
587
+ * With `"ask"`, the dispatch is held, the operator gets one question (so the
588
+ * common answer is one click: `Default`, or `Same as last time`), and only
589
+ * then are the real `task` calls released, inside the same opencode turn.
590
+ * `Customise…` opens a second form with one row per agent type, and a row
591
+ * can ask for a third form with one row per task. Dismissing any of them
592
+ * dispatches with the defaults and says so; the dispatch is never lost.
593
+ *
594
+ * See `docs/configuration/subagents.md` and `src/subagent-dispatch.ts`.
595
+ */
596
+ subagentDispatch?: SubagentDispatchMode;
597
+ /**
598
+ * Let the dispatch form offer Claude accounts outside the dispatching
599
+ * account's own `accountGroups` group. **False by default, and never
600
+ * implied**: a subagent is handed the task text the main agent writes, which
601
+ * can quote the conversation, and it reads the repository, so offering
602
+ * another group is offering that group the conversation by another route.
603
+ * Does nothing when `accountGroups` is unset, where every account is already
604
+ * one group.
605
+ */
606
+ subagentDispatchCrossGroup?: boolean;
534
607
  /**
535
608
  * Model that subagents run on when their own definition pins nothing.
536
609
  * Unset means no implicit override at all, so an agent keeps inheriting the
@@ -1309,6 +1382,17 @@ declare class ClaudeCodeLanguageModel implements LanguageModelV3 {
1309
1382
  private skillBridgeSpawn;
1310
1383
  /** Share one lazy registry request within a turn without making it stale. */
1311
1384
  private createLiveToolInfoLoader;
1385
+ /**
1386
+ * What a subagent dispatch form chose for THIS session, or undefined.
1387
+ *
1388
+ * Two lookups, cheapest first. A session that already claimed a choice keeps
1389
+ * it for the rest of its life, because the model and effort are in its
1390
+ * session key and a choice that came and went mid-conversation would strand
1391
+ * the key behind it. Otherwise, and only when a released dispatch actually
1392
+ * recorded a claim this session could match, the parent is fetched and the
1393
+ * claim taken: a choice must never land on the wrong child (h #g227).
1394
+ */
1395
+ private resolveDispatchChoice;
1312
1396
  /**
1313
1397
  * Whether the ExitPlanMode approval bridge is live for this turn: the
1314
1398
  * operator opted in AND opencode's registry actually has the `question`
@@ -1316,6 +1400,26 @@ declare class ClaudeCodeLanguageModel implements LanguageModelV3 {
1316
1400
  * `⚙ invalid` and wedge the turn, so the plugin keeps the text path.
1317
1401
  */
1318
1402
  private resolvePlanModeQuestion;
1403
+ /**
1404
+ * A dispatch form, as a turn: one synthetic `question` tool call and a
1405
+ * `tool-calls` finish, which is how the operator's answer comes back on the
1406
+ * next `doStream` as a `tool-result` with the same id. The same mechanism
1407
+ * `finishWithQuestionCall` gives the plan-approval bridge and the
1408
+ * account-switch form, minus a Claude process, because there is nothing for
1409
+ * the CLI to do while the operator reads a form.
1410
+ */
1411
+ private subagentDispatchFormStream;
1412
+ /**
1413
+ * The release: the dispatch the form was holding, handed to opencode as the
1414
+ * `task` tool calls it would have been without the form, with every task's
1415
+ * answer recorded as a claim its child will take.
1416
+ *
1417
+ * A held call that is gone (its deadline, an abort, the child dying while
1418
+ * the form was up) is skipped rather than invented, and with every call gone
1419
+ * the turn finishes on `stop`: there is nothing left to dispatch and ending
1420
+ * on `tool-calls` with no tool calls is a protocol violation.
1421
+ */
1422
+ private subagentDispatchReleaseStream;
1319
1423
  /**
1320
1424
  * Create a proxy MCP server for a single active Claude process/session.
1321
1425
  * The process lifecycle owns the server lifecycle via session-manager.