opencode-subagent-magazine 1.6.0 → 1.7.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.
Files changed (44) hide show
  1. package/README.md +12 -1
  2. package/dist/_version.d.ts +1 -1
  3. package/dist/_version.js +1 -1
  4. package/dist/core/format.d.ts +7 -0
  5. package/dist/core/format.js +45 -0
  6. package/dist/core/kv.d.ts +21 -1
  7. package/dist/core/kv.js +33 -1
  8. package/dist/core/types.d.ts +12 -0
  9. package/dist/i18n.d.ts +19 -0
  10. package/dist/i18n.js +76 -0
  11. package/dist/index.js +73 -2
  12. package/dist/panel/SubAgentPanel.d.ts +5 -1
  13. package/dist/panel/SubAgentPanel.js +568 -261
  14. package/dist/panel/entry-map.d.ts +16 -0
  15. package/dist/panel/entry-map.js +74 -0
  16. package/dist/panel/panel-api.d.ts +8 -0
  17. package/dist/server.d.ts +3 -1
  18. package/dist/server.js +8 -0
  19. package/dist/tui.js +927 -431
  20. package/dist/v2/commands.js +188 -44
  21. package/dist/v2/db.d.ts +47 -0
  22. package/dist/v2/db.js +267 -0
  23. package/dist/v2/index.js +26 -6
  24. package/dist/v2/settings-menu.d.ts +9 -0
  25. package/dist/v2/settings-menu.js +225 -0
  26. package/dist/v2/v2-panel-api.js +304 -44
  27. package/dist/v2.js +1741 -560
  28. package/package.json +1 -1
  29. package/src/_version.ts +1 -1
  30. package/src/core/format.ts +44 -0
  31. package/src/core/kv.ts +42 -2
  32. package/src/core/types.ts +12 -0
  33. package/src/i18n.ts +76 -0
  34. package/src/index.tsx +93 -2
  35. package/src/panel/SubAgentPanel.tsx +541 -233
  36. package/src/panel/entry-map.ts +77 -1
  37. package/src/panel/panel-api.ts +8 -0
  38. package/src/server.ts +10 -1
  39. package/src/v2/commands.ts +187 -43
  40. package/src/v2/db.ts +274 -0
  41. package/src/v2/index.tsx +49 -7
  42. package/src/v2/settings-menu.ts +241 -0
  43. package/src/v2/types.ts +3 -1
  44. package/src/v2/v2-panel-api.ts +241 -33
@@ -4,3 +4,19 @@ export type SubEntryPatch = Omit<SubEntry, "startedAt" | "endedAt"> & {
4
4
  };
5
5
  export declare function findSubEntryKey(entries: ReadonlyMap<string, SubEntry>, id: string, sessionId?: string): string | undefined;
6
6
  export declare function upsertSubEntry(entries: ReadonlyMap<string, SubEntry>, partial: SubEntryPatch, now?: number): Map<string, SubEntry>;
7
+ /**
8
+ * 合并同一子代理条目的两个视图,绝不回退状态。
9
+ *
10
+ * 持久化存储由多个 TUI 实例写入,每个写入者都可能
11
+ * 持有过期快照。终态始终优先于 running /
12
+ * cancel_requested,进度计数只增不减,描述性字段
13
+ * 则回退到仍保有它的一侧。
14
+ */
15
+ export declare function mergeSubEntry(base: SubEntry, incoming: SubEntry): SubEntry;
16
+ /**
17
+ * 合并两个条目集合,去重方式与 `upsertSubEntry` 相同
18
+ * (先子会话、后条目 id),冲突用 `mergeSubEntry` 合并。
19
+ * 所有持久化路径都走这里,避免并发实例以整表写入
20
+ * 互相丢弃对方的条目。
21
+ */
22
+ export declare function mergeSubEntries(base: Iterable<SubEntry>, incoming: Iterable<SubEntry>): Map<string, SubEntry>;
@@ -23,3 +23,77 @@ export function upsertSubEntry(entries, partial, now = Date.now()) {
23
23
  });
24
24
  return next;
25
25
  }
26
+ /** running < cancel_requested < 终态(done/error/cancelled)。 */
27
+ function statusRank(status) {
28
+ if (status === "running")
29
+ return 0;
30
+ if (status === "cancel_requested")
31
+ return 1;
32
+ return 2;
33
+ }
34
+ const isTerminalStatus = (status) => statusRank(status) === 2;
35
+ function minDefined(a, b) {
36
+ if (a === undefined)
37
+ return b;
38
+ if (b === undefined)
39
+ return a;
40
+ return Math.min(a, b);
41
+ }
42
+ function maxDefined(a, b) {
43
+ if (a === undefined)
44
+ return b;
45
+ if (b === undefined)
46
+ return a;
47
+ return Math.max(a, b);
48
+ }
49
+ /**
50
+ * 合并同一子代理条目的两个视图,绝不回退状态。
51
+ *
52
+ * 持久化存储由多个 TUI 实例写入,每个写入者都可能
53
+ * 持有过期快照。终态始终优先于 running /
54
+ * cancel_requested,进度计数只增不减,描述性字段
55
+ * 则回退到仍保有它的一侧。
56
+ */
57
+ export function mergeSubEntry(base, incoming) {
58
+ const successor = statusRank(incoming.status) > statusRank(base.status) ? incoming : base;
59
+ const status = successor.status;
60
+ const ended = isTerminalStatus(status);
61
+ return {
62
+ ...base,
63
+ ...incoming,
64
+ id: base.id,
65
+ status,
66
+ sessionId: incoming.sessionId ?? base.sessionId,
67
+ startedAt: minDefined(base.startedAt, incoming.startedAt) ?? base.startedAt,
68
+ endedAt: ended ? (base.endedAt ?? incoming.endedAt ?? Date.now()) : undefined,
69
+ tokens: maxDefined(base.tokens, incoming.tokens),
70
+ cost: maxDefined(base.cost, incoming.cost),
71
+ model: incoming.model ?? base.model,
72
+ todoTotal: maxDefined(base.todoTotal, incoming.todoTotal),
73
+ todoDone: maxDefined(base.todoDone, incoming.todoDone),
74
+ error: incoming.error ?? base.error,
75
+ cancelRequestedAt: minDefined(base.cancelRequestedAt, incoming.cancelRequestedAt),
76
+ abortAccepted: base.abortAccepted || incoming.abortAccepted || undefined,
77
+ cancelReason: incoming.cancelReason ?? base.cancelReason,
78
+ };
79
+ }
80
+ /**
81
+ * 合并两个条目集合,去重方式与 `upsertSubEntry` 相同
82
+ * (先子会话、后条目 id),冲突用 `mergeSubEntry` 合并。
83
+ * 所有持久化路径都走这里,避免并发实例以整表写入
84
+ * 互相丢弃对方的条目。
85
+ */
86
+ export function mergeSubEntries(base, incoming) {
87
+ const out = new Map();
88
+ for (const entry of base)
89
+ out.set(entry.id, entry);
90
+ for (const entry of incoming) {
91
+ const key = findSubEntryKey(out, entry.id, entry.sessionId);
92
+ if (!key) {
93
+ out.set(entry.id, entry);
94
+ continue;
95
+ }
96
+ out.set(key, mergeSubEntry(out.get(key), entry));
97
+ }
98
+ return out;
99
+ }
@@ -45,6 +45,14 @@ export interface PanelApi {
45
45
  messages(sid: string): unknown[] | undefined;
46
46
  /** Raw parts of a message (scan). */
47
47
  part(messageID: string): unknown[] | undefined;
48
+ /** Optional host-side fallback: map a subagent tool call to its child session
49
+ * when live events/history lack the link (V2 reads the local database). */
50
+ resolveChild?(input: {
51
+ parentId: string;
52
+ callId?: string;
53
+ agent?: string;
54
+ startedAt?: number;
55
+ }): string | undefined;
48
56
  };
49
57
  event: {
50
58
  on(type: PanelEventType, cb: (e: PanelEvent) => void): () => void;
package/dist/server.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  import type { PluginModule } from "@opencode-ai/plugin";
2
- declare const mod: PluginModule;
2
+ declare const mod: PluginModule & {
3
+ setup: () => Promise<void>;
4
+ };
3
5
  export default mod;
package/dist/server.js CHANGED
@@ -1,6 +1,14 @@
1
1
  const server = async () => ({});
2
+ /**
3
+ * V2 (opencode2) requires the default export to expose an `id` plus a
4
+ * `setup` (or `effect`) function. This plugin has no server-side behavior,
5
+ * so an empty setup keeps the module schema-valid and active on V2 while the
6
+ * `server` field stays for V1 detection.
7
+ */
8
+ const setup = async () => { };
2
9
  const mod = {
3
10
  id: "opencode-subagent-magazine",
4
11
  server,
12
+ setup,
5
13
  };
6
14
  export default mod;