lark-agent-bridge 0.1.39

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 (155) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +265 -0
  3. package/README.zh.md +265 -0
  4. package/bin/lark-agent-bridge.mjs +2 -0
  5. package/dist/agent/cursor/cursor-sdk-worker.js +702 -0
  6. package/dist/cli.js +7588 -0
  7. package/dist/index.d.ts +113 -0
  8. package/dist/index.js +721 -0
  9. package/package.json +72 -0
  10. package/vendor/cursor-sdk/LICENSE.md +3 -0
  11. package/vendor/cursor-sdk/README.md +23 -0
  12. package/vendor/cursor-sdk/dist/cjs/642.index.js +1 -0
  13. package/vendor/cursor-sdk/dist/cjs/agent.d.ts +170 -0
  14. package/vendor/cursor-sdk/dist/cjs/agent.d.ts.map +1 -0
  15. package/vendor/cursor-sdk/dist/cjs/analytics.d.ts +98 -0
  16. package/vendor/cursor-sdk/dist/cjs/analytics.d.ts.map +1 -0
  17. package/vendor/cursor-sdk/dist/cjs/artifacts.d.ts +6 -0
  18. package/vendor/cursor-sdk/dist/cjs/artifacts.d.ts.map +1 -0
  19. package/vendor/cursor-sdk/dist/cjs/cloud-agent.d.ts +47 -0
  20. package/vendor/cursor-sdk/dist/cjs/cloud-agent.d.ts.map +1 -0
  21. package/vendor/cursor-sdk/dist/cjs/cloud-api-client.d.ts +197 -0
  22. package/vendor/cursor-sdk/dist/cjs/cloud-api-client.d.ts.map +1 -0
  23. package/vendor/cursor-sdk/dist/cjs/cloud-executor.d.ts +14 -0
  24. package/vendor/cursor-sdk/dist/cjs/cloud-executor.d.ts.map +1 -0
  25. package/vendor/cursor-sdk/dist/cjs/cloud-mcp-utils.d.ts +4 -0
  26. package/vendor/cursor-sdk/dist/cjs/cloud-mcp-utils.d.ts.map +1 -0
  27. package/vendor/cursor-sdk/dist/cjs/core-adapter.d.ts +2 -0
  28. package/vendor/cursor-sdk/dist/cjs/core-adapter.d.ts.map +1 -0
  29. package/vendor/cursor-sdk/dist/cjs/errors.d.ts +135 -0
  30. package/vendor/cursor-sdk/dist/cjs/errors.d.ts.map +1 -0
  31. package/vendor/cursor-sdk/dist/cjs/executor-common.d.ts +16 -0
  32. package/vendor/cursor-sdk/dist/cjs/executor-common.d.ts.map +1 -0
  33. package/vendor/cursor-sdk/dist/cjs/executor-types.d.ts +65 -0
  34. package/vendor/cursor-sdk/dist/cjs/executor-types.d.ts.map +1 -0
  35. package/vendor/cursor-sdk/dist/cjs/index.d.ts +18 -0
  36. package/vendor/cursor-sdk/dist/cjs/index.d.ts.map +1 -0
  37. package/vendor/cursor-sdk/dist/cjs/index.js +8 -0
  38. package/vendor/cursor-sdk/dist/cjs/index.js.LICENSE.txt +285 -0
  39. package/vendor/cursor-sdk/dist/cjs/local-executor.d.ts +18 -0
  40. package/vendor/cursor-sdk/dist/cjs/local-executor.d.ts.map +1 -0
  41. package/vendor/cursor-sdk/dist/cjs/local-model-validation.d.ts +6 -0
  42. package/vendor/cursor-sdk/dist/cjs/local-model-validation.d.ts.map +1 -0
  43. package/vendor/cursor-sdk/dist/cjs/messages.d.ts +110 -0
  44. package/vendor/cursor-sdk/dist/cjs/messages.d.ts.map +1 -0
  45. package/vendor/cursor-sdk/dist/cjs/options.d.ts +145 -0
  46. package/vendor/cursor-sdk/dist/cjs/options.d.ts.map +1 -0
  47. package/vendor/cursor-sdk/dist/cjs/package.json +3 -0
  48. package/vendor/cursor-sdk/dist/cjs/platform.d.ts +71 -0
  49. package/vendor/cursor-sdk/dist/cjs/platform.d.ts.map +1 -0
  50. package/vendor/cursor-sdk/dist/cjs/prefetched-blobs.d.ts +13 -0
  51. package/vendor/cursor-sdk/dist/cjs/prefetched-blobs.d.ts.map +1 -0
  52. package/vendor/cursor-sdk/dist/cjs/public-api.d.ts +12 -0
  53. package/vendor/cursor-sdk/dist/cjs/public-api.d.ts.map +1 -0
  54. package/vendor/cursor-sdk/dist/cjs/run-event-tailer.d.ts +33 -0
  55. package/vendor/cursor-sdk/dist/cjs/run-event-tailer.d.ts.map +1 -0
  56. package/vendor/cursor-sdk/dist/cjs/run-interaction-accumulator.d.ts +33 -0
  57. package/vendor/cursor-sdk/dist/cjs/run-interaction-accumulator.d.ts.map +1 -0
  58. package/vendor/cursor-sdk/dist/cjs/run.d.ts +44 -0
  59. package/vendor/cursor-sdk/dist/cjs/run.d.ts.map +1 -0
  60. package/vendor/cursor-sdk/dist/cjs/sdk-statsig.d.ts +10 -0
  61. package/vendor/cursor-sdk/dist/cjs/sdk-statsig.d.ts.map +1 -0
  62. package/vendor/cursor-sdk/dist/cjs/stubs.d.ts +98 -0
  63. package/vendor/cursor-sdk/dist/cjs/stubs.d.ts.map +1 -0
  64. package/vendor/cursor-sdk/dist/cjs/subagent-conversion.d.ts +22 -0
  65. package/vendor/cursor-sdk/dist/cjs/subagent-conversion.d.ts.map +1 -0
  66. package/vendor/cursor-sdk/dist/cjs/tool-call-utils.d.ts +7 -0
  67. package/vendor/cursor-sdk/dist/cjs/tool-call-utils.d.ts.map +1 -0
  68. package/vendor/cursor-sdk/dist/cjs/types/conversation-types.d.ts +12062 -0
  69. package/vendor/cursor-sdk/dist/cjs/types/conversation-types.d.ts.map +1 -0
  70. package/vendor/cursor-sdk/dist/cjs/types/delta-types.d.ts +2 -0
  71. package/vendor/cursor-sdk/dist/cjs/types/delta-types.d.ts.map +1 -0
  72. package/vendor/cursor-sdk/dist/cjs/types/tool-call-types.d.ts +2 -0
  73. package/vendor/cursor-sdk/dist/cjs/types/tool-call-types.d.ts.map +1 -0
  74. package/vendor/cursor-sdk/dist/cjs/utils/conversation-utils.d.ts +3 -0
  75. package/vendor/cursor-sdk/dist/cjs/utils/conversation-utils.d.ts.map +1 -0
  76. package/vendor/cursor-sdk/dist/cjs/utils/logger.d.ts +12 -0
  77. package/vendor/cursor-sdk/dist/cjs/utils/logger.d.ts.map +1 -0
  78. package/vendor/cursor-sdk/dist/cjs/utils/message-schemas.d.ts +2 -0
  79. package/vendor/cursor-sdk/dist/cjs/utils/message-schemas.d.ts.map +1 -0
  80. package/vendor/cursor-sdk/dist/esm/642.index.js +1 -0
  81. package/vendor/cursor-sdk/dist/esm/agent.d.ts +170 -0
  82. package/vendor/cursor-sdk/dist/esm/agent.d.ts.map +1 -0
  83. package/vendor/cursor-sdk/dist/esm/analytics.d.ts +98 -0
  84. package/vendor/cursor-sdk/dist/esm/analytics.d.ts.map +1 -0
  85. package/vendor/cursor-sdk/dist/esm/artifacts.d.ts +6 -0
  86. package/vendor/cursor-sdk/dist/esm/artifacts.d.ts.map +1 -0
  87. package/vendor/cursor-sdk/dist/esm/cloud-agent.d.ts +47 -0
  88. package/vendor/cursor-sdk/dist/esm/cloud-agent.d.ts.map +1 -0
  89. package/vendor/cursor-sdk/dist/esm/cloud-api-client.d.ts +197 -0
  90. package/vendor/cursor-sdk/dist/esm/cloud-api-client.d.ts.map +1 -0
  91. package/vendor/cursor-sdk/dist/esm/cloud-executor.d.ts +14 -0
  92. package/vendor/cursor-sdk/dist/esm/cloud-executor.d.ts.map +1 -0
  93. package/vendor/cursor-sdk/dist/esm/cloud-mcp-utils.d.ts +4 -0
  94. package/vendor/cursor-sdk/dist/esm/cloud-mcp-utils.d.ts.map +1 -0
  95. package/vendor/cursor-sdk/dist/esm/core-adapter.d.ts +2 -0
  96. package/vendor/cursor-sdk/dist/esm/core-adapter.d.ts.map +1 -0
  97. package/vendor/cursor-sdk/dist/esm/errors.d.ts +135 -0
  98. package/vendor/cursor-sdk/dist/esm/errors.d.ts.map +1 -0
  99. package/vendor/cursor-sdk/dist/esm/executor-common.d.ts +16 -0
  100. package/vendor/cursor-sdk/dist/esm/executor-common.d.ts.map +1 -0
  101. package/vendor/cursor-sdk/dist/esm/executor-types.d.ts +65 -0
  102. package/vendor/cursor-sdk/dist/esm/executor-types.d.ts.map +1 -0
  103. package/vendor/cursor-sdk/dist/esm/index.d.ts +18 -0
  104. package/vendor/cursor-sdk/dist/esm/index.d.ts.map +1 -0
  105. package/vendor/cursor-sdk/dist/esm/index.js +8 -0
  106. package/vendor/cursor-sdk/dist/esm/index.js.LICENSE.txt +285 -0
  107. package/vendor/cursor-sdk/dist/esm/local-executor.d.ts +18 -0
  108. package/vendor/cursor-sdk/dist/esm/local-executor.d.ts.map +1 -0
  109. package/vendor/cursor-sdk/dist/esm/local-model-validation.d.ts +6 -0
  110. package/vendor/cursor-sdk/dist/esm/local-model-validation.d.ts.map +1 -0
  111. package/vendor/cursor-sdk/dist/esm/messages.d.ts +110 -0
  112. package/vendor/cursor-sdk/dist/esm/messages.d.ts.map +1 -0
  113. package/vendor/cursor-sdk/dist/esm/options.d.ts +145 -0
  114. package/vendor/cursor-sdk/dist/esm/options.d.ts.map +1 -0
  115. package/vendor/cursor-sdk/dist/esm/platform.d.ts +71 -0
  116. package/vendor/cursor-sdk/dist/esm/platform.d.ts.map +1 -0
  117. package/vendor/cursor-sdk/dist/esm/prefetched-blobs.d.ts +13 -0
  118. package/vendor/cursor-sdk/dist/esm/prefetched-blobs.d.ts.map +1 -0
  119. package/vendor/cursor-sdk/dist/esm/public-api.d.ts +12 -0
  120. package/vendor/cursor-sdk/dist/esm/public-api.d.ts.map +1 -0
  121. package/vendor/cursor-sdk/dist/esm/run-event-tailer.d.ts +33 -0
  122. package/vendor/cursor-sdk/dist/esm/run-event-tailer.d.ts.map +1 -0
  123. package/vendor/cursor-sdk/dist/esm/run-interaction-accumulator.d.ts +33 -0
  124. package/vendor/cursor-sdk/dist/esm/run-interaction-accumulator.d.ts.map +1 -0
  125. package/vendor/cursor-sdk/dist/esm/run.d.ts +44 -0
  126. package/vendor/cursor-sdk/dist/esm/run.d.ts.map +1 -0
  127. package/vendor/cursor-sdk/dist/esm/sdk-statsig.d.ts +10 -0
  128. package/vendor/cursor-sdk/dist/esm/sdk-statsig.d.ts.map +1 -0
  129. package/vendor/cursor-sdk/dist/esm/stubs.d.ts +98 -0
  130. package/vendor/cursor-sdk/dist/esm/stubs.d.ts.map +1 -0
  131. package/vendor/cursor-sdk/dist/esm/subagent-conversion.d.ts +22 -0
  132. package/vendor/cursor-sdk/dist/esm/subagent-conversion.d.ts.map +1 -0
  133. package/vendor/cursor-sdk/dist/esm/tool-call-utils.d.ts +7 -0
  134. package/vendor/cursor-sdk/dist/esm/tool-call-utils.d.ts.map +1 -0
  135. package/vendor/cursor-sdk/dist/esm/types/conversation-types.d.ts +12062 -0
  136. package/vendor/cursor-sdk/dist/esm/types/conversation-types.d.ts.map +1 -0
  137. package/vendor/cursor-sdk/dist/esm/types/delta-types.d.ts +2 -0
  138. package/vendor/cursor-sdk/dist/esm/types/delta-types.d.ts.map +1 -0
  139. package/vendor/cursor-sdk/dist/esm/types/tool-call-types.d.ts +2 -0
  140. package/vendor/cursor-sdk/dist/esm/types/tool-call-types.d.ts.map +1 -0
  141. package/vendor/cursor-sdk/dist/esm/utils/conversation-utils.d.ts +3 -0
  142. package/vendor/cursor-sdk/dist/esm/utils/conversation-utils.d.ts.map +1 -0
  143. package/vendor/cursor-sdk/dist/esm/utils/logger.d.ts +12 -0
  144. package/vendor/cursor-sdk/dist/esm/utils/logger.d.ts.map +1 -0
  145. package/vendor/cursor-sdk/dist/esm/utils/message-schemas.d.ts +2 -0
  146. package/vendor/cursor-sdk/dist/esm/utils/message-schemas.d.ts.map +1 -0
  147. package/vendor/cursor-sdk/package.json +77 -0
  148. package/vendor/cursor-sdk-linux-x64/README.md +5 -0
  149. package/vendor/cursor-sdk-linux-x64/bin/cursorsandbox +0 -0
  150. package/vendor/cursor-sdk-linux-x64/bin/rg +0 -0
  151. package/vendor/cursor-sdk-linux-x64/package.json +8 -0
  152. package/vendor/package/README.md +5 -0
  153. package/vendor/package/bin/cursorsandbox +0 -0
  154. package/vendor/package/bin/rg +0 -0
  155. package/vendor/package/package.json +25 -0
@@ -0,0 +1,702 @@
1
+ // src/agent/cursor/sdk-worker.ts
2
+ import { Agent } from "@cursor/sdk";
3
+
4
+ // src/agent/cursor/sdk-error.ts
5
+ import { CursorAgentError } from "@cursor/sdk";
6
+ var AUTH_HINT = 'Cursor \u9700\u8981 API Key\uFF1A\u5728 config.json \u914D\u7F6E preferences.agentCursorApiKey\uFF08\u63A8\u8350\u52A0\u5BC6\uFF1Alark-agent-bridge secrets set --id cursor-api-key\uFF09\uFF0C\u6216 export CURSOR_API_KEY\uFF1B\u4E5F\u53EF\u5C06 agentCursorRuntime \u8BBE\u4E3A "cli" \u4EE5\u4F7F\u7528 `agent login` \u4F1A\u8BDD\u3002';
7
+ function getCause(err) {
8
+ if (!err || typeof err !== "object") return void 0;
9
+ if ("cause" in err && err.cause !== err) {
10
+ return err.cause;
11
+ }
12
+ return void 0;
13
+ }
14
+ function errorName(err) {
15
+ if (!err || typeof err !== "object") return "Error";
16
+ if ("name" in err && typeof err.name === "string") {
17
+ return err.name;
18
+ }
19
+ return "Error";
20
+ }
21
+ function errorMessage(err) {
22
+ if (err instanceof Error) return err.message || err.name;
23
+ if (typeof err === "string") return err;
24
+ return String(err);
25
+ }
26
+ function errorCode(err) {
27
+ if (!err || typeof err !== "object") return void 0;
28
+ if ("code" in err) {
29
+ const code = err.code;
30
+ if (typeof code === "string" || typeof code === "number") return code;
31
+ }
32
+ return void 0;
33
+ }
34
+ function connectRawMessage(err) {
35
+ if (!err || typeof err !== "object" || !("rawMessage" in err)) return void 0;
36
+ const raw = err.rawMessage;
37
+ return typeof raw === "string" && raw.length > 0 ? raw : void 0;
38
+ }
39
+ function sdkExtras(err) {
40
+ if (!(err instanceof CursorAgentError)) return [];
41
+ const parts = [];
42
+ if (err.code) parts.push(`code=${err.code}`);
43
+ if (err.status !== void 0) parts.push(`status=${err.status}`);
44
+ if (err.operation) parts.push(`operation=${err.operation}`);
45
+ if (err.endpoint) parts.push(`endpoint=${err.endpoint}`);
46
+ if (err.requestId) parts.push(`requestId=${err.requestId}`);
47
+ parts.push(`retryable=${err.isRetryable}`);
48
+ return parts;
49
+ }
50
+ function classifyKind(err) {
51
+ if (err instanceof CursorAgentError) {
52
+ const name = errorName(err);
53
+ if (name === "AuthenticationError" || err.code === "unauthenticated") return "auth";
54
+ if (name === "RateLimitError") return "rate_limit";
55
+ if (name === "NetworkError") return "network";
56
+ if (name === "ConfigurationError") return "config";
57
+ }
58
+ if (errorName(err) === "ConfigurationError") return "config";
59
+ if (errorMessage(err).includes("Cannot use this model")) return "config";
60
+ const code = errorCode(err);
61
+ if (code === "unauthenticated" || code === 16) return "auth";
62
+ if (typeof code === "number" && code === 8) return "rate_limit";
63
+ const msg = errorMessage(err).toLowerCase();
64
+ if (msg.includes("unauthenticated") || msg.includes("authentication") || msg.includes("api key")) {
65
+ return "auth";
66
+ }
67
+ if (msg.includes("cancelled") || msg.includes("canceled")) return "cancelled";
68
+ if (msg.includes("econnrefused") || msg.includes("econnreset") || msg.includes("socket hang up") || msg.includes("network") || msg.includes("timeout")) {
69
+ return "network";
70
+ }
71
+ return "unknown";
72
+ }
73
+ function formatChainLine(err, depth) {
74
+ const name = errorName(err);
75
+ const msg = errorMessage(err);
76
+ const raw = connectRawMessage(err);
77
+ const code = errorCode(err);
78
+ const extras = sdkExtras(err);
79
+ const bits = [`${" ".repeat(depth)}${name}: ${msg}`];
80
+ if (raw && raw !== msg) bits.push(`raw=${raw}`);
81
+ if (code !== void 0) bits.push(`code=${code}`);
82
+ if (extras.length > 0) bits.push(extras.join(", "));
83
+ return bits.join(" | ");
84
+ }
85
+ function headlineForKind(kind, root) {
86
+ const msg = errorMessage(root);
87
+ switch (kind) {
88
+ case "auth":
89
+ return msg && msg !== "Error" ? `Cursor API \u9274\u6743\u5931\u8D25: ${msg}` : "Cursor API \u9274\u6743\u5931\u8D25 (unauthenticated)";
90
+ case "rate_limit":
91
+ return `Cursor API \u9650\u6D41: ${msg}`;
92
+ case "network":
93
+ return `Cursor API \u7F51\u7EDC\u9519\u8BEF: ${msg}`;
94
+ case "config":
95
+ return `Cursor SDK \u914D\u7F6E\u9519\u8BEF: ${msg}`;
96
+ case "cancelled":
97
+ return "Cursor agent run cancelled";
98
+ default:
99
+ return msg || "Cursor SDK error";
100
+ }
101
+ }
102
+ function describeSdkError(err) {
103
+ const lines = [];
104
+ let current = err;
105
+ let depth = 0;
106
+ let kind = "unknown";
107
+ while (current && depth < 8) {
108
+ lines.push(formatChainLine(current, depth));
109
+ const k = classifyKind(current);
110
+ if (k !== "unknown") kind = k;
111
+ current = getCause(current);
112
+ depth += 1;
113
+ }
114
+ const headline = headlineForKind(kind, err);
115
+ const hint = kind === "auth" ? AUTH_HINT : kind === "rate_limit" ? "\u7A0D\u540E\u91CD\u8BD5\uFF0C\u6216\u964D\u4F4E\u5E76\u53D1\uFF08maxConcurrentRuns / agentSessionPoolSize\uFF09\u3002" : void 0;
116
+ const detail = [headline, ...lines, hint].filter(Boolean).join("\n");
117
+ return { kind, headline, detail, hint };
118
+ }
119
+ function isCursorAgentNotFoundError(err, agentId) {
120
+ const msg = errorMessage(err);
121
+ if (!msg.includes(`Agent ${agentId} not found`)) return false;
122
+ if (errorName(err) !== "ConfigurationError") return false;
123
+ if (err instanceof CursorAgentError && err.operation !== "Agent.resume") return false;
124
+ if (err && typeof err === "object" && "operation" in err && err.operation !== "Agent.resume") {
125
+ return false;
126
+ }
127
+ return true;
128
+ }
129
+ function isCursorAgentActiveRunError(err, agentId) {
130
+ const msg = errorMessage(err);
131
+ if (!msg.includes(`Agent ${agentId} already has active run`)) return false;
132
+ if (err instanceof CursorAgentError && err.operation !== "agent.send") return false;
133
+ if (err && typeof err === "object" && "operation" in err && err.operation !== "agent.send") {
134
+ return false;
135
+ }
136
+ return true;
137
+ }
138
+ function isCursorRateLimitError(err) {
139
+ return describeSdkError(err).kind === "rate_limit";
140
+ }
141
+ function isCursorNetworkError(err) {
142
+ return describeSdkError(err).kind === "network";
143
+ }
144
+ function formatSdkErrorForIpc(phase, err) {
145
+ const d = describeSdkError(err);
146
+ const parts = [`${phase}: ${d.headline}`];
147
+ const rest = d.detail.split("\n").filter((line) => line !== d.headline && line !== d.hint);
148
+ if (rest.length > 0) parts.push(...rest);
149
+ if (d.hint) parts.push(d.hint);
150
+ return parts.join("\n");
151
+ }
152
+ function formatSdkErrorForStderr(phase, err) {
153
+ const d = describeSdkError(err);
154
+ return [`[sdk-worker] ${phase}`, d.detail, d.hint].filter(Boolean).join("\n");
155
+ }
156
+
157
+ // src/agent/cursor/spawn-run.ts
158
+ import { spawn as spawn2 } from "child_process";
159
+ import { statSync } from "fs";
160
+ import { createInterface as createInterface2 } from "readline";
161
+
162
+ // src/core/logger.ts
163
+ import { AsyncLocalStorage } from "async_hooks";
164
+ import { createWriteStream, mkdirSync } from "fs";
165
+ import { open, readdir, rm, stat } from "fs/promises";
166
+ import { join as join2 } from "path";
167
+
168
+ // src/config/paths.ts
169
+ import { homedir } from "os";
170
+ import { join } from "path";
171
+ var appDir = join(homedir(), ".lark-channel");
172
+ var paths = {
173
+ appDir,
174
+ cacheDir: appDir,
175
+ configFile: join(appDir, "config.json"),
176
+ sessionsFile: join(appDir, "sessions.json"),
177
+ workspacesFile: join(appDir, "workspaces.json"),
178
+ processesFile: join(appDir, "processes.json"),
179
+ secretsFile: join(appDir, "secrets.enc"),
180
+ keystoreSaltFile: join(appDir, ".keystore.salt"),
181
+ /**
182
+ * Thin shell wrapper that lark-cli (and other openclaw-exec-protocol
183
+ * consumers) invoke to resolve secrets from the bridge's encrypted store.
184
+ * Written user-owned and non-symlinked so it passes lark-cli's
185
+ * AssertSecurePath audit on machines where `node` is a Homebrew/Volta
186
+ * symlink or root-owned (`/usr/bin/node`). Wrapper internals do the
187
+ * `node ... secrets get` invocation; lark-cli only audits the wrapper.
188
+ */
189
+ secretsGetterScript: join(appDir, "secrets-getter"),
190
+ mediaDir: join(appDir, "media")
191
+ };
192
+ var legacyPaths = {
193
+ appDir: join(
194
+ process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"),
195
+ "lark-channel-bridge"
196
+ ),
197
+ cacheDir: join(
198
+ process.env.XDG_CACHE_HOME ?? join(homedir(), ".cache"),
199
+ "lark-channel-bridge"
200
+ )
201
+ };
202
+
203
+ // src/core/logger.ts
204
+ var LOG_RETENTION_DAYS = Math.max(
205
+ 1,
206
+ Number(process.env.LARK_CHANNEL_LOG_DAYS ?? 7) || 7
207
+ );
208
+ var als = new AsyncLocalStorage();
209
+
210
+ // src/agent/claude/adapter.ts
211
+ import { spawn } from "child_process";
212
+ import { createInterface } from "readline";
213
+ var BRIDGE_SYSTEM_PROMPT = `# lark-agent-bridge \u8FD0\u884C\u7EA6\u5B9A
214
+
215
+ \u4F60\u6B63\u5728 lark-agent-bridge \u91CC\u8DD1\uFF1A\u628A\u98DE\u4E66/Lark \u7528\u6237\u6D88\u606F\u6865\u5230\u672C\u5730\u547D\u4EE4\u884C coding agent\u3002
216
+
217
+ ## bridge_context
218
+
219
+ \u6BCF\u6761 user message \u9876\u90E8\u4F1A\u5E26\u4E00\u4E2A \`<bridge_context>\` \u5757\uFF1A
220
+
221
+ \`\`\`
222
+ <bridge_context>
223
+ chat_id: oc_xxx
224
+ chat_type: p2p
225
+ sender_id: ou_xxx
226
+ sender_name: ...
227
+ </bridge_context>
228
+ \`\`\`
229
+
230
+ \u91CC\u9762\u662F\u5F53\u524D\u5BF9\u8BDD\u7684 chat_id\u3001chat \u7C7B\u578B\uFF08p2p / group\uFF09\u3001\u53D1\u9001\u8005\u3002\u8FD9\u4E9B\u662F bridge \u6CE8\u5165\u7684\u5143\u6570\u636E\uFF0C**\u4E0D\u8981\u7167\u6284\u3001\u4E0D\u8981\u5728\u4F60\u7684\u56DE\u590D\u91CC\u6E32\u67D3**\u2014\u2014\u5B83\u5BF9\u7528\u6237\u4E0D\u53EF\u89C1\u3002
231
+
232
+ ## quoted_message
233
+
234
+ \u5982\u679C\u7528\u6237\u7528"\u5F15\u7528\u56DE\u590D"\u6307\u5411\u67D0\u6761\u6D88\u606F\uFF0Cbridge \u4F1A\u5728 \`<bridge_context>\` \u540E\u6CE8\u5165\u4E00\u4E2A \`<quoted_message>\` \u5757\uFF1A
235
+
236
+ \`\`\`
237
+ <quoted_message id="om_xxx" sender_id="ou_xxx" sender_name="..." created_at="..." type="text|merge_forward|...">
238
+ \uFF08\u88AB\u5F15\u7528\u6D88\u606F\u7684\u5185\u5BB9\uFF1Bmerge_forward \u7C7B\u578B\u4F1A\u5C55\u5F00\u6210 <forwarded_messages>...</forwarded_messages>\uFF09
239
+ </quoted_message>
240
+ \`\`\`
241
+
242
+ \u8FD9\u662F\u7528\u6237**\u6307\u5411\u7684\u5BF9\u8C61**\u2014\u2014\u7528\u6237\u7684\u5B9E\u9645\u95EE\u9898\u5728\u5B83\u4E4B\u540E\u3002\u56DE\u7B54\u65F6\u56F4\u7ED5\u8FD9\u6BB5\u5185\u5BB9\u5C55\u5F00\uFF1B\u5B83\u4E5F\u662F bridge \u6CE8\u5165\u7684\u5143\u6570\u636E\uFF0C**\u4E0D\u8981\u7167\u6284 XML \u6807\u7B7E**\u5230\u56DE\u590D\u91CC\u3002
243
+
244
+ ## \u53D1\u4EA4\u4E92\u5361\u7247\uFF08\u6309\u94AE\u3001\u8868\u5355\uFF09\u7684\u56DE\u8C03\u7EA6\u5B9A
245
+
246
+ \u4F60\u60F3\u53D1\u4E00\u5F20\u53EF\u4EA4\u4E92\u7684\u5361\u7247\u8BA9\u7528\u6237\u70B9\u9009\u65F6\uFF1A
247
+
248
+ 1. \u7528 \`lark-cli\` \u628A\u5361\u53D1\u5230 \`bridge_context.chat_id\`\uFF1A
249
+ \`lark-cli im send-card --chat-id <chat_id> --card '<json>'\`
250
+ 2. \u5361\u7247\u7528 CardKit 2.0 schema\uFF08\`schema: "2.0"\`\uFF09\u3002
251
+ 3. **\u5982\u679C\u4F60\u5E0C\u671B\u7528\u6237\u70B9\u6309\u94AE\u540E\u56DE\u8C03\u5230\u4F60\uFF08\u8BA9\u4F60\u5728\u540C\u4E00\u4F1A\u8BDD\u91CC\u7EE7\u7EED\u5904\u7406\uFF09**\uFF1A
252
+ - \u6309\u94AE\u7684 \`value\` \u5BF9\u8C61**\u5FC5\u987B**\u5305\u542B \`__claude_cb: true\`
253
+ - \u540C\u65F6\u53EF\u4EE5\u585E\u4EFB\u610F\u5176\u5B83\u5B57\u6BB5\uFF0C\u4F5C\u4E3A\u4F60\u9700\u8981\u5728\u56DE\u8C03\u65F6\u8BB0\u4F4F\u7684\u72B6\u6001\uFF08\u6BD4\u5982 \`{"__claude_cb": true, "choice": "a", "ticket_id": "T-123"}\`\uFF09
254
+ 4. \u7528\u6237\u70B9\u51FB\u540E\uFF0Cbridge \u4F1A\u628A payload\uFF08\u53BB\u6389 \`__claude_cb\` marker\uFF09\u4F5C\u4E3A \`[card-click] {...}\` \u6D88\u606F\u53D1\u56DE\u7ED9\u4F60\uFF1B\u4F60\u7684 session \u81EA\u52A8\u7EED\u4E0A\uFF0C\u80FD\u770B\u5230\u81EA\u5DF1\u4E0A\u8F6E\u53D1\u4E86\u4EC0\u4E48\u5361\u3002
255
+ 5. **\u5982\u679C\u53EA\u662F\u5C55\u793A\u5361\uFF08\u4E0D\u9700\u8981\u56DE\u8C03\uFF09**\uFF0C\u4E0D\u8981\u52A0 \`__claude_cb\`\uFF0C\u5426\u5219\u70B9\u51FB\u5C31\u4F1A\u89E6\u53D1\u989D\u5916\u7684\u4F1A\u8BDD\u8F6E\u6B21\u3002
256
+
257
+ \u793A\u4F8B button\uFF1A
258
+ \`\`\`json
259
+ {
260
+ "tag": "button",
261
+ "text": { "tag": "plain_text", "content": "\u65B9\u6848 A" },
262
+ "behaviors": [{
263
+ "type": "callback",
264
+ "value": { "__claude_cb": true, "choice": "a" }
265
+ }]
266
+ }
267
+ \`\`\`
268
+
269
+ ## \u98DE\u4E66 OAuth \u6388\u6743\uFF08\`lark-cli auth login\`\uFF09
270
+
271
+ \u6388\u6743\u6D41\u7A0B\u8981\u8BA9 \`lark-cli\` \u8FDB\u7A0B\u4E00\u76F4\u6D3B\u5230\u7528\u6237\u5728\u6D4F\u89C8\u5668\u91CC\u70B9\u5B8C\u4E3A\u6B62\u3002bridge \u5728\u4F60\u7684 run \u7ED3\u675F\u4E4B\u540E\u4F1A\u56DE\u6536 claude\uFF0C**\u4F60 spawn \u7684\u4EFB\u4F55\u540E\u53F0 bash \u4E5F\u4F1A\u8DDF\u7740\u6B7B**\u2014\u2014\u6240\u4EE5\u6388\u6743\u5FC5\u987B\u7528"\u524D\u53F0\u963B\u585E"\u7684\u65B9\u5F0F\u8DD1\uFF1A
272
+
273
+ 1. **\u4EC5\u5728 p2p \u91CC\u53D1\u8D77\u6388\u6743**\u3002\u4ECE \`bridge_context.chat_type\` \u770B\uFF1A
274
+ - \`chat_type: p2p\` \u2014\u2014 \u6B63\u5E38\u6309\u4E0B\u9762\u6D41\u7A0B\u8D70\u3002
275
+ - \`chat_type: group\`\uFF08\u542B topic \u7FA4\uFF09\u2014\u2014 **\u4E0D\u8981**\u8C03 \`lark-cli auth login\`\u3002device flow \u628A \`verification_url\` \u53D1\u5230\u7FA4\u91CC\uFF0C\u8C01\u5148\u70B9\u8C01\u62FF\u8D70 token\u2014\u2014\u4F1A\u7ED1\u5B9A\u5230\u9519\u7684\u8EAB\u4EFD\u3002\u6B63\u786E\u505A\u6CD5\u662F\u56DE\u590D\u7528\u6237\uFF1A"\u6388\u6743\u8981\u5728\u79C1\u804A\u91CC\u505A\uFF0C\u8BF7\u5355\u72EC\u79C1\u4FE1\u6211\u3002"
276
+ 2. **\u7981\u6B62** \u7528 \`run_in_background: true\` \u8C03 \`lark-cli auth login\`\u2014\u2014\u5B83\u4F1A\u88AB\u4F60 exit \u65F6\u4E00\u8D77\u5E26\u8D70\uFF0C\u7528\u6237\u8FD8\u6CA1\u70B9\u5B8C\u5C31\u4E22\u4E86\u3002
277
+ 3. **\u63A8\u8350\u4E24\u9636\u6BB5\u6D41**\uFF08lark-cli \u5728 \`--no-wait\` \u7684\u8F93\u51FA\u91CC\u4E5F\u4F1A\u544A\u8BC9\u4F60\u8FD9\u5957\uFF09\uFF1A
278
+ - \u5148\u8DD1 \`lark-cli auth login --no-wait --json [--recommend | --domain ... | --scope ...]\`\uFF0C**\u8FD9\u4E00\u6B65\u79D2\u8FD4\u56DE**\uFF0Cstdout \u91CC\u6709 \`verification_url\` \u548C \`device_code\`\u3002
279
+ - \u628A \`verification_url\` **\u539F\u6837**\u7528\u4EE3\u7801\u5757\u53D1\u7ED9\u7528\u6237\uFF08\u4E0D\u8981 Markdown \u94FE\u63A5\u5316\u3001\u4E0D\u8981 URL \u7F16\u7801\uFF09\u3002
280
+ - \u7D27\u63A5\u7740\u540C\u4E00\u8F6E\u91CC\u8DD1 \`lark-cli auth login --device-code <code>\`\uFF0C**\u8FD9\u4E00\u6B65\u524D\u53F0\u963B\u585E**\u76F4\u5230\u7528\u6237\u70B9\u5B8C\u6216 10 \u5206\u949F\u8D85\u65F6\u2014\u2014\u8FD9\u662F\u4F60\u5E94\u8BE5\u7B49\u7684\u5730\u65B9\uFF0C\u4E0D\u8981\u4E22\u5230\u540E\u53F0\u3002
281
+ 4. \u4F60\u524D\u53F0\u963B\u585E\u671F\u95F4\uFF0C\u7528\u6237\u53D1\u7684\u65B0\u6D88\u606F bridge \u4F1A\u81EA\u52A8\u6392\u961F\uFF0C**\u4E0D\u4F1A\u6253\u65AD\u4F60**\uFF1B\u7B49\u4F60 tool_result \u4E00\u56DE\u6765\uFF0C\u4E0B\u4E00\u6279\u6D88\u606F\u518D\u8FDB\u6765\u3002\u6240\u4EE5\u653E\u5FC3\u963B\u585E\u3002
282
+ 5. \u5982\u679C\u7528\u6237\u4E2D\u9014\u60F3\u53D6\u6D88\uFF0C\u4ED6\u4EEC\u4F1A\u53D1 \`/stop\`\u2014\u2014\u90A3\u65F6\u88AB kill \u662F\u9884\u671F\u884C\u4E3A\uFF0C\u4E0D\u7528\u515C\u5E95\u3002
283
+ `;
284
+
285
+ // src/agent/cursor/spawn-run.ts
286
+ function buildCursorPrompt(prompt) {
287
+ return `<bridge_system_prompt>
288
+ ${BRIDGE_SYSTEM_PROMPT}
289
+ </bridge_system_prompt>
290
+
291
+ <user_prompt>
292
+ ${prompt}
293
+ </user_prompt>`;
294
+ }
295
+
296
+ // src/agent/cursor/sdk-translate.ts
297
+ function* translateSdkMessage(msg) {
298
+ if (msg.type === "system" && msg.subtype === "init") {
299
+ yield {
300
+ type: "system",
301
+ sessionId: msg.agent_id,
302
+ model: typeof msg.model?.id === "string" ? msg.model.id : void 0
303
+ };
304
+ return;
305
+ }
306
+ if (msg.type === "thinking" && typeof msg.text === "string" && msg.text) {
307
+ yield { type: "thinking", delta: msg.text };
308
+ return;
309
+ }
310
+ if (msg.type === "status" && typeof msg.status === "string") {
311
+ yield {
312
+ type: "progress",
313
+ phase: phaseForSdkStatus(msg.status),
314
+ label: labelForSdkStatus(msg.status, msg.text)
315
+ };
316
+ return;
317
+ }
318
+ if (msg.type === "task") {
319
+ const label = typeof msg.text === "string" && msg.text.trim() ? msg.text : msg.status;
320
+ if (typeof label === "string" && label.trim()) {
321
+ yield { type: "progress", phase: "thinking", label };
322
+ }
323
+ return;
324
+ }
325
+ if (msg.type === "assistant" && msg.message?.content) {
326
+ for (const block of msg.message.content) {
327
+ if (block.type === "text" && typeof block.text === "string" && block.text) {
328
+ yield { type: "text", delta: block.text };
329
+ }
330
+ if (block.type === "tool_use" && block.id && block.name) {
331
+ yield { type: "tool_use", id: block.id, name: block.name, input: block.input ?? {} };
332
+ }
333
+ }
334
+ return;
335
+ }
336
+ if (msg.type === "tool_call" && msg.call_id && msg.name) {
337
+ if (msg.status === "running") {
338
+ yield { type: "tool_use", id: msg.call_id, name: msg.name, input: msg.args ?? {} };
339
+ } else if (msg.status === "completed" || msg.status === "error") {
340
+ yield {
341
+ type: "tool_result",
342
+ id: msg.call_id,
343
+ output: stringifyResult(msg.result),
344
+ isError: msg.status === "error" || isErrorResult(msg.result)
345
+ };
346
+ }
347
+ }
348
+ }
349
+ function phaseForSdkStatus(status) {
350
+ switch (status) {
351
+ case "CREATING":
352
+ return "starting";
353
+ case "FINISHED":
354
+ return "streaming";
355
+ case "RUNNING":
356
+ case "ERROR":
357
+ case "CANCELLED":
358
+ case "EXPIRED":
359
+ default:
360
+ return "thinking";
361
+ }
362
+ }
363
+ function labelForSdkStatus(status, message) {
364
+ if (typeof message === "string" && message.trim()) return message;
365
+ switch (status) {
366
+ case "CREATING":
367
+ return "\u6B63\u5728\u521B\u5EFA Agent";
368
+ case "RUNNING":
369
+ return "Agent \u6B63\u5728\u8FD0\u884C";
370
+ case "FINISHED":
371
+ return "Agent \u6B63\u5728\u6536\u5C3E";
372
+ case "ERROR":
373
+ return "Agent \u72B6\u6001\u5F02\u5E38";
374
+ case "CANCELLED":
375
+ return "Agent \u5DF2\u53D6\u6D88";
376
+ case "EXPIRED":
377
+ return "Agent \u5DF2\u8FC7\u671F";
378
+ default:
379
+ return `Agent \u72B6\u6001: ${status}`;
380
+ }
381
+ }
382
+ function stringifyResult(result) {
383
+ if (typeof result === "string") return result;
384
+ if (result === void 0) return "";
385
+ try {
386
+ return JSON.stringify(result);
387
+ } catch {
388
+ return String(result);
389
+ }
390
+ }
391
+ function isErrorResult(result) {
392
+ if (!result || typeof result !== "object") return false;
393
+ const record = result;
394
+ return record.error === true || record.is_error === true || typeof record.error === "string";
395
+ }
396
+
397
+ // src/agent/cursor/sdk-worker.ts
398
+ function readConfig() {
399
+ const raw = process.env.LARK_CURSOR_SDK_CONFIG;
400
+ if (!raw) return void 0;
401
+ try {
402
+ return JSON.parse(raw);
403
+ } catch {
404
+ return void 0;
405
+ }
406
+ }
407
+ var config = readConfig();
408
+ var agent;
409
+ var agentCwd;
410
+ var activeRunId;
411
+ var activeAbort;
412
+ var ensureQueue = Promise.resolve();
413
+ var runQueue = Promise.resolve();
414
+ var pendingRunRecoveryNotes = [];
415
+ var RATE_LIMIT_RETRY_DELAYS_MS = [1e3, 2500, 5e3];
416
+ var RECOVERY_NOTE_MAX = 6;
417
+ function send(msg) {
418
+ if (typeof process.send === "function") process.send(msg);
419
+ }
420
+ function reportWorkerError(phase, err, runId, recoveryNotes = [], fatal = false) {
421
+ process.stderr.write(`${formatSdkErrorForStderr(phase, err)}
422
+ `);
423
+ send({
424
+ type: "error",
425
+ id: runId,
426
+ message: withWorkerRecoveryHint(withRecoverySummary(formatSdkErrorForIpc(phase, err), recoveryNotes), fatal),
427
+ fatal
428
+ });
429
+ }
430
+ async function withRecoverableRetry(label, task, recoveryNotes) {
431
+ for (let attempt = 0; ; attempt++) {
432
+ try {
433
+ return await task();
434
+ } catch (err) {
435
+ const delayMs = RATE_LIMIT_RETRY_DELAYS_MS[attempt];
436
+ const kind = isCursorRateLimitError(err) ? "\u9650\u6D41" : isCursorNetworkError(err) ? "\u7F51\u7EDC\u9519\u8BEF" : void 0;
437
+ if (delayMs === void 0 || !kind) throw err;
438
+ addRecoveryNote(
439
+ recoveryNotes,
440
+ `${label} \u9047\u5230${kind}\uFF0C\u5DF2\u81EA\u52A8\u91CD\u8BD5 ${attempt + 1}/${RATE_LIMIT_RETRY_DELAYS_MS.length} \u6B21`
441
+ );
442
+ process.stderr.write(
443
+ `[sdk-worker] ${label} recoverable ${kind}; retrying in ${delayMs}ms (attempt ${attempt + 2})
444
+ `
445
+ );
446
+ await sleep(delayMs);
447
+ }
448
+ }
449
+ }
450
+ function agentOptions(cwd) {
451
+ return {
452
+ ...config?.apiKey ? { apiKey: config.apiKey } : {},
453
+ model: config.model,
454
+ local: { cwd }
455
+ };
456
+ }
457
+ function queueEnsure(task) {
458
+ ensureQueue = ensureQueue.then(task).catch((err) => {
459
+ reportWorkerError("sdk ensure failed", err);
460
+ });
461
+ }
462
+ function queueRun(id, task) {
463
+ runQueue = runQueue.then(task).catch((err) => {
464
+ reportWorkerError("sdk run queue failed", err, id);
465
+ });
466
+ }
467
+ async function ensureAgent(id, cwd, agentId, allowReplacement = true) {
468
+ if (!config) {
469
+ send({ type: "error", id, message: "sdk worker config missing" });
470
+ return;
471
+ }
472
+ if (agent && agent.agentId === agentId) {
473
+ send({ type: "agent", id, agentId: agent.agentId });
474
+ return;
475
+ }
476
+ if (agent) {
477
+ try {
478
+ agent.close();
479
+ } catch {
480
+ }
481
+ agent = void 0;
482
+ }
483
+ const opts = agentOptions(cwd);
484
+ const recoveryNotes = [];
485
+ try {
486
+ if (agentId) {
487
+ try {
488
+ agent = await withRecoverableRetry("Agent.resume", () => Agent.resume(agentId, opts), recoveryNotes);
489
+ } catch (err) {
490
+ if (!isCursorAgentNotFoundError(err, agentId)) throw err;
491
+ if (!allowReplacement) {
492
+ addRecoveryNote(
493
+ recoveryNotes,
494
+ `\u539F SDK session \u4E0D\u53EF\u6062\u590D\uFF0C\u672A\u81EA\u52A8\u521B\u5EFA replacement session`
495
+ );
496
+ throw err;
497
+ }
498
+ process.stderr.write(
499
+ `[sdk-worker] stale SDK agent ${agentId}; creating a replacement session
500
+ `
501
+ );
502
+ addRecoveryNote(
503
+ recoveryNotes,
504
+ `\u65E7 SDK session \u4E0D\u53EF\u6062\u590D\uFF0C\u5DF2\u81EA\u52A8\u521B\u5EFA replacement session`
505
+ );
506
+ agent = await withRecoverableRetry("Agent.create", () => Agent.create(opts), recoveryNotes);
507
+ }
508
+ } else {
509
+ agent = await withRecoverableRetry("Agent.create", () => Agent.create(opts), recoveryNotes);
510
+ }
511
+ agentCwd = cwd;
512
+ if (id.startsWith("ensure-")) stashRunRecoveryNotes(recoveryNotes);
513
+ send({ type: "agent", id, agentId: agent.agentId });
514
+ } catch (err) {
515
+ reportWorkerError("sdk agent init failed", err, id);
516
+ }
517
+ }
518
+ async function sendPromptWithStaleSessionRecovery(id, prompt, recoveryNotes, allowReplacement = true) {
519
+ if (!agent) throw new Error("sdk worker agent not initialized");
520
+ try {
521
+ return await withRecoverableRetry("agent.send", () => agent.send(buildCursorPrompt(prompt)), recoveryNotes);
522
+ } catch (err) {
523
+ const staleAgentId = agent.agentId;
524
+ if (!agentCwd || !isCursorAgentActiveRunError(err, staleAgentId)) throw err;
525
+ if (!allowReplacement) {
526
+ addRecoveryNote(
527
+ recoveryNotes,
528
+ `\u539F SDK session \u4ECD\u6709 active run\uFF0C\u672A\u81EA\u52A8\u521B\u5EFA replacement session`
529
+ );
530
+ throw err;
531
+ }
532
+ const replacementCwd = agentCwd;
533
+ process.stderr.write(
534
+ `[sdk-worker] SDK agent ${staleAgentId} still has an active run; creating a replacement session
535
+ `
536
+ );
537
+ addRecoveryNote(
538
+ recoveryNotes,
539
+ `\u68C0\u6D4B\u5230\u65E7 SDK session \u4ECD\u6709 active run\uFF0C\u5DF2\u81EA\u52A8\u521B\u5EFA replacement session`
540
+ );
541
+ try {
542
+ agent.close();
543
+ } catch {
544
+ }
545
+ agent = await withRecoverableRetry("Agent.create", () => Agent.create(agentOptions(replacementCwd)), recoveryNotes);
546
+ send({ type: "event", id, event: { type: "system", sessionId: agent.agentId, cwd: replacementCwd } });
547
+ return await withRecoverableRetry("agent.send", () => agent.send(buildCursorPrompt(prompt)), recoveryNotes);
548
+ }
549
+ }
550
+ function sleep(ms) {
551
+ return new Promise((resolve) => setTimeout(resolve, ms));
552
+ }
553
+ async function handleRun(id, prompt, allowReplacement = true) {
554
+ if (!agent) {
555
+ send({ type: "error", id, message: "sdk worker agent not initialized" });
556
+ return;
557
+ }
558
+ if (activeRunId) {
559
+ send({ type: "error", id, message: "run already active in sdk worker" });
560
+ return;
561
+ }
562
+ activeRunId = id;
563
+ const recoveryNotes = consumeRunRecoveryNotes();
564
+ let cancelled = false;
565
+ activeAbort = () => {
566
+ cancelled = true;
567
+ };
568
+ try {
569
+ const run = await sendPromptWithStaleSessionRecovery(id, prompt, recoveryNotes, allowReplacement);
570
+ activeAbort = () => {
571
+ cancelled = true;
572
+ void run.cancel().catch(() => {
573
+ });
574
+ };
575
+ try {
576
+ for await (const msg of run.stream()) {
577
+ if (cancelled) break;
578
+ for (const event of translateSdkMessage(msg)) {
579
+ send({ type: "event", id, event });
580
+ }
581
+ }
582
+ } catch (streamErr) {
583
+ reportWorkerError("sdk run stream failed", streamErr, id, recoveryNotes, true);
584
+ return;
585
+ }
586
+ if (cancelled) {
587
+ send({ type: "error", id, message: "run cancelled" });
588
+ return;
589
+ }
590
+ const result = await run.wait();
591
+ if (result.status === "error") {
592
+ const message = withWorkerRecoveryHint(withRecoverySummary(formatRunResultError(result), recoveryNotes), true);
593
+ process.stderr.write(`[sdk-worker] ${message}
594
+ `);
595
+ send({
596
+ type: "error",
597
+ id,
598
+ message,
599
+ fatal: true
600
+ });
601
+ return;
602
+ }
603
+ send({ type: "done", id, agentId: agent.agentId });
604
+ } catch (err) {
605
+ reportWorkerError("sdk run failed", err, id, recoveryNotes, true);
606
+ } finally {
607
+ activeRunId = void 0;
608
+ activeAbort = void 0;
609
+ }
610
+ }
611
+ function formatRunResultError(result) {
612
+ const headline = `sdk run failed (runId=${result.id}, status=${result.status})`;
613
+ if (typeof result.result === "string" && result.result.trim()) {
614
+ return `${headline}: ${result.result.trim()}`;
615
+ }
616
+ const diagnostic = safeJson({
617
+ id: result.id,
618
+ status: result.status,
619
+ result: result.result
620
+ });
621
+ return `${headline}; Cursor returned no error detail${diagnostic ? ` | result=${diagnostic}` : ""}`;
622
+ }
623
+ function safeJson(value) {
624
+ try {
625
+ return JSON.stringify(value).slice(0, 1200);
626
+ } catch {
627
+ return "";
628
+ }
629
+ }
630
+ function addRecoveryNote(notes, note) {
631
+ if (!notes || notes.includes(note)) return;
632
+ notes.push(note);
633
+ if (notes.length > RECOVERY_NOTE_MAX) notes.splice(0, notes.length - RECOVERY_NOTE_MAX);
634
+ }
635
+ function stashRunRecoveryNotes(notes) {
636
+ for (const note of notes) addRecoveryNote(pendingRunRecoveryNotes, note);
637
+ }
638
+ function consumeRunRecoveryNotes() {
639
+ const notes = pendingRunRecoveryNotes;
640
+ pendingRunRecoveryNotes = [];
641
+ return notes;
642
+ }
643
+ function withRecoverySummary(message, recoveryNotes) {
644
+ if (recoveryNotes.length === 0) return message;
645
+ return [
646
+ `\u5DF2\u81EA\u52A8\u6062\u590D/\u91CD\u8BD5 ${recoveryNotes.length} \u6B65\uFF1A`,
647
+ ...recoveryNotes.map((note) => `- ${note}`),
648
+ "",
649
+ `\u6700\u7EC8\u5931\u8D25\u539F\u56E0\uFF1A${message}`
650
+ ].join("\n");
651
+ }
652
+ function withWorkerRecoveryHint(message, fatal) {
653
+ if (!fatal) return message;
654
+ return `${message}
655
+
656
+ \u5DF2\u81EA\u52A8\u4E22\u5F03\u5F53\u524D SDK worker\u3002bridge \u4F1A\u4F18\u5148\u7528\u539F session \u521B\u5EFA\u65B0 worker \u5E76\u7EE7\u7EED\u4E00\u6B21\uFF1B\u82E5\u539F session \u4E0D\u53EF\u6062\u590D\u6216\u4ECD\u6709 active run\uFF0C\u5C06\u505C\u6B62\u81EA\u52A8\u7EE7\u7EED\uFF0C\u4FDD\u7559\u4E00\u952E\u91CD\u8BD5/\u65B0 session \u5165\u53E3\u3002`;
657
+ }
658
+ process.on("uncaughtException", (err) => {
659
+ reportWorkerError("uncaughtException", err, activeRunId, [], true);
660
+ activeRunId = void 0;
661
+ activeAbort = void 0;
662
+ });
663
+ process.on("unhandledRejection", (reason) => {
664
+ reportWorkerError("unhandledRejection", reason, activeRunId, [], true);
665
+ activeRunId = void 0;
666
+ activeAbort = void 0;
667
+ });
668
+ process.on("message", (msg) => {
669
+ if (!msg || typeof msg !== "object") return;
670
+ switch (msg.type) {
671
+ case "ensure":
672
+ if (agent && msg.agentId !== void 0 && agent.agentId === msg.agentId) {
673
+ send({ type: "agent", id: msg.id, agentId: agent.agentId });
674
+ return;
675
+ }
676
+ queueEnsure(() => ensureAgent(msg.id, msg.cwd, msg.agentId, msg.allowReplacement));
677
+ return;
678
+ case "run":
679
+ queueRun(msg.id, () => handleRun(msg.id, msg.prompt, msg.allowReplacement));
680
+ return;
681
+ case "stop":
682
+ if (activeRunId === msg.id) activeAbort?.();
683
+ return;
684
+ case "shutdown":
685
+ if (activeRunId) activeAbort?.();
686
+ if (agent) {
687
+ try {
688
+ agent.close();
689
+ } catch {
690
+ }
691
+ }
692
+ process.exit(0);
693
+ return;
694
+ default:
695
+ return;
696
+ }
697
+ });
698
+ if (config) {
699
+ send({ type: "ready" });
700
+ } else {
701
+ send({ type: "error", message: "sdk worker config missing" });
702
+ }