sortie-dogs 0.5.1 → 0.5.2

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/README.md CHANGED
@@ -20,7 +20,7 @@ Requirements: Node.js 22.6 or newer, npm, and OpenCode.
20
20
 
21
21
  Guides: [日本語](docs/guide-ja.md) · [简体中文](docs/guide-zh-CN.md) · [CLI testing](docs/cli-testing.md)
22
22
 
23
- Release: [v0.5.1](https://github.com/zufall-upon/Sortie-dogs/releases/tag/v0.5.1)
23
+ Release: [v0.5.2](https://github.com/zufall-upon/Sortie-dogs/releases/tag/v0.5.2)
24
24
 
25
25
  ## Quick start
26
26
 
@@ -8,7 +8,18 @@ export interface OpenCodePluginInput {
8
8
  directory: string;
9
9
  worktree?: string;
10
10
  /** The host SDK client. Absent in hosts that construct the plugin without one. */
11
- client?: SessionMessageReader & ContinuationClient & OpenCodeModelAvailabilityClient;
11
+ client?: SessionMessageReader & ContinuationClient & OpenCodeModelAvailabilityClient & {
12
+ tui?: {
13
+ showToast?: (request: {
14
+ body: {
15
+ title: string;
16
+ message: string;
17
+ variant: "warning";
18
+ duration: number;
19
+ };
20
+ }) => Promise<unknown>;
21
+ };
22
+ };
12
23
  [key: string]: unknown;
13
24
  }
14
25
  export interface OpenCodeEvent {
@@ -2303,7 +2303,7 @@ export const SortieDogsPlugin = async (input, options) => {
2303
2303
  return undefined;
2304
2304
  }
2305
2305
  }
2306
- async function hostSessionHasForeignUserTurn(sessionID) {
2306
+ async function hostSessionForeignUserAgent(sessionID) {
2307
2307
  const messages = input.client?.session?.messages;
2308
2308
  if (messages === undefined)
2309
2309
  return undefined;
@@ -2322,7 +2322,7 @@ export const SortieDogsPlugin = async (input, options) => {
2322
2322
  if (typeof agent !== "string")
2323
2323
  return undefined;
2324
2324
  if (agent !== COORDINATOR_AGENT)
2325
- return true;
2325
+ return agent;
2326
2326
  }
2327
2327
  return false;
2328
2328
  }
@@ -2330,6 +2330,10 @@ export const SortieDogsPlugin = async (input, options) => {
2330
2330
  return undefined;
2331
2331
  }
2332
2332
  }
2333
+ async function hostSessionHasForeignUserTurn(sessionID) {
2334
+ const agent = await hostSessionForeignUserAgent(sessionID);
2335
+ return typeof agent === "string" ? true : agent;
2336
+ }
2333
2337
  async function assistantMessageText(sessionID, messageID, expectedAgent, partID) {
2334
2338
  const messages = input.client?.session?.messages;
2335
2339
  if (messages === undefined)
@@ -2708,12 +2712,38 @@ export const SortieDogsPlugin = async (input, options) => {
2708
2712
  ? undefined
2709
2713
  : await hostSessionIdentity(chatInput.sessionID);
2710
2714
  const foreignRoot = identity?.agent !== undefined && identity.agent !== COORDINATOR_AGENT;
2711
- const foreignHistory = await hostSessionHasForeignUserTurn(chatInput.sessionID);
2715
+ const foreignHistoryAgent = await hostSessionForeignUserAgent(chatInput.sessionID);
2716
+ const foreignHistory = typeof foreignHistoryAgent === "string" ? true : foreignHistoryAgent;
2712
2717
  const unverifiableRoot = (input.client?.session?.get !== undefined && (identity === undefined ||
2713
2718
  (identity.agent === undefined && input.client?.session?.messages === undefined))) ||
2714
2719
  (input.client?.session?.messages !== undefined && foreignHistory === undefined);
2715
- if (explicitChild || identity?.parentPresent === true || foreignRoot ||
2716
- foreignHistory === true || unverifiableRoot) {
2720
+ const currentAgent = !explicitChild && identity?.parentPresent === false
2721
+ ? typeof foreignHistoryAgent === "string"
2722
+ ? foreignHistoryAgent
2723
+ : foreignRoot
2724
+ ? identity.agent
2725
+ : undefined
2726
+ : undefined;
2727
+ if (currentAgent !== undefined) {
2728
+ const noticePart = output.parts.find((part) => isRecord(part) && part.type === "text");
2729
+ if (!isRecord(noticePart)) {
2730
+ throw new Error("SORTIE_FRESH_SESSION_REQUIRED: /sortie requires a fresh root dog-coordinator session; it cannot convert another agent or promote a child");
2731
+ }
2732
+ chatInput.agent = currentAgent;
2733
+ output.message.agent = currentAgent;
2734
+ noticePart.text = "SORTIE_FRESH_SESSION_REQUIRED. Do not perform the requested task or use tools. " +
2735
+ `Explain only that /sortie must start in a new session because this session belongs to ${currentAgent}.`;
2736
+ output.parts.splice(0, output.parts.length, noticePart);
2737
+ await input.client?.tui?.showToast?.({ body: {
2738
+ title: "Sortie-dogs",
2739
+ message: `/sortie requires a new session. This session remains ${currentAgent}.`,
2740
+ variant: "warning",
2741
+ duration: 8000,
2742
+ } }).catch(() => undefined);
2743
+ return;
2744
+ }
2745
+ if (explicitChild || identity?.parentPresent === true ||
2746
+ foreignHistory || unverifiableRoot) {
2717
2747
  throw new Error("SORTIE_FRESH_SESSION_REQUIRED: /sortie requires a fresh root dog-coordinator session; it cannot convert another agent or promote a child");
2718
2748
  }
2719
2749
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sortie-dogs",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Bounded, validated orchestration loop plugin for OpenCode",
5
5
  "keywords": [
6
6
  "opencode",