dsh-reference-anything 0.4.4 → 0.5.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.
- package/NOTICE.md +58 -0
- package/README.md +146 -65
- package/cordis.patch.yml +17 -15
- package/images/agents/LICENSE +22 -0
- package/images/agents/README.md +3 -0
- package/images/agents/antigravity.svg +1 -0
- package/images/agents/chatgpt.svg +1 -0
- package/images/agents/claude.svg +1 -0
- package/images/agents/cline.svg +1 -0
- package/images/agents/codex.svg +1 -0
- package/images/agents/continue.svg +1 -0
- package/images/agents/crush.svg +1 -0
- package/images/agents/cursor.svg +1 -0
- package/images/agents/dsh.svg +1 -0
- package/images/agents/gemini.svg +1 -0
- package/images/agents/goose.svg +1 -0
- package/images/agents/grokbuild.svg +1 -0
- package/images/agents/hermes.svg +1 -0
- package/images/agents/kilocode.svg +1 -0
- package/images/agents/kimi.svg +1 -0
- package/images/agents/mimocode.svg +1 -0
- package/images/agents/openclaw.svg +1 -0
- package/images/agents/opencode.svg +1 -0
- package/images/agents/pi.svg +1 -0
- package/images/agents/qoder.svg +1 -0
- package/images/agents/qwen.svg +1 -0
- package/images/agents/reasonix.svg +6 -0
- package/images/agents/teleagent.svg +1 -0
- package/images/agents/trae.svg +1 -0
- package/images/agents/vibe.svg +1 -0
- package/images/agents/workbuddy.svg +37 -0
- package/images/agents/zcode.svg +1 -0
- package/images/agents/zed.svg +1 -0
- package/lib/agent-scan-cache.d.ts +13 -0
- package/lib/agent-scan-cache.js +43 -0
- package/lib/chat-import-compatibility.d.ts +18 -0
- package/lib/chat-import-compatibility.js +87 -0
- package/lib/chat-import-discovery.d.ts +32 -0
- package/lib/chat-import-discovery.js +17 -0
- package/lib/chat-import-reader.d.ts +27 -0
- package/lib/chat-import-reader.js +111 -0
- package/lib/chat-import-runtime.d.ts +4 -0
- package/lib/chat-import-runtime.js +4 -0
- package/lib/client/index.d.ts +5 -0
- package/lib/client.js +4 -34024
- package/lib/contract.d.ts +50 -3
- package/lib/contract.js +14 -4
- package/lib/conversation-availability.d.ts +13 -0
- package/lib/conversation-availability.js +76 -0
- package/lib/errors.d.ts +2 -2
- package/lib/host.d.ts +55 -11
- package/lib/host.js +197 -14
- package/lib/index.d.ts +3 -1
- package/lib/index.js +31 -3
- package/lib/local-conversation-reader.d.ts +3 -0
- package/lib/local-conversation-reader.js +81 -0
- package/lib/local-conversation-scanner.d.ts +18 -0
- package/lib/local-conversation-scanner.js +55 -0
- package/lib/local-locator.d.ts +14 -0
- package/lib/local-locator.js +34 -0
- package/lib/local-reference-tools.d.ts +4 -0
- package/lib/local-reference-tools.js +195 -0
- package/lib/local-reference.d.ts +118 -0
- package/lib/local-reference.js +289 -0
- package/lib/opencli.d.ts +5 -2
- package/lib/opencli.js +88 -64
- package/lib/reference.d.ts +5 -3
- package/lib/reference.js +167 -72
- package/lib/render.d.ts +1 -1
- package/lib/render.js +4 -4
- package/lib/retain.d.ts +14 -0
- package/lib/retain.js +1 -1
- package/lib/serialize.d.ts +1 -1
- package/lib/serialize.js +2 -2
- package/lib/sources/local-agent/index.d.ts +23 -16
- package/lib/sources/local-agent/index.js +101 -15
- package/lib/store/spec.d.ts +40 -7
- package/lib/sync/index.js +4 -0
- package/lib/tool.d.ts +2 -0
- package/lib/tool.js +36 -41
- package/lib/typert.js +2 -0
- package/lib/types.d.ts +2 -0
- package/lib/update.d.ts +2 -0
- package/lib/update.js +12 -0
- package/lib/uri-codec.d.ts +1 -0
- package/lib/uri-codec.js +64 -3
- package/lib/uri.d.ts +1 -10
- package/lib/uri.js +16 -5
- package/lib/wire.d.ts +59 -0
- package/lib/wire.js +13 -4
- package/opencli-plugin/common.js +5 -3
- package/opencli-plugin/opencli-plugin.json +1 -1
- package/opencli-plugin/package.json +1 -1
- package/package.json +28 -4
- 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/features.json +36 -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
- package/release-notes/0.5.0/features.json +65 -0
- package/release-notes/README.md +36 -0
- package/vendor/chat-import-reader/LICENSE +22 -0
- package/vendor/chat-import-reader/LICENSE.fzstd +21 -0
- package/vendor/chat-import-reader/README.md +48 -0
- package/vendor/chat-import-reader/availability-worker.mjs +114 -0
- package/vendor/chat-import-reader/parsers.d.mts +6 -0
- package/vendor/chat-import-reader/parsers.mjs +11168 -0
- package/vendor/chat-import-reader/scan-worker.mjs +7 -0
- package/vendor/chat-import-reader/scanners.mjs +4286 -0
- package/vendor/chat-import-reader/upstream-sha256.json +101 -0
package/lib/contract.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { InvocationDescriptor } from '@deepseek-ai/dsh-typert-protocol';
|
|
|
3
3
|
/**
|
|
4
4
|
* One local-agent transcript as the `@` menu sees it.
|
|
5
5
|
*
|
|
6
|
-
* `id` is
|
|
6
|
+
* `id` is a source-scoped `kind:relPath` or an opaque import-only selection, not a `dsh-ref:` URI — the client
|
|
7
7
|
* wraps it, the way it does for web chats, so the `'local-agent'` source string
|
|
8
8
|
* stays hardcoded in exactly one place. Deliberately carries no `origin`: the
|
|
9
9
|
* absolute path adds nothing a menu row can use and everything a screen-share
|
|
@@ -15,9 +15,19 @@ export declare const agentCandidateSchema: z.ZodReadonly<z.ZodObject<{
|
|
|
15
15
|
label: z.ZodString;
|
|
16
16
|
provider: z.ZodString;
|
|
17
17
|
updatedAt: z.ZodOptional<z.ZodNumber>;
|
|
18
|
+
referenceId: z.ZodOptional<z.ZodString>;
|
|
19
|
+
importOnly: z.ZodOptional<z.ZodBoolean>;
|
|
20
|
+
importStatus: z.ZodOptional<z.ZodEnum<{
|
|
21
|
+
imported: "imported";
|
|
22
|
+
partial: "partial";
|
|
23
|
+
"not-imported": "not-imported";
|
|
24
|
+
archived: "archived";
|
|
25
|
+
}>>;
|
|
26
|
+
warning: z.ZodOptional<z.ZodString>;
|
|
18
27
|
}, z.core.$strip>>;
|
|
19
28
|
export declare const agentStatsSchema: z.ZodReadonly<z.ZodObject<{
|
|
20
29
|
agent: z.ZodEnum<{
|
|
30
|
+
chatgpt: "chatgpt";
|
|
21
31
|
kimi: "kimi";
|
|
22
32
|
"claude-code": "claude-code";
|
|
23
33
|
codex: "codex";
|
|
@@ -32,8 +42,26 @@ export declare const agentStatsSchema: z.ZodReadonly<z.ZodObject<{
|
|
|
32
42
|
opencode: "opencode";
|
|
33
43
|
mimocode: "mimocode";
|
|
34
44
|
zcode: "zcode";
|
|
45
|
+
antigravity: "antigravity";
|
|
46
|
+
kilocode: "kilocode";
|
|
47
|
+
workbuddy: "workbuddy";
|
|
48
|
+
qwen: "qwen";
|
|
49
|
+
continue: "continue";
|
|
50
|
+
cline: "cline";
|
|
51
|
+
goose: "goose";
|
|
52
|
+
dsh4: "dsh4";
|
|
53
|
+
zed: "zed";
|
|
54
|
+
crush: "crush";
|
|
55
|
+
teleagent: "teleagent";
|
|
56
|
+
trae: "trae";
|
|
57
|
+
vibe: "vibe";
|
|
58
|
+
dsh: "dsh";
|
|
35
59
|
}>;
|
|
36
60
|
conversations: z.ZodNumber;
|
|
61
|
+
error: z.ZodOptional<z.ZodString>;
|
|
62
|
+
unavailable: z.ZodOptional<z.ZodBoolean>;
|
|
63
|
+
paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
64
|
+
readable: z.ZodOptional<z.ZodBoolean>;
|
|
37
65
|
}, z.core.$strip>>;
|
|
38
66
|
export declare const driveCandidateSchema: z.ZodReadonly<z.ZodObject<{
|
|
39
67
|
id: z.ZodString;
|
|
@@ -71,8 +99,8 @@ export declare const searchInputSchema: z.ZodReadonly<z.ZodObject<{
|
|
|
71
99
|
limit: z.ZodNumber;
|
|
72
100
|
}, z.core.$strip>>;
|
|
73
101
|
export declare const matchedViaSchema: z.ZodEnum<{
|
|
74
|
-
recent: "recent";
|
|
75
102
|
title: "title";
|
|
103
|
+
recent: "recent";
|
|
76
104
|
content: "content";
|
|
77
105
|
}>;
|
|
78
106
|
export declare const searchResultSchema: z.ZodReadonly<z.ZodObject<{
|
|
@@ -92,8 +120,8 @@ export declare const searchResultSchema: z.ZodReadonly<z.ZodObject<{
|
|
|
92
120
|
partial: z.ZodBoolean;
|
|
93
121
|
syncedAt: z.ZodString;
|
|
94
122
|
matchedVia: z.ZodEnum<{
|
|
95
|
-
recent: "recent";
|
|
96
123
|
title: "title";
|
|
124
|
+
recent: "recent";
|
|
97
125
|
content: "content";
|
|
98
126
|
}>;
|
|
99
127
|
snippet: z.ZodOptional<z.ZodString>;
|
|
@@ -120,6 +148,9 @@ export declare const healthSchema: z.ZodReadonly<z.ZodObject<{
|
|
|
120
148
|
}>;
|
|
121
149
|
extensionVersion: z.ZodOptional<z.ZodString>;
|
|
122
150
|
profileCount: z.ZodOptional<z.ZodNumber>;
|
|
151
|
+
latestExtensionVersion: z.ZodOptional<z.ZodString>;
|
|
152
|
+
extensionUpdateAvailable: z.ZodOptional<z.ZodBoolean>;
|
|
153
|
+
extensionCompatible: z.ZodOptional<z.ZodBoolean>;
|
|
123
154
|
opencliCompatible: z.ZodBoolean;
|
|
124
155
|
daemonVersion: z.ZodOptional<z.ZodString>;
|
|
125
156
|
daemonStale: z.ZodBoolean;
|
|
@@ -155,6 +186,8 @@ export declare const packageUpdateStatusSchema: z.ZodReadonly<z.ZodObject<{
|
|
|
155
186
|
releaseNotes: z.ZodOptional<z.ZodString>;
|
|
156
187
|
releaseUrl: z.ZodOptional<z.ZodString>;
|
|
157
188
|
error: z.ZodOptional<z.ZodString>;
|
|
189
|
+
currentReleaseNotes: z.ZodOptional<z.ZodString>;
|
|
190
|
+
currentReleaseUrl: z.ZodOptional<z.ZodString>;
|
|
158
191
|
}, z.core.$strip>>;
|
|
159
192
|
export declare const packageUpdateResultSchema: z.ZodReadonly<z.ZodObject<{
|
|
160
193
|
version: z.ZodString;
|
|
@@ -465,4 +498,18 @@ export declare const openListDisableMountSchema: z.ZodReadonly<z.ZodObject<{
|
|
|
465
498
|
export declare const openListUpgradeInputSchema: z.ZodReadonly<z.ZodObject<{
|
|
466
499
|
rollback: z.ZodOptional<z.ZodBoolean>;
|
|
467
500
|
}, z.core.$strict>>;
|
|
501
|
+
export declare const chatImportCompatibilitySchema: z.ZodReadonly<z.ZodObject<{
|
|
502
|
+
state: z.ZodEnum<{
|
|
503
|
+
unavailable: "unavailable";
|
|
504
|
+
disabled: "disabled";
|
|
505
|
+
ready: "ready";
|
|
506
|
+
incompatible: "incompatible";
|
|
507
|
+
installing: "installing";
|
|
508
|
+
"restart-required": "restart-required";
|
|
509
|
+
}>;
|
|
510
|
+
version: z.ZodString;
|
|
511
|
+
missing: z.ZodArray<z.ZodString>;
|
|
512
|
+
canUpgrade: z.ZodBoolean;
|
|
513
|
+
error: z.ZodOptional<z.ZodString>;
|
|
514
|
+
}, z.core.$strict>>;
|
|
468
515
|
export declare const REFERENCE_ANYTHING_INVOCATIONS: readonly InvocationDescriptor[];
|
package/lib/contract.js
CHANGED
|
@@ -3,14 +3,14 @@ import { localAgentSchema, providerSchema, settingsRecordSchema } from "./wire.j
|
|
|
3
3
|
/**
|
|
4
4
|
* One local-agent transcript as the `@` menu sees it.
|
|
5
5
|
*
|
|
6
|
-
* `id` is
|
|
6
|
+
* `id` is a source-scoped `kind:relPath` or an opaque import-only selection, not a `dsh-ref:` URI — the client
|
|
7
7
|
* wraps it, the way it does for web chats, so the `'local-agent'` source string
|
|
8
8
|
* stays hardcoded in exactly one place. Deliberately carries no `origin`: the
|
|
9
9
|
* absolute path adds nothing a menu row can use and everything a screen-share
|
|
10
10
|
* leaks.
|
|
11
11
|
*/
|
|
12
|
-
export const agentCandidateSchema = z.object({ id: z.string(), kind: z.string(), label: z.string(), provider: z.string(), updatedAt: z.number().optional() }).readonly();
|
|
13
|
-
export const agentStatsSchema = z.object({ agent: localAgentSchema, conversations: z.number().int().nonnegative() }).readonly();
|
|
12
|
+
export const agentCandidateSchema = z.object({ id: z.string(), kind: z.string(), label: z.string(), provider: z.string(), updatedAt: z.number().optional(), referenceId: z.string().optional(), importOnly: z.boolean().optional(), importStatus: z.enum(['imported', 'partial', 'not-imported', 'archived']).optional(), warning: z.string().optional() }).readonly();
|
|
13
|
+
export const agentStatsSchema = z.object({ agent: localAgentSchema, conversations: z.number().int().nonnegative(), error: z.string().optional(), unavailable: z.boolean().optional(), paths: z.array(z.string()).optional(), readable: z.boolean().optional() }).readonly();
|
|
14
14
|
// `origin` is the drive's own display path, shown under the candidate. It is
|
|
15
15
|
// never a download URL: those are signed with the account's credential and
|
|
16
16
|
// must not cross this wire.
|
|
@@ -49,6 +49,7 @@ export const healthSchema = z.object({
|
|
|
49
49
|
version: z.string(), daemon: z.string(), pluginInstalled: z.boolean(),
|
|
50
50
|
daemonRunning: z.boolean(), extensionConnected: z.boolean(), extensionState: extensionStateSchema,
|
|
51
51
|
extensionVersion: z.string().optional(), profileCount: z.number().int().nonnegative().optional(),
|
|
52
|
+
latestExtensionVersion: z.string().optional(), extensionUpdateAvailable: z.boolean().optional(), extensionCompatible: z.boolean().optional(),
|
|
52
53
|
opencliCompatible: z.boolean(), daemonVersion: z.string().optional(), daemonStale: z.boolean(),
|
|
53
54
|
connectivityOk: z.boolean(), connectivityChecked: z.boolean(), pluginVersion: z.string().optional(), adapterCommandsReady: z.boolean(), adapterCompatible: z.boolean(), latestVersion: z.string().optional(), updateAvailable: z.boolean(),
|
|
54
55
|
versionError: z.string().optional(), daemonError: z.string().optional(), pluginError: z.string().optional(), doctorError: z.string().optional(),
|
|
@@ -60,6 +61,7 @@ export const openCliDiscoverySchema = z.object({
|
|
|
60
61
|
export const packageUpdateStatusSchema = z.object({
|
|
61
62
|
currentVersion: z.string(), latestVersion: z.string(), updateAvailable: z.boolean(),
|
|
62
63
|
checkedAt: z.number().int().nonnegative(), releaseNotes: z.string().max(12_000).optional(), releaseUrl: z.string().url().optional(), error: z.string().optional(),
|
|
64
|
+
currentReleaseNotes: z.string().max(12_000).optional(), currentReleaseUrl: z.string().url().optional(),
|
|
63
65
|
}).readonly();
|
|
64
66
|
export const packageUpdateResultSchema = z.object({
|
|
65
67
|
version: z.string(), restartRequired: z.boolean(),
|
|
@@ -125,8 +127,16 @@ export const openListMountCreateSchema = z.object({ id: z.string().min(1).option
|
|
|
125
127
|
export const openListMountInputSchema = z.object({ id: z.string().min(1) }).strict().readonly();
|
|
126
128
|
export const openListDisableMountSchema = z.object({ id: z.string().min(1), disabled: z.boolean().optional() }).strict().readonly();
|
|
127
129
|
export const openListUpgradeInputSchema = z.object({ rollback: z.boolean().optional() }).strict().readonly();
|
|
130
|
+
export const chatImportCompatibilitySchema = z.object({
|
|
131
|
+
state: z.enum(['ready', 'incompatible', 'unavailable', 'disabled', 'installing', 'restart-required']),
|
|
132
|
+
version: z.string(), missing: z.array(z.string()), canUpgrade: z.boolean(), error: z.string().optional(),
|
|
133
|
+
}).strict().readonly();
|
|
128
134
|
export const REFERENCE_ANYTHING_INVOCATIONS = [
|
|
129
|
-
descriptor('
|
|
135
|
+
descriptor('chatImportStatus', [], strict('ChatImportCompatibility', chatImportCompatibilitySchema)),
|
|
136
|
+
descriptor('chatImportUpgradeInstall', [], strict('ChatImportCompatibility', chatImportCompatibilitySchema), true),
|
|
137
|
+
descriptor('agentResume', [agentLookup, { name: 'input', wire: 'input', source: 'json', codec: strict('AgentResumeInput', z.object({ id: z.string().min(1) }).strict().readonly()) }], strict('ResumeSummary', z.string().min(1)), true),
|
|
138
|
+
descriptor('agentImport', [agentLookup, { name: 'input', wire: 'input', source: 'json', codec: strict('AgentImportInput', z.object({ id: z.string().min(1) }).strict().readonly()) }], strict('ImportedSessionId', z.string().min(1)), true),
|
|
139
|
+
descriptor('agentSearch', [agentLookup, { name: 'input', wire: 'input', source: 'json', codec: strict('AgentSearchInput', z.object({ query: z.string(), limit: z.number().int().min(1).max(100), kind: localAgentSchema.optional() }).readonly()) }], strict('AgentCandidate[]', z.array(agentCandidateSchema)), true),
|
|
130
140
|
descriptor('agentStats', [], strict('AgentStats[]', z.array(agentStatsSchema)), true),
|
|
131
141
|
// No session lookup, unlike `agentSearch`: a drive is the same drive from
|
|
132
142
|
// every workspace, so there is nothing to scope the query to.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ChatImportTarget } from './chat-import-reader.ts';
|
|
2
|
+
/** Unknown/error rows stay visible. One background parser never delays discovery. */
|
|
3
|
+
export declare class ConversationAvailability {
|
|
4
|
+
private cache;
|
|
5
|
+
private queued;
|
|
6
|
+
private worker?;
|
|
7
|
+
private active?;
|
|
8
|
+
private timer?;
|
|
9
|
+
visible(target: ChatImportTarget): Promise<boolean>;
|
|
10
|
+
private next;
|
|
11
|
+
private failed;
|
|
12
|
+
dispose(): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
/** Unknown/error rows stay visible. One background parser never delays discovery. */
|
|
5
|
+
export class ConversationAvailability {
|
|
6
|
+
cache = new Map();
|
|
7
|
+
queued = new Map();
|
|
8
|
+
worker;
|
|
9
|
+
active;
|
|
10
|
+
timer;
|
|
11
|
+
async visible(target) {
|
|
12
|
+
const key = JSON.stringify(target);
|
|
13
|
+
const entry = this.cache.get(key);
|
|
14
|
+
if (entry) {
|
|
15
|
+
const unchanged = (await Promise.all(entry.dependencies.map(async ([path, version]) => {
|
|
16
|
+
try {
|
|
17
|
+
const s = await stat(path);
|
|
18
|
+
return version === `${s.size}:${s.mtimeMs}:${s.ctimeMs}`;
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
return error.code === 'ENOENT' && version === 'missing';
|
|
22
|
+
}
|
|
23
|
+
}))).every(Boolean);
|
|
24
|
+
if (unchanged && (entry.state !== 'unknown' || Date.now() - entry.checked < 300_000))
|
|
25
|
+
return entry.state !== 'empty';
|
|
26
|
+
this.cache.delete(key);
|
|
27
|
+
}
|
|
28
|
+
if (this.active !== key && this.queued.size < 128)
|
|
29
|
+
this.queued.set(key, target);
|
|
30
|
+
this.next();
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
next() {
|
|
34
|
+
if (this.active || !this.queued.size)
|
|
35
|
+
return;
|
|
36
|
+
const [id, target] = this.queued.entries().next().value;
|
|
37
|
+
this.queued.delete(id);
|
|
38
|
+
this.active = id;
|
|
39
|
+
if (!this.worker) {
|
|
40
|
+
// Native parser failures and V8 OOM must not terminate the DSH host.
|
|
41
|
+
this.worker = spawn(process.execPath, ['--max-old-space-size=256', fileURLToPath(new URL('../vendor/chat-import-reader/availability-worker.mjs', import.meta.url))], {
|
|
42
|
+
windowsHide: true, stdio: ['ignore', 'ignore', 'ignore', 'ipc'],
|
|
43
|
+
});
|
|
44
|
+
this.worker.on('message', (result) => {
|
|
45
|
+
if (result.id !== this.active)
|
|
46
|
+
return;
|
|
47
|
+
clearTimeout(this.timer);
|
|
48
|
+
if (this.cache.size >= 2000)
|
|
49
|
+
this.cache.delete(this.cache.keys().next().value);
|
|
50
|
+
this.cache.set(result.id, { ...result, checked: Date.now() });
|
|
51
|
+
this.active = undefined;
|
|
52
|
+
this.next();
|
|
53
|
+
});
|
|
54
|
+
this.worker.on('error', () => this.failed());
|
|
55
|
+
this.worker.on('exit', () => this.failed());
|
|
56
|
+
this.worker.unref();
|
|
57
|
+
this.worker.channel?.unref();
|
|
58
|
+
}
|
|
59
|
+
this.timer = setTimeout(() => this.failed(), 15_000);
|
|
60
|
+
this.timer.unref();
|
|
61
|
+
this.worker.send({ id, target });
|
|
62
|
+
}
|
|
63
|
+
failed() {
|
|
64
|
+
if (this.active)
|
|
65
|
+
this.cache.set(this.active, { state: 'unknown', dependencies: [], checked: Date.now() });
|
|
66
|
+
this.dispose();
|
|
67
|
+
this.next();
|
|
68
|
+
}
|
|
69
|
+
dispose() {
|
|
70
|
+
clearTimeout(this.timer);
|
|
71
|
+
this.worker?.removeAllListeners();
|
|
72
|
+
this.worker?.kill();
|
|
73
|
+
this.worker = undefined;
|
|
74
|
+
this.active = undefined;
|
|
75
|
+
}
|
|
76
|
+
}
|
package/lib/errors.d.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { HarnessError } from '@deepseek-ai/dsh-llm';
|
|
7
7
|
/** Stable, machine-routable failure classes; route on these, never on message text. */
|
|
8
|
-
export type ReferenceErrorCode =
|
|
8
|
+
export type ReferenceErrorCode = 'INVALID_ARGUMENT' | 'SOURCE_DISABLED' | 'ACCESS_DENIED' | 'NOT_FOUND' | 'REVISION_REQUIRED' | 'REVISION_CHANGED' | 'UNSUPPORTED_PART' | 'IMAGE_UNAVAILABLE' | 'IMAGE_TOO_LARGE' | 'BUDGET_TOO_SMALL' | 'READ_FAILED' | 'TIMEOUT' | 'CANCELLED'
|
|
9
9
|
/** Two sources claimed the same registry id. */
|
|
10
|
-
'SOURCE_DUPLICATE'
|
|
10
|
+
| 'SOURCE_DUPLICATE'
|
|
11
11
|
/** A reference named a source that is not registered. */
|
|
12
12
|
| 'SOURCE_UNKNOWN'
|
|
13
13
|
/** The owning source is registered but reported itself unusable. */
|
package/lib/host.d.ts
CHANGED
|
@@ -3,8 +3,50 @@ import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
|
3
3
|
import type { ChatProvider, SettingsRecord } from './store/spec.ts';
|
|
4
4
|
import type { SyncMode } from './sync/index.ts';
|
|
5
5
|
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
6
|
+
import { type LocalAgent } from './wire.ts';
|
|
7
|
+
import type { AgentCandidate } from './client/remote.ts';
|
|
8
|
+
declare module '@deepseek-ai/cordis' {
|
|
9
|
+
interface Context {
|
|
10
|
+
chatImport: {
|
|
11
|
+
readConversation?(input: {
|
|
12
|
+
format: string;
|
|
13
|
+
path: string;
|
|
14
|
+
sessionId?: string;
|
|
15
|
+
limit?: number;
|
|
16
|
+
before?: number;
|
|
17
|
+
revision?: string;
|
|
18
|
+
detail?: 'summary' | 'full';
|
|
19
|
+
}, signal?: AbortSignal): Promise<unknown>;
|
|
20
|
+
discoveryRoots?(): Record<string, string | string[] | null>;
|
|
21
|
+
scanDiscover(input: {
|
|
22
|
+
format?: string;
|
|
23
|
+
path?: string;
|
|
24
|
+
query?: string;
|
|
25
|
+
}, signal?: AbortSignal): Promise<unknown>;
|
|
26
|
+
importPath(input: {
|
|
27
|
+
format: string;
|
|
28
|
+
path: string;
|
|
29
|
+
sessionIds?: string[];
|
|
30
|
+
}, signal?: AbortSignal): Promise<unknown>;
|
|
31
|
+
resumeSummary(input: {
|
|
32
|
+
format: 'claude' | 'codex';
|
|
33
|
+
path: string;
|
|
34
|
+
}, signal?: AbortSignal): Promise<unknown>;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
6
38
|
export declare class ReferenceAnythingRemote extends TypertRemoteService {
|
|
39
|
+
chatImportStatus(): Promise<import("./chat-import-compatibility.ts").ChatImportCompatibility>;
|
|
40
|
+
chatImportUpgradeInstall(signal: AbortSignal): Promise<import("./chat-import-compatibility.ts").ChatImportCompatibility>;
|
|
41
|
+
private readonly agentScans;
|
|
42
|
+
private readonly scannedTargets;
|
|
7
43
|
constructor(ctx: Context);
|
|
44
|
+
agentResume(_agent: Agent, input: {
|
|
45
|
+
id: string;
|
|
46
|
+
}, signal: AbortSignal): Promise<string>;
|
|
47
|
+
agentImport(_agent: Agent, input: {
|
|
48
|
+
id: string;
|
|
49
|
+
}, signal: AbortSignal): Promise<string>;
|
|
8
50
|
/**
|
|
9
51
|
* Discovery for the `@` menu's local-agent group.
|
|
10
52
|
*
|
|
@@ -17,18 +59,17 @@ export declare class ReferenceAnythingRemote extends TypertRemoteService {
|
|
|
17
59
|
agentSearch(agent: Agent, input: {
|
|
18
60
|
query: string;
|
|
19
61
|
limit: number;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
updatedAt?: number | undefined;
|
|
23
|
-
id: string;
|
|
24
|
-
kind: string;
|
|
25
|
-
label: string;
|
|
26
|
-
provider: string;
|
|
27
|
-
}[]>;
|
|
62
|
+
kind?: LocalAgent;
|
|
63
|
+
}, signal: AbortSignal): Promise<AgentCandidate[]>;
|
|
28
64
|
agentStats(signal: AbortSignal): Promise<{
|
|
29
|
-
|
|
65
|
+
readable: boolean;
|
|
66
|
+
paths?: string[];
|
|
67
|
+
agent: LocalAgent;
|
|
30
68
|
conversations: number;
|
|
69
|
+
error?: string;
|
|
70
|
+
unavailable?: boolean;
|
|
31
71
|
}[]>;
|
|
72
|
+
private assertScannedSelection;
|
|
32
73
|
/**
|
|
33
74
|
* Discovery for the `@` menu's cloud-drive group.
|
|
34
75
|
*
|
|
@@ -86,10 +127,10 @@ export declare class ReferenceAnythingRemote extends TypertRemoteService {
|
|
|
86
127
|
historyMode: "metadata-only" | "offline-mirror";
|
|
87
128
|
syncHistoryDays: number | null;
|
|
88
129
|
enabledProviders: ("chatgpt" | "claude" | "gemini" | "deepseek" | "grok" | "kimi")[];
|
|
89
|
-
enabledAgents: ("kimi" | "claude-code" | "codex" | "cursor" | "qoder" | "reasonix" | "openclaw" | "grokbuild" | "hermes" | "gemini-cli" | "pi" | "opencode" | "mimocode" | "zcode")[];
|
|
130
|
+
enabledAgents: ("chatgpt" | "kimi" | "claude-code" | "codex" | "cursor" | "qoder" | "reasonix" | "openclaw" | "grokbuild" | "hermes" | "gemini-cli" | "pi" | "opencode" | "mimocode" | "zcode" | "antigravity" | "kilocode" | "workbuddy" | "qwen" | "continue" | "cline" | "goose" | "dsh4" | "zed" | "crush" | "teleagent" | "trae" | "vibe" | "dsh")[];
|
|
90
131
|
maxReadTurns: number;
|
|
91
132
|
inputRenderMode: "pill" | "raw-text";
|
|
92
|
-
agentDirectories?: Partial<Record<"kimi" | "claude-code" | "codex" | "cursor" | "qoder" | "reasonix" | "openclaw" | "grokbuild" | "hermes" | "gemini-cli" | "pi" | "opencode" | "mimocode" | "zcode", string>> | undefined;
|
|
133
|
+
agentDirectories?: Partial<Record<"chatgpt" | "kimi" | "claude-code" | "codex" | "cursor" | "qoder" | "reasonix" | "openclaw" | "grokbuild" | "hermes" | "gemini-cli" | "pi" | "opencode" | "mimocode" | "zcode" | "antigravity" | "kilocode" | "workbuddy" | "qwen" | "continue" | "cline" | "goose" | "dsh4" | "zed" | "crush" | "teleagent" | "trae" | "vibe" | "dsh", string>> | undefined;
|
|
93
134
|
enabledDriveMounts?: string[] | undefined;
|
|
94
135
|
picker?: {
|
|
95
136
|
displayMode: "collapse" | "native-scroll";
|
|
@@ -140,6 +181,9 @@ export declare class ReferenceAnythingRemote extends TypertRemoteService {
|
|
|
140
181
|
maxCandidates: number;
|
|
141
182
|
sort: "name" | "updated";
|
|
142
183
|
shortcut: string;
|
|
184
|
+
showImport: boolean;
|
|
185
|
+
showSummary: boolean;
|
|
186
|
+
skipConfirmation: boolean;
|
|
143
187
|
aliases?: string[] | undefined;
|
|
144
188
|
sourceAliases?: Record<string, string[]> | undefined;
|
|
145
189
|
};
|
package/lib/host.js
CHANGED
|
@@ -1,10 +1,75 @@
|
|
|
1
|
+
import { AgentScanCache } from "./agent-scan-cache.js";
|
|
2
|
+
import { localConversationRoots } from "./local-conversation-reader.js";
|
|
1
3
|
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
2
4
|
import { tmpdir } from 'node:os';
|
|
3
5
|
import { spawn } from 'node:child_process';
|
|
4
6
|
import { validateDownloadDirectory } from "./download-directory.js";
|
|
5
7
|
import { resolveLocalPlugins } from "./local-plugins.js";
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { randomUUID } from 'node:crypto';
|
|
10
|
+
import { discoverySchema, scanFormat, agentKind } from "./chat-import-discovery.js";
|
|
11
|
+
import { ALL_LOCAL_AGENTS, LOCAL_AGENT_LABEL } from "./wire.js";
|
|
12
|
+
import { expandRoot } from "./sources/local-agent/registry.js";
|
|
13
|
+
import { homedir } from 'node:os';
|
|
14
|
+
import { inWorkspace } from "./sources/local-agent/path.js";
|
|
15
|
+
import { chatImportCompatibility, upgradeChatImport } from "./chat-import-compatibility.js";
|
|
16
|
+
const importedItemSchema = z.object({
|
|
17
|
+
status: z.string(), sessionId: z.string().min(1).optional(),
|
|
18
|
+
error: z.string().optional(), reason: z.string().optional(), skipReason: z.string().optional(),
|
|
19
|
+
});
|
|
20
|
+
const chatImportResultSchema = z.discriminatedUnion('mode', [
|
|
21
|
+
importedItemSchema.extend({ mode: z.literal('single') }),
|
|
22
|
+
z.object({ mode: z.literal('batch'), results: z.array(importedItemSchema) }),
|
|
23
|
+
]);
|
|
6
24
|
export class ReferenceAnythingRemote extends TypertRemoteService {
|
|
25
|
+
async chatImportStatus() { return chatImportCompatibility(this.ctx); }
|
|
26
|
+
async chatImportUpgradeInstall(signal) {
|
|
27
|
+
await upgradeChatImport(this.ctx, signal);
|
|
28
|
+
return this.chatImportStatus();
|
|
29
|
+
}
|
|
30
|
+
agentScans = new AgentScanCache();
|
|
31
|
+
scannedTargets = new Map();
|
|
7
32
|
constructor(ctx) { super(ctx, 'referenceAnything'); }
|
|
33
|
+
async agentResume(_agent, input, signal) {
|
|
34
|
+
signal.throwIfAborted();
|
|
35
|
+
this.assertScannedSelection(_agent, input.id);
|
|
36
|
+
const importer = this.ctx.get('chatImport');
|
|
37
|
+
if (typeof importer?.resumeSummary !== 'function')
|
|
38
|
+
throw new Error('Chat Import API unavailable. Open Reference Anything settings → Local Agent conversations to check compatibility and upgrade, then restart DSH.');
|
|
39
|
+
const agents = this.ctx.get('referenceLocalAgents');
|
|
40
|
+
if (!agents)
|
|
41
|
+
throw new Error('Local agent conversations are unavailable.');
|
|
42
|
+
const { format, path } = await agents.importTarget(input.id);
|
|
43
|
+
if (format !== 'claude' && format !== 'codex')
|
|
44
|
+
throw new Error('Chat Import Resume supports Claude Code and Codex only.');
|
|
45
|
+
signal.throwIfAborted();
|
|
46
|
+
const result = await importer.resumeSummary({ format, path }, signal);
|
|
47
|
+
return z.object({ summary: z.string().min(1) }).parse(result).summary;
|
|
48
|
+
}
|
|
49
|
+
async agentImport(_agent, input, signal) {
|
|
50
|
+
signal.throwIfAborted();
|
|
51
|
+
const importer = this.ctx.get('chatImport');
|
|
52
|
+
if (typeof importer?.importPath !== 'function')
|
|
53
|
+
throw new Error('Chat Import API unavailable. Open Reference Anything settings → Local Agent conversations to check compatibility and upgrade, then restart DSH.');
|
|
54
|
+
const agents = this.ctx.get('referenceLocalAgents');
|
|
55
|
+
if (!agents)
|
|
56
|
+
throw new Error('Local agent conversations are unavailable.');
|
|
57
|
+
const scanned = input.id.startsWith('scan:') || input.id.includes(':chat-import:')
|
|
58
|
+
? this.scannedTargets.get(`${_agent.session.header.id}:${input.id}`) : undefined;
|
|
59
|
+
this.assertScannedSelection(_agent, input.id);
|
|
60
|
+
const target = scanned ? { format: scanned.format, path: scanned.path, sessionIds: scanned.sessionIds } : await agents.importTarget(input.id);
|
|
61
|
+
signal.throwIfAborted();
|
|
62
|
+
const result = await importer.importPath(target, signal);
|
|
63
|
+
const parsed = chatImportResultSchema.parse(result);
|
|
64
|
+
const items = parsed.mode === 'single' ? [parsed] : parsed.results;
|
|
65
|
+
if (items.length !== 1)
|
|
66
|
+
throw new Error('Expected exactly one imported conversation; no conversation was opened.');
|
|
67
|
+
const item = items[0];
|
|
68
|
+
if (!['imported', 'replaced', 'already-imported', 'appended'].includes(item.status) || !item.sessionId) {
|
|
69
|
+
throw new Error(`Conversation was not imported (${item.status}): ${item.error ?? item.reason ?? item.skipReason ?? ''}`);
|
|
70
|
+
}
|
|
71
|
+
return item.sessionId;
|
|
72
|
+
}
|
|
8
73
|
/**
|
|
9
74
|
* Discovery for the `@` menu's local-agent group.
|
|
10
75
|
*
|
|
@@ -18,26 +83,144 @@ export class ReferenceAnythingRemote extends TypertRemoteService {
|
|
|
18
83
|
const agents = this.ctx.get('referenceLocalAgents');
|
|
19
84
|
if (agents === undefined)
|
|
20
85
|
return [];
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
86
|
+
const importer = this.ctx.get('chatImport');
|
|
87
|
+
{
|
|
88
|
+
const settings = this.ctx.referenceChatHistory.getSettings();
|
|
89
|
+
agents.setAgentDirectories(settings.agentDirectories ?? {});
|
|
90
|
+
const policy = agents.discoveryPolicy();
|
|
91
|
+
const requests = policy.roots.map(root => ({ format: scanFormat(root.kind), path: root.path }));
|
|
92
|
+
{
|
|
93
|
+
for (const kind of ALL_LOCAL_AGENTS) {
|
|
94
|
+
if (!(settings.enabledAgents ?? ALL_LOCAL_AGENTS).includes(kind))
|
|
95
|
+
continue;
|
|
96
|
+
const format = scanFormat(kind);
|
|
97
|
+
requests.push({ format });
|
|
98
|
+
const custom = expandRoot(settings.agentDirectories?.[kind] ?? '', homedir());
|
|
99
|
+
if (custom)
|
|
100
|
+
requests.push({ format, path: custom });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const candidates = [];
|
|
104
|
+
const discovered = [];
|
|
105
|
+
const warnings = [];
|
|
106
|
+
const seen = new Set();
|
|
107
|
+
const owner = agent.session.header.id;
|
|
108
|
+
// Scope before scanning and deduplicate explicit roots repeated by settings.
|
|
109
|
+
const scannedRequests = new Set();
|
|
110
|
+
for (const request of requests) {
|
|
111
|
+
const kind = agentKind(request.format);
|
|
112
|
+
if ((input.kind && kind !== input.kind) || !(settings.enabledAgents ?? ALL_LOCAL_AGENTS).includes(kind))
|
|
113
|
+
continue;
|
|
114
|
+
const requestKey = JSON.stringify([request.format, request.path ?? null]);
|
|
115
|
+
if (scannedRequests.has(requestKey))
|
|
116
|
+
continue;
|
|
117
|
+
scannedRequests.add(requestKey);
|
|
118
|
+
signal.throwIfAborted();
|
|
119
|
+
try {
|
|
120
|
+
const result = await agents.scanner.scanDiscover(request, signal);
|
|
121
|
+
for (const warning of result.warnings)
|
|
122
|
+
warnings.push({ id: `warning:${warnings.length}`, kind: 'scan-warning', label: warning.format, provider: '', warning: `${warning.target}: ${warning.error}` });
|
|
123
|
+
for (const row of result.sessions) {
|
|
124
|
+
const query = input.query.trim().toLowerCase();
|
|
125
|
+
if (query && ![row.title, row.project, row.sourcePath].some(value => value?.toLowerCase().includes(query)))
|
|
126
|
+
continue;
|
|
127
|
+
const key = JSON.stringify([row.format, row.sourcePath, row.sessionId]);
|
|
128
|
+
if ((input.kind && agentKind(row.format) !== input.kind) || seen.has(key) || (policy.scope === 'workspace' && !inWorkspace(row.cwd ?? '', agent.session.header.cwd ?? process.cwd())))
|
|
129
|
+
continue;
|
|
130
|
+
seen.add(key);
|
|
131
|
+
discovered.push({ ...row });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
signal.throwIfAborted();
|
|
136
|
+
warnings.push({ id: `warning:${warnings.length}`, kind: 'scan-warning', label: request.format, provider: '', warning: error instanceof Error ? error.message : String(error) });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (importer?.scanDiscover) {
|
|
140
|
+
const statuses = new Map();
|
|
141
|
+
await Promise.all([...scannedRequests].map(async (key) => {
|
|
142
|
+
const [format, path] = JSON.parse(key);
|
|
143
|
+
try {
|
|
144
|
+
const result = await this.agentScans.read(importer, '', key, () => importer.scanDiscover({ format, ...(path ? { path } : {}) }, AbortSignal.timeout(2_000)), AbortSignal.any([signal, AbortSignal.timeout(2_000)]));
|
|
145
|
+
for (const row of result.sessions)
|
|
146
|
+
statuses.set(JSON.stringify([row.format, row.sourcePath, row.sessionId]), row.importStatus);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
signal.throwIfAborted();
|
|
150
|
+
}
|
|
151
|
+
}));
|
|
152
|
+
for (const row of discovered)
|
|
153
|
+
row.importStatus = statuses.get(JSON.stringify([row.format, row.sourcePath, row.sessionId]));
|
|
154
|
+
}
|
|
155
|
+
discovered.sort((a, b) => (b.lastActiveAt ?? 0) - (a.lastActiveAt ?? 0));
|
|
156
|
+
for (const row of discovered) {
|
|
157
|
+
signal.throwIfAborted();
|
|
158
|
+
if (candidates.length >= input.limit)
|
|
159
|
+
break;
|
|
160
|
+
if (!await agents.conversationAvailability.visible({ format: row.format, path: row.sourcePath, sessionId: row.sessionId }))
|
|
161
|
+
continue;
|
|
162
|
+
const kind = agentKind(row.format);
|
|
163
|
+
const referenceId = await agents.referenceForDiscovered(kind, row.sourcePath, row.sessionId);
|
|
164
|
+
if (!referenceId && settings.picker?.agents.showImport === false)
|
|
165
|
+
continue;
|
|
166
|
+
const id = referenceId ?? `scan:${randomUUID()}`;
|
|
167
|
+
if (!referenceId || referenceId.includes(':chat-import:')) {
|
|
168
|
+
this.scannedTargets.set(`${owner}:${id}`, { owner, policy: JSON.stringify(settings), format: row.format, path: row.sourcePath, sessionIds: [row.sessionId] });
|
|
169
|
+
if (this.scannedTargets.size > 2000)
|
|
170
|
+
this.scannedTargets.delete(this.scannedTargets.keys().next().value);
|
|
171
|
+
}
|
|
172
|
+
candidates.push({ id, kind, label: row.title || row.sessionId, provider: LOCAL_AGENT_LABEL[kind] ?? row.format,
|
|
173
|
+
...(referenceId ? { referenceId } : { importOnly: true }), importStatus: row.importStatus,
|
|
174
|
+
...(row.lastActiveAt == null ? {} : { updatedAt: row.lastActiveAt }) });
|
|
175
|
+
}
|
|
176
|
+
return [...warnings, ...candidates];
|
|
177
|
+
}
|
|
33
178
|
}
|
|
34
179
|
async agentStats(signal) {
|
|
35
180
|
signal.throwIfAborted();
|
|
36
181
|
const agents = this.ctx.get('referenceLocalAgents');
|
|
37
182
|
if (agents === undefined)
|
|
38
183
|
return [];
|
|
39
|
-
|
|
40
|
-
|
|
184
|
+
const settings = this.ctx.referenceChatHistory.getSettings();
|
|
185
|
+
agents.setAgentDirectories(settings.agentDirectories ?? {});
|
|
186
|
+
const rows = [];
|
|
187
|
+
for (const kind of ALL_LOCAL_AGENTS) {
|
|
188
|
+
const format = scanFormat(kind);
|
|
189
|
+
signal.throwIfAborted();
|
|
190
|
+
const sessions = new Set();
|
|
191
|
+
const errors = [];
|
|
192
|
+
const custom = expandRoot(settings.agentDirectories?.[kind] ?? '', homedir());
|
|
193
|
+
for (const path of custom ? [undefined, custom] : [undefined]) {
|
|
194
|
+
try {
|
|
195
|
+
const result = discoverySchema.parse(await agents.scanner.scanDiscover({ format, ...(path ? { path } : {}) }, signal));
|
|
196
|
+
for (const row of result.sessions) {
|
|
197
|
+
if (await agents.conversationAvailability.visible({ format: row.format, path: row.sourcePath, sessionId: row.sessionId }))
|
|
198
|
+
sessions.add(JSON.stringify([row.sourcePath, row.sessionId]));
|
|
199
|
+
}
|
|
200
|
+
errors.push(...result.warnings.map(warning => `${warning.target}: ${warning.error}`));
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
signal.throwIfAborted();
|
|
204
|
+
errors.push(error instanceof Error ? error.message : String(error));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
rows.push({ agent: kind, conversations: sessions.size, ...(errors.length ? { error: errors.join('\n') } : {}) });
|
|
208
|
+
}
|
|
209
|
+
const roots = localConversationRoots();
|
|
210
|
+
return rows.map(row => {
|
|
211
|
+
const root = roots?.[scanFormat(row.agent)];
|
|
212
|
+
const custom = settings.agentDirectories?.[row.agent];
|
|
213
|
+
const paths = [...new Set([...(Array.isArray(root) ? root : root ? [root] : []), ...(custom ? [custom] : [])])];
|
|
214
|
+
return { ...row, ...(roots ? { paths } : {}), readable: true };
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
assertScannedSelection(agent, id) {
|
|
218
|
+
if (!id.startsWith('scan:') && !id.includes(':chat-import:'))
|
|
219
|
+
return;
|
|
220
|
+
const selected = this.scannedTargets.get(`${agent.session.header.id}:${id}`);
|
|
221
|
+
if (!selected || selected.owner !== agent.session.header.id || selected.policy !== JSON.stringify(this.ctx.referenceChatHistory.getSettings())) {
|
|
222
|
+
throw new Error('Conversation selection expired. Search and select it again.');
|
|
223
|
+
}
|
|
41
224
|
}
|
|
42
225
|
/**
|
|
43
226
|
* Discovery for the `@` menu's cloud-drive group.
|
package/lib/index.d.ts
CHANGED
|
@@ -76,6 +76,8 @@ export default class ReferenceRuntime extends Service {
|
|
|
76
76
|
assertGranted(sessionId: string | undefined, ref: ReferenceRef): void;
|
|
77
77
|
/** Allow a gated URI granted live or named in this task's durable user/tool-result history. */
|
|
78
78
|
assertSessionGranted(session: Session | undefined, ref: ReferenceRef): void;
|
|
79
|
+
/** Resolve short handles only against references already named in this task. */
|
|
80
|
+
resolveReadReference(session: Session | undefined, uri: string): ReferenceRef;
|
|
79
81
|
/** Release task-local grants when a host knows the task is gone. */
|
|
80
82
|
revoke(sessionId: string): void;
|
|
81
83
|
/**
|
|
@@ -90,7 +92,7 @@ export default class ReferenceRuntime extends Service {
|
|
|
90
92
|
* @param signal - cancellation from the caller.
|
|
91
93
|
* @returns matching items, capped at `limit`.
|
|
92
94
|
*/
|
|
93
|
-
list(query?: string, limit?: number, signal?: AbortSignal): Promise<ReferenceSummary[]>;
|
|
95
|
+
list(query?: string, limit?: number, signal?: AbortSignal, externalOnly?: boolean): Promise<ReferenceSummary[]>;
|
|
94
96
|
/**
|
|
95
97
|
* Read one window of turns from a reference.
|
|
96
98
|
* @param ref - the reference to resolve; its `source` selects the owning implementation.
|