@yaag/cli 0.4.0 → 0.5.2
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/assets/types/runtime/index.d.ts +1 -0
- package/assets/types/runtime/pi-state.d.ts +19 -0
- package/assets/types/runtime/system-prompt-recorder-extension.d.ts +43 -0
- package/assets/types/runtime/system-prompt-recorder.d.ts +17 -0
- package/assets/types/runtime/tool-probe.d.ts +39 -7
- package/package.json +3 -3
- package/src/cli-tree-host.ts +3 -1
|
@@ -28,6 +28,7 @@ export type { RunContext } from "./run-context.ts";
|
|
|
28
28
|
export type { DiscoveredSkill, SkillProbeFactory } from "./skill-probe.ts";
|
|
29
29
|
export type { AgentInfo, AgentState, AskingAgentInfo, EndedRunSummary, ExitedAgentInfo, IdleAgentInfo, NodeInfo, RunningRunSummary, RunOutcome, RunState, RunSummary, } from "./summary.ts";
|
|
30
30
|
export { applyEvent, initialSummary } from "./summary.ts";
|
|
31
|
+
export { readSystemPromptSidecar } from "./system-prompt-recorder.ts";
|
|
31
32
|
export type { AgentStats, AgentTransport, AskMarker, AskMarkerContext, AskPlayback, Frame, TokenBreakdown, TransportFactory, TransportStartup, TransportStartupObserver, WorktreeResolution, } from "./transport.ts";
|
|
32
33
|
export type { AskOptions, Handle, ResolvedSpawnOptions, SpawnOptions, SpawnOverrides, StructuredAskOptions, ThinkingLevel, } from "./types.ts";
|
|
33
34
|
export { AGENT_NODE_TABLE_MAX, ASK_OUTPUT_FLUSH_INTERVAL_MS, ASK_OUTPUT_MAX_BYTES, ASK_OUTPUT_TRUNCATION_MARKER, NODE_GIST_MAX_CHARS, PROMPT_GIST_MAX_CHARS, TOOL_ARGS_GIST_MAX_CHARS, } from "./wire-constants.ts";
|
|
@@ -10,6 +10,25 @@ export interface AgentProgress {
|
|
|
10
10
|
}
|
|
11
11
|
/** The command line for one Agent. */
|
|
12
12
|
export declare function piCommand(options: OpenOptions, toolProbeExtensionPath?: string): string[];
|
|
13
|
+
/** The spawn options that decide pi's `--tools` allowlist. */
|
|
14
|
+
export interface ToolSelection {
|
|
15
|
+
readonly tools?: readonly string[] | undefined;
|
|
16
|
+
readonly inherit?: boolean | undefined;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The names for pi's `--tools` flag, or null when yaag emits no allowlist and
|
|
20
|
+
* pi composes the toolset itself.
|
|
21
|
+
*
|
|
22
|
+
* This is the single source of the allowlist rule: `piCommand` writes the flag
|
|
23
|
+
* from it, and `toolContract` in tool-probe.ts states its promise from it.
|
|
24
|
+
*
|
|
25
|
+
* `--no-tools` strips extension tools as well, and refuses a tool registered
|
|
26
|
+
* afterwards, so "no tools" becomes an allowlist of exactly yaag's own tool
|
|
27
|
+
* (e2e/report-result-spike.test.ts). The tool stays inactive until a
|
|
28
|
+
* schema-bearing Ask activates it, so the Agent's effective capability is
|
|
29
|
+
* unchanged.
|
|
30
|
+
*/
|
|
31
|
+
export declare function toolAllowlist(options: ToolSelection): readonly string[] | null;
|
|
13
32
|
/**
|
|
14
33
|
* `provider/id` from a `get_state` response — what the Agent actually resolved
|
|
15
34
|
* to, not the pattern that was requested. Null when the payload has no model.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* yaag's private system-prompt recorder, loaded into every Agent at spawn.
|
|
3
|
+
*
|
|
4
|
+
* pi assembles the system prompt per turn and never persists it in the session
|
|
5
|
+
* file, so a Peek has nothing to show (observation #1204). This extension
|
|
6
|
+
* writes the assembled prompt to a sidecar file beside the session file, and pi
|
|
7
|
+
* loads it last, so the prompt it records holds every other extension's
|
|
8
|
+
* appends. It records rather than reports, so it is no probe: it sends no frame
|
|
9
|
+
* and the Orchestrator never waits for it (ADR-0035).
|
|
10
|
+
*
|
|
11
|
+
* It is strictly best-effort and silent: an Agent without a session file, or a
|
|
12
|
+
* write that fails, records nothing. It never changes the prompt, and it emits
|
|
13
|
+
* no frame, so no Ask can settle differently because of it.
|
|
14
|
+
*
|
|
15
|
+
* Types are declared locally rather than imported from pi: this file is passed
|
|
16
|
+
* to `pi -e` as a path and must load without yaag's dependency graph. pi loads
|
|
17
|
+
* it through jiti, in Node, so it uses `node:fs/promises` and no Bun-only API.
|
|
18
|
+
*/
|
|
19
|
+
/** The pi event that carries the assembled prompt of one turn. */
|
|
20
|
+
interface BeforeAgentStart {
|
|
21
|
+
readonly systemPrompt?: unknown;
|
|
22
|
+
}
|
|
23
|
+
/** The pi context slice this extension reads. */
|
|
24
|
+
interface RecorderContext {
|
|
25
|
+
readonly sessionManager: {
|
|
26
|
+
getSessionFile(): string | undefined;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** The pi surface this extension registers on. */
|
|
30
|
+
interface RecorderAPI {
|
|
31
|
+
on(event: "before_agent_start", handler: (event: BeforeAgentStart, context: RecorderContext) => Promise<undefined>): void;
|
|
32
|
+
}
|
|
33
|
+
/** Extension of the sidecar that holds one Agent's latest system prompt. */
|
|
34
|
+
export declare const SYSTEM_PROMPT_SIDECAR_SUFFIX = ".system-prompt.md";
|
|
35
|
+
/**
|
|
36
|
+
* The sidecar path for one pi session file.
|
|
37
|
+
*
|
|
38
|
+
* The session file's `.jsonl` extension is dropped, so `<id>.jsonl` and its
|
|
39
|
+
* sidecar `<id>.system-prompt.md` sit next to each other in the session dir.
|
|
40
|
+
*/
|
|
41
|
+
export declare function systemPromptSidecarPath(sessionFile: string): string;
|
|
42
|
+
export default function (pi: RecorderAPI): void;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { systemPromptSidecarPath } from "./system-prompt-recorder-extension.ts";
|
|
2
|
+
export { systemPromptSidecarPath };
|
|
3
|
+
/** Filesystem sibling path of the recorder; decodes percent-escapes (e.g. spaces). */
|
|
4
|
+
export declare function systemPromptRecorderExtensionPath(moduleUrl: string): string;
|
|
5
|
+
/** Loadable source path for the private extension that records the system prompt. */
|
|
6
|
+
export declare const SYSTEM_PROMPT_RECORDER_EXTENSION_PATH: string;
|
|
7
|
+
/**
|
|
8
|
+
* Reads the system-prompt sidecar of one Agent, or null when there is none.
|
|
9
|
+
*
|
|
10
|
+
* Null covers every case a Peek cannot show a real prompt for: an Agent that
|
|
11
|
+
* reported no session file, a session whose first turn has not started, and a
|
|
12
|
+
* session written before yaag recorded a sidecar. A Peek then falls back to the
|
|
13
|
+
* session file. An Agent of a replayed Run has the recording's session path, so
|
|
14
|
+
* a Peek on the recording machine reads the original Agent's sidecar, exactly
|
|
15
|
+
* as it reads the original Agent's transcript.
|
|
16
|
+
*/
|
|
17
|
+
export declare function readSystemPromptSidecar(sessionFile: string | null | undefined): Promise<string | null>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ToolSelection } from "./pi-state.ts";
|
|
1
2
|
import type { Frame } from "./transport.ts";
|
|
2
3
|
/** The private status key used only by yaag's internal pi tool probe extension. */
|
|
3
4
|
export declare const TOOL_PROBE_STATUS_KEY = "yaag.tool-probe.v1";
|
|
@@ -14,17 +15,48 @@ export interface ToolProbe {
|
|
|
14
15
|
/** Rejects startup when the spawned pi process ends before reporting. */
|
|
15
16
|
fail(error: Error): void;
|
|
16
17
|
}
|
|
18
|
+
/** What the spawn flags promised about the Agent's effective toolset. */
|
|
19
|
+
export interface ToolContract {
|
|
20
|
+
/** Names that must be active at startup. Never holds `report_result`. */
|
|
21
|
+
readonly required: readonly string[];
|
|
22
|
+
/** The only names that may be active; null when the effective set is unpredictable. */
|
|
23
|
+
readonly allowed: readonly string[] | null;
|
|
24
|
+
/** Names that must not be active. */
|
|
25
|
+
readonly denied: readonly string[];
|
|
26
|
+
}
|
|
27
|
+
/** The spawn options that decide what the probe can verify. */
|
|
28
|
+
export interface ToolContractOptions extends ToolSelection {
|
|
29
|
+
readonly disallowedTools?: readonly string[] | undefined;
|
|
30
|
+
}
|
|
17
31
|
/**
|
|
18
|
-
* Returns promised
|
|
32
|
+
* Returns what the spawn flags promised, or null when they promised nothing.
|
|
33
|
+
*
|
|
34
|
+
* Two promises are verifiable. A spawn that pi gets a `--tools` allowlist for
|
|
35
|
+
* promises that the allowlist holds every active name. A spawn that only denies
|
|
36
|
+
* tools promises the absence of every denied name, and nothing about the rest.
|
|
37
|
+
* An inheriting spawn without `tools` and without `disallowedTools` promises
|
|
38
|
+
* nothing, so it needs no probe.
|
|
19
39
|
*
|
|
20
|
-
*
|
|
40
|
+
* `report_result` is allowed but never required: report-result-extension.ts
|
|
41
|
+
* registers the tool when a schema-bearing Ask activates it, long after startup
|
|
42
|
+
* (ADR-0032), so at startup the probe reports it as inactive.
|
|
21
43
|
*/
|
|
22
|
-
export declare function
|
|
23
|
-
/**
|
|
24
|
-
|
|
44
|
+
export declare function toolContract(options: ToolContractOptions): ToolContract | null;
|
|
45
|
+
/**
|
|
46
|
+
* Creates a startup collector for the probe's report.
|
|
47
|
+
*
|
|
48
|
+
* The caller creates one only when `toolContract` returned a contract to verify
|
|
49
|
+
* it against, and loads the probe extension in the same decision.
|
|
50
|
+
*/
|
|
51
|
+
export declare function createToolProbe(timeoutMs?: number): ToolProbe;
|
|
25
52
|
/** True exactly for a status frame emitted by the private probe extension. */
|
|
26
53
|
export declare function isToolProbeFrame(frame: Frame): boolean;
|
|
27
54
|
/** Parses the private status payload, rejecting every malformed boundary. */
|
|
28
55
|
export declare function parseToolProbeFrame(frame: Frame): readonly string[];
|
|
29
|
-
/**
|
|
30
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Throws a diagnostic when the effective toolset breaks the promise.
|
|
58
|
+
*
|
|
59
|
+
* A missing required tool, an extra tool outside the allowlist, and a denied
|
|
60
|
+
* tool that is still active all fail the spawn the same way.
|
|
61
|
+
*/
|
|
62
|
+
export declare function verifyEffectiveTools(contract: ToolContract, effective: readonly string[]): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yaag/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@earendil-works/pi-tui": "^0.84.0",
|
|
24
|
-
"@yaag/runtime": "0.
|
|
25
|
-
"@yaag/tui": "0.
|
|
24
|
+
"@yaag/runtime": "0.5.2",
|
|
25
|
+
"@yaag/tui": "0.5.2",
|
|
26
26
|
"typebox": "1.3.7"
|
|
27
27
|
}
|
|
28
28
|
}
|
package/src/cli-tree-host.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { readFile } from "node:fs/promises";
|
|
10
10
|
import type { Terminal } from "@earendil-works/pi-tui";
|
|
11
|
-
import type
|
|
11
|
+
import { type AgentInfo, readSystemPromptSidecar } from "@yaag/runtime";
|
|
12
12
|
import { cliKeybindings, type RunTreeViewHost, type TreeState } from "@yaag/tui";
|
|
13
13
|
|
|
14
14
|
/** The terminal services one open CLI view holds. */
|
|
@@ -31,6 +31,8 @@ export function createCliTreeHost(options: CliTreeHostOptions): ReadOnlyCliHost
|
|
|
31
31
|
keybindings: cliKeybindings(),
|
|
32
32
|
agentInfo: (agent) => state.summary.agents[agent],
|
|
33
33
|
readSession: (agent) => readSession(state.summary.agents[agent]),
|
|
34
|
+
readSystemPromptSidecar: (agent) =>
|
|
35
|
+
readSystemPromptSidecar(state.summary.agents[agent]?.sessionFile),
|
|
34
36
|
sessionPath: (agent) => state.summary.agents[agent]?.sessionFile ?? null,
|
|
35
37
|
// OSC 52 is the only copy path that works over SSH without a child
|
|
36
38
|
// process, and it is what pi-tui itself uses for its own copy gesture.
|