@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-
|
|
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.
|
|
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.
|
|
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.
|
|
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-
|
|
8105
|
+
//# sourceMappingURL=chunk-2ARDOUIX.js.map
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
requireHost,
|
|
38
38
|
safeWriteJsonAtomic,
|
|
39
39
|
setConfigHash
|
|
40
|
-
} from "../chunk-
|
|
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.
|
|
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();
|