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 +1 -1
- package/lib/gateway.js +34 -2
- package/lib/index.js +12 -9
- package/lib/types/gateway.d.ts +18 -0
- package/package.json +1 -1
package/cordis.patch.yml
CHANGED
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 =
|
|
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 =
|
|
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,
|
|
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 = '~/.
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
488
|
+
return { workspaces: listAgentWorkspaces(effectiveDataDir(this.cfg.dataDir)) };
|
|
486
489
|
}
|
|
487
490
|
async workspaceGet(request) {
|
|
488
|
-
const config = readAgentWorkspace(
|
|
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(
|
|
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(
|
|
522
|
+
appendFileSync(join(effectiveDataDir(this.cfg.dataDir), DIAG_FILE), line + '\n');
|
|
520
523
|
return { written: true };
|
|
521
524
|
}
|
|
522
525
|
catch {
|
package/lib/types/gateway.d.ts
CHANGED
|
@@ -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.
|
|
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",
|