@duckmind/dm-windows-x64 0.63.4 → 0.63.9

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.
Files changed (121) hide show
  1. package/dm.exe +0 -0
  2. package/extensions/.dm-extensions.json +236 -13
  3. package/extensions/dm-context/package.json +1 -1
  4. package/extensions/dm-context/skills/context-management/SKILL.md +173 -223
  5. package/extensions/dm-context/skills/context-management/references/development-and-troubleshooting.md +75 -0
  6. package/extensions/dm-context/skills/context-management/references/interleaved-async-work.md +143 -0
  7. package/extensions/dm-context/skills/context-management/references/planning-and-execution.md +81 -0
  8. package/extensions/dm-context/skills/context-management/references/repeated-items-and-batch-work.md +69 -0
  9. package/extensions/dm-context/skills/context-management/references/retry-branch-and-pivot.md +80 -0
  10. package/extensions/dm-context/skills/context-management/references/search-research-and-reading.md +103 -0
  11. package/extensions/dm-context/skills/context-management/references/task-switching-and-cleanup.md +73 -0
  12. package/extensions/dm-context/src/context.js +3 -2
  13. package/extensions/dm-context/src/index.js +168 -84
  14. package/extensions/dm-mcp-adapter/OAUTH.md +3 -0
  15. package/extensions/dm-mcp-adapter/THIRD_PARTY_NOTICES.md +4 -0
  16. package/extensions/dm-mcp-adapter/abort.js +35 -0
  17. package/extensions/dm-mcp-adapter/agent-dir.js +45 -0
  18. package/extensions/dm-mcp-adapter/agent-plugin-loader.js +349 -0
  19. package/extensions/dm-mcp-adapter/app-bridge.bundle.js +5843 -0
  20. package/extensions/dm-mcp-adapter/cli.js +354 -0
  21. package/extensions/dm-mcp-adapter/commands.js +619 -0
  22. package/extensions/dm-mcp-adapter/config.js +1060 -0
  23. package/extensions/dm-mcp-adapter/consent-manager.js +60 -0
  24. package/extensions/dm-mcp-adapter/direct-tools.js +544 -0
  25. package/extensions/dm-mcp-adapter/dist/agent-dir.js +45 -0
  26. package/extensions/dm-mcp-adapter/dist/agent-plugin-loader.js +349 -0
  27. package/extensions/dm-mcp-adapter/dist/config.js +1060 -0
  28. package/extensions/dm-mcp-adapter/dist/mcp-bearer-store.js +311 -0
  29. package/extensions/dm-mcp-adapter/dist/metadata-cache.js +285 -0
  30. package/extensions/dm-mcp-adapter/dist/package-mcp-loader.js +144 -0
  31. package/extensions/dm-mcp-adapter/dist/resource-tools.js +7 -0
  32. package/extensions/dm-mcp-adapter/dist/types.js +247 -0
  33. package/extensions/dm-mcp-adapter/dist/ui-app-bridge-helpers.js +36 -0
  34. package/extensions/dm-mcp-adapter/dist/ui-stream-types.js +58 -0
  35. package/extensions/dm-mcp-adapter/dist/ui-tool-visibility.js +26 -0
  36. package/extensions/dm-mcp-adapter/dist/utils.js +307 -0
  37. package/extensions/dm-mcp-adapter/elicitation-handler.js +306 -0
  38. package/extensions/dm-mcp-adapter/error-signal.js +16 -0
  39. package/extensions/dm-mcp-adapter/errors.js +225 -0
  40. package/extensions/dm-mcp-adapter/failure-backoff.js +19 -0
  41. package/extensions/dm-mcp-adapter/glimpse-ui.js +61 -0
  42. package/extensions/dm-mcp-adapter/host-html-template.js +464 -0
  43. package/extensions/dm-mcp-adapter/index.js +1079 -0
  44. package/extensions/dm-mcp-adapter/init.js +624 -0
  45. package/extensions/dm-mcp-adapter/json-schema-validator.js +53 -0
  46. package/extensions/dm-mcp-adapter/lifecycle.js +385 -0
  47. package/extensions/dm-mcp-adapter/logger.js +115 -0
  48. package/extensions/dm-mcp-adapter/mcp-auth-flow.js +824 -0
  49. package/extensions/dm-mcp-adapter/mcp-auth.js +732 -0
  50. package/extensions/dm-mcp-adapter/mcp-bearer-store.js +311 -0
  51. package/extensions/dm-mcp-adapter/mcp-callback-server.js +388 -0
  52. package/extensions/dm-mcp-adapter/mcp-code.js +291 -0
  53. package/extensions/dm-mcp-adapter/mcp-keyring-helper.cjs +88 -0
  54. package/extensions/dm-mcp-adapter/mcp-oauth-provider.js +490 -0
  55. package/extensions/dm-mcp-adapter/mcp-output-guard.js +386 -0
  56. package/extensions/dm-mcp-adapter/mcp-panel.js +951 -0
  57. package/extensions/dm-mcp-adapter/mcp-probe.js +151 -0
  58. package/extensions/dm-mcp-adapter/mcp-references.js +263 -0
  59. package/extensions/dm-mcp-adapter/mcp-script-worker.mjs +126 -0
  60. package/extensions/dm-mcp-adapter/mcp-setup-panel.js +578 -0
  61. package/extensions/dm-mcp-adapter/mcp-status.js +80 -0
  62. package/extensions/dm-mcp-adapter/mcp-trace.js +215 -0
  63. package/extensions/dm-mcp-adapter/metadata-cache.js +292 -0
  64. package/extensions/dm-mcp-adapter/namespace-tools.js +155 -0
  65. package/extensions/dm-mcp-adapter/npx-resolver.js +465 -0
  66. package/extensions/dm-mcp-adapter/oauth-handler.js +17 -0
  67. package/extensions/dm-mcp-adapter/oauth.js +17 -0
  68. package/extensions/dm-mcp-adapter/onboarding-state.js +62 -0
  69. package/extensions/dm-mcp-adapter/package-mcp-loader.js +144 -0
  70. package/extensions/dm-mcp-adapter/package.json +68 -0
  71. package/extensions/dm-mcp-adapter/panel-keys.js +26 -0
  72. package/extensions/dm-mcp-adapter/prompts.js +258 -0
  73. package/extensions/dm-mcp-adapter/proxy-modes.js +1336 -0
  74. package/extensions/dm-mcp-adapter/request-headers-command.js +293 -0
  75. package/extensions/dm-mcp-adapter/resource-tools.js +7 -0
  76. package/extensions/dm-mcp-adapter/runtime-owner.js +79 -0
  77. package/extensions/dm-mcp-adapter/sampling-handler.js +222 -0
  78. package/extensions/dm-mcp-adapter/sandbox-proxy-template.js +190 -0
  79. package/extensions/dm-mcp-adapter/search-ranking.js +198 -0
  80. package/extensions/dm-mcp-adapter/server-manager.js +1258 -0
  81. package/extensions/dm-mcp-adapter/session-recovery.js +82 -0
  82. package/extensions/dm-mcp-adapter/skills/mcp-scripting/SKILL.md +39 -0
  83. package/extensions/dm-mcp-adapter/state.js +0 -0
  84. package/extensions/dm-mcp-adapter/test-runner.mjs +18 -0
  85. package/extensions/dm-mcp-adapter/tool-approval.js +151 -0
  86. package/extensions/dm-mcp-adapter/tool-metadata.js +247 -0
  87. package/extensions/dm-mcp-adapter/tool-registrar.js +212 -0
  88. package/extensions/dm-mcp-adapter/tool-result-renderer.js +355 -0
  89. package/extensions/dm-mcp-adapter/ts-shape.js +157 -0
  90. package/extensions/dm-mcp-adapter/types.js +264 -0
  91. package/extensions/dm-mcp-adapter/ui-app-bridge-helpers.js +36 -0
  92. package/extensions/dm-mcp-adapter/ui-resource-handler.js +209 -0
  93. package/extensions/dm-mcp-adapter/ui-server.js +815 -0
  94. package/extensions/dm-mcp-adapter/ui-session.js +455 -0
  95. package/extensions/dm-mcp-adapter/ui-stream-types.js +58 -0
  96. package/extensions/dm-mcp-adapter/ui-tool-visibility.js +26 -0
  97. package/extensions/dm-mcp-adapter/unix-socket-transport.js +83 -0
  98. package/extensions/dm-mcp-adapter/utils.js +307 -0
  99. package/extensions/dm-skills-manager/THIRD_PARTY_NOTICES.md +27 -0
  100. package/extensions/dm-skills-manager/extensions/skills-manager/components.js +265 -0
  101. package/extensions/dm-skills-manager/extensions/skills-manager/constants.js +31 -0
  102. package/extensions/dm-skills-manager/extensions/skills-manager/creation-fallback.js +20 -0
  103. package/extensions/dm-skills-manager/extensions/skills-manager/creation.js +145 -0
  104. package/extensions/dm-skills-manager/extensions/skills-manager/dialog.js +738 -0
  105. package/extensions/dm-skills-manager/extensions/skills-manager/dm-ai-compat.js +15 -0
  106. package/extensions/dm-skills-manager/extensions/skills-manager/format.js +125 -0
  107. package/extensions/dm-skills-manager/extensions/skills-manager/glyphs.js +142 -0
  108. package/extensions/dm-skills-manager/extensions/skills-manager/layout.js +93 -0
  109. package/extensions/dm-skills-manager/extensions/skills-manager/paths.js +76 -0
  110. package/extensions/dm-skills-manager/extensions/skills-manager/registry.js +95 -0
  111. package/extensions/dm-skills-manager/extensions/skills-manager/settings.js +93 -0
  112. package/extensions/dm-skills-manager/extensions/skills-manager/startup.js +32 -0
  113. package/extensions/dm-skills-manager/extensions/skills-manager/toggle.js +54 -0
  114. package/extensions/dm-skills-manager/extensions/skills-manager/types.js +14 -0
  115. package/extensions/dm-skills-manager/extensions/skills-manager/ui.js +121 -0
  116. package/extensions/dm-skills-manager/extensions/skills-manager.js +111 -0
  117. package/extensions/dm-skills-manager/package.json +121 -0
  118. package/package.json +13 -1
  119. package/extensions/dm-localllm-provider/detect.test.js +0 -1051
  120. package/extensions/dm-localllm-provider/index.test.js +0 -149
  121. package/extensions/dm-localllm-provider/keychain.test.js +0 -61
@@ -0,0 +1,291 @@
1
+ import { formatWithOptions } from "node:util";
2
+ import { Worker } from "node:worker_threads";
3
+ import { guardMcpOutput, guardedMcpDetails, resolveMcpOutputGuardOptions } from "./mcp-output-guard.js";
4
+ import { executeCall } from "./proxy-modes.js";
5
+ import { combineAbortSignals } from "./runtime-owner.js";
6
+ import { paginate, rankSuggestions, rankToolMatches } from "./search-ranking.js";
7
+ import { isServerInActiveFailureBackoff } from "./failure-backoff.js";
8
+ import { findToolByName, formatSchema } from "./tool-metadata.js";
9
+ import { renderTsShape } from "./ts-shape.js";
10
+ export const DEFAULT_MCP_SCRIPT_TIMEOUT_MS = 30000;
11
+
12
+ class McpScriptTimeoutError extends Error {
13
+ constructor(timeoutMs) {
14
+ super(`mcpScript timed out after ${timeoutMs}ms`);
15
+ this.name = "McpScriptTimeoutError";
16
+ }
17
+ }
18
+ function needsInspectableFormatting(value, stack = new WeakSet) {
19
+ if (value === undefined || typeof value === "bigint" || typeof value === "function" || typeof value === "symbol")
20
+ return true;
21
+ if (typeof value !== "object" || value === null)
22
+ return false;
23
+ if (stack.has(value))
24
+ return true;
25
+ if (value instanceof Map || value instanceof Set || value instanceof WeakMap || value instanceof WeakSet)
26
+ return true;
27
+ stack.add(value);
28
+ try {
29
+ return Object.values(value).some((entry) => needsInspectableFormatting(entry, stack));
30
+ } finally {
31
+ stack.delete(value);
32
+ }
33
+ }
34
+ function formatValue(value) {
35
+ if (typeof value === "string")
36
+ return value;
37
+ try {
38
+ if (!needsInspectableFormatting(value)) {
39
+ const json = JSON.stringify(value, null, 2);
40
+ if (json !== undefined)
41
+ return json;
42
+ }
43
+ return formatWithOptions({ colors: false, depth: 6 }, value);
44
+ } catch {
45
+ return "[unserializable value]";
46
+ }
47
+ }
48
+ function toContentBlock(value) {
49
+ if (typeof value === "object" && value !== null) {
50
+ const block = value;
51
+ if (block.type === "text" && typeof block.text === "string") {
52
+ return { type: "text", text: block.text };
53
+ }
54
+ if (block.type === "image" && typeof block.data === "string" && typeof block.mimeType === "string") {
55
+ return { type: "image", data: block.data, mimeType: block.mimeType };
56
+ }
57
+ }
58
+ return { type: "text", text: formatValue(value) };
59
+ }
60
+ function textFromContent(content) {
61
+ return content.filter((block) => block.type === "text").map((block) => block.text).join(`
62
+ `);
63
+ }
64
+ function abortReasonError(reason) {
65
+ return reason instanceof Error ? reason : new Error(String(reason ?? "MCP request aborted"));
66
+ }
67
+ function parseWorkerMessage(value) {
68
+ if (typeof value !== "object" || value === null)
69
+ return null;
70
+ const message = value;
71
+ if (message.type === "emit" && "block" in message)
72
+ return { type: "emit", block: message.block };
73
+ if (message.type === "call" && typeof message.id === "number" && typeof message.path === "string") {
74
+ return "args" in message ? { type: "call", id: message.id, path: message.path, args: message.args } : { type: "call", id: message.id, path: message.path };
75
+ }
76
+ if ((message.type === "search" || message.type === "describe") && typeof message.id === "number") {
77
+ return "input" in message ? { type: message.type, id: message.id, input: message.input } : { type: message.type, id: message.id };
78
+ }
79
+ if (message.type === "done") {
80
+ return "returnBlock" in message ? { type: "done", returnBlock: message.returnBlock } : { type: "done" };
81
+ }
82
+ if (message.type === "error" && typeof message.message === "string") {
83
+ return { type: "error", message: message.message };
84
+ }
85
+ return null;
86
+ }
87
+ export async function runMcpScript(state, code, timeoutMs = DEFAULT_MCP_SCRIPT_TIMEOUT_MS, getPiTools, signal) {
88
+ const resolvedTimeoutMs = Number.isFinite(timeoutMs) && timeoutMs > 0 ? Math.floor(timeoutMs) : DEFAULT_MCP_SCRIPT_TIMEOUT_MS;
89
+ const output = [];
90
+ const externalSignal = combineAbortSignals(state.owner?.signal, signal);
91
+ const timeoutController = new AbortController;
92
+ const callSignal = combineAbortSignals(externalSignal, timeoutController.signal);
93
+ const calls = [];
94
+ const snapshotCalls = () => calls.map(({ startedAt, ...operation }) => ({
95
+ ...operation,
96
+ durationMs: "error" in operation && operation.error === "incomplete" ? Math.max(0, Date.now() - startedAt) : operation.durationMs
97
+ }));
98
+ let callsSnapshot;
99
+ const callTool = async (path, args) => {
100
+ const startedAt = Date.now();
101
+ const index = calls.push({ operation: "call", path, ok: false, error: "incomplete", durationMs: 0, startedAt }) - 1;
102
+ const result = await executeCall(state, path, args, undefined, getPiTools, callSignal, "script");
103
+ const details = result.details;
104
+ if (details.error !== undefined) {
105
+ const errorCode = String(details.error);
106
+ const suggestions = Array.isArray(details.suggestions) ? details.suggestions.filter((suggestion) => typeof suggestion === "string") : [];
107
+ const message = errorCode === "tool_not_found" ? `Tool "${path}" not found. Use await tools.search({ query: "..." }) inside mcpScript.${suggestions.length > 0 ? ` Did you mean: ${suggestions.join(", ")}` : ""}` : typeof details.message === "string" ? details.message : textFromContent(result.content);
108
+ calls[index] = { operation: "call", path, ok: false, error: errorCode, durationMs: Date.now() - startedAt, startedAt };
109
+ return {
110
+ ok: false,
111
+ error: { code: errorCode, message }
112
+ };
113
+ }
114
+ calls[index] = { operation: "call", path, ok: true, durationMs: Date.now() - startedAt, startedAt };
115
+ return {
116
+ ok: true,
117
+ data: details.mcpResult !== undefined ? details.mcpResult : textFromContent(result.content)
118
+ };
119
+ };
120
+ const searchTools = (input) => {
121
+ const startedAt = Date.now();
122
+ const query = typeof input?.query === "string" ? input.query : "";
123
+ let error;
124
+ try {
125
+ if (query.trim() === "") {
126
+ return { items: [], total: 0, hasMore: false, nextOffset: null };
127
+ }
128
+ const server = typeof input?.server === "string" ? input.server : undefined;
129
+ const limit = typeof input?.limit === "number" ? input.limit : 12;
130
+ const offset = typeof input?.offset === "number" ? input.offset : 0;
131
+ const page = paginate(rankToolMatches(state, query, server), offset, limit);
132
+ return {
133
+ ...page,
134
+ items: page.items.map(({ server: matchServer, tool, score }) => ({
135
+ path: tool.name,
136
+ name: tool.originalName,
137
+ server: matchServer,
138
+ ...tool.description ? { description: tool.description } : {},
139
+ score
140
+ }))
141
+ };
142
+ } catch (caught) {
143
+ error = caught;
144
+ throw caught;
145
+ } finally {
146
+ calls.push(error === undefined ? { operation: "search", query, ok: true, durationMs: Date.now() - startedAt, startedAt } : { operation: "search", query, ok: false, error: error instanceof Error ? error.message : String(error), durationMs: Date.now() - startedAt, startedAt });
147
+ }
148
+ };
149
+ const describeTool = (input) => {
150
+ const startedAt = Date.now();
151
+ const path = typeof input?.path === "string" ? input.path : "";
152
+ let error;
153
+ try {
154
+ for (const [server, metadata] of state.toolMetadata) {
155
+ if (isServerInActiveFailureBackoff(state, server))
156
+ continue;
157
+ const tool = findToolByName(metadata, path);
158
+ if (!tool)
159
+ continue;
160
+ const inputTypeScript = tool.inputSchema ? renderTsShape(tool.inputSchema) ?? formatSchema(tool.inputSchema) : null;
161
+ return {
162
+ path: tool.name,
163
+ name: tool.originalName,
164
+ server,
165
+ ...tool.description ? { description: tool.description } : {},
166
+ ...inputTypeScript ? { inputTypeScript } : {}
167
+ };
168
+ }
169
+ const suggestions = path ? rankSuggestions(state, path, 5) : [];
170
+ error = "tool_not_found";
171
+ return {
172
+ path,
173
+ error: {
174
+ code: "tool_not_found",
175
+ message: `Tool not found: ${path}`,
176
+ suggestions
177
+ }
178
+ };
179
+ } catch (caught) {
180
+ error = caught;
181
+ throw caught;
182
+ } finally {
183
+ calls.push(error === undefined ? { operation: "describe", path, ok: true, durationMs: Date.now() - startedAt, startedAt } : { operation: "describe", path, ok: false, error: error instanceof Error ? error.message : String(error), durationMs: Date.now() - startedAt, startedAt });
184
+ }
185
+ };
186
+ let worker;
187
+ let timer;
188
+ let removeAbortListener = () => {};
189
+ let errorCode;
190
+ let errorMessage;
191
+ try {
192
+ if (externalSignal?.aborted) {
193
+ throw abortReasonError(externalSignal.reason);
194
+ }
195
+ worker = new Worker(new URL("./mcp-script-worker.mjs", import.meta.url), {
196
+ workerData: { code },
197
+ env: {},
198
+ trackUnmanagedFds: false
199
+ });
200
+ const activeWorker = worker;
201
+ const execution = new Promise((resolve, reject) => {
202
+ let completed = false;
203
+ activeWorker.on("message", (value) => {
204
+ const message = parseWorkerMessage(value);
205
+ if (!message || completed)
206
+ return;
207
+ if (message.type === "emit") {
208
+ output.push(toContentBlock(message.block));
209
+ return;
210
+ }
211
+ if (message.type === "done") {
212
+ completed = true;
213
+ if ("returnBlock" in message)
214
+ output.push(toContentBlock(message.returnBlock));
215
+ resolve();
216
+ return;
217
+ }
218
+ if (message.type === "error") {
219
+ completed = true;
220
+ reject(new Error(message.message));
221
+ return;
222
+ }
223
+ (async () => {
224
+ let envelope;
225
+ if (message.type === "call") {
226
+ envelope = await callTool(message.path, message.args);
227
+ } else if (message.type === "search") {
228
+ envelope = searchTools(message.input);
229
+ } else {
230
+ envelope = describeTool(message.input);
231
+ }
232
+ const response = { type: "result", id: message.id, envelope };
233
+ activeWorker.postMessage(response);
234
+ })().catch(reject);
235
+ });
236
+ activeWorker.once("error", reject);
237
+ activeWorker.once("exit", (code) => {
238
+ if (!completed && code !== 0)
239
+ reject(new Error(`mcpScript worker exited with code ${code}`));
240
+ });
241
+ });
242
+ const timeoutError = new McpScriptTimeoutError(resolvedTimeoutMs);
243
+ const timeout = new Promise((_resolve, reject) => {
244
+ timer = setTimeout(() => {
245
+ callsSnapshot = snapshotCalls();
246
+ timeoutController.abort(timeoutError);
247
+ activeWorker.terminate();
248
+ reject(timeoutError);
249
+ }, resolvedTimeoutMs);
250
+ });
251
+ const aborted = externalSignal ? new Promise((_resolve, reject) => {
252
+ const onAbort = () => {
253
+ callsSnapshot = snapshotCalls();
254
+ activeWorker.terminate();
255
+ reject(abortReasonError(externalSignal.reason));
256
+ };
257
+ externalSignal.addEventListener("abort", onAbort, { once: true });
258
+ removeAbortListener = () => externalSignal.removeEventListener("abort", onAbort);
259
+ }) : new Promise(() => {});
260
+ await Promise.race([execution, timeout, aborted]);
261
+ } catch (error) {
262
+ if (error instanceof McpScriptTimeoutError) {
263
+ errorCode = "timeout";
264
+ errorMessage = `mcpScript timed out after ${resolvedTimeoutMs}ms`;
265
+ } else if (externalSignal?.aborted) {
266
+ errorCode = "aborted";
267
+ errorMessage = error instanceof Error ? error.message : String(error);
268
+ } else {
269
+ errorCode = "script_error";
270
+ errorMessage = error instanceof Error ? error.message : String(error);
271
+ }
272
+ output.push({ type: "text", text: errorMessage });
273
+ } finally {
274
+ clearTimeout(timer);
275
+ removeAbortListener();
276
+ callsSnapshot ??= snapshotCalls();
277
+ timeoutController.abort(new Error("mcpScript finished"));
278
+ await worker?.terminate();
279
+ }
280
+ const guarded = await guardMcpOutput(output.length > 0 ? [...output] : [{ type: "text", text: "(no output)" }], resolveMcpOutputGuardOptions(state.config.settings));
281
+ return {
282
+ content: guarded.content,
283
+ details: {
284
+ mode: "script",
285
+ ...errorCode ? { error: errorCode, message: errorMessage } : {},
286
+ timeoutMs: resolvedTimeoutMs,
287
+ ...callsSnapshot.length > 0 ? { calls: callsSnapshot } : {},
288
+ ...guardedMcpDetails(guarded)
289
+ }
290
+ };
291
+ }
@@ -0,0 +1,88 @@
1
+ var __filename = "/Users/que/Projects/dm/dm-mono/packages/coding-agent/dist/extensions/dm-mcp-adapter/mcp-keyring-helper.cjs";
2
+ const { createRequire } = require("node:module");
3
+ const { dirname, join } = require("node:path");
4
+ const requireFromHere = createRequire(__filename);
5
+ function loadKeyringEntryClass() {
6
+ try {
7
+ return requireFromHere("@napi-rs/keyring").Entry;
8
+ } catch (loaderError) {
9
+ const suffixes = getNativeBindingSuffixes(process.platform, process.arch);
10
+ let lastError;
11
+ for (const suffix of suffixes) {
12
+ try {
13
+ const packageJsonPath = requireFromHere.resolve(`@napi-rs/keyring-${suffix}/package.json`);
14
+ return requireFromHere(join(dirname(packageJsonPath), `keyring.${suffix}.node`)).Entry;
15
+ } catch (error) {
16
+ lastError = error;
17
+ }
18
+ }
19
+ const error = new Error(`Failed to load @napi-rs/keyring in recovery helper: ${lastError?.message ?? loaderError.message}`);
20
+ error.cause = loaderError;
21
+ throw error;
22
+ }
23
+ }
24
+ function getNativeBindingSuffixes(platform, arch) {
25
+ if (platform === "linux") {
26
+ if (arch === "arm64")
27
+ return ["linux-arm64-gnu", "linux-arm64-musl"];
28
+ if (arch === "arm")
29
+ return ["linux-arm-gnueabihf"];
30
+ if (arch === "riscv64")
31
+ return ["linux-riscv64-gnu"];
32
+ if (arch === "x64")
33
+ return ["linux-x64-gnu", "linux-x64-musl"];
34
+ }
35
+ return [];
36
+ }
37
+ function readStdin() {
38
+ return new Promise((resolve, reject) => {
39
+ let input = "";
40
+ process.stdin.setEncoding("utf8");
41
+ process.stdin.on("data", (chunk) => {
42
+ input += chunk;
43
+ if (input.length > 1024 * 1024) {
44
+ reject(new Error("request too large"));
45
+ process.stdin.destroy();
46
+ }
47
+ });
48
+ process.stdin.on("error", reject);
49
+ process.stdin.on("end", () => resolve(input));
50
+ });
51
+ }
52
+ function writeResponse(response) {
53
+ process.stdout.write(`${JSON.stringify(response)}
54
+ `);
55
+ }
56
+ (async () => {
57
+ try {
58
+ const request = JSON.parse(await readStdin());
59
+ if (!request || typeof request !== "object")
60
+ throw new Error("invalid request");
61
+ const { operation, service, account, payload } = request;
62
+ if (!["read", "write", "remove"].includes(operation))
63
+ throw new Error("invalid operation");
64
+ if (typeof service !== "string" || !service)
65
+ throw new Error("invalid service");
66
+ if (typeof account !== "string" || !account)
67
+ throw new Error("invalid account");
68
+ const Entry = loadKeyringEntryClass();
69
+ const entry = new Entry(service, account);
70
+ if (operation === "read") {
71
+ const value = entry.getPassword();
72
+ writeResponse(value === null ? { ok: true, found: false } : { ok: true, found: true, value });
73
+ return;
74
+ }
75
+ if (operation === "write") {
76
+ if (typeof payload !== "string")
77
+ throw new Error("invalid payload");
78
+ entry.setPassword(payload);
79
+ writeResponse({ ok: true });
80
+ return;
81
+ }
82
+ entry.deleteCredential();
83
+ writeResponse({ ok: true });
84
+ } catch (error) {
85
+ writeResponse({ ok: false, error: error instanceof Error ? error.message : String(error) });
86
+ process.exitCode = 1;
87
+ }
88
+ })();