dsh-manage-session 0.5.7 → 2.0.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/CHANGELOG.ja.md +33 -229
- package/CHANGELOG.ko.md +33 -229
- package/CHANGELOG.md +33 -363
- package/INSTALL.ja.md +164 -164
- package/INSTALL.ko.md +164 -164
- package/INSTALL.md +164 -164
- package/INSTALL.zh.md +164 -164
- package/LICENSE +21 -21
- package/README.en.md +41 -46
- package/README.ja.md +33 -57
- package/README.ko.md +32 -55
- package/README.md +64 -64
- package/cordis.patch.yml +19 -16
- package/dsh.plugin.json +4 -4
- package/lib/client.js +661 -3082
- package/lib/index.d.ts +79 -970
- package/lib/index.js +249 -2669
- package/locale/de.json +2 -2
- package/locale/en.json +2 -2
- package/locale/es.json +2 -2
- package/locale/fr.json +2 -2
- package/locale/it.json +2 -2
- package/locale/ja.json +2 -2
- package/locale/ko.json +2 -2
- package/locale/ru.json +2 -2
- package/locale/zh.json +2 -2
- package/package.json +15 -25
- package/screenshots.json +3 -3
- package/src/client/bridge-scope.ts +202 -213
- package/src/client/card.tsx +154 -154
- package/src/client/health-panel.tsx +49 -49
- package/src/client/host-api.ts +72 -6
- package/src/client/index.ts +594 -503
- package/src/client/locales.ts +893 -893
- package/src/client/manage-locales.ts +178 -0
- package/src/client/{search/manage.tsx → manage.tsx} +430 -404
- package/src/client/panel.tsx +131 -129
- package/src/client/session-menu-legacy.ts +2 -3
- package/src/client/session-menu.tsx +5 -5
- package/src/config.ts +43 -99
- package/src/host/health/attribution.ts +118 -118
- package/src/host/health/lossless.ts +128 -128
- package/src/host/health/repair.ts +2 -2
- package/src/host/health/source-kind.ts +350 -350
- package/src/host/history/archive-source.ts +250 -250
- package/src/host/history/archive.ts +249 -249
- package/src/host/history/favorites.ts +71 -71
- package/src/host/history/purge.ts +370 -370
- package/src/host/history/tombstones.ts +3 -3
- package/src/host/registry/archive-registry.ts +317 -317
- package/src/host/settings-bridge.ts +222 -264
- package/src/index.ts +66 -694
- package/src/client/search/card.tsx +0 -563
- package/src/client/search/host-api.ts +0 -213
- package/src/client/search/locales.ts +0 -861
- package/src/client/search/locate.ts +0 -330
- package/src/client/search/panel.tsx +0 -940
- package/src/client/search/platform.ts +0 -136
- package/src/host/index/archive-source.ts +0 -90
- package/src/host/index/drs-source.ts +0 -211
- package/src/host/index/engine.ts +0 -699
- package/src/host/index/extract.ts +0 -272
- package/src/host/index/peers.ts +0 -62
- package/src/host/index/rebuild.ts +0 -432
- package/src/host/index/schema.ts +0 -136
- package/src/host/index/snapshot.ts +0 -135
- package/src/host/index/sync.ts +0 -413
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Client-side helpers and structural mirrors shared by the search panel and
|
|
3
|
-
* the settings card. Everything talks to the host through the fenced
|
|
4
|
-
* `/switch-search/api` route; no official package is value-imported.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/** Fetch timeout for one host call (long for import: the body can be large). */
|
|
8
|
-
const FETCH_TIMEOUT = 10_000
|
|
9
|
-
|
|
10
|
-
/** POST a JSON body to a fenced switch-search API method (items shape). */
|
|
11
|
-
export function callHost<T>(method: string, body: unknown): Promise<{ ok: boolean; items: T[]; error?: string }> {
|
|
12
|
-
const controller = typeof AbortController === 'undefined' ? undefined : new AbortController()
|
|
13
|
-
const timer = controller !== undefined && typeof setTimeout === 'function'
|
|
14
|
-
? setTimeout(() => { controller.abort() }, FETCH_TIMEOUT)
|
|
15
|
-
: undefined
|
|
16
|
-
return fetch(`/switch-search/api/${method}`, {
|
|
17
|
-
method: 'POST',
|
|
18
|
-
headers: { 'content-type': 'application/json' },
|
|
19
|
-
body: JSON.stringify(body),
|
|
20
|
-
signal: controller?.signal,
|
|
21
|
-
})
|
|
22
|
-
.then((res) => (res.ok ? res.json() : Promise.reject(new Error(`HTTP ${res.status}`))))
|
|
23
|
-
.then((data: unknown) => {
|
|
24
|
-
const record = data as { ok?: boolean; items?: T[]; error?: string }
|
|
25
|
-
if (record && record.ok === true && Array.isArray(record.items)) {
|
|
26
|
-
return { ok: true, items: record.items }
|
|
27
|
-
}
|
|
28
|
-
return { ok: false, items: [], error: record?.error ?? '请求失败' }
|
|
29
|
-
})
|
|
30
|
-
.catch((err: unknown) => ({
|
|
31
|
-
ok: false,
|
|
32
|
-
items: [],
|
|
33
|
-
error: err instanceof DOMException && err.name === 'AbortError' ? '请求超时' : String(err instanceof Error ? err.message : err),
|
|
34
|
-
}))
|
|
35
|
-
.finally(() => {
|
|
36
|
-
if (timer !== undefined) clearTimeout(timer)
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/** POST a body to a fenced switch-search API method, returning the whole record. */
|
|
41
|
-
export function callHostAny<T>(method: string, body: unknown, timeout = FETCH_TIMEOUT): Promise<Partial<T> & { ok: boolean; error?: string }> {
|
|
42
|
-
const controller = typeof AbortController === 'undefined' ? undefined : new AbortController()
|
|
43
|
-
const timer = typeof setTimeout === 'function'
|
|
44
|
-
? setTimeout(() => { controller?.abort() }, timeout)
|
|
45
|
-
: undefined
|
|
46
|
-
return fetch(`/switch-search/api/${method}`, {
|
|
47
|
-
method: 'POST',
|
|
48
|
-
headers: { 'content-type': 'application/json' },
|
|
49
|
-
body: typeof body === 'string' ? body : JSON.stringify(body),
|
|
50
|
-
signal: controller?.signal,
|
|
51
|
-
})
|
|
52
|
-
.then((res) => (res.ok ? res.json() : Promise.reject(new Error(`HTTP ${res.status}`))))
|
|
53
|
-
.catch((err: unknown) => ({
|
|
54
|
-
ok: false,
|
|
55
|
-
error: err instanceof DOMException && err.name === 'AbortError' ? '请求超时' : String(err instanceof Error ? err.message : err),
|
|
56
|
-
}))
|
|
57
|
-
.finally(() => {
|
|
58
|
-
if (timer !== undefined) clearTimeout(timer)
|
|
59
|
-
})
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** One session listed for the title-search corpus. */
|
|
63
|
-
export interface HostSessionItem {
|
|
64
|
-
sessionId: string
|
|
65
|
-
title: string
|
|
66
|
-
cwd: string
|
|
67
|
-
updatedAt: number
|
|
68
|
-
/**
|
|
69
|
-
* 归档标记(R1 合表语义)。旧宿主半缺省该字段时按 undefined 处理——
|
|
70
|
-
* 归档筛选 chip 对 undefined 行按「活跃」对待,与旧数据形状兼容。
|
|
71
|
-
*/
|
|
72
|
-
archived?: boolean
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* One content-search hit (session-level: title + strongest snippet).
|
|
77
|
-
* `time` belongs to the strongest matching document; `updatedAt` is the
|
|
78
|
-
* session-level clock and is what recency ordering keys on. Both ship so the
|
|
79
|
-
* panel can re-sort locally without another round-trip.
|
|
80
|
-
*/
|
|
81
|
-
export interface HostContentHit {
|
|
82
|
-
sessionId: string
|
|
83
|
-
title: string
|
|
84
|
-
snippet: string
|
|
85
|
-
seq: number
|
|
86
|
-
type: string
|
|
87
|
-
time: number
|
|
88
|
-
updatedAt: number
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** Result ordering accepted by the host `content-search` method. */
|
|
92
|
-
export type HostSortMode = 'relevance' | 'time'
|
|
93
|
-
|
|
94
|
-
/** Host watermark-sync state (subset used here). */
|
|
95
|
-
export interface HostSyncState {
|
|
96
|
-
state: string
|
|
97
|
-
indexed: number
|
|
98
|
-
total: number
|
|
99
|
-
updated: number
|
|
100
|
-
lastSyncAt: number
|
|
101
|
-
failures: { sessionId: string; error: string }[]
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/** Host rebuild ("整理") state (subset used here). */
|
|
105
|
-
export interface HostRebuildState {
|
|
106
|
-
state: string
|
|
107
|
-
done: number
|
|
108
|
-
total: number
|
|
109
|
-
error?: string
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/** Host independent-index status (subset used here). */
|
|
113
|
-
export interface HostIndexStatus {
|
|
114
|
-
ok: boolean
|
|
115
|
-
available: boolean
|
|
116
|
-
reason?: string
|
|
117
|
-
dir?: string
|
|
118
|
-
archives?: string[]
|
|
119
|
-
archivedSessions?: number
|
|
120
|
-
/**
|
|
121
|
-
* Resolution state of the peer plugin that owns archiving. Absent on an
|
|
122
|
-
* older host half — treated as `unknown`, which renders the neutral hint.
|
|
123
|
-
*/
|
|
124
|
-
steward?: 'installed' | 'missing' | 'unknown'
|
|
125
|
-
/**
|
|
126
|
-
* 直接删除入口开关(功能①,管家 session-steward.directDelete):true 时
|
|
127
|
-
* 面板结果行渲染行内删除按钮。旧宿主半无此字段 = undefined = 不渲染。
|
|
128
|
-
*/
|
|
129
|
-
directDelete?: boolean
|
|
130
|
-
sync?: HostSyncState
|
|
131
|
-
rebuild?: HostRebuildState
|
|
132
|
-
error?: string
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* POST to the STEWARD fenced route (`/session-steward/api`) — the batch
|
|
137
|
-
* management console (archive / unarchive / purge) rides the steward subdomain,
|
|
138
|
-
* per the merged package's route contract (session-* methods stay there).
|
|
139
|
-
*/
|
|
140
|
-
export function callSteward<T>(method: string, body: unknown, timeout = FETCH_TIMEOUT): Promise<Partial<T> & { ok: boolean; error?: string }> {
|
|
141
|
-
const controller = typeof AbortController === 'undefined' ? undefined : new AbortController()
|
|
142
|
-
const timer = typeof setTimeout === 'function'
|
|
143
|
-
? setTimeout(() => { controller?.abort() }, timeout)
|
|
144
|
-
: undefined
|
|
145
|
-
return fetch(`/session-steward/api/${method}`, {
|
|
146
|
-
method: 'POST',
|
|
147
|
-
headers: { 'content-type': 'application/json' },
|
|
148
|
-
body: JSON.stringify(body),
|
|
149
|
-
signal: controller?.signal,
|
|
150
|
-
})
|
|
151
|
-
.then((res) => (res.ok ? res.json() : Promise.reject(new Error(`HTTP ${res.status}`))))
|
|
152
|
-
.catch((err: unknown) => ({
|
|
153
|
-
ok: false,
|
|
154
|
-
error: err instanceof DOMException && err.name === 'AbortError' ? '请求超时' : String(err instanceof Error ? err.message : err),
|
|
155
|
-
}))
|
|
156
|
-
.finally(() => {
|
|
157
|
-
if (timer !== undefined) clearTimeout(timer)
|
|
158
|
-
})
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/** Trigger a browser download of the index snapshot from the host route. */
|
|
162
|
-
export async function downloadSnapshot(): Promise<void> {
|
|
163
|
-
const res = await fetch('/switch-search/api/index-export', { method: 'POST' })
|
|
164
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`)
|
|
165
|
-
const blob = await res.blob()
|
|
166
|
-
const url = URL.createObjectURL(blob)
|
|
167
|
-
const anchor = document.createElement('a')
|
|
168
|
-
anchor.href = url
|
|
169
|
-
anchor.download = `switch-search-snapshot-${new Date().toISOString().slice(0, 10)}.jsonl`
|
|
170
|
-
anchor.click()
|
|
171
|
-
URL.revokeObjectURL(url)
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* The client sessions service face. Host lines before 0.1.7 exposed session
|
|
176
|
-
* navigation here as `open`; the 0.1.7 contract dropped it ("navigation
|
|
177
|
-
* belongs to view owners") — kept only as the legacy fallback of
|
|
178
|
-
* `openSessionThrough`.
|
|
179
|
-
*/
|
|
180
|
-
export interface SwitchSessionsService {
|
|
181
|
-
open(id: string): void
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* The client ui-workspace face: session navigation has been owned by this
|
|
186
|
-
* service since host 0.1.7 (`openSession`; `SessionTarget = SessionId |
|
|
187
|
-
* SubagentAddress`, so a bare session id is accepted).
|
|
188
|
-
*/
|
|
189
|
-
export interface SwitchUiWorkspaceService {
|
|
190
|
-
openSession(target: string): void
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Open a session from a search hit through whichever face the running host
|
|
195
|
-
* offers: `uiWorkspace.openSession` first (0.1.7+), the pre-0.1.7
|
|
196
|
-
* `sessions.open` as fallback. Neither present → silent no-op: a host line
|
|
197
|
-
* this package does not target must not crash the panel.
|
|
198
|
-
*
|
|
199
|
-
* The service names are resolved through `get` at call time, not captured at
|
|
200
|
-
* apply time: this plugin applies before the session-controller / ui-workspace
|
|
201
|
-
* client modules in the load order, so an eager lookup captures `undefined`
|
|
202
|
-
* and every result click silently no-ops. Both are root-context singletons,
|
|
203
|
-
* so by the time a user clicks a hit they are always mounted.
|
|
204
|
-
*/
|
|
205
|
-
export function openSessionThrough(get: (name: string) => unknown, sessionId: string): void {
|
|
206
|
-
const uiWorkspace = get('uiWorkspace') as SwitchUiWorkspaceService | undefined
|
|
207
|
-
if (uiWorkspace !== undefined && typeof uiWorkspace.openSession === 'function') {
|
|
208
|
-
uiWorkspace.openSession(sessionId)
|
|
209
|
-
return
|
|
210
|
-
}
|
|
211
|
-
const sessions = get('sessions') as SwitchSessionsService | undefined
|
|
212
|
-
if (sessions !== undefined && typeof sessions.open === 'function') sessions.open(sessionId)
|
|
213
|
-
}
|