patchwork-os 0.2.0-beta.10 → 0.2.0-beta.10.canary.101

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 (151) hide show
  1. package/dist/bridge.js +17 -10
  2. package/dist/bridge.js.map +1 -1
  3. package/dist/commands/connect.d.ts +47 -0
  4. package/dist/commands/connect.js +419 -0
  5. package/dist/commands/connect.js.map +1 -0
  6. package/dist/commands/recipe.d.ts +45 -4
  7. package/dist/commands/recipe.js +141 -4
  8. package/dist/commands/recipe.js.map +1 -1
  9. package/dist/commands/task.d.ts +25 -0
  10. package/dist/commands/task.js +61 -41
  11. package/dist/commands/task.js.map +1 -1
  12. package/dist/commands/tracesExport.d.ts +15 -1
  13. package/dist/commands/tracesExport.js +39 -5
  14. package/dist/commands/tracesExport.js.map +1 -1
  15. package/dist/connectorRoutes.js +556 -0
  16. package/dist/connectorRoutes.js.map +1 -1
  17. package/dist/connectors/connectorRegistry.d.ts +0 -3
  18. package/dist/connectors/connectorRegistry.js +8 -8
  19. package/dist/connectors/connectorRegistry.js.map +1 -1
  20. package/dist/connectors/datadog.js +8 -1
  21. package/dist/connectors/datadog.js.map +1 -1
  22. package/dist/connectors/jira.js +7 -2
  23. package/dist/connectors/jira.js.map +1 -1
  24. package/dist/connectors/mcpClient.js +37 -23
  25. package/dist/connectors/mcpClient.js.map +1 -1
  26. package/dist/connectors/notion.d.ts +1 -1
  27. package/dist/connectors/notion.js +13 -4
  28. package/dist/connectors/notion.js.map +1 -1
  29. package/dist/connectors/redis.js +10 -2
  30. package/dist/connectors/redis.js.map +1 -1
  31. package/dist/connectors/snowflake.js +18 -0
  32. package/dist/connectors/snowflake.js.map +1 -1
  33. package/dist/decisionReplay.d.ts +8 -6
  34. package/dist/decisionReplay.js +35 -11
  35. package/dist/decisionReplay.js.map +1 -1
  36. package/dist/drivers/claude/api.js +28 -5
  37. package/dist/drivers/claude/api.js.map +1 -1
  38. package/dist/drivers/claude/subprocess.js +47 -13
  39. package/dist/drivers/claude/subprocess.js.map +1 -1
  40. package/dist/drivers/local/index.d.ts +2 -17
  41. package/dist/drivers/local/index.js +5 -92
  42. package/dist/drivers/local/index.js.map +1 -1
  43. package/dist/fp/automationInterpreter.js +57 -12
  44. package/dist/fp/automationInterpreter.js.map +1 -1
  45. package/dist/fp/policyParser.js +5 -1
  46. package/dist/fp/policyParser.js.map +1 -1
  47. package/dist/index.js +154 -83
  48. package/dist/index.js.map +1 -1
  49. package/dist/localEndpointGuard.d.ts +25 -0
  50. package/dist/localEndpointGuard.js +101 -0
  51. package/dist/localEndpointGuard.js.map +1 -0
  52. package/dist/orchestrator/childBridgeClient.d.ts +5 -0
  53. package/dist/orchestrator/childBridgeClient.js +28 -1
  54. package/dist/orchestrator/childBridgeClient.js.map +1 -1
  55. package/dist/orchestrator/orchestratorBridge.d.ts +33 -0
  56. package/dist/orchestrator/orchestratorBridge.js +70 -9
  57. package/dist/orchestrator/orchestratorBridge.js.map +1 -1
  58. package/dist/recipes/chainedRunner.js +14 -4
  59. package/dist/recipes/chainedRunner.js.map +1 -1
  60. package/dist/recipes/compiler.js +9 -5
  61. package/dist/recipes/compiler.js.map +1 -1
  62. package/dist/recipes/dependencyGraph.d.ts +9 -0
  63. package/dist/recipes/dependencyGraph.js +19 -2
  64. package/dist/recipes/dependencyGraph.js.map +1 -1
  65. package/dist/recipes/githubInstallSource.d.ts +9 -2
  66. package/dist/recipes/githubInstallSource.js +36 -6
  67. package/dist/recipes/githubInstallSource.js.map +1 -1
  68. package/dist/recipes/idempotencyKey.d.ts +23 -3
  69. package/dist/recipes/idempotencyKey.js +57 -4
  70. package/dist/recipes/idempotencyKey.js.map +1 -1
  71. package/dist/recipes/installer.js +10 -1
  72. package/dist/recipes/installer.js.map +1 -1
  73. package/dist/recipes/parser.js +28 -1
  74. package/dist/recipes/parser.js.map +1 -1
  75. package/dist/recipes/schema.d.ts +29 -2
  76. package/dist/recipes/schemaGenerator.js +16 -2
  77. package/dist/recipes/schemaGenerator.js.map +1 -1
  78. package/dist/recipes/toolRegistry.js +13 -4
  79. package/dist/recipes/toolRegistry.js.map +1 -1
  80. package/dist/recipes/tools/airtable.d.ts +15 -0
  81. package/dist/recipes/tools/airtable.js +239 -0
  82. package/dist/recipes/tools/airtable.js.map +1 -0
  83. package/dist/recipes/tools/circleci.d.ts +10 -0
  84. package/dist/recipes/tools/circleci.js +203 -0
  85. package/dist/recipes/tools/circleci.js.map +1 -0
  86. package/dist/recipes/tools/grafana.d.ts +11 -0
  87. package/dist/recipes/tools/grafana.js +215 -0
  88. package/dist/recipes/tools/grafana.js.map +1 -0
  89. package/dist/recipes/tools/index.d.ts +11 -0
  90. package/dist/recipes/tools/index.js +11 -0
  91. package/dist/recipes/tools/index.js.map +1 -1
  92. package/dist/recipes/tools/pipedrive.d.ts +16 -0
  93. package/dist/recipes/tools/pipedrive.js +233 -0
  94. package/dist/recipes/tools/pipedrive.js.map +1 -0
  95. package/dist/recipes/tools/posthog.d.ts +16 -0
  96. package/dist/recipes/tools/posthog.js +218 -0
  97. package/dist/recipes/tools/posthog.js.map +1 -0
  98. package/dist/recipes/tools/resend.d.ts +8 -0
  99. package/dist/recipes/tools/resend.js +152 -0
  100. package/dist/recipes/tools/resend.js.map +1 -0
  101. package/dist/recipes/tools/sendgrid.d.ts +9 -0
  102. package/dist/recipes/tools/sendgrid.js +174 -0
  103. package/dist/recipes/tools/sendgrid.js.map +1 -0
  104. package/dist/recipes/tools/shopify.d.ts +16 -0
  105. package/dist/recipes/tools/shopify.js +265 -0
  106. package/dist/recipes/tools/shopify.js.map +1 -0
  107. package/dist/recipes/tools/todoist.d.ts +15 -0
  108. package/dist/recipes/tools/todoist.js +227 -0
  109. package/dist/recipes/tools/todoist.js.map +1 -0
  110. package/dist/recipes/tools/twilio.d.ts +11 -0
  111. package/dist/recipes/tools/twilio.js +179 -0
  112. package/dist/recipes/tools/twilio.js.map +1 -0
  113. package/dist/recipes/tools/vercel.d.ts +9 -0
  114. package/dist/recipes/tools/vercel.js +145 -0
  115. package/dist/recipes/tools/vercel.js.map +1 -0
  116. package/dist/recipes/validation.js +112 -0
  117. package/dist/recipes/validation.js.map +1 -1
  118. package/dist/recipes/yamlRunner.d.ts +3 -0
  119. package/dist/recipes/yamlRunner.js +112 -29
  120. package/dist/recipes/yamlRunner.js.map +1 -1
  121. package/dist/schemas/recipe.v1.json +2 -2
  122. package/dist/telemetry.js +20 -9
  123. package/dist/telemetry.js.map +1 -1
  124. package/dist/tools/getGitStatus.js +6 -1
  125. package/dist/tools/getGitStatus.js.map +1 -1
  126. package/dist/tools/getToolCapabilities.js +39 -4
  127. package/dist/tools/getToolCapabilities.js.map +1 -1
  128. package/dist/tools/github/composite.d.ts +1 -1
  129. package/dist/tools/github/composite.js +7 -7
  130. package/dist/tools/github/composite.js.map +1 -1
  131. package/dist/tools/github/pr.d.ts +6 -6
  132. package/dist/tools/github/pr.js +18 -11
  133. package/dist/tools/github/pr.js.map +1 -1
  134. package/dist/tools/index.js +14 -10
  135. package/dist/tools/index.js.map +1 -1
  136. package/dist/tools/previewEdit.js +16 -1
  137. package/dist/tools/previewEdit.js.map +1 -1
  138. package/dist/tools/searchAndReplace.js +4 -5
  139. package/dist/tools/searchAndReplace.js.map +1 -1
  140. package/dist/tools/searchTools.d.ts +26 -0
  141. package/dist/tools/searchTools.js +42 -2
  142. package/dist/tools/searchTools.js.map +1 -1
  143. package/dist/tools/transaction.d.ts +9 -1
  144. package/dist/tools/transaction.js +59 -4
  145. package/dist/tools/transaction.js.map +1 -1
  146. package/dist/tools/utils.d.ts +15 -0
  147. package/dist/tools/utils.js +19 -0
  148. package/dist/tools/utils.js.map +1 -1
  149. package/dist/transport.js +23 -0
  150. package/dist/transport.js.map +1 -1
  151. package/package.json +1 -1
@@ -17,14 +17,37 @@
17
17
  * the rule match is tool-name-only. Noted in the result via `incomplete`.
18
18
  */
19
19
  import { evaluateRules, loadCcPermissions } from "./ccPermissions.js";
20
+ /**
21
+ * Decide whether two decisions are equivalent for replay purposes.
22
+ *
23
+ * A `replay` of "none" (no current rule matched) is treated as unchanged when
24
+ * the original was "allow" or "deny" — absence of an explicit rule defaults to
25
+ * the same effective outcome the user already saw, so it is not a real flip.
26
+ */
27
+ function isUnchanged(original, replay) {
28
+ return (replay === original ||
29
+ (replay === "none" && original === "allow") ||
30
+ (replay === "none" && original === "deny"));
31
+ }
32
+ /**
33
+ * Bucket a CHANGED row by its NEW (replay) outcome. Keyed purely off the replay
34
+ * direction so every changed row maps to exactly one bucket and the three
35
+ * bucket counts always sum to changedCount:
36
+ * - replay "allow" → now_allowed
37
+ * - replay "ask" → now_asked
38
+ * - replay "deny"/"none" → now_denied (effectively blocked)
39
+ *
40
+ * Returns undefined for unchanged rows (no bucket).
41
+ */
20
42
  function changeKind(original, replay) {
21
- if (replay === "allow" && original !== "allow")
43
+ if (isUnchanged(original, replay))
44
+ return undefined;
45
+ if (replay === "allow")
22
46
  return "now_allowed";
23
- if ((replay === "deny" || replay === "none") && original === "allow")
24
- return "now_denied";
25
- if (replay === "ask" && original !== "ask")
47
+ if (replay === "ask")
26
48
  return "now_asked";
27
- return undefined;
49
+ // A changed row whose replay is "deny" or "none" is effectively now blocked.
50
+ return "now_denied";
28
51
  }
29
52
  export function computeDecisionReplay(activityLog, opts) {
30
53
  const { workspace, sinceMs = 0, limit = 500 } = opts;
@@ -60,9 +83,8 @@ export function computeDecisionReplay(activityLog, opts) {
60
83
  }
61
84
  const incomplete = specifier === undefined;
62
85
  const replay = evaluateRules(toolName, specifier, rules);
63
- const unchanged = replay === originalDecision ||
64
- (replay === "none" && originalDecision === "allow") ||
65
- (replay === "none" && originalDecision === "deny");
86
+ const unchanged = isUnchanged(originalDecision, replay);
87
+ const kind = changeKind(originalDecision, replay);
66
88
  rows.push({
67
89
  timestamp: entry.timestamp,
68
90
  toolName,
@@ -70,15 +92,14 @@ export function computeDecisionReplay(activityLog, opts) {
70
92
  originalDecision,
71
93
  replayDecision: replay,
72
94
  unchanged,
73
- ...(changeKind(originalDecision, replay) !== undefined && {
74
- changeKind: changeKind(originalDecision, replay),
75
- }),
95
+ ...(kind !== undefined && { changeKind: kind }),
76
96
  ...(incomplete && { incomplete: true }),
77
97
  });
78
98
  }
79
99
  let changedCount = 0;
80
100
  let nowAllowedCount = 0;
81
101
  let nowDeniedCount = 0;
102
+ let nowAskedCount = 0;
82
103
  for (const r of rows) {
83
104
  if (r.unchanged)
84
105
  continue;
@@ -87,6 +108,8 @@ export function computeDecisionReplay(activityLog, opts) {
87
108
  nowAllowedCount++;
88
109
  else if (r.changeKind === "now_denied")
89
110
  nowDeniedCount++;
111
+ else if (r.changeKind === "now_asked")
112
+ nowAskedCount++;
90
113
  }
91
114
  return {
92
115
  rows,
@@ -95,6 +118,7 @@ export function computeDecisionReplay(activityLog, opts) {
95
118
  changedCount,
96
119
  nowAllowedCount,
97
120
  nowDeniedCount,
121
+ nowAskedCount,
98
122
  workspace,
99
123
  };
100
124
  }
@@ -1 +1 @@
1
- {"version":3,"file":"decisionReplay.js","sourceRoot":"","sources":["../src/decisionReplay.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"decisionReplay.js","sourceRoot":"","sources":["../src/decisionReplay.ts"],"names":[],"mappings":"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"}
@@ -32,11 +32,34 @@ export class ApiDriver {
32
32
  .join("\n")}\n--- END CONTEXT FILE LIST ---`
33
33
  : "";
34
34
  this.log("[ApiDriver] sending request to Anthropic API");
35
- const message = await client.messages.create({
36
- model: input.model ?? "claude-haiku-4-5-20251001",
37
- max_tokens: 4096,
38
- messages: [{ role: "user", content: input.prompt + contextNote }],
39
- }, { signal: input.signal });
35
+ // ProviderDriver contract (types.ts): run() must resolve, never reject —
36
+ // swallow auth/429/network/abort errors into the result. messages.create
37
+ // rejects on all of these, so wrap it and translate into an errorMessage
38
+ // (or wasAborted for an abort/cancellation), mirroring OpenAIApiDriver.run.
39
+ let message;
40
+ try {
41
+ message = await client.messages.create({
42
+ model: input.model ?? "claude-haiku-4-5-20251001",
43
+ max_tokens: 4096,
44
+ messages: [{ role: "user", content: input.prompt + contextNote }],
45
+ }, { signal: input.signal });
46
+ }
47
+ catch (err) {
48
+ const isAbort = (err instanceof Error && err.name === "AbortError") ||
49
+ input.signal.aborted;
50
+ if (isAbort) {
51
+ return {
52
+ text: "",
53
+ durationMs: Date.now() - start,
54
+ wasAborted: true,
55
+ };
56
+ }
57
+ return {
58
+ text: "",
59
+ durationMs: Date.now() - start,
60
+ errorMessage: err instanceof Error ? err.message : String(err),
61
+ };
62
+ }
40
63
  // biome-ignore lint/suspicious/noExplicitAny: message is from dynamically imported optional dep
41
64
  const content = message.content;
42
65
  let text = "";
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/drivers/claude/api.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,CAAC;AAE7B;;;GAGG;AACH,MAAM,OAAO,SAAS;IAGS;IAFpB,IAAI,GAAG,KAAK,CAAC;IAEtB,YAA6B,GAA0B;QAA1B,QAAG,GAAH,GAAG,CAAuB;QACrD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CACb,2DAA2D,CAC5D,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAwB;QAChC,kFAAkF;QAClF,IAAI,aAA4B,CAAC;QACjC,IAAI,CAAC;YACH,6DAA6D;YAC7D,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,mBAA0B,CAAC,CAAC;YACrD,6DAA6D;YAC7D,aAAa,GAAI,GAAW,CAAC,OAAO,IAAI,GAAG,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CACb,uFAAuF,CACxF,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEzB,MAAM,WAAW,GACf,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;YACjD,CAAC,CAAC,0EAA0E,KAAK,CAAC,YAAY;iBACzF,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;iBAC3D,IAAI,CAAC,IAAI,CAAC,iCAAiC;YAChD,CAAC,CAAC,EAAE,CAAC;QAET,IAAI,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAEzD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAC1C;YACE,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,2BAA2B;YACjD,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC;SAClE,EACD,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CACzB,CAAC;QAEF,gGAAgG;QAChG,MAAM,OAAO,GAAI,OAAe,CAAC,OAG/B,CAAC;QACH,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,KAAK,MAAM,CAAC,IAAI,OAAiD,EAAE,CAAC;YAClE,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;gBAAE,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;QAC9C,CAAC;QAED,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;QAEtB,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC;YAC/B,QAAQ,EAAE,CAAC;YACX,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;SAC/B,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/drivers/claude/api.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,35 @@ import { sanitizeEnv } from "./envSanitizer.js";
9
9
  import { parseStreamLine, splitLines } from "./streamParser.js";
10
10
  import { createSubprocessSettings } from "./subprocessSettings.js";
11
11
  const OUTPUT_CAP = 50 * 1024; // 50KB
12
+ /**
13
+ * Truncate `text` to at most `cap` UTF-8 bytes without splitting a multi-byte
14
+ * codepoint mid-sequence. `String.slice(0, cap)` operates on UTF-16 code
15
+ * units, so a 50K cap can store ~50K code points but emit up to ~200KB of
16
+ * UTF-8 wire bytes for CJK / emoji content — and may produce a lone surrogate
17
+ * at the boundary. `Buffer.toString("utf8")` substitutes U+FFFD for incomplete
18
+ * trailing sequences instead.
19
+ */
20
+ function truncateUtf8Bytes(text, cap) {
21
+ const buf = Buffer.from(text, "utf8");
22
+ if (buf.length <= cap)
23
+ return text;
24
+ return buf.subarray(0, cap).toString("utf8");
25
+ }
26
+ /**
27
+ * Truncate `text` so it adds at most `remaining` UTF-8 bytes to the stream and
28
+ * never splits a multi-byte codepoint mid-sequence. Returns the safely-
29
+ * truncated slice plus its actual byte length so the running byte total can be
30
+ * advanced correctly.
31
+ */
32
+ function truncateToBytes(text, remaining) {
33
+ const buf = Buffer.from(text, "utf8");
34
+ if (buf.length <= remaining)
35
+ return { send: text, bytes: buf.length };
36
+ // Buffer.toString("utf8") substitutes U+FFFD for incomplete trailing
37
+ // sequences, which is the correct UTF-8 truncation behavior.
38
+ const sliced = buf.subarray(0, remaining).toString("utf8");
39
+ return { send: sliced, bytes: Buffer.byteLength(sliced, "utf8") };
40
+ }
12
41
  /**
13
42
  * Write a single-server MCP config to a 0600 temp file, return the path.
14
43
  * Caller passes path via `--mcp-config <path>` to claude -p.
@@ -188,10 +217,10 @@ export class SubprocessDriver {
188
217
  if (parsed.kind === "raw") {
189
218
  accumulated += parsed.text;
190
219
  if (outputBytesSent < OUTPUT_CAP) {
191
- const send = parsed.text.slice(0, OUTPUT_CAP - outputBytesSent);
192
- if (send.length > 0) {
220
+ const { send, bytes } = truncateToBytes(parsed.text, OUTPUT_CAP - outputBytesSent);
221
+ if (bytes > 0) {
193
222
  input.onChunk?.(send);
194
- outputBytesSent += send.length;
223
+ outputBytesSent += bytes;
195
224
  }
196
225
  }
197
226
  continue;
@@ -203,10 +232,10 @@ export class SubprocessDriver {
203
232
  if (text.length > 0) {
204
233
  accumulated += text;
205
234
  if (outputBytesSent < OUTPUT_CAP) {
206
- const send = text.slice(0, OUTPUT_CAP - outputBytesSent);
207
- if (send.length > 0) {
235
+ const { send, bytes } = truncateToBytes(text, OUTPUT_CAP - outputBytesSent);
236
+ if (bytes > 0) {
208
237
  input.onChunk?.(send);
209
- outputBytesSent += send.length;
238
+ outputBytesSent += bytes;
210
239
  }
211
240
  }
212
241
  }
@@ -221,10 +250,15 @@ export class SubprocessDriver {
221
250
  let stderr = "";
222
251
  child.stderr.setEncoding("utf-8");
223
252
  child.stderr.on("data", (chunk) => {
224
- if (stderr.length < OUTPUT_CAP) {
253
+ // Apply the same byte-budget cap to stderr to prevent unbounded memory
254
+ // growth on multi-byte UTF-8 output. Counting via Buffer.byteLength /
255
+ // truncateUtf8Bytes keeps the cap a true byte budget rather than a
256
+ // UTF-16 code-unit budget.
257
+ if (Buffer.byteLength(stderr, "utf8") < OUTPUT_CAP) {
225
258
  stderr += chunk;
226
- if (stderr.length > OUTPUT_CAP)
227
- stderr = stderr.slice(0, OUTPUT_CAP);
259
+ if (Buffer.byteLength(stderr, "utf8") > OUTPUT_CAP) {
260
+ stderr = truncateUtf8Bytes(stderr, OUTPUT_CAP);
261
+ }
228
262
  }
229
263
  });
230
264
  const start = Date.now();
@@ -251,7 +285,7 @@ export class SubprocessDriver {
251
285
  clearTimeout(startupHandle);
252
286
  if (doneFromResult) {
253
287
  return {
254
- text: resultText.slice(0, OUTPUT_CAP),
288
+ text: truncateUtf8Bytes(resultText, OUTPUT_CAP),
255
289
  exitCode: resultIsError ? 1 : 0,
256
290
  durationMs: Date.now() - start,
257
291
  stderrTail: stderrTailOf(stderr),
@@ -262,7 +296,7 @@ export class SubprocessDriver {
262
296
  input.signal.aborted;
263
297
  if (isAbort) {
264
298
  return {
265
- text: accumulated.slice(0, OUTPUT_CAP),
299
+ text: truncateUtf8Bytes(accumulated, OUTPUT_CAP),
266
300
  exitCode: -1,
267
301
  durationMs: Date.now() - start,
268
302
  stderrTail: stderrTailOf(stderr),
@@ -282,7 +316,7 @@ export class SubprocessDriver {
282
316
  const finalText = doneFromResult ? resultText : accumulated;
283
317
  if (startupTimedOut) {
284
318
  return {
285
- text: accumulated.slice(0, OUTPUT_CAP),
319
+ text: truncateUtf8Bytes(accumulated, OUTPUT_CAP),
286
320
  exitCode: -1,
287
321
  durationMs: Date.now() - start,
288
322
  stderrTail: stderrTailOf(stderr),
@@ -294,7 +328,7 @@ export class SubprocessDriver {
294
328
  this.log(`[SubprocessDriver] stderr: ${stderr.slice(0, 500)}`);
295
329
  }
296
330
  return {
297
- text: finalText.slice(0, OUTPUT_CAP),
331
+ text: truncateUtf8Bytes(finalText, OUTPUT_CAP),
298
332
  exitCode: effectiveExitCode,
299
333
  durationMs: Date.now() - start,
300
334
  stderrTail: stderrTailOf(stderr),
@@ -1 +1 @@
1
- {"version":3,"file":"subprocess.js","sourceRoot":"","sources":["../../../src/drivers/claude/subprocess.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"subprocess.js","sourceRoot":"","sources":["../../../src/drivers/claude/subprocess.ts"],"names":[],"mappings":"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"}
@@ -1,21 +1,6 @@
1
+ import { isLoopbackOrPrivateEndpoint } from "../../localEndpointGuard.js";
1
2
  import { OpenAIApiDriver } from "../openai/index.js";
2
- /**
3
- * Reject any LOCAL_ENDPOINT that doesn't resolve to loopback or RFC1918
4
- * private space. The local driver streams the user prompt + context-file
5
- * paths to whatever URL is set; if a malicious recipe (or a user pasting
6
- * a phishy "free local LLM" link) sets `LOCAL_ENDPOINT=https://attacker/v1`,
7
- * everything the local driver receives gets exfiltrated.
8
- *
9
- * Rule: hostname must be one of
10
- * - localhost / 127.0.0.1 / ::1
11
- * - RFC1918 private space (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
12
- * - link-local (169.254.0.0/16, fe80::/10)
13
- * - .local mDNS / .lan / .home / .internal suffixes
14
- *
15
- * To opt out (e.g. authorized remote inference cluster), the operator can
16
- * set LOCAL_ENDPOINT_ALLOW_REMOTE=1 — explicit override, audited via env.
17
- */
18
- export declare function isLoopbackOrPrivateEndpoint(rawUrl: string): boolean;
3
+ export { isLoopbackOrPrivateEndpoint };
19
4
  /**
20
5
  * Local LLM driver — Ollama, LM Studio, vLLM, llama.cpp server, and most
21
6
  * other self-hosted runtimes expose an OpenAI-compatible chat-completions
@@ -1,96 +1,9 @@
1
+ import { isLoopbackOrPrivateEndpoint } from "../../localEndpointGuard.js";
1
2
  import { OpenAIApiDriver } from "../openai/index.js";
2
- /**
3
- * Reject any LOCAL_ENDPOINT that doesn't resolve to loopback or RFC1918
4
- * private space. The local driver streams the user prompt + context-file
5
- * paths to whatever URL is set; if a malicious recipe (or a user pasting
6
- * a phishy "free local LLM" link) sets `LOCAL_ENDPOINT=https://attacker/v1`,
7
- * everything the local driver receives gets exfiltrated.
8
- *
9
- * Rule: hostname must be one of
10
- * - localhost / 127.0.0.1 / ::1
11
- * - RFC1918 private space (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
12
- * - link-local (169.254.0.0/16, fe80::/10)
13
- * - .local mDNS / .lan / .home / .internal suffixes
14
- *
15
- * To opt out (e.g. authorized remote inference cluster), the operator can
16
- * set LOCAL_ENDPOINT_ALLOW_REMOTE=1 — explicit override, audited via env.
17
- */
18
- export function isLoopbackOrPrivateEndpoint(rawUrl) {
19
- let host;
20
- let wasBracketed = false;
21
- try {
22
- host = new URL(rawUrl).hostname.toLowerCase();
23
- }
24
- catch {
25
- return false;
26
- }
27
- if (!host)
28
- return false;
29
- // Strip IPv6 brackets if any
30
- if (host.startsWith("[") && host.endsWith("]")) {
31
- host = host.slice(1, -1);
32
- wasBracketed = true;
33
- }
34
- if (host === "localhost" || host === "127.0.0.1" || host === "::1") {
35
- return true;
36
- }
37
- // IPv4 RFC1918 + link-local + 127/8 (check first — strict literal match)
38
- const v4 = host.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
39
- if (v4) {
40
- const a = Number(v4[1]);
41
- const b = Number(v4[2]);
42
- if (a === 10)
43
- return true;
44
- if (a === 127)
45
- return true;
46
- if (a === 169 && b === 254)
47
- return true;
48
- if (a === 172 && b >= 16 && b <= 31)
49
- return true;
50
- if (a === 192 && b === 168)
51
- return true;
52
- return false;
53
- }
54
- // IPv6 ranges — only when the input looked like an IPv6 literal (was
55
- // bracketed in the URL, or matches an IPv6 syntactic shape). Without this
56
- // gate, a hostname like `fc-services.example.com` or `fe8a-test` would
57
- // match the legacy `startsWith("fc")` / `startsWith("fe8")` checks and
58
- // bypass the validator. RFC3986 allows IPv6 literals only inside `[…]`,
59
- // so requiring the brackets is the conservative path.
60
- if (wasBracketed || /^[0-9a-f:]+$/.test(host)) {
61
- if (host.startsWith("fe8") ||
62
- host.startsWith("fe9") ||
63
- host.startsWith("fea") ||
64
- host.startsWith("feb")) {
65
- return true; // link-local fe80::/10
66
- }
67
- if (host.startsWith("fc") || host.startsWith("fd")) {
68
- return true; // unique-local fc00::/7
69
- }
70
- }
71
- // mDNS / common LAN suffixes — checked LAST and require a leading dot
72
- // boundary so attacker-registered public domains like `evil.com.local`
73
- // don't slip through (`.local` and `.lan` are not reserved TLDs at the
74
- // DNS resolver level — only RFC6762 reserves them for mDNS, but public
75
- // resolvers will happily look them up).
76
- //
77
- // The trade-off: a host literally named `printer.local` (single label
78
- // before `.local`) is the legitimate mDNS form and matches; a host like
79
- // `evil.com.local` (two-or-more labels before `.local`) is only the
80
- // mDNS form by accident and is the bypass we're rejecting.
81
- for (const suffix of [".local", ".lan", ".home", ".internal"]) {
82
- if (host.endsWith(suffix)) {
83
- const labels = host.split(".");
84
- // 2 labels exactly: `<name>.local` — legitimate mDNS shape.
85
- if (labels.length === 2)
86
- return true;
87
- // More labels: ambiguous — refuse by default. Operator can opt out
88
- // via LOCAL_ENDPOINT_ALLOW_REMOTE for legitimate multi-label
89
- // internal DNS zones (e.g. `service.team.internal`).
90
- }
91
- }
92
- return false;
93
- }
3
+ // Re-export so existing importers (`import { isLoopbackOrPrivateEndpoint }
4
+ // from ".../drivers/local/index.js"`) keep working after the predicate moved
5
+ // to the shared `src/localEndpointGuard.ts` module.
6
+ export { isLoopbackOrPrivateEndpoint };
94
7
  /**
95
8
  * Local LLM driver — Ollama, LM Studio, vLLM, llama.cpp server, and most
96
9
  * other self-hosted runtimes expose an OpenAI-compatible chat-completions
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/drivers/local/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/drivers/local/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,2EAA2E;AAC3E,6EAA6E;AAC7E,oDAAoD;AACpD,OAAO,EAAE,2BAA2B,EAAE,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,cAAe,SAAQ,eAAe;IAC/B,IAAI,GAAG,OAAO,CAAC;IAEjC,YAAY,GAA0B;QACpC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,8FAA8F,CAC/F,CAAC;QACJ,CAAC;QACD,IACE,OAAO,CAAC,GAAG,CAAC,2BAA2B,KAAK,GAAG;YAC/C,CAAC,2BAA2B,CAAC,OAAO,CAAC,EACrC,CAAC;YACD,MAAM,IAAI,KAAK,CACb,mCAAmC,OAAO,gCAAgC;gBACxE,yEAAyE;gBACzE,uEAAuE;gBACvE,iDAAiD,CACpD,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,GAAG,EAAE;YACT,OAAO;YACP,mEAAmE;YACnE,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,UAAU;SACpD,CAAC,CAAC;IACL,CAAC;IAEkB,MAAM;QACvB,mEAAmE;QACnE,6DAA6D;QAC7D,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,QAAQ,CAAC;IAC/C,CAAC;CACF"}
@@ -225,6 +225,27 @@ function buildFinalPrompt(promptTemplate, hookType, eventData, nonce) {
225
225
  }
226
226
  return truncatePrompt(meta + resolved);
227
227
  }
228
+ /**
229
+ * Resolve `{{placeholder}}` tokens in a WithCooldown key against the live
230
+ * `eventData` at interpret time. Lets a hook scope its cooldown bucket per
231
+ * dynamic value — e.g. `recipesave:{{file}}` cools down only the saved file,
232
+ * not every recipe. Keys without any `{{…}}` token pass through unchanged, so
233
+ * every other hook's cooldown behaviour is untouched.
234
+ *
235
+ * Sanitised to a stable map-key shape: control chars stripped, length capped,
236
+ * unresolved placeholders collapse to `*` so a missing value still produces a
237
+ * deterministic bucket (rather than leaking the raw `{{file}}` literal).
238
+ */
239
+ function resolveCooldownKey(key, eventData) {
240
+ if (!key.includes("{{"))
241
+ return key;
242
+ return key.replace(/\{\{(\w+)\}\}/g, (_m, name) => {
243
+ const val = eventData[name];
244
+ if (val === undefined || val === "")
245
+ return "*";
246
+ return val.replace(/[\x00-\x1F\x7F]/g, "").slice(0, 256);
247
+ });
248
+ }
228
249
  // ── Interpreter ───────────────────────────────────────────────────────────────
229
250
  async function interpret(program, ctx, acc) {
230
251
  switch (program._tag) {
@@ -463,15 +484,19 @@ async function interpret(program, ctx, acc) {
463
484
  return current;
464
485
  }
465
486
  case "WithCooldown": {
466
- if (isOnCooldown(acc.state, program.key, ctx.now, program.cooldownMs)) {
487
+ // Resolve any `{{placeholder}}` in the cooldown key against the live
488
+ // event so a per-file hook (e.g. onRecipeSave → `recipesave:{{file}}`)
489
+ // gets its OWN cooldown bucket. Static keys pass through unchanged.
490
+ const cooldownKey = resolveCooldownKey(program.key, ctx.eventData);
491
+ if (isOnCooldown(acc.state, cooldownKey, ctx.now, program.cooldownMs)) {
467
492
  const hookLabel = program.program._tag === "Hook"
468
493
  ? program.program.hookType
469
- : program.key;
494
+ : cooldownKey;
470
495
  return {
471
496
  ...acc,
472
497
  skipped: [
473
498
  ...acc.skipped,
474
- { reason: `cooldown:${program.key}`, hook: hookLabel },
499
+ { reason: `cooldown:${cooldownKey}`, hook: hookLabel },
475
500
  ],
476
501
  };
477
502
  }
@@ -495,11 +520,11 @@ async function interpret(program, ctx, acc) {
495
520
  }
496
521
  if (newTaskIds.length > 0) {
497
522
  const lastTaskId = newTaskIds[newTaskIds.length - 1] ?? "";
498
- const newState = recordTrigger(innerAcc.state, program.key, lastTaskId, ctx.now);
523
+ const newState = recordTrigger(innerAcc.state, cooldownKey, lastTaskId, ctx.now);
499
524
  return { ...innerAcc, state: newState };
500
525
  }
501
526
  if (webhookFired) {
502
- const newState = recordTrigger(innerAcc.state, program.key, "webhook", ctx.now);
527
+ const newState = recordTrigger(innerAcc.state, cooldownKey, "webhook", ctx.now);
503
528
  return { ...innerAcc, state: newState };
504
529
  }
505
530
  return innerAcc;
@@ -554,8 +579,17 @@ async function interpret(program, ctx, acc) {
554
579
  if (attempt < program.maxRetries) {
555
580
  const nextAttempt = attempt + 1;
556
581
  const nextRetryAt = ctx.now + program.retryDelayMs;
557
- // Schedule retry: re-run the wrapped program when the timer
558
- // fires. The work runs INSIDE AutomationHooks' mutation lock
582
+ // Schedule retry: re-run the WithRetry NODE (not just its wrapped
583
+ // child) when the timer fires. Re-entering the WithRetry case is
584
+ // what lets each successive failure re-check `attempt < maxRetries`
585
+ // and schedule the next retry — running only `program.program`
586
+ // capped retries at 1 because the inner program never re-enters
587
+ // this branch. The interpret() result already carries the
588
+ // pendingRetries bookkeeping the node performs (record on
589
+ // re-schedule, clear on success/exhaustion), so the retry returns
590
+ // it as-is rather than force-clearing.
591
+ //
592
+ // The work runs INSIDE AutomationHooks' mutation lock
559
593
  // (`runRetryUnderLock`) so:
560
594
  // 1. Read of live state is atomic w.r.t. concurrent _runInterpreter
561
595
  // calls — the retry sees their cooldown / dedup / rateLimit
@@ -563,15 +597,14 @@ async function interpret(program, ctx, acc) {
563
597
  // 2. Write of post-retry state is atomic w.r.t. the same chain,
564
598
  // so the retry's effects can't be lost to a concurrent run
565
599
  // that started between scheduling and merge.
566
- // 3. `clearPendingRetry` is in a try/finally so the
567
- // pendingRetries entry is dropped even if the inner
600
+ // 3. The catch clears the pendingRetries entry even if the inner
568
601
  // interpret() throws (otherwise the retry leaks the entry
569
602
  // forever).
570
603
  //
571
604
  // TestBackend records the call but does not actually fire the timer.
572
605
  // Tests that exercise retry dispatch synchronously override
573
606
  // `scheduleRetry`.
574
- const wrappedProgram = program.program;
607
+ const retryProgram = program;
575
608
  const retrySnapshot = innerAcc.state;
576
609
  const liveStateFn = ctx.getLiveState;
577
610
  const runUnderLock = ctx.runRetryUnderLock;
@@ -584,8 +617,12 @@ async function interpret(program, ctx, acc) {
584
617
  state: live,
585
618
  now: Date.now(),
586
619
  };
587
- const retryResult = await interpret(wrappedProgram, retryCtx, emptyAcc(live));
588
- return clearPendingRetry(retryResult.state, program.key);
620
+ // Re-enter the WithRetry node so a repeated failure can
621
+ // schedule the next attempt (up to maxRetries). The node
622
+ // owns the pendingRetries lifecycle — return its state
623
+ // directly so a re-scheduled attempt isn't force-cleared.
624
+ const retryResult = await interpret(retryProgram, retryCtx, emptyAcc(live));
625
+ return retryResult.state;
589
626
  }
590
627
  catch (e) {
591
628
  const m = e instanceof Error ? e.message : String(e);
@@ -612,6 +649,14 @@ async function interpret(program, ctx, acc) {
612
649
  const newState = recordPendingRetry(innerAcc.state, program.key, nextAttempt, nextRetryAt, "");
613
650
  return { ...innerAcc, state: newState };
614
651
  }
652
+ // Retries exhausted (attempt >= maxRetries): the inner program still
653
+ // failed but no further retry is scheduled. Drop the pendingRetries
654
+ // entry so it doesn't leak and block a future, unrelated retry for
655
+ // the same key.
656
+ return {
657
+ ...innerAcc,
658
+ state: clearPendingRetry(innerAcc.state, program.key),
659
+ };
615
660
  }
616
661
  return innerAcc;
617
662
  }