@integrity-labs/agt-cli 0.28.249 → 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) {
|
|
@@ -6098,7 +6217,7 @@ function verifyPendingRestarts(now) {
|
|
|
6098
6217
|
log(`[restart-verify] '${codeName}' respawned healthy after MCP change \u2014 tools bound (ENG-6174)`);
|
|
6099
6218
|
finishRestartTiming(codeName, "tools-bound", void 0, log, now);
|
|
6100
6219
|
if (hostFlagStore().getBoolean("session-tool-probe")) {
|
|
6101
|
-
|
|
6220
|
+
promptBindProbeAttempts.set(codeName, PROMPT_BIND_PROBE_ATTEMPTS);
|
|
6102
6221
|
}
|
|
6103
6222
|
break;
|
|
6104
6223
|
case "waiting":
|
|
@@ -6278,7 +6397,8 @@ var SESSION_TOOL_REBIND_COOLDOWN_MS = 10 * 60 * 1e3;
|
|
|
6278
6397
|
function sessionToolRebindKey(codeName, serverKey) {
|
|
6279
6398
|
return `${codeName}\0${serverKey}`;
|
|
6280
6399
|
}
|
|
6281
|
-
var
|
|
6400
|
+
var promptBindProbeAttempts = /* @__PURE__ */ new Map();
|
|
6401
|
+
var PROMPT_BIND_PROBE_ATTEMPTS = 6;
|
|
6282
6402
|
async function runAgentSessionToolBindProbes(agent, integrations, projectDir, opts) {
|
|
6283
6403
|
if (integrations.length === 0) return true;
|
|
6284
6404
|
const intervalSec = Number(process.env.AGT_CONNECTIVITY_PROBE_INTERVAL_SECONDS) || 3600;
|
|
@@ -6519,7 +6639,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
6519
6639
|
var lastVersionCheckAt = 0;
|
|
6520
6640
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
6521
6641
|
var lastResponsivenessProbeAt = 0;
|
|
6522
|
-
var agtCliVersion = true ? "0.28.
|
|
6642
|
+
var agtCliVersion = true ? "0.28.251" : "dev";
|
|
6523
6643
|
function resolveBrewPath(execFileSync2) {
|
|
6524
6644
|
try {
|
|
6525
6645
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -7928,6 +8048,9 @@ async function pollCycle() {
|
|
|
7928
8048
|
if (fastRespawn && restartAcks.has(agent.agent_id) && isSessionHealthy(agent.code_name)) {
|
|
7929
8049
|
flushRestartedAgentDiagnostics(hostId, [agent.code_name]);
|
|
7930
8050
|
}
|
|
8051
|
+
if (restartAcks.has(agent.agent_id) && isSessionHealthy(agent.code_name) && hostFlagStore().getBoolean("session-tool-probe")) {
|
|
8052
|
+
promptBindProbeAttempts.set(agent.code_name, PROMPT_BIND_PROBE_ATTEMPTS);
|
|
8053
|
+
}
|
|
7931
8054
|
}
|
|
7932
8055
|
void maybeReportActivityCache({ api, log });
|
|
7933
8056
|
const restartAckStateChanged = applyRestartAcks({
|
|
@@ -9089,7 +9212,8 @@ async function processAgent(agent, agentStates) {
|
|
|
9089
9212
|
}
|
|
9090
9213
|
}
|
|
9091
9214
|
if (hostFlagStore().getBoolean("session-tool-probe")) {
|
|
9092
|
-
const
|
|
9215
|
+
const attemptsLeft = promptBindProbeAttempts.get(agent.code_name) ?? 0;
|
|
9216
|
+
const forceDue = attemptsLeft > 0;
|
|
9093
9217
|
let probeRan = false;
|
|
9094
9218
|
try {
|
|
9095
9219
|
const probeProjectDir = join16(homedir9(), ".augmented", agent.code_name, "project");
|
|
@@ -9097,7 +9221,11 @@ async function processAgent(agent, agentStates) {
|
|
|
9097
9221
|
} catch (err) {
|
|
9098
9222
|
log(`Session-tool-bind probe failed for '${agent.code_name}': ${err.message}`);
|
|
9099
9223
|
}
|
|
9100
|
-
if (forceDue &&
|
|
9224
|
+
if (forceDue && probeRan) {
|
|
9225
|
+
const left = attemptsLeft - 1;
|
|
9226
|
+
if (left > 0) promptBindProbeAttempts.set(agent.code_name, left);
|
|
9227
|
+
else promptBindProbeAttempts.delete(agent.code_name);
|
|
9228
|
+
}
|
|
9101
9229
|
}
|
|
9102
9230
|
if (frameworkAdapter.removeMcpServer && frameworkAdapter.getMcpPath) {
|
|
9103
9231
|
const mcpPath = frameworkAdapter.getMcpPath(agent.code_name);
|