agentic-engineering-harness 0.6.6 → 0.6.8
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/operations/controller.d.ts +3 -1
- package/dist/operations/controller.js +165 -31
- package/dist/operations/controller.js.map +1 -1
- package/dist/operations/mcp.d.ts +6 -0
- package/dist/operations/mcp.js +65 -1
- package/dist/operations/mcp.js.map +1 -1
- package/dist/operations/state.d.ts +11 -0
- package/dist/operations/state.js +69 -13
- package/dist/operations/state.js.map +1 -1
- package/dist/paseo/capabilities.d.ts +14 -2
- package/dist/paseo/capabilities.js +46 -14
- package/dist/paseo/capabilities.js.map +1 -1
- package/dist/paseo/context.d.ts +11 -2
- package/dist/paseo/context.js +118 -81
- package/dist/paseo/context.js.map +1 -1
- package/dist/paseo/native.d.ts +63 -0
- package/dist/paseo/native.js +549 -0
- package/dist/paseo/native.js.map +1 -0
- package/dist/paseo/runtime.d.ts +9 -1
- package/dist/paseo/runtime.js +348 -57
- package/dist/paseo/runtime.js.map +1 -1
- package/dist/paseo/start.d.ts +3 -3
- package/dist/paseo/start.js +156 -37
- package/dist/paseo/start.js.map +1 -1
- package/dist/paseo/trace.d.ts +12 -0
- package/dist/paseo/trace.js +26 -0
- package/dist/paseo/trace.js.map +1 -0
- package/docs/PASEO_NATIVE.md +185 -0
- package/package.json +1 -1
- package/skills/engineering-workflow/SKILL.md +5 -1
- package/skills/paseo-orchestration/SKILL.md +33 -5
package/dist/operations/state.js
CHANGED
|
@@ -17,16 +17,40 @@ export async function saveOperation(root, record) {
|
|
|
17
17
|
await withOperationLock(file, async () => writeRecord(file, record));
|
|
18
18
|
}
|
|
19
19
|
export async function patchOperation(root, operationId, patch) {
|
|
20
|
-
|
|
21
|
-
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
22
|
-
return withOperationLock(file, async () => {
|
|
23
|
-
const current = JSON.parse(await fs.readFile(file, "utf8"));
|
|
20
|
+
return mutateOperation(root, operationId, (current) => {
|
|
24
21
|
const guardedPatch = guardTerminalTransition(current, patch);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
return { ...current, ...guardedPatch };
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export async function registerOperationAgent(root, operationId, agent) {
|
|
26
|
+
return mutateOperation(root, operationId, (current) => {
|
|
27
|
+
if (isTerminal(current.status))
|
|
28
|
+
return current;
|
|
29
|
+
const existing = current.agents ?? [];
|
|
30
|
+
const previous = existing.find((item) => item.id === agent.id);
|
|
31
|
+
const next = {
|
|
32
|
+
...previous,
|
|
33
|
+
...agent,
|
|
34
|
+
registeredAt: previous?.registeredAt ?? new Date().toISOString()
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
...current,
|
|
38
|
+
agents: [...existing.filter((item) => item.id !== agent.id), next]
|
|
39
|
+
};
|
|
28
40
|
});
|
|
29
41
|
}
|
|
42
|
+
export async function registerCurrentOperationAgent(root, agent) {
|
|
43
|
+
const operationId = currentOperationContext().id;
|
|
44
|
+
if (!operationId)
|
|
45
|
+
return;
|
|
46
|
+
try {
|
|
47
|
+
await registerOperationAgent(root, operationId, agent);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Direct/non-controller execution may carry stale environment state. Agent
|
|
51
|
+
// registration is observability/cleanup metadata, not execution authority.
|
|
52
|
+
}
|
|
53
|
+
}
|
|
30
54
|
export function currentOperationContext() {
|
|
31
55
|
return {
|
|
32
56
|
id: process.env.AEH_OPERATION_ID?.trim() || undefined,
|
|
@@ -41,7 +65,26 @@ export async function updateCurrentOperationPhase(root, phase) {
|
|
|
41
65
|
try {
|
|
42
66
|
await patchOperation(root, operationId, { phase });
|
|
43
67
|
}
|
|
44
|
-
catch {
|
|
68
|
+
catch {
|
|
69
|
+
// Direct/non-controller execution has no operation state to update.
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function mutateOperation(root, operationId, mutate) {
|
|
73
|
+
const file = operationFile(root, operationId);
|
|
74
|
+
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
75
|
+
return withOperationLock(file, async () => {
|
|
76
|
+
const current = JSON.parse(await fs.readFile(file, "utf8"));
|
|
77
|
+
const candidate = mutate(current);
|
|
78
|
+
const next = {
|
|
79
|
+
...candidate,
|
|
80
|
+
id: current.id,
|
|
81
|
+
kind: current.kind,
|
|
82
|
+
version: 1,
|
|
83
|
+
updatedAt: new Date().toISOString()
|
|
84
|
+
};
|
|
85
|
+
await writeRecord(file, next);
|
|
86
|
+
return next;
|
|
87
|
+
});
|
|
45
88
|
}
|
|
46
89
|
async function writeRecord(file, record) {
|
|
47
90
|
const temp = `${file}.${process.pid}.${crypto.randomUUID()}.tmp`;
|
|
@@ -81,15 +124,19 @@ async function withOperationLock(file, action) {
|
|
|
81
124
|
await fs.rm(lock, { force: true }).catch(() => undefined);
|
|
82
125
|
continue;
|
|
83
126
|
}
|
|
84
|
-
if (Date.now() >= deadline)
|
|
127
|
+
if (Date.now() >= deadline) {
|
|
85
128
|
throw new Error(`Timed out acquiring operation state lock for ${path.basename(file)}.`);
|
|
129
|
+
}
|
|
86
130
|
await delay(LOCK_RETRY_MS);
|
|
87
131
|
}
|
|
88
132
|
}
|
|
89
133
|
}
|
|
90
134
|
async function canRecoverLock(lock) {
|
|
91
135
|
try {
|
|
92
|
-
const [rawPid, stat] = await Promise.all([
|
|
136
|
+
const [rawPid, stat] = await Promise.all([
|
|
137
|
+
fs.readFile(lock, "utf8").catch(() => ""),
|
|
138
|
+
fs.stat(lock)
|
|
139
|
+
]);
|
|
93
140
|
const ownerPid = Number.parseInt(rawPid.trim(), 10);
|
|
94
141
|
if (Number.isInteger(ownerPid) && ownerPid > 0 && !processAlive(ownerPid))
|
|
95
142
|
return true;
|
|
@@ -116,9 +163,18 @@ function guardTerminalTransition(current, patch) {
|
|
|
116
163
|
guarded.cleanupWarnings = patch.cleanupWarnings;
|
|
117
164
|
return guarded;
|
|
118
165
|
}
|
|
119
|
-
function isTerminal(status) {
|
|
120
|
-
|
|
121
|
-
|
|
166
|
+
function isTerminal(status) {
|
|
167
|
+
return status === "SUCCEEDED" || status === "FAILED" || status === "CANCELLED";
|
|
168
|
+
}
|
|
169
|
+
function isAlreadyExists(error) {
|
|
170
|
+
return Boolean(error &&
|
|
171
|
+
typeof error === "object" &&
|
|
172
|
+
"code" in error &&
|
|
173
|
+
error.code === "EEXIST");
|
|
174
|
+
}
|
|
175
|
+
function delay(ms) {
|
|
176
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
177
|
+
}
|
|
122
178
|
function safeId(value) {
|
|
123
179
|
if (!/^[A-Za-z0-9._-]+$/.test(value))
|
|
124
180
|
throw new Error(`Invalid operation id '${value}'.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/operations/state.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/operations/state.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { ProcessResult } from "../utils/process.js";
|
|
2
2
|
import { runProcess } from "../utils/process.js";
|
|
3
|
-
export interface
|
|
3
|
+
export interface PaseoDaemonCapabilities {
|
|
4
4
|
version?: string;
|
|
5
|
+
daemonJson: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface PaseoCapabilities extends PaseoDaemonCapabilities {
|
|
5
8
|
background: boolean;
|
|
6
9
|
quiet: boolean;
|
|
7
10
|
json: boolean;
|
|
8
11
|
outputSchema: boolean;
|
|
9
|
-
daemonJson: boolean;
|
|
10
12
|
nativeToolsRecommended: boolean;
|
|
11
13
|
}
|
|
12
14
|
export interface PaseoBackgroundRunOptions {
|
|
@@ -17,6 +19,16 @@ export interface PaseoBackgroundRunOptions {
|
|
|
17
19
|
prompt: string;
|
|
18
20
|
}
|
|
19
21
|
type Runner = typeof runProcess;
|
|
22
|
+
/**
|
|
23
|
+
* Minimal CLI discovery needed by daemon bootstrap. This deliberately does not
|
|
24
|
+
* inspect `paseo run --help`; run flags belong to the compatibility CLI runtime
|
|
25
|
+
* and are probed only if that fallback is actually needed.
|
|
26
|
+
*/
|
|
27
|
+
export declare function detectPaseoDaemonCapabilities(root: string, run?: Runner): Promise<PaseoDaemonCapabilities>;
|
|
28
|
+
/**
|
|
29
|
+
* Full CLI runtime negotiation. Call this only when AEH is about to use the
|
|
30
|
+
* Paseo CLI compatibility execution path.
|
|
31
|
+
*/
|
|
20
32
|
export declare function detectPaseoCapabilities(root: string, run?: Runner): Promise<PaseoCapabilities>;
|
|
21
33
|
export declare function buildPaseoBackgroundRunCommand(options: PaseoBackgroundRunOptions, capabilities: PaseoCapabilities): string;
|
|
22
34
|
export declare function extractPaseoAgentId(stdout: string): string | undefined;
|
|
@@ -1,26 +1,46 @@
|
|
|
1
1
|
import { runProcess } from "../utils/process.js";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Minimal CLI discovery needed by daemon bootstrap. This deliberately does not
|
|
4
|
+
* inspect `paseo run --help`; run flags belong to the compatibility CLI runtime
|
|
5
|
+
* and are probed only if that fallback is actually needed.
|
|
6
|
+
*/
|
|
7
|
+
export async function detectPaseoDaemonCapabilities(root, run = runProcess) {
|
|
8
|
+
const [versionResult, daemonHelp] = await Promise.all([
|
|
4
9
|
run("paseo --version", { cwd: root, timeoutMs: 15_000 }),
|
|
5
|
-
run("paseo run --help", { cwd: root, timeoutMs: 15_000 }),
|
|
6
10
|
run("paseo daemon status --help", { cwd: root, timeoutMs: 15_000 })
|
|
7
11
|
]);
|
|
8
12
|
const version = parseVersion(`${versionResult.stdout}\n${versionResult.stderr}`);
|
|
9
|
-
const runText = `${runHelp.stdout}\n${runHelp.stderr}`;
|
|
10
13
|
const daemonText = `${daemonHelp.stdout}\n${daemonHelp.stderr}`;
|
|
11
14
|
return {
|
|
12
15
|
version,
|
|
16
|
+
daemonJson: hasOption(daemonText, "--json")
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Full CLI runtime negotiation. Call this only when AEH is about to use the
|
|
21
|
+
* Paseo CLI compatibility execution path.
|
|
22
|
+
*/
|
|
23
|
+
export async function detectPaseoCapabilities(root, run = runProcess) {
|
|
24
|
+
const [daemon, runHelp] = await Promise.all([
|
|
25
|
+
detectPaseoDaemonCapabilities(root, run),
|
|
26
|
+
run("paseo run --help", { cwd: root, timeoutMs: 15_000 })
|
|
27
|
+
]);
|
|
28
|
+
const runText = `${runHelp.stdout}\n${runHelp.stderr}`;
|
|
29
|
+
return {
|
|
30
|
+
...daemon,
|
|
13
31
|
background: hasOption(runText, "--background"),
|
|
14
|
-
quiet: hasOption(runText, "--quiet") ||
|
|
32
|
+
quiet: hasOption(runText, "--quiet") ||
|
|
33
|
+
hasOption(runText, "-q") ||
|
|
34
|
+
semverAtLeast(daemon.version, [0, 4, 0]),
|
|
15
35
|
json: hasOption(runText, "--json"),
|
|
16
36
|
outputSchema: hasOption(runText, "--output-schema"),
|
|
17
|
-
|
|
18
|
-
nativeToolsRecommended: semverAtLeast(version, [0, 4, 0])
|
|
37
|
+
nativeToolsRecommended: semverAtLeast(daemon.version, [0, 4, 0])
|
|
19
38
|
};
|
|
20
39
|
}
|
|
21
40
|
export function buildPaseoBackgroundRunCommand(options, capabilities) {
|
|
22
|
-
if (!capabilities.background)
|
|
41
|
+
if (!capabilities.background) {
|
|
23
42
|
throw new Error(`Installed Paseo${capabilities.version ? ` ${capabilities.version}` : ""} does not advertise background runs.`);
|
|
43
|
+
}
|
|
24
44
|
const parts = ["paseo run", "--background"];
|
|
25
45
|
if (capabilities.json)
|
|
26
46
|
parts.push("--json");
|
|
@@ -44,8 +64,13 @@ export function extractPaseoAgentId(stdout) {
|
|
|
44
64
|
if (id)
|
|
45
65
|
return id;
|
|
46
66
|
}
|
|
47
|
-
catch {
|
|
48
|
-
|
|
67
|
+
catch {
|
|
68
|
+
// Older Paseo emits plain text.
|
|
69
|
+
}
|
|
70
|
+
const lines = trimmed
|
|
71
|
+
.split(/\r?\n/)
|
|
72
|
+
.map((line) => line.trim())
|
|
73
|
+
.filter(Boolean);
|
|
49
74
|
for (const line of lines.reverse()) {
|
|
50
75
|
const direct = line.match(/^(?:agent(?:Id)?[=: ]+)?([A-Za-z0-9][A-Za-z0-9._:-]{2,})$/i)?.[1];
|
|
51
76
|
if (direct)
|
|
@@ -73,9 +98,10 @@ function findId(value) {
|
|
|
73
98
|
return undefined;
|
|
74
99
|
}
|
|
75
100
|
const record = value;
|
|
76
|
-
for (const key of ["agentId", "agent_id", "id"])
|
|
101
|
+
for (const key of ["agentId", "agent_id", "id"]) {
|
|
77
102
|
if (typeof record[key] === "string" && record[key])
|
|
78
103
|
return record[key];
|
|
104
|
+
}
|
|
79
105
|
for (const child of Object.values(record)) {
|
|
80
106
|
const found = findId(child);
|
|
81
107
|
if (found)
|
|
@@ -83,8 +109,12 @@ function findId(value) {
|
|
|
83
109
|
}
|
|
84
110
|
return undefined;
|
|
85
111
|
}
|
|
86
|
-
function parseVersion(text) {
|
|
87
|
-
|
|
112
|
+
function parseVersion(text) {
|
|
113
|
+
return text.match(/\b(?:v)?(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)/)?.[1];
|
|
114
|
+
}
|
|
115
|
+
function hasOption(text, option) {
|
|
116
|
+
return text.includes(option);
|
|
117
|
+
}
|
|
88
118
|
function semverAtLeast(version, minimum) {
|
|
89
119
|
if (!version)
|
|
90
120
|
return false;
|
|
@@ -100,5 +130,7 @@ function semverAtLeast(version, minimum) {
|
|
|
100
130
|
}
|
|
101
131
|
return true;
|
|
102
132
|
}
|
|
103
|
-
function quote(value) {
|
|
133
|
+
function quote(value) {
|
|
134
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
135
|
+
}
|
|
104
136
|
//# sourceMappingURL=capabilities.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/paseo/capabilities.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/paseo/capabilities.ts"],"names":[],"mappings":"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"}
|
package/dist/paseo/context.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { HarnessProjectConfig } from "../core/types.js";
|
|
2
2
|
import { runProcess } from "../utils/process.js";
|
|
3
3
|
import { startPaseoHarness } from "./start.js";
|
|
4
|
-
|
|
4
|
+
import { inspectPaseoNativeAgent } from "./native.js";
|
|
5
|
+
import { recordPaseoTrace } from "./trace.js";
|
|
6
|
+
export type ContextGuardState = "OK" | "PRESSURE" | "HANDOFF_REQUIRED" | "HARD_HANDOFF" | "NO_USAGE_YET" | "USAGE_UNAVAILABLE" | "UNKNOWN";
|
|
5
7
|
export interface ContextUsage {
|
|
6
8
|
used?: number;
|
|
7
9
|
limit?: number;
|
|
8
10
|
ratio?: number;
|
|
9
11
|
source: string;
|
|
12
|
+
availability?: "available" | "no-usage-yet" | "provider-usage-unavailable" | "agent-unavailable";
|
|
10
13
|
}
|
|
11
14
|
export interface LeadHandoffArtifact {
|
|
12
15
|
version: 1;
|
|
@@ -32,14 +35,20 @@ export interface ContextGuardResult {
|
|
|
32
35
|
}
|
|
33
36
|
type Runner = typeof runProcess;
|
|
34
37
|
type Starter = typeof startPaseoHarness;
|
|
38
|
+
type Inspector = typeof inspectPaseoNativeAgent;
|
|
39
|
+
type Trace = typeof recordPaseoTrace;
|
|
35
40
|
export interface ContextGuardOptions {
|
|
36
41
|
brief?: string;
|
|
37
42
|
run?: Runner;
|
|
38
43
|
autoRotate?: boolean;
|
|
39
44
|
aehCommand?: string;
|
|
40
45
|
start?: Starter;
|
|
46
|
+
inspect?: Inspector;
|
|
47
|
+
trace?: Trace;
|
|
41
48
|
}
|
|
49
|
+
export declare function statusLeadContext(root: string, config: HarnessProjectConfig, agentId: string, options?: Pick<ContextGuardOptions, "inspect" | "trace">): Promise<ContextGuardResult>;
|
|
42
50
|
export declare function guardLeadContext(root: string, config: HarnessProjectConfig, agentId: string, options?: ContextGuardOptions): Promise<ContextGuardResult>;
|
|
43
|
-
export declare function inspectPaseoContextUsage(root: string, agentId: string,
|
|
51
|
+
export declare function inspectPaseoContextUsage(root: string, agentId: string, inspect?: Inspector): Promise<ContextUsage>;
|
|
52
|
+
/** Compatibility helper retained for callers/tests, but intentionally strict. */
|
|
44
53
|
export declare function extractContextUsage(value: unknown): ContextUsage;
|
|
45
54
|
export {};
|
package/dist/paseo/context.js
CHANGED
|
@@ -3,64 +3,129 @@ import path from "node:path";
|
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { runProcess } from "../utils/process.js";
|
|
5
5
|
import { startPaseoHarness } from "./start.js";
|
|
6
|
+
import { contextUsageFromPaseoSnapshot, inspectPaseoNativeAgent } from "./native.js";
|
|
7
|
+
import { recordPaseoTrace } from "./trace.js";
|
|
8
|
+
export async function statusLeadContext(root, config, agentId, options = {}) {
|
|
9
|
+
const inspect = options.inspect ?? inspectPaseoNativeAgent;
|
|
10
|
+
const trace = options.trace ?? recordPaseoTrace;
|
|
11
|
+
let snapshot;
|
|
12
|
+
try {
|
|
13
|
+
snapshot = await inspect(root, agentId);
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
const usage = { source: "paseo-agent-snapshot", availability: "agent-unavailable" };
|
|
17
|
+
await trace(root, "context.status", { agentId, state: "USAGE_UNAVAILABLE", source: usage.source, error: String(error) });
|
|
18
|
+
return {
|
|
19
|
+
state: "USAGE_UNAVAILABLE",
|
|
20
|
+
usage,
|
|
21
|
+
message: `Paseo could not provide the current agent snapshot: ${error instanceof Error ? error.message : String(error)}`
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (!snapshot) {
|
|
25
|
+
const usage = { source: "paseo-agent-snapshot", availability: "agent-unavailable" };
|
|
26
|
+
await trace(root, "context.status", { agentId, state: "USAGE_UNAVAILABLE", source: usage.source });
|
|
27
|
+
return { state: "USAGE_UNAVAILABLE", usage, message: "Paseo did not return a snapshot for the managed lead." };
|
|
28
|
+
}
|
|
29
|
+
const native = contextUsageFromPaseoSnapshot(snapshot);
|
|
30
|
+
const usage = { used: native.used, limit: native.limit, ratio: native.ratio, source: native.source, availability: native.availability };
|
|
31
|
+
if (native.availability === "no-usage-yet") {
|
|
32
|
+
await trace(root, "context.status", { agentId, state: "NO_USAGE_YET", source: usage.source });
|
|
33
|
+
return { state: "NO_USAGE_YET", usage, message: "The lead has not reported context-window usage yet. This is normal before the provider emits its first usage snapshot." };
|
|
34
|
+
}
|
|
35
|
+
if (native.availability !== "available" || native.ratio === undefined) {
|
|
36
|
+
await trace(root, "context.status", {
|
|
37
|
+
agentId,
|
|
38
|
+
state: "USAGE_UNAVAILABLE",
|
|
39
|
+
source: usage.source,
|
|
40
|
+
used: usage.used ?? -1,
|
|
41
|
+
limit: usage.limit ?? -1
|
|
42
|
+
});
|
|
43
|
+
return { state: "USAGE_UNAVAILABLE", usage, message: "The active provider reported usage but did not expose both contextWindowUsedTokens and contextWindowMaxTokens." };
|
|
44
|
+
}
|
|
45
|
+
const policy = contextPolicy(config);
|
|
46
|
+
let state;
|
|
47
|
+
let message;
|
|
48
|
+
if (native.ratio < policy.pressure) {
|
|
49
|
+
state = "OK";
|
|
50
|
+
message = `Lead context ${(native.ratio * 100).toFixed(1)}% is below the pressure threshold.`;
|
|
51
|
+
}
|
|
52
|
+
else if (native.ratio < policy.handoff) {
|
|
53
|
+
state = "PRESSURE";
|
|
54
|
+
message = `Lead context ${(native.ratio * 100).toFixed(1)}% is under pressure. Stop exploratory shell work and delegate all non-semantic operations.`;
|
|
55
|
+
}
|
|
56
|
+
else if (native.ratio >= policy.hard) {
|
|
57
|
+
state = "HARD_HANDOFF";
|
|
58
|
+
message = `HARD_HANDOFF: context ${(native.ratio * 100).toFixed(1)}%. Responsibility must move to a fresh lead before additional engineering work.`;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
state = "HANDOFF_REQUIRED";
|
|
62
|
+
message = `HANDOFF_REQUIRED: context ${(native.ratio * 100).toFixed(1)}%. Prepare responsibility transfer to a fresh lead.`;
|
|
63
|
+
}
|
|
64
|
+
await trace(root, "context.status", {
|
|
65
|
+
agentId,
|
|
66
|
+
state,
|
|
67
|
+
source: usage.source,
|
|
68
|
+
used: native.used ?? -1,
|
|
69
|
+
limit: native.limit ?? -1,
|
|
70
|
+
ratio: native.ratio,
|
|
71
|
+
pressureThreshold: policy.pressure,
|
|
72
|
+
handoffThreshold: policy.handoff,
|
|
73
|
+
hardHandoffThreshold: policy.hard
|
|
74
|
+
});
|
|
75
|
+
return { state, usage, message };
|
|
76
|
+
}
|
|
6
77
|
export async function guardLeadContext(root, config, agentId, options = {}) {
|
|
78
|
+
const status = await statusLeadContext(root, config, agentId, options);
|
|
79
|
+
if (status.state !== "HANDOFF_REQUIRED" && status.state !== "HARD_HANDOFF")
|
|
80
|
+
return status;
|
|
7
81
|
const run = options.run ?? runProcess;
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
if (usage.ratio === undefined)
|
|
11
|
-
return { state: "UNKNOWN", usage, message: "Paseo did not expose a stable context-usage ratio; continue with delegation-first behavior and prefer a fresh lead on the next aeh start." };
|
|
12
|
-
if (usage.ratio < policy.pressure)
|
|
13
|
-
return { state: "OK", usage, message: `Lead context ${(usage.ratio * 100).toFixed(1)}% is below the pressure threshold.` };
|
|
14
|
-
if (usage.ratio < policy.handoff)
|
|
15
|
-
return { state: "PRESSURE", usage, message: `Lead context ${(usage.ratio * 100).toFixed(1)}% is under pressure. Stop exploratory shell work and delegate all non-semantic operations.` };
|
|
16
|
-
const artifactPath = await writeHandoffArtifact(root, config, agentId, usage, options.brief, run);
|
|
17
|
-
const state = usage.ratio >= policy.hard ? "HARD_HANDOFF" : "HANDOFF_REQUIRED";
|
|
82
|
+
const trace = options.trace ?? recordPaseoTrace;
|
|
83
|
+
const artifactPath = await writeHandoffArtifact(root, config, agentId, status.usage, options.brief, run);
|
|
18
84
|
const autoRotate = options.autoRotate ?? Boolean(process.env.PASEO_AGENT_ID);
|
|
19
|
-
if (!autoRotate)
|
|
20
|
-
|
|
85
|
+
if (!autoRotate) {
|
|
86
|
+
await trace(root, "context.handoff", { agentId, state: status.state, action: "artifact-created", handoffPath: relative(root, artifactPath) });
|
|
87
|
+
return {
|
|
88
|
+
...status,
|
|
89
|
+
handoffPath: artifactPath,
|
|
90
|
+
message: `${status.message} Handoff artifact created at ${relative(root, artifactPath)}. Create a fresh lead with /paseo-handoff (preferred) or rerun the guard from the managed lead to rotate automatically.`
|
|
91
|
+
};
|
|
92
|
+
}
|
|
21
93
|
const starter = options.start ?? startPaseoHarness;
|
|
22
94
|
const aehCommand = options.aehCommand ?? exactAehCommand();
|
|
23
95
|
const relativeHandoff = relative(root, artifactPath);
|
|
24
96
|
const fresh = await starter(root, config, { forceNew: true, resume: false, handoffPath: relativeHandoff, aehCommand });
|
|
25
97
|
await recordRotatedLead(artifactPath, fresh.agentId);
|
|
98
|
+
await trace(root, "context.handoff", { agentId, rotatedAgentId: fresh.agentId, state: status.state, action: "rotated", handoffPath: relativeHandoff });
|
|
26
99
|
return {
|
|
27
|
-
|
|
28
|
-
usage,
|
|
100
|
+
...status,
|
|
29
101
|
handoffPath: artifactPath,
|
|
30
102
|
rotatedAgentId: fresh.agentId,
|
|
31
|
-
message: `${
|
|
103
|
+
message: `${status.message} AEH rotated responsibility to fresh lead ${fresh.agentId} using ${relativeHandoff}. Stop engineering work in ${agentId}; the fresh lead bootstraps from deterministic artifacts.`
|
|
32
104
|
};
|
|
33
105
|
}
|
|
34
|
-
export async function inspectPaseoContextUsage(root, agentId,
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
const parsed = JSON.parse(result.stdout);
|
|
42
|
-
const agent = findAgent(parsed, agentId) ?? parsed;
|
|
43
|
-
const usage = extractContextUsage(agent);
|
|
44
|
-
if (usage.ratio !== undefined)
|
|
45
|
-
return usage;
|
|
46
|
-
}
|
|
47
|
-
catch { /* older Paseo or non-JSON output */ }
|
|
48
|
-
}
|
|
49
|
-
return { source: "unavailable" };
|
|
106
|
+
export async function inspectPaseoContextUsage(root, agentId, inspect = inspectPaseoNativeAgent) {
|
|
107
|
+
const snapshot = await inspect(root, agentId);
|
|
108
|
+
if (!snapshot)
|
|
109
|
+
return { source: "paseo-agent-snapshot", availability: "agent-unavailable" };
|
|
110
|
+
const usage = contextUsageFromPaseoSnapshot(snapshot);
|
|
111
|
+
return { used: usage.used, limit: usage.limit, ratio: usage.ratio, source: usage.source, availability: usage.availability };
|
|
50
112
|
}
|
|
113
|
+
/** Compatibility helper retained for callers/tests, but intentionally strict. */
|
|
51
114
|
export function extractContextUsage(value) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const used =
|
|
60
|
-
const limit =
|
|
61
|
-
if (used
|
|
62
|
-
return {
|
|
63
|
-
|
|
115
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
116
|
+
return { source: "paseo-snapshot-invalid", availability: "agent-unavailable" };
|
|
117
|
+
const record = value;
|
|
118
|
+
const usageValue = record.lastUsage ?? record;
|
|
119
|
+
if (!usageValue || typeof usageValue !== "object" || Array.isArray(usageValue))
|
|
120
|
+
return { source: "paseo-agent-snapshot", availability: "no-usage-yet" };
|
|
121
|
+
const usage = usageValue;
|
|
122
|
+
const used = finiteNonNegative(usage.contextWindowUsedTokens);
|
|
123
|
+
const limit = finitePositive(usage.contextWindowMaxTokens);
|
|
124
|
+
if (used === undefined && limit === undefined)
|
|
125
|
+
return { source: "paseo-agent-snapshot", availability: "no-usage-yet" };
|
|
126
|
+
if (used === undefined || limit === undefined)
|
|
127
|
+
return { used, limit, source: "paseo-agent-snapshot", availability: "provider-usage-unavailable" };
|
|
128
|
+
return { used, limit, ratio: Math.min(used / limit, 1), source: "paseo-agent-snapshot", availability: "available" };
|
|
64
129
|
}
|
|
65
130
|
function contextPolicy(config) {
|
|
66
131
|
const context = config.orchestration?.interactive?.context;
|
|
@@ -108,46 +173,18 @@ async function latestJsonPath(root, relativeDir) {
|
|
|
108
173
|
values.sort((a, b) => b.stat.mtimeMs - a.stat.mtimeMs);
|
|
109
174
|
return relative(root, path.join(dir, values[0].name));
|
|
110
175
|
}
|
|
111
|
-
async function existingRelative(root, relativePath) {
|
|
112
|
-
|
|
113
|
-
|
|
176
|
+
async function existingRelative(root, relativePath) {
|
|
177
|
+
try {
|
|
178
|
+
await fs.access(path.resolve(root, relativePath));
|
|
179
|
+
return relativePath.replaceAll("\\", "/");
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
114
184
|
}
|
|
115
|
-
catch {
|
|
116
|
-
return undefined;
|
|
117
|
-
} }
|
|
118
185
|
function exactAehCommand() { const entry = path.resolve(process.argv[1]); return `${JSON.stringify(process.execPath)} ${JSON.stringify(entry)}`; }
|
|
119
|
-
function findAgent(value, id) { if (Array.isArray(value)) {
|
|
120
|
-
for (const child of value) {
|
|
121
|
-
const found = findAgent(child, id);
|
|
122
|
-
if (found)
|
|
123
|
-
return found;
|
|
124
|
-
}
|
|
125
|
-
return undefined;
|
|
126
|
-
} if (!value || typeof value !== "object")
|
|
127
|
-
return undefined; const record = value; if ([record.id, record.agentId, record.agent_id].some((item) => item === id))
|
|
128
|
-
return record; for (const child of Object.values(record)) {
|
|
129
|
-
const found = findAgent(child, id);
|
|
130
|
-
if (found)
|
|
131
|
-
return found;
|
|
132
|
-
} return undefined; }
|
|
133
|
-
function collectNumericFields(value, out = new Map()) { if (Array.isArray(value)) {
|
|
134
|
-
for (const child of value)
|
|
135
|
-
collectNumericFields(child, out);
|
|
136
|
-
return out;
|
|
137
|
-
} if (!value || typeof value !== "object")
|
|
138
|
-
return out; for (const [key, child] of Object.entries(value)) {
|
|
139
|
-
const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
140
|
-
if (typeof child === "number" && Number.isFinite(child) && !out.has(normalized))
|
|
141
|
-
out.set(normalized, child);
|
|
142
|
-
else
|
|
143
|
-
collectNumericFields(child, out);
|
|
144
|
-
} return out; }
|
|
145
|
-
function first(values, keys) { for (const key of keys) {
|
|
146
|
-
const value = values.get(key);
|
|
147
|
-
if (value !== undefined)
|
|
148
|
-
return value;
|
|
149
|
-
} return undefined; }
|
|
150
186
|
function clamp(value) { return Math.max(0, Math.min(1, value)); }
|
|
151
187
|
function relative(root, file) { return path.relative(root, file).replaceAll("\\", "/"); }
|
|
152
|
-
function
|
|
188
|
+
function finiteNonNegative(value) { return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined; }
|
|
189
|
+
function finitePositive(value) { return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined; }
|
|
153
190
|
//# sourceMappingURL=context.js.map
|