opencode-subagent-magazine 1.6.0-beta.2 → 1.6.0-beta.4

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/src/core/index.ts CHANGED
@@ -1,6 +1,6 @@
1
- export * from "./types"
2
- export * from "./format"
3
- export * from "./color"
4
- export * from "./kv"
5
- export * from "./usage"
6
- export * from "./state-machine"
1
+ export * from "./types"
2
+ export * from "./format"
3
+ export * from "./color"
4
+ export * from "./kv"
5
+ export * from "./usage"
6
+ export * from "./state-machine"
package/src/core/kv.ts CHANGED
@@ -1,36 +1,37 @@
1
- import type { SessionRecord } from "./types"
2
-
3
- export const KV_PREFIX = "subagent_magazine"
4
- export const SESSION_DATA_KEY = `${KV_PREFIX}.session_data`
5
-
6
- /** Minimal KV surface used by the magazine's persistence layer. */
7
- export interface KVApi {
8
- get(key: string, fallback?: unknown): unknown
9
- set(key: string, value: unknown): void
10
- }
11
-
12
- /** Setting keys shared by V1/V2 (values are raw strings in KV). */
13
- export const SETTING_KEYS = {
14
- lang: `${KV_PREFIX}.lang`,
15
- maxEntries: `${KV_PREFIX}.max_entries`,
16
- order: `${KV_PREFIX}.order`,
17
- scrollMode: `${KV_PREFIX}.scroll_mode`,
18
- open: `${KV_PREFIX}.open`,
19
- ttlDays: `${KV_PREFIX}.ttl_days`,
20
- } as const
21
-
22
- export function loadSessionData(kv: KVApi): Record<string, SessionRecord> {
23
- try {
24
- const raw = kv.get(SESSION_DATA_KEY, "{}")
25
- return JSON.parse(String(raw))
26
- } catch { return {} }
27
- }
28
-
29
- export function saveSessionData(kv: KVApi, data: Record<string, SessionRecord>) {
30
- try { kv.set(SESSION_DATA_KEY, JSON.stringify(data)) } catch {}
31
- }
32
-
33
- export function readTTLDays(kv: KVApi): number {
34
- const ttlDaysRaw = parseInt(String(kv.get(SETTING_KEYS.ttlDays, "3")), 10)
35
- return Number.isNaN(ttlDaysRaw) ? 3 : ttlDaysRaw
36
- }
1
+ import type { SessionRecord } from "./types"
2
+
3
+ export const KV_PREFIX = "subagent_magazine"
4
+ export const SESSION_DATA_KEY = `${KV_PREFIX}.session_data`
5
+
6
+ /** Minimal KV surface used by the magazine's persistence layer. */
7
+ export interface KVApi {
8
+ get(key: string, fallback?: unknown): unknown
9
+ set(key: string, value: unknown): void
10
+ }
11
+
12
+ /** Setting keys shared by V1/V2 (values are raw strings in KV). */
13
+ export const SETTING_KEYS = {
14
+ lang: `${KV_PREFIX}.lang`,
15
+ maxEntries: `${KV_PREFIX}.max_entries`,
16
+ order: `${KV_PREFIX}.order`,
17
+ scrollMode: `${KV_PREFIX}.scroll_mode`,
18
+ open: `${KV_PREFIX}.open`,
19
+ ttlDays: `${KV_PREFIX}.ttl_days`,
20
+ border: `${KV_PREFIX}.border`,
21
+ } as const
22
+
23
+ export function loadSessionData(kv: KVApi): Record<string, SessionRecord> {
24
+ try {
25
+ const raw = kv.get(SESSION_DATA_KEY, "{}")
26
+ return JSON.parse(String(raw))
27
+ } catch { return {} }
28
+ }
29
+
30
+ export function saveSessionData(kv: KVApi, data: Record<string, SessionRecord>) {
31
+ try { kv.set(SESSION_DATA_KEY, JSON.stringify(data)) } catch {}
32
+ }
33
+
34
+ export function readTTLDays(kv: KVApi): number {
35
+ const ttlDaysRaw = parseInt(String(kv.get(SETTING_KEYS.ttlDays, "3")), 10)
36
+ return Number.isNaN(ttlDaysRaw) ? 3 : ttlDaysRaw
37
+ }
@@ -1,46 +1,46 @@
1
- import type { SubEntry, SubStatus } from "./types"
2
- import type { TodoStats } from "./usage"
3
-
4
- /** Final status decision when a child session settles (V1 `session.idle` semantics). */
5
- export function settleOnIdle(entry: SubEntry): SubStatus {
6
- if (entry.status === "cancel_requested" && entry.abortAccepted) return "cancelled"
7
- return "done"
8
- }
9
-
10
- /** Agent-name normalization used by the fallback matching chain. */
11
- export function normalizeAgent(s: string): string {
12
- return s.toLowerCase().replace(/[^a-z0-9-]/g, "")
13
- }
14
-
15
- /** Snapshot of usage values captured when a child session settles. */
16
- export interface SettleSnapshot {
17
- tokens?: number
18
- cost?: number
19
- model?: string
20
- todo?: TodoStats
21
- }
22
-
23
- /** Apply a settled status + usage backfill onto an entry (no-op preserving already-settled). */
24
- export function settleEntry(
25
- entry: SubEntry,
26
- targetStatus: SubStatus,
27
- nowTs: number,
28
- snap: SettleSnapshot,
29
- errorMsg?: string,
30
- ): SubEntry {
31
- const alreadySettled = entry.status !== "running" && entry.status !== "cancel_requested"
32
- const finalStatus = targetStatus === "error" ? "error" : settleOnIdle(entry)
33
- return {
34
- ...entry,
35
- ...(alreadySettled ? {} : { status: finalStatus, endedAt: nowTs }),
36
- tokens: entry.tokens ?? snap.tokens,
37
- cost: entry.cost ?? snap.cost,
38
- model: entry.model ?? snap.model,
39
- todoTotal: entry.todoTotal ?? snap.todo?.total,
40
- todoDone: entry.todoDone ?? snap.todo?.done,
41
- error: errorMsg || entry.error,
42
- }
43
- }
44
-
45
- /** Time-based scan heuristic: how old must a running entry be before assuming completion. */
46
- export const STALE_RUNNING_MS = 30 * 60 * 1000
1
+ import type { SubEntry, SubStatus } from "./types"
2
+ import type { TodoStats } from "./usage"
3
+
4
+ /** Final status decision when a child session settles (V1 `session.idle` semantics). */
5
+ export function settleOnIdle(entry: SubEntry): SubStatus {
6
+ if (entry.status === "cancel_requested" && entry.abortAccepted) return "cancelled"
7
+ return "done"
8
+ }
9
+
10
+ /** Agent-name normalization used by the fallback matching chain. */
11
+ export function normalizeAgent(s: string): string {
12
+ return s.toLowerCase().replace(/[^a-z0-9-]/g, "")
13
+ }
14
+
15
+ /** Snapshot of usage values captured when a child session settles. */
16
+ export interface SettleSnapshot {
17
+ tokens?: number
18
+ cost?: number
19
+ model?: string
20
+ todo?: TodoStats
21
+ }
22
+
23
+ /** Apply a settled status + usage backfill onto an entry (no-op preserving already-settled). */
24
+ export function settleEntry(
25
+ entry: SubEntry,
26
+ targetStatus: SubStatus,
27
+ nowTs: number,
28
+ snap: SettleSnapshot,
29
+ errorMsg?: string,
30
+ ): SubEntry {
31
+ const alreadySettled = entry.status !== "running" && entry.status !== "cancel_requested"
32
+ const finalStatus = targetStatus === "error" ? "error" : settleOnIdle(entry)
33
+ return {
34
+ ...entry,
35
+ ...(alreadySettled ? {} : { status: finalStatus, endedAt: nowTs }),
36
+ tokens: entry.tokens ?? snap.tokens,
37
+ cost: entry.cost ?? snap.cost,
38
+ model: entry.model ?? snap.model,
39
+ todoTotal: entry.todoTotal ?? snap.todo?.total,
40
+ todoDone: entry.todoDone ?? snap.todo?.done,
41
+ error: errorMsg || entry.error,
42
+ }
43
+ }
44
+
45
+ /** Time-based scan heuristic: how old must a running entry be before assuming completion. */
46
+ export const STALE_RUNNING_MS = 30 * 60 * 1000
package/src/core/types.ts CHANGED
@@ -54,5 +54,7 @@ export interface SharedSignals {
54
54
  setSortOrder: (o: SortOrder) => void
55
55
  scrollMode: () => ScrollMode
56
56
  setScrollMode: (m: ScrollMode) => void
57
+ borderVisible: () => boolean
58
+ setBorderVisible: (v: boolean) => void
57
59
  sessionId: string
58
60
  }
package/src/core/usage.ts CHANGED
@@ -1,16 +1,16 @@
1
- export interface TodoStats {
2
- total: number
3
- done: number
4
- }
5
-
6
- /**
7
- * Data-source abstraction for per-session usage reads.
8
- * V1 and V2 provide their own implementations backed by their respective
9
- * client APIs; the state machine consumes only this surface.
10
- */
11
- export interface UsageReader {
12
- readSessionTokens(sid: string): number | undefined
13
- readSessionCost(sid: string): number | undefined
14
- readSessionModel(sid: string): string | undefined
15
- readSessionTodo(sid: string): TodoStats | undefined
16
- }
1
+ export interface TodoStats {
2
+ total: number
3
+ done: number
4
+ }
5
+
6
+ /**
7
+ * Data-source abstraction for per-session usage reads.
8
+ * V1 and V2 provide their own implementations backed by their respective
9
+ * client APIs; the state machine consumes only this surface.
10
+ */
11
+ export interface UsageReader {
12
+ readSessionTokens(sid: string): number | undefined
13
+ readSessionCost(sid: string): number | undefined
14
+ readSessionModel(sid: string): string | undefined
15
+ readSessionTodo(sid: string): TodoStats | undefined
16
+ }
package/src/i18n.ts CHANGED
@@ -56,6 +56,8 @@ const ZH_T = {
56
56
  "cancel.status_error": "无法查询会话状态",
57
57
  "cancel.sent": "已发送取消指令",
58
58
  "cancel.failed": "取消失败",
59
+ "borderShown": "面板边框 已显示",
60
+ "borderHidden": "面板边框 已隐藏",
59
61
  } as const
60
62
 
61
63
  /** 结构约束:值放宽为 string,键集合来自中文表(新增语言缺 key 会编译报错)。 */
@@ -111,6 +113,8 @@ const EN_T: Translation = {
111
113
  "cancel.status_error": "Cannot query session status",
112
114
  "cancel.sent": "Cancel instruction sent",
113
115
  "cancel.failed": "Cancellation failed",
116
+ "borderShown": "Panel border shown",
117
+ "borderHidden": "Panel border hidden",
114
118
  }
115
119
 
116
120
  const JA_T: Translation = {
@@ -163,6 +167,8 @@ const JA_T: Translation = {
163
167
  "cancel.status_error": "セッション状態を照会できません",
164
168
  "cancel.sent": "キャンセル指示を送信しました",
165
169
  "cancel.failed": "キャンセルに失敗しました",
170
+ "borderShown": "パネル枠線 表示",
171
+ "borderHidden": "パネル枠線 非表示",
166
172
  }
167
173
 
168
174
  const KO_T: Translation = {
@@ -215,6 +221,8 @@ const KO_T: Translation = {
215
221
  "cancel.status_error": "세션 상태를 조회할 수 없습니다",
216
222
  "cancel.sent": "취소 지시를 보냈습니다",
217
223
  "cancel.failed": "취소에 실패했습니다",
224
+ "borderShown": "패널 테두리 표시",
225
+ "borderHidden": "패널 테두리 숨김",
218
226
  }
219
227
 
220
228
  export const LANGS: Record<LangCode, Translation> = { zh: ZH_T, en: EN_T, ja: JA_T, ko: KO_T }