Ship prebuilt lib/index.js so GitHub installs load under node_modules.

Node refuses TypeScript stripping inside node_modules; point package main at the host bundle and document GitHub as the default install.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-09-04 22:32:01 +08:00
parent 0fcff2d45a
commit 0040de078c
4 changed files with 150 additions and 7 deletions

3
.gitignore vendored
View file

@ -1,7 +1,8 @@
node_modules/
dist/
# keep published client artifact; ignore other build junk under lib/
# keep published host + client artifacts
lib/*
!lib/index.js
!lib/client.js
*.log
.DS_Store

100
lib/index.js Normal file
View file

@ -0,0 +1,100 @@
// src/index.ts
import z from "@deepseek-ai/schemastery";
import { credentialRef } from "@deepseek-ai/dsh-credentials";
import * as McpClient from "@deepseek-ai/dsh-mcp-client";
var name = "netxops";
var inject = ["tools"];
var NETXOPS_SETTINGS_NAMESPACE = "netxops";
var DEFAULT_TOKEN_REF = "NETX_API_TOKEN";
var Config2 = z.object({
apiUrl: z.string().default("http://127.0.0.1:8890"),
lang: z.string().default("zh"),
pythonCommand: z.string().default("python"),
tokenCredentialRef: z.string().role("credential-ref").default(DEFAULT_TOKEN_REF),
toolCallTimeoutMs: z.number().step(1).min(1000).default(120000),
failOnStartupError: z.boolean().default(false)
});
async function resolveToken(ctx, refName) {
const credentials = ctx.get("credentials");
if (credentials === undefined)
return "";
const hit = await credentials.resolve(credentialRef(refName));
return hit?.value ?? "";
}
function apply(ctx, config = Config2({})) {
let source = () => config;
let mcpFiber;
let remounting = Promise.resolve();
let generation = 0;
const remount = () => {
remounting = remounting.then(async () => {
const gen = ++generation;
const previous = mcpFiber;
mcpFiber = undefined;
if (previous !== undefined) {
try {
await previous.dispose();
} catch (error) {
ctx.logger.warn("netxops: disposing previous mcp-client failed: %s", error);
}
}
if (gen !== generation)
return;
const current = source();
const token = await resolveToken(ctx, current.tokenCredentialRef);
if (gen !== generation)
return;
const mcpConfig = McpClient.Config({
transport: "stdio",
serverName: "netx",
command: current.pythonCommand,
args: ["-m", "netx_mcp"],
env: {
NETX_API_URL: current.apiUrl.replace(/\/$/, ""),
NETX_API_TOKEN: token,
NETX_LANG: current.lang
},
toolCallTimeoutMs: current.toolCallTimeoutMs,
failOnStartupError: current.failOnStartupError
});
try {
mcpFiber = await ctx.plugin(McpClient, mcpConfig);
} catch (error) {
ctx.logger.error("netxops: failed to mount mcp-client: %s", error);
if (current.failOnStartupError)
throw error;
}
}).catch((error) => {
ctx.logger.error("netxops: remount error: %s", error);
});
};
remount();
ctx.inject(["settings"], (settingsCtx) => {
settingsCtx.settings.installSection(ctx, NETXOPS_SETTINGS_NAMESPACE, Config2, config, {
setSource: (current) => {
source = current;
},
onChange: () => {
remount();
}
});
});
ctx.on("credentials/reference-updated", (ref) => {
if (String(ref) === source().tokenCredentialRef)
remount();
});
ctx.effect(() => () => {
generation += 1;
const fiber = mcpFiber;
mcpFiber = undefined;
fiber?.dispose();
}, "netxops: dispose mcp-client");
}
export {
name,
inject,
apply,
NETXOPS_SETTINGS_NAMESPACE,
DEFAULT_TOKEN_REF,
Config2 as Config
};

View file

@ -1,18 +1,19 @@
{
"name": "dsh-netxops",
"version": "0.1.4",
"version": "0.1.5",
"description": "DeepSeek Harness Netx Ops: host bridge + Plugins settings card + agent preset",
"license": "MIT",
"type": "module",
"private": false,
"main": "./src/index.ts",
"main": "./lib/index.js",
"exports": {
".": "./src/index.ts",
".": "./lib/index.js",
"./client": "./lib/client.js",
"./package.json": "./package.json"
},
"files": [
"src/",
"lib/index.js",
"lib/client.js",
"presets/",
"cordis.patch.yml",
@ -39,9 +40,10 @@
},
"homepage": "https://github.com/hansjone/netxops#readme",
"scripts": {
"bundle": "bun run scripts/build-client.mjs"
},
"dsh": {
"bundle": "bun run scripts/build-host.mjs && bun run scripts/build-client.mjs",
"bundle:host": "bun run scripts/build-host.mjs",
"bundle:client": "bun run scripts/build-client.mjs"
}, "dsh": {
"bundle": {
"patch": "./cordis.patch.yml"
},

40
scripts/build-host.mjs Normal file
View file

@ -0,0 +1,40 @@
/**
* Build lib/index.js (host Cordis plugin) for installs under node_modules.
* Node refuses to strip TypeScript inside node_modules, so GitHub/npm installs
* must ship prebuilt JS. Usage: bun run scripts/build-host.mjs
*/
import { mkdirSync, writeFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
const root = join(dirname(fileURLToPath(import.meta.url)), '..')
const entry = join(root, 'src/index.ts')
const outFile = join(root, 'lib', 'index.js')
const external = [
'@deepseek-ai/cordis',
'@deepseek-ai/schemastery',
'@deepseek-ai/dsh-credentials',
'@deepseek-ai/dsh-settings',
'@deepseek-ai/dsh-mcp-client',
'@deepseek-ai/dsh-tools',
]
const result = await Bun.build({
entrypoints: [entry],
target: 'node',
format: 'esm',
sourcemap: 'none',
minify: false,
external,
})
if (!result.success) {
console.error(result.logs)
throw new Error('Bun.build host failed')
}
const text = await result.outputs[0].text()
mkdirSync(dirname(outFile), { recursive: true })
writeFileSync(outFile, text, 'utf8')
console.log(`wrote ${outFile} (${text.length} bytes)`)