@probelabs/visor 0.1.149 → 0.1.150

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 (123) hide show
  1. package/README.md +52 -1
  2. package/dist/909.index.js +27117 -0
  3. package/dist/ai-review-service.d.ts.map +1 -1
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/docs/assistant-workflows.md +805 -0
  6. package/dist/docs/event-triggers.md +25 -0
  7. package/dist/docs/scheduler.md +156 -0
  8. package/dist/docs/slack-integration.md +48 -0
  9. package/dist/enterprise/scheduler/knex-store.d.ts +7 -1
  10. package/dist/enterprise/scheduler/knex-store.d.ts.map +1 -1
  11. package/dist/examples/code-talk-as-tool.yaml +76 -0
  12. package/dist/examples/code-talk-workflow.yaml +68 -0
  13. package/dist/examples/intent-router-workflow.yaml +66 -0
  14. package/dist/examples/slack-message-triggers.yaml +270 -0
  15. package/dist/generated/config-schema.d.ts +102 -7
  16. package/dist/generated/config-schema.d.ts.map +1 -1
  17. package/dist/generated/config-schema.json +116 -7
  18. package/dist/git-repository-analyzer.d.ts +8 -0
  19. package/dist/git-repository-analyzer.d.ts.map +1 -1
  20. package/dist/index.js +4030 -4735
  21. package/dist/output/traces/{run-2026-03-03T07-19-07-543Z.ndjson → run-2026-03-03T20-21-24-501Z.ndjson} +84 -84
  22. package/dist/{traces/run-2026-03-03T07-19-50-933Z.ndjson → output/traces/run-2026-03-03T20-22-08-701Z.ndjson} +1806 -1730
  23. package/dist/scheduler/message-trigger.d.ts +47 -0
  24. package/dist/scheduler/message-trigger.d.ts.map +1 -0
  25. package/dist/scheduler/schedule-store.d.ts +31 -1
  26. package/dist/scheduler/schedule-store.d.ts.map +1 -1
  27. package/dist/scheduler/schedule-tool.d.ts +17 -1
  28. package/dist/scheduler/schedule-tool.d.ts.map +1 -1
  29. package/dist/scheduler/store/sqlite-store.d.ts +7 -1
  30. package/dist/scheduler/store/sqlite-store.d.ts.map +1 -1
  31. package/dist/scheduler/store/types.d.ts +45 -0
  32. package/dist/scheduler/store/types.d.ts.map +1 -1
  33. package/dist/sdk/{check-provider-registry-LVLC4EPF.mjs → check-provider-registry-6D5CAX44.mjs} +6 -6
  34. package/dist/sdk/{check-provider-registry-X4OZJWPK.mjs → check-provider-registry-RRYBG6AU.mjs} +6 -6
  35. package/dist/sdk/{check-provider-registry-IYSUDKPB.mjs → check-provider-registry-YFC5KSJY.mjs} +6 -6
  36. package/dist/sdk/{chunk-V6GI4U2M.mjs → chunk-AADKUA6L.mjs} +585 -29
  37. package/dist/sdk/{chunk-6EXCUX7Y.mjs.map → chunk-AADKUA6L.mjs.map} +1 -1
  38. package/dist/sdk/{chunk-6EXCUX7Y.mjs → chunk-CKDFGNF4.mjs} +585 -29
  39. package/dist/sdk/{chunk-GFNXX64M.mjs.map → chunk-CKDFGNF4.mjs.map} +1 -1
  40. package/dist/sdk/{chunk-YYZAN5NK.mjs → chunk-FYK2DJK6.mjs} +106 -9
  41. package/dist/sdk/chunk-FYK2DJK6.mjs.map +1 -0
  42. package/dist/sdk/{chunk-RJLJUTSU.mjs → chunk-FZEQ744M.mjs} +2 -2
  43. package/dist/sdk/{chunk-Q6EPAJ6Z.mjs → chunk-GIAN7HCT.mjs} +3 -3
  44. package/dist/sdk/{chunk-CISJ6DJW.mjs → chunk-GLROSEYJ.mjs} +3 -3
  45. package/dist/sdk/{chunk-VLUGLWLA.mjs → chunk-H4HFH7HH.mjs} +3 -3
  46. package/dist/sdk/{chunk-VLUGLWLA.mjs.map → chunk-H4HFH7HH.mjs.map} +1 -1
  47. package/dist/sdk/{chunk-62TNF5PJ.mjs → chunk-PETLPNRA.mjs} +2 -2
  48. package/dist/sdk/{chunk-62TNF5PJ.mjs.map → chunk-PETLPNRA.mjs.map} +1 -1
  49. package/dist/sdk/{chunk-BR7DYA3S.mjs → chunk-SWO4W57C.mjs} +2 -2
  50. package/dist/sdk/{chunk-GFNXX64M.mjs → chunk-YY3KADY2.mjs} +585 -29
  51. package/dist/sdk/{chunk-V6GI4U2M.mjs.map → chunk-YY3KADY2.mjs.map} +1 -1
  52. package/dist/sdk/{config-KQH254CA.mjs → config-MTEIGCOQ.mjs} +2 -2
  53. package/dist/sdk/{failure-condition-evaluator-IVCTD4BZ.mjs → failure-condition-evaluator-P6QUFLIN.mjs} +3 -3
  54. package/dist/sdk/{failure-condition-evaluator-LZ2AG5PY.mjs → failure-condition-evaluator-XV2ZMFFY.mjs} +3 -3
  55. package/dist/sdk/{git-repository-analyzer-QFMW6WIS.mjs → git-repository-analyzer-TWNJUN42.mjs} +34 -3
  56. package/dist/sdk/git-repository-analyzer-TWNJUN42.mjs.map +1 -0
  57. package/dist/sdk/{github-frontend-DFT5G32K.mjs → github-frontend-A2R7D4N6.mjs} +3 -3
  58. package/dist/sdk/{github-frontend-S523EEJB.mjs → github-frontend-GSB2P5PE.mjs} +3 -3
  59. package/dist/sdk/{host-7YKRMOUJ.mjs → host-CLPM2WVQ.mjs} +2 -2
  60. package/dist/sdk/{host-H7IX4GBK.mjs → host-MR7L57QI.mjs} +2 -2
  61. package/dist/sdk/{routing-LU5PAREW.mjs → routing-KLVK2MJZ.mjs} +4 -4
  62. package/dist/sdk/{routing-ZMBKWMVI.mjs → routing-V3MYZAOH.mjs} +4 -4
  63. package/dist/sdk/{schedule-tool-EOMZFICZ.mjs → schedule-tool-HYM55K3H.mjs} +6 -6
  64. package/dist/sdk/{schedule-tool-NX75VKGA.mjs → schedule-tool-NYLNJUEW.mjs} +6 -6
  65. package/dist/sdk/{schedule-tool-CDVUSZEG.mjs → schedule-tool-PRXFAV4K.mjs} +6 -6
  66. package/dist/sdk/{schedule-tool-handler-3FJHDIPG.mjs → schedule-tool-handler-EFQIYD3W.mjs} +6 -6
  67. package/dist/sdk/{schedule-tool-handler-KKN7XJYT.mjs → schedule-tool-handler-HVWCEGQ6.mjs} +6 -6
  68. package/dist/sdk/{schedule-tool-handler-QNZG55DX.mjs → schedule-tool-handler-M5YI573R.mjs} +6 -6
  69. package/dist/sdk/sdk.d.mts +38 -1
  70. package/dist/sdk/sdk.d.ts +38 -1
  71. package/dist/sdk/sdk.js +706 -22
  72. package/dist/sdk/sdk.js.map +1 -1
  73. package/dist/sdk/sdk.mjs +5 -5
  74. package/dist/sdk/{trace-helpers-EJUIOP6L.mjs → trace-helpers-6NSZBC35.mjs} +2 -2
  75. package/dist/sdk/{trace-helpers-6ROJR7N3.mjs → trace-helpers-TORF3JD5.mjs} +2 -2
  76. package/dist/sdk/{workflow-check-provider-AGZ5JY2I.mjs → workflow-check-provider-3F6CBHVD.mjs} +6 -6
  77. package/dist/sdk/{workflow-check-provider-PTNUWM5W.mjs → workflow-check-provider-OXHMLICJ.mjs} +6 -6
  78. package/dist/sdk/{workflow-check-provider-6ERNNCNA.mjs → workflow-check-provider-XLH7N4FV.mjs} +6 -6
  79. package/dist/slack/socket-runner.d.ts +14 -0
  80. package/dist/slack/socket-runner.d.ts.map +1 -1
  81. package/dist/test-runner/core/flow-stage.d.ts.map +1 -1
  82. package/dist/test-runner/fixture-loader.d.ts +1 -1
  83. package/dist/test-runner/fixture-loader.d.ts.map +1 -1
  84. package/dist/test-runner/index.d.ts.map +1 -1
  85. package/dist/test-runner/validator.d.ts.map +1 -1
  86. package/dist/traces/{run-2026-03-03T07-19-07-543Z.ndjson → run-2026-03-03T20-21-24-501Z.ndjson} +84 -84
  87. package/dist/{output/traces/run-2026-03-03T07-19-50-933Z.ndjson → traces/run-2026-03-03T20-22-08-701Z.ndjson} +1806 -1730
  88. package/dist/types/config.d.ts +38 -1
  89. package/dist/types/config.d.ts.map +1 -1
  90. package/dist/utils/workspace-manager.d.ts +4 -0
  91. package/dist/utils/workspace-manager.d.ts.map +1 -1
  92. package/dist/utils/worktree-manager.d.ts +15 -1
  93. package/dist/utils/worktree-manager.d.ts.map +1 -1
  94. package/package.json +2 -2
  95. package/dist/sdk/chunk-YYZAN5NK.mjs.map +0 -1
  96. package/dist/sdk/git-repository-analyzer-QFMW6WIS.mjs.map +0 -1
  97. /package/dist/sdk/{check-provider-registry-IYSUDKPB.mjs.map → check-provider-registry-6D5CAX44.mjs.map} +0 -0
  98. /package/dist/sdk/{check-provider-registry-LVLC4EPF.mjs.map → check-provider-registry-RRYBG6AU.mjs.map} +0 -0
  99. /package/dist/sdk/{check-provider-registry-X4OZJWPK.mjs.map → check-provider-registry-YFC5KSJY.mjs.map} +0 -0
  100. /package/dist/sdk/{chunk-BR7DYA3S.mjs.map → chunk-FZEQ744M.mjs.map} +0 -0
  101. /package/dist/sdk/{chunk-CISJ6DJW.mjs.map → chunk-GIAN7HCT.mjs.map} +0 -0
  102. /package/dist/sdk/{chunk-Q6EPAJ6Z.mjs.map → chunk-GLROSEYJ.mjs.map} +0 -0
  103. /package/dist/sdk/{chunk-RJLJUTSU.mjs.map → chunk-SWO4W57C.mjs.map} +0 -0
  104. /package/dist/sdk/{config-KQH254CA.mjs.map → config-MTEIGCOQ.mjs.map} +0 -0
  105. /package/dist/sdk/{failure-condition-evaluator-IVCTD4BZ.mjs.map → failure-condition-evaluator-P6QUFLIN.mjs.map} +0 -0
  106. /package/dist/sdk/{failure-condition-evaluator-LZ2AG5PY.mjs.map → failure-condition-evaluator-XV2ZMFFY.mjs.map} +0 -0
  107. /package/dist/sdk/{github-frontend-DFT5G32K.mjs.map → github-frontend-A2R7D4N6.mjs.map} +0 -0
  108. /package/dist/sdk/{github-frontend-S523EEJB.mjs.map → github-frontend-GSB2P5PE.mjs.map} +0 -0
  109. /package/dist/sdk/{host-7YKRMOUJ.mjs.map → host-CLPM2WVQ.mjs.map} +0 -0
  110. /package/dist/sdk/{host-H7IX4GBK.mjs.map → host-MR7L57QI.mjs.map} +0 -0
  111. /package/dist/sdk/{routing-LU5PAREW.mjs.map → routing-KLVK2MJZ.mjs.map} +0 -0
  112. /package/dist/sdk/{routing-ZMBKWMVI.mjs.map → routing-V3MYZAOH.mjs.map} +0 -0
  113. /package/dist/sdk/{schedule-tool-CDVUSZEG.mjs.map → schedule-tool-HYM55K3H.mjs.map} +0 -0
  114. /package/dist/sdk/{schedule-tool-EOMZFICZ.mjs.map → schedule-tool-NYLNJUEW.mjs.map} +0 -0
  115. /package/dist/sdk/{schedule-tool-NX75VKGA.mjs.map → schedule-tool-PRXFAV4K.mjs.map} +0 -0
  116. /package/dist/sdk/{schedule-tool-handler-3FJHDIPG.mjs.map → schedule-tool-handler-EFQIYD3W.mjs.map} +0 -0
  117. /package/dist/sdk/{schedule-tool-handler-KKN7XJYT.mjs.map → schedule-tool-handler-HVWCEGQ6.mjs.map} +0 -0
  118. /package/dist/sdk/{schedule-tool-handler-QNZG55DX.mjs.map → schedule-tool-handler-M5YI573R.mjs.map} +0 -0
  119. /package/dist/sdk/{trace-helpers-6ROJR7N3.mjs.map → trace-helpers-6NSZBC35.mjs.map} +0 -0
  120. /package/dist/sdk/{trace-helpers-EJUIOP6L.mjs.map → trace-helpers-TORF3JD5.mjs.map} +0 -0
  121. /package/dist/sdk/{workflow-check-provider-6ERNNCNA.mjs.map → workflow-check-provider-3F6CBHVD.mjs.map} +0 -0
  122. /package/dist/sdk/{workflow-check-provider-AGZ5JY2I.mjs.map → workflow-check-provider-OXHMLICJ.mjs.map} +0 -0
  123. /package/dist/sdk/{workflow-check-provider-PTNUWM5W.mjs.map → workflow-check-provider-XLH7N4FV.mjs.map} +0 -0
@@ -33,7 +33,7 @@ import {
33
33
  import {
34
34
  config_exports,
35
35
  init_config
36
- } from "./chunk-YYZAN5NK.mjs";
36
+ } from "./chunk-FYK2DJK6.mjs";
37
37
  import {
38
38
  ExecutionJournal,
39
39
  checkLoopBudget,
@@ -42,11 +42,11 @@ import {
42
42
  init_routing,
43
43
  init_snapshot_store,
44
44
  snapshot_store_exports
45
- } from "./chunk-CISJ6DJW.mjs";
45
+ } from "./chunk-GLROSEYJ.mjs";
46
46
  import {
47
47
  FailureConditionEvaluator,
48
48
  init_failure_condition_evaluator
49
- } from "./chunk-RJLJUTSU.mjs";
49
+ } from "./chunk-FZEQ744M.mjs";
50
50
  import {
51
51
  addEvent,
52
52
  emitNdjsonFallback,
@@ -57,7 +57,7 @@ import {
57
57
  setSpanAttributes,
58
58
  trace_helpers_exports,
59
59
  withActiveSpan
60
- } from "./chunk-62TNF5PJ.mjs";
60
+ } from "./chunk-PETLPNRA.mjs";
61
61
  import {
62
62
  addDiagramBlock,
63
63
  init_metrics
@@ -257,6 +257,23 @@ function createProbeTracerAdapter(fallbackTracer) {
257
257
  }
258
258
  }
259
259
  },
260
+ recordToolResult: (toolName, result, success, durationMs, metadata) => {
261
+ const resultStr = typeof result === "string" ? result : JSON.stringify(result || "");
262
+ emitEvent("tool.result", {
263
+ "tool.name": toolName,
264
+ "tool.result": resultStr.substring(0, 1e4),
265
+ "tool.result.length": resultStr.length,
266
+ "tool.duration_ms": durationMs,
267
+ "tool.success": success,
268
+ ...metadata || {}
269
+ });
270
+ if (fallback && typeof fallback.recordToolResult === "function") {
271
+ try {
272
+ fallback.recordToolResult(toolName, result, success, durationMs, metadata);
273
+ } catch {
274
+ }
275
+ }
276
+ },
260
277
  recordDelegationEvent: (phase, attrs) => {
261
278
  emitEvent(`delegation.${phase}`, attrs);
262
279
  if (fallback && typeof fallback.recordDelegationEvent === "function") {
@@ -3942,7 +3959,7 @@ async function executeWorkflowAsTool(workflowId, args, context2, argsOverrides)
3942
3959
  ...args,
3943
3960
  ...argsOverrides
3944
3961
  };
3945
- const { WorkflowCheckProvider: WorkflowCheckProvider2 } = await import("./workflow-check-provider-AGZ5JY2I.mjs");
3962
+ const { WorkflowCheckProvider: WorkflowCheckProvider2 } = await import("./workflow-check-provider-XLH7N4FV.mjs");
3946
3963
  const provider = new WorkflowCheckProvider2();
3947
3964
  const checkConfig = {
3948
3965
  type: "workflow",
@@ -4070,6 +4087,48 @@ function fromDbRow(row) {
4070
4087
  previousResponse: row.previous_response ?? void 0
4071
4088
  };
4072
4089
  }
4090
+ function toTriggerRow(trigger) {
4091
+ return {
4092
+ id: trigger.id,
4093
+ creator_id: trigger.creatorId,
4094
+ creator_context: trigger.creatorContext ?? null,
4095
+ creator_name: trigger.creatorName ?? null,
4096
+ description: trigger.description ?? null,
4097
+ channels: trigger.channels ? JSON.stringify(trigger.channels) : null,
4098
+ from_users: trigger.fromUsers ? JSON.stringify(trigger.fromUsers) : null,
4099
+ from_bots: trigger.fromBots ? 1 : 0,
4100
+ contains: trigger.contains ? JSON.stringify(trigger.contains) : null,
4101
+ match_pattern: trigger.matchPattern ?? null,
4102
+ threads: trigger.threads,
4103
+ workflow: trigger.workflow,
4104
+ inputs: trigger.inputs ? JSON.stringify(trigger.inputs) : null,
4105
+ output_context: trigger.outputContext ? JSON.stringify(trigger.outputContext) : null,
4106
+ status: trigger.status,
4107
+ enabled: trigger.enabled ? 1 : 0,
4108
+ created_at: trigger.createdAt
4109
+ };
4110
+ }
4111
+ function fromTriggerRow(row) {
4112
+ return {
4113
+ id: row.id,
4114
+ creatorId: row.creator_id,
4115
+ creatorContext: row.creator_context ?? void 0,
4116
+ creatorName: row.creator_name ?? void 0,
4117
+ description: row.description ?? void 0,
4118
+ channels: safeJsonParse(row.channels),
4119
+ fromUsers: safeJsonParse(row.from_users),
4120
+ fromBots: row.from_bots === 1,
4121
+ contains: safeJsonParse(row.contains),
4122
+ matchPattern: row.match_pattern ?? void 0,
4123
+ threads: row.threads,
4124
+ workflow: row.workflow,
4125
+ inputs: safeJsonParse(row.inputs),
4126
+ outputContext: safeJsonParse(row.output_context),
4127
+ status: row.status,
4128
+ enabled: row.enabled === 1,
4129
+ createdAt: row.created_at
4130
+ };
4131
+ }
4073
4132
  var SqliteStoreBackend;
4074
4133
  var init_sqlite_store = __esm({
4075
4134
  "src/scheduler/store/sqlite-store.ts"() {
@@ -4159,6 +4218,32 @@ var init_sqlite_store = __esm({
4159
4218
  acquired_at BIGINT NOT NULL,
4160
4219
  expires_at BIGINT NOT NULL
4161
4220
  );
4221
+
4222
+ CREATE TABLE IF NOT EXISTS message_triggers (
4223
+ id VARCHAR(36) PRIMARY KEY,
4224
+ creator_id VARCHAR(255) NOT NULL,
4225
+ creator_context VARCHAR(255),
4226
+ creator_name VARCHAR(255),
4227
+ description TEXT,
4228
+ channels TEXT,
4229
+ from_users TEXT,
4230
+ from_bots BOOLEAN NOT NULL DEFAULT 0,
4231
+ contains TEXT,
4232
+ match_pattern TEXT,
4233
+ threads VARCHAR(20) NOT NULL DEFAULT 'any',
4234
+ workflow VARCHAR(255) NOT NULL,
4235
+ inputs TEXT,
4236
+ output_context TEXT,
4237
+ status VARCHAR(20) NOT NULL DEFAULT 'active',
4238
+ enabled BOOLEAN NOT NULL DEFAULT 1,
4239
+ created_at BIGINT NOT NULL
4240
+ );
4241
+
4242
+ CREATE INDEX IF NOT EXISTS idx_message_triggers_creator
4243
+ ON message_triggers(creator_id);
4244
+
4245
+ CREATE INDEX IF NOT EXISTS idx_message_triggers_status
4246
+ ON message_triggers(status);
4162
4247
  `);
4163
4248
  }
4164
4249
  // --- Helpers ---
@@ -4440,6 +4525,114 @@ var init_sqlite_store = __esm({
4440
4525
  }
4441
4526
  async flush() {
4442
4527
  }
4528
+ // --- Message Triggers ---
4529
+ async createTrigger(trigger) {
4530
+ const db = this.getDb();
4531
+ const newTrigger = {
4532
+ ...trigger,
4533
+ id: uuidv4(),
4534
+ createdAt: Date.now()
4535
+ };
4536
+ const row = toTriggerRow(newTrigger);
4537
+ db.prepare(
4538
+ `INSERT INTO message_triggers (
4539
+ id, creator_id, creator_context, creator_name, description,
4540
+ channels, from_users, from_bots, contains, match_pattern,
4541
+ threads, workflow, inputs, output_context,
4542
+ status, enabled, created_at
4543
+ ) VALUES (
4544
+ ?, ?, ?, ?, ?,
4545
+ ?, ?, ?, ?, ?,
4546
+ ?, ?, ?, ?,
4547
+ ?, ?, ?
4548
+ )`
4549
+ ).run(
4550
+ row.id,
4551
+ row.creator_id,
4552
+ row.creator_context,
4553
+ row.creator_name,
4554
+ row.description,
4555
+ row.channels,
4556
+ row.from_users,
4557
+ row.from_bots,
4558
+ row.contains,
4559
+ row.match_pattern,
4560
+ row.threads,
4561
+ row.workflow,
4562
+ row.inputs,
4563
+ row.output_context,
4564
+ row.status,
4565
+ row.enabled,
4566
+ row.created_at
4567
+ );
4568
+ logger.info(
4569
+ `[SqliteStore] Created message trigger ${newTrigger.id} for user ${newTrigger.creatorId}`
4570
+ );
4571
+ return newTrigger;
4572
+ }
4573
+ async getTrigger(id) {
4574
+ const db = this.getDb();
4575
+ const row = db.prepare("SELECT * FROM message_triggers WHERE id = ?").get(id);
4576
+ return row ? fromTriggerRow(row) : void 0;
4577
+ }
4578
+ async updateTrigger(id, patch) {
4579
+ const db = this.getDb();
4580
+ const existing = db.prepare("SELECT * FROM message_triggers WHERE id = ?").get(id);
4581
+ if (!existing) return void 0;
4582
+ const current = fromTriggerRow(existing);
4583
+ const updated = {
4584
+ ...current,
4585
+ ...patch,
4586
+ id: current.id,
4587
+ createdAt: current.createdAt
4588
+ };
4589
+ const row = toTriggerRow(updated);
4590
+ db.prepare(
4591
+ `UPDATE message_triggers SET
4592
+ creator_id = ?, creator_context = ?, creator_name = ?, description = ?,
4593
+ channels = ?, from_users = ?, from_bots = ?, contains = ?, match_pattern = ?,
4594
+ threads = ?, workflow = ?, inputs = ?, output_context = ?,
4595
+ status = ?, enabled = ?
4596
+ WHERE id = ?`
4597
+ ).run(
4598
+ row.creator_id,
4599
+ row.creator_context,
4600
+ row.creator_name,
4601
+ row.description,
4602
+ row.channels,
4603
+ row.from_users,
4604
+ row.from_bots,
4605
+ row.contains,
4606
+ row.match_pattern,
4607
+ row.threads,
4608
+ row.workflow,
4609
+ row.inputs,
4610
+ row.output_context,
4611
+ row.status,
4612
+ row.enabled,
4613
+ row.id
4614
+ );
4615
+ return updated;
4616
+ }
4617
+ async deleteTrigger(id) {
4618
+ const db = this.getDb();
4619
+ const result = db.prepare("DELETE FROM message_triggers WHERE id = ?").run(id);
4620
+ if (result.changes > 0) {
4621
+ logger.info(`[SqliteStore] Deleted message trigger ${id}`);
4622
+ return true;
4623
+ }
4624
+ return false;
4625
+ }
4626
+ async getTriggersByCreator(creatorId) {
4627
+ const db = this.getDb();
4628
+ const rows = db.prepare("SELECT * FROM message_triggers WHERE creator_id = ?").all(creatorId);
4629
+ return rows.map(fromTriggerRow);
4630
+ }
4631
+ async getActiveTriggers() {
4632
+ const db = this.getDb();
4633
+ const rows = db.prepare("SELECT * FROM message_triggers WHERE status = 'active' AND enabled = 1").all();
4634
+ return rows.map(fromTriggerRow);
4635
+ }
4443
4636
  };
4444
4637
  }
4445
4638
  });
@@ -4558,11 +4751,19 @@ var init_schedule_store = __esm({
4558
4751
  init_json_migrator();
4559
4752
  ScheduleStore = class _ScheduleStore {
4560
4753
  static instance;
4754
+ static onTriggersChanged;
4561
4755
  backend = null;
4562
4756
  initialized = false;
4563
4757
  limits;
4564
4758
  config;
4565
4759
  externalBackend = null;
4760
+ /**
4761
+ * Register a callback to be invoked when message triggers change (create/update/delete).
4762
+ * Used by SlackSocketRunner to rebuild its evaluator.
4763
+ */
4764
+ static setTriggersChangedCallback(cb) {
4765
+ _ScheduleStore.onTriggersChanged = cb;
4766
+ }
4566
4767
  constructor(config, limits, backend) {
4567
4768
  this.config = config || {};
4568
4769
  this.limits = {
@@ -4724,6 +4925,53 @@ var init_schedule_store = __esm({
4724
4925
  }
4725
4926
  return this.backend;
4726
4927
  }
4928
+ // --- Message Trigger Methods ---
4929
+ /**
4930
+ * Create a new message trigger
4931
+ */
4932
+ async createTriggerAsync(trigger) {
4933
+ const result = await this.getBackend().createTrigger(trigger);
4934
+ _ScheduleStore.onTriggersChanged?.();
4935
+ return result;
4936
+ }
4937
+ /**
4938
+ * Get a trigger by ID
4939
+ */
4940
+ async getTriggerAsync(id) {
4941
+ return this.getBackend().getTrigger(id);
4942
+ }
4943
+ /**
4944
+ * Update a trigger
4945
+ */
4946
+ async updateTriggerAsync(id, patch) {
4947
+ const result = await this.getBackend().updateTrigger(id, patch);
4948
+ if (result) {
4949
+ _ScheduleStore.onTriggersChanged?.();
4950
+ }
4951
+ return result;
4952
+ }
4953
+ /**
4954
+ * Delete a trigger
4955
+ */
4956
+ async deleteTriggerAsync(id) {
4957
+ const result = await this.getBackend().deleteTrigger(id);
4958
+ if (result) {
4959
+ _ScheduleStore.onTriggersChanged?.();
4960
+ }
4961
+ return result;
4962
+ }
4963
+ /**
4964
+ * Get all triggers for a specific creator
4965
+ */
4966
+ async getTriggersByCreatorAsync(creatorId) {
4967
+ return this.getBackend().getTriggersByCreator(creatorId);
4968
+ }
4969
+ /**
4970
+ * Get all active triggers
4971
+ */
4972
+ async getActiveTriggersAsync() {
4973
+ return this.getBackend().getActiveTriggers();
4974
+ }
4727
4975
  /**
4728
4976
  * Shut down the backend cleanly
4729
4977
  */
@@ -9007,7 +9255,7 @@ async function executeCheckWithForEachItems2(checkId, forEachParent, forEachItem
9007
9255
  }
9008
9256
  }
9009
9257
  try {
9010
- const { evaluateTransitions } = await import("./routing-LU5PAREW.mjs");
9258
+ const { evaluateTransitions } = await import("./routing-V3MYZAOH.mjs");
9011
9259
  const transTarget = await evaluateTransitions(
9012
9260
  onFinish.transitions,
9013
9261
  forEachParent,
@@ -9067,7 +9315,7 @@ async function executeCheckWithForEachItems2(checkId, forEachParent, forEachItem
9067
9315
  `[LevelDispatch] Error evaluating on_finish transitions for ${forEachParent}: ${e instanceof Error ? e.message : String(e)}`
9068
9316
  );
9069
9317
  }
9070
- const { evaluateGoto: evaluateGoto2 } = await import("./routing-LU5PAREW.mjs");
9318
+ const { evaluateGoto: evaluateGoto2 } = await import("./routing-V3MYZAOH.mjs");
9071
9319
  if (context2.debug) {
9072
9320
  logger.info(
9073
9321
  `[LevelDispatch] Evaluating on_finish.goto_js for forEach parent: ${forEachParent}`
@@ -12323,6 +12571,30 @@ var init_workspace_manager = __esm({
12323
12571
  if (cleanResult.exitCode !== 0) {
12324
12572
  logger.warn(`[Workspace] clean -fdx failed: ${cleanResult.stderr}`);
12325
12573
  }
12574
+ await this.deleteLocalBranches(worktreePath);
12575
+ }
12576
+ /**
12577
+ * Delete all local branches in a worktree.
12578
+ */
12579
+ async deleteLocalBranches(worktreePath) {
12580
+ const escapedPath = shellEscape(worktreePath);
12581
+ const listResult = await commandExecutor.execute(
12582
+ `git -C ${escapedPath} branch --list --format='%(refname:short)'`,
12583
+ { timeout: 1e4 }
12584
+ );
12585
+ if (listResult.exitCode !== 0 || !listResult.stdout.trim()) {
12586
+ return;
12587
+ }
12588
+ const branches = listResult.stdout.trim().split("\n").map((b) => b.trim()).filter((b) => b.length > 0);
12589
+ for (const branch of branches) {
12590
+ const deleteResult = await commandExecutor.execute(
12591
+ `git -C ${escapedPath} branch -D ${shellEscape(branch)}`,
12592
+ { timeout: 1e4 }
12593
+ );
12594
+ if (deleteResult.exitCode === 0) {
12595
+ logger.debug(`[Workspace] Deleted local branch '${branch}' from worktree`);
12596
+ }
12597
+ }
12326
12598
  }
12327
12599
  /**
12328
12600
  * Refresh an existing worktree to the latest upstream default branch
@@ -12692,7 +12964,7 @@ var init_state_machine_execution_engine = __esm({
12692
12964
  await memoryStore.initialize();
12693
12965
  logger.debug("Memory store initialized");
12694
12966
  }
12695
- const { GitRepositoryAnalyzer } = await import("./git-repository-analyzer-QFMW6WIS.mjs");
12967
+ const { GitRepositoryAnalyzer } = await import("./git-repository-analyzer-TWNJUN42.mjs");
12696
12968
  const gitAnalyzer = new GitRepositoryAnalyzer(options.workingDirectory);
12697
12969
  logger.info("Analyzing local git repository...");
12698
12970
  const repositoryInfo = await gitAnalyzer.analyzeRepository();
@@ -12729,7 +13001,7 @@ var init_state_machine_execution_engine = __esm({
12729
13001
  try {
12730
13002
  const map = options?.webhookContext?.webhookData;
12731
13003
  if (map) {
12732
- const { CheckProviderRegistry: CheckProviderRegistry2 } = await import("./check-provider-registry-LVLC4EPF.mjs");
13004
+ const { CheckProviderRegistry: CheckProviderRegistry2 } = await import("./check-provider-registry-RRYBG6AU.mjs");
12733
13005
  const reg = CheckProviderRegistry2.getInstance();
12734
13006
  const p = reg.getProvider("http_input");
12735
13007
  if (p && typeof p.setWebhookContext === "function") p.setWebhookContext(map);
@@ -12842,7 +13114,7 @@ var init_state_machine_execution_engine = __esm({
12842
13114
  logger.info("[StateMachine] Using state machine engine");
12843
13115
  }
12844
13116
  if (!config) {
12845
- const { ConfigManager } = await import("./config-KQH254CA.mjs");
13117
+ const { ConfigManager } = await import("./config-MTEIGCOQ.mjs");
12846
13118
  const configManager = new ConfigManager();
12847
13119
  config = await configManager.getDefaultConfig();
12848
13120
  logger.debug("[StateMachine] Using default configuration (no config provided)");
@@ -12852,7 +13124,7 @@ var init_state_machine_execution_engine = __esm({
12852
13124
  tag_filter: tagFilter
12853
13125
  } : config;
12854
13126
  try {
12855
- const { CheckProviderRegistry: CheckProviderRegistry2 } = await import("./check-provider-registry-LVLC4EPF.mjs");
13127
+ const { CheckProviderRegistry: CheckProviderRegistry2 } = await import("./check-provider-registry-RRYBG6AU.mjs");
12856
13128
  const registry = CheckProviderRegistry2.getInstance();
12857
13129
  registry.setCustomTools(configWithTagFilter.tools || {});
12858
13130
  } catch (error) {
@@ -12916,7 +13188,7 @@ var init_state_machine_execution_engine = __esm({
12916
13188
  try {
12917
13189
  const webhookData = this.executionContext?.webhookContext?.webhookData;
12918
13190
  if (webhookData instanceof Map) {
12919
- const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-KKN7XJYT.mjs");
13191
+ const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-EFQIYD3W.mjs");
12920
13192
  const slackCtx = extractSlackContext2(webhookData);
12921
13193
  if (slackCtx) {
12922
13194
  const payload = Array.from(webhookData.values())[0];
@@ -12945,7 +13217,7 @@ var init_state_machine_execution_engine = __esm({
12945
13217
  if (Array.isArray(configWithTagFilter.frontends) && configWithTagFilter.frontends.length > 0) {
12946
13218
  try {
12947
13219
  const { EventBus } = await import("./event-bus-5K3Y2FCS.mjs");
12948
- const { FrontendsHost } = await import("./host-H7IX4GBK.mjs");
13220
+ const { FrontendsHost } = await import("./host-MR7L57QI.mjs");
12949
13221
  const bus = new EventBus();
12950
13222
  context2.eventBus = bus;
12951
13223
  frontendsHost = new FrontendsHost(bus, logger);
@@ -13295,9 +13567,9 @@ var init_state_machine_execution_engine = __esm({
13295
13567
  * @returns Array of failure condition evaluation results
13296
13568
  */
13297
13569
  async evaluateFailureConditions(checkName, reviewSummary, config, previousOutputs, authorAssociation) {
13298
- const { FailureConditionEvaluator: FailureConditionEvaluator2 } = await import("./failure-condition-evaluator-IVCTD4BZ.mjs");
13570
+ const { FailureConditionEvaluator: FailureConditionEvaluator2 } = await import("./failure-condition-evaluator-XV2ZMFFY.mjs");
13299
13571
  const evaluator = new FailureConditionEvaluator2();
13300
- const { addEvent: addEvent3 } = await import("./trace-helpers-6ROJR7N3.mjs");
13572
+ const { addEvent: addEvent3 } = await import("./trace-helpers-6NSZBC35.mjs");
13301
13573
  const { addFailIfTriggered } = await import("./metrics-I6A7IHG4.mjs");
13302
13574
  const checkConfig = config.checks?.[checkName];
13303
13575
  if (!checkConfig) {
@@ -13400,7 +13672,7 @@ var init_state_machine_execution_engine = __esm({
13400
13672
  */
13401
13673
  async getRepositoryStatus() {
13402
13674
  try {
13403
- const { GitRepositoryAnalyzer } = await import("./git-repository-analyzer-QFMW6WIS.mjs");
13675
+ const { GitRepositoryAnalyzer } = await import("./git-repository-analyzer-TWNJUN42.mjs");
13404
13676
  const analyzer = new GitRepositoryAnalyzer(this.workingDirectory);
13405
13677
  const info = await analyzer.analyzeRepository();
13406
13678
  return {
@@ -14470,11 +14742,19 @@ async function handleScheduleAction(args, context2) {
14470
14742
  return handlePauseResume(args, context2, store, "paused");
14471
14743
  case "resume":
14472
14744
  return handlePauseResume(args, context2, store, "active");
14745
+ case "create_trigger":
14746
+ return handleCreateTrigger(args, context2, store);
14747
+ case "list_triggers":
14748
+ return handleListTriggers(context2, store);
14749
+ case "delete_trigger":
14750
+ return handleDeleteTrigger(args, context2, store);
14751
+ case "update_trigger":
14752
+ return handleUpdateTrigger(args, context2, store);
14473
14753
  default:
14474
14754
  return {
14475
14755
  success: false,
14476
14756
  message: `Unknown action: ${args.action}`,
14477
- error: `Supported actions: create, list, cancel, pause, resume`
14757
+ error: `Supported actions: create, list, cancel, pause, resume, create_trigger, list_triggers, delete_trigger, update_trigger`
14478
14758
  };
14479
14759
  }
14480
14760
  }
@@ -14717,6 +14997,172 @@ async function handlePauseResume(args, context2, store, newStatus) {
14717
14997
  schedule: updated
14718
14998
  };
14719
14999
  }
15000
+ function formatTrigger(trigger) {
15001
+ const channels = trigger.channels?.length ? trigger.channels.join(", ") : "all";
15002
+ const filters = [];
15003
+ if (trigger.contains?.length) filters.push(`contains: ${trigger.contains.join(", ")}`);
15004
+ if (trigger.matchPattern) filters.push(`match: /${trigger.matchPattern}/`);
15005
+ if (trigger.fromBots) filters.push("bots: yes");
15006
+ const filterStr = filters.length ? ` [${filters.join("; ")}]` : "";
15007
+ const status = trigger.enabled ? "" : " (disabled)";
15008
+ return `\`${trigger.id.substring(0, 8)}\` - channels: ${channels} \u2192 workflow: "${trigger.workflow}"${filterStr}${status}`;
15009
+ }
15010
+ async function handleCreateTrigger(args, context2, store) {
15011
+ if (!args.workflow) {
15012
+ return {
15013
+ success: false,
15014
+ message: "Missing workflow",
15015
+ error: "Please specify the workflow to run when the trigger fires."
15016
+ };
15017
+ }
15018
+ if (context2.availableWorkflows && !context2.availableWorkflows.includes(args.workflow)) {
15019
+ return {
15020
+ success: false,
15021
+ message: `Workflow "${args.workflow}" not found`,
15022
+ error: `Available workflows: ${context2.availableWorkflows.slice(0, 5).join(", ")}${context2.availableWorkflows.length > 5 ? "..." : ""}`
15023
+ };
15024
+ }
15025
+ if ((!args.trigger_channels || args.trigger_channels.length === 0) && (!args.trigger_contains || args.trigger_contains.length === 0) && !args.trigger_match) {
15026
+ return {
15027
+ success: false,
15028
+ message: "Missing trigger filters",
15029
+ error: "Please specify at least one filter: trigger_channels, trigger_contains, or trigger_match."
15030
+ };
15031
+ }
15032
+ const permissionCheck = checkSchedulePermissions(context2, args.workflow);
15033
+ if (!permissionCheck.allowed) {
15034
+ return {
15035
+ success: false,
15036
+ message: "Permission denied",
15037
+ error: permissionCheck.reason || "You do not have permission to create triggers for this workflow"
15038
+ };
15039
+ }
15040
+ try {
15041
+ const trigger = await store.createTriggerAsync({
15042
+ creatorId: context2.userId,
15043
+ creatorContext: context2.contextType,
15044
+ creatorName: context2.userName,
15045
+ description: args.trigger_description,
15046
+ channels: args.trigger_channels,
15047
+ fromBots: args.trigger_from_bots ?? false,
15048
+ contains: args.trigger_contains,
15049
+ matchPattern: args.trigger_match,
15050
+ threads: args.trigger_threads ?? "any",
15051
+ workflow: args.workflow,
15052
+ inputs: args.workflow_inputs,
15053
+ status: "active",
15054
+ enabled: true
15055
+ });
15056
+ logger.info(
15057
+ `[ScheduleTool] Created message trigger ${trigger.id} for user ${context2.userId}: workflow="${args.workflow}"`
15058
+ );
15059
+ return {
15060
+ success: true,
15061
+ message: `**Message trigger created!**
15062
+
15063
+ **Workflow**: ${trigger.workflow}
15064
+ **Channels**: ${trigger.channels?.join(", ") || "all"}
15065
+ ${trigger.contains?.length ? `**Contains**: ${trigger.contains.join(", ")}
15066
+ ` : ""}${trigger.matchPattern ? `**Pattern**: /${trigger.matchPattern}/
15067
+ ` : ""}${trigger.description ? `**Description**: ${trigger.description}
15068
+ ` : ""}
15069
+ ID: \`${trigger.id.substring(0, 8)}\``
15070
+ };
15071
+ } catch (error) {
15072
+ const errorMsg = error instanceof Error ? error.message : "Unknown error";
15073
+ logger.warn(`[ScheduleTool] Failed to create trigger: ${errorMsg}`);
15074
+ return {
15075
+ success: false,
15076
+ message: `Failed to create trigger: ${errorMsg}`,
15077
+ error: errorMsg
15078
+ };
15079
+ }
15080
+ }
15081
+ async function handleListTriggers(context2, store) {
15082
+ const triggers = await store.getTriggersByCreatorAsync(context2.userId);
15083
+ const active = triggers.filter((t) => t.status !== "deleted");
15084
+ if (active.length === 0) {
15085
+ return {
15086
+ success: true,
15087
+ message: `You don't have any message triggers.
15088
+
15089
+ To create one: "watch #channel for messages containing 'error' and run %my-workflow"`
15090
+ };
15091
+ }
15092
+ const lines = active.map((t, i) => `${i + 1}. ${formatTrigger(t)}`);
15093
+ return {
15094
+ success: true,
15095
+ message: `**Your message triggers:**
15096
+
15097
+ ${lines.join("\n")}
15098
+
15099
+ To delete: "delete trigger <id>"
15100
+ To disable: "disable trigger <id>"`
15101
+ };
15102
+ }
15103
+ async function handleDeleteTrigger(args, context2, store) {
15104
+ if (!args.trigger_id) {
15105
+ return {
15106
+ success: false,
15107
+ message: "Missing trigger ID",
15108
+ error: "Please specify which trigger to delete."
15109
+ };
15110
+ }
15111
+ const userTriggers = await store.getTriggersByCreatorAsync(context2.userId);
15112
+ let trigger = userTriggers.find((t) => t.id === args.trigger_id);
15113
+ if (!trigger) {
15114
+ trigger = userTriggers.find((t) => t.id.startsWith(args.trigger_id));
15115
+ }
15116
+ if (!trigger) {
15117
+ return {
15118
+ success: false,
15119
+ message: "Trigger not found",
15120
+ error: `Could not find trigger with ID "${args.trigger_id}" in your triggers. Use "list my triggers" to see your triggers.`
15121
+ };
15122
+ }
15123
+ await store.deleteTriggerAsync(trigger.id);
15124
+ logger.info(`[ScheduleTool] Deleted trigger ${trigger.id} for user ${context2.userId}`);
15125
+ return {
15126
+ success: true,
15127
+ message: `**Trigger deleted!**
15128
+
15129
+ Was: watching for "${trigger.workflow}" ${trigger.channels?.length ? `in ${trigger.channels.join(", ")}` : ""}`
15130
+ };
15131
+ }
15132
+ async function handleUpdateTrigger(args, context2, store) {
15133
+ if (!args.trigger_id) {
15134
+ return {
15135
+ success: false,
15136
+ message: "Missing trigger ID",
15137
+ error: "Please specify which trigger to update."
15138
+ };
15139
+ }
15140
+ const userTriggers = await store.getTriggersByCreatorAsync(context2.userId);
15141
+ let trigger = userTriggers.find((t) => t.id === args.trigger_id);
15142
+ if (!trigger) {
15143
+ trigger = userTriggers.find((t) => t.id.startsWith(args.trigger_id));
15144
+ }
15145
+ if (!trigger) {
15146
+ return {
15147
+ success: false,
15148
+ message: "Trigger not found",
15149
+ error: `Could not find trigger with ID "${args.trigger_id}" in your triggers.`
15150
+ };
15151
+ }
15152
+ const patch = {};
15153
+ if (args.trigger_enabled !== void 0) {
15154
+ patch.enabled = args.trigger_enabled;
15155
+ }
15156
+ await store.updateTriggerAsync(trigger.id, patch);
15157
+ const action = args.trigger_enabled === false ? "disabled" : "enabled";
15158
+ logger.info(`[ScheduleTool] ${action} trigger ${trigger.id} for user ${context2.userId}`);
15159
+ return {
15160
+ success: true,
15161
+ message: `**Trigger ${action}!**
15162
+
15163
+ "${trigger.workflow}" ${trigger.channels?.length ? `in ${trigger.channels.join(", ")}` : ""}`
15164
+ };
15165
+ }
14720
15166
  function getScheduleToolDefinition() {
14721
15167
  return {
14722
15168
  name: "schedule",
@@ -14736,6 +15182,17 @@ ACTIONS:
14736
15182
  - cancel: Remove a schedule by ID
14737
15183
  - pause/resume: Temporarily disable/enable a schedule
14738
15184
 
15185
+ MESSAGE-BASED TRIGGERS:
15186
+ In addition to time-based schedules, this tool can create/manage message-based triggers that react to
15187
+ Slack messages in specific channels. Use the create_trigger, list_triggers, delete_trigger, and update_trigger
15188
+ actions for this. Message triggers fire workflows based on message content, channel, sender, and thread scope.
15189
+
15190
+ TRIGGER ACTIONS:
15191
+ - create_trigger: Create a new message trigger (requires workflow + at least one filter)
15192
+ - list_triggers: Show user's message triggers
15193
+ - delete_trigger: Remove a trigger by ID
15194
+ - update_trigger: Enable/disable a trigger by ID
15195
+
14739
15196
  FOR CREATE ACTION - Extract these from user's request:
14740
15197
  1. WHAT:
14741
15198
  - If user says "schedule %some-workflow ...", populate 'workflow' with "some-workflow".
@@ -14823,14 +15280,36 @@ User: "list my schedules"
14823
15280
  \u2192 { "action": "list" }
14824
15281
 
14825
15282
  User: "cancel schedule abc123"
14826
- \u2192 { "action": "cancel", "schedule_id": "abc123" }`,
15283
+ \u2192 { "action": "cancel", "schedule_id": "abc123" }
15284
+
15285
+ User: "watch #cicd for messages containing 'failed' and run %handle-cicd"
15286
+ \u2192 { "action": "create_trigger", "trigger_channels": ["C0CICD"], "trigger_contains": ["failed"], "workflow": "handle-cicd" }
15287
+
15288
+ User: "list my message triggers"
15289
+ \u2192 { "action": "list_triggers" }
15290
+
15291
+ User: "delete trigger abc123"
15292
+ \u2192 { "action": "delete_trigger", "trigger_id": "abc123" }
15293
+
15294
+ User: "disable trigger abc123"
15295
+ \u2192 { "action": "update_trigger", "trigger_id": "abc123", "trigger_enabled": false }`,
14827
15296
  inputSchema: {
14828
15297
  type: "object",
14829
15298
  properties: {
14830
15299
  action: {
14831
15300
  type: "string",
14832
- enum: ["create", "list", "cancel", "pause", "resume"],
14833
- description: "What to do: create new, list existing, cancel/pause/resume by ID"
15301
+ enum: [
15302
+ "create",
15303
+ "list",
15304
+ "cancel",
15305
+ "pause",
15306
+ "resume",
15307
+ "create_trigger",
15308
+ "list_triggers",
15309
+ "delete_trigger",
15310
+ "update_trigger"
15311
+ ],
15312
+ description: "What to do: create/list/cancel/pause/resume for time-based schedules; create_trigger/list_triggers/delete_trigger/update_trigger for message-based triggers"
14834
15313
  },
14835
15314
  // WHAT to do
14836
15315
  reminder_text: {
@@ -14880,6 +15359,42 @@ User: "cancel schedule abc123"
14880
15359
  schedule_id: {
14881
15360
  type: "string",
14882
15361
  description: "For cancel/pause/resume: the schedule ID to act on (first 8 chars is enough)"
15362
+ },
15363
+ // For message trigger actions
15364
+ trigger_channels: {
15365
+ type: "array",
15366
+ items: { type: "string" },
15367
+ description: 'For create_trigger: Slack channel IDs to monitor (e.g., ["C0CICD"]). Supports wildcard suffix (e.g., "CENG*").'
15368
+ },
15369
+ trigger_from_bots: {
15370
+ type: "boolean",
15371
+ description: "For create_trigger: allow bot messages to trigger (default: false)"
15372
+ },
15373
+ trigger_contains: {
15374
+ type: "array",
15375
+ items: { type: "string" },
15376
+ description: 'For create_trigger: keywords to match (case-insensitive OR). E.g., ["failed", "error"].'
15377
+ },
15378
+ trigger_match: {
15379
+ type: "string",
15380
+ description: "For create_trigger: regex pattern to match against message text."
15381
+ },
15382
+ trigger_threads: {
15383
+ type: "string",
15384
+ enum: ["root_only", "thread_only", "any"],
15385
+ description: 'For create_trigger: thread scope filter (default: "any").'
15386
+ },
15387
+ trigger_description: {
15388
+ type: "string",
15389
+ description: "For create_trigger: human-readable description of the trigger."
15390
+ },
15391
+ trigger_id: {
15392
+ type: "string",
15393
+ description: "For delete_trigger/update_trigger: the trigger ID to act on (first 8 chars is enough)."
15394
+ },
15395
+ trigger_enabled: {
15396
+ type: "boolean",
15397
+ description: "For update_trigger: set to false to disable, true to enable."
14883
15398
  }
14884
15399
  },
14885
15400
  required: ["action"]
@@ -40151,8 +40666,8 @@ function buildBuiltinGlobals(opts) {
40151
40666
  const asyncFunctionNames = /* @__PURE__ */ new Set();
40152
40667
  const scheduleFn = async (args = {}) => {
40153
40668
  try {
40154
- const { handleScheduleAction: handleScheduleAction2, buildScheduleToolContext: buildScheduleToolContext2 } = await import("./schedule-tool-NX75VKGA.mjs");
40155
- const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-KKN7XJYT.mjs");
40669
+ const { handleScheduleAction: handleScheduleAction2, buildScheduleToolContext: buildScheduleToolContext2 } = await import("./schedule-tool-NYLNJUEW.mjs");
40670
+ const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-EFQIYD3W.mjs");
40156
40671
  const parentCtx = opts.sessionInfo?._parentContext;
40157
40672
  const webhookData = parentCtx?.prInfo?.eventContext?.webhookData;
40158
40673
  const visorCfg = parentCtx?.config;
@@ -41013,7 +41528,7 @@ var init_worktree_manager = __esm({
41013
41528
  await this.saveMetadata(worktreePath, updatedMetadata);
41014
41529
  if (options.clean) {
41015
41530
  logger.debug(`Cleaning updated worktree`);
41016
- await this.cleanWorktree(worktreePath);
41531
+ await this.cleanWorktree(worktreePath, latestCommit);
41017
41532
  }
41018
41533
  this.activeWorktrees.set(worktreeId, updatedMetadata);
41019
41534
  return {
@@ -41032,7 +41547,7 @@ var init_worktree_manager = __esm({
41032
41547
  }
41033
41548
  if (options.clean) {
41034
41549
  logger.debug(`Cleaning existing worktree`);
41035
- await this.cleanWorktree(worktreePath);
41550
+ await this.cleanWorktree(worktreePath, metadata2.commit);
41036
41551
  }
41037
41552
  this.activeWorktrees.set(worktreeId, metadata2);
41038
41553
  return {
@@ -41074,7 +41589,7 @@ var init_worktree_manager = __esm({
41074
41589
  await this.saveMetadata(worktreePath, updatedMetadata);
41075
41590
  if (options.clean) {
41076
41591
  logger.debug(`Cleaning updated worktree`);
41077
- await this.cleanWorktree(worktreePath);
41592
+ await this.cleanWorktree(worktreePath, newCommit);
41078
41593
  }
41079
41594
  this.activeWorktrees.set(worktreeId, updatedMetadata);
41080
41595
  logger.info(`Successfully updated worktree to ${ref} (${newCommit})`);
@@ -41164,13 +41679,54 @@ var init_worktree_manager = __esm({
41164
41679
  return true;
41165
41680
  }
41166
41681
  /**
41167
- * Clean worktree (reset and remove untracked files)
41168
- */
41169
- async cleanWorktree(worktreePath) {
41682
+ * Clean worktree (reset and remove untracked files).
41683
+ *
41684
+ * When `expectedCommit` is provided the worktree is first forced back to a
41685
+ * detached HEAD at that commit. This is essential because AI agents or user
41686
+ * commands may have created local branches inside the worktree, switching
41687
+ * HEAD away from the detached state. A plain `reset --hard HEAD` would
41688
+ * then reset to the *wrong* commit. After resetting, any local branches
41689
+ * that were created inside the worktree are deleted so they cannot leak
41690
+ * into future runs or PRs.
41691
+ */
41692
+ async cleanWorktree(worktreePath, expectedCommit) {
41693
+ if (expectedCommit) {
41694
+ const detachCmd = `git -C ${this.escapeShellArg(worktreePath)} checkout --detach ${this.escapeShellArg(expectedCommit)}`;
41695
+ const detachResult = await this.executeGitCommand(detachCmd, { timeout: 3e4 });
41696
+ if (detachResult.exitCode !== 0) {
41697
+ await this.executeGitCommand(`git -C ${this.escapeShellArg(worktreePath)} reset --hard`, {
41698
+ timeout: 1e4
41699
+ });
41700
+ await this.executeGitCommand(detachCmd, { timeout: 3e4 });
41701
+ }
41702
+ }
41170
41703
  const resetCmd = `git -C ${this.escapeShellArg(worktreePath)} reset --hard HEAD`;
41171
41704
  await this.executeGitCommand(resetCmd);
41172
41705
  const cleanCmd = `git -C ${this.escapeShellArg(worktreePath)} clean -fdx`;
41173
41706
  await this.executeGitCommand(cleanCmd);
41707
+ await this.deleteLocalBranches(worktreePath);
41708
+ }
41709
+ /**
41710
+ * Delete all local branches in a worktree.
41711
+ * Worktrees are always used in detached HEAD state, so any local branches
41712
+ * were unintentionally created and should be cleaned up.
41713
+ */
41714
+ async deleteLocalBranches(worktreePath) {
41715
+ const listCmd = `git -C ${this.escapeShellArg(worktreePath)} branch --list --format='%(refname:short)'`;
41716
+ const listResult = await this.executeGitCommand(listCmd, { timeout: 1e4 });
41717
+ if (listResult.exitCode !== 0 || !listResult.stdout.trim()) {
41718
+ return;
41719
+ }
41720
+ const branches = listResult.stdout.trim().split("\n").map((b) => b.trim()).filter((b) => b.length > 0);
41721
+ for (const branch of branches) {
41722
+ const deleteCmd = `git -C ${this.escapeShellArg(worktreePath)} branch -D ${this.escapeShellArg(branch)}`;
41723
+ const deleteResult = await this.executeGitCommand(deleteCmd, { timeout: 1e4 });
41724
+ if (deleteResult.exitCode === 0) {
41725
+ logger.debug(`Deleted local branch '${branch}' from worktree`);
41726
+ } else {
41727
+ logger.warn(`Failed to delete branch '${branch}': ${deleteResult.stderr}`);
41728
+ }
41729
+ }
41174
41730
  }
41175
41731
  /**
41176
41732
  * Get commit SHA for a given ref inside a bare repository.
@@ -43156,4 +43712,4 @@ undici/lib/fetch/body.js:
43156
43712
  undici/lib/websocket/frame.js:
43157
43713
  (*! ws. MIT License. Einar Otto Stangvik <einaros@gmail.com> *)
43158
43714
  */
43159
- //# sourceMappingURL=chunk-V6GI4U2M.mjs.map
43715
+ //# sourceMappingURL=chunk-AADKUA6L.mjs.map