ainecto 0.12.1 → 0.13.0

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/bin/mcp.js CHANGED
@@ -58,7 +58,28 @@ function assertEnv(value) {
58
58
 
59
59
  // src/core/auth/tokenStore.ts
60
60
  import { createHash } from "crypto";
61
- import { mkdir, readFile, rename, rm, stat, writeFile, chmod } from "fs/promises";
61
+ import { mkdir as mkdir2, readFile, rename, rm, stat as stat2, writeFile, chmod as chmod2 } from "fs/promises";
62
+
63
+ // src/core/fs/privateFiles.ts
64
+ import { chmod, lstat, mkdir, stat } from "fs/promises";
65
+ function isNodeError(error, code) {
66
+ return error instanceof Error && "code" in error && error.code === code;
67
+ }
68
+ async function chmodIfPermissive(path, mode) {
69
+ try {
70
+ const result = await stat(path);
71
+ if ((result.mode & 63) !== 0) {
72
+ await chmod(path, mode);
73
+ }
74
+ } catch (error) {
75
+ if (isNodeError(error, "ENOENT")) {
76
+ return;
77
+ }
78
+ throw error;
79
+ }
80
+ }
81
+
82
+ // src/core/auth/tokenStore.ts
62
83
  import { homedir } from "os";
63
84
  import { dirname, join } from "path";
64
85
  var FileTokenStore = class {
@@ -97,14 +118,14 @@ var FileTokenStore = class {
97
118
  }
98
119
  }
99
120
  async writeFile(file) {
100
- await mkdir(dirname(this.filePath), { recursive: true, mode: 448 });
101
- await chmod(dirname(this.filePath), 448);
121
+ await mkdir2(dirname(this.filePath), { recursive: true, mode: 448 });
122
+ await chmod2(dirname(this.filePath), 448);
102
123
  const tmpPath = `${this.filePath}.${process.pid}.${Date.now()}.tmp`;
103
124
  await writeFile(tmpPath, `${JSON.stringify(file, null, 2)}
104
125
  `, { mode: 384 });
105
- await chmod(tmpPath, 384);
126
+ await chmod2(tmpPath, 384);
106
127
  await rename(tmpPath, this.filePath);
107
- await chmod(this.filePath, 384);
128
+ await chmod2(this.filePath, 384);
108
129
  }
109
130
  async hardenExistingPermissions() {
110
131
  const dirPath = dirname(this.filePath);
@@ -115,22 +136,6 @@ var FileTokenStore = class {
115
136
  function tokenKey(endpoint) {
116
137
  return createHash("sha256").update(endpoint).digest("hex");
117
138
  }
118
- function isNodeError(error, code) {
119
- return error instanceof Error && "code" in error && error.code === code;
120
- }
121
- async function chmodIfPermissive(path, mode) {
122
- try {
123
- const result = await stat(path);
124
- if ((result.mode & 63) !== 0) {
125
- await chmod(path, mode);
126
- }
127
- } catch (error) {
128
- if (isNodeError(error, "ENOENT")) {
129
- return;
130
- }
131
- throw error;
132
- }
133
- }
134
139
 
135
140
  // src/core/auth/oauth.ts
136
141
  import { createHash as createHash2, randomBytes } from "crypto";
@@ -214,7 +219,7 @@ function legacyRoleInput(flag, envVars = process.env) {
214
219
  }
215
220
 
216
221
  // src/core/version.ts
217
- var CLI_VERSION = true ? "0.12.1" : UNBUNDLED_VERSION;
222
+ var CLI_VERSION = true ? "0.13.0" : UNBUNDLED_VERSION;
218
223
  var PACKAGE_NAME = "@ainecto/mcp";
219
224
  var CLI_USER_AGENT = `${PACKAGE_NAME} ${CLI_VERSION}`;
220
225
 
@@ -288,7 +293,7 @@ var McpRpcClient = class {
288
293
  const details = rateLimitDetails(void 0, response.error.data);
289
294
  throw new RateLimitedError(rateLimitMessage(`MCP ${method}`, details), details);
290
295
  }
291
- throw new McpRpcError(response.error.message, "MCP_ERROR", response.error);
296
+ throw new McpRpcError(describeRpcError(response.error), "MCP_ERROR", response.error);
292
297
  }
293
298
  return response.result;
294
299
  }
@@ -309,6 +314,10 @@ var McpRpcClient = class {
309
314
  return rateLimitedResponse(text, response.headers.get("retry-after"));
310
315
  }
311
316
  if (!response.ok) {
317
+ const envelope = rpcErrorEnvelope(text);
318
+ if (envelope) {
319
+ return envelope;
320
+ }
312
321
  const serverError = parseServerError(text);
313
322
  throw new McpRpcError(
314
323
  `MCP HTTP request failed with HTTP ${response.status}${serverError ? ` \u2014 ${describeServerError(serverError)}` : "."}`,
@@ -352,23 +361,39 @@ var McpRpcClient = class {
352
361
  }
353
362
  };
354
363
  function rateLimitedResponse(text, retryAfter) {
355
- let parsed;
356
- try {
357
- parsed = JSON.parse(text);
358
- } catch {
359
- parsed = void 0;
360
- }
361
- if (isJsonRpcResponse(parsed) && "error" in parsed) {
362
- const data = isRecord3(parsed.error.data) ? parsed.error.data : {};
364
+ const envelope = rpcErrorEnvelope(text);
365
+ if (envelope) {
366
+ const data = isRecord3(envelope.error.data) ? envelope.error.data : {};
363
367
  const seconds = parseRetryAfter(retryAfter);
364
368
  if (data.retryAfterSeconds === void 0 && seconds !== void 0) {
365
- parsed.error.data = { ...data, retryAfterSeconds: seconds };
369
+ envelope.error.data = { ...data, retryAfterSeconds: seconds };
366
370
  }
367
- return parsed;
371
+ return envelope;
368
372
  }
369
- const details = rateLimitDetails(retryAfter, parsed);
373
+ const details = rateLimitDetails(retryAfter, parseJsonOrUndefined(text));
370
374
  throw new RateLimitedError(rateLimitMessage("MCP HTTP request", details), details);
371
375
  }
376
+ function rpcErrorEnvelope(text) {
377
+ const parsed = parseJsonOrUndefined(text);
378
+ return isJsonRpcResponse(parsed) && "error" in parsed && isRecord3(parsed.error) ? parsed : void 0;
379
+ }
380
+ function parseJsonOrUndefined(text) {
381
+ try {
382
+ return JSON.parse(text);
383
+ } catch {
384
+ return void 0;
385
+ }
386
+ }
387
+ function describeRpcError(error) {
388
+ const data = isRecord3(error.data) ? error.data : {};
389
+ const messages = isRecord3(data.messages) ? data.messages : {};
390
+ const sentence = [error.message, data.message, messages.en, messages.ko].find((value) => typeof value === "string" && value.trim() !== "");
391
+ const code = typeof data.code === "string" && data.code.trim() ? data.code.trim() : void 0;
392
+ if (!code) {
393
+ return sentence ?? `JSON-RPC error ${error.code}`;
394
+ }
395
+ return describeServerError({ error: code, description: sentence });
396
+ }
372
397
  function agentHeaderValue(clientName) {
373
398
  return printableHeaderValue(clientName);
374
399
  }
@@ -898,12 +923,12 @@ signed-in user's AiNecto permissions decide what they may change, and the server
898
923
  ${MARKER_END}`;
899
924
 
900
925
  // src/core/harness/repositoryFiles.ts
901
- import { lstat, readFile as readFile2, realpath } from "fs/promises";
926
+ import { lstat as lstat2, readFile as readFile2, realpath } from "fs/promises";
902
927
  import { dirname as dirname2, join as join2, resolve, sep } from "path";
903
928
  async function findGitRoot(cwd) {
904
929
  for (let at = resolve(cwd); ; at = dirname2(at)) {
905
930
  try {
906
- await lstat(join2(at, ".git"));
931
+ await lstat2(join2(at, ".git"));
907
932
  return at;
908
933
  } catch {
909
934
  }
@@ -944,7 +969,7 @@ async function assertInsideRepository(root, relativePath) {
944
969
  );
945
970
  }
946
971
  try {
947
- if ((await lstat(absolutePath)).isSymbolicLink()) {
972
+ if ((await lstat2(absolutePath)).isSymbolicLink()) {
948
973
  throw new Error(`${relativePath} is a symbolic link; refusing to write through it.`);
949
974
  }
950
975
  } catch (error) {