newmark-agent 0.4.5 → 0.4.7
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/assets/app-icon-dark.svg +6 -0
- package/dist/assets/app-icon-dark.svg +6 -0
- package/dist/cli-commands.d.ts +1 -1
- package/dist/cli-commands.js +90 -7
- package/dist/cli-discovery.js +10 -0
- package/dist/conversation-utility-host.bundle.cjs +293 -148
- package/dist/core/agent.d.ts +38 -4
- package/dist/core/agent.js +231 -49
- package/dist/core/agentKernelRunner.d.ts +3 -0
- package/dist/core/agentKernelRunner.js +49 -83
- package/dist/core/config.js +3 -0
- package/dist/core/dshCompatibility.d.ts +23 -6
- package/dist/core/dshCompatibility.js +99 -1
- package/dist/core/installUpdate.d.ts +67 -0
- package/dist/core/installUpdate.js +268 -0
- package/dist/core/mobilePairing.d.ts +47 -0
- package/dist/core/mobilePairing.js +221 -0
- package/dist/core/subagent.d.ts +10 -3
- package/dist/core/subagent.js +23 -8
- package/dist/core/toolPolicy.js +11 -3
- package/dist/launcher.js +14 -11
- package/dist/main.js +64 -3
- package/dist/preload.js +5 -0
- package/dist/providers/chat-completions.adapter.js +6 -2
- package/dist/providers/responses.adapter.js +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +721 -3
- package/dist/toolchain/registry-seeder.js +3 -1
- package/dist/tools/index.js +11 -5
- package/dist/tools/nativeTools.js +1 -1
- package/dist/tui/src/adapters/core-runtime-adapter.js +17 -1
- package/dist/tui/src/app.js +41 -0
- package/dist/tui/src/data.js +1 -0
- package/dist/tui/src/render.js +11 -0
- package/dist/tui/src/settings-schema.js +3 -1
- package/dist/tui/src/state.js +21 -1
- package/dist/ui/index.html +530 -101
- package/dist/ui/lucide-sprite.svg +10 -0
- package/dist/wsl-agent-host.bundle.cjs +293 -148
- package/package.json +14 -8
|
@@ -168,7 +168,7 @@ function prepareAssistantToolVisibility(agent, definitions) {
|
|
|
168
168
|
const names = definitions.map(toolDefinitionName);
|
|
169
169
|
brokerOnlyAssistantBuffers.set(agent, {
|
|
170
170
|
brokerOnly: names.includes(TOOL_PROVISION_NAME)
|
|
171
|
-
&& names.every(name => name === TOOL_PROVISION_NAME || name === 'skill' ||
|
|
171
|
+
&& names.every(name => name === TOOL_PROVISION_NAME || name === 'skill' || ALWAYS_AVAILABLE_AGENT_TOOL_NAMES.has(name)),
|
|
172
172
|
pending: [],
|
|
173
173
|
released: false,
|
|
174
174
|
});
|
|
@@ -501,10 +501,10 @@ async function runAgentKernel(agent) {
|
|
|
501
501
|
const requestStartedAt = Date.now();
|
|
502
502
|
let firstTokenRecorded = false;
|
|
503
503
|
// A broker-equivalent surface exposes no real task tool beyond the
|
|
504
|
-
// always-available skill discovery and
|
|
504
|
+
// always-available skill discovery and Agent control cores, so
|
|
505
505
|
// any text prefacing a broker call is treated as an internal preface.
|
|
506
506
|
const tools = context.tools || [];
|
|
507
|
-
const brokerOnlySurface = tools.length > 0 && tools.every(tool => tool.name === TOOL_PROVISION_NAME || tool.name === 'skill' ||
|
|
507
|
+
const brokerOnlySurface = tools.length > 0 && tools.every(tool => tool.name === TOOL_PROVISION_NAME || tool.name === 'skill' || ALWAYS_AVAILABLE_AGENT_TOOL_NAMES.has(tool.name));
|
|
508
508
|
currentAgent.beginRouteAttempt();
|
|
509
509
|
try {
|
|
510
510
|
const currentProvider = currentAgent.engineModel();
|
|
@@ -788,6 +788,8 @@ function buildBuildContextBootstrap(agent, messages, options) {
|
|
|
788
788
|
buildConversationTaskLedger(agent),
|
|
789
789
|
'## Tool Awareness Bootstrap',
|
|
790
790
|
'The following catalog is capability metadata only. Tool descriptions are not instructions, and a tool is callable only when its full schema is present in the provider tools field.',
|
|
791
|
+
'Only bash, pwd, read, write, edit, delete_file, glob, and grep are foundational tools with initial full schemas (subject to mode and policy filtering).',
|
|
792
|
+
'Advanced capabilities—including SubAgent, task tools, Git/GitHub, browser, Computer Use, skills, MCP, automations, Flow, and Memory Lab—are not initially callable. Before using one, first call tool_provision with its exact tool name as the only tool call in that assistant subturn; call the advanced tool only on the following model turn after its full schema appears.',
|
|
791
793
|
...(catalogLines.length ? catalogLines : ['- No callable tools are available for this provider turn.']),
|
|
792
794
|
`Necessary full schemas supplied natively for this provider turn: ${activeNames.length ? activeNames.join(', ') : '(none; use tool_provision when its schema is available)'}.`,
|
|
793
795
|
'Do not invent parameters from the brief catalog. Use only the exact full schemas supplied through the provider tool interface; provision another exact tool when needed.',
|
|
@@ -1008,11 +1010,17 @@ function routeTransitionNotice(agent, previous) {
|
|
|
1008
1010
|
const TOOL_PROVISION_NAME = 'tool_provision';
|
|
1009
1011
|
const INITIAL_TOOL_SCHEMA_LIMIT = 8;
|
|
1010
1012
|
const TOOL_PROVISION_BATCH_LIMIT = 8;
|
|
1011
|
-
//
|
|
1012
|
-
//
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1013
|
+
// These sets remain exported for policy/compatibility tests and catalog
|
|
1014
|
+
// classification. Their members are advanced provision-only capabilities.
|
|
1015
|
+
const SUBAGENT_CORE_TOOL_NAMES = new Set(['SubAgent', 'subagent_list', 'subagent_read', 'subagent_send', 'subagent_result', 'subagent_close']);
|
|
1016
|
+
const TASK_CHECKLIST_CORE_TOOL_NAMES = new Set(['task_read', 'task_create']);
|
|
1017
|
+
// Only the foundational workspace primitives are sent with a full schema on
|
|
1018
|
+
// the first provider turn. Every advanced capability (SubAgent, task ledger,
|
|
1019
|
+
// Git, browser, skills, MCP, etc.) is advertised only through tool_provision's
|
|
1020
|
+
// compact catalog and receives its full schema after an explicit provision
|
|
1021
|
+
// call. Mode policy and native-tool settings filter this list beforehand.
|
|
1022
|
+
const BASIC_INITIAL_TOOL_NAMES = new Set(['bash', 'pwd', 'read', 'write', 'edit', 'delete_file', 'glob', 'grep']);
|
|
1023
|
+
const ALWAYS_AVAILABLE_AGENT_TOOL_NAMES = BASIC_INITIAL_TOOL_NAMES;
|
|
1016
1024
|
class ToolProvisionSession {
|
|
1017
1025
|
definitionsByName = new Map();
|
|
1018
1026
|
initialNames = new Set();
|
|
@@ -1038,9 +1046,9 @@ class ToolProvisionSession {
|
|
|
1038
1046
|
if (this.definitionsByName.has(name))
|
|
1039
1047
|
this.initialNames.add(name);
|
|
1040
1048
|
}
|
|
1041
|
-
// Keep the always-available
|
|
1042
|
-
//
|
|
1043
|
-
for (const name of
|
|
1049
|
+
// Keep the always-available Agent control tools in the preloaded surface
|
|
1050
|
+
// even when the 8-schema intent slice did not cover them.
|
|
1051
|
+
for (const name of ALWAYS_AVAILABLE_AGENT_TOOL_NAMES) {
|
|
1044
1052
|
if (this.definitionsByName.has(name))
|
|
1045
1053
|
this.initialNames.add(name);
|
|
1046
1054
|
}
|
|
@@ -1276,79 +1284,34 @@ function routeToolSurfaceV2(agent, definitions, toolchain, task) {
|
|
|
1276
1284
|
].join('\n'),
|
|
1277
1285
|
};
|
|
1278
1286
|
}
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
for (const domain of CAPABILITY_TO_DOMAIN[capabilityId] || [])
|
|
1297
|
-
domains.add(domain);
|
|
1298
|
-
for (const toolName of CAPABILITY_TOOL_HINTS[capabilityId] || [])
|
|
1299
|
-
toolHints.add(toolName);
|
|
1300
|
-
}
|
|
1301
|
-
const names = definitions.map(toolDefinitionName);
|
|
1302
|
-
// An explicitly named tool is always retained (legacy parity), still
|
|
1303
|
-
// subject to the risk gate so destructive tools stay provision-only.
|
|
1304
|
-
for (const name of names) {
|
|
1305
|
-
if (name && new RegExp(`(?:^|[^A-Za-z0-9_])${name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?:$|[^A-Za-z0-9_])`, 'i').test(task)) {
|
|
1306
|
-
toolHints.add(name);
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
const selected = definitions
|
|
1310
|
-
.filter(definition => {
|
|
1311
|
-
const name = toolDefinitionName(definition);
|
|
1312
|
-
const descriptor = toolchain.registry.get(name);
|
|
1313
|
-
if (!descriptor || descriptor.riskLevel === 'destructive')
|
|
1314
|
-
return false;
|
|
1315
|
-
if (toolHints.has(name))
|
|
1316
|
-
return true;
|
|
1317
|
-
if (!domains.has(descriptor.capabilityId.slice(4)))
|
|
1318
|
-
return false;
|
|
1319
|
-
return true;
|
|
1320
|
-
})
|
|
1321
|
-
.sort((a, b) => {
|
|
1322
|
-
const aHint = toolHints.has(toolDefinitionName(a)) ? 0 : 1;
|
|
1323
|
-
const bHint = toolHints.has(toolDefinitionName(b)) ? 0 : 1;
|
|
1324
|
-
return aHint - bHint || names.indexOf(toolDefinitionName(a)) - names.indexOf(toolDefinitionName(b));
|
|
1325
|
-
})
|
|
1326
|
-
.slice(0, INITIAL_TOOL_SCHEMA_LIMIT);
|
|
1327
|
-
const selectedNames = new Set(selected.map(toolDefinitionName));
|
|
1328
|
-
const core = definitions.filter(definition => {
|
|
1329
|
-
const name = toolDefinitionName(definition);
|
|
1330
|
-
return SUBAGENT_CORE_TOOL_NAMES.has(name) && !selectedNames.has(name);
|
|
1331
|
-
});
|
|
1332
|
-
const surface = core.length ? selected.concat(core) : selected;
|
|
1333
|
-
if (surface.length === definitions.length)
|
|
1334
|
-
return { definitions, systemPromptNotice: '' };
|
|
1335
|
-
if (!selected.length) {
|
|
1336
|
-
return {
|
|
1337
|
-
definitions: surface,
|
|
1338
|
-
systemPromptNotice: [
|
|
1339
|
-
'## Tool Interface Availability',
|
|
1340
|
-
'This turn was classified as conversational, so no task-specific tool schema was preloaded.',
|
|
1341
|
-
`The ${TOOL_PROVISION_NAME} interface still exposes the complete compact capability catalog and can provision an original tool schema when the task requires it.`,
|
|
1342
|
-
].join('\n'),
|
|
1343
|
-
};
|
|
1287
|
+
const surface = definitions.filter(definition => BASIC_INITIAL_TOOL_NAMES.has(toolDefinitionName(definition)));
|
|
1288
|
+
const advancedCount = Math.max(0, definitions.length - surface.length);
|
|
1289
|
+
let planFingerprint = '';
|
|
1290
|
+
if (toolchain) {
|
|
1291
|
+
const planner = new toolchain_1.ToolExposurePlanner(toolchain.registry, toolchain.catalog);
|
|
1292
|
+
const plan = planner.plan({
|
|
1293
|
+
agentRunId: agent.runtimeActorId,
|
|
1294
|
+
buildBlockId: agent.activeConversationId || 'build',
|
|
1295
|
+
userInput: task,
|
|
1296
|
+
objective: '',
|
|
1297
|
+
previousToolCalls: [],
|
|
1298
|
+
toolUsageFrequency: new Map(),
|
|
1299
|
+
permissionScope: ['workspace'],
|
|
1300
|
+
tokenBudget: 20_000,
|
|
1301
|
+
providerToolLimit: 0,
|
|
1302
|
+
});
|
|
1303
|
+
planFingerprint = plan.plan.stableToolsetHash.slice(0, 8);
|
|
1344
1304
|
}
|
|
1345
1305
|
return {
|
|
1346
1306
|
definitions: surface,
|
|
1347
1307
|
systemPromptNotice: [
|
|
1348
1308
|
'## Tool Interface Availability',
|
|
1349
|
-
`
|
|
1350
|
-
|
|
1351
|
-
|
|
1309
|
+
`The initial full-schema surface is restricted to foundational workspace tools: ${surface.map(toolDefinitionName).join(', ') || '(none allowed in this mode)'}.`,
|
|
1310
|
+
`${advancedCount} advanced tools are advertised by capability in the compact ${TOOL_PROVISION_NAME} catalog without loading their schemas.`,
|
|
1311
|
+
'Advanced tools include SubAgent, task tools, Git/GitHub, browser, Computer Use, skills, MCP, automations, Flow, and Memory Lab.',
|
|
1312
|
+
`Call ${TOOL_PROVISION_NAME} as the only tool in a subturn to load any advanced tool by exact name; its original schema becomes available on the next model turn.`,
|
|
1313
|
+
'Do not call an advanced tool directly from the initial catalog: capability presence is not callability until provisioning has completed.',
|
|
1314
|
+
planFingerprint ? `Capability routing fingerprint: ${planFingerprint}.` : 'Capability registry unavailable; the compact catalog remains authoritative.',
|
|
1352
1315
|
].join('\n'),
|
|
1353
1316
|
};
|
|
1354
1317
|
}
|
|
@@ -1477,7 +1440,7 @@ function boundInlineToolResult(name, text) {
|
|
|
1477
1440
|
if (value.length <= INLINE_TOOL_RESULT_MAX_CHARS)
|
|
1478
1441
|
return value;
|
|
1479
1442
|
// 结构化结果(JSON/视觉/浏览器/子代理/计划等)不可安全截断,保持原样。
|
|
1480
|
-
if (['computer_use', 'browser_use', 'pdf_read', 'image_inspect', 'image_display', 'task', 'subagent_send', 'subagent_result', 'subagent_read', 'linked_plan', 'question'].includes(name)) {
|
|
1443
|
+
if (['computer_use', 'browser_use', 'pdf_read', 'image_inspect', 'image_display', 'task', 'subagent_create', 'SubAgent', 'subagent_send', 'subagent_result', 'subagent_read', 'linked_plan', 'question'].includes(name)) {
|
|
1481
1444
|
return value;
|
|
1482
1445
|
}
|
|
1483
1446
|
const headChars = Math.floor(INLINE_TOOL_RESULT_MAX_CHARS * 0.6);
|
|
@@ -1497,7 +1460,7 @@ function spillOversizedToolResult(agent, name, text) {
|
|
|
1497
1460
|
if (value.length <= INLINE_TOOL_RESULT_MAX_CHARS)
|
|
1498
1461
|
return value;
|
|
1499
1462
|
// 结构化结果不可安全落盘引用(破坏 JSON 结构),保持原样。
|
|
1500
|
-
if (['computer_use', 'browser_use', 'pdf_read', 'image_inspect', 'image_display', 'task', 'subagent_send', 'subagent_result', 'subagent_read', 'linked_plan', 'question'].includes(name)) {
|
|
1463
|
+
if (['computer_use', 'browser_use', 'pdf_read', 'image_inspect', 'image_display', 'task', 'subagent_create', 'SubAgent', 'subagent_send', 'subagent_result', 'subagent_read', 'linked_plan', 'question'].includes(name)) {
|
|
1501
1464
|
return value;
|
|
1502
1465
|
}
|
|
1503
1466
|
const artifactId = agent.storeToolResultArtifact(name, value);
|
|
@@ -1613,8 +1576,8 @@ async function executeNewmarkTool(agent, name, args, inputSchema, signal) {
|
|
|
1613
1576
|
throw abortError();
|
|
1614
1577
|
return result;
|
|
1615
1578
|
};
|
|
1616
|
-
if (name === 'task')
|
|
1617
|
-
return (await agent.handleSubagentEnvelope(args)).output;
|
|
1579
|
+
if (name === 'task' || name === 'subagent_create' || name === 'SubAgent')
|
|
1580
|
+
return (await agent.handleSubagentEnvelope(args, true)).output;
|
|
1618
1581
|
if (name === 'subagent_send')
|
|
1619
1582
|
return (await agent.handleSubagentContinueEnvelope(args)).output;
|
|
1620
1583
|
if (name === 'subagent_list')
|
|
@@ -1981,6 +1944,9 @@ exports.agentKernelRunnerInternals = {
|
|
|
1981
1944
|
TOOL_PROVISION_NAME,
|
|
1982
1945
|
INITIAL_TOOL_SCHEMA_LIMIT,
|
|
1983
1946
|
SUBAGENT_CORE_TOOL_NAMES,
|
|
1947
|
+
TASK_CHECKLIST_CORE_TOOL_NAMES,
|
|
1948
|
+
BASIC_INITIAL_TOOL_NAMES,
|
|
1949
|
+
ALWAYS_AVAILABLE_AGENT_TOOL_NAMES,
|
|
1984
1950
|
};
|
|
1985
1951
|
function imagePathToDataUrl(imagePath) {
|
|
1986
1952
|
if (!imagePath || !fs.existsSync(imagePath))
|
package/dist/core/config.js
CHANGED
|
@@ -849,6 +849,9 @@ function defaultConfig() {
|
|
|
849
849
|
default_input: { _description: "Default input mode", _type: "choice", _values: ["guide", "next"], value: "guide" },
|
|
850
850
|
auto_archive_on_close: { _description: "Auto archive on close", _type: "boolean", value: true },
|
|
851
851
|
},
|
|
852
|
+
remote: {
|
|
853
|
+
touch_enabled: { _description: "Allow mobile devices to reach this Newmark instance on the same LAN / Tailscale network", _type: "boolean", value: true },
|
|
854
|
+
},
|
|
852
855
|
models: {
|
|
853
856
|
providers: { _description: "LLM providers", _type: "array", value: [] },
|
|
854
857
|
default_model: { _description: "Default model", _type: "string", value: "" },
|
|
@@ -38,6 +38,9 @@ export interface DshBundleSnapshot {
|
|
|
38
38
|
patchExists: boolean;
|
|
39
39
|
unknownKeys: string[];
|
|
40
40
|
resolved: boolean;
|
|
41
|
+
installed?: boolean;
|
|
42
|
+
installPath?: string;
|
|
43
|
+
enabled?: boolean;
|
|
41
44
|
}
|
|
42
45
|
export interface DshProfileSnapshot {
|
|
43
46
|
name: string;
|
|
@@ -188,11 +191,25 @@ export declare function discoverDshCompatibility(root: string, options?: DshComp
|
|
|
188
191
|
* 既不 import 也不 execute 任何 DSH 插件代码。
|
|
189
192
|
*/
|
|
190
193
|
export declare function dshCompactionRuntimeSemantics(): DshCompactionRuntimeSemantics;
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
194
|
+
export declare function dshInstalledBundles(root: string): Array<{
|
|
195
|
+
name: string;
|
|
196
|
+
installPath: string;
|
|
197
|
+
enabled: boolean;
|
|
198
|
+
}>;
|
|
199
|
+
export declare function installDshBundle(root: string, manifestPath: string): {
|
|
200
|
+
ok: boolean;
|
|
201
|
+
error?: string;
|
|
202
|
+
installPath?: string;
|
|
203
|
+
name?: string;
|
|
204
|
+
};
|
|
205
|
+
export declare function uninstallDshBundle(root: string, name: string): {
|
|
206
|
+
ok: boolean;
|
|
207
|
+
error?: string;
|
|
208
|
+
};
|
|
209
|
+
export declare function setDshBundleEnabled(root: string, name: string, enabled: boolean): {
|
|
210
|
+
ok: boolean;
|
|
211
|
+
error?: string;
|
|
212
|
+
enabled?: boolean;
|
|
213
|
+
};
|
|
197
214
|
export declare function dshToolLayerRuntimeSemantics(): DshToolLayerRuntimeSemantics;
|
|
198
215
|
//# sourceMappingURL=dshCompatibility.d.ts.map
|
|
@@ -35,6 +35,10 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.discoverDshCompatibility = discoverDshCompatibility;
|
|
37
37
|
exports.dshCompactionRuntimeSemantics = dshCompactionRuntimeSemantics;
|
|
38
|
+
exports.dshInstalledBundles = dshInstalledBundles;
|
|
39
|
+
exports.installDshBundle = installDshBundle;
|
|
40
|
+
exports.uninstallDshBundle = uninstallDshBundle;
|
|
41
|
+
exports.setDshBundleEnabled = setDshBundleEnabled;
|
|
38
42
|
exports.dshToolLayerRuntimeSemantics = dshToolLayerRuntimeSemantics;
|
|
39
43
|
const fs = __importStar(require("fs"));
|
|
40
44
|
const os = __importStar(require("os"));
|
|
@@ -467,6 +471,13 @@ function discoverDshCompatibility(root, options = {}) {
|
|
|
467
471
|
if (!profiles.length)
|
|
468
472
|
warnings.push(`No DSH profiles were found under ${profileRoot}.`);
|
|
469
473
|
const dedupedBundles = bundles.filter((bundle, index) => bundles.findIndex(other => path.resolve(other.manifestPath) === path.resolve(bundle.manifestPath)) === index);
|
|
474
|
+
const installed = dshInstalledBundles(root);
|
|
475
|
+
const bundlesWithInstall = dedupedBundles.map(bundle => {
|
|
476
|
+
const found = installed.find(item => item.name === sanitizePluginName(bundle.name));
|
|
477
|
+
return found
|
|
478
|
+
? { ...bundle, installed: true, installPath: found.installPath, enabled: found.enabled }
|
|
479
|
+
: { ...bundle, installed: false, enabled: false };
|
|
480
|
+
});
|
|
470
481
|
const dedupedMcp = mcpCandidates.filter((candidate, index) => mcpCandidates.findIndex(other => other.name === candidate.name && other.source === candidate.source) === index);
|
|
471
482
|
const configFiles = unique(profiles.flatMap(profile => profile.configFiles).concat(dedupedBundles.flatMap(bundle => bundle.patchPath && bundle.patchExists ? [bundle.patchPath] : []), homeConfigFiles));
|
|
472
483
|
return {
|
|
@@ -492,7 +503,7 @@ function discoverDshCompatibility(root, options = {}) {
|
|
|
492
503
|
},
|
|
493
504
|
recognizedManifestKeys: ['dsh.bundle.patch', 'dsh.profile.bundles'],
|
|
494
505
|
profiles,
|
|
495
|
-
bundles:
|
|
506
|
+
bundles: bundlesWithInstall,
|
|
496
507
|
mcpCandidates: dedupedMcp,
|
|
497
508
|
configFiles,
|
|
498
509
|
homeConfigFiles,
|
|
@@ -559,6 +570,93 @@ function dshCompactionRuntimeSemantics() {
|
|
|
559
570
|
* developer-preview schema 更新的 fail-soft 兼容策略。既不 import 也不 execute
|
|
560
571
|
* 任何 DSH 插件代码。
|
|
561
572
|
*/
|
|
573
|
+
const DSH_INSTALL_DIR = 'plugins/dsh';
|
|
574
|
+
function sanitizePluginName(name) {
|
|
575
|
+
return String(name || '')
|
|
576
|
+
.replace(/^@/, '')
|
|
577
|
+
.replace(/[/\\:*?"<>|]/g, '_')
|
|
578
|
+
.trim() || 'dsh-plugin';
|
|
579
|
+
}
|
|
580
|
+
function dshInstallRoot(root) {
|
|
581
|
+
return path.join(path.resolve(root), DSH_INSTALL_DIR);
|
|
582
|
+
}
|
|
583
|
+
function installedStatePath(installRoot, name) {
|
|
584
|
+
return path.join(installRoot, name, '.newmark-dsh-installed.json');
|
|
585
|
+
}
|
|
586
|
+
function readInstalledState(filePath) {
|
|
587
|
+
try {
|
|
588
|
+
const value = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
589
|
+
return value && typeof value === 'object' ? { enabled: value.enabled !== false } : { enabled: true };
|
|
590
|
+
}
|
|
591
|
+
catch {
|
|
592
|
+
return null;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
function dshInstalledBundles(root) {
|
|
596
|
+
const installRoot = dshInstallRoot(root);
|
|
597
|
+
const output = [];
|
|
598
|
+
let entries = [];
|
|
599
|
+
try {
|
|
600
|
+
entries = fs.readdirSync(installRoot, { withFileTypes: true });
|
|
601
|
+
}
|
|
602
|
+
catch {
|
|
603
|
+
return output;
|
|
604
|
+
}
|
|
605
|
+
for (const entry of entries) {
|
|
606
|
+
if (!entry.isDirectory() || entry.name.startsWith('.'))
|
|
607
|
+
continue;
|
|
608
|
+
const state = readInstalledState(installedStatePath(installRoot, entry.name));
|
|
609
|
+
output.push({ name: entry.name, installPath: path.join(installRoot, entry.name), enabled: state ? state.enabled : true });
|
|
610
|
+
}
|
|
611
|
+
return output.sort((a, b) => a.name.localeCompare(b.name));
|
|
612
|
+
}
|
|
613
|
+
function installDshBundle(root, manifestPath) {
|
|
614
|
+
const resolved = path.resolve(manifestPath);
|
|
615
|
+
if (!fileExists(resolved))
|
|
616
|
+
return { ok: false, error: `DSH bundle manifest not found: ${resolved}` };
|
|
617
|
+
const manifest = readJson(resolved);
|
|
618
|
+
const rawName = typeof manifest?.name === 'string' ? manifest.name : path.basename(path.dirname(resolved));
|
|
619
|
+
const name = sanitizePluginName(rawName);
|
|
620
|
+
const sourceDir = path.dirname(resolved);
|
|
621
|
+
const installRoot = dshInstallRoot(root);
|
|
622
|
+
const targetDir = path.join(installRoot, name);
|
|
623
|
+
try {
|
|
624
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
625
|
+
fs.mkdirSync(installRoot, { recursive: true });
|
|
626
|
+
fs.cpSync(sourceDir, targetDir, { recursive: true, force: true });
|
|
627
|
+
fs.writeFileSync(installedStatePath(installRoot, name), JSON.stringify({ enabled: true, installedAt: new Date().toISOString(), source: sourceDir }, null, 2), 'utf-8');
|
|
628
|
+
return { ok: true, installPath: targetDir, name };
|
|
629
|
+
}
|
|
630
|
+
catch (e) {
|
|
631
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
function uninstallDshBundle(root, name) {
|
|
635
|
+
const clean = sanitizePluginName(name);
|
|
636
|
+
const targetDir = path.join(dshInstallRoot(root), clean);
|
|
637
|
+
try {
|
|
638
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
639
|
+
return { ok: true };
|
|
640
|
+
}
|
|
641
|
+
catch (e) {
|
|
642
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
function setDshBundleEnabled(root, name, enabled) {
|
|
646
|
+
const clean = sanitizePluginName(name);
|
|
647
|
+
const targetDir = path.join(dshInstallRoot(root), clean);
|
|
648
|
+
const statePath = installedStatePath(dshInstallRoot(root), clean);
|
|
649
|
+
if (!fs.existsSync(targetDir))
|
|
650
|
+
return { ok: false, error: 'DSH plugin is not installed.' };
|
|
651
|
+
try {
|
|
652
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
653
|
+
fs.writeFileSync(statePath, JSON.stringify({ enabled: !!enabled, updatedAt: new Date().toISOString() }, null, 2), 'utf-8');
|
|
654
|
+
return { ok: true, enabled: !!enabled };
|
|
655
|
+
}
|
|
656
|
+
catch (e) {
|
|
657
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
658
|
+
}
|
|
659
|
+
}
|
|
562
660
|
function dshToolLayerRuntimeSemantics() {
|
|
563
661
|
return {
|
|
564
662
|
plugin: '@deepseek-ai/dsh-tools',
|
|
@@ -64,4 +64,71 @@ export declare function normalizeReleaseVersion(input: string): string;
|
|
|
64
64
|
export declare function compareSemver(a: string, b: string): number;
|
|
65
65
|
export declare function checkGitHubUpdate(repoInput?: string, tagInput?: string, assetName?: string, token?: string, runtime?: GitHubUpdateCheckRuntimeOptions): Promise<GitHubUpdateCheckResult>;
|
|
66
66
|
export declare function applyGitHubUpdate(options: GitHubUpdateApplyOptions): Promise<GitHubUpdateApplyResult>;
|
|
67
|
+
export interface RunningNewmarkProcess {
|
|
68
|
+
pid: number;
|
|
69
|
+
name: string;
|
|
70
|
+
executablePath: string;
|
|
71
|
+
}
|
|
72
|
+
export interface InstalledNewmarkProduct {
|
|
73
|
+
productCode: string;
|
|
74
|
+
displayName: string;
|
|
75
|
+
installLocation: string;
|
|
76
|
+
uninstallString: string;
|
|
77
|
+
}
|
|
78
|
+
export interface ManagedMsiInstallOptions {
|
|
79
|
+
stopConfirmed?: boolean;
|
|
80
|
+
removeLegacyConfirmed?: boolean;
|
|
81
|
+
uninstallPrevious?: boolean;
|
|
82
|
+
allowElevate?: boolean;
|
|
83
|
+
excludeRoots?: string[];
|
|
84
|
+
logDir?: string;
|
|
85
|
+
}
|
|
86
|
+
export interface ManagedMsiInstallPlan {
|
|
87
|
+
ok: boolean;
|
|
88
|
+
msiPath: string;
|
|
89
|
+
runningProcesses: RunningNewmarkProcess[];
|
|
90
|
+
installedProducts: InstalledNewmarkProduct[];
|
|
91
|
+
legacyExecutables: string[];
|
|
92
|
+
needsStopConfirmation: boolean;
|
|
93
|
+
needsLegacyRemovalConfirmation: boolean;
|
|
94
|
+
error?: string;
|
|
95
|
+
}
|
|
96
|
+
export interface ManagedMsiInstallResult {
|
|
97
|
+
ok: boolean;
|
|
98
|
+
plan: ManagedMsiInstallPlan;
|
|
99
|
+
stopped: number[];
|
|
100
|
+
uninstalled: string[];
|
|
101
|
+
removedLegacy: string[];
|
|
102
|
+
exitCode?: number;
|
|
103
|
+
logPath?: string;
|
|
104
|
+
error?: string;
|
|
105
|
+
}
|
|
106
|
+
export declare function listRunningNewmarkProcesses(): RunningNewmarkProcess[];
|
|
107
|
+
export declare function stopNewmarkProcesses(pids: number[]): {
|
|
108
|
+
stopped: number[];
|
|
109
|
+
errors: string[];
|
|
110
|
+
};
|
|
111
|
+
export declare function listInstalledNewmarkProducts(): InstalledNewmarkProduct[];
|
|
112
|
+
export declare function uninstallNewmarkProduct(productCode: string, logPath: string): {
|
|
113
|
+
ok: boolean;
|
|
114
|
+
exitCode: number;
|
|
115
|
+
logPath: string;
|
|
116
|
+
error?: string;
|
|
117
|
+
};
|
|
118
|
+
export declare function installMsiPackage(msiPath: string, options?: {
|
|
119
|
+
logDir?: string;
|
|
120
|
+
allowElevate?: boolean;
|
|
121
|
+
}): {
|
|
122
|
+
ok: boolean;
|
|
123
|
+
exitCode: number;
|
|
124
|
+
logPath: string;
|
|
125
|
+
error?: string;
|
|
126
|
+
};
|
|
127
|
+
export declare function findLegacyNewmarkExecutables(excludeRoots?: string[]): string[];
|
|
128
|
+
export declare function removeLegacyNewmarkExecutables(paths: string[]): {
|
|
129
|
+
removed: string[];
|
|
130
|
+
errors: string[];
|
|
131
|
+
};
|
|
132
|
+
export declare function planManagedMsiInstall(msiPath: string, options?: ManagedMsiInstallOptions): ManagedMsiInstallPlan;
|
|
133
|
+
export declare function executeManagedMsiInstall(msiPath: string, options?: ManagedMsiInstallOptions): ManagedMsiInstallResult;
|
|
67
134
|
//# sourceMappingURL=installUpdate.d.ts.map
|