dsh-bots 0.2.14 → 0.2.16

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/cordis.patch.yml CHANGED
@@ -2,4 +2,4 @@
2
2
  - id: bots
3
3
  name: dsh-bots
4
4
  config:
5
- dataDir: '~/.sdk-bots'
5
+ dataDir: '~/.dsh-bots'
package/lib/gateway.js CHANGED
@@ -13,6 +13,38 @@ import { readFileSync } from 'node:fs';
13
13
  import { homedir } from 'node:os';
14
14
  import { AVATAR_DATA_URL_MAX } from './shared.js';
15
15
  const TOKEN_RE = /^[A-Za-z0-9._~+-]+$/;
16
+ /** New default root (0.2.16). The gateway may still live at the legacy root
17
+ * until the engine's SAND_DATA_ROOT migrates — every discovery consumer tries
18
+ * the configured dir first, then the legacy one. */
19
+ export const LEGACY_DATA_DIR = '~/.sdk-bots';
20
+ /**
21
+ * Discovery that follows the gateway to wherever it actually lives: the
22
+ * configured dir when it holds a gateway.json, else the legacy root. Returns
23
+ * null when neither has one (the gateway is simply down).
24
+ */
25
+ export function readDiscoveryWithFallback(dataDir, legacyDir = LEGACY_DATA_DIR) {
26
+ const direct = readDiscovery(dataDir);
27
+ if (direct !== null)
28
+ return direct;
29
+ if (expandHome(dataDir) !== expandHome(legacyDir))
30
+ return readDiscovery(legacyDir);
31
+ return null;
32
+ }
33
+ /**
34
+ * The directory where the gateway (and therefore agents/, box-workspace/,
35
+ * swarm/) actually lives right now: the configured dir if it has discovery,
36
+ * else the legacy root, else the configured dir as-is. All state-adjacent
37
+ * consumers (unread ledger, workspace ops, media allowlist, diag) resolve
38
+ * through this so they stay co-located with the real data across migration.
39
+ */
40
+ export function effectiveDataDir(dataDir, legacyDir = LEGACY_DATA_DIR) {
41
+ if (readDiscovery(dataDir) !== null)
42
+ return expandHome(dataDir);
43
+ if (expandHome(dataDir) !== expandHome(legacyDir) && readDiscovery(legacyDir) !== null) {
44
+ return expandHome(legacyDir);
45
+ }
46
+ return expandHome(dataDir);
47
+ }
16
48
  export function expandHome(p) {
17
49
  if (p === '~')
18
50
  return homedir();
@@ -54,7 +86,7 @@ export function readDiscovery(dataDir) {
54
86
  }
55
87
  /** Discovery + `/health` probe with pid match validation. */
56
88
  export async function discover(dataDir) {
57
- const d = readDiscovery(dataDir);
89
+ const d = readDiscoveryWithFallback(dataDir);
58
90
  if (d === null)
59
91
  return { ok: false, reason: 'no-gateway-json' };
60
92
  const baseUrl = `http://${d.host}:${d.port}`;
@@ -87,7 +119,7 @@ export async function discover(dataDir) {
87
119
  }
88
120
  /** POST one `/api/<method>` command; unwraps `{result}` and throws on errors. */
89
121
  export async function callGateway(dataDir, method, args = {}) {
90
- const d = readDiscovery(dataDir);
122
+ const d = readDiscoveryWithFallback(dataDir);
91
123
  if (d === null)
92
124
  throw new Error('gateway.json not found — sdk-bots host 是否在运行?');
93
125
  const baseUrl = `http://${d.host}:${d.port}`;
package/lib/index.js CHANGED
@@ -23,7 +23,7 @@ import { dirname, extname, join, resolve, sep } from 'node:path';
23
23
  import { appendFileSync, readFileSync, realpathSync, statSync } from 'node:fs';
24
24
  import { spawn } from 'node:child_process';
25
25
  import { pathToFileURL } from 'node:url';
26
- import { callGateway, discover, expandHome, nextNonce, normalizeAgents, readDiscovery, trimAgent, trimEntry } from './gateway.js';
26
+ import { callGateway, discover, effectiveDataDir, expandHome, nextNonce, normalizeAgents, readDiscoveryWithFallback, trimAgent, trimEntry } from './gateway.js';
27
27
  import { GatewaySseClient, SseRingBuffer } from './sse.js';
28
28
  import { UnreadStore } from './unread.js';
29
29
  import { listAgentWorkspaces, readAgentWorkspace, setAgentWorkspace } from './workspace.js';
@@ -34,7 +34,10 @@ export const name = 'dsh-bots';
34
34
  export const inject = [];
35
35
  /** Cordis range this plugin is tested against; only surfaces a warning. */
36
36
  export const TESTED_CORDIS_RANGE = '^4.0.1';
37
- const DEFAULT_DATA_DIR = '~/.sdk-bots';
37
+ const DEFAULT_DATA_DIR = '~/.dsh-bots';
38
+ /** Where the gateway lived before the 0.2.16 default rename — discovery and
39
+ * every data-dir consumer fall back to it until the engine migrates. */
40
+ const LEGACY_DATA_DIR = '~/.sdk-bots';
38
41
  /** Append-only diagnostics file, read when a shadow takeover misbehaves. */
39
42
  const DIAG_FILE = 'dsh-bots-diag.jsonl';
40
43
  /** Persisted read markers ("读到哪了") backing the sidebar unread badge. */
@@ -131,12 +134,12 @@ export class BotsRemote extends TypertRemoteService {
131
134
  constructor(ctx, config) {
132
135
  super(ctx, 'bots');
133
136
  this.cfg = { dataDir: config?.dataDir ?? DEFAULT_DATA_DIR };
134
- this.unread = new UnreadStore(join(expandHome(this.cfg.dataDir), UNREAD_FILE));
137
+ this.unread = new UnreadStore(join(effectiveDataDir(this.cfg.dataDir), UNREAD_FILE));
135
138
  const ring = new SseRingBuffer(3000, (channel, data) => { this.observeTranscript(channel, data); });
136
139
  this.sse = new GatewaySseClient({
137
140
  ring,
138
141
  resolveBase: () => {
139
- const d = readDiscovery(this.cfg.dataDir);
142
+ const d = readDiscoveryWithFallback(this.cfg.dataDir);
140
143
  if (d === null)
141
144
  return null;
142
145
  return { url: `http://${d.host}:${d.port}`, token: d.token };
@@ -295,7 +298,7 @@ export class BotsRemote extends TypertRemoteService {
295
298
  const p = String(raw ?? '').trim();
296
299
  if (p === '')
297
300
  throw new Error('path is required');
298
- const root = realpathSync(expandHome(this.cfg.dataDir));
301
+ const root = realpathSync(effectiveDataDir(this.cfg.dataDir));
299
302
  let resolved = resolve(expandHome(p));
300
303
  try {
301
304
  resolved = realpathSync(resolved);
@@ -482,16 +485,16 @@ export class BotsRemote extends TypertRemoteService {
482
485
  // these methods only read/write the per-agent settings.json contract.
483
486
  // ==========================================================
484
487
  async workspaceList(request) {
485
- return { workspaces: listAgentWorkspaces(expandHome(this.cfg.dataDir)) };
488
+ return { workspaces: listAgentWorkspaces(effectiveDataDir(this.cfg.dataDir)) };
486
489
  }
487
490
  async workspaceGet(request) {
488
- const config = readAgentWorkspace(expandHome(this.cfg.dataDir), String(request?.agentId ?? ''));
491
+ const config = readAgentWorkspace(effectiveDataDir(this.cfg.dataDir), String(request?.agentId ?? ''));
489
492
  if (config === null)
490
493
  throw new Error(`workspaceGet: agent 不存在或 id 不合法`);
491
494
  return config;
492
495
  }
493
496
  async workspaceSet(request) {
494
- return setAgentWorkspace(expandHome(this.cfg.dataDir), String(request?.agentId ?? ''), {
497
+ return setAgentWorkspace(effectiveDataDir(this.cfg.dataDir), String(request?.agentId ?? ''), {
495
498
  workspaceRoot: request?.workspaceRoot,
496
499
  allowPaths: request?.allowPaths,
497
500
  });
@@ -516,7 +519,7 @@ export class BotsRemote extends TypertRemoteService {
516
519
  stage: request.stage,
517
520
  detail: request.detail ?? null,
518
521
  });
519
- appendFileSync(join(expandHome(this.cfg.dataDir), DIAG_FILE), line + '\n');
522
+ appendFileSync(join(effectiveDataDir(this.cfg.dataDir), DIAG_FILE), line + '\n');
520
523
  return { written: true };
521
524
  }
522
525
  catch {
@@ -15,6 +15,24 @@ export interface Discovery {
15
15
  token: string | null;
16
16
  host: string;
17
17
  }
18
+ /** New default root (0.2.16). The gateway may still live at the legacy root
19
+ * until the engine's SAND_DATA_ROOT migrates — every discovery consumer tries
20
+ * the configured dir first, then the legacy one. */
21
+ export declare const LEGACY_DATA_DIR = "~/.sdk-bots";
22
+ /**
23
+ * Discovery that follows the gateway to wherever it actually lives: the
24
+ * configured dir when it holds a gateway.json, else the legacy root. Returns
25
+ * null when neither has one (the gateway is simply down).
26
+ */
27
+ export declare function readDiscoveryWithFallback(dataDir: string, legacyDir?: string): Discovery | null;
28
+ /**
29
+ * The directory where the gateway (and therefore agents/, box-workspace/,
30
+ * swarm/) actually lives right now: the configured dir if it has discovery,
31
+ * else the legacy root, else the configured dir as-is. All state-adjacent
32
+ * consumers (unread ledger, workspace ops, media allowlist, diag) resolve
33
+ * through this so they stay co-located with the real data across migration.
34
+ */
35
+ export declare function effectiveDataDir(dataDir: string, legacyDir?: string): string;
18
36
  export declare function expandHome(p: string): string;
19
37
  /** Read loopback discovery from `<dataDir>/gateway.json`; null when absent/stale. */
20
38
  export declare function readDiscovery(dataDir: string): Discovery | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-bots",
3
- "version": "0.2.14",
3
+ "version": "0.2.16",
4
4
  "description": "Multi-bot workbench for DeepSeek Harness: bridges the sdk-bots orchestration gateway (group chats, single bots) into the dsh web shell with official-styled UI.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",