@lengmoxxl/sdk 0.1.2 → 0.1.4

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 CHANGED
@@ -32,8 +32,8 @@ connection.disconnect();
32
32
 
33
33
  `openMachine` returns a `MachineConnection`; every call opens its own. Sharing one belongs to the caller: a
34
34
  connection is reference counted, so callers that hand the same one around keep it alive until the last
35
- `disconnect()`. `openMachine({ type: 'ssh', host, agent })` installs the carrier agent on the host first when
36
- `agent` is given.
35
+ `disconnect()`. `openMachine({ type: 'ssh', host, agent })` calls `agent(host)` before it connects: putting
36
+ the carrier agent on the host belongs to the app that embeds the SDK.
37
37
 
38
38
  - `connection.pty` - `list`, `cwd`, `create`, `attach`, `close`
39
39
  - `connection.fs` - `stat`, `readDirectory`, `readFile`
package/dist/agent.d.ts CHANGED
@@ -1,5 +1 @@
1
- import type { AgentInfo } from './types';
2
1
  export declare function agentCommand(command: string): string;
3
- export declare function ensureAgent(host: string, { version, prefix, signal }: AgentInfo & {
4
- signal?: AbortSignal;
5
- }): Promise<void>;
package/dist/channel.d.ts CHANGED
@@ -53,5 +53,6 @@ export interface UiContext {
53
53
  message: string;
54
54
  };
55
55
  tabs(options: TabOptions): void;
56
+ open(url: string): Promise<void>;
56
57
  };
57
58
  }
@@ -4,6 +4,7 @@ export declare class MachineConnection {
4
4
  private options;
5
5
  private listeners;
6
6
  private terminals;
7
+ port?: number;
7
8
  private instance?;
8
9
  readonly ready: Promise<void>;
9
10
  private resolveReady;
package/dist/index.cjs CHANGED
@@ -30,14 +30,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ agentCommand: () => agentCommand,
33
34
  openMachine: () => openMachine
34
35
  });
35
36
  module.exports = __toCommonJS(index_exports);
36
37
 
37
38
  // connection.ts
38
- var import_node_child_process2 = require("node:child_process");
39
+ var import_node_child_process = require("node:child_process");
39
40
  var import_node_net = require("node:net");
40
- var import_node_util2 = require("node:util");
41
+ var import_node_util = require("node:util");
41
42
  var import_ws = __toESM(require("ws"));
42
43
 
43
44
  // pty.ts
@@ -111,44 +112,14 @@ var Pty = class {
111
112
  };
112
113
 
113
114
  // agent.ts
114
- var import_node_child_process = require("node:child_process");
115
- var import_node_util = require("node:util");
116
- var exec = (0, import_node_util.promisify)(import_node_child_process.execFile);
117
115
  function agentCommand(command) {
118
116
  const home = process.env.WANGCAI_HOME;
119
117
  const exportHome = home ? `export WANGCAI_HOME='${home.replace(/'/g, String.raw`'\''`)}'; ` : "";
120
118
  return `${exportHome}export PATH="$HOME/.local/bin:$PATH"; ${command}`;
121
119
  }
122
- async function ensureAgent(host, { version, prefix, signal }) {
123
- const targets = {
124
- "Darwin x86_64": "x86_64-apple-darwin",
125
- "Darwin arm64": "aarch64-apple-darwin",
126
- "Linux x86_64": "x86_64-unknown-linux-musl"
127
- };
128
- const remote = (command) => ["-T", "-o", "BatchMode=yes", "-o", "ConnectTimeout=8", host, command];
129
- const probe = await exec("ssh", remote(agentCommand("uname -s -m; wangcai --version 2>/dev/null; true")), { timeout: 3e4, signal }).catch(() => void 0);
130
- const [platform, installed] = (probe?.stdout ?? "").split("\n").map((line) => line.trim());
131
- if (!platform) return;
132
- const target = targets[platform];
133
- if (!target) throw new Error(`${platform} \u4E0A\u6682\u4E0D\u652F\u6301\u81EA\u52A8\u5B89\u88C5 agent`);
134
- if (installed === `wangcai ${version}`) return;
135
- const response = await fetch(`${prefix}/v${version}/wangcai-${target}`, { signal });
136
- if (!response.ok) throw new Error(`\u4E0B\u8F7D agent \u5931\u8D25\uFF1A${response.status} ${response.statusText}`);
137
- const binary = Buffer.from(await response.arrayBuffer());
138
- await new Promise((resolve, reject) => {
139
- const child = (0, import_node_child_process.spawn)("ssh", remote("mkdir -p ~/.local/bin && cat > ~/.local/bin/.wangcai.tmp && chmod 755 ~/.local/bin/.wangcai.tmp && mv ~/.local/bin/.wangcai.tmp ~/.local/bin/wangcai"), { stdio: ["pipe", "ignore", "pipe"] });
140
- let stderr = "";
141
- child.stderr.on("data", (chunk) => {
142
- stderr += chunk;
143
- });
144
- child.on("error", reject);
145
- child.on("close", (code) => code === 0 ? resolve() : reject(new Error(stderr.trim() || `\u5199\u5165 agent \u5931\u8D25\uFF08ssh \u9000\u51FA\u7801 ${code}\uFF09`)));
146
- child.stdin.end(binary);
147
- });
148
- }
149
120
 
150
121
  // connection.ts
151
- var exec2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
122
+ var exec = (0, import_node_util.promisify)(import_node_child_process.execFile);
152
123
  var MachineConnection = class {
153
124
  constructor(options) {
154
125
  this.options = options;
@@ -161,6 +132,8 @@ var MachineConnection = class {
161
132
  }
162
133
  listeners = /* @__PURE__ */ new Set();
163
134
  terminals = /* @__PURE__ */ new Map();
135
+ // Where the daemon listens: the window reaches it with this.
136
+ port;
164
137
  instance;
165
138
  ready;
166
139
  resolveReady;
@@ -283,12 +256,12 @@ var MachineConnection = class {
283
256
  let info;
284
257
  let port;
285
258
  if (this.options.type === "local") {
286
- const { stdout } = await exec2(this.options.binary ?? "wangcai", ["server", "start", "--json"], { timeout: 15e3 });
259
+ const { stdout } = await exec(this.options.binary ?? "wangcai", ["server", "start", "--json"], { timeout: 15e3 });
287
260
  info = JSON.parse(stdout);
288
261
  port = info.port;
289
262
  } else {
290
- if (this.options.agent) await ensureAgent(this.options.host, { ...this.options.agent, signal: this.options.signal });
291
- const { stdout } = await exec2("ssh", [
263
+ if (this.options.agent) await this.options.agent(this.options.host, this.options.signal);
264
+ const { stdout } = await exec("ssh", [
292
265
  "-T",
293
266
  "-o",
294
267
  "BatchMode=yes",
@@ -302,6 +275,7 @@ var MachineConnection = class {
302
275
  if (!current()) return;
303
276
  port = await this.forward(info.port, current);
304
277
  }
278
+ this.port = port;
305
279
  if (!current()) return;
306
280
  const socket = new import_ws.default(`ws://127.0.0.1:${port}`, { handshakeTimeout: 5e3, maxPayload: 64 * 1024 * 1024 });
307
281
  this.ws = socket;
@@ -398,7 +372,7 @@ var MachineConnection = class {
398
372
  const port = reservation.address().port;
399
373
  await new Promise((resolve) => reservation.close(() => resolve()));
400
374
  if (!current()) throw new Error("Connection cancelled");
401
- const tunnel = (0, import_node_child_process2.spawn)("ssh", [
375
+ const tunnel = (0, import_node_child_process.spawn)("ssh", [
402
376
  "-N",
403
377
  "-T",
404
378
  "-o",
@@ -504,5 +478,6 @@ async function openMachine(options) {
504
478
  }
505
479
  // Annotate the CommonJS export names for ESM import in node:
506
480
  0 && (module.exports = {
481
+ agentCommand,
507
482
  openMachine
508
483
  });
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { MachineConnection } from './connection';
2
2
  import type { ConnectionOptions } from './types';
3
- export type { AgentInfo, ConnectionOptions, FileClick, Machine, MachineState, Session, Size, Output, Snapshot, TerminalEvent, DirectoryEntry, ExecOptions, ExecResult, Profile, Theme, WorkspaceActive, WorkspaceRow, WorkspaceMenuItem } from './types';
3
+ export { agentCommand } from './agent';
4
+ export type { ConnectionOptions, FileClick, Machine, MachineState, Session, Size, Output, Snapshot, TerminalEvent, DirectoryEntry, ExecOptions, ExecResult, InstallAgent, Profile, Theme, WorkspaceActive, WorkspaceRow, WorkspaceMenuItem } from './types';
4
5
  export type { MachineConnection } from './connection';
5
6
  export type { Pty } from './pty';
6
7
  /** Opens one connection to a machine and waits for it to be ready. */
package/dist/types.d.ts CHANGED
@@ -1,7 +1,5 @@
1
- export interface AgentInfo {
2
- version: string;
3
- prefix: string;
4
- }
1
+ /** What puts the agent on an ssh machine, which the SDK calls before it connects to it. */
2
+ export type InstallAgent = (host: string, signal?: AbortSignal) => Promise<void>;
5
3
  /**
6
4
  * The workspace protocol. A plugin that init.ts lists under `workspaces` is a workspace provider, and
7
5
  * the app drives it through these `ui` methods:
@@ -58,7 +56,7 @@ export type ConnectionOptions = {
58
56
  } | {
59
57
  type: 'ssh';
60
58
  host: string;
61
- agent?: AgentInfo;
59
+ agent?: InstallAgent;
62
60
  signal?: AbortSignal;
63
61
  };
64
62
  export interface Size {
@@ -132,7 +130,4 @@ export interface Theme {
132
130
  }
133
131
  export interface Profile {
134
132
  theme: Theme;
135
- agent: {
136
- downloadPrefix: string;
137
- };
138
133
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lengmoxxl/sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Client SDK for WangCai: connect to a local or remote machine and drive its pty, files and git",
5
5
  "license": "MIT",
6
6
  "repository": {