@prestyj/cli 5.30.3 → 5.32.0
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/app-sidecar/goal-routes.d.ts +2 -22
- package/dist/app-sidecar/goal-routes.js +12 -93
- package/dist/app-sidecar/goal-routes.js.map +1 -1
- package/dist/app-sidecar/history-routes.js +1 -2
- package/dist/app-sidecar/history-routes.js.map +1 -1
- package/dist/app-sidecar/prompt-routes.js +1 -2
- package/dist/app-sidecar/prompt-routes.js.map +1 -1
- package/dist/app-sidecar/run-control-routes.d.ts +14 -0
- package/dist/app-sidecar/run-control-routes.js +61 -22
- package/dist/app-sidecar/run-control-routes.js.map +1 -1
- package/dist/app-sidecar/session-routes.js +5 -1
- package/dist/app-sidecar/session-routes.js.map +1 -1
- package/dist/app-sidecar/task-routes.js +22 -0
- package/dist/app-sidecar/task-routes.js.map +1 -1
- package/dist/app-sidecar.js +6 -7
- package/dist/app-sidecar.js.map +1 -1
- package/dist/core/agent-session.d.ts +17 -0
- package/dist/core/agent-session.js +48 -12
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/custom-commands.d.ts +6 -0
- package/dist/core/custom-commands.js +17 -0
- package/dist/core/custom-commands.js.map +1 -1
- package/dist/core/goal-run-marker.d.ts +32 -0
- package/dist/core/goal-run-marker.js +178 -0
- package/dist/core/goal-run-marker.js.map +1 -0
- package/dist/core/goal-summary.d.ts +32 -0
- package/dist/core/goal-summary.js +110 -0
- package/dist/core/goal-summary.js.map +1 -0
- package/dist/core/plan-handoff.d.ts +8 -0
- package/dist/core/plan-handoff.js +11 -0
- package/dist/core/plan-handoff.js.map +1 -1
- package/dist/core/resolve-start.d.ts +2 -0
- package/dist/core/resolve-start.js +34 -5
- package/dist/core/resolve-start.js.map +1 -1
- package/dist/core/subagent-policy.js +4 -1
- package/dist/core/subagent-policy.js.map +1 -1
- package/dist/goals-agent/goals-agent.js +43 -1
- package/dist/goals-agent/goals-agent.js.map +1 -1
- package/dist/modes/acp-autopilot.d.ts +27 -0
- package/dist/modes/acp-autopilot.js +54 -0
- package/dist/modes/acp-autopilot.js.map +1 -0
- package/dist/modes/acp-goals.d.ts +52 -0
- package/dist/modes/acp-goals.js +102 -0
- package/dist/modes/acp-goals.js.map +1 -0
- package/dist/modes/acp-mode.d.ts +128 -3
- package/dist/modes/acp-mode.js +1086 -52
- package/dist/modes/acp-mode.js.map +1 -1
- package/dist/tools/grep-scan.d.ts +96 -0
- package/dist/tools/grep-scan.js +283 -0
- package/dist/tools/grep-scan.js.map +1 -0
- package/dist/tools/grep.d.ts +10 -0
- package/dist/tools/grep.js +418 -10
- package/dist/tools/grep.js.map +1 -1
- package/dist/ui/components/Footer.js +4 -0
- package/dist/ui/components/Footer.js.map +1 -1
- package/dist/utils/git-overview.d.ts +41 -0
- package/dist/utils/git-overview.js +146 -0
- package/dist/utils/git-overview.js.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Autopilot Nolan for `ezcoder acp`: the reviewer session the autopilot cycle
|
|
3
|
+
* prompts. Built like the desktop's `ensureNolanAutoSession` (app-sidecar.ts):
|
|
4
|
+
* Nolan's autopilot system prompt, Nolan's read-only tool set, a transient
|
|
5
|
+
* session, long cache retention, and the project's Nolan model pin when one is
|
|
6
|
+
* valid (otherwise Nolan follows EZ Coder's model, as on the desktop).
|
|
7
|
+
*/
|
|
8
|
+
import type { Provider } from "@prestyj/ai";
|
|
9
|
+
/** The reviewer the ACP autopilot cycle talks to. A seam so tests can script Nolan. */
|
|
10
|
+
export interface AcpNolanReviewer {
|
|
11
|
+
/** Wipe review history (start of each cycle). */
|
|
12
|
+
reset(): Promise<void>;
|
|
13
|
+
/** Prompt Nolan with a digest; resolves to his final reply text. */
|
|
14
|
+
review(digest: string): Promise<string>;
|
|
15
|
+
/** Stop an in-flight review (session/cancel, queued message). */
|
|
16
|
+
abort(): void;
|
|
17
|
+
dispose(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export interface AcpNolanReviewerOptions {
|
|
20
|
+
cwd: string;
|
|
21
|
+
/** EZ Coder's current model; Nolan follows it unless the project pins his own. */
|
|
22
|
+
buildModel: () => {
|
|
23
|
+
provider: Provider;
|
|
24
|
+
model: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export declare function createAcpNolanReviewer(options: AcpNolanReviewerOptions): AcpNolanReviewer;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { getModel } from "@prestyj/core";
|
|
2
|
+
import { AgentSession } from "../core/agent-session.js";
|
|
3
|
+
import { buildNolanAutopilotSystemPrompt } from "../core/nolan-prompt.js";
|
|
4
|
+
import { validateNolanModelPref } from "../core/nolan-model.js";
|
|
5
|
+
import { NOLAN_ALLOWED_TOOLS, lastAssistantText } from "../app-sidecar/nolan-context.js";
|
|
6
|
+
import { loadNolanModelPref } from "../app-sidecar/app-settings.js";
|
|
7
|
+
export function createAcpNolanReviewer(options) {
|
|
8
|
+
let abort = new AbortController();
|
|
9
|
+
let nolan = null;
|
|
10
|
+
async function ensure() {
|
|
11
|
+
if (nolan)
|
|
12
|
+
return nolan;
|
|
13
|
+
const pinned = validateNolanModelPref(await loadNolanModelPref(options.cwd), {
|
|
14
|
+
modelExists: (id) => getModel(id) !== undefined,
|
|
15
|
+
providerConnected: () => true,
|
|
16
|
+
});
|
|
17
|
+
const target = pinned ?? options.buildModel();
|
|
18
|
+
const created = new AgentSession({
|
|
19
|
+
provider: target.provider,
|
|
20
|
+
model: target.model,
|
|
21
|
+
cwd: options.cwd,
|
|
22
|
+
systemPrompt: await buildNolanAutopilotSystemPrompt(options.cwd),
|
|
23
|
+
allowedTools: NOLAN_ALLOWED_TOOLS,
|
|
24
|
+
transient: true,
|
|
25
|
+
signal: abort.signal,
|
|
26
|
+
forceLongCacheRetention: true,
|
|
27
|
+
});
|
|
28
|
+
await created.initialize();
|
|
29
|
+
nolan = created;
|
|
30
|
+
return created;
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
async reset() {
|
|
34
|
+
await nolan?.newSession().catch(() => undefined);
|
|
35
|
+
},
|
|
36
|
+
async review(digest) {
|
|
37
|
+
const session = await ensure();
|
|
38
|
+
await session.prompt(digest);
|
|
39
|
+
return lastAssistantText(session.getMessages());
|
|
40
|
+
},
|
|
41
|
+
abort() {
|
|
42
|
+
abort.abort();
|
|
43
|
+
abort = new AbortController();
|
|
44
|
+
nolan?.setSignal(abort.signal);
|
|
45
|
+
},
|
|
46
|
+
async dispose() {
|
|
47
|
+
abort.abort();
|
|
48
|
+
const current = nolan;
|
|
49
|
+
nolan = null;
|
|
50
|
+
await current?.dispose();
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=acp-autopilot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp-autopilot.js","sourceRoot":"","sources":["../../src/modes/acp-autopilot.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,+BAA+B,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAmBpE,MAAM,UAAU,sBAAsB,CAAC,OAAgC;IACrE,IAAI,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IAClC,IAAI,KAAK,GAAwB,IAAI,CAAC;IAEtC,KAAK,UAAU,MAAM;QACnB,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxB,MAAM,MAAM,GAAG,sBAAsB,CAAC,MAAM,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YAC3E,WAAW,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,SAAS;YAC/C,iBAAiB,EAAE,GAAG,EAAE,CAAC,IAAI;SAC9B,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC;YAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,YAAY,EAAE,MAAM,+BAA+B,CAAC,OAAO,CAAC,GAAG,CAAC;YAChE,YAAY,EAAE,mBAAmB;YACjC,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,uBAAuB,EAAE,IAAI;SAC9B,CAAC,CAAC;QACH,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;QAC3B,KAAK,GAAG,OAAO,CAAC;QAChB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO;QACL,KAAK,CAAC,KAAK;YACT,MAAM,KAAK,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACnD,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,MAAM;YACjB,MAAM,OAAO,GAAG,MAAM,MAAM,EAAE,CAAC;YAC/B,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC7B,OAAO,iBAAiB,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,KAAK;YACH,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;YAC9B,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QACD,KAAK,CAAC,OAAO;YACX,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,MAAM,OAAO,GAAG,KAAK,CAAC;YACtB,KAAK,GAAG,IAAI,CAAC;YACb,MAAM,OAAO,EAAE,OAAO,EAAE,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type GoalRecord, type GoalResult } from "../core/goals-store.js";
|
|
2
|
+
import type { SubAgentSnapshot } from "../core/subagent-manager.js";
|
|
3
|
+
import type { AppAttachment } from "../app-sidecar/attachments.js";
|
|
4
|
+
/** `_gg/goals/list` row: the sidecar's GoalSummary, addressed by session id. */
|
|
5
|
+
export interface AcpGoalSummary {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
goal: string;
|
|
9
|
+
context: GoalRecord["context"];
|
|
10
|
+
path: string;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
lastActiveMs: number;
|
|
13
|
+
lastActiveDisplay: string;
|
|
14
|
+
/** The id `session/load` / `session/resume` take; null starts a fresh coordinator. */
|
|
15
|
+
agentSessionId: string | null;
|
|
16
|
+
/**
|
|
17
|
+
* Standing instructions, so a client's goal settings can show what is set
|
|
18
|
+
* (absent = none). The desktop app reads them from the record the same way.
|
|
19
|
+
*/
|
|
20
|
+
instructions?: string;
|
|
21
|
+
/**
|
|
22
|
+
* `running` when some process holds the goal's run marker (this one, the
|
|
23
|
+
* desktop app, another `ezcoder acp`). A client that knows of a live run of
|
|
24
|
+
* its own may still overlay `running` on top.
|
|
25
|
+
*/
|
|
26
|
+
status: "briefing" | "running" | "paused" | "interrupted" | "idle";
|
|
27
|
+
}
|
|
28
|
+
/** pew2 wire `GoalWorker`. */
|
|
29
|
+
export interface AcpGoalWorker {
|
|
30
|
+
id: string;
|
|
31
|
+
name: string;
|
|
32
|
+
agent?: string;
|
|
33
|
+
state: "starting" | "running" | "completed" | "failed" | "interrupted" | "closed";
|
|
34
|
+
activity?: string;
|
|
35
|
+
startedAt?: number;
|
|
36
|
+
elapsedMs?: number;
|
|
37
|
+
toolUses?: number;
|
|
38
|
+
model?: string;
|
|
39
|
+
error?: string;
|
|
40
|
+
}
|
|
41
|
+
/** Every goal, most recently active first. */
|
|
42
|
+
export declare function listAcpGoals(agentDir: string): Promise<AcpGoalSummary[]>;
|
|
43
|
+
/** Create a goal from `_gg/goals/create` params; the store's own error text on failure. */
|
|
44
|
+
export declare function createAcpGoal(agentDir: string, params: unknown): Promise<GoalResult<AcpGoalSummary>>;
|
|
45
|
+
/** The worker roster for `_gg/goal_state`. A reaped worker reads as closed. */
|
|
46
|
+
export declare function goalWorkers(snapshots: readonly SubAgentSnapshot[]): AcpGoalWorker[];
|
|
47
|
+
/**
|
|
48
|
+
* ACP `image` prompt blocks as the app's attachment shape, so they take the
|
|
49
|
+
* same `prepareAttachments` → `promptWithAttachments` path the desktop does.
|
|
50
|
+
* Blocks carrying only a `uri` (no inline data) are skipped.
|
|
51
|
+
*/
|
|
52
|
+
export declare function acpImageAttachments(blocks: unknown): AppAttachment[];
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EZ Goals over ACP (`_gg/goals/*`, `_gg/goal/*`, `_gg/goal_state`): the pure
|
|
3
|
+
* pieces, kept out of `acp-mode.ts` so the transport stays readable. The goal
|
|
4
|
+
* list rows come from the same `summarizeGoal` the desktop sidecar uses.
|
|
5
|
+
*/
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { createGoal, goalsRoot, listGoals, } from "../core/goals-store.js";
|
|
8
|
+
import { summarizeGoal } from "../core/goal-summary.js";
|
|
9
|
+
import { SessionManager } from "../core/session-manager.js";
|
|
10
|
+
function toAcpSummary(summary, instructions) {
|
|
11
|
+
return {
|
|
12
|
+
...(instructions ? { instructions } : {}),
|
|
13
|
+
id: summary.id,
|
|
14
|
+
name: summary.name,
|
|
15
|
+
goal: summary.goal,
|
|
16
|
+
context: summary.context,
|
|
17
|
+
path: summary.path,
|
|
18
|
+
createdAt: summary.createdAt,
|
|
19
|
+
lastActiveMs: summary.lastActiveMs,
|
|
20
|
+
lastActiveDisplay: summary.lastActiveDisplay,
|
|
21
|
+
agentSessionId: summary.latestSessionId,
|
|
22
|
+
status: summary.status,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function sessionsDir(agentDir) {
|
|
26
|
+
return path.join(agentDir, "sessions");
|
|
27
|
+
}
|
|
28
|
+
/** Every goal, most recently active first. */
|
|
29
|
+
export async function listAcpGoals(agentDir) {
|
|
30
|
+
const sessions = new SessionManager(sessionsDir(agentDir));
|
|
31
|
+
const goals = await listGoals(goalsRoot(agentDir));
|
|
32
|
+
const rows = await Promise.all(goals.map(async (g) => toAcpSummary(await summarizeGoal(sessions, g.dir, g.record), g.record.instructions)));
|
|
33
|
+
rows.sort((a, b) => b.lastActiveMs - a.lastActiveMs || a.id.localeCompare(b.id));
|
|
34
|
+
return rows;
|
|
35
|
+
}
|
|
36
|
+
/** Create a goal from `_gg/goals/create` params; the store's own error text on failure. */
|
|
37
|
+
export async function createAcpGoal(agentDir, params) {
|
|
38
|
+
const input = params && typeof params === "object"
|
|
39
|
+
? params
|
|
40
|
+
: {};
|
|
41
|
+
const created = await createGoal(goalsRoot(agentDir), {
|
|
42
|
+
name: typeof input.name === "string" ? input.name : "",
|
|
43
|
+
goal: typeof input.goal === "string" ? input.goal : "",
|
|
44
|
+
context: Array.isArray(input.context)
|
|
45
|
+
? input.context.filter((p) => typeof p === "string")
|
|
46
|
+
: [],
|
|
47
|
+
...(typeof input.instructions === "string" ? { instructions: input.instructions } : {}),
|
|
48
|
+
}, new Date());
|
|
49
|
+
if (!created.ok)
|
|
50
|
+
return created;
|
|
51
|
+
const sessions = new SessionManager(sessionsDir(agentDir));
|
|
52
|
+
return {
|
|
53
|
+
ok: true,
|
|
54
|
+
value: toAcpSummary(await summarizeGoal(sessions, created.value.dir, created.value.record), created.value.record.instructions),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** The worker roster for `_gg/goal_state`. A reaped worker reads as closed. */
|
|
58
|
+
export function goalWorkers(snapshots) {
|
|
59
|
+
return snapshots.map((s) => ({
|
|
60
|
+
id: s.agent_id,
|
|
61
|
+
name: s.task_name,
|
|
62
|
+
...(s.agent_name ? { agent: s.agent_name } : {}),
|
|
63
|
+
state: s.state === "reaped" ? "closed" : s.state,
|
|
64
|
+
...(s.current_activity ? { activity: s.current_activity } : {}),
|
|
65
|
+
startedAt: s.started_at,
|
|
66
|
+
elapsedMs: s.elapsed_ms,
|
|
67
|
+
toolUses: s.tool_use_count,
|
|
68
|
+
...(s.model ? { model: s.model } : {}),
|
|
69
|
+
...(s.error ? { error: s.error } : {}),
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
const IMAGE_EXTENSIONS = {
|
|
73
|
+
"image/png": "png",
|
|
74
|
+
"image/jpeg": "jpg",
|
|
75
|
+
"image/gif": "gif",
|
|
76
|
+
"image/webp": "webp",
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* ACP `image` prompt blocks as the app's attachment shape, so they take the
|
|
80
|
+
* same `prepareAttachments` → `promptWithAttachments` path the desktop does.
|
|
81
|
+
* Blocks carrying only a `uri` (no inline data) are skipped.
|
|
82
|
+
*/
|
|
83
|
+
export function acpImageAttachments(blocks) {
|
|
84
|
+
if (!Array.isArray(blocks))
|
|
85
|
+
return [];
|
|
86
|
+
const out = [];
|
|
87
|
+
for (const block of blocks) {
|
|
88
|
+
const entry = block;
|
|
89
|
+
if (entry?.type !== "image" || typeof entry.data !== "string" || !entry.data)
|
|
90
|
+
continue;
|
|
91
|
+
const mediaType = typeof entry.mimeType === "string" ? entry.mimeType : "image/png";
|
|
92
|
+
const ext = IMAGE_EXTENSIONS[mediaType] ?? "img";
|
|
93
|
+
out.push({
|
|
94
|
+
kind: "image",
|
|
95
|
+
name: `image-${out.length + 1}.${ext}`,
|
|
96
|
+
mediaType,
|
|
97
|
+
data: entry.data,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return out;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=acp-goals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp-goals.js","sourceRoot":"","sources":["../../src/modes/acp-goals.ts"],"names":[],"mappings":"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"}
|
package/dist/modes/acp-mode.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import type { Message, Provider, ThinkingLevel } from "@prestyj/ai";
|
|
1
|
+
import type { Message, MessageProvenance, Provider, ThinkingLevel } from "@prestyj/ai";
|
|
2
2
|
import { type ToolExecuteResult } from "@prestyj/agent";
|
|
3
|
+
import { AgentSession, type SessionAttachment } from "../core/agent-session.js";
|
|
4
|
+
import type { ChildModelPick, SubAgentSnapshot } from "../core/subagent-manager.js";
|
|
5
|
+
import { createAskUserTool } from "../tools/ask-user.js";
|
|
6
|
+
import { type GoalBriefExtras, type GoalRecord } from "../core/goals-store.js";
|
|
3
7
|
import type { EventBus } from "../core/event-bus.js";
|
|
8
|
+
import type { AutopilotMarkerPayload } from "../core/session-manager.js";
|
|
9
|
+
import { type AcpNolanReviewer } from "./acp-autopilot.js";
|
|
4
10
|
/** The ACP major version this mode implements. Bumped only for breaking changes. */
|
|
5
11
|
export declare const ACP_PROTOCOL_VERSION = 1;
|
|
6
12
|
/**
|
|
@@ -13,7 +19,32 @@ export declare const ACP_PROTOCOL_VERSION = 1;
|
|
|
13
19
|
export interface AcpAgentSession {
|
|
14
20
|
readonly eventBus: Pick<EventBus, "on">;
|
|
15
21
|
initialize(): Promise<void>;
|
|
16
|
-
|
|
22
|
+
/** `provenance` marks EZ Goals' hidden kickoff/resume instructions. */
|
|
23
|
+
prompt(content: string, provenance?: MessageProvenance): Promise<void>;
|
|
24
|
+
/** Image prompts (`promptCapabilities.image`); without it images are ignored. */
|
|
25
|
+
promptWithAttachments?(text: string, attachments: SessionAttachment[]): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Mid-run steering (`_gg/queue`). Optional so a test double or alternative
|
|
28
|
+
* session need not support it; `_gg/queue` then answers -32602.
|
|
29
|
+
*/
|
|
30
|
+
queueMessage?(text: string): number;
|
|
31
|
+
listQueuedMessages?(): Array<{
|
|
32
|
+
id: string;
|
|
33
|
+
text: string;
|
|
34
|
+
}>;
|
|
35
|
+
cancelQueuedMessage?(id: string): boolean;
|
|
36
|
+
drainQueue?(): string;
|
|
37
|
+
/** EZ Goals' workers, for `_gg/goal_state`. */
|
|
38
|
+
listSubAgents?(): SubAgentSnapshot[];
|
|
39
|
+
/** Adds a goal's attached folder to the workspace. */
|
|
40
|
+
addDirectory?(dir: string): Promise<{
|
|
41
|
+
ok: true;
|
|
42
|
+
} | {
|
|
43
|
+
ok: false;
|
|
44
|
+
error: string;
|
|
45
|
+
}>;
|
|
46
|
+
/** Tell the agent a fact at its next turn (goal settings changed). */
|
|
47
|
+
notify?(id: string, text: string): void;
|
|
17
48
|
getState(): {
|
|
18
49
|
sessionId: string;
|
|
19
50
|
provider: Provider;
|
|
@@ -34,6 +65,16 @@ export interface AcpAgentSession {
|
|
|
34
65
|
setSignal(signal: AbortSignal): void;
|
|
35
66
|
/** Replay a session file from disk into this session. */
|
|
36
67
|
loadSession(sessionPath: string): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Nolan's verdict markers (desktop `persistAutopilotMarker`). Optional so a
|
|
70
|
+
* test double need not persist; without them a reopened session has no
|
|
71
|
+
* Nolan bubbles.
|
|
72
|
+
*/
|
|
73
|
+
persistAutopilotMarker?(phase: AutopilotMarkerPayload["phase"], extra?: {
|
|
74
|
+
reason?: string;
|
|
75
|
+
body?: string;
|
|
76
|
+
}): Promise<void>;
|
|
77
|
+
getAutopilotMarkers?(): AutopilotMarkerPayload[];
|
|
37
78
|
/** The conversation as restored, used to replay history to the client. */
|
|
38
79
|
getMessages(): Message[];
|
|
39
80
|
switchModel(provider: string, model: string): Promise<void>;
|
|
@@ -44,6 +85,12 @@ export interface AcpAgentSession {
|
|
|
44
85
|
setPlanMode(active: boolean): Promise<void>;
|
|
45
86
|
/** Bake an approved plan into the prompt so [DONE:n] progress markers work. */
|
|
46
87
|
setApprovedPlan(planPath: string | undefined): Promise<void>;
|
|
88
|
+
/** Host verification evidence for Nolan's digest; optional for test doubles. */
|
|
89
|
+
getVerificationEvidence?(): AgentSession["getVerificationEvidence"] extends () => infer R ? R : never;
|
|
90
|
+
getVerificationProblem?(): string | null;
|
|
91
|
+
/** Fresh context for an accepted plan (desktop /plan/accept). Optional:
|
|
92
|
+
* without it an accept keeps the current context and sends no reset. */
|
|
93
|
+
newSession?(preserveConversation?: boolean): Promise<void>;
|
|
47
94
|
/**
|
|
48
95
|
* Registry commands (/model, /compact, …), including any an extension
|
|
49
96
|
* registered during `initialize`. Optional so a test double need not carry a
|
|
@@ -71,6 +118,52 @@ export interface AcpPlanHooks {
|
|
|
71
118
|
/** Returns the instruction handed back to the model after approval. */
|
|
72
119
|
onExitPlan: (planPath: string) => Promise<ToolExecuteResult>;
|
|
73
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* What a session is being built for, beyond the plan hooks.
|
|
123
|
+
*
|
|
124
|
+
* A third argument rather than a change to the first two so existing session
|
|
125
|
+
* factories (tests) keep working unchanged.
|
|
126
|
+
*/
|
|
127
|
+
export interface AcpSessionContext {
|
|
128
|
+
/** The session's working directory: the goal folder for a goal session. */
|
|
129
|
+
cwd: string;
|
|
130
|
+
/** Set when the cwd is a goal folder: build a EZ Goals coordinator. */
|
|
131
|
+
goal: {
|
|
132
|
+
dir: string;
|
|
133
|
+
record: GoalRecord;
|
|
134
|
+
} | null;
|
|
135
|
+
/** The goal's brief extras (memory, attached projects' rules), read once. */
|
|
136
|
+
goalExtras?: GoalBriefExtras;
|
|
137
|
+
/** Read live: true once the user has started the goal. */
|
|
138
|
+
isGoalActive: () => boolean;
|
|
139
|
+
/** Read live at each worker spawn. */
|
|
140
|
+
getChildModel: () => ChildModelPick | undefined;
|
|
141
|
+
/**
|
|
142
|
+
* The `ask_user` tool, present only when the client opted in with
|
|
143
|
+
* `clientCapabilities._meta.gg.askUser`. Goes in `additionalTools` at
|
|
144
|
+
* construction (the tool array is append-only for the prompt cache).
|
|
145
|
+
*/
|
|
146
|
+
askUserTool?: ReturnType<typeof createAskUserTool>;
|
|
147
|
+
/**
|
|
148
|
+
* The client reviews plans itself (`clientCapabilities._meta.gg.planReview`):
|
|
149
|
+
* exit_plan parks the plan for a human decision instead of auto-approving,
|
|
150
|
+
* and the session gets the desktop's `planSubmissionGate`.
|
|
151
|
+
*/
|
|
152
|
+
planReview?: boolean;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* A plan submitted via exit_plan that awaits a decision (desktop parity:
|
|
156
|
+
* app-sidecar.ts pendingPlanPath/planGeneration/offeredPlanGeneration). One
|
|
157
|
+
* object so the autopilot cycle can read and settle it.
|
|
158
|
+
*/
|
|
159
|
+
export interface AcpPendingPlanState {
|
|
160
|
+
planPath: string | null;
|
|
161
|
+
content: string;
|
|
162
|
+
/** Bumped on every set/clear; a stale decision is refused. */
|
|
163
|
+
generation: number;
|
|
164
|
+
/** Generation last offered to the client; -1 when none. */
|
|
165
|
+
offeredGeneration: number;
|
|
166
|
+
}
|
|
74
167
|
export interface AcpModeOptions {
|
|
75
168
|
provider: Provider;
|
|
76
169
|
model: string;
|
|
@@ -86,7 +179,22 @@ export interface AcpModeOptions {
|
|
|
86
179
|
* Builds the session for `session/new`. Overridden by tests; production
|
|
87
180
|
* always gets a real {@link AgentSession}.
|
|
88
181
|
*/
|
|
89
|
-
createSession?: (signal: AbortSignal, hooks: AcpPlanHooks) => AcpAgentSession;
|
|
182
|
+
createSession?: (signal: AbortSignal, hooks: AcpPlanHooks, context: AcpSessionContext) => AcpAgentSession;
|
|
183
|
+
/** `~/.ezcoder` by default; where goals (`goals/`) and sessions live. */
|
|
184
|
+
agentDir?: string;
|
|
185
|
+
/**
|
|
186
|
+
* `ask_user` soft deadline (default: the desktop's interactive 10 min). Past
|
|
187
|
+
* it the model hears "no answer yet" and the client's question stays open.
|
|
188
|
+
*/
|
|
189
|
+
askUserDeadlineMs?: number;
|
|
190
|
+
/**
|
|
191
|
+
* Builds Autopilot Nolan's reviewer for a session's project. Overridden by
|
|
192
|
+
* tests; production gets {@link createAcpNolanReviewer}.
|
|
193
|
+
*/
|
|
194
|
+
createNolanReviewer?: (cwd: string, buildModel: () => {
|
|
195
|
+
provider: Provider;
|
|
196
|
+
model: string;
|
|
197
|
+
}) => AcpNolanReviewer;
|
|
90
198
|
}
|
|
91
199
|
/** The selectors this agent exposes. Ids are part of the wire contract. */
|
|
92
200
|
export declare const MODEL_CONFIG_ID = "model";
|
|
@@ -107,6 +215,23 @@ export declare const MODE_CONFIG_ID = "mode";
|
|
|
107
215
|
* the protocol needs of them.
|
|
108
216
|
*/
|
|
109
217
|
export declare function historyUpdates(messages: readonly Message[]): Record<string, unknown>[];
|
|
218
|
+
/** A replayed Nolan marker, as `_gg/autopilot_event` params (sans sessionId). */
|
|
219
|
+
export interface HistoryAutopilotEvent {
|
|
220
|
+
phase: string;
|
|
221
|
+
reason?: string;
|
|
222
|
+
body?: string;
|
|
223
|
+
history: true;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* {@link historyUpdates} with Nolan's verdict markers interleaved at their
|
|
227
|
+
* `afterMessageCount` (non-system messages, as the desktop history route
|
|
228
|
+
* counts them). Marker phase `plan_approved` replays as ACP `plan_accepted`.
|
|
229
|
+
*/
|
|
230
|
+
export declare function historyFrames(messages: readonly Message[], markers: readonly AutopilotMarkerPayload[]): Array<{
|
|
231
|
+
update: Record<string, unknown>;
|
|
232
|
+
} | {
|
|
233
|
+
autopilot: HistoryAutopilotEvent;
|
|
234
|
+
}>;
|
|
110
235
|
/**
|
|
111
236
|
* Serve ACP on stdio until the input stream ends.
|
|
112
237
|
*
|