dsh-reference-anything 0.4.2 → 0.4.3

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/lib/contract.d.ts CHANGED
@@ -114,6 +114,8 @@ export declare const healthSchema: z.ZodReadonly<z.ZodObject<{
114
114
  pluginVersion: z.ZodOptional<z.ZodString>;
115
115
  adapterCommandsReady: z.ZodBoolean;
116
116
  adapterCompatible: z.ZodBoolean;
117
+ latestVersion: z.ZodOptional<z.ZodString>;
118
+ updateAvailable: z.ZodBoolean;
117
119
  versionError: z.ZodOptional<z.ZodString>;
118
120
  daemonError: z.ZodOptional<z.ZodString>;
119
121
  pluginError: z.ZodOptional<z.ZodString>;
@@ -305,6 +307,7 @@ export declare const deleteInputSchema: z.ZodReadonly<z.ZodObject<{
305
307
  uriId: z.ZodString;
306
308
  }, z.core.$strip>>;
307
309
  export declare const storageStatsSchema: z.ZodReadonly<z.ZodObject<{
310
+ systemTempDirectory: z.ZodOptional<z.ZodString>;
308
311
  bytes: z.ZodNumber;
309
312
  conversations: z.ZodNumber;
310
313
  remoteMissing: z.ZodDefault<z.ZodNumber>;
package/lib/contract.js CHANGED
@@ -41,7 +41,7 @@ export const healthSchema = z.object({
41
41
  daemonRunning: z.boolean(), extensionConnected: z.boolean(), extensionState: extensionStateSchema,
42
42
  extensionVersion: z.string().optional(), profileCount: z.number().int().nonnegative().optional(),
43
43
  opencliCompatible: z.boolean(), daemonVersion: z.string().optional(), daemonStale: z.boolean(),
44
- connectivityOk: z.boolean(), connectivityChecked: z.boolean(), pluginVersion: z.string().optional(), adapterCommandsReady: z.boolean(), adapterCompatible: z.boolean(),
44
+ connectivityOk: z.boolean(), connectivityChecked: z.boolean(), pluginVersion: z.string().optional(), adapterCommandsReady: z.boolean(), adapterCompatible: z.boolean(), latestVersion: z.string().optional(), updateAvailable: z.boolean(),
45
45
  versionError: z.string().optional(), daemonError: z.string().optional(), pluginError: z.string().optional(), doctorError: z.string().optional(),
46
46
  }).readonly();
47
47
  export const browserProfileSchema = z.object({ id: z.string(), alias: z.string().optional(), connected: z.boolean(), isDefault: z.boolean() }).readonly();
@@ -84,6 +84,7 @@ export const browsePageSchema = z.object({
84
84
  }).readonly();
85
85
  export const deleteInputSchema = z.object({ uriId: z.string().min(1) }).readonly();
86
86
  export const storageStatsSchema = z.object({
87
+ systemTempDirectory: z.string().optional(),
87
88
  bytes: z.number().int().nonnegative(), conversations: z.number().int().nonnegative(),
88
89
  remoteMissing: z.number().int().nonnegative().default(0), oldAccountConversations: z.number().int().nonnegative().default(0),
89
90
  }).readonly();
package/lib/host.d.ts CHANGED
@@ -67,7 +67,7 @@ export declare class ReferenceAnythingRemote extends TypertRemoteService {
67
67
  syncStart(input: {
68
68
  providers: ChatProvider[];
69
69
  mode: SyncMode;
70
- }): string;
70
+ }): Promise<string>;
71
71
  syncStatus(input: {
72
72
  jobId: string;
73
73
  }): import("./sync/index.ts").SyncJobStatus | undefined;
@@ -150,7 +150,13 @@ export declare class ReferenceAnythingRemote extends TypertRemoteService {
150
150
  deleteConversation(input: {
151
151
  uriId: string;
152
152
  }, signal: AbortSignal): Promise<boolean>;
153
- storageStats(): import("./store/store.ts").StorageStats;
153
+ storageStats(): {
154
+ systemTempDirectory: string;
155
+ bytes: number;
156
+ conversations: number;
157
+ remoteMissing: number;
158
+ oldAccountConversations: number;
159
+ };
154
160
  clearProvider(input: {
155
161
  provider: ChatProvider;
156
162
  }, signal: AbortSignal): Promise<number>;
package/lib/host.js CHANGED
@@ -75,7 +75,8 @@ export class ReferenceAnythingRemote extends TypertRemoteService {
75
75
  checkUpdate(signal) { return this.ctx.referenceChatHistory.checkUpdate(signal); }
76
76
  installUpdate(signal) { return this.ctx.referenceChatHistory.installUpdate(signal); }
77
77
  stats() { return this.ctx.referenceChatHistory.stats(); }
78
- syncStart(input) {
78
+ async syncStart(input) {
79
+ await this.ctx.referenceChatHistory.ensureBrowser();
79
80
  return this.ctx.referenceChatHistory.sync.start(input.providers, input.mode);
80
81
  }
81
82
  syncStatus(input) { return this.ctx.referenceChatHistory.sync.status(input.jobId); }
@@ -107,7 +108,7 @@ export class ReferenceAnythingRemote extends TypertRemoteService {
107
108
  signal.throwIfAborted();
108
109
  return this.ctx.referenceChatHistory.remove(input.uriId);
109
110
  }
110
- storageStats() { return this.ctx.referenceChatHistory.storageStats(); }
111
+ storageStats() { return { ...this.ctx.referenceChatHistory.storageStats(), systemTempDirectory: tmpdir() }; }
111
112
  clearProvider(input, signal) {
112
113
  signal.throwIfAborted();
113
114
  return this.ctx.referenceChatHistory.removeProvider(input.provider);
package/lib/index.js CHANGED
@@ -79,8 +79,6 @@ export default class ReferenceRuntime extends Service {
79
79
  static grantKey(ref) { return `${ref.source}\u0000${ref.id}`; }
80
80
  static contentMentions(blocks, key) {
81
81
  return blocks.some(block => {
82
- if (block.type === 'tool-result')
83
- return ReferenceRuntime.contentMentions(block.content, key);
84
82
  if (block.type !== 'text' || !mayContainReference(block.text))
85
83
  return false;
86
84
  try {
package/lib/opencli.d.ts CHANGED
@@ -38,6 +38,8 @@ export interface OpenCliHealth {
38
38
  pluginVersion?: string;
39
39
  adapterCommandsReady: boolean;
40
40
  adapterCompatible: boolean;
41
+ latestVersion?: string;
42
+ updateAvailable: boolean;
41
43
  versionError?: string;
42
44
  daemonError?: string;
43
45
  pluginError?: string;
@@ -107,6 +109,7 @@ export declare class OpenCliRunner {
107
109
  /** Confirm the executable also exposes OpenCLI's plugin command, not merely a semver-looking --version. */
108
110
  verifyInstallation(signal?: AbortSignal): Promise<void>;
109
111
  profiles(signal?: AbortSignal): Promise<BrowserProfile[]>;
112
+ ensureBrowser(signal?: AbortSignal): Promise<void>;
110
113
  installPlugin(pluginUrl: string, signal?: AbortSignal): Promise<void>;
111
114
  restartDaemon(signal?: AbortSignal): Promise<void>;
112
115
  private probe;
package/lib/opencli.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { execFile as nodeExecFile } from 'node:child_process';
2
2
  import { existsSync } from 'node:fs';
3
- import { dirname, join, resolve } from 'node:path';
3
+ import { delimiter, dirname, join, resolve } from 'node:path';
4
4
  import { promisify } from 'node:util';
5
+ import { spawn } from 'node:child_process';
5
6
  import { createHash } from 'node:crypto';
6
7
  const execFile = promisify(nodeExecFile);
7
8
  export const MIN_OPENCLI_VERSION = '1.8.6';
@@ -124,9 +125,10 @@ export class OpenCliRunner {
124
125
  return this.inspectHealth(false, signal);
125
126
  }
126
127
  async inspectHealth(checkConnectivity, signal) {
127
- const [version, daemon, plugins, doctor] = await Promise.all([
128
+ const [version, daemon, plugins, doctor, latest] = await Promise.all([
128
129
  this.probe(['--version'], signal), this.probe(['daemon', 'status'], signal), this.probe(['plugin', 'list'], signal),
129
130
  checkConnectivity ? this.probe(['doctor'], signal) : Promise.resolve({ value: '', diagnostic: '' }),
131
+ latestOpenCliVersion(signal),
130
132
  ]);
131
133
  const status = parseDaemonStatus(daemon.value);
132
134
  const cliVersion = normalizeVersion(version.value);
@@ -149,6 +151,8 @@ export class OpenCliRunner {
149
151
  ...(pluginVersion ? { pluginVersion: normalizeVersion(pluginVersion) } : {}),
150
152
  adapterCommandsReady,
151
153
  adapterCompatible: pluginInstalled && adapterCommandsReady && versionAtLeast(pluginVersion ?? '', MIN_ADAPTER_VERSION),
154
+ ...(latest.value.trim() ? { latestVersion: normalizeVersion(latest.value) } : {}),
155
+ updateAvailable: Boolean(latest.value.trim() && versionAtLeast(normalizeVersion(latest.value), cliVersion) && normalizeVersion(latest.value) !== cliVersion),
152
156
  ...(version.error ? { versionError: version.error } : {}),
153
157
  ...(daemon.error ? { daemonError: daemon.error } : {}),
154
158
  ...(plugins.error || adapterLoadError ? { pluginError: plugins.error || adapterLoadError } : {}),
@@ -171,6 +175,22 @@ export class OpenCliRunner {
171
175
  connected: match[3] === 'connected' && (disconnected < 0 || position < disconnected), isDefault: /\sdefault\s+—/.test(line) }];
172
176
  });
173
177
  }
178
+ async ensureBrowser(signal) {
179
+ if ((await this.profiles(signal)).some(profile => profile.connected))
180
+ return;
181
+ const child = process.platform === 'win32'
182
+ ? spawn('cmd.exe', ['/c', 'start', '', 'msedge.exe', 'about:blank'], { detached: true, stdio: 'ignore', windowsHide: true })
183
+ : process.platform === 'darwin'
184
+ ? spawn('open', ['-a', 'Google Chrome', 'about:blank'], { detached: true, stdio: 'ignore' })
185
+ : spawn('xdg-open', ['about:blank'], { detached: true, stdio: 'ignore' });
186
+ child.unref();
187
+ for (let i = 0; i < 20; i++) {
188
+ await new Promise(resolve => setTimeout(resolve, 500));
189
+ if ((await this.profiles(signal)).some(profile => profile.connected))
190
+ return;
191
+ }
192
+ throw new OpenCliError('Browser started, but the OpenCLI extension did not connect', 'EXTENSION_NOT_CONNECTED');
193
+ }
174
194
  async installPlugin(pluginUrl, signal) {
175
195
  const before = await this.command(['plugin', 'list'], signal);
176
196
  if (new RegExp(`\\b${ADAPTER_PLUGIN_NAME}\\b`, 'i').test(before.stdout)) {
@@ -259,6 +279,18 @@ export class OpenCliRunner {
259
279
  }
260
280
  }
261
281
  }
282
+ async function latestOpenCliVersion(signal) {
283
+ const npm = resolveNpmInvocation();
284
+ if (!npm)
285
+ return { value: '', diagnostic: '' };
286
+ try {
287
+ const result = await execFile(npm.file, [...npm.prefix, 'view', OPENCLI_NPM_PACKAGE, 'version'], { encoding: 'utf8', timeout: 15_000, signal });
288
+ return { value: String(result.stdout).trim(), diagnostic: '' };
289
+ }
290
+ catch {
291
+ return { value: '', diagnostic: '' };
292
+ }
293
+ }
262
294
  /** Keep successful-process diagnostics: OpenCLI reports plugin import failures on stderr while exiting zero. */
263
295
  function adapterPluginLoadError(diagnostic = '') {
264
296
  const lines = diagnostic.split(/\r?\n/)
@@ -323,19 +355,40 @@ function openCliCandidates(configured) {
323
355
  return [...new Set(candidates.filter(Boolean))];
324
356
  }
325
357
  function resolveNpmInvocation() {
358
+ const node = resolveNodeExecutable();
326
359
  const npmExecPath = process.env.npm_execpath;
327
360
  if (npmExecPath && existsSync(npmExecPath)) {
328
361
  return /\.(?:c?js|mjs)$/i.test(npmExecPath)
329
- ? { file: process.execPath, prefix: [npmExecPath] }
362
+ ? { file: node, prefix: [npmExecPath] }
330
363
  : { file: npmExecPath, prefix: [] };
331
364
  }
332
- const besideNode = join(dirname(process.execPath), 'node_modules', 'npm', 'bin', 'npm-cli.js');
333
- if (existsSync(besideNode))
334
- return { file: process.execPath, prefix: [besideNode] };
365
+ const npmEntries = [
366
+ join(dirname(node), 'node_modules', 'npm', 'bin', 'npm-cli.js'),
367
+ join(dirname(node), '..', 'node_modules', 'npm', 'bin', 'npm-cli.js'),
368
+ ];
369
+ for (const entry of npmEntries)
370
+ if (existsSync(entry))
371
+ return { file: node, prefix: [entry] };
335
372
  if (process.platform !== 'win32')
336
373
  return { file: 'npm', prefix: [] };
337
374
  return undefined;
338
375
  }
376
+ /** Electron Node mode still advertises Electron, so CLI parsers misread argv. */
377
+ function resolveNodeExecutable(shimDirectory) {
378
+ if (!process.versions.electron)
379
+ return process.execPath;
380
+ const binary = process.platform === 'win32' ? 'node.exe' : 'node';
381
+ const resources = process.platform === 'darwin'
382
+ ? resolve(dirname(process.execPath), '..', 'Resources')
383
+ : join(dirname(process.execPath), 'resources');
384
+ const candidates = [
385
+ ...(shimDirectory ? [join(shimDirectory, binary)] : []),
386
+ // Official Desktop ships a standalone dependency runtime as well as Electron.
387
+ join(resources, 'runtime', 'primary-runtime', 'dependencies', 'node', 'bin', binary),
388
+ ...(process.env.PATH ?? '').split(delimiter).filter(Boolean).map(path => join(path.replace(/^"|"$/g, ''), binary)),
389
+ ];
390
+ return candidates.find(candidate => existsSync(candidate) && resolve(candidate) !== resolve(process.execPath)) ?? 'node';
391
+ }
339
392
  function normalizeVersion(value) { return value.trim().replace(/^v/i, '').split(/\s+/)[0] ?? ''; }
340
393
  /** Numeric semver comparison for the stable x.y.z versions OpenCLI publishes. */
341
394
  export function versionAtLeast(value, minimum) {
@@ -357,12 +410,12 @@ function resolveInvocation(configured) {
357
410
  if (/\.cmd$/i.test(configured) && existsSync(explicit)) {
358
411
  const entry = join(explicit, '..', 'node_modules', '@jackwener', 'opencli', 'dist', 'src', 'main.js');
359
412
  if (existsSync(entry))
360
- return { file: process.execPath, prefix: [entry] };
413
+ return { file: resolveNodeExecutable(dirname(explicit)), prefix: [entry] };
361
414
  }
362
415
  if (process.platform === 'win32' && configured === 'opencli') {
363
416
  const entry = process.env.APPDATA && join(process.env.APPDATA, 'npm', 'node_modules', '@jackwener', 'opencli', 'dist', 'src', 'main.js');
364
417
  if (entry && existsSync(entry))
365
- return { file: process.execPath, prefix: [entry] };
418
+ return { file: resolveNodeExecutable(join(process.env.APPDATA, 'npm')), prefix: [entry] };
366
419
  }
367
420
  return { file: configured, prefix: [] };
368
421
  }
package/lib/reference.js CHANGED
@@ -158,8 +158,7 @@ function notice(summary) {
158
158
  text: `A conversation reference in the previous message could not be resolved: ${summary}`,
159
159
  }],
160
160
  source: {
161
- kind: 'plugin',
162
- plugin: name,
161
+ kind: 'reference-anything',
163
162
  form: 'notice',
164
163
  summary: boundContextSummary(summary),
165
164
  },
@@ -100,6 +100,7 @@ export default class WebChatHistoryService extends Service implements ReferenceS
100
100
  health(signal?: AbortSignal): Promise<import("../../opencli.ts").OpenCliHealth>;
101
101
  quickHealth(signal?: AbortSignal): Promise<import("../../opencli.ts").OpenCliHealth>;
102
102
  profiles(signal?: AbortSignal): Promise<import("../../opencli.ts").BrowserProfile[]>;
103
+ ensureBrowser(signal?: AbortSignal): Promise<void>;
103
104
  private runner;
104
105
  installAdapter(signal?: AbortSignal): Promise<boolean>;
105
106
  private installAdapterFrom;
@@ -123,6 +123,7 @@ export default class WebChatHistoryService extends Service {
123
123
  end = decodeLiveCursor(window.cursor, conversationKey);
124
124
  let rows;
125
125
  try {
126
+ await this.ensureBrowser(signal);
126
127
  rows = await this.runner().detail(conversation.provider, conversation.externalId, signal, conversation.accountScope);
127
128
  }
128
129
  catch (error) {
@@ -208,7 +209,12 @@ export default class WebChatHistoryService extends Service {
208
209
  throw new ReferenceAnythingError('wait for the current conversation sync to finish before updating', 'REFERENCE_SYNC_IN_PROGRESS');
209
210
  return this.packageUpdates.update(signal);
210
211
  }
211
- async restartDaemon(signal) { await this.runner().restartDaemon(signal); return true; }
212
+ async restartDaemon(signal) {
213
+ const runner = this.runner();
214
+ await runner.restartDaemon(signal);
215
+ await this.ensureBrowser(signal);
216
+ return true;
217
+ }
212
218
  async discoverOpenCli(signal) {
213
219
  return discoverOpenCli(this.store.settings.opencliPath, signal);
214
220
  }
@@ -267,6 +273,20 @@ export default class WebChatHistoryService extends Service {
267
273
  return new OpenCliRunner({ executable: settings.opencliPath, profile: '',
268
274
  timeoutMs: this.config.timeoutMs, maxStdoutBytes: this.config.maxStdoutBytes }).profiles(signal);
269
275
  }
276
+ async ensureBrowser(signal) {
277
+ const settings = this.store.settings;
278
+ const runner = this.runner();
279
+ const connected = await runner.profiles(signal);
280
+ const selected = connected.find(profile => profile.connected);
281
+ if (selected && !settings.profile) {
282
+ await this.store.setSettings({ ...settings, profile: selected.alias || selected.id });
283
+ return;
284
+ }
285
+ await runner.ensureBrowser(signal);
286
+ const after = (await runner.profiles(signal)).find(profile => profile.connected);
287
+ if (after)
288
+ await this.store.setSettings({ ...settings, profile: after.alias || after.id });
289
+ }
270
290
  runner() {
271
291
  const settings = this.store.settings;
272
292
  return new OpenCliRunner({ executable: settings.opencliPath, profile: settings.profile,
package/lib/types.d.ts CHANGED
@@ -236,6 +236,10 @@ export interface ReferenceInput {
236
236
  }
237
237
  declare module '@deepseek-ai/dsh-llm' {
238
238
  interface MessageSourceMap {
239
- 'reference-anything': ReferenceContextSource;
239
+ 'reference-anything': ReferenceContextSource | {
240
+ readonly kind: 'reference-anything';
241
+ readonly form: 'notice';
242
+ readonly summary: string;
243
+ };
240
244
  }
241
245
  }
package/lib/web.js CHANGED
@@ -1,11 +1,10 @@
1
1
  import { ReferenceAnythingRemote } from "./host.js";
2
2
  import { TYPERT_MANIFEST } from "./typert.js";
3
3
  export const name = 'reference-anything-web';
4
- // `referenceCloudDrive` is consumed lazily by ReferenceAnythingRemote when the
5
- // composer asks for @drive candidates. Declare it here so Cordis exposes the
6
- // sibling service in this plugin scope instead of making driveSearch silently
7
- // look like an unconfigured installation.
8
- export const inject = ['typert', 'referenceChatHistory', 'openListManager', 'referenceCloudDrive'];
4
+ // ReferenceAnythingRemote looks up optional sources through ctx.get(). Making
5
+ // cloud drives a required injection blocks all conversation endpoints when
6
+ // that source is disabled or unavailable in the active profile.
7
+ export const inject = ['typert', 'referenceChatHistory', 'openListManager'];
9
8
  export function apply(ctx) {
10
9
  new ReferenceAnythingRemote(ctx);
11
10
  ctx.effect(() => {
package/locale/en.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "Reference Anything",
4
+ "description": "Reference files, sessions, commands, skills, and historical external AI chats from the DSH @ menu."
5
+ }
6
+ }
package/locale/zh.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "引用万物",
4
+ "description": "在 DSH 的 @ 菜单中引用文件、会话、命令、技能和外部 AI 历史对话。"
5
+ }
6
+ }
@@ -138,6 +138,22 @@ async function inTemporaryTab(page, task) {
138
138
  }
139
139
  }
140
140
 
141
+ async function navigate(page, url, options) {
142
+ let last
143
+ for (let attempt = 0; attempt < 3; attempt++) {
144
+ try { await page.goto(url, options); return } catch (error) {
145
+ last = error
146
+ if (!/Navigation rejected/i.test(String(error?.message || error)) || attempt === 2) throw error
147
+ if (attempt > 0 && typeof page.newTab === 'function' && typeof page.setActivePage === 'function') {
148
+ const pageId = await page.newTab(url).catch(() => undefined)
149
+ if (pageId) { await page.setActivePage(pageId); return }
150
+ }
151
+ await new Promise(resolve => setTimeout(resolve, 250 * (attempt + 1)))
152
+ }
153
+ }
154
+ throw last
155
+ }
156
+
141
157
  export function registerProvider(config) {
142
158
  const browserSession = SYNC_BROWSER_SESSION
143
159
 
@@ -154,7 +170,7 @@ export function registerProvider(config) {
154
170
  args: [],
155
171
  columns: ['identity'],
156
172
  func: async (page) => inTemporaryTab(page, async () => {
157
- await page.goto(config.home, { waitUntil: 'none' })
173
+ await navigate(page, config.home, { waitUntil: 'none' })
158
174
  const result = await evaluateWhenProviderReady(
159
175
  page, config.whoamiScript, {}, `${config.site} whoami`, { accepts: terminalIdentityResult },
160
176
  )
@@ -180,7 +196,7 @@ export function registerProvider(config) {
180
196
  func: async (page, kwargs) => inTemporaryTab(page, async () => {
181
197
  const since = String(kwargs.since || '').trim()
182
198
  if (since && Number.isNaN(Date.parse(since))) throw new ArgumentError('since must be an ISO 8601 instant')
183
- await page.goto(config.home, { waitUntil: 'none' })
199
+ await navigate(page, config.home, { waitUntil: 'none' })
184
200
  const identity = await evaluateWhenProviderReady(
185
201
  page, config.whoamiScript, {}, `${config.site} sync-index identity`, { accepts: terminalIdentityResult },
186
202
  )
@@ -217,7 +233,7 @@ export function registerProvider(config) {
217
233
  func: async (page, kwargs) => inTemporaryTab(page, async () => {
218
234
  const since = String(kwargs.since || '').trim()
219
235
  if (since && Number.isNaN(Date.parse(since))) throw new ArgumentError('since must be an ISO 8601 instant')
220
- await page.goto(config.home, { waitUntil: 'none' })
236
+ await navigate(page, config.home, { waitUntil: 'none' })
221
237
  const rows = assertResult(
222
238
  await evaluateWhenProviderReady(page, config.historyScript, { since }, `${config.site} history-all`),
223
239
  config.domain,
@@ -245,7 +261,7 @@ export function registerProvider(config) {
245
261
  func: async (page, kwargs) => inTemporaryTab(page, async () => {
246
262
  const id = String(kwargs.id || '').trim()
247
263
  if (!id) throw new ArgumentError('id must be a non-empty conversation id')
248
- await page.goto(config.home, { settleMs: 600 })
264
+ await navigate(page, config.home, { settleMs: 600 })
249
265
  const expectedScope = parseExpectedAccountScope(kwargs.accountScope)
250
266
  if (expectedScope) {
251
267
  const identity = await evaluate(page, config.whoamiScript, {}, `${config.site} detail identity`)
@@ -257,7 +273,7 @@ export function registerProvider(config) {
257
273
  }
258
274
  let result = await evaluate(page, config.detailScript, { id }, `${config.site} detail`)
259
275
  if (result?.ok !== true && result?.code !== 'AUTH' && result?.code !== 'RATE_LIMIT' && config.fallbackScript) {
260
- await page.goto(config.conversationUrl(id), { settleMs: 1800 })
276
+ await navigate(page, config.conversationUrl(id), { settleMs: 1800 })
261
277
  result = await evaluate(page, config.fallbackScript, { id }, `${config.site} detail fallback`)
262
278
  }
263
279
  const rows = assertResult(result, config.domain, `${config.site} detail`)
@@ -291,7 +307,7 @@ export function registerProvider(config) {
291
307
  if (!Number.isInteger(maxBytes) || maxBytes < 1 || maxBytes > 26_214_400) {
292
308
  throw new ArgumentError('maxBytes must be between 1 and 26214400')
293
309
  }
294
- await page.goto(config.home, { settleMs: 500 })
310
+ await navigate(page, config.home, { settleMs: 500 })
295
311
  const expectedScope = parseExpectedAccountScope(kwargs.accountScope)
296
312
  if (expectedScope) {
297
313
  const identity = await evaluateWhenProviderReady(
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "dsh-reference-anything",
3
- "version": "0.4.2",
4
- "description": "Reference commands, skills, workspace files, DSH sessions, local agent transcripts, cloud-drive files, and mirrored web-chat conversations from one DeepSeek Harness @ menu",
3
+ "version": "0.4.3",
4
+ "description": "Reference files, sessions, commands, skills, and historical external AI chats from the DSH @ menu.",
5
+ "icon": "./images/logo-icon.png",
5
6
  "license": "MIT",
6
7
  "publishConfig": {
7
8
  "access": "public"
@@ -58,6 +59,8 @@
58
59
  "types": "./lib/client/index.d.ts",
59
60
  "default": "./lib/client.js"
60
61
  },
62
+ "./locale/en.json": "./locale/en.json",
63
+ "./locale/zh.json": "./locale/zh.json",
61
64
  "./package.json": "./package.json"
62
65
  },
63
66
  "files": [
@@ -66,7 +69,10 @@
66
69
  "opencli-plugin/opencli-plugin.json",
67
70
  "opencli-plugin/package.json",
68
71
  "cordis.patch.yml",
72
+ "locale/*.json",
69
73
  "images/logo.png",
74
+ "images/logo-icon.png",
75
+ "images/logo-mono.png",
70
76
  "NOTICE.md",
71
77
  "README.md"
72
78
  ],
@@ -99,29 +105,30 @@
99
105
  },
100
106
  "peerDependencies": {
101
107
  "@deepseek-ai/cordis": ">=4.0.1",
102
- "@deepseek-ai/dsh-agent": ">=0.1.2-rc.1",
103
- "@deepseek-ai/dsh-api-remotes": ">=0.1.2-rc.1",
104
- "@deepseek-ai/dsh-attachment": ">=0.1.2-rc.1",
105
- "@deepseek-ai/dsh-client-connection": ">=0.1.2-rc.1",
106
- "@deepseek-ai/dsh-client-locale": ">=0.1.2-rc.1",
107
- "@deepseek-ai/dsh-api-session-controller": ">=0.1.2-rc.1",
108
- "@deepseek-ai/dsh-client-store": ">=0.1.2-rc.1",
109
- "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.2-rc.1",
110
- "@deepseek-ai/dsh-client-ui-input-trigger": ">=0.1.2-rc.1",
111
- "@deepseek-ai/dsh-client-ui-renderer": ">=0.1.2-rc.1",
112
- "@deepseek-ai/dsh-client-ui-settings": ">=0.1.2-rc.1",
113
- "@deepseek-ai/dsh-client-ui-slots": ">=0.1.2-rc.1",
114
- "@deepseek-ai/dsh-client-ui-workspace": ">=0.1.2-rc.1",
115
- "@deepseek-ai/dsh-file-reference": ">=0.1.2-rc.1",
116
- "@deepseek-ai/dsh-llm": ">=0.1.2-rc.1",
117
- "@deepseek-ai/dsh-output-retention": ">=0.1.2-rc.1",
118
- "@deepseek-ai/dsh-session": ">=0.1.2-rc.1",
119
- "@deepseek-ai/dsh-session-reference": ">=0.1.2-rc.1",
120
- "@deepseek-ai/dsh-settings": ">=0.1.2-rc.1",
121
- "@deepseek-ai/dsh-storage-domain": ">=0.1.2-rc.1",
122
- "@deepseek-ai/dsh-tools": ">=0.1.2-rc.1",
123
- "@deepseek-ai/dsh-typert-protocol": ">=0.1.2-rc.1",
124
- "@deepseek-ai/dsh-typert-registry": ">=0.1.2-rc.1",
108
+ "@deepseek-ai/dsh-agent": ">=0.2.0-rc.2",
109
+ "@deepseek-ai/dsh-api-remotes": ">=0.2.0-rc.2",
110
+ "@deepseek-ai/dsh-api-session-controller": ">=0.2.0-rc.2",
111
+ "@deepseek-ai/dsh-attachment": ">=0.2.0-rc.2",
112
+ "@deepseek-ai/dsh-client-connection": ">=0.2.0-rc.2",
113
+ "@deepseek-ai/dsh-client-locale": ">=0.2.0-rc.2",
114
+ "@deepseek-ai/dsh-client-store": ">=0.2.0-rc.2",
115
+ "@deepseek-ai/dsh-client-ui-conversation": ">=0.2.0-rc.2",
116
+ "@deepseek-ai/dsh-client-ui-input-trigger": ">=0.2.0-rc.2",
117
+ "@deepseek-ai/dsh-client-ui-primitives": ">=0.2.0-rc.2",
118
+ "@deepseek-ai/dsh-client-ui-renderer": ">=0.2.0-rc.2",
119
+ "@deepseek-ai/dsh-client-ui-settings": ">=0.2.0-rc.2",
120
+ "@deepseek-ai/dsh-client-ui-slots": ">=0.2.0-rc.2",
121
+ "@deepseek-ai/dsh-client-ui-workspace": ">=0.2.0-rc.2",
122
+ "@deepseek-ai/dsh-file-reference": ">=0.2.0-rc.2",
123
+ "@deepseek-ai/dsh-llm": ">=0.2.0-rc.2",
124
+ "@deepseek-ai/dsh-output-retention": ">=0.2.0-rc.2",
125
+ "@deepseek-ai/dsh-session": ">=0.2.0-rc.2",
126
+ "@deepseek-ai/dsh-session-reference": ">=0.2.0-rc.2",
127
+ "@deepseek-ai/dsh-settings": ">=0.2.0-rc.2",
128
+ "@deepseek-ai/dsh-storage-domain": ">=0.2.0-rc.2",
129
+ "@deepseek-ai/dsh-tools": ">=0.2.0-rc.2",
130
+ "@deepseek-ai/dsh-typert-protocol": ">=0.2.0-rc.2",
131
+ "@deepseek-ai/dsh-typert-registry": ">=0.2.0-rc.2",
125
132
  "react": "^18.2.0"
126
133
  },
127
134
  "peerDependenciesMeta": {
@@ -175,44 +182,55 @@
175
182
  "@deepseek-ai/schemastery": "^3.18.1",
176
183
  "@lobehub/icons": "^5.16.0",
177
184
  "react-markdown": "^10.1.0",
185
+ "sortablejs": "^1.15.7",
178
186
  "zod": "^4.4.3"
179
187
  },
180
188
  "devDependencies": {
181
189
  "@deepseek-ai/cordis": "^4.0.1",
182
- "@deepseek-ai/dsh-agent": "0.1.2-rc.1",
183
- "@deepseek-ai/dsh-api-remotes": "0.1.2-rc.1",
184
- "@deepseek-ai/dsh-attachment": "0.1.2-rc.1",
185
- "@deepseek-ai/dsh-client-connection": "0.1.2-rc.1",
186
- "@deepseek-ai/dsh-client-locale": "0.1.2-rc.1",
187
- "@deepseek-ai/dsh-api-session-controller": "0.1.2-rc.1",
188
- "@deepseek-ai/dsh-client-store": "0.1.2-rc.1",
189
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1",
190
- "@deepseek-ai/dsh-client-ui-input-trigger": "0.1.2-rc.1",
191
- "@deepseek-ai/dsh-client-ui-renderer": "0.1.2-rc.1",
192
- "@deepseek-ai/dsh-client-ui-settings": "0.1.2-rc.1",
193
- "@deepseek-ai/dsh-client-ui-slots": "0.1.2-rc.1",
194
- "@deepseek-ai/dsh-client-ui-workspace": "0.1.2-rc.1",
195
- "@deepseek-ai/dsh-file-reference": "0.1.2-rc.1",
196
- "@deepseek-ai/dsh-llm": "0.1.2-rc.1",
197
- "@deepseek-ai/dsh-output-retention": "0.1.2-rc.1",
198
- "@deepseek-ai/dsh-session": "0.1.2-rc.1",
199
- "@deepseek-ai/dsh-session-reference": "0.1.2-rc.1",
200
- "@deepseek-ai/dsh-settings": "0.1.2-rc.1",
201
- "@deepseek-ai/dsh-storage": "0.1.2-rc.1",
202
- "@deepseek-ai/dsh-storage-domain": "0.1.2-rc.1",
203
- "@deepseek-ai/dsh-system-prompt": "0.1.2-rc.1",
204
- "@deepseek-ai/dsh-tools": "0.1.2-rc.1",
205
- "@deepseek-ai/dsh-typert-protocol": "0.1.2-rc.1",
206
- "@deepseek-ai/dsh-typert-registry": "0.1.2-rc.1",
190
+ "@deepseek-ai/dsh-agent": "0.2.0-rc.2",
191
+ "@deepseek-ai/dsh-api-remotes": "0.2.0-rc.2",
192
+ "@deepseek-ai/dsh-api-session-controller": "0.2.0-rc.2",
193
+ "@deepseek-ai/dsh-attachment": "0.2.0-rc.2",
194
+ "@deepseek-ai/dsh-client-connection": "0.2.0-rc.2",
195
+ "@deepseek-ai/dsh-client-locale": "0.2.0-rc.2",
196
+ "@deepseek-ai/dsh-client-store": "0.2.0-rc.2",
197
+ "@deepseek-ai/dsh-client-ui-conversation": "0.2.0-rc.2",
198
+ "@deepseek-ai/dsh-client-ui-input-trigger": "0.2.0-rc.2",
199
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.2",
200
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.2",
201
+ "@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.2",
202
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.2",
203
+ "@deepseek-ai/dsh-client-ui-workspace": "0.2.0-rc.2",
204
+ "@deepseek-ai/dsh-file-reference": "0.2.0-rc.2",
205
+ "@deepseek-ai/dsh-llm": "0.2.0-rc.2",
206
+ "@deepseek-ai/dsh-output-retention": "0.2.0-rc.2",
207
+ "@deepseek-ai/dsh-session": "0.2.0-rc.2",
208
+ "@deepseek-ai/dsh-session-reference": "0.2.0-rc.2",
209
+ "@deepseek-ai/dsh-settings": "0.2.0-rc.2",
210
+ "@deepseek-ai/dsh-storage": "0.2.0-rc.2",
211
+ "@deepseek-ai/dsh-storage-domain": "0.2.0-rc.2",
212
+ "@deepseek-ai/dsh-system-prompt": "0.2.0-rc.2",
213
+ "@deepseek-ai/dsh-tools": "0.2.0-rc.2",
214
+ "@deepseek-ai/dsh-typert-protocol": "0.2.0-rc.2",
215
+ "@deepseek-ai/dsh-typert-registry": "0.2.0-rc.2",
216
+ "@deepseek-ai/dsh-util-code-language": "0.2.0-rc.2",
217
+ "@deepseek-ai/dsh-util-workspace-path": "0.2.0-rc.2",
207
218
  "@jackwener/opencli": "1.8.6",
219
+ "@shikijs/langs": "4.3.1",
208
220
  "@types/node": "^22.20.1",
209
221
  "@types/react": "^18.2.0",
210
222
  "@types/react-dom": "^18.3.7",
223
+ "@types/sortablejs": "^1.15.9",
224
+ "anser": "2.3.5",
211
225
  "esbuild": "^0.25.0",
212
226
  "jsdom": "^26.1.0",
227
+ "katex": "0.16.47",
213
228
  "react": "^18.2.0",
214
229
  "react-dom": "^18.2.0",
230
+ "shiki": "4.3.1",
231
+ "simple-icons": "^16.31.0",
215
232
  "typescript": "^5.7.0",
216
- "vitest": "^3.0.0"
233
+ "vitest": "^3.0.0",
234
+ "zustand": "^5.0.15"
217
235
  }
218
236
  }