dsh-reference-anything 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/LICENSE +22 -22
- package/NOTICE.md +110 -110
- package/README.md +472 -459
- package/cordis.patch.yml +136 -136
- package/docs/release/0.4.4/README.md +75 -0
- package/{release-notes → docs/release}/0.4.4/features.json +36 -36
- package/docs/release/0.5.0/README.md +148 -0
- package/{release-notes → docs/release}/0.5.0/features.json +65 -65
- package/docs/release/0.5.1/README.md +33 -0
- package/docs/release/0.5.2/README.md +51 -0
- package/docs/release/0.5.2/features.json +29 -0
- package/{release-notes → docs/release}/README.md +42 -38
- package/images/agents/LICENSE +22 -22
- package/images/agents/README.md +7 -3
- package/images/agents/antigravity.svg +1 -1
- package/images/agents/cline.svg +1 -1
- package/images/agents/continue.svg +1 -1
- package/images/agents/copilot.svg +27 -0
- package/images/agents/crush.svg +1 -1
- package/images/agents/doubao.svg +1 -0
- package/images/agents/goose.svg +1 -1
- package/images/agents/omp.svg +1 -0
- package/images/agents/reasonix.svg +5 -5
- package/images/agents/teleagent.svg +1 -1
- package/images/agents/trae.svg +1 -1
- package/images/agents/vibe.svg +1 -1
- package/images/agents/workbuddy.svg +37 -37
- package/images/agents/zed.svg +1 -1
- package/lib/chat-import-compatibility.js +8 -5
- package/lib/client.js +36526 -4
- package/lib/contract.d.ts +4 -0
- package/lib/host.d.ts +2 -2
- package/lib/local-conversation-reader.js +16 -11
- package/lib/render.js +21 -21
- package/lib/store/spec.d.ts +9 -1
- package/lib/tool.js +3 -2
- package/lib/wire.d.ts +13 -1
- package/lib/wire.js +5 -4
- package/locale/en.json +6 -6
- package/locale/zh.json +6 -6
- package/opencli-plugin/chatgpt.js +128 -128
- package/opencli-plugin/claude.js +138 -138
- package/opencli-plugin/common.js +452 -452
- package/opencli-plugin/deepseek.js +155 -155
- package/opencli-plugin/gemini.js +169 -169
- package/opencli-plugin/grok.js +124 -124
- package/opencli-plugin/kimi.js +126 -126
- package/opencli-plugin/opencli-plugin.json +6 -6
- package/opencli-plugin/package.json +8 -8
- package/opencli-plugin/since-guard.js +45 -45
- package/package.json +263 -262
- package/vendor/chat-import-reader/LICENSE +22 -22
- package/vendor/chat-import-reader/LICENSE.fzstd +20 -20
- package/vendor/chat-import-reader/README.md +54 -48
- package/vendor/chat-import-reader/availability-worker.mjs +119 -114
- package/vendor/chat-import-reader/parsers.d.mts +6 -6
- package/vendor/chat-import-reader/parsers.mjs +13069 -11168
- package/vendor/chat-import-reader/scan-worker.mjs +7 -7
- package/vendor/chat-import-reader/scanners.mjs +5523 -4286
- package/vendor/chat-import-reader/upstream-sha256.json +114 -101
- package/release-notes/0.4.4/commands.png +0 -0
- package/release-notes/0.4.4/demos/agent-import.gif +0 -0
- package/release-notes/0.4.4/demos/chat-import-upgrade.gif +0 -0
- package/release-notes/0.4.4/demos/folders.gif +0 -0
- package/release-notes/0.4.4/demos/local-plugins.gif +0 -0
- package/release-notes/0.4.4/demos/shortcuts.gif +0 -0
- package/release-notes/0.4.4/files.png +0 -0
- package/release-notes/0.5.0/demos/agent-import.gif +0 -0
- package/release-notes/0.5.0/demos/chat-import-upgrade.gif +0 -0
- package/release-notes/0.5.0/demos/folders.gif +0 -0
- package/release-notes/0.5.0/demos/local-plugins.gif +0 -0
- package/release-notes/0.5.0/demos/local-references.gif +0 -0
- package/release-notes/0.5.0/demos/shortcuts.gif +0 -0
|
@@ -1,48 +1,54 @@
|
|
|
1
|
-
# Bundled conversation scanners and readers
|
|
2
|
-
|
|
3
|
-
Derived from [dsh-chat-import](https://github.com/Nwflower/dsh-chat-import), npm
|
|
4
|
-
0.26.
|
|
5
|
-
Both generated bundles include fzstd (MIT); `LICENSE` and `LICENSE.fzstd` ship
|
|
6
|
-
with the package. Upstream paths in comments are not runtime dependencies.
|
|
7
|
-
|
|
8
|
-
`parsers.mjs` exposes preview-based text/image reading and default roots.
|
|
9
|
-
`scanners.mjs` reuses all upstream source descriptors and SQLite summary readers.
|
|
10
|
-
The scan entry provides filesystem-only access and runs in `scan-worker.mjs`,
|
|
11
|
-
without plugin registration or session mutations. The host caches metadata for
|
|
12
|
-
30 seconds; missing paths are empty, while permission/database errors are warnings.
|
|
13
|
-
Import status is not inferred locally: Reference Anything asks the optional
|
|
14
|
-
Chat Import API separately. Import and summaries also remain API operations.
|
|
15
|
-
|
|
16
|
-
Local patches expose preview content, preserve Trae message parts, export the
|
|
17
|
-
upstream database-summary table, and replace a dynamic Trae scanner import with
|
|
18
|
-
a static named import so mutation code can be removed by tree shaking.
|
|
19
|
-
The generator rejects leaked mutation code and changed patch anchors.
|
|
20
|
-
Antigravity IDE typed tool results (directory/file reads, code actions,
|
|
21
|
-
subagents, commands and searches) are matched by tool name rather than discarded
|
|
22
|
-
as missing background output; GENERIC results keep their existing handling.
|
|
23
|
-
Async sidecar reports only supplement GENERIC results, never replace typed output.
|
|
24
|
-
Hermes SQLite and JSONL reads preserve tool-only assistant messages, OpenAI-style
|
|
25
|
-
function calls, and role=tool results. Results are associated by call ID, including
|
|
26
|
-
parallel calls; string arguments and result text remain unchanged.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
1
|
+
# Bundled conversation scanners and readers
|
|
2
|
+
|
|
3
|
+
Derived from [dsh-chat-import](https://github.com/Nwflower/dsh-chat-import), npm
|
|
4
|
+
0.26.3 (MIT). `upstream-sha256.json` records the exact version and source hashes.
|
|
5
|
+
Both generated bundles include fzstd (MIT); `LICENSE` and `LICENSE.fzstd` ship
|
|
6
|
+
with the package. Upstream paths in comments are not runtime dependencies.
|
|
7
|
+
|
|
8
|
+
`parsers.mjs` exposes preview-based text/image reading and default roots.
|
|
9
|
+
`scanners.mjs` reuses all upstream source descriptors and SQLite summary readers.
|
|
10
|
+
The scan entry provides filesystem-only access and runs in `scan-worker.mjs`,
|
|
11
|
+
without plugin registration or session mutations. The host caches metadata for
|
|
12
|
+
30 seconds; missing paths are empty, while permission/database errors are warnings.
|
|
13
|
+
Import status is not inferred locally: Reference Anything asks the optional
|
|
14
|
+
Chat Import API separately. Import and summaries also remain API operations.
|
|
15
|
+
|
|
16
|
+
Local patches expose preview content, preserve Trae message parts, export the
|
|
17
|
+
upstream database-summary table, and replace a dynamic Trae scanner import with
|
|
18
|
+
a static named import so mutation code can be removed by tree shaking.
|
|
19
|
+
The generator rejects leaked mutation code and changed patch anchors.
|
|
20
|
+
Antigravity IDE typed tool results (directory/file reads, code actions,
|
|
21
|
+
subagents, commands and searches) are matched by tool name rather than discarded
|
|
22
|
+
as missing background output; GENERIC results keep their existing handling.
|
|
23
|
+
Async sidecar reports only supplement GENERIC results, never replace typed output.
|
|
24
|
+
Hermes SQLite and JSONL reads preserve tool-only assistant messages, OpenAI-style
|
|
25
|
+
function calls, and role=tool results. Results are associated by call ID, including
|
|
26
|
+
parallel calls; string arguments and result text remain unchanged.
|
|
27
|
+
|
|
28
|
+
The 0.26.3 snapshot adds Copilot VS Code, Copilot CLI and Doubao Desktop.
|
|
29
|
+
Doubao reads cached local IndexedDB bodies only. Its directory entries must be
|
|
30
|
+
regular files, and child-file fingerprints invalidate revisions and availability
|
|
31
|
+
checks when the database changes. Background availability checks leave databases
|
|
32
|
+
larger than 8 MiB unknown instead of eagerly parsing them.
|
|
33
|
+
|
|
34
|
+
## Update from upstream
|
|
35
|
+
|
|
36
|
+
1. Download/build the desired upstream version in a separate directory (or use
|
|
37
|
+
an installed npm package directory). Do not overwrite the running Desktop plugin.
|
|
38
|
+
2. Run `npm run vendor:sync -- <built-dsh-chat-import-directory>` from this repository.
|
|
39
|
+
This regenerates both bundles and their shared version/hash manifest. Normal
|
|
40
|
+
builds never download upstream or inspect another installed plugin.
|
|
41
|
+
3. Review source/version/license changes, then run `npm run agent:verify` and
|
|
42
|
+
test the Web profile with Chat Import disabled and enabled. The catalog test
|
|
43
|
+
detects new upstream formats that need settings/icon/type support here.
|
|
44
|
+
4. Ship the verified snapshot in a new Reference Anything release. Users receive
|
|
45
|
+
upstream changes when updating Reference Anything, not automatically at runtime.
|
|
46
|
+
|
|
47
|
+
Parsing a reference may read its whole source before returning a page. Images
|
|
48
|
+
require recoverable bytes or a valid attachment; unavailable images are reported.
|
|
49
|
+
|
|
50
|
+
The structured read projection numbers body messages independently of tools,
|
|
51
|
+
links tool records and images to those numbers, and hashes normalized source
|
|
52
|
+
content before applying presentation budgets. The host adds original-file
|
|
53
|
+
fingerprints/version checks. This projection is used for automatic send-time
|
|
54
|
+
previews and numeric read/search/image calls; it retains no parsed-body cache.
|
|
@@ -1,114 +1,119 @@
|
|
|
1
|
-
import { parentPort } from 'node:worker_threads'
|
|
2
|
-
import { readFile, readdir, stat } from 'node:fs/promises'
|
|
3
|
-
import { join, resolve } from 'node:path'
|
|
4
|
-
import { homedir } from 'node:os'
|
|
5
|
-
import { readConversation } from './parsers.mjs'
|
|
6
|
-
const channel = parentPort || { on: (...args) => process.on(...args), postMessage: value => process.send(value) }
|
|
7
|
-
if (!parentPort) process.on('disconnect', () => process.exit(0))
|
|
8
|
-
|
|
9
|
-
// Parsing stays off the picker thread. Only states and file fingerprints cross back.
|
|
10
|
-
channel.on('message', async ({ id, target }) => {
|
|
11
|
-
const dependencies = new Map()
|
|
12
|
-
const inspect = async path => {
|
|
13
|
-
try {
|
|
14
|
-
const s = await stat(path)
|
|
15
|
-
dependencies.set(path, `${s.size}:${s.mtimeMs}:${s.ctimeMs}`)
|
|
16
|
-
return { type: s.isDirectory() ? 'directory' : 'file', size: s.size, mtimeMs: s.mtimeMs }
|
|
17
|
-
} catch (error) {
|
|
18
|
-
if (error.code !== 'ENOENT') throw error
|
|
19
|
-
dependencies.set(path, 'missing')
|
|
20
|
-
return undefined
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
const fs = {
|
|
24
|
-
resolve: async path => ({ displayPath: resolve(path) }),
|
|
25
|
-
processPath: value => value.displayPath,
|
|
26
|
-
stat: async value => inspect(value.displayPath),
|
|
27
|
-
readText: async value => {
|
|
28
|
-
const info = await inspect(value.displayPath)
|
|
29
|
-
// shortcut: large sources stay unknown; use streaming probes before raising this background budget.
|
|
30
|
-
if (info?.size > 8 * 1024 * 1024) throw new Error('Background validation budget exceeded')
|
|
31
|
-
const raw = await readFile(value.displayPath, 'utf8')
|
|
32
|
-
// A tolerant converter may skip broken lines; that must never prove emptiness.
|
|
33
|
-
if (/\.jsonl$/i.test(value.displayPath)) for (const line of raw.split(/\r?\n/)) if (line.trim()) JSON.parse(line)
|
|
34
|
-
return raw
|
|
35
|
-
},
|
|
36
|
-
listDir: async value => {
|
|
37
|
-
await inspect(value.displayPath)
|
|
38
|
-
return (await readdir(value.displayPath, { withFileTypes: true })).map(e => ({
|
|
39
|
-
name: e.name, type: e.isDirectory() ? 'directory' : 'file', target: { displayPath: join(value.displayPath, e.name) },
|
|
40
|
-
}))
|
|
41
|
-
},
|
|
42
|
-
}
|
|
43
|
-
let state = 'unknown'
|
|
44
|
-
try {
|
|
45
|
-
const info = await inspect(target.path)
|
|
46
|
-
if (!info || (info.type === 'file' && info.size === 0)) state = 'empty'
|
|
47
|
-
else if (target.format === 'claude' && /\.json$/i.test(target.path)) {
|
|
48
|
-
const meta = JSON.parse(await fs.readText({ displayPath: target.path }))
|
|
49
|
-
if (meta.cliSessionId && !meta.messages) {
|
|
50
|
-
// Match the exact CLI identity; never substitute another chat in the project.
|
|
51
|
-
const root = join(homedir(), '.claude', 'projects')
|
|
52
|
-
let found = false
|
|
53
|
-
const walk = async dir => {
|
|
54
|
-
await inspect(dir)
|
|
55
|
-
for (const e of await readdir(dir, { withFileTypes: true })) {
|
|
56
|
-
if (e.isDirectory()) await walk(join(dir, e.name))
|
|
57
|
-
else if (e.name === `${meta.cliSessionId}.jsonl`) found = true
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (await inspect(root)) await walk(root)
|
|
61
|
-
state = found ? 'unknown' : 'empty'
|
|
62
|
-
}
|
|
63
|
-
} else {
|
|
64
|
-
if (info.type === 'directory' &&
|
|
65
|
-
const names = target.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
1
|
+
import { parentPort } from 'node:worker_threads'
|
|
2
|
+
import { readFile, readdir, stat } from 'node:fs/promises'
|
|
3
|
+
import { join, resolve } from 'node:path'
|
|
4
|
+
import { homedir } from 'node:os'
|
|
5
|
+
import { readConversation } from './parsers.mjs'
|
|
6
|
+
const channel = parentPort || { on: (...args) => process.on(...args), postMessage: value => process.send(value) }
|
|
7
|
+
if (!parentPort) process.on('disconnect', () => process.exit(0))
|
|
8
|
+
|
|
9
|
+
// Parsing stays off the picker thread. Only states and file fingerprints cross back.
|
|
10
|
+
channel.on('message', async ({ id, target }) => {
|
|
11
|
+
const dependencies = new Map()
|
|
12
|
+
const inspect = async path => {
|
|
13
|
+
try {
|
|
14
|
+
const s = await stat(path)
|
|
15
|
+
dependencies.set(path, `${s.size}:${s.mtimeMs}:${s.ctimeMs}`)
|
|
16
|
+
return { type: s.isDirectory() ? 'directory' : 'file', size: s.size, mtimeMs: s.mtimeMs }
|
|
17
|
+
} catch (error) {
|
|
18
|
+
if (error.code !== 'ENOENT') throw error
|
|
19
|
+
dependencies.set(path, 'missing')
|
|
20
|
+
return undefined
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const fs = {
|
|
24
|
+
resolve: async path => ({ displayPath: resolve(path) }),
|
|
25
|
+
processPath: value => value.displayPath,
|
|
26
|
+
stat: async value => inspect(value.displayPath),
|
|
27
|
+
readText: async value => {
|
|
28
|
+
const info = await inspect(value.displayPath)
|
|
29
|
+
// shortcut: large sources stay unknown; use streaming probes before raising this background budget.
|
|
30
|
+
if (info?.size > 8 * 1024 * 1024) throw new Error('Background validation budget exceeded')
|
|
31
|
+
const raw = await readFile(value.displayPath, 'utf8')
|
|
32
|
+
// A tolerant converter may skip broken lines; that must never prove emptiness.
|
|
33
|
+
if (/\.jsonl$/i.test(value.displayPath)) for (const line of raw.split(/\r?\n/)) if (line.trim()) JSON.parse(line)
|
|
34
|
+
return raw
|
|
35
|
+
},
|
|
36
|
+
listDir: async value => {
|
|
37
|
+
await inspect(value.displayPath)
|
|
38
|
+
return (await readdir(value.displayPath, { withFileTypes: true })).map(e => ({
|
|
39
|
+
name: e.name, type: e.isDirectory() ? 'directory' : 'file', target: { displayPath: join(value.displayPath, e.name) },
|
|
40
|
+
}))
|
|
41
|
+
},
|
|
42
|
+
}
|
|
43
|
+
let state = 'unknown'
|
|
44
|
+
try {
|
|
45
|
+
const info = await inspect(target.path)
|
|
46
|
+
if (!info || (info.type === 'file' && info.size === 0)) state = 'empty'
|
|
47
|
+
else if (target.format === 'claude' && /\.json$/i.test(target.path)) {
|
|
48
|
+
const meta = JSON.parse(await fs.readText({ displayPath: target.path }))
|
|
49
|
+
if (meta.cliSessionId && !meta.messages) {
|
|
50
|
+
// Match the exact CLI identity; never substitute another chat in the project.
|
|
51
|
+
const root = join(homedir(), '.claude', 'projects')
|
|
52
|
+
let found = false
|
|
53
|
+
const walk = async dir => {
|
|
54
|
+
await inspect(dir)
|
|
55
|
+
for (const e of await readdir(dir, { withFileTypes: true })) {
|
|
56
|
+
if (e.isDirectory()) await walk(join(dir, e.name))
|
|
57
|
+
else if (e.name === `${meta.cliSessionId}.jsonl`) found = true
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (await inspect(root)) await walk(root)
|
|
61
|
+
state = found ? 'unknown' : 'empty'
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
if (info.type === 'directory' && target.format === 'doubao') {
|
|
65
|
+
const names = (await readdir(target.path)).filter(name => /\.(ldb|log)$/.test(name))
|
|
66
|
+
const files = await Promise.all(names.map(name => inspect(join(target.path, name))))
|
|
67
|
+
if (files.reduce((sum, file) => sum + (file?.size || 0), 0) > 8 * 1024 * 1024) throw new Error('Background validation budget exceeded')
|
|
68
|
+
}
|
|
69
|
+
if (info.type === 'directory' && ['grokbuild', 'vibe', 'kimi'].includes(target.format)) {
|
|
70
|
+
const names = target.format === 'grokbuild' ? ['chat_history.jsonl']
|
|
71
|
+
: target.format === 'vibe' ? ['messages.jsonl'] : ['wire.jsonl', 'agents/main/wire.jsonl']
|
|
72
|
+
const bodies = await Promise.all(names.map(name => inspect(join(target.path, name))))
|
|
73
|
+
if (bodies.every(body => !body || body.size === 0)) {
|
|
74
|
+
channel.postMessage({ id, state: 'empty', dependencies: [...dependencies] })
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (/\.(?:db|vscdb)$/i.test(target.path)) {
|
|
79
|
+
await inspect(target.path + '-wal')
|
|
80
|
+
await inspect(target.path + '-shm')
|
|
81
|
+
const schemas = {
|
|
82
|
+
opencode: ['session', 'message'], mimocode: ['session', 'message'], kilocode: ['session', 'message'],
|
|
83
|
+
teleagent: ['session', 'message'], zcode: ['session', 'message'],
|
|
84
|
+
hermes: ['sessions', 'messages'], goose: ['sessions', 'messages'], crush: ['sessions', 'messages'],
|
|
85
|
+
}
|
|
86
|
+
let schema = schemas[target.format]
|
|
87
|
+
if (schema) {
|
|
88
|
+
const { DatabaseSync } = await import('node:sqlite')
|
|
89
|
+
const db = new DatabaseSync(target.path, { readOnly: true })
|
|
90
|
+
try {
|
|
91
|
+
const tables = new Set(db.prepare("SELECT name FROM sqlite_master WHERE type='table'").all().map(r => r.name))
|
|
92
|
+
if (schema[0] === 'session' && tables.has('session_v2')) schema = ['session_v2', 'session_message']
|
|
93
|
+
if (tables.has(schema[0]) && tables.has(schema[1])
|
|
94
|
+
&& db.prepare(`SELECT 1 FROM ${schema[0]} WHERE id = ? LIMIT 1`).get(target.sessionId)
|
|
95
|
+
&& !db.prepare(`SELECT 1 FROM ${schema[1]} WHERE session_id = ? LIMIT 1`).get(target.sessionId)) {
|
|
96
|
+
channel.postMessage({ id, state: 'empty', dependencies: [...dependencies] })
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
} finally { db.close() }
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (target.format === 'chatgpt') {
|
|
103
|
+
const exported = JSON.parse(await fs.readText({ displayPath: target.path }))
|
|
104
|
+
const chat = Array.isArray(exported) ? exported.find(c => c.id === target.sessionId) : null
|
|
105
|
+
if (chat?.mapping && Object.values(chat.mapping).every(node => node && !node.message)) {
|
|
106
|
+
channel.postMessage({ id, state: 'empty', dependencies: [...dependencies] })
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
state = await readConversation(fs, { ...target, limit: 1, detail: 'full', probe: true })
|
|
111
|
+
if (state === 'unknown' && ['pi', 'codex', 'openclaw', 'hermes', 'dsh', 'dsh4'].includes(target.format) && info.type === 'file' && !/\.(db|vscdb|zstd)$/i.test(target.path)) {
|
|
112
|
+
const records = (await fs.readText({ displayPath: target.path })).split(/\r?\n/).filter(line => line.trim()).map(line => JSON.parse(line))
|
|
113
|
+
const allowed = target.format === 'codex' ? ['session_meta'] : ['session', 'session_info', 'session/title']
|
|
114
|
+
if (records.length && records.every(r => allowed.includes(r.type))) state = 'empty'
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
} catch { state = 'unknown' }
|
|
118
|
+
channel.postMessage({ id, state, dependencies: [...dependencies] })
|
|
119
|
+
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export function defaultRoots(): Record<string, string | string[] | null>
|
|
2
|
-
export function readConversation(fs: unknown, input: {
|
|
3
|
-
format: string; path: string; sessionId: string; limit: number;
|
|
4
|
-
before?: number; revision?: string; detail: 'summary' | 'full';
|
|
5
|
-
probe?: boolean; structured?: boolean;
|
|
6
|
-
}, signal?: AbortSignal): Promise<unknown>
|
|
1
|
+
export function defaultRoots(): Record<string, string | string[] | null>
|
|
2
|
+
export function readConversation(fs: unknown, input: {
|
|
3
|
+
format: string; path: string; sessionId: string; limit: number;
|
|
4
|
+
before?: number; revision?: string; detail: 'summary' | 'full';
|
|
5
|
+
probe?: boolean; structured?: boolean;
|
|
6
|
+
}, signal?: AbortSignal): Promise<unknown>
|