super-dsh 0.3.0-e → 0.3.0-g
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/README.md +13 -55
- package/client/index.js +141 -10
- package/cordis.patch.yml +6 -3
- package/package.json +12 -5
- package/remote/file-worker.js +341 -0
- package/remote/plugin.d.ts +523 -0
- package/remote/plugin.js +4979 -0
- package/remote/provenance.json +64 -0
- package/superd-hub/dist/a2a-row.d.ts +18 -2
- package/superd-hub/dist/a2a-row.js +11 -69
- package/superd-hub/dist/bundle-setup.d.ts +16 -6
- package/superd-hub/dist/bundle-setup.js +84 -148
- package/superd-hub/dist/client/companion-api.d.ts +5 -0
- package/superd-hub/dist/client/companion-api.js +30 -0
- package/superd-hub/dist/companion-contract.d.ts +9 -0
- package/superd-hub/dist/companion-contract.js +1 -0
- package/superd-hub/dist/companions.d.ts +30 -0
- package/superd-hub/dist/companions.js +209 -0
- package/superd-hub/dist/exec-pty-framing.d.ts +3 -1
- package/superd-hub/dist/exec-pty-framing.js +12 -4
- package/superd-hub/dist/exec-pty-session.d.ts +2 -0
- package/superd-hub/dist/exec-pty-session.js +7 -13
- package/superd-hub/dist/exec.d.ts +5 -2
- package/superd-hub/dist/exec.js +34 -54
- package/superd-hub/dist/fusion-transport.js +1 -0
- package/superd-hub/dist/gateway.js +24 -11
- package/superd-hub/dist/hub-tool.d.ts +3 -0
- package/superd-hub/dist/hub-tool.js +13 -5
- package/superd-hub/dist/remote-file-rpc.d.ts +20 -0
- package/superd-hub/dist/remote-file-rpc.js +574 -0
- package/superd-hub/dist/remote-job-client.d.ts +3 -0
- package/superd-hub/dist/remote-job-client.js +197 -0
- package/superd-hub/dist/remote-job-rpc.d.ts +21 -0
- package/superd-hub/dist/remote-job-rpc.js +155 -0
- package/superd-hub/dist/remote-provider.d.ts +13 -0
- package/superd-hub/dist/remote-provider.js +151 -0
- package/superd-hub/dist/remote-row.d.ts +6 -0
- package/superd-hub/dist/remote-row.js +13 -0
- package/superd-hub/lib/client/index.js +141 -10
- package/superd-hub/package.json +1 -2
- package/superd-hub/scripts/register-companion.mjs +0 -100
|
@@ -2198,6 +2198,145 @@ async function removeProvider(agentKey, namespace, id, doFetch) {
|
|
|
2198
2198
|
return requireProvidersView(await callRuntimeSettings(agentKey, namespace, "remove", { request: { id } }, doFetch));
|
|
2199
2199
|
}
|
|
2200
2200
|
|
|
2201
|
+
//#endregion
|
|
2202
|
+
//#region src/client/companion-api.ts
|
|
2203
|
+
async function callCompanion(operation, doFetch) {
|
|
2204
|
+
const method = `superdCompanions/${operation}`;
|
|
2205
|
+
const response = await (doFetch ?? ((path, init) => fetch(path, init)))(`/api/${method}`, {
|
|
2206
|
+
method: "POST",
|
|
2207
|
+
credentials: "same-origin",
|
|
2208
|
+
headers: { "content-type": "application/json" },
|
|
2209
|
+
body: JSON.stringify({
|
|
2210
|
+
type: "client-request",
|
|
2211
|
+
rpcId: mintRpcId(),
|
|
2212
|
+
method,
|
|
2213
|
+
payload: { args: {} }
|
|
2214
|
+
})
|
|
2215
|
+
});
|
|
2216
|
+
if (!response.ok) throw new Error(`Better Dash: HTTP ${response.status}`);
|
|
2217
|
+
let body;
|
|
2218
|
+
try {
|
|
2219
|
+
body = JSON.parse(await response.text());
|
|
2220
|
+
} catch {
|
|
2221
|
+
throw new Error("Better Dash: unreadable response");
|
|
2222
|
+
}
|
|
2223
|
+
const result = body?.result;
|
|
2224
|
+
if (result?.ok !== true) throw new Error(result?.error?.message ?? "Better Dash: request failed");
|
|
2225
|
+
const value = result.value;
|
|
2226
|
+
if (value === null || typeof value !== "object" || typeof value.installed !== "boolean" || typeof value.installing !== "boolean" || typeof value.requestedVersion !== "string" || value.version !== void 0 && typeof value.version !== "string" || value.enabled !== void 0 && typeof value.enabled !== "boolean" || value.error !== void 0 && typeof value.error !== "string") throw new Error("Better Dash: invalid status");
|
|
2227
|
+
return value;
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2230
|
+
//#endregion
|
|
2231
|
+
//#region src/client/CompanionSettings.tsx
|
|
2232
|
+
/** Native plugin switches remain in Plugin Manager; this row provides explicit recovery. */
|
|
2233
|
+
function CompanionSettings() {
|
|
2234
|
+
const [status, setStatus] = react.default.useState();
|
|
2235
|
+
const [error, setError] = react.default.useState();
|
|
2236
|
+
const [busy, setBusy] = react.default.useState(false);
|
|
2237
|
+
const live = react.default.useRef(false);
|
|
2238
|
+
const operation = react.default.useRef(false);
|
|
2239
|
+
react.default.useEffect(() => {
|
|
2240
|
+
live.current = true;
|
|
2241
|
+
let reading = false;
|
|
2242
|
+
const refresh = async () => {
|
|
2243
|
+
if (reading || operation.current) return;
|
|
2244
|
+
reading = true;
|
|
2245
|
+
try {
|
|
2246
|
+
const next = await callCompanion("getBetterDash");
|
|
2247
|
+
if (live.current) {
|
|
2248
|
+
setStatus(next);
|
|
2249
|
+
setError(next.error);
|
|
2250
|
+
}
|
|
2251
|
+
} catch (cause) {
|
|
2252
|
+
if (live.current) setError(cause instanceof Error ? cause.message : String(cause));
|
|
2253
|
+
} finally {
|
|
2254
|
+
reading = false;
|
|
2255
|
+
}
|
|
2256
|
+
};
|
|
2257
|
+
refresh();
|
|
2258
|
+
const timer = window.setInterval(() => {
|
|
2259
|
+
refresh();
|
|
2260
|
+
}, 5e3);
|
|
2261
|
+
return () => {
|
|
2262
|
+
live.current = false;
|
|
2263
|
+
window.clearInterval(timer);
|
|
2264
|
+
};
|
|
2265
|
+
}, []);
|
|
2266
|
+
const install = async () => {
|
|
2267
|
+
if (operation.current) return;
|
|
2268
|
+
operation.current = true;
|
|
2269
|
+
setBusy(true);
|
|
2270
|
+
setError(void 0);
|
|
2271
|
+
try {
|
|
2272
|
+
const next = await callCompanion("installBetterDash");
|
|
2273
|
+
if (live.current) {
|
|
2274
|
+
setStatus(next);
|
|
2275
|
+
setError(next.error);
|
|
2276
|
+
}
|
|
2277
|
+
} catch (cause) {
|
|
2278
|
+
if (live.current) setError(cause instanceof Error ? cause.message : String(cause));
|
|
2279
|
+
} finally {
|
|
2280
|
+
operation.current = false;
|
|
2281
|
+
if (live.current) setBusy(false);
|
|
2282
|
+
}
|
|
2283
|
+
};
|
|
2284
|
+
const installing = busy || status?.installing === true;
|
|
2285
|
+
const label = status === void 0 ? "Loading…" : status.installed ? `Installed${status.version ? " · " + status.version : ""}${status.enabled === false ? " · Disabled" : ""}` : "Not installed";
|
|
2286
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2287
|
+
style: {
|
|
2288
|
+
borderRadius: 12,
|
|
2289
|
+
padding: "12px 14px",
|
|
2290
|
+
background: "var(--dsw-alias-interactive-bg-hover)"
|
|
2291
|
+
},
|
|
2292
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2293
|
+
style: {
|
|
2294
|
+
display: "flex",
|
|
2295
|
+
alignItems: "center",
|
|
2296
|
+
gap: 16
|
|
2297
|
+
},
|
|
2298
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2299
|
+
style: { flex: 1 },
|
|
2300
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2301
|
+
style: {
|
|
2302
|
+
fontSize: 14,
|
|
2303
|
+
fontWeight: 600
|
|
2304
|
+
},
|
|
2305
|
+
children: "Better Dash"
|
|
2306
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2307
|
+
role: "status",
|
|
2308
|
+
style: {
|
|
2309
|
+
fontSize: 12,
|
|
2310
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
2311
|
+
marginTop: 4
|
|
2312
|
+
},
|
|
2313
|
+
children: installing ? "Installing…" : label
|
|
2314
|
+
})]
|
|
2315
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2316
|
+
type: "button",
|
|
2317
|
+
disabled: installing || status?.installed === true,
|
|
2318
|
+
onClick: () => {
|
|
2319
|
+
install();
|
|
2320
|
+
},
|
|
2321
|
+
style: {
|
|
2322
|
+
padding: "6px 12px",
|
|
2323
|
+
borderRadius: 8,
|
|
2324
|
+
cursor: installing || status?.installed ? "default" : "pointer"
|
|
2325
|
+
},
|
|
2326
|
+
children: installing ? "Installing…" : status?.installed ? "Installed" : "Install"
|
|
2327
|
+
})]
|
|
2328
|
+
}), error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2329
|
+
role: "alert",
|
|
2330
|
+
style: {
|
|
2331
|
+
fontSize: 12,
|
|
2332
|
+
margin: "8px 0 0",
|
|
2333
|
+
color: "var(--dsw-alias-state-error-primary)"
|
|
2334
|
+
},
|
|
2335
|
+
children: error
|
|
2336
|
+
})]
|
|
2337
|
+
});
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2201
2340
|
//#endregion
|
|
2202
2341
|
//#region src/client/HubPage.tsx
|
|
2203
2342
|
const EMPTY_DRAFT = {
|
|
@@ -3415,16 +3554,8 @@ function HubPage() {
|
|
|
3415
3554
|
},
|
|
3416
3555
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupHead, {
|
|
3417
3556
|
title: "Settings",
|
|
3418
|
-
count:
|
|
3419
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
3420
|
-
style: {
|
|
3421
|
-
margin: 0,
|
|
3422
|
-
fontSize: 13,
|
|
3423
|
-
lineHeight: "20px",
|
|
3424
|
-
color: "var(--dsw-alias-label-tertiary)"
|
|
3425
|
-
},
|
|
3426
|
-
children: "Hub preferences — pairing, runtime visibility, and orchestration defaults land with the hub service."
|
|
3427
|
-
})]
|
|
3557
|
+
count: 1
|
|
3558
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CompanionSettings, {})]
|
|
3428
3559
|
}),
|
|
3429
3560
|
tab === "home" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
3430
3561
|
style: {
|
package/superd-hub/package.json
CHANGED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
// Separate-process entry for the SAME native package operations used by dsh plugin.
|
|
2
|
-
// No shell interpolation, package scripts, upstream edits, or online companion lookup.
|
|
3
|
-
import { createRequire } from 'node:module'
|
|
4
|
-
import { readFile } from 'node:fs/promises'
|
|
5
|
-
import { join } from 'node:path'
|
|
6
|
-
import { pathToFileURL } from 'node:url'
|
|
7
|
-
let input = ''
|
|
8
|
-
for await (const bytes of process.stdin) input += bytes
|
|
9
|
-
const {profile,expected} = JSON.parse(input)
|
|
10
|
-
const require = createRequire(profile.installAnchor)
|
|
11
|
-
const {runProfilePnpm,saveManifest} = await import(pathToFileURL(require.resolve('@deepseek-ai/dsh-plugin-manager/operations')).href)
|
|
12
|
-
const {withFileLock,writeFileAtomic} = await import(pathToFileURL(require.resolve('@deepseek-ai/dsh-atomic-write')).href)
|
|
13
|
-
const abort = new AbortController()
|
|
14
|
-
process.once('SIGTERM', () => abort.abort())
|
|
15
|
-
const json = async path => JSON.parse(await readFile(path, 'utf8'))
|
|
16
|
-
async function optionalJson(path) { try { return await json(path) } catch(error) { if(error.code === 'ENOENT') return undefined; throw error } }
|
|
17
|
-
const skipped = disposition => ({ exitCode: 0, disposition })
|
|
18
|
-
// Complete each native acquisition/release before observing cancellation;
|
|
19
|
-
// exiting during its async lock-file write can strand incomplete lock metadata.
|
|
20
|
-
async function withCancellableProfileLock(operation) {
|
|
21
|
-
const path = join(profile.dir, 'package.json'), deadline = Date.now() + 120000
|
|
22
|
-
for (;;) {
|
|
23
|
-
abort.signal.throwIfAborted()
|
|
24
|
-
let acquired = false
|
|
25
|
-
try {
|
|
26
|
-
return await withFileLock(path, async () => {
|
|
27
|
-
acquired = true
|
|
28
|
-
abort.signal.throwIfAborted()
|
|
29
|
-
return operation()
|
|
30
|
-
}, { waitMs: Math.min(250, Math.max(0, deadline - Date.now())) })
|
|
31
|
-
} catch (error) {
|
|
32
|
-
abort.signal.throwIfAborted()
|
|
33
|
-
if (acquired || Date.now() >= deadline
|
|
34
|
-
|| error.message !== `atomic-write: timed out waiting for the writer lock at ${path}.lock`) throw error
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
const result = await withCancellableProfileLock(async () => {
|
|
39
|
-
abort.signal.throwIfAborted()
|
|
40
|
-
const current = await json(join(profile.dir, 'package.json'))
|
|
41
|
-
if (typeof expected.ownerSpec !== 'string' || current.dependencies?.[expected.owner] !== expected.ownerSpec) return skipped('owner-changed')
|
|
42
|
-
const ownerDir = join(profile.dir, 'node_modules', expected.owner)
|
|
43
|
-
let owner
|
|
44
|
-
try { owner = await json(join(ownerDir, 'package.json')) }
|
|
45
|
-
catch (error) { if (error.code === 'ENOENT') return skipped('owner-changed'); throw error }
|
|
46
|
-
const item=expected.companion
|
|
47
|
-
if(owner.name !== 'super-dsh' || owner.version !== item.version || owner.dependencies?.[item.name] !== item.version) return skipped('owner-changed')
|
|
48
|
-
// Resolve from the owner: a retained older direct Better may coexist with the new transitive version.
|
|
49
|
-
const ownerRequire=createRequire(join(ownerDir,'package.json'))
|
|
50
|
-
const downloaded=await json(ownerRequire.resolve(item.name+'/package.json'))
|
|
51
|
-
if(downloaded.name !== item.name || downloaded.version !== item.version) throw new Error('The user installation did not fetch the exact companion dependency')
|
|
52
|
-
const prior = current.dependencies?.[item.name]
|
|
53
|
-
if (prior !== expected.priorSpec) return skipped(prior === undefined && expected.priorSpec !== undefined ? 'companion-removed' : 'companion-changed')
|
|
54
|
-
abort.signal.throwIfAborted()
|
|
55
|
-
// A plain npm consumer already has the exact transitive files but not a pnpm
|
|
56
|
-
// store. Fresh hoisted registration changes metadata only, preserving npm ci.
|
|
57
|
-
const npmLockPath=join(profile.dir,'package-lock.json')
|
|
58
|
-
const npmLock=await optionalJson(npmLockPath)
|
|
59
|
-
const staged=structuredClone(current)
|
|
60
|
-
staged.dependencies={...staged.dependencies,[item.name]:item.version}
|
|
61
|
-
const selectNew=manifest=>{
|
|
62
|
-
if(prior !== undefined)return
|
|
63
|
-
const bundles=manifest.dsh?.profile?.bundles??[]
|
|
64
|
-
manifest.dsh={...manifest.dsh,profile:{...manifest.dsh?.profile,bundles:[...bundles,...bundles.includes(item.name)?[]:[item.name]]}}
|
|
65
|
-
}
|
|
66
|
-
const installedBefore=await optionalJson(join(profile.dir,'node_modules',item.name,'package.json'))
|
|
67
|
-
if(npmLock?.packages?.[''] && installedBefore?.version === item.version) {
|
|
68
|
-
const beforeLock=await readFile(npmLockPath,'utf8')
|
|
69
|
-
npmLock.packages[''].dependencies={...npmLock.packages[''].dependencies,[item.name]:item.version}
|
|
70
|
-
try {
|
|
71
|
-
selectNew(staged)
|
|
72
|
-
await writeFileAtomic(npmLockPath,JSON.stringify(npmLock,null,2)+'\n',{mode:0o600})
|
|
73
|
-
await saveManifest(profile.dir,staged)
|
|
74
|
-
} catch(error) { await writeFileAtomic(npmLockPath,beforeLock,{mode:0o600});await saveManifest(profile.dir,current);throw error }
|
|
75
|
-
return {exitCode:0,disposition:'installed'}
|
|
76
|
-
}
|
|
77
|
-
// No named spec: native add --offline still does online pnpm view preflight.
|
|
78
|
-
// Stage the exact dependency under the same lock, then re-layout cached files
|
|
79
|
-
// with the package manager that actually produced the consumer's lockfile.
|
|
80
|
-
await saveManifest(profile.dir,staged)
|
|
81
|
-
let operation
|
|
82
|
-
try {
|
|
83
|
-
operation=await runProfilePnpm({profile:profile.name,dir:profile.dir,installAnchor:profile.installAnchor,cwd:profile.dir,home:profile.home},
|
|
84
|
-
npmLock ? ['install','--offline','--ignore-scripts','--no-audit','--no-fund'] : ['install','--offline','--ignore-scripts','--no-frozen-lockfile'], {
|
|
85
|
-
...profile.packageManager, ...npmLock?{command:'npm',args:[]}: {},
|
|
86
|
-
execution:'service', signal:abort.signal, outputBytes:16384,
|
|
87
|
-
lookupTimeoutMs:120000, idleTimeoutMs:120000,
|
|
88
|
-
})
|
|
89
|
-
if(operation.exitCode !== 0) { await saveManifest(profile.dir,current) }
|
|
90
|
-
else {
|
|
91
|
-
const installed=await json(join(profile.dir,'node_modules',item.name,'package.json'))
|
|
92
|
-
const after=await json(join(profile.dir,'package.json'))
|
|
93
|
-
if(installed.name !== item.name || installed.version !== item.version || after.dependencies?.[item.name] !== item.version) throw new Error('Native companion registration did not resolve the exact cached registry version')
|
|
94
|
-
selectNew(after)
|
|
95
|
-
await saveManifest(profile.dir,after)
|
|
96
|
-
}
|
|
97
|
-
} catch(error) { await saveManifest(profile.dir,current);throw error }
|
|
98
|
-
return { exitCode: operation.exitCode, logPath: operation.logPath, disposition: 'installed' }
|
|
99
|
-
})
|
|
100
|
-
process.stdout.write(JSON.stringify(result)+'\n')
|