@integrity-labs/agt-cli 0.28.422 → 0.28.424

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/agt.js CHANGED
@@ -40,7 +40,7 @@ import {
40
40
  success,
41
41
  table,
42
42
  warn
43
- } from "../chunk-6JC5YLU5.js";
43
+ } from "../chunk-2QBY2QVX.js";
44
44
  import {
45
45
  AnchorSessionClient,
46
46
  CHANNEL_REGISTRY,
@@ -70,7 +70,7 @@ import {
70
70
  renderTemplate,
71
71
  resolveChannels,
72
72
  serializeManifestForSlackCli
73
- } from "../chunk-XFC7YVGS.js";
73
+ } from "../chunk-CWIWI2ZX.js";
74
74
  import "../chunk-XWVM4KPK.js";
75
75
 
76
76
  // src/bin/agt.ts
@@ -4829,7 +4829,7 @@ import { execFileSync, execSync } from "child_process";
4829
4829
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4830
4830
  import chalk18 from "chalk";
4831
4831
  import ora16 from "ora";
4832
- var cliVersion = true ? "0.28.422" : "dev";
4832
+ var cliVersion = true ? "0.28.424" : "dev";
4833
4833
  async function fetchLatestVersion() {
4834
4834
  const host2 = getHost();
4835
4835
  if (!host2) return null;
@@ -6001,7 +6001,7 @@ function handleError(err) {
6001
6001
  }
6002
6002
 
6003
6003
  // src/bin/agt.ts
6004
- var cliVersion2 = true ? "0.28.422" : "dev";
6004
+ var cliVersion2 = true ? "0.28.424" : "dev";
6005
6005
  var program = new Command();
6006
6006
  program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
6007
6007
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -25,7 +25,7 @@ import {
25
25
  resolveConnectivityProbe,
26
26
  worseConnectivityOutcome,
27
27
  wrapScheduledTaskPrompt
28
- } from "./chunk-XFC7YVGS.js";
28
+ } from "./chunk-CWIWI2ZX.js";
29
29
  import {
30
30
  parsePsRows
31
31
  } from "./chunk-XWVM4KPK.js";
@@ -6027,7 +6027,7 @@ function requireHost() {
6027
6027
  }
6028
6028
 
6029
6029
  // src/lib/api-client.ts
6030
- var agtCliVersion = true ? "0.28.422" : "dev";
6030
+ var agtCliVersion = true ? "0.28.424" : "dev";
6031
6031
  var lastConfigHash = null;
6032
6032
  function setConfigHash(hash) {
6033
6033
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -8531,4 +8531,4 @@ export {
8531
8531
  managerInstallSystemUnitCommand,
8532
8532
  managerUninstallSystemUnitCommand
8533
8533
  };
8534
- //# sourceMappingURL=chunk-6JC5YLU5.js.map
8534
+ //# sourceMappingURL=chunk-2QBY2QVX.js.map
@@ -36,6 +36,11 @@ function computeNextFire(kind, expr, every, at, timezone, afterMs) {
36
36
  }
37
37
  return null;
38
38
  }
39
+ var TRIGGER_FRESHNESS_MS = 10 * 6e4;
40
+ function isTriggerFresh(triggeredAtMs, nowMs = Date.now()) {
41
+ if (triggeredAtMs === null) return false;
42
+ return nowMs - triggeredAtMs <= TRIGGER_FRESHNESS_MS;
43
+ }
39
44
  function getStateDir(codeName) {
40
45
  return join(homedir(), ".augmented", codeName);
41
46
  }
@@ -46,7 +51,13 @@ function loadSchedulerState(codeName) {
46
51
  const path = getStatePath(codeName);
47
52
  if (existsSync(path)) {
48
53
  try {
49
- return JSON.parse(readFileSync(path, "utf-8"));
54
+ const parsed = JSON.parse(readFileSync(path, "utf-8"));
55
+ for (const task of Object.values(parsed.tasks ?? {})) {
56
+ if (task.consumedTriggeredAt === void 0) {
57
+ task.consumedTriggeredAt = isTriggerFresh(task.triggeredAt) ? null : task.triggeredAt ?? null;
58
+ }
59
+ }
60
+ return parsed;
50
61
  } catch {
51
62
  }
52
63
  }
@@ -118,6 +129,19 @@ function syncTasksToScheduler(codeName, agentId, tasks) {
118
129
  deliveryTo: t.delivery_to,
119
130
  enabled: t.enabled,
120
131
  triggeredAt: t.triggered_at ? new Date(t.triggered_at).getTime() : null,
132
+ // ENG-8154: a task entering state COLD must not fire a trigger that was
133
+ // already sitting on the row, so a STALE trigger is seeded as consumed.
134
+ // This is the load-bearing line: syncTasksToScheduler deletes any task
135
+ // absent from a sync's task list, so a transient partial list re-adds it
136
+ // here — and before this, the fresh `lastFireAt: null` made `!lastFireAt`
137
+ // true and it fired on the spot, whatever nextFireAt said. That is the
138
+ // ~11-fires-in-75-min engine.
139
+ //
140
+ // A FRESH trigger is left unconsumed so it still fires. That case is
141
+ // real: a task created and immediately "Run now"-ed enters state through
142
+ // this branch carrying a live trigger, and seeding it unconditionally
143
+ // would silently swallow the user's explicit request.
144
+ consumedTriggeredAt: isTriggerFresh(t.triggered_at ? new Date(t.triggered_at).getTime() : null) ? null : t.triggered_at ? new Date(t.triggered_at).getTime() : null,
121
145
  nextFireAt: computeNextFire(
122
146
  t.schedule_kind,
123
147
  t.schedule_expr,
@@ -139,10 +163,7 @@ function getReadyTasks(state, inFlightTaskIds) {
139
163
  const ready = Object.values(state.tasks).filter((t) => {
140
164
  if (!t.enabled) return false;
141
165
  if (inFlightTaskIds?.has(t.taskId)) return false;
142
- if (t.triggeredAt) {
143
- const triggerReady = !t.lastFireAt || t.triggeredAt > t.lastFireAt;
144
- if (triggerReady) return true;
145
- }
166
+ if (t.triggeredAt && t.triggeredAt > (t.consumedTriggeredAt ?? 0)) return true;
146
167
  return t.nextFireAt !== null && t.nextFireAt <= now;
147
168
  });
148
169
  const seen = /* @__PURE__ */ new Set();
@@ -159,6 +180,7 @@ function markTaskFired(codeName, taskId, status) {
159
180
  task.lastFireAt = Date.now();
160
181
  task.lastStatus = status;
161
182
  task.firedCount++;
183
+ if (task.triggeredAt) task.consumedTriggeredAt = task.triggeredAt;
162
184
  if (task.scheduleKind === "at") {
163
185
  task.nextFireAt = null;
164
186
  } else {
@@ -199,4 +221,4 @@ export {
199
221
  findTaskByTemplate,
200
222
  getProjectDir
201
223
  };
202
- //# sourceMappingURL=chunk-EP6E6CIY.js.map
224
+ //# sourceMappingURL=chunk-3HLECXMI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/scheduler-engine.ts"],"sourcesContent":["/**\n * Framework-agnostic scheduled-task state machine.\n *\n * The pure scheduling engine: schedule definitions -> next-fire computation ->\n * ready-task detection -> post-fire state advance, with on-disk persistence so\n * nextFireAt/lastFireAt survive manager restarts. It owns the WHEN, not the HOW:\n * each framework supplies its own firing leaf and calls back into\n * `markTaskFired`.\n * - Claude Code fires via the in-session kanban todo-card route\n * (manager/scheduler/execution.ts + kanban-route.ts).\n * - opencode fires via an HTTP inject into `opencode serve`\n * (manager/opencode-scheduler.ts).\n * Both share this engine verbatim, so cadence, one-shot completion,\n * manual-trigger, and cross-restart recovery are identical across frameworks.\n * (Named claude-scheduler.ts historically, when the claude `-p` oneshot was the\n * only consumer.)\n */\n\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { Cron } from 'croner';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SchedulerTaskState {\n taskId: string;\n templateId: string;\n name: string;\n agentCodeName: string;\n agentId: string;\n scheduleKind: 'cron' | 'every' | 'at';\n scheduleExpr: string | null;\n scheduleEvery: string | null;\n scheduleAt: string | null;\n timezone: string;\n prompt: string;\n sessionTarget: string;\n deliveryMode: string;\n /** ENG-6107: always | conditional | never — whether results deliver.\n * Optional: states persisted by older CLIs lack it; absent = 'always'. */\n deliveryPolicy?: string | null;\n deliveryChannel: string | null;\n /** ENG-4422 §4: JSONB DeliveryTarget (or null). Legacy string form is gone\n * after the migration; in-memory shape is the structured object. */\n deliveryTo: unknown | null;\n enabled: boolean;\n triggeredAt: number | null; // epoch ms — manual trigger from webapp\n /** ENG-8154: the `triggeredAt` value this task has already been fired for.\n * A manual trigger is a ONE-SHOT COMMAND, but `scheduled_tasks.triggered_at`\n * is only ever set server-side and never cleared, so the manager re-reads the\n * same historical trigger on every sync, forever. Consumption used to be\n * inferred from `lastFireAt`, which is null on any cold entry into state —\n * so a task that had ever been triggered re-fired immediately, ignoring its\n * own nextFireAt. Tracking the consumed trigger explicitly makes the trigger\n * idempotent per occurrence and independent of fire history.\n * Optional: states persisted by older CLIs lack it; normalised on load. */\n consumedTriggeredAt?: number | null;\n nextFireAt: number | null; // epoch ms, null = completed one-shot\n lastFireAt: number | null;\n lastStatus: 'ok' | 'error' | null;\n firedCount: number;\n}\n\nexport interface SchedulerState {\n version: 1;\n tasks: Record<string, SchedulerTaskState>;\n updatedAt: string;\n}\n\nexport interface SchedulerTaskInput {\n id: string;\n template_id: string;\n name: string;\n schedule_kind: 'cron' | 'every' | 'at';\n schedule_expr: string | null;\n schedule_every: string | null;\n schedule_at: string | null;\n timezone: string;\n prompt: string;\n session_target: string;\n delivery_mode: string;\n /** ENG-6107: absent from older APIs — treated as 'always'. */\n delivery_policy?: string | null;\n delivery_channel: string | null;\n /** ENG-4422 §4: JSONB DeliveryTarget or null (post-migration). */\n delivery_to: unknown | null;\n enabled: boolean;\n triggered_at?: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Interval parsing (reused from Claude Code adapter)\n// ---------------------------------------------------------------------------\n\nfunction parseIntervalMs(scheduleEvery: string | null): number {\n if (!scheduleEvery) return 60 * 60_000; // 1hr default\n const match = scheduleEvery.match(/^(\\d+)\\s*(m|min|h|hr|d)$/i);\n if (!match) return 60 * 60_000;\n const value = parseInt(match[1]!, 10);\n const unit = match[2]!.toLowerCase();\n if (unit === 'h' || unit === 'hr') return value * 60 * 60_000;\n if (unit === 'd') return value * 24 * 60 * 60_000;\n return value * 60_000; // minutes\n}\n\n// ---------------------------------------------------------------------------\n// Next-fire computation\n// ---------------------------------------------------------------------------\n\nexport function computeNextFire(\n kind: 'cron' | 'every' | 'at',\n expr: string | null,\n every: string | null,\n at: string | null,\n timezone: string,\n afterMs?: number,\n): number | null {\n const now = afterMs ?? Date.now();\n\n if (kind === 'cron' && expr) {\n try {\n const cron = new Cron(expr, { timezone: timezone || undefined });\n const next = cron.nextRun(new Date(now));\n return next ? next.getTime() : null;\n } catch {\n return null;\n }\n }\n\n if (kind === 'every') {\n const intervalMs = parseIntervalMs(every);\n return now + intervalMs;\n }\n\n if (kind === 'at' && at) {\n const ts = new Date(at).getTime();\n if (isNaN(ts)) return null;\n // If the 'at' timestamp is in the past and afterMs is set (meaning we already\n // fired), return null to prevent re-firing on state rebuild.\n if (afterMs && ts <= afterMs) return null;\n return ts;\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// State persistence\n// ---------------------------------------------------------------------------\n\n/**\n * ENG-8154: how recent a `triggered_at` must be to count as a LIVE manual\n * trigger when a task enters scheduler state cold.\n *\n * `scheduled_tasks.triggered_at` is never cleared server-side, so on a cold\n * entry we cannot tell \"the user just hit Run now\" from \"the user hit Run now\n * three days ago\" by presence alone — and treating every cold-seen trigger as\n * live is precisely the defect (a task re-added by a sync fired on the spot,\n * ignoring its own nextFireAt). Age is the only signal available host-side.\n *\n * Sized against the manager's task-sync cadence, ~3 min in the field (the\n * ENG-8154 report shows polls at 06:08 / 06:11 / 06:14 / 06:17), so this allows\n * three missed polls before a genuine trigger is written off. Well under the\n * respawn cadence that produced the stale-trigger storm, and far under the\n * multi-day age of the trigger in the incident.\n *\n * Known trade-off, deliberate: a \"Run now\" issued while the agent is down for\n * longer than this window will not fire on recovery. Firing a much older\n * trigger on an unrelated restart is the worse failure, and it is the one that\n * actually happened. The durable fix is to acknowledge and clear the trigger\n * server-side, which removes the need to guess from age at all.\n */\nconst TRIGGER_FRESHNESS_MS = 10 * 60_000;\n\n/**\n * ENG-8154: is a trigger recent enough to still be owed a run on cold entry?\n * Returns false for null so callers can seed the consumed watermark safely.\n */\nfunction isTriggerFresh(triggeredAtMs: number | null, nowMs = Date.now()): boolean {\n if (triggeredAtMs === null) return false;\n return nowMs - triggeredAtMs <= TRIGGER_FRESHNESS_MS;\n}\n\nfunction getStateDir(codeName: string): string {\n // ENG-4418: unified agent dir — scheduler state lives at the agent root\n // alongside other runtime state files (plugins.json, schedules.json,\n // registration.json). Legacy ~/.augmented/<codeName>/claudecode/scheduler-state.json\n // is migrated up by claudeCodeAdapter.getAgentDir on first poll.\n return join(homedir(), '.augmented', codeName);\n}\n\nfunction getStatePath(codeName: string): string {\n return join(getStateDir(codeName), 'scheduler-state.json');\n}\n\nexport function loadSchedulerState(codeName: string): SchedulerState {\n const path = getStatePath(codeName);\n if (existsSync(path)) {\n try {\n const parsed: SchedulerState = JSON.parse(readFileSync(path, 'utf-8'));\n // ENG-8154 upgrade normalisation. A state file written by an older CLI has\n // no `consumedTriggeredAt`. Seeding it from the CURRENT `triggeredAt`\n // treats any trigger already on the task as consumed, so upgrading does not\n // itself fire a historical trigger — which is the exact bug being fixed.\n // A genuinely new manual trigger arrives with a LATER timestamp and still\n // fires normally.\n for (const task of Object.values(parsed.tasks ?? {})) {\n if (task.consumedTriggeredAt === undefined) {\n // Same freshness rule as the cold-add path: a trigger still inside the\n // window was plausibly issued moments ago and is left owed, anything\n // older is written off so upgrading cannot fire history.\n task.consumedTriggeredAt = isTriggerFresh(task.triggeredAt) ? null : (task.triggeredAt ?? null);\n }\n }\n return parsed;\n } catch { /* corrupted — start fresh */ }\n }\n return { version: 1, tasks: {}, updatedAt: new Date().toISOString() };\n}\n\nexport function saveSchedulerState(codeName: string, state: SchedulerState): void {\n const dir = getStateDir(codeName);\n mkdirSync(dir, { recursive: true });\n state.updatedAt = new Date().toISOString();\n const path = getStatePath(codeName);\n const tmpPath = path + '.tmp';\n writeFileSync(tmpPath, JSON.stringify(state, null, 2));\n renameSync(tmpPath, path);\n}\n\n// ---------------------------------------------------------------------------\n// Sync API tasks → scheduler state\n// ---------------------------------------------------------------------------\n\nexport function syncTasksToScheduler(\n codeName: string,\n agentId: string,\n tasks: SchedulerTaskInput[],\n): SchedulerState {\n const state = loadSchedulerState(codeName);\n const desiredIds = new Set(tasks.map((t) => t.id));\n\n // Remove tasks no longer in API\n for (const id of Object.keys(state.tasks)) {\n if (!desiredIds.has(id)) {\n delete state.tasks[id];\n }\n }\n\n // Add or update tasks\n for (const t of tasks) {\n const existing = state.tasks[t.id];\n if (existing) {\n // Only recompute nextFireAt if the schedule definition actually changed.\n // Without this guard, every sync cycle resets nextFireAt from \"now\",\n // preventing past-due tasks from ever being detected as ready.\n const scheduleChanged =\n existing.scheduleKind !== t.schedule_kind ||\n existing.scheduleExpr !== t.schedule_expr ||\n existing.scheduleEvery !== t.schedule_every ||\n existing.scheduleAt !== t.schedule_at ||\n existing.timezone !== t.timezone;\n\n // Update mutable fields, preserve fire history\n existing.name = t.name;\n existing.templateId = t.template_id;\n existing.scheduleKind = t.schedule_kind;\n existing.scheduleExpr = t.schedule_expr;\n existing.scheduleEvery = t.schedule_every;\n existing.scheduleAt = t.schedule_at;\n existing.timezone = t.timezone;\n existing.prompt = t.prompt;\n existing.sessionTarget = t.session_target;\n existing.deliveryMode = t.delivery_mode;\n existing.deliveryPolicy = t.delivery_policy ?? 'always';\n existing.deliveryChannel = t.delivery_channel;\n existing.deliveryTo = t.delivery_to;\n existing.enabled = t.enabled;\n if (t.triggered_at) existing.triggeredAt = new Date(t.triggered_at).getTime();\n if (scheduleChanged) {\n existing.nextFireAt = computeNextFire(\n t.schedule_kind, t.schedule_expr, t.schedule_every, t.schedule_at,\n t.timezone, existing.lastFireAt ?? undefined,\n );\n }\n } else {\n // New task\n state.tasks[t.id] = {\n taskId: t.id,\n templateId: t.template_id,\n name: t.name,\n agentCodeName: codeName,\n agentId,\n scheduleKind: t.schedule_kind,\n scheduleExpr: t.schedule_expr,\n scheduleEvery: t.schedule_every,\n scheduleAt: t.schedule_at,\n timezone: t.timezone,\n prompt: t.prompt,\n sessionTarget: t.session_target,\n deliveryMode: t.delivery_mode,\n deliveryPolicy: t.delivery_policy ?? 'always',\n deliveryChannel: t.delivery_channel,\n deliveryTo: t.delivery_to,\n enabled: t.enabled,\n triggeredAt: t.triggered_at ? new Date(t.triggered_at).getTime() : null,\n // ENG-8154: a task entering state COLD must not fire a trigger that was\n // already sitting on the row, so a STALE trigger is seeded as consumed.\n // This is the load-bearing line: syncTasksToScheduler deletes any task\n // absent from a sync's task list, so a transient partial list re-adds it\n // here — and before this, the fresh `lastFireAt: null` made `!lastFireAt`\n // true and it fired on the spot, whatever nextFireAt said. That is the\n // ~11-fires-in-75-min engine.\n //\n // A FRESH trigger is left unconsumed so it still fires. That case is\n // real: a task created and immediately \"Run now\"-ed enters state through\n // this branch carrying a live trigger, and seeding it unconditionally\n // would silently swallow the user's explicit request.\n consumedTriggeredAt: isTriggerFresh(t.triggered_at ? new Date(t.triggered_at).getTime() : null)\n ? null\n : (t.triggered_at ? new Date(t.triggered_at).getTime() : null),\n nextFireAt: computeNextFire(\n t.schedule_kind, t.schedule_expr, t.schedule_every, t.schedule_at, t.timezone,\n ),\n lastFireAt: null,\n lastStatus: null,\n firedCount: 0,\n };\n }\n }\n\n saveSchedulerState(codeName, state);\n return state;\n}\n\n// ---------------------------------------------------------------------------\n// Ready-task detection\n// ---------------------------------------------------------------------------\n\n// ENG-4675: pass `inFlightTaskIds` so the manager's poll loop doesn't\n// re-detect tasks that already have a `claude -p` subprocess running.\n// Without this, every supervisor tick (~17s) saw the manual trigger as\n// still ready (because lastFireAt is only set on completion, not on\n// fire start), spamming \"N ready task(s)\" + \"Firing task\" log lines that\n// looked like duplicate fires. The in-flight guard at the spawn site\n// prevented actual duplicate subprocesses, but the log was misleading.\nexport function getReadyTasks(\n state: SchedulerState,\n inFlightTaskIds?: ReadonlySet<string>,\n): SchedulerTaskState[] {\n const now = Date.now();\n const ready = Object.values(state.tasks).filter((t) => {\n if (!t.enabled) return false;\n if (inFlightTaskIds?.has(t.taskId)) return false;\n // Manual trigger: triggered_at is set and this exact trigger hasn't been\n // consumed yet. ENG-8154: consumption is tracked explicitly rather than\n // inferred from `lastFireAt`. The old test (`!t.lastFireAt || ...`) treated\n // \"we have no fire history\" as \"this trigger is pending\", so any cold entry\n // into scheduler state re-fired a long-dead trigger and — because this\n // branch returns before the nextFireAt check below — did so regardless of\n // when the task was actually next due.\n if (t.triggeredAt && t.triggeredAt > (t.consumedTriggeredAt ?? 0)) return true;\n // Normal schedule\n return t.nextFireAt !== null && t.nextFireAt <= now;\n });\n // Deduplicate by templateId — only fire one task per template per cycle\n const seen = new Set<string>();\n return ready.filter((t) => {\n if (seen.has(t.templateId)) return false;\n seen.add(t.templateId);\n return true;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Post-execution state update\n// ---------------------------------------------------------------------------\n\nexport function markTaskFired(\n codeName: string,\n taskId: string,\n status: 'ok' | 'error',\n): SchedulerState {\n const state = loadSchedulerState(codeName);\n const task = state.tasks[taskId];\n if (!task) return state;\n\n task.lastFireAt = Date.now();\n task.lastStatus = status;\n task.firedCount++;\n // ENG-8154: whatever caused this fire, the trigger currently on the task is\n // now spent. Recording it here (rather than relying on lastFireAt ordering)\n // keeps the trigger one-shot even if the fire-history watermark is later lost.\n if (task.triggeredAt) task.consumedTriggeredAt = task.triggeredAt;\n\n // Compute next fire\n if (task.scheduleKind === 'at') {\n // One-shot — mark as completed\n task.nextFireAt = null;\n } else {\n task.nextFireAt = computeNextFire(\n task.scheduleKind, task.scheduleExpr, task.scheduleEvery, task.scheduleAt,\n task.timezone, task.lastFireAt,\n );\n }\n\n // Persisting is best-effort: the SchedulerState the caller stores in memory\n // (claudeSchedulerStates) is the running source of truth — getReadyTasks\n // reads it, not the disk file. A disk-write failure (ENOSPC/EACCES) must NOT\n // throw, or the caller's in-memory state would never advance and the task\n // would be treated as ready again next poll (ENG-5599: a duplicate\n // scheduled-task card materialised every tick). The mutated `state` is\n // returned regardless; cross-restart recovery is a separate concern.\n try {\n saveSchedulerState(codeName, state);\n } catch (err) {\n console.error(\n `[scheduler-engine] markTaskFired: failed to persist state for '${codeName}': ${(err as Error).message}`,\n );\n }\n return state;\n}\n\n// ---------------------------------------------------------------------------\n// Find a task by template ID (for work triggers)\n// ---------------------------------------------------------------------------\n\nexport function findTaskByTemplate(state: SchedulerState, templateId: string): SchedulerTaskState | undefined {\n return Object.values(state.tasks).find(\n (t) => t.templateId === templateId && t.enabled,\n );\n}\n\nexport function getProjectDir(codeName: string): string {\n return join(homedir(), '.augmented', codeName, 'project');\n}\n"],"mappings":"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","names":[]}
@@ -12745,4 +12745,4 @@ export {
12745
12745
  stopAllSessionsAndWait,
12746
12746
  getProjectDir
12747
12747
  };
12748
- //# sourceMappingURL=chunk-XFC7YVGS.js.map
12748
+ //# sourceMappingURL=chunk-CWIWI2ZX.js.map