@integrity-labs/agt-cli 0.28.250 → 0.28.251

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
@@ -38,7 +38,7 @@ import {
38
38
  success,
39
39
  table,
40
40
  warn
41
- } from "../chunk-FQBAABKO.js";
41
+ } from "../chunk-2ARDOUIX.js";
42
42
  import {
43
43
  CHANNEL_REGISTRY,
44
44
  DEFAULT_FRAMEWORK,
@@ -4826,7 +4826,7 @@ import { execFileSync, execSync } from "child_process";
4826
4826
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4827
4827
  import chalk18 from "chalk";
4828
4828
  import ora16 from "ora";
4829
- var cliVersion = true ? "0.28.250" : "dev";
4829
+ var cliVersion = true ? "0.28.251" : "dev";
4830
4830
  async function fetchLatestVersion() {
4831
4831
  const host2 = getHost();
4832
4832
  if (!host2) return null;
@@ -5840,7 +5840,7 @@ function handleError(err) {
5840
5840
  }
5841
5841
 
5842
5842
  // src/bin/agt.ts
5843
- var cliVersion2 = true ? "0.28.250" : "dev";
5843
+ var cliVersion2 = true ? "0.28.251" : "dev";
5844
5844
  var program = new Command();
5845
5845
  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");
5846
5846
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -5832,7 +5832,7 @@ function requireHost() {
5832
5832
  }
5833
5833
 
5834
5834
  // src/lib/api-client.ts
5835
- var agtCliVersion = true ? "0.28.250" : "dev";
5835
+ var agtCliVersion = true ? "0.28.251" : "dev";
5836
5836
  var lastConfigHash = null;
5837
5837
  function setConfigHash(hash) {
5838
5838
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -8102,4 +8102,4 @@ export {
8102
8102
  managerInstallSystemUnitCommand,
8103
8103
  managerUninstallSystemUnitCommand
8104
8104
  };
8105
- //# sourceMappingURL=chunk-FQBAABKO.js.map
8105
+ //# sourceMappingURL=chunk-2ARDOUIX.js.map
@@ -37,7 +37,7 @@ import {
37
37
  requireHost,
38
38
  safeWriteJsonAtomic,
39
39
  setConfigHash
40
- } from "../chunk-FQBAABKO.js";
40
+ } from "../chunk-2ARDOUIX.js";
41
41
  import {
42
42
  getProjectDir as getProjectDir2,
43
43
  getReadyTasks,
@@ -2358,6 +2358,114 @@ function readRecentTurns(dir, nowMs) {
2358
2358
  return turns;
2359
2359
  }
2360
2360
 
2361
+ // src/lib/routine-candidate-extractor.ts
2362
+ var VALID_CADENCE_GUESSES = /* @__PURE__ */ new Set(["daily", "weekdays", "weekly", "unknown"]);
2363
+ var MAX_ASK_CHARS = 400;
2364
+ var MAX_INPUT_CHARS = 6e3;
2365
+ function buildUserAsksInput(turns) {
2366
+ const lines = [];
2367
+ let total = 0;
2368
+ for (const turn of turns) {
2369
+ if (turn.role !== "user") continue;
2370
+ const body = turn.text.length > MAX_ASK_CHARS ? `${turn.text.slice(0, MAX_ASK_CHARS)}\u2026` : turn.text;
2371
+ const line = `User: ${body}`;
2372
+ if (total + line.length > MAX_INPUT_CHARS) break;
2373
+ lines.push(line);
2374
+ total += line.length;
2375
+ }
2376
+ return lines.join("\n");
2377
+ }
2378
+ function buildRoutinePrompt(channel, userAsks) {
2379
+ return `You are looking for a DURABLE RECURRING ASK in the user's messages from one completed ${channel} conversation with an AI agent. A routine candidate is something the user asks for repeatedly or explicitly wants on a schedule ("every morning", "each Friday", "again" for the third time) - not a one-off task.
2380
+
2381
+ User messages (agent replies deliberately omitted):
2382
+ """
2383
+ ${userAsks}
2384
+ """
2385
+
2386
+ Extract 0-2 routine candidates. For each:
2387
+ - description: the recurring ask, self-contained and generic (max 200 chars). No secrets, no personal data beyond what is needed to name the task.
2388
+ - cadence_guess: "daily", "weekdays", "weekly", or "unknown" if the messages imply repetition without a clear cadence
2389
+ - evidence_count: how many of the user messages above support this ask (integer >= 1)
2390
+ - confidence: 0.0-1.0 - how sure you are this is a genuine recurring responsibility
2391
+
2392
+ Most conversations contain NO routine candidate - return an empty array unless the recurrence signal is clear. Do NOT invent candidates.
2393
+
2394
+ Respond with ONLY a JSON array, no other text:
2395
+ [{"description":"...","cadence_guess":"daily","evidence_count":2,"confidence":0.7}]`;
2396
+ }
2397
+ function parseRoutineCandidates(raw) {
2398
+ const match = raw.match(/\[[\s\S]*\]/);
2399
+ if (!match) return null;
2400
+ let arr;
2401
+ try {
2402
+ arr = JSON.parse(match[0]);
2403
+ } catch {
2404
+ return null;
2405
+ }
2406
+ if (!Array.isArray(arr)) return null;
2407
+ const out = [];
2408
+ for (const entry of arr) {
2409
+ if (!entry || typeof entry !== "object") continue;
2410
+ const c = entry;
2411
+ const description = typeof c.description === "string" ? c.description.trim() : "";
2412
+ if (!description) continue;
2413
+ const confidence = typeof c.confidence === "number" && Number.isFinite(c.confidence) ? Math.max(0, Math.min(1, c.confidence)) : 0;
2414
+ if (confidence === 0) continue;
2415
+ const cadence = typeof c.cadence_guess === "string" && VALID_CADENCE_GUESSES.has(c.cadence_guess) ? c.cadence_guess : "unknown";
2416
+ const evidenceRaw = typeof c.evidence_count === "number" && Number.isFinite(c.evidence_count) ? Math.floor(c.evidence_count) : 1;
2417
+ out.push({
2418
+ // Bounded parse only - the FINAL 200-char truncation happens after
2419
+ // scrubbing (maybeEmitRoutineCandidates), because slicing first can
2420
+ // split a secret across the cut so the scrub regex no longer matches
2421
+ // and a fragment leaks onto the wire.
2422
+ description: description.slice(0, 500),
2423
+ cadence_guess: cadence,
2424
+ evidence_count: Math.max(1, Math.min(50, evidenceRaw)),
2425
+ confidence
2426
+ });
2427
+ }
2428
+ return out;
2429
+ }
2430
+ async function maybeEmitRoutineCandidates(args) {
2431
+ const { api: api2, backend, codeName, agentId, conversationId, channel, turns, log: log2 } = args;
2432
+ try {
2433
+ const userAsks = buildUserAsksInput(turns);
2434
+ if (!userAsks.trim()) return;
2435
+ let candidates;
2436
+ try {
2437
+ const out = await backend.run(buildRoutinePrompt(channel, userAsks));
2438
+ candidates = parseRoutineCandidates(out);
2439
+ } catch (err) {
2440
+ log2(`[routine-extract] ${codeName}: extraction failed: ${err.message}`);
2441
+ args.onModelCallError?.(err);
2442
+ return;
2443
+ }
2444
+ if (!candidates || candidates.length === 0) return;
2445
+ const scrubbed = candidates.map((c) => ({
2446
+ ...c,
2447
+ description: scrubSensitive(c.description).slice(0, 200)
2448
+ }));
2449
+ try {
2450
+ const res = await api2.post(
2451
+ "/host/routines/candidates",
2452
+ {
2453
+ agent_id: agentId,
2454
+ conversation_id: conversationId,
2455
+ candidates: scrubbed
2456
+ }
2457
+ );
2458
+ log2(
2459
+ `[routine-extract] ${codeName}: ${conversationId.slice(0, 8)} \u2192 ${scrubbed.length} candidate(s)${res?.discarded ? " (discarded: feature off)" : ""}`
2460
+ );
2461
+ } catch (err) {
2462
+ log2(`[routine-extract] ${codeName}: report failed: ${err.message}`);
2463
+ }
2464
+ } catch (err) {
2465
+ log2(`[routine-extract] ${codeName}: unexpected error: ${err.message}`);
2466
+ }
2467
+ }
2468
+
2361
2469
  // src/lib/memory-extractor.ts
2362
2470
  var MIN_CHECK_INTERVAL_MS5 = 10 * 6e4;
2363
2471
  var WINDOW_PAD_MS2 = 5 * 6e4;
@@ -2503,6 +2611,17 @@ async function maybeExtractMemories(args) {
2503
2611
  } catch (err) {
2504
2612
  log2(`[memory-extract] ${codeName}: report failed: ${err.message}`);
2505
2613
  }
2614
+ await maybeEmitRoutineCandidates({
2615
+ api: api2,
2616
+ backend,
2617
+ codeName,
2618
+ agentId,
2619
+ conversationId: conv.conversation_id,
2620
+ channel: conv.channel,
2621
+ turns,
2622
+ log: log2,
2623
+ onModelCallError: args.onModelCallError
2624
+ });
2506
2625
  }
2507
2626
  }
2508
2627
  async function reportSkip2(api2, agentId, conversationId, log2, codeName) {
@@ -6520,7 +6639,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
6520
6639
  var lastVersionCheckAt = 0;
6521
6640
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
6522
6641
  var lastResponsivenessProbeAt = 0;
6523
- var agtCliVersion = true ? "0.28.250" : "dev";
6642
+ var agtCliVersion = true ? "0.28.251" : "dev";
6524
6643
  function resolveBrewPath(execFileSync2) {
6525
6644
  try {
6526
6645
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();