dsh-reference-anything 0.3.0 → 0.3.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.
Files changed (109) hide show
  1. package/LICENSE +22 -22
  2. package/NOTICE.md +52 -25
  3. package/README.md +339 -286
  4. package/cordis.patch.yml +89 -18
  5. package/lib/client.js +13538 -591
  6. package/lib/contract.d.ts +155 -16
  7. package/lib/contract.js +68 -7
  8. package/lib/download-directory.d.ts +18 -0
  9. package/lib/download-directory.js +55 -0
  10. package/lib/errors.d.ts +4 -0
  11. package/lib/host.d.ts +96 -8
  12. package/lib/host.js +88 -19
  13. package/lib/index.d.ts +22 -2
  14. package/lib/index.js +57 -7
  15. package/lib/opencli.d.ts +5 -3
  16. package/lib/opencli.js +13 -6
  17. package/lib/openlist/host.d.ts +157 -0
  18. package/lib/openlist/host.js +873 -0
  19. package/lib/openlist/index.d.ts +84 -0
  20. package/lib/openlist/index.js +507 -0
  21. package/lib/render.d.ts +12 -7
  22. package/lib/render.js +27 -21
  23. package/lib/sources/cloud-drive/cache.d.ts +60 -0
  24. package/lib/sources/cloud-drive/cache.js +107 -0
  25. package/lib/sources/cloud-drive/index.d.ts +190 -0
  26. package/lib/sources/cloud-drive/index.js +526 -0
  27. package/lib/sources/cloud-drive/providers/http.d.ts +27 -0
  28. package/lib/sources/cloud-drive/providers/http.js +73 -0
  29. package/lib/sources/cloud-drive/providers/openlist.d.ts +59 -0
  30. package/lib/sources/cloud-drive/providers/openlist.js +535 -0
  31. package/lib/sources/cloud-drive/registry.d.ts +53 -0
  32. package/lib/sources/cloud-drive/registry.js +101 -0
  33. package/lib/sources/cloud-drive/types.d.ts +169 -0
  34. package/lib/sources/cloud-drive/types.js +17 -0
  35. package/lib/sources/file.d.ts +2 -0
  36. package/lib/sources/file.js +2 -0
  37. package/lib/sources/local-agent/adapters/claude-code.d.ts +16 -0
  38. package/lib/sources/local-agent/adapters/claude-code.js +171 -0
  39. package/lib/sources/local-agent/adapters/codex.d.ts +20 -0
  40. package/lib/sources/local-agent/adapters/codex.js +204 -0
  41. package/lib/sources/local-agent/adapters/cursor.d.ts +23 -0
  42. package/lib/sources/local-agent/adapters/cursor.js +121 -0
  43. package/lib/sources/local-agent/adapters/gemini-cli.d.ts +20 -0
  44. package/lib/sources/local-agent/adapters/gemini-cli.js +141 -0
  45. package/lib/sources/local-agent/adapters/grokbuild.d.ts +22 -0
  46. package/lib/sources/local-agent/adapters/grokbuild.js +76 -0
  47. package/lib/sources/local-agent/adapters/hermes.d.ts +19 -0
  48. package/lib/sources/local-agent/adapters/hermes.js +85 -0
  49. package/lib/sources/local-agent/adapters/kimi.d.ts +28 -0
  50. package/lib/sources/local-agent/adapters/kimi.js +261 -0
  51. package/lib/sources/local-agent/adapters/openclaw.d.ts +21 -0
  52. package/lib/sources/local-agent/adapters/openclaw.js +120 -0
  53. package/lib/sources/local-agent/adapters/opencode.d.ts +44 -0
  54. package/lib/sources/local-agent/adapters/opencode.js +236 -0
  55. package/lib/sources/local-agent/adapters/pi.d.ts +26 -0
  56. package/lib/sources/local-agent/adapters/pi.js +242 -0
  57. package/lib/sources/local-agent/adapters/qoder.d.ts +19 -0
  58. package/lib/sources/local-agent/adapters/qoder.js +93 -0
  59. package/lib/sources/local-agent/adapters/reasonix.d.ts +23 -0
  60. package/lib/sources/local-agent/adapters/reasonix.js +90 -0
  61. package/lib/sources/local-agent/adapters/shared.d.ts +163 -0
  62. package/lib/sources/local-agent/adapters/shared.js +415 -0
  63. package/lib/sources/local-agent/adapters/sqlite-shared.d.ts +92 -0
  64. package/lib/sources/local-agent/adapters/sqlite-shared.js +215 -0
  65. package/lib/sources/local-agent/adapters/zcode.d.ts +41 -0
  66. package/lib/sources/local-agent/adapters/zcode.js +159 -0
  67. package/lib/sources/local-agent/index.d.ts +222 -0
  68. package/lib/sources/local-agent/index.js +656 -0
  69. package/lib/sources/local-agent/page.d.ts +55 -0
  70. package/lib/sources/local-agent/page.js +83 -0
  71. package/lib/sources/local-agent/path.d.ts +8 -0
  72. package/lib/sources/local-agent/path.js +43 -0
  73. package/lib/sources/local-agent/registry.d.ts +68 -0
  74. package/lib/sources/local-agent/registry.js +116 -0
  75. package/lib/sources/local-agent/scan.d.ts +175 -0
  76. package/lib/sources/local-agent/scan.js +472 -0
  77. package/lib/sources/local-agent/sqlite.d.ts +45 -0
  78. package/lib/sources/local-agent/sqlite.js +113 -0
  79. package/lib/sources/local-agent/store.d.ts +93 -0
  80. package/lib/sources/local-agent/store.js +113 -0
  81. package/lib/sources/local-agent/types.d.ts +338 -0
  82. package/lib/sources/local-agent/types.js +20 -0
  83. package/lib/sources/web-chat/index.d.ts +5 -1
  84. package/lib/sources/web-chat/index.js +47 -8
  85. package/lib/store/spec.d.ts +50 -4
  86. package/lib/store/spec.js +2 -2
  87. package/lib/sync/index.d.ts +1 -0
  88. package/lib/sync/index.js +28 -8
  89. package/lib/tool.d.ts +5 -0
  90. package/lib/tool.js +418 -45
  91. package/lib/typert.js +13 -2
  92. package/lib/types.d.ts +28 -2
  93. package/lib/update.d.ts +6 -0
  94. package/lib/update.js +29 -1
  95. package/lib/web.js +5 -1
  96. package/lib/wire.d.ts +80 -9
  97. package/lib/wire.js +30 -4
  98. package/opencli-plugin/chatgpt.js +30 -27
  99. package/opencli-plugin/claude.js +12 -8
  100. package/opencli-plugin/common.js +266 -187
  101. package/opencli-plugin/deepseek.js +8 -5
  102. package/opencli-plugin/gemini.js +42 -38
  103. package/opencli-plugin/grok.js +22 -21
  104. package/opencli-plugin/kimi.js +34 -31
  105. package/opencli-plugin/opencli-plugin.json +6 -6
  106. package/opencli-plugin/package.json +8 -8
  107. package/package.json +182 -167
  108. package/lib/profile-mode.d.ts +0 -30
  109. package/lib/profile-mode.js +0 -90
package/lib/contract.d.ts CHANGED
@@ -1,5 +1,49 @@
1
1
  import { z } from 'zod';
2
2
  import type { InvocationDescriptor } from '@deepseek-ai/dsh-typert-protocol';
3
+ /**
4
+ * One local-agent transcript as the `@` menu sees it.
5
+ *
6
+ * `id` is the source-scoped `kind:relPath`, not a `dsh-ref:` URI — the client
7
+ * wraps it, the way it does for web chats, so the `'local-agent'` source string
8
+ * stays hardcoded in exactly one place. Deliberately carries no `origin`: the
9
+ * absolute path adds nothing a menu row can use and everything a screen-share
10
+ * leaks.
11
+ */
12
+ export declare const agentCandidateSchema: z.ZodReadonly<z.ZodObject<{
13
+ id: z.ZodString;
14
+ kind: z.ZodString;
15
+ label: z.ZodString;
16
+ provider: z.ZodString;
17
+ updatedAt: z.ZodOptional<z.ZodNumber>;
18
+ }, z.core.$strip>>;
19
+ export declare const agentStatsSchema: z.ZodReadonly<z.ZodObject<{
20
+ agent: z.ZodEnum<{
21
+ kimi: "kimi";
22
+ "claude-code": "claude-code";
23
+ codex: "codex";
24
+ cursor: "cursor";
25
+ qoder: "qoder";
26
+ reasonix: "reasonix";
27
+ openclaw: "openclaw";
28
+ grokbuild: "grokbuild";
29
+ hermes: "hermes";
30
+ "gemini-cli": "gemini-cli";
31
+ pi: "pi";
32
+ opencode: "opencode";
33
+ mimocode: "mimocode";
34
+ zcode: "zcode";
35
+ }>;
36
+ conversations: z.ZodNumber;
37
+ }, z.core.$strip>>;
38
+ export declare const driveCandidateSchema: z.ZodReadonly<z.ZodObject<{
39
+ id: z.ZodString;
40
+ label: z.ZodString;
41
+ provider: z.ZodString;
42
+ origin: z.ZodOptional<z.ZodString>;
43
+ updatedAt: z.ZodOptional<z.ZodNumber>;
44
+ searchIncomplete: z.ZodOptional<z.ZodBoolean>;
45
+ isDirectory: z.ZodOptional<z.ZodBoolean>;
46
+ }, z.core.$strict>>;
3
47
  export declare const searchInputSchema: z.ZodReadonly<z.ZodObject<{
4
48
  query: z.ZodString;
5
49
  provider: z.ZodOptional<z.ZodEnum<{
@@ -92,25 +136,14 @@ export declare const packageUpdateStatusSchema: z.ZodReadonly<z.ZodObject<{
92
136
  latestVersion: z.ZodString;
93
137
  updateAvailable: z.ZodBoolean;
94
138
  checkedAt: z.ZodNumber;
139
+ releaseNotes: z.ZodOptional<z.ZodString>;
140
+ releaseUrl: z.ZodOptional<z.ZodString>;
95
141
  error: z.ZodOptional<z.ZodString>;
96
142
  }, z.core.$strip>>;
97
143
  export declare const packageUpdateResultSchema: z.ZodReadonly<z.ZodObject<{
98
144
  version: z.ZodString;
99
145
  restartRequired: z.ZodBoolean;
100
146
  }, z.core.$strip>>;
101
- export declare const referenceUiModeInputSchema: z.ZodReadonly<z.ZodObject<{
102
- mode: z.ZodEnum<{
103
- plugin: "plugin";
104
- official: "official";
105
- }>;
106
- }, z.core.$strip>>;
107
- export declare const referenceUiSwitchResultSchema: z.ZodReadonly<z.ZodObject<{
108
- mode: z.ZodEnum<{
109
- plugin: "plugin";
110
- official: "official";
111
- }>;
112
- restartRequired: z.ZodLiteral<false>;
113
- }, z.core.$strip>>;
114
147
  export declare const providerStatsSchema: z.ZodReadonly<z.ZodObject<{
115
148
  provider: z.ZodEnum<{
116
149
  chatgpt: "chatgpt";
@@ -287,9 +320,6 @@ export declare const clearProviderInputSchema: z.ZodReadonly<z.ZodObject<{
287
320
  kimi: "kimi";
288
321
  }>;
289
322
  }, z.core.$strip>>;
290
- export declare const clearOlderInputSchema: z.ZodReadonly<z.ZodObject<{
291
- days: z.ZodNumber;
292
- }, z.core.$strip>>;
293
323
  export declare const providerSyncStateSchema: z.ZodReadonly<z.ZodObject<{
294
324
  provider: z.ZodEnum<{
295
325
  chatgpt: "chatgpt";
@@ -309,4 +339,113 @@ export declare const providerSyncStateSchema: z.ZodReadonly<z.ZodObject<{
309
339
  lastCompleteScanAt: z.ZodString;
310
340
  error: z.ZodString;
311
341
  }, z.core.$strip>>;
342
+ export declare const openListStatusSchema: z.ZodReadonly<z.ZodObject<{
343
+ state: z.ZodEnum<{
344
+ failed: "failed";
345
+ running: "running";
346
+ install: "install";
347
+ downloading: "downloading";
348
+ upgrade: "upgrade";
349
+ }>;
350
+ installed: z.ZodBoolean;
351
+ mode: z.ZodOptional<z.ZodEnum<{
352
+ managed: "managed";
353
+ external: "external";
354
+ }>>;
355
+ version: z.ZodOptional<z.ZodString>;
356
+ endpoint: z.ZodOptional<z.ZodString>;
357
+ supportsRollback: z.ZodBoolean;
358
+ upgradeAvailable: z.ZodBoolean;
359
+ newerVersion: z.ZodOptional<z.ZodBoolean>;
360
+ error: z.ZodOptional<z.ZodString>;
361
+ }, z.core.$strict>>;
362
+ export declare const openListDriverFieldSchema: z.ZodReadonly<z.ZodObject<{
363
+ name: z.ZodString;
364
+ label: z.ZodString;
365
+ type: z.ZodEnum<{
366
+ number: "number";
367
+ boolean: "boolean";
368
+ text: "text";
369
+ password: "password";
370
+ select: "select";
371
+ }>;
372
+ secret: z.ZodBoolean;
373
+ required: z.ZodBoolean;
374
+ hasDefault: z.ZodOptional<z.ZodBoolean>;
375
+ default: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
376
+ options: z.ZodOptional<z.ZodArray<z.ZodReadonly<z.ZodObject<{
377
+ label: z.ZodString;
378
+ value: z.ZodString;
379
+ }, z.core.$strip>>>>;
380
+ }, z.core.$strict>>;
381
+ export declare const openListDriverSchema: z.ZodReadonly<z.ZodObject<{
382
+ name: z.ZodString;
383
+ description: z.ZodOptional<z.ZodString>;
384
+ quickAuth: z.ZodBoolean;
385
+ fields: z.ZodArray<z.ZodReadonly<z.ZodObject<{
386
+ name: z.ZodString;
387
+ label: z.ZodString;
388
+ type: z.ZodEnum<{
389
+ number: "number";
390
+ boolean: "boolean";
391
+ text: "text";
392
+ password: "password";
393
+ select: "select";
394
+ }>;
395
+ secret: z.ZodBoolean;
396
+ required: z.ZodBoolean;
397
+ hasDefault: z.ZodOptional<z.ZodBoolean>;
398
+ default: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
399
+ options: z.ZodOptional<z.ZodArray<z.ZodReadonly<z.ZodObject<{
400
+ label: z.ZodString;
401
+ value: z.ZodString;
402
+ }, z.core.$strip>>>>;
403
+ }, z.core.$strict>>>;
404
+ }, z.core.$strict>>;
405
+ export declare const openListMountSchema: z.ZodReadonly<z.ZodObject<{
406
+ id: z.ZodString;
407
+ name: z.ZodString;
408
+ driver: z.ZodString;
409
+ enabled: z.ZodBoolean;
410
+ status: z.ZodOptional<z.ZodEnum<{
411
+ error: "error";
412
+ ready: "ready";
413
+ disabled: "disabled";
414
+ }>>;
415
+ error: z.ZodOptional<z.ZodString>;
416
+ capacityUsed: z.ZodOptional<z.ZodNumber>;
417
+ capacityTotal: z.ZodOptional<z.ZodNumber>;
418
+ indexStatus: z.ZodOptional<z.ZodEnum<{
419
+ complete: "complete";
420
+ failed: "failed";
421
+ running: "running";
422
+ idle: "idle";
423
+ }>>;
424
+ indexProgress: z.ZodOptional<z.ZodNumber>;
425
+ indexCount: z.ZodOptional<z.ZodNumber>;
426
+ }, z.core.$strict>>;
427
+ export declare const openListExternalConnectSchema: z.ZodReadonly<z.ZodObject<{
428
+ endpoint: z.ZodString;
429
+ username: z.ZodOptional<z.ZodString>;
430
+ password: z.ZodOptional<z.ZodString>;
431
+ token: z.ZodOptional<z.ZodString>;
432
+ }, z.core.$strict>>;
433
+ export declare const openListMountCreateSchema: z.ZodReadonly<z.ZodObject<{
434
+ id: z.ZodOptional<z.ZodString>;
435
+ mountPath: z.ZodString;
436
+ driver: z.ZodString;
437
+ addition: z.ZodRecord<z.ZodString, z.ZodUnknown>;
438
+ order: z.ZodOptional<z.ZodNumber>;
439
+ remark: z.ZodOptional<z.ZodString>;
440
+ }, z.core.$strict>>;
441
+ export declare const openListMountInputSchema: z.ZodReadonly<z.ZodObject<{
442
+ id: z.ZodString;
443
+ }, z.core.$strict>>;
444
+ export declare const openListDisableMountSchema: z.ZodReadonly<z.ZodObject<{
445
+ id: z.ZodString;
446
+ disabled: z.ZodOptional<z.ZodBoolean>;
447
+ }, z.core.$strict>>;
448
+ export declare const openListUpgradeInputSchema: z.ZodReadonly<z.ZodObject<{
449
+ rollback: z.ZodOptional<z.ZodBoolean>;
450
+ }, z.core.$strict>>;
312
451
  export declare const REFERENCE_ANYTHING_INVOCATIONS: readonly InvocationDescriptor[];
package/lib/contract.js CHANGED
@@ -1,5 +1,31 @@
1
1
  import { z } from 'zod';
2
- import { providerSchema, referenceUiModeSchema, settingsRecordSchema } from "./wire.js";
2
+ import { localAgentSchema, providerSchema, settingsRecordSchema } from "./wire.js";
3
+ /**
4
+ * One local-agent transcript as the `@` menu sees it.
5
+ *
6
+ * `id` is the source-scoped `kind:relPath`, not a `dsh-ref:` URI — the client
7
+ * wraps it, the way it does for web chats, so the `'local-agent'` source string
8
+ * stays hardcoded in exactly one place. Deliberately carries no `origin`: the
9
+ * absolute path adds nothing a menu row can use and everything a screen-share
10
+ * leaks.
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();
14
+ // `origin` is the drive's own display path, shown under the candidate. It is
15
+ // never a download URL: those are signed with the account's credential and
16
+ // must not cross this wire.
17
+ export const driveCandidateSchema = z.object({
18
+ id: z.string(), label: z.string(), provider: z.string(),
19
+ origin: z.string().optional(), updatedAt: z.number().optional(),
20
+ searchIncomplete: z.boolean().optional(), isDirectory: z.boolean().optional(),
21
+ }).strict().readonly();
22
+ /**
23
+ * Binds the calling session to the invocation, so the Host can scope a search
24
+ * to the session's cwd. Reintroduced here after 0.3.0 handed file and session
25
+ * lookup back to DSH's native Remotes and removed its last other caller.
26
+ */
27
+ const agentLookup = { name: 'agent', wire: 'agentId', source: 'lookup', lookup: 'agent',
28
+ codec: { mode: 'strict', typeSymbol: '@deepseek-ai/dsh-session/types#SessionId', schema: z.string().min(1) } };
3
29
  export const searchInputSchema = z.object({
4
30
  query: z.string(), provider: providerSchema.optional(), limit: z.number().int().min(1).max(100),
5
31
  }).readonly();
@@ -24,13 +50,11 @@ export const openCliDiscoverySchema = z.object({
24
50
  }).readonly();
25
51
  export const packageUpdateStatusSchema = z.object({
26
52
  currentVersion: z.string(), latestVersion: z.string(), updateAvailable: z.boolean(),
27
- checkedAt: z.number().int().nonnegative(), error: z.string().optional(),
53
+ checkedAt: z.number().int().nonnegative(), releaseNotes: z.string().max(12_000).optional(), releaseUrl: z.string().url().optional(), error: z.string().optional(),
28
54
  }).readonly();
29
55
  export const packageUpdateResultSchema = z.object({
30
56
  version: z.string(), restartRequired: z.boolean(),
31
57
  }).readonly();
32
- export const referenceUiModeInputSchema = z.object({ mode: referenceUiModeSchema }).readonly();
33
- export const referenceUiSwitchResultSchema = z.object({ mode: referenceUiModeSchema, restartRequired: z.literal(false) }).readonly();
34
58
  export const providerStatsSchema = z.object({
35
59
  provider: providerSchema, conversations: z.number().int().nonnegative(), lastSyncedAt: z.string(),
36
60
  status: z.enum(['ready', 'syncing', 'error', 'empty']), error: z.string().optional(),
@@ -64,12 +88,39 @@ export const storageStatsSchema = z.object({
64
88
  remoteMissing: z.number().int().nonnegative().default(0), oldAccountConversations: z.number().int().nonnegative().default(0),
65
89
  }).readonly();
66
90
  export const clearProviderInputSchema = z.object({ provider: providerSchema }).readonly();
67
- export const clearOlderInputSchema = z.object({ days: z.number().int().min(1).max(36500) }).readonly();
68
91
  export const providerSyncStateSchema = z.object({
69
92
  provider: providerSchema, status: z.enum(['idle', 'running', 'cancelled', 'failed']),
70
93
  lastSyncAt: z.string(), lastCompleteScanAt: z.string(), error: z.string(),
71
94
  }).readonly();
95
+ // OpenList wire DTOs intentionally omit every credential, storage addition,
96
+ // raw/signed URL, and server-supplied diagnostic. The Host keeps those in its
97
+ // restricted credential file and translates failures to a generic message.
98
+ export const openListStatusSchema = z.object({
99
+ state: z.enum(['install', 'downloading', 'running', 'failed', 'upgrade']), installed: z.boolean(),
100
+ mode: z.enum(['managed', 'external']).optional(), version: z.string().optional(), endpoint: z.string().optional(),
101
+ supportsRollback: z.boolean(), upgradeAvailable: z.boolean(), newerVersion: z.boolean().optional(), error: z.string().optional(),
102
+ }).strict().readonly();
103
+ export const openListDriverFieldSchema = z.object({
104
+ name: z.string(), label: z.string(), type: z.enum(['text', 'password', 'number', 'boolean', 'select']), secret: z.boolean(), required: z.boolean(), hasDefault: z.boolean().optional(), default: z.union([z.string(), z.number(), z.boolean()]).optional(),
105
+ options: z.array(z.object({ label: z.string(), value: z.string() }).readonly()).optional(),
106
+ }).strict().readonly();
107
+ export const openListDriverSchema = z.object({ name: z.string(), description: z.string().optional(), quickAuth: z.boolean(), fields: z.array(openListDriverFieldSchema) }).strict().readonly();
108
+ export const openListMountSchema = z.object({
109
+ id: z.string(), name: z.string(), driver: z.string(), enabled: z.boolean(), status: z.enum(['ready', 'disabled', 'error']).optional(), error: z.string().optional(),
110
+ capacityUsed: z.number().nonnegative().optional(), capacityTotal: z.number().nonnegative().optional(),
111
+ indexStatus: z.enum(['idle', 'running', 'complete', 'failed']).optional(), indexProgress: z.number().min(0).max(1).optional(), indexCount: z.number().nonnegative().optional(),
112
+ }).strict().readonly();
113
+ export const openListExternalConnectSchema = z.object({ endpoint: z.string().min(1), username: z.string().optional(), password: z.string().optional(), token: z.string().optional() }).strict().readonly();
114
+ export const openListMountCreateSchema = z.object({ id: z.string().min(1).optional(), mountPath: z.string().min(1), driver: z.string().min(1), addition: z.record(z.string(), z.unknown()), order: z.number().int().optional(), remark: z.string().optional() }).strict().readonly();
115
+ export const openListMountInputSchema = z.object({ id: z.string().min(1) }).strict().readonly();
116
+ export const openListDisableMountSchema = z.object({ id: z.string().min(1), disabled: z.boolean().optional() }).strict().readonly();
117
+ export const openListUpgradeInputSchema = z.object({ rollback: z.boolean().optional() }).strict().readonly();
72
118
  export const REFERENCE_ANYTHING_INVOCATIONS = [
119
+ 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) }).readonly()) }], strict('AgentCandidate[]', z.array(agentCandidateSchema)), true),
120
+ descriptor('agentStats', [], strict('AgentStats[]', z.array(agentStatsSchema)), true),
121
+ // No session lookup, unlike `agentSearch`: a drive is the same drive from
122
+ // every workspace, so there is nothing to scope the query to.
123
+ descriptor('driveSearch', [{ name: 'input', wire: 'input', source: 'json', codec: strict('DriveSearchInput', z.object({ query: z.string(), limit: z.number().int().min(1).max(100) }).readonly()) }], strict('DriveCandidate[]', z.array(driveCandidateSchema)), true),
73
124
  descriptor('search', [{ name: 'input', wire: 'input', source: 'json', codec: strict('SearchInput', searchInputSchema) }], strict('SearchResult[]', z.array(searchResultSchema)), true),
74
125
  descriptor('health', [], strict('Health', healthSchema), true),
75
126
  descriptor('quickHealth', [], strict('Health', healthSchema), true),
@@ -81,21 +132,31 @@ export const REFERENCE_ANYTHING_INVOCATIONS = [
81
132
  descriptor('updateStatus', [], strict('PackageUpdateStatus', packageUpdateStatusSchema), true),
82
133
  descriptor('checkUpdate', [], strict('PackageUpdateStatus', packageUpdateStatusSchema), true),
83
134
  descriptor('installUpdate', [], strict('PackageUpdateResult', packageUpdateResultSchema), true),
84
- descriptor('switchReferenceUiMode', [{ name: 'input', wire: 'input', source: 'json', codec: strict('ReferenceUiModeInput', referenceUiModeInputSchema) }], strict('ReferenceUiSwitchResult', referenceUiSwitchResultSchema), true),
85
135
  descriptor('stats', [], strict('ProviderStats[]', z.array(providerStatsSchema))),
86
136
  descriptor('syncStart', [{ name: 'input', wire: 'input', source: 'json', codec: strict('SyncStart', syncStartSchema) }], strict('JobId', z.string())),
87
137
  descriptor('syncStatus', [{ name: 'input', wire: 'input', source: 'json', codec: strict('JobInput', jobInputSchema) }], strict('SyncStatus?', syncStatusSchema.optional())),
88
138
  descriptor('syncCancel', [{ name: 'input', wire: 'input', source: 'json', codec: strict('JobInput', jobInputSchema) }], strict('Boolean', z.boolean())),
89
139
  descriptor('settingsGet', [], strict('Settings', settingsRecordSchema)),
90
140
  descriptor('settingsUpdate', [{ name: 'settings', wire: 'settings', source: 'json', codec: strict('Settings', settingsRecordSchema) }], strict('Settings', settingsRecordSchema)),
141
+ descriptor('openDownloadDirectory', [], strict('Boolean', z.boolean()), true),
91
142
  descriptor('browse', [{ name: 'input', wire: 'input', source: 'json', codec: strict('BrowseInput', browseInputSchema) }], strict('BrowsePage', browsePageSchema), true),
92
143
  descriptor('deleteConversation', [{ name: 'input', wire: 'input', source: 'json', codec: strict('DeleteInput', deleteInputSchema) }], strict('Boolean', z.boolean()), true),
93
144
  descriptor('storageStats', [], strict('StorageStats', storageStatsSchema)),
94
145
  descriptor('clearProvider', [{ name: 'input', wire: 'input', source: 'json', codec: strict('ClearProviderInput', clearProviderInputSchema) }], strict('Count', z.number().int().nonnegative()), true),
95
- descriptor('clearOlder', [{ name: 'input', wire: 'input', source: 'json', codec: strict('ClearOlderInput', clearOlderInputSchema) }], strict('Count', z.number().int().nonnegative()), true),
96
146
  descriptor('clearRemoteMissing', [], strict('Count', z.number().int().nonnegative()), true),
97
147
  descriptor('clearOldAccounts', [], strict('Count', z.number().int().nonnegative()), true),
98
148
  descriptor('syncStates', [], strict('ProviderSyncState[]', z.array(providerSyncStateSchema))),
149
+ descriptor('openListStatus', [], strict('OpenListStatus', openListStatusSchema), true),
150
+ descriptor('openListInstall', [], strict('OpenListStatus', openListStatusSchema), true),
151
+ descriptor('openListUpgrade', [{ name: 'input', wire: 'input', source: 'json', codec: strict('OpenListUpgradeInput', openListUpgradeInputSchema) }], strict('OpenListStatus', openListStatusSchema), true),
152
+ descriptor('openListConnectExternal', [{ name: 'input', wire: 'input', source: 'json', codec: strict('OpenListExternalConnect', openListExternalConnectSchema) }], strict('OpenListStatus', openListStatusSchema), true),
153
+ descriptor('openListDisconnect', [], strict('OpenListStatus', openListStatusSchema), true),
154
+ descriptor('openListDrivers', [], strict('OpenListDriver[]', z.array(openListDriverSchema)), true),
155
+ descriptor('openListMounts', [], strict('OpenListMount[]', z.array(openListMountSchema)), true),
156
+ descriptor('openListCreateMount', [{ name: 'input', wire: 'input', source: 'json', codec: strict('OpenListMountCreate', openListMountCreateSchema) }], strict('OpenListMount', openListMountSchema), true),
157
+ descriptor('openListDisableMount', [{ name: 'input', wire: 'input', source: 'json', codec: strict('OpenListDisableMountInput', openListDisableMountSchema) }], strict('Boolean', z.boolean()), true),
158
+ descriptor('openListRemoveMount', [{ name: 'input', wire: 'input', source: 'json', codec: strict('OpenListMountInput', openListMountInputSchema) }], strict('Boolean', z.boolean()), true),
159
+ descriptor('openListReindex', [{ name: 'input', wire: 'input', source: 'json', codec: strict('OpenListMountInput', openListMountInputSchema) }], strict('OpenListReindex', z.object({ supported: z.boolean(), reason: z.string().optional() }).readonly()), true),
99
160
  ];
100
161
  function strict(type, schema) {
101
162
  return { mode: 'strict', typeSymbol: `dsh-reference-anything#${type}`, schema };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Unlike `path.isAbsolute`, this excludes Windows paths rooted on the current
3
+ * drive (`\foo`) and drive-relative paths (`C:foo`). Those forms can silently
4
+ * resolve somewhere other than the directory displayed in Settings.
5
+ */
6
+ export declare function isFullyQualifiedDownloadDirectory(value: string, platform?: NodeJS.Platform): boolean;
7
+ /** Append an mkdtemp prefix without lexically resolving symlinks or `..`. */
8
+ export declare function appendDownloadDirectoryPrefix(directory: string, prefix: string, platform?: NodeJS.Platform): string;
9
+ export interface DownloadDirectoryValidationOptions {
10
+ platform?: NodeJS.Platform;
11
+ lstatPath?: (path: string) => Promise<{
12
+ isDirectory(): boolean;
13
+ isSymbolicLink(): boolean;
14
+ }>;
15
+ accessPath?: (path: string, mode: number) => Promise<void>;
16
+ }
17
+ /** Validate the user-selected base without changing its filesystem semantics. */
18
+ export declare function validateDownloadDirectory(value: string, options?: DownloadDirectoryValidationOptions): Promise<string>;
@@ -0,0 +1,55 @@
1
+ import { constants } from 'node:fs';
2
+ import { access, lstat } from 'node:fs/promises';
3
+ import { ReferenceAnythingError } from "./errors.js";
4
+ /**
5
+ * Unlike `path.isAbsolute`, this excludes Windows paths rooted on the current
6
+ * drive (`\foo`) and drive-relative paths (`C:foo`). Those forms can silently
7
+ * resolve somewhere other than the directory displayed in Settings.
8
+ */
9
+ export function isFullyQualifiedDownloadDirectory(value, platform = process.platform) {
10
+ if (platform !== 'win32')
11
+ return value.startsWith('/');
12
+ // Device and NT namespaces bypass ordinary filesystem parsing and can name
13
+ // objects outside the selected volume/share boundary. This feature only
14
+ // accepts conventional DOS drive paths and UNC shares.
15
+ if (/^\\\\[?.][\\/]/.test(value))
16
+ return false;
17
+ if (/^[A-Za-z]:[\\/]/.test(value))
18
+ return true;
19
+ return /^\\\\[^\\/]+[\\/][^\\/]+(?:[\\/].*)?$/.test(value);
20
+ }
21
+ /** Append an mkdtemp prefix without lexically resolving symlinks or `..`. */
22
+ export function appendDownloadDirectoryPrefix(directory, prefix, platform = process.platform) {
23
+ if (!isFullyQualifiedDownloadDirectory(directory, platform) || directory.includes('\0')) {
24
+ throw new ReferenceAnythingError('Cloud-drive download directory is invalid', 'REFERENCE_INVALID_CONFIG');
25
+ }
26
+ if (prefix === '' || prefix === '.' || prefix === '..' || prefix.includes('\0') || /[\\/]/.test(prefix)) {
27
+ throw new ReferenceAnythingError('Cloud-drive temporary-directory prefix is invalid', 'REFERENCE_INVALID_CONFIG');
28
+ }
29
+ const hasSeparator = platform === 'win32' ? /[\\/]$/.test(directory) : directory.endsWith('/');
30
+ return `${directory}${hasSeparator ? '' : platform === 'win32' ? '\\' : '/'}${prefix}`;
31
+ }
32
+ /** Validate the user-selected base without changing its filesystem semantics. */
33
+ export async function validateDownloadDirectory(value, options = {}) {
34
+ if (value === '')
35
+ return '';
36
+ const platform = options.platform ?? process.platform;
37
+ if (value.includes('\0') || !isFullyQualifiedDownloadDirectory(value, platform)) {
38
+ throw new ReferenceAnythingError('Cloud-drive download directory must be a fully-qualified absolute path', 'REFERENCE_INVALID_CONFIG');
39
+ }
40
+ const lstatPath = options.lstatPath ?? (async (path) => lstat(path));
41
+ const accessPath = options.accessPath ?? (async (path, mode) => access(path, mode));
42
+ try {
43
+ const metadata = await lstatPath(value);
44
+ if (metadata.isSymbolicLink() || !metadata.isDirectory()) {
45
+ throw new ReferenceAnythingError('Cloud-drive download directory must name a real directory, not a symbolic link', 'REFERENCE_INVALID_CONFIG');
46
+ }
47
+ await accessPath(value, constants.W_OK | constants.X_OK);
48
+ }
49
+ catch (cause) {
50
+ if (cause instanceof ReferenceAnythingError)
51
+ throw cause;
52
+ throw new ReferenceAnythingError('Cloud-drive download directory does not exist or is not writable', 'REFERENCE_INVALID_CONFIG', { cause });
53
+ }
54
+ return value;
55
+ }
package/lib/errors.d.ts CHANGED
@@ -16,8 +16,12 @@ export type ReferenceErrorCode =
16
16
  | 'REFERENCE_NOT_FOUND'
17
17
  /** A live browser read targeted a conversation owned by another account. */
18
18
  | 'REFERENCE_ACCOUNT_MISMATCH'
19
+ /** The active provider account temporarily refused identity verification due to rate limiting. */
20
+ | 'PROVIDER_RATE_LIMIT'
19
21
  /** The source failed while reading; its own error is the `cause`. */
20
22
  | 'REFERENCE_READ_FAILED'
23
+ /** A transcript whose format must be read whole is larger than the scan budget. */
24
+ | 'REFERENCE_TRANSCRIPT_TOO_LARGE'
21
25
  /** The caller cancelled before the read settled. */
22
26
  | 'REFERENCE_CANCELLED'
23
27
  /** A `dsh-ref:` URI was malformed, non-canonical, or not a reference at all. */
package/lib/host.d.ts CHANGED
@@ -1,10 +1,53 @@
1
1
  import type { Context } from '@deepseek-ai/cordis';
2
2
  import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
3
3
  import type { ChatProvider, SettingsRecord } from './store/spec.ts';
4
- import type { ReferenceUiMode } from './wire.ts';
5
4
  import type { SyncMode } from './sync/index.ts';
5
+ import type { Agent } from '@deepseek-ai/dsh-agent';
6
6
  export declare class ReferenceAnythingRemote extends TypertRemoteService {
7
7
  constructor(ctx: Context);
8
+ /**
9
+ * Discovery for the `@` menu's local-agent group.
10
+ *
11
+ * Resolved optionally rather than injected: `reference-anything-web` must
12
+ * still load in a profile where the local-agent plugin is switched off, and an
13
+ * absent service means an empty group, not a broken composer. Workspace
14
+ * scoping takes the session's own cwd, so a Web server serving projects from
15
+ * anywhere still scopes to the project the user is in.
16
+ */
17
+ agentSearch(agent: Agent, input: {
18
+ query: string;
19
+ limit: number;
20
+ }, signal: AbortSignal): Promise<{
21
+ searchIncomplete?: boolean | undefined;
22
+ updatedAt?: number | undefined;
23
+ id: string;
24
+ kind: string;
25
+ label: string;
26
+ provider: string;
27
+ }[]>;
28
+ agentStats(signal: AbortSignal): Promise<{
29
+ agent: import("./sources/local-agent/types.ts").AgentKind;
30
+ conversations: number;
31
+ }[]>;
32
+ /**
33
+ * Discovery for the `@` menu's cloud-drive group.
34
+ *
35
+ * Optional for the same reason as `agentSearch` above. It takes no session:
36
+ * a drive is not scoped to a workspace, so there is nothing a cwd could
37
+ * narrow. `list` already refuses to name a download URL, so what comes back
38
+ * here is a label and a display path.
39
+ */
40
+ driveSearch(input: {
41
+ query: string;
42
+ limit: number;
43
+ }, signal: AbortSignal): Promise<{
44
+ isDirectory?: boolean | undefined;
45
+ updatedAt?: number | undefined;
46
+ origin?: string | undefined;
47
+ id: string;
48
+ label: string;
49
+ provider: string;
50
+ }[]>;
8
51
  search(input: {
9
52
  query: string;
10
53
  provider?: ChatProvider;
@@ -20,9 +63,6 @@ export declare class ReferenceAnythingRemote extends TypertRemoteService {
20
63
  updateStatus(signal: AbortSignal): Promise<import("./update.ts").PackageUpdateStatus>;
21
64
  checkUpdate(signal: AbortSignal): Promise<import("./update.ts").PackageUpdateStatus>;
22
65
  installUpdate(signal: AbortSignal): Promise<import("./update.ts").PackageUpdateResult>;
23
- switchReferenceUiMode(input: {
24
- mode: ReferenceUiMode;
25
- }, signal: AbortSignal): Promise<import("./profile-mode.ts").ReferenceUiSwitchResult>;
26
66
  stats(): import("./store/store.ts").ProviderStats[];
27
67
  syncStart(input: {
28
68
  providers: ChatProvider[];
@@ -38,15 +78,19 @@ export declare class ReferenceAnythingRemote extends TypertRemoteService {
38
78
  settingsUpdate(settings: SettingsRecord): Promise<{
39
79
  opencliPath: string;
40
80
  profile: string;
81
+ cloudDriveDownloadDirectory: string;
41
82
  detailConcurrency: number;
42
83
  autoSync: boolean;
43
84
  syncOnStartup: boolean;
44
85
  autoSyncMinutes: number;
45
86
  historyMode: "metadata-only" | "offline-mirror";
87
+ syncHistoryDays: number | null;
46
88
  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")[];
47
90
  maxReadTurns: number;
48
91
  inputRenderMode: "pill" | "raw-text";
49
- referenceUiMode?: "plugin" | "official" | undefined;
92
+ agentDirectories?: Partial<Record<"kimi" | "claude-code" | "codex" | "cursor" | "qoder" | "reasonix" | "openclaw" | "grokbuild" | "hermes" | "gemini-cli" | "pi" | "opencode" | "mimocode" | "zcode", string>> | undefined;
93
+ enabledDriveMounts?: string[] | undefined;
50
94
  picker?: {
51
95
  displayMode: "collapse" | "native-scroll";
52
96
  commands: {
@@ -73,14 +117,27 @@ export declare class ReferenceAnythingRemote extends TypertRemoteService {
73
117
  limit: number;
74
118
  maxCandidates: number;
75
119
  };
120
+ agents: {
121
+ enabled: boolean;
122
+ order: number;
123
+ limit: number;
124
+ maxCandidates: number;
125
+ };
76
126
  conversations: {
77
127
  enabled: boolean;
78
128
  order: number;
79
129
  limit: number;
80
130
  maxCandidates: number;
81
131
  };
132
+ drives: {
133
+ enabled: boolean;
134
+ order: number;
135
+ limit: number;
136
+ maxCandidates: number;
137
+ };
82
138
  } | undefined;
83
139
  }>;
140
+ openDownloadDirectory(signal: AbortSignal): Promise<boolean>;
84
141
  browse(input: {
85
142
  query: string;
86
143
  provider?: ChatProvider;
@@ -97,10 +154,41 @@ export declare class ReferenceAnythingRemote extends TypertRemoteService {
97
154
  clearProvider(input: {
98
155
  provider: ChatProvider;
99
156
  }, signal: AbortSignal): Promise<number>;
100
- clearOlder(input: {
101
- days: number;
102
- }, signal: AbortSignal): Promise<number>;
103
157
  clearRemoteMissing(signal: AbortSignal): Promise<number>;
104
158
  clearOldAccounts(signal: AbortSignal): Promise<number>;
105
159
  syncStates(): import("./store/store.ts").ProviderSyncState[];
160
+ openListStatus(signal: AbortSignal): Promise<import("./openlist/index.ts").OpenListStatus>;
161
+ openListInstall(signal: AbortSignal): Promise<import("./openlist/index.ts").OpenListStatus>;
162
+ openListUpgrade(input: {
163
+ rollback?: boolean;
164
+ }, signal: AbortSignal): Promise<import("./openlist/index.ts").OpenListStatus>;
165
+ openListConnectExternal(input: {
166
+ endpoint: string;
167
+ username?: string;
168
+ password?: string;
169
+ token?: string;
170
+ }, signal: AbortSignal): Promise<import("./openlist/index.ts").OpenListStatus>;
171
+ openListDisconnect(signal: AbortSignal): Promise<import("./openlist/index.ts").OpenListStatus>;
172
+ openListDrivers(signal: AbortSignal): Promise<import("./openlist/host.ts").OpenListDriver[]>;
173
+ openListMounts(signal: AbortSignal): Promise<import("./openlist/host.ts").OpenListMount[]>;
174
+ openListCreateMount(input: {
175
+ id?: string;
176
+ mountPath: string;
177
+ driver: string;
178
+ addition: Record<string, unknown>;
179
+ order?: number;
180
+ remark?: string;
181
+ }, signal: AbortSignal): Promise<import("./openlist/host.ts").OpenListMount>;
182
+ openListDisableMount(input: {
183
+ id: string;
184
+ disabled?: boolean;
185
+ }, signal: AbortSignal): Promise<boolean>;
186
+ openListRemoveMount(input: {
187
+ id: string;
188
+ }, signal: AbortSignal): Promise<boolean>;
189
+ openListReindex(input: {
190
+ id: string;
191
+ }, signal: AbortSignal): Promise<{
192
+ supported: true;
193
+ }>;
106
194
  }