@tekmidian/pai 0.14.0 → 0.14.2

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.
@@ -6,7 +6,7 @@ import "../db-CmYbAVCD.mjs";
6
6
  import "../helpers-IjZkXBhj.mjs";
7
7
  import "../embeddings-BJPOcbik.mjs";
8
8
  import "../search-HcdKtMla.mjs";
9
- import "../pick-DxS6p2vI.mjs";
9
+ import "../pick-gne3kOJG.mjs";
10
10
  import "../kg-extraction-C8DEUHTS.mjs";
11
11
  import "../factory-Q88X1bAN.mjs";
12
12
  import "../config-C8m-tPhP.mjs";
@@ -5,7 +5,7 @@ import "../db-CmYbAVCD.mjs";
5
5
  import "../helpers-IjZkXBhj.mjs";
6
6
  import "../embeddings-BJPOcbik.mjs";
7
7
  import "../search-HcdKtMla.mjs";
8
- import { C as registerDaemonCommands, D as registerProjectsCommands, E as registerRegistryCommands, O as findMovedPath, S as registerBackupCommands, T as registerMemoryCommands, _ as registerObservationCommands, a as cmdPauseAll, b as registerSetupCommand, c as cmdPause, d as registerKgCommands, f as registerTopicCommands, g as registerSkillCommands, h as registerUpdateCommand, i as cmdClearNames, k as resolveIdentifier, l as registerHelpCommand, m as registerNotifyCommands, n as cmdFind, o as cmdGoto, p as registerTaskCommands, r as cmdList, s as cmdEnd, t as cmdPick, u as registerDbCommands, v as registerZettelCommands, w as registerMcpCommands, x as registerRestoreCommands, y as registerObsidianCommands } from "../pick-DxS6p2vI.mjs";
8
+ import { C as registerDaemonCommands, D as registerProjectsCommands, E as registerRegistryCommands, O as findMovedPath, S as registerBackupCommands, T as registerMemoryCommands, _ as registerObservationCommands, a as cmdPauseAll, b as registerSetupCommand, c as cmdPause, d as registerKgCommands, f as registerTopicCommands, g as registerSkillCommands, h as registerUpdateCommand, i as cmdClearNames, k as resolveIdentifier, l as registerHelpCommand, m as registerNotifyCommands, n as cmdFind, o as cmdGoto, p as registerTaskCommands, r as cmdList, s as cmdEnd, t as cmdPick, u as registerDbCommands, v as registerZettelCommands, w as registerMcpCommands, x as registerRestoreCommands, y as registerObsidianCommands } from "../pick-gne3kOJG.mjs";
9
9
  import "../kg-extraction-C8DEUHTS.mjs";
10
10
  import "../factory-Q88X1bAN.mjs";
11
11
  import "../config-C8m-tPhP.mjs";
@@ -6786,27 +6786,30 @@ var AiBrokerProber = class {
6786
6786
  ], question, this.timeoutSecs * 1e3 + KILL_MARGIN_MS);
6787
6787
  } catch (e) {
6788
6788
  return {
6789
- replied: false,
6789
+ state: "silent",
6790
6790
  reason: e instanceof Error ? e.message : String(e)
6791
6791
  };
6792
6792
  }
6793
6793
  const start = stdout.lastIndexOf("{");
6794
6794
  if (start === -1) return {
6795
- replied: false,
6795
+ state: "silent",
6796
6796
  reason: "aibroker returned no JSON"
6797
6797
  };
6798
6798
  try {
6799
6799
  const wire = JSON.parse(stdout.slice(start));
6800
- return wire.replied === true ? {
6801
- replied: true,
6802
- reply: wire.reply
6803
- } : {
6804
- replied: false,
6805
- reason: wire.reason ?? "no reply"
6800
+ const state = wire.state ?? (wire.replied === true ? "replied" : "silent");
6801
+ if (state === "replied" || state === "busy" || state === "silent" || state === "absent") return {
6802
+ state,
6803
+ reply: wire.reply,
6804
+ reason: wire.reason
6805
+ };
6806
+ return {
6807
+ state: "silent",
6808
+ reason: `unexpected state from aibroker: ${String(wire.state)}`
6806
6809
  };
6807
6810
  } catch {
6808
6811
  return {
6809
- replied: false,
6812
+ state: "silent",
6810
6813
  reason: "aibroker returned malformed JSON"
6811
6814
  };
6812
6815
  }
@@ -7005,8 +7008,11 @@ const HISTORY_LIMIT = 5;
7005
7008
  const EMPTY = {
7006
7009
  ...EMPTY_RUN_STATE,
7007
7010
  history: {},
7008
- lastReported: {}
7011
+ lastReported: {},
7012
+ failedDispatches: {}
7009
7013
  };
7014
+ /** Consecutive failed dispatches before a task is reported as needing attention. */
7015
+ const DISPATCH_FAILURES_BEFORE_ALARM = 3;
7010
7016
  /**
7011
7017
  * Run state is a rebuildable cache, so a damaged file must not block the
7012
7018
  * scheduler forever — starting fresh is the correct recovery here, which is
@@ -7026,6 +7032,12 @@ function loadState$1() {
7026
7032
  function saveState$1(state) {
7027
7033
  writeJsonAtomic(STATE_FILE$1, state, { backup: false });
7028
7034
  }
7035
+ /**
7036
+ * Multiple of the expected duration past which a task is flagged even though it
7037
+ * keeps reporting `busy`. A session can be alive and still wrong — stuck in a
7038
+ * loop, waiting on a prompt that will never come. Liveness is not progress.
7039
+ */
7040
+ const GROSS_OVERRUN_FACTOR = 5;
7029
7041
  async function tick(opts) {
7030
7042
  const now = opts.now ?? Date.now();
7031
7043
  const state = loadState$1();
@@ -7052,10 +7064,15 @@ async function tick(opts) {
7052
7064
  case "running":
7053
7065
  note = `${d.elapsedMinutes}m elapsed`;
7054
7066
  break;
7055
- case "dispatch":
7056
- note = await handleDispatch(task, d.overdueMinutes, opts, state, now);
7057
- if (!opts.dryRun) report.dispatched++;
7067
+ case "dispatch": {
7068
+ const r = await handleDispatch(task, d.overdueMinutes, opts, state, now);
7069
+ note = r.note;
7070
+ if (!opts.dryRun) {
7071
+ report.dispatched++;
7072
+ if (r.alarm) report.stuck++;
7073
+ }
7058
7074
  break;
7075
+ }
7059
7076
  case "complete":
7060
7077
  note = await handleComplete(task, d.durationMinutes, opts, state);
7061
7078
  if (!opts.dryRun) report.completed++;
@@ -7081,8 +7098,14 @@ async function tick(opts) {
7081
7098
  }
7082
7099
  async function handleDispatch(task, overdue, opts, state, now) {
7083
7100
  const late = overdue > 5 ? ` (${overdue}m late)` : "";
7084
- if (opts.dryRun) return `would dispatch to ${task.owner.project ?? "nobody"}${late}`;
7085
- if (!task.owner.project) return "unrouted — cannot dispatch";
7101
+ if (opts.dryRun) return {
7102
+ note: `would dispatch to ${task.owner.project ?? "nobody"}${late}`,
7103
+ alarm: false
7104
+ };
7105
+ if (!task.owner.project) return {
7106
+ note: "unrouted — cannot dispatch",
7107
+ alarm: false
7108
+ };
7086
7109
  const result = await dispatchTask(task, {
7087
7110
  transport: opts.transport,
7088
7111
  autoDispatch: opts.autoDispatch,
@@ -7092,9 +7115,23 @@ async function handleDispatch(task, overdue, opts, state, now) {
7092
7115
  await opts.provider.setLabels(task.id, [...task.labels, RUNNING_LABEL]);
7093
7116
  state.startedAt[task.id] = now;
7094
7117
  delete state.failedProbes[task.id];
7095
- return `${result.outcome} to ${result.session}${late}`;
7118
+ delete state.failedDispatches[task.id];
7119
+ return {
7120
+ note: `${result.outcome} to ${result.session}${late}`,
7121
+ alarm: false
7122
+ };
7096
7123
  }
7097
- return `not dispatched: ${result.outcome}${result.reason ? " — " + result.reason : ""}`;
7124
+ const fails = (state.failedDispatches[task.id] ?? 0) + 1;
7125
+ state.failedDispatches[task.id] = fails;
7126
+ const detail = `${result.outcome}${result.reason ? " — " + result.reason : ""}`;
7127
+ if (fails >= DISPATCH_FAILURES_BEFORE_ALARM) return {
7128
+ note: `NOT RUNNING — ${fails} failed dispatches: ${detail}`,
7129
+ alarm: true
7130
+ };
7131
+ return {
7132
+ note: `not dispatched (${fails}/${DISPATCH_FAILURES_BEFORE_ALARM}): ${detail}`,
7133
+ alarm: false
7134
+ };
7098
7135
  }
7099
7136
  async function handleComplete(task, durationMinutes, opts, state) {
7100
7137
  if (opts.dryRun) return `would clear ${RUNNING_LABEL}, ${durationMinutes ?? "?"}m`;
@@ -7121,21 +7158,30 @@ async function handleProbe(task, elapsed, opts, state) {
7121
7158
  stuck: false
7122
7159
  };
7123
7160
  const answer = await opts.prober.ask(project, `Are you still working on the task "${task.title}"? Reply in one short line.`);
7124
- if (answer.replied) {
7161
+ if (answer.state === "replied" || answer.state === "busy") {
7125
7162
  state.failedProbes[task.id] = 0;
7126
- return {
7163
+ const expected = expectedMinutes(state.history[task.id] ?? []);
7164
+ if (elapsed !== null && elapsed > expected * GROSS_OVERRUN_FACTOR) return {
7165
+ note: `alive but ${el} against an expected ${expected}m — ${GROSS_OVERRUN_FACTOR}x over, worth a look`,
7166
+ stuck: true
7167
+ };
7168
+ return answer.state === "busy" ? {
7169
+ note: `busy after ${el} (mid-turn, nothing sent)`,
7170
+ stuck: false
7171
+ } : {
7127
7172
  note: `alive after ${el}: ${answer.reply ?? "(no detail)"}`,
7128
7173
  stuck: false
7129
7174
  };
7130
7175
  }
7131
7176
  const fails = (state.failedProbes[task.id] ?? 0) + 1;
7132
7177
  state.failedProbes[task.id] = fails;
7178
+ const what = answer.state === "absent" ? "session gone" : "no reply";
7133
7179
  if (fails >= STUCK_AFTER_FAILED_PROBES) return {
7134
- note: `STUCK after ${el} and ${fails} unanswered probes (${answer.reason ?? "no reply"}) — needs attention`,
7180
+ note: `STUCK after ${el} ${what} x${fails} (${answer.reason ?? "no detail"})`,
7135
7181
  stuck: true
7136
7182
  };
7137
7183
  return {
7138
- note: `no reply ${fails}/${STUCK_AFTER_FAILED_PROBES} after ${el}`,
7184
+ note: `${what} ${fails}/${STUCK_AFTER_FAILED_PROBES} after ${el}`,
7139
7185
  stuck: false
7140
7186
  };
7141
7187
  }
@@ -9661,4 +9707,4 @@ async function cmdPick(db, opts = {}) {
9661
9707
 
9662
9708
  //#endregion
9663
9709
  export { registerDaemonCommands as C, registerProjectsCommands as D, registerRegistryCommands as E, findMovedPath as O, registerBackupCommands as S, registerMemoryCommands as T, registerObservationCommands as _, cmdPauseAll as a, registerSetupCommand as b, cmdPause as c, registerKgCommands as d, registerTopicCommands as f, registerSkillCommands as g, registerUpdateCommand as h, cmdClearNames as i, resolveIdentifier as k, registerHelpCommand as l, registerNotifyCommands as m, cmdFind as n, cmdGoto as o, registerTaskCommands as p, cmdList as r, cmdEnd as s, cmdPick as t, registerDbCommands as u, registerZettelCommands as v, registerMcpCommands as w, registerRestoreCommands as x, registerObsidianCommands as y };
9664
- //# sourceMappingURL=pick-DxS6p2vI.mjs.map
9710
+ //# sourceMappingURL=pick-gne3kOJG.mjs.map