terminal-commands 0.1.1 → 0.1.2

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/dist/agent.js CHANGED
@@ -11894,7 +11894,7 @@ function attachSchema(issues, start, inst) {
11894
11894
  (_a3 = issues[i]).schema ?? (_a3.schema = inst);
11895
11895
  }
11896
11896
  }
11897
- function finalizeIssue(iss, ctx, config2) {
11897
+ function finalizeIssue(iss, ctx, config3) {
11898
11898
  var _a3;
11899
11899
  const traits = iss.inst?._zod?.traits;
11900
11900
  if (traits?.has("$ZodType")) {
@@ -11904,7 +11904,7 @@ function finalizeIssue(iss, ctx, config2) {
11904
11904
  iss.schema = iss.inst;
11905
11905
  }
11906
11906
  const schemaError = iss.schema !== iss.inst ? iss.schema?._zod.def?.error : void 0;
11907
- const message = iss.message ? iss.message : unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(schemaError?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config2.customError?.(iss)) ?? unwrapMessage(config2.localeError?.(iss)) ?? "Invalid input";
11907
+ const message = iss.message ? iss.message : unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(schemaError?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config3.customError?.(iss)) ?? unwrapMessage(config3.localeError?.(iss)) ?? "Invalid input";
11908
11908
  const full = {};
11909
11909
  for (const k of Object.keys(iss)) {
11910
11910
  if (k === "inst" || k === "schema" || k === "continue" || k === "input" || k === "__proto__")
@@ -33537,21 +33537,21 @@ var Client = class extends Protocol {
33537
33537
  * Handlers are silently skipped if the server doesn't advertise the corresponding listChanged capability.
33538
33538
  * @internal
33539
33539
  */
33540
- _setupListChangedHandlers(config2) {
33541
- if (config2.tools && this._serverCapabilities?.tools?.listChanged) {
33542
- this._setupListChangedHandler("tools", ToolListChangedNotificationSchema, config2.tools, async () => {
33540
+ _setupListChangedHandlers(config3) {
33541
+ if (config3.tools && this._serverCapabilities?.tools?.listChanged) {
33542
+ this._setupListChangedHandler("tools", ToolListChangedNotificationSchema, config3.tools, async () => {
33543
33543
  const result = await this.listTools();
33544
33544
  return result.tools;
33545
33545
  });
33546
33546
  }
33547
- if (config2.prompts && this._serverCapabilities?.prompts?.listChanged) {
33548
- this._setupListChangedHandler("prompts", PromptListChangedNotificationSchema, config2.prompts, async () => {
33547
+ if (config3.prompts && this._serverCapabilities?.prompts?.listChanged) {
33548
+ this._setupListChangedHandler("prompts", PromptListChangedNotificationSchema, config3.prompts, async () => {
33549
33549
  const result = await this.listPrompts();
33550
33550
  return result.prompts;
33551
33551
  });
33552
33552
  }
33553
- if (config2.resources && this._serverCapabilities?.resources?.listChanged) {
33554
- this._setupListChangedHandler("resources", ResourceListChangedNotificationSchema, config2.resources, async () => {
33553
+ if (config3.resources && this._serverCapabilities?.resources?.listChanged) {
33554
+ this._setupListChangedHandler("resources", ResourceListChangedNotificationSchema, config3.resources, async () => {
33555
33555
  const result = await this.listResources();
33556
33556
  return result.resources;
33557
33557
  });
@@ -34881,12 +34881,12 @@ var CR = 13;
34881
34881
  var SPACE = 32;
34882
34882
  function noop(_arg) {
34883
34883
  }
34884
- function createParser(config2) {
34885
- if (typeof config2 == "function")
34884
+ function createParser(config3) {
34885
+ if (typeof config3 == "function")
34886
34886
  throw new TypeError(
34887
34887
  "`config` must be an object, got a function instead. Did you mean `createParser({onEvent: fn})`?"
34888
34888
  );
34889
- const { onEvent = noop, onError = noop, onRetry = noop, onComment, maxBufferSize } = config2, pendingFragments = [];
34889
+ const { onEvent = noop, onError = noop, onRetry = noop, onComment, maxBufferSize } = config3, pendingFragments = [];
34890
34890
  let pendingFragmentsLength = 0, isFirstChunk = true, id, data = "", dataLines = 0, eventType, terminated = false;
34891
34891
  function feed(chunk) {
34892
34892
  if (terminated)
@@ -35505,18 +35505,18 @@ async function authorizeToolCall(tool, args, allowDestructive, approve) {
35505
35505
  }
35506
35506
  }
35507
35507
  async function connectOnce(options) {
35508
- const { config: config2, signal } = options;
35508
+ const { config: config3, signal } = options;
35509
35509
  const client = new Client({
35510
35510
  name: "terminal-commands-cli",
35511
35511
  version: "0.1.0"
35512
35512
  });
35513
35513
  await client.connect(
35514
35514
  new StreamableHTTPClientTransport(
35515
- new URL(config2.MACHINE_TERMINAL_LOCAL_MCP_URL)
35515
+ new URL(config3.MACHINE_TERMINAL_LOCAL_MCP_URL)
35516
35516
  )
35517
35517
  );
35518
- const token = options.getToken ? await options.getToken() : config2.MACHINE_TERMINAL_DEVICE_TOKEN;
35519
- const socket = new wrapper_default(config2.MACHINE_TERMINAL_GATEWAY_URL, {
35518
+ const token = options.getToken ? await options.getToken() : config3.MACHINE_TERMINAL_DEVICE_TOKEN;
35519
+ const socket = new wrapper_default(config3.MACHINE_TERMINAL_GATEWAY_URL, {
35520
35520
  headers: { Authorization: `Bearer ${token}` }
35521
35521
  });
35522
35522
  const stop2 = () => socket.close(1e3, "Client stopping.");
@@ -35525,8 +35525,8 @@ async function connectOnce(options) {
35525
35525
  socket.send(
35526
35526
  JSON.stringify({
35527
35527
  type: "hello",
35528
- deviceId: config2.MACHINE_TERMINAL_DEVICE_ID,
35529
- name: config2.MACHINE_TERMINAL_DEVICE_NAME,
35528
+ deviceId: config3.MACHINE_TERMINAL_DEVICE_ID,
35529
+ name: config3.MACHINE_TERMINAL_DEVICE_NAME,
35530
35530
  platform: `${os.platform()}-${os.arch()}`
35531
35531
  })
35532
35532
  );
@@ -35618,11 +35618,12 @@ var schema = external_exports.object({
35618
35618
  MACHINE_TERMINAL_DEVICE_ID: external_exports.string().min(1).max(128),
35619
35619
  MACHINE_TERMINAL_DEVICE_NAME: external_exports.string().min(1).max(128).default(os2.hostname()),
35620
35620
  MACHINE_TERMINAL_LOCAL_MCP_URL: external_exports.string().url().default("http://127.0.0.1:3333/mcp"),
35621
- MACHINE_TERMINAL_AGENT_ALLOW_DESTRUCTIVE: external_exports.enum(["0", "1"]).default("0")
35621
+ MACHINE_TERMINAL_AGENT_ALLOW_DESTRUCTIVE: external_exports.enum(["0", "1"]).default("0"),
35622
+ MACHINE_TERMINAL_AUTO_APPROVE: external_exports.enum(["0", "1"]).default("0")
35622
35623
  });
35623
35624
  function loadAgentConfig(environment = process.env) {
35624
- const config2 = schema.parse(environment);
35625
- const gateway = new URL(config2.MACHINE_TERMINAL_GATEWAY_URL);
35625
+ const config3 = schema.parse(environment);
35626
+ const gateway = new URL(config3.MACHINE_TERMINAL_GATEWAY_URL);
35626
35627
  if (!(/* @__PURE__ */ new Set(["wss:", "ws:"])).has(gateway.protocol)) {
35627
35628
  throw new Error("MACHINE_TERMINAL_GATEWAY_URL must use wss:// or ws://.");
35628
35629
  }
@@ -35631,7 +35632,84 @@ function loadAgentConfig(environment = process.env) {
35631
35632
  "Unencrypted ws:// is allowed only for loopback development."
35632
35633
  );
35633
35634
  }
35634
- return config2;
35635
+ return {
35636
+ ...config3,
35637
+ MACHINE_TERMINAL_AGENT_ALLOW_DESTRUCTIVE: config3.MACHINE_TERMINAL_AUTO_APPROVE === "1" ? "1" : config3.MACHINE_TERMINAL_AGENT_ALLOW_DESTRUCTIVE
35638
+ };
35639
+ }
35640
+
35641
+ // src/approval.ts
35642
+ import { createInterface } from "node:readline/promises";
35643
+
35644
+ // src/cli-format.ts
35645
+ var isColorEnabled = Boolean(process.stdout.isTTY) && process.env.NO_COLOR === void 0 && process.env.TERM !== "dumb";
35646
+ var CODES = {
35647
+ reset: "\x1B[0m",
35648
+ bold: "\x1B[1m",
35649
+ dim: "\x1B[2m",
35650
+ red: "\x1B[31m",
35651
+ green: "\x1B[32m",
35652
+ yellow: "\x1B[33m",
35653
+ blue: "\x1B[34m",
35654
+ cyan: "\x1B[36m",
35655
+ gray: "\x1B[90m"
35656
+ };
35657
+ function paint(code, text) {
35658
+ if (!isColorEnabled) return text;
35659
+ return `${CODES[code]}${text}${CODES.reset}`;
35660
+ }
35661
+ var bold = (text) => paint("bold", text);
35662
+ var dim = (text) => paint("dim", text);
35663
+ var warn = (text) => paint("yellow", text);
35664
+
35665
+ // src/approval.ts
35666
+ function approvalSummary(tool, args) {
35667
+ if (tool === "write_text_file") {
35668
+ const bytes = Buffer.byteLength(String(args.contents ?? ""));
35669
+ return `Write ${bytes} bytes to ${String(args.path ?? "an unknown path")}${args.overwrite ? " (overwrite)" : ""}`;
35670
+ }
35671
+ if (tool === "run_program") {
35672
+ const command = [
35673
+ String(args.program ?? ""),
35674
+ ...Array.isArray(args.args) ? args.args.map(String) : []
35675
+ ];
35676
+ return `Run: ${command.join(" ")}`;
35677
+ }
35678
+ return `Run destructive tool: ${tool}`;
35679
+ }
35680
+ function createAutoApprover() {
35681
+ return (tool, args) => {
35682
+ console.log(
35683
+ `
35684
+ ${warn("Approval requested:")} ${approvalSummary(tool, args)} ${dim("(auto-approved)")}`
35685
+ );
35686
+ return Promise.resolve(true);
35687
+ };
35688
+ }
35689
+ function createTerminalApprover() {
35690
+ let queue = Promise.resolve(false);
35691
+ return (tool, args) => {
35692
+ queue = queue.catch(() => false).then(async () => {
35693
+ if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
35694
+ const prompt = createInterface({
35695
+ input: process.stdin,
35696
+ output: process.stdout
35697
+ });
35698
+ try {
35699
+ console.log(
35700
+ `
35701
+ ${warn("Approval requested:")} ${approvalSummary(tool, args)}`
35702
+ );
35703
+ const answer = await prompt.question(
35704
+ `${bold("Approve this action?")} [y/N] `
35705
+ );
35706
+ return (/* @__PURE__ */ new Set(["y", "yes"])).has(answer.trim().toLowerCase());
35707
+ } finally {
35708
+ prompt.close();
35709
+ }
35710
+ });
35711
+ return queue;
35712
+ };
35635
35713
  }
35636
35714
 
35637
35715
  // src/agent.ts
@@ -35639,8 +35717,10 @@ var controller = new AbortController();
35639
35717
  var stop = () => controller.abort();
35640
35718
  process.on("SIGINT", stop);
35641
35719
  process.on("SIGTERM", stop);
35720
+ var config2 = loadAgentConfig();
35642
35721
  void runAgent({
35643
- config: loadAgentConfig(),
35722
+ config: config2,
35723
+ approve: config2.MACHINE_TERMINAL_AUTO_APPROVE === "1" ? createAutoApprover() : createTerminalApprover(),
35644
35724
  signal: controller.signal,
35645
35725
  log: (message) => console.error(`Terminal Commands: ${message}`)
35646
35726
  }).catch((error62) => {
package/dist/cli.js CHANGED
@@ -10984,7 +10984,6 @@ import { spawn } from "node:child_process";
10984
10984
  import { fileURLToPath } from "node:url";
10985
10985
  import os5 from "node:os";
10986
10986
  import path3 from "node:path";
10987
- import { createInterface } from "node:readline/promises";
10988
10987
 
10989
10988
  // src/agent-core.ts
10990
10989
  import os from "node:os";
@@ -35626,7 +35625,8 @@ var schema = external_exports.object({
35626
35625
  MACHINE_TERMINAL_DEVICE_ID: external_exports.string().min(1).max(128),
35627
35626
  MACHINE_TERMINAL_DEVICE_NAME: external_exports.string().min(1).max(128).default(os2.hostname()),
35628
35627
  MACHINE_TERMINAL_LOCAL_MCP_URL: external_exports.string().url().default("http://127.0.0.1:3333/mcp"),
35629
- MACHINE_TERMINAL_AGENT_ALLOW_DESTRUCTIVE: external_exports.enum(["0", "1"]).default("0")
35628
+ MACHINE_TERMINAL_AGENT_ALLOW_DESTRUCTIVE: external_exports.enum(["0", "1"]).default("0"),
35629
+ MACHINE_TERMINAL_AUTO_APPROVE: external_exports.enum(["0", "1"]).default("0")
35630
35630
  });
35631
35631
  function loadAgentConfig(environment = process.env) {
35632
35632
  const config2 = schema.parse(environment);
@@ -35639,7 +35639,100 @@ function loadAgentConfig(environment = process.env) {
35639
35639
  "Unencrypted ws:// is allowed only for loopback development."
35640
35640
  );
35641
35641
  }
35642
- return config2;
35642
+ return {
35643
+ ...config2,
35644
+ MACHINE_TERMINAL_AGENT_ALLOW_DESTRUCTIVE: config2.MACHINE_TERMINAL_AUTO_APPROVE === "1" ? "1" : config2.MACHINE_TERMINAL_AGENT_ALLOW_DESTRUCTIVE
35645
+ };
35646
+ }
35647
+
35648
+ // src/approval.ts
35649
+ import { createInterface } from "node:readline/promises";
35650
+
35651
+ // src/cli-format.ts
35652
+ var isColorEnabled = Boolean(process.stdout.isTTY) && process.env.NO_COLOR === void 0 && process.env.TERM !== "dumb";
35653
+ var CODES = {
35654
+ reset: "\x1B[0m",
35655
+ bold: "\x1B[1m",
35656
+ dim: "\x1B[2m",
35657
+ red: "\x1B[31m",
35658
+ green: "\x1B[32m",
35659
+ yellow: "\x1B[33m",
35660
+ blue: "\x1B[34m",
35661
+ cyan: "\x1B[36m",
35662
+ gray: "\x1B[90m"
35663
+ };
35664
+ function paint(code, text) {
35665
+ if (!isColorEnabled) return text;
35666
+ return `${CODES[code]}${text}${CODES.reset}`;
35667
+ }
35668
+ var bold = (text) => paint("bold", text);
35669
+ var dim = (text) => paint("dim", text);
35670
+ var ok = (text) => paint("green", text);
35671
+ var warn = (text) => paint("yellow", text);
35672
+ var danger = (text) => paint("red", text);
35673
+ var info = (text) => paint("cyan", text);
35674
+ var muted = (text) => paint("gray", text);
35675
+ function heading(text) {
35676
+ const rule = "\u2500".repeat(Math.max(text.length, 3));
35677
+ return `${bold(info(text))}
35678
+ ${muted(rule)}`;
35679
+ }
35680
+ function keyValueBlock(rows) {
35681
+ const width = rows.reduce(
35682
+ (widest, [label]) => Math.max(widest, label.length),
35683
+ 0
35684
+ );
35685
+ return rows.map(([label, value]) => ` ${dim(label.padEnd(width))} ${value}`).join("\n");
35686
+ }
35687
+
35688
+ // src/approval.ts
35689
+ function approvalSummary(tool, args) {
35690
+ if (tool === "write_text_file") {
35691
+ const bytes = Buffer.byteLength(String(args.contents ?? ""));
35692
+ return `Write ${bytes} bytes to ${String(args.path ?? "an unknown path")}${args.overwrite ? " (overwrite)" : ""}`;
35693
+ }
35694
+ if (tool === "run_program") {
35695
+ const command = [
35696
+ String(args.program ?? ""),
35697
+ ...Array.isArray(args.args) ? args.args.map(String) : []
35698
+ ];
35699
+ return `Run: ${command.join(" ")}`;
35700
+ }
35701
+ return `Run destructive tool: ${tool}`;
35702
+ }
35703
+ function createAutoApprover() {
35704
+ return (tool, args) => {
35705
+ console.log(
35706
+ `
35707
+ ${warn("Approval requested:")} ${approvalSummary(tool, args)} ${dim("(auto-approved)")}`
35708
+ );
35709
+ return Promise.resolve(true);
35710
+ };
35711
+ }
35712
+ function createTerminalApprover() {
35713
+ let queue = Promise.resolve(false);
35714
+ return (tool, args) => {
35715
+ queue = queue.catch(() => false).then(async () => {
35716
+ if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
35717
+ const prompt = createInterface({
35718
+ input: process.stdin,
35719
+ output: process.stdout
35720
+ });
35721
+ try {
35722
+ console.log(
35723
+ `
35724
+ ${warn("Approval requested:")} ${approvalSummary(tool, args)}`
35725
+ );
35726
+ const answer = await prompt.question(
35727
+ `${bold("Approve this action?")} [y/N] `
35728
+ );
35729
+ return (/* @__PURE__ */ new Set(["y", "yes"])).has(answer.trim().toLowerCase());
35730
+ } finally {
35731
+ prompt.close();
35732
+ }
35733
+ });
35734
+ return queue;
35735
+ };
35643
35736
  }
35644
35737
 
35645
35738
  // src/cli-options.ts
@@ -36021,43 +36114,6 @@ function renderHelp(command = "help") {
36021
36114
  return lines.join("\n");
36022
36115
  }
36023
36116
 
36024
- // src/cli-format.ts
36025
- var isColorEnabled = Boolean(process.stdout.isTTY) && process.env.NO_COLOR === void 0 && process.env.TERM !== "dumb";
36026
- var CODES = {
36027
- reset: "\x1B[0m",
36028
- bold: "\x1B[1m",
36029
- dim: "\x1B[2m",
36030
- red: "\x1B[31m",
36031
- green: "\x1B[32m",
36032
- yellow: "\x1B[33m",
36033
- blue: "\x1B[34m",
36034
- cyan: "\x1B[36m",
36035
- gray: "\x1B[90m"
36036
- };
36037
- function paint(code, text) {
36038
- if (!isColorEnabled) return text;
36039
- return `${CODES[code]}${text}${CODES.reset}`;
36040
- }
36041
- var bold = (text) => paint("bold", text);
36042
- var dim = (text) => paint("dim", text);
36043
- var ok = (text) => paint("green", text);
36044
- var warn = (text) => paint("yellow", text);
36045
- var danger = (text) => paint("red", text);
36046
- var info = (text) => paint("cyan", text);
36047
- var muted = (text) => paint("gray", text);
36048
- function heading(text) {
36049
- const rule = "\u2500".repeat(Math.max(text.length, 3));
36050
- return `${bold(info(text))}
36051
- ${muted(rule)}`;
36052
- }
36053
- function keyValueBlock(rows) {
36054
- const width = rows.reduce(
36055
- (widest, [label]) => Math.max(widest, label.length),
36056
- 0
36057
- );
36058
- return rows.map(([label, value]) => ` ${dim(label.padEnd(width))} ${value}`).join("\n");
36059
- }
36060
-
36061
36117
  // src/credential-store.ts
36062
36118
  import { promises as fs2 } from "node:fs";
36063
36119
  import { randomUUID } from "node:crypto";
@@ -36347,54 +36403,6 @@ function describeSettings(settings, deviceId) {
36347
36403
  ])
36348
36404
  ].join("\n");
36349
36405
  }
36350
- function approvalSummary(tool, args) {
36351
- if (tool === "write_text_file") {
36352
- const bytes = Buffer.byteLength(String(args.contents ?? ""));
36353
- return `Write ${bytes} bytes to ${String(args.path ?? "an unknown path")}${args.overwrite ? " (overwrite)" : ""}`;
36354
- }
36355
- if (tool === "run_program") {
36356
- const command = [
36357
- String(args.program ?? ""),
36358
- ...Array.isArray(args.args) ? args.args.map(String) : []
36359
- ];
36360
- return `Run: ${command.join(" ")}`;
36361
- }
36362
- return `Run destructive tool: ${tool}`;
36363
- }
36364
- function createAutoApprover() {
36365
- return (tool, args) => {
36366
- console.log(
36367
- `
36368
- ${warn("Approval requested:")} ${approvalSummary(tool, args)} ${dim("(auto-approved)")}`
36369
- );
36370
- return Promise.resolve(true);
36371
- };
36372
- }
36373
- function createTerminalApprover() {
36374
- let queue = Promise.resolve(false);
36375
- return (tool, args) => {
36376
- queue = queue.catch(() => false).then(async () => {
36377
- if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
36378
- const prompt = createInterface({
36379
- input: process.stdin,
36380
- output: process.stdout
36381
- });
36382
- try {
36383
- console.log(
36384
- `
36385
- ${warn("Approval requested:")} ${approvalSummary(tool, args)}`
36386
- );
36387
- const answer = await prompt.question(
36388
- `${bold("Approve this action?")} [y/N] `
36389
- );
36390
- return (/* @__PURE__ */ new Set(["y", "yes"])).has(answer.trim().toLowerCase());
36391
- } finally {
36392
- prompt.close();
36393
- }
36394
- });
36395
- return queue;
36396
- };
36397
- }
36398
36406
  async function login(environment) {
36399
36407
  const auth2 = resolveAuth(environment);
36400
36408
  const code = await requestDeviceCode(auth2);
package/dist/index.js CHANGED
@@ -18390,11 +18390,11 @@ var require_parse = __commonJS({
18390
18390
  segments[segments.length] = parent;
18391
18391
  }
18392
18392
  var n = key.length;
18393
- var open2 = first;
18393
+ var open3 = first;
18394
18394
  var collected = 0;
18395
- while (open2 >= 0 && collected < options.depth) {
18395
+ while (open3 >= 0 && collected < options.depth) {
18396
18396
  var level = 1;
18397
- var i = open2 + 1;
18397
+ var i = open3 + 1;
18398
18398
  var close = -1;
18399
18399
  while (i < n && close < 0) {
18400
18400
  var cu = key.charCodeAt(i);
@@ -18409,23 +18409,23 @@ var require_parse = __commonJS({
18409
18409
  i += 1;
18410
18410
  }
18411
18411
  if (close < 0) {
18412
- segments[segments.length] = "[" + key.slice(open2) + "]";
18412
+ segments[segments.length] = "[" + key.slice(open3) + "]";
18413
18413
  return segments;
18414
18414
  }
18415
- var seg = key.slice(open2, close + 1);
18415
+ var seg = key.slice(open3, close + 1);
18416
18416
  var content = seg.slice(1, -1);
18417
18417
  if (!options.plainObjects && has.call(Object.prototype, content) && !options.allowPrototypes) {
18418
18418
  return;
18419
18419
  }
18420
18420
  segments[segments.length] = seg;
18421
18421
  collected += 1;
18422
- open2 = key.indexOf("[", close + 1);
18422
+ open3 = key.indexOf("[", close + 1);
18423
18423
  }
18424
- if (open2 >= 0) {
18424
+ if (open3 >= 0) {
18425
18425
  if (options.strictDepth === true) {
18426
18426
  throw new RangeError("Input depth exceeded depth option of " + options.depth + " and strictDepth is true");
18427
18427
  }
18428
- segments[segments.length] = "[" + key.slice(open2) + "]";
18428
+ segments[segments.length] = "[" + key.slice(open3) + "]";
18429
18429
  }
18430
18430
  return segments;
18431
18431
  };
@@ -54524,7 +54524,7 @@ var StreamableHTTPServerTransport = class {
54524
54524
  };
54525
54525
 
54526
54526
  // src/server.ts
54527
- import { readFile, readdir, writeFile } from "node:fs/promises";
54527
+ import { readdir, writeFile } from "node:fs/promises";
54528
54528
 
54529
54529
  // node_modules/zod/v3/helpers/util.js
54530
54530
  var util;
@@ -62620,6 +62620,27 @@ async function runProgram(options) {
62620
62620
  }
62621
62621
  }
62622
62622
 
62623
+ // src/file-reader.ts
62624
+ import { open as open2 } from "node:fs/promises";
62625
+ async function readBoundedTextFile(filename, maxCharacters) {
62626
+ const handle = await open2(filename, "r");
62627
+ try {
62628
+ const stats = await handle.stat();
62629
+ const buffer = Buffer.allocUnsafe(maxCharacters * 4 + 4);
62630
+ const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
62631
+ const hasUnreadBytes = bytesRead < stats.size;
62632
+ const decoded = new TextDecoder().decode(buffer.subarray(0, bytesRead), {
62633
+ stream: hasUnreadBytes
62634
+ });
62635
+ return {
62636
+ contents: decoded.slice(0, maxCharacters),
62637
+ truncated: hasUnreadBytes || decoded.length > maxCharacters
62638
+ };
62639
+ } finally {
62640
+ await handle.close();
62641
+ }
62642
+ }
62643
+
62623
62644
  // src/server.ts
62624
62645
  var roots = configuredRoots();
62625
62646
  function textResult(value) {
@@ -62717,11 +62738,14 @@ function createServer() {
62717
62738
  },
62718
62739
  async ({ path: requestedPath, maxCharacters }) => {
62719
62740
  const filename = await resolveReadablePath(requestedPath, roots);
62720
- const contents = await readFile(filename, "utf8");
62741
+ const { contents, truncated } = await readBoundedTextFile(
62742
+ filename,
62743
+ maxCharacters
62744
+ );
62721
62745
  return textResult({
62722
62746
  path: filename,
62723
- contents: contents.slice(0, maxCharacters),
62724
- truncated: contents.length > maxCharacters
62747
+ contents,
62748
+ truncated
62725
62749
  });
62726
62750
  }
62727
62751
  );
package/dist/stdio.js CHANGED
@@ -28505,7 +28505,7 @@ var StdioServerTransport = class {
28505
28505
  };
28506
28506
 
28507
28507
  // src/server.ts
28508
- import { readFile, readdir, writeFile } from "node:fs/promises";
28508
+ import { readdir, writeFile } from "node:fs/promises";
28509
28509
 
28510
28510
  // node_modules/zod/v3/helpers/util.js
28511
28511
  var util;
@@ -36601,6 +36601,27 @@ async function runProgram(options) {
36601
36601
  }
36602
36602
  }
36603
36603
 
36604
+ // src/file-reader.ts
36605
+ import { open as open2 } from "node:fs/promises";
36606
+ async function readBoundedTextFile(filename, maxCharacters) {
36607
+ const handle = await open2(filename, "r");
36608
+ try {
36609
+ const stats = await handle.stat();
36610
+ const buffer = Buffer.allocUnsafe(maxCharacters * 4 + 4);
36611
+ const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
36612
+ const hasUnreadBytes = bytesRead < stats.size;
36613
+ const decoded = new TextDecoder().decode(buffer.subarray(0, bytesRead), {
36614
+ stream: hasUnreadBytes
36615
+ });
36616
+ return {
36617
+ contents: decoded.slice(0, maxCharacters),
36618
+ truncated: hasUnreadBytes || decoded.length > maxCharacters
36619
+ };
36620
+ } finally {
36621
+ await handle.close();
36622
+ }
36623
+ }
36624
+
36604
36625
  // src/server.ts
36605
36626
  var roots = configuredRoots();
36606
36627
  function textResult(value) {
@@ -36698,11 +36719,14 @@ function createServer() {
36698
36719
  },
36699
36720
  async ({ path: requestedPath, maxCharacters }) => {
36700
36721
  const filename = await resolveReadablePath(requestedPath, roots);
36701
- const contents = await readFile(filename, "utf8");
36722
+ const { contents, truncated } = await readBoundedTextFile(
36723
+ filename,
36724
+ maxCharacters
36725
+ );
36702
36726
  return textResult({
36703
36727
  path: filename,
36704
- contents: contents.slice(0, maxCharacters),
36705
- truncated: contents.length > maxCharacters
36728
+ contents,
36729
+ truncated
36706
36730
  });
36707
36731
  }
36708
36732
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "terminal-commands",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "A cross-platform, approval-gated terminal companion for ChatGPT, Claude, Codex, and any MCP-compatible AI client.",
@@ -10,6 +10,10 @@
10
10
  "bin": {
11
11
  "terminal-commands": "dist/cli.js"
12
12
  },
13
+ "files": [
14
+ "dist",
15
+ "README.md"
16
+ ],
13
17
  "scripts": {
14
18
  "build": "esbuild src/index.ts src/stdio.ts src/agent.ts src/cli.ts --bundle --platform=node --format=esm --target=node20 --outdir=dist --banner:js=\"import { createRequire as __createRequire } from 'module'; const require = __createRequire(import.meta.url);\"",
15
19
  "check": "tsc --noEmit",
@@ -19,7 +23,8 @@
19
23
  "cli": "node dist/cli.js",
20
24
  "cli:dev": "tsx src/cli.ts",
21
25
  "test": "tsx --test test/**/*.test.ts",
22
- "test:smoke": "node test/smoke.mjs"
26
+ "test:smoke": "node test/smoke.mjs",
27
+ "prepack": "npm run build"
23
28
  },
24
29
  "dependencies": {
25
30
  "@modelcontextprotocol/sdk": "1.30.0",
@@ -1,40 +0,0 @@
1
- import os from "node:os";
2
-
3
- import { z } from "zod";
4
-
5
- const schema = z.object({
6
- MACHINE_TERMINAL_GATEWAY_URL: z.string().url(),
7
- MACHINE_TERMINAL_DEVICE_TOKEN: z.string().min(1),
8
- MACHINE_TERMINAL_DEVICE_ID: z.string().min(1).max(128),
9
- MACHINE_TERMINAL_DEVICE_NAME: z
10
- .string()
11
- .min(1)
12
- .max(128)
13
- .default(os.hostname()),
14
- MACHINE_TERMINAL_LOCAL_MCP_URL: z
15
- .string()
16
- .url()
17
- .default("http://127.0.0.1:3333/mcp"),
18
- MACHINE_TERMINAL_AGENT_ALLOW_DESTRUCTIVE: z.enum(["0", "1"]).default("0"),
19
- });
20
-
21
- export type AgentConfig = z.infer<typeof schema>;
22
-
23
- export function loadAgentConfig(
24
- environment: NodeJS.ProcessEnv = process.env,
25
- ): AgentConfig {
26
- const config = schema.parse(environment);
27
- const gateway = new URL(config.MACHINE_TERMINAL_GATEWAY_URL);
28
- if (!new Set(["wss:", "ws:"]).has(gateway.protocol)) {
29
- throw new Error("MACHINE_TERMINAL_GATEWAY_URL must use wss:// or ws://.");
30
- }
31
- if (
32
- gateway.protocol === "ws:" &&
33
- !new Set(["127.0.0.1", "localhost", "::1"]).has(gateway.hostname)
34
- ) {
35
- throw new Error(
36
- "Unencrypted ws:// is allowed only for loopback development.",
37
- );
38
- }
39
- return config;
40
- }