@yaag/cli 0.8.3 → 0.10.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/assets/types/runtime/agent/spawn-parent.d.ts +11 -0
- package/assets/types/runtime/agent/spawn-request.d.ts +2 -0
- package/assets/types/runtime/ask/ask-exchange-events.d.ts +7 -1
- package/assets/types/runtime/cassette/cassette-schema.d.ts +1 -0
- package/assets/types/runtime/cassette/cassette.d.ts +5 -0
- package/assets/types/runtime/events.d.ts +22 -0
- package/assets/types/runtime/index.d.ts +1 -1
- package/assets/types/runtime/model/model-fallback.d.ts +4 -1
- package/assets/types/runtime/summary/index.d.ts +1 -1
- package/assets/types/runtime/summary/summary-agent.d.ts +13 -2
- package/assets/types/runtime/summary/summary-fallbacks.d.ts +2 -3
- package/assets/types/runtime/summary/summary-model.d.ts +16 -0
- package/assets/types/runtime/summary/summary.d.ts +1 -1
- package/assets/types/runtime/transport/fake-transport.d.ts +2 -0
- package/assets/types/runtime/transport/transport.d.ts +5 -0
- package/assets/types/runtime/types.d.ts +12 -1
- package/package.json +3 -3
- package/src/terminal/render.ts +4 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Agent } from "./agent.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Resolves a Parent Link to the parent Agent's name.
|
|
4
|
+
*
|
|
5
|
+
* Only a Handle this Run already spawned is accepted, which is what makes a
|
|
6
|
+
* lineage cycle impossible by construction: a Handle exists only after its own
|
|
7
|
+
* spawn resolved. Liveness is deliberately not checked — a cleanly exited Agent
|
|
8
|
+
* remains a valid parent, because the link states tree position, not a
|
|
9
|
+
* dependency on a live process.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveParent(parent: unknown, agents: readonly Agent[]): string | undefined;
|
|
@@ -8,6 +8,8 @@ export interface OpenRequestOptions {
|
|
|
8
8
|
readonly spawnOptions: SpawnOptions;
|
|
9
9
|
readonly resolvedExtensionPaths?: readonly string[];
|
|
10
10
|
readonly declaredExtensions?: readonly string[];
|
|
11
|
+
/** Resolved parent Agent name (Parent Link); spawn identity only, never argv. */
|
|
12
|
+
readonly parent?: string;
|
|
11
13
|
readonly sessionDir: string | undefined;
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
@@ -12,7 +12,7 @@ export interface AskEndOutcome {
|
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* Emits the Ask-scoped Lifecycle Events for one exchange, plus the Agent-scoped
|
|
15
|
-
* `model_fallback` this exchange's fallback loop reports.
|
|
15
|
+
* `model_fallback` and `agent_model` this exchange's fallback loop reports.
|
|
16
16
|
*/
|
|
17
17
|
export declare class AskEvents {
|
|
18
18
|
#private;
|
|
@@ -24,6 +24,12 @@ export declare class AskEvents {
|
|
|
24
24
|
node: (snapshot: NodeSnapshot) => void;
|
|
25
25
|
/** Not Ask-scoped: a fallback names the Agent only, like the spawn-time loop. */
|
|
26
26
|
fallback: (fallback: ModelFallback) => void;
|
|
27
|
+
/**
|
|
28
|
+
* The concrete model the Agent runs after a swap that landed (ADR-0041).
|
|
29
|
+
* Agent-scoped like `fallback`: the pattern side of the story stays in
|
|
30
|
+
* `model_fallback`, and this carries pi's own `provider/id`.
|
|
31
|
+
*/
|
|
32
|
+
model: (model: string) => void;
|
|
27
33
|
/** A `normal` cause is the absent default, so ordinary settlements stay lean. */
|
|
28
34
|
end(outcome: AskEndOutcome): void;
|
|
29
35
|
}
|
|
@@ -31,6 +31,7 @@ export declare const CassetteSchema: Type.TObject<{
|
|
|
31
31
|
cwd: Type.TString;
|
|
32
32
|
worktree: Type.TOptional<Type.TLiteral<true>>;
|
|
33
33
|
declaredExtensions: Type.TOptional<Type.TArray<Type.TString>>;
|
|
34
|
+
parent: Type.TOptional<Type.TString>;
|
|
34
35
|
}>;
|
|
35
36
|
model: Type.TString;
|
|
36
37
|
sessionFile: Type.TOptional<Type.TString>;
|
|
@@ -72,6 +72,11 @@ export interface CassetteSpawn {
|
|
|
72
72
|
* across machines (ADR-0040). Absent when the Agent ran no extension.
|
|
73
73
|
*/
|
|
74
74
|
readonly declaredExtensions?: readonly string[];
|
|
75
|
+
/**
|
|
76
|
+
* Resolved name of the Agent named as this Agent's parent (Parent Link).
|
|
77
|
+
* Part of spawn identity; absent for a root Agent and for older Cassettes.
|
|
78
|
+
*/
|
|
79
|
+
readonly parent?: string;
|
|
75
80
|
}
|
|
76
81
|
/** The frames attributed to one Ask marker. */
|
|
77
82
|
export interface CassetteAsk {
|
|
@@ -17,6 +17,11 @@ export type { ModelErrorReason } from "./model/index.ts";
|
|
|
17
17
|
* settled Run never writes it (ADR-0031).
|
|
18
18
|
*/
|
|
19
19
|
export type RunOutcome = "completed" | "failed" | "stopped" | "paused" | "interrupted";
|
|
20
|
+
/**
|
|
21
|
+
* How an Agent came to be. An absent value on an event means "spawn"; "fork"
|
|
22
|
+
* arrives with the forking spec.
|
|
23
|
+
*/
|
|
24
|
+
export type SpawnOrigin = "spawn" | "fork";
|
|
20
25
|
/** The current, Ask-scoped observer projection derived from Agent frames. */
|
|
21
26
|
export type AgentActivity = {
|
|
22
27
|
readonly type: "thinking";
|
|
@@ -65,6 +70,10 @@ export type LifecycleEventBody = {
|
|
|
65
70
|
* Cassette-playback Agents and events from older CLIs.
|
|
66
71
|
*/
|
|
67
72
|
readonly sessionFile?: string;
|
|
73
|
+
/** Resolved name of the Agent named as this Agent's parent (Parent Link). */
|
|
74
|
+
readonly parent?: string;
|
|
75
|
+
/** How the Agent came to be; absent means "spawn". */
|
|
76
|
+
readonly origin?: SpawnOrigin;
|
|
68
77
|
} | {
|
|
69
78
|
readonly type: "ask_start";
|
|
70
79
|
readonly agent: string;
|
|
@@ -130,6 +139,19 @@ export type LifecycleEventBody = {
|
|
|
130
139
|
readonly attempt: number;
|
|
131
140
|
/** The candidate resolution picked next. */
|
|
132
141
|
readonly resolvedModel: string;
|
|
142
|
+
} | {
|
|
143
|
+
/**
|
|
144
|
+
* The concrete model an Agent runs from now on, reported when it changes
|
|
145
|
+
* after spawn. Today the only producer is a successful mid-Ask model swap
|
|
146
|
+
* (ADR-0038, ADR-0041): `model_fallback` names the pattern the resolver
|
|
147
|
+
* picked, this names the `provider/id` pi landed on, so `agent.model`
|
|
148
|
+
* stays concrete. Spawn needs none: `agent_spawn.model` is already
|
|
149
|
+
* concrete.
|
|
150
|
+
*/
|
|
151
|
+
readonly type: "agent_model";
|
|
152
|
+
readonly agent: string;
|
|
153
|
+
/** pi's concrete `provider/id` for the model the Agent runs now. */
|
|
154
|
+
readonly model: string;
|
|
133
155
|
} | {
|
|
134
156
|
readonly type: "agent_usage";
|
|
135
157
|
readonly agent: string;
|
|
@@ -6,7 +6,7 @@ export type { ConfigEnvironment, ConfigExtension, ConfigLayerName, EffectiveConf
|
|
|
6
6
|
export { EMPTY_EFFECTIVE_CONFIG, loadEffectiveConfig, PROJECT_CONFIG_DIR, } from "./config/index.ts";
|
|
7
7
|
export type { AskInvalidOutputOutcome, AskLimitKind, AskLimitOutcome, AskStalledOutcome, ModelResolutionOutcome, YaagErrorCode, } from "./errors.ts";
|
|
8
8
|
export { isYaagError, YaagError } from "./errors.ts";
|
|
9
|
-
export type { AgentActivity, AskOutputChannel, EventSink, LifecycleEvent, LifecycleEventBody, NodeState, NodeUsage, StampedEventSink, } from "./events.ts";
|
|
9
|
+
export type { AgentActivity, AskOutputChannel, EventSink, LifecycleEvent, LifecycleEventBody, NodeState, NodeUsage, SpawnOrigin, StampedEventSink, } from "./events.ts";
|
|
10
10
|
export type { ModelError, ModelErrorReason, ModelResolver, ModelSelection, ModelSpec, ThinkingResolver, ThinkingSpec, } from "./model/index.ts";
|
|
11
11
|
export type { DecodedNode, NodeDecoder, NodePath, NodeSnapshot } from "./node/index.ts";
|
|
12
12
|
export { agentAskPath, childPath, DEFAULT_NODE_DECODERS, NodeTracker, sanitizeNodeName, } from "./node/index.ts";
|
|
@@ -6,7 +6,10 @@ export interface ModelFallback {
|
|
|
6
6
|
readonly reason: ModelErrorReason;
|
|
7
7
|
/** 0-based index of the failed attempt in the Agent's shared history. */
|
|
8
8
|
readonly attempt: number;
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* The candidate the resolver picked next. It is a yaag pattern, not a
|
|
11
|
+
* concrete `provider/id`, so it is never an Agent's model (ADR-0041).
|
|
12
|
+
*/
|
|
10
13
|
readonly resolvedModel: string;
|
|
11
14
|
}
|
|
12
15
|
/** Where a Model Resolution loop reports each fallback it takes. */
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* Files inside this directory import each other directly.
|
|
4
4
|
*/
|
|
5
5
|
export { applyEvent, type EndedRunSummary, initialSummary, type RunningRunSummary, type RunOutcome, type RunState, type RunSummary, } from "./summary.ts";
|
|
6
|
-
export type { AgentInfo, AgentState, AskingAgentInfo, ExitedAgentInfo, IdleAgentInfo, ModelFallbackInfo, NodeInfo, } from "./summary-agent.ts";
|
|
6
|
+
export type { AgentInfo, AgentState, AskingAgentInfo, ExitedAgentInfo, IdleAgentInfo, ModelFallbackInfo, NodeInfo, SpawnOrigin, } from "./summary-agent.ts";
|
|
@@ -1,19 +1,28 @@
|
|
|
1
|
-
import type { AgentActivity } from "../events.ts";
|
|
1
|
+
import type { AgentActivity, SpawnOrigin } from "../events.ts";
|
|
2
2
|
import type { TokenBreakdown, WorktreeResolution } from "../transport/index.ts";
|
|
3
3
|
import type { ModelFallbackInfo } from "./summary-fallbacks.ts";
|
|
4
4
|
import type { NodeInfo } from "./summary-nodes.ts";
|
|
5
|
-
export type { AgentActivity } from "../events.ts";
|
|
5
|
+
export type { AgentActivity, SpawnOrigin } from "../events.ts";
|
|
6
6
|
export type { ModelFallbackInfo } from "./summary-fallbacks.ts";
|
|
7
7
|
export type { NodeInfo } from "./summary-nodes.ts";
|
|
8
8
|
/** The observer-facing lifecycle state of an Agent. */
|
|
9
9
|
export type AgentState = "idle" | "asking" | "exited";
|
|
10
10
|
/** Identity and accounting facts that apply in every observer Agent state. */
|
|
11
11
|
interface AgentInfoBase {
|
|
12
|
+
/**
|
|
13
|
+
* Always the concrete `provider/id` pi reports — from `agent_spawn` at spawn
|
|
14
|
+
* and from `agent_model` after every Model Fallback that landed (ADR-0041).
|
|
15
|
+
* A `resolvedModel` pattern never lands here.
|
|
16
|
+
*/
|
|
12
17
|
readonly model: string | null;
|
|
13
18
|
readonly cwd: string | null;
|
|
14
19
|
readonly branch: string | null;
|
|
15
20
|
/** pi's session file for this Agent, when the spawn reported one; a Peek reads it. */
|
|
16
21
|
readonly sessionFile: string | null;
|
|
22
|
+
/** The Agent named as this one's parent (Parent Link), or null for a root Agent. */
|
|
23
|
+
readonly parent: string | null;
|
|
24
|
+
/** How the Agent came to be; "spawn" until forking ships. */
|
|
25
|
+
readonly origin: SpawnOrigin;
|
|
17
26
|
readonly activity: AgentActivity | null;
|
|
18
27
|
readonly tokens: TokenBreakdown | null;
|
|
19
28
|
readonly cost: number | null;
|
|
@@ -85,6 +94,8 @@ export declare function spawnAgent(current: AgentRecord | undefined, identity: {
|
|
|
85
94
|
readonly cwd: string;
|
|
86
95
|
readonly branch?: string;
|
|
87
96
|
readonly sessionFile?: string;
|
|
97
|
+
readonly parent?: string;
|
|
98
|
+
readonly origin?: SpawnOrigin;
|
|
88
99
|
}, at: number | null): AgentRecord;
|
|
89
100
|
/**
|
|
90
101
|
* Folds an Ask start into the asking arm when it is not older than the folded
|
|
@@ -22,9 +22,8 @@ type ModelFallbackEvent = Extract<LifecycleEventBody, {
|
|
|
22
22
|
* The Agent's `model` is left alone. `resolvedModel` is a yaag pattern, which
|
|
23
23
|
* can be partial, and the event reports it before the swap is applied, while
|
|
24
24
|
* `model` is pi's resolved `provider/id` for the model the Agent really runs.
|
|
25
|
-
* `agent_spawn`
|
|
26
|
-
*
|
|
27
|
-
* spawn-time id.
|
|
25
|
+
* Only `agent_spawn` and `agent_model` write that field: a mid-Ask swap that
|
|
26
|
+
* lands reports the concrete model in its own `agent_model` event (ADR-0041).
|
|
28
27
|
*/
|
|
29
28
|
export declare function applyModelFallback(agent: AgentRecord, event: ModelFallbackEvent, at: number | null): AgentRecord;
|
|
30
29
|
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LifecycleEventBody } from "../events.ts";
|
|
2
|
+
import type { AgentRecord } from "./summary-agent.ts";
|
|
3
|
+
type AgentModelEvent = Extract<LifecycleEventBody, {
|
|
4
|
+
readonly type: "agent_model";
|
|
5
|
+
}>;
|
|
6
|
+
/**
|
|
7
|
+
* Folds the concrete model an Agent runs now (ADR-0041).
|
|
8
|
+
*
|
|
9
|
+
* The event reports pi's `provider/id` after a swap landed, so it replaces
|
|
10
|
+
* `model` and nothing else: a model change is not a lifecycle state change, and
|
|
11
|
+
* `state`, `askIndex`, `activity`, `stateChangedAt` and the bounded fallback
|
|
12
|
+
* table stay as they are. An exited Agent is skipped, because its model is
|
|
13
|
+
* frozen together with its final accounting.
|
|
14
|
+
*/
|
|
15
|
+
export declare function applyAgentModel(agent: AgentRecord, event: AgentModelEvent): AgentRecord;
|
|
16
|
+
export {};
|
|
@@ -2,7 +2,7 @@ import type { LifecycleEvent, LifecycleEventBody, RunOutcome } from "../events.t
|
|
|
2
2
|
import type { TokenBreakdown } from "../transport/index.ts";
|
|
3
3
|
import type { AgentInfo } from "./summary-agent.ts";
|
|
4
4
|
export type { NodeState, NodeUsage, RunOutcome } from "../events.ts";
|
|
5
|
-
export type { AgentActivity, AgentInfo, AgentState, AskingAgentInfo, ExitedAgentInfo, IdleAgentInfo, ModelFallbackInfo, NodeInfo, } from "./summary-agent.ts";
|
|
5
|
+
export type { AgentActivity, AgentInfo, AgentState, AskingAgentInfo, ExitedAgentInfo, IdleAgentInfo, ModelFallbackInfo, NodeInfo, SpawnOrigin, } from "./summary-agent.ts";
|
|
6
6
|
/** The observer-facing lifecycle state of a Run. */
|
|
7
7
|
export type RunState = "running" | "ended";
|
|
8
8
|
/** Accounting and identity facts shared by all Run observer states. */
|
|
@@ -45,6 +45,8 @@ export interface FakeTransportOptions extends FakePromptScript {
|
|
|
45
45
|
readonly schemaCommandError?: string;
|
|
46
46
|
/** The snapshot answered to `get_available_models`; defaults to this fake's own model. */
|
|
47
47
|
readonly models?: readonly AvailableModel[];
|
|
48
|
+
/** The model this fake reports before any swap; defaults to a placeholder id. */
|
|
49
|
+
readonly model?: string;
|
|
48
50
|
/** Makes a `set_model` command fail, as pi does for a pair it does not know. */
|
|
49
51
|
readonly setModelError?: string;
|
|
50
52
|
/** Makes a `set_thinking_level` command fail. */
|
|
@@ -162,6 +162,11 @@ export interface OpenOptions {
|
|
|
162
162
|
* Spawn identity only: it never becomes argv, and it is absent when empty.
|
|
163
163
|
*/
|
|
164
164
|
readonly declaredExtensions?: readonly string[];
|
|
165
|
+
/**
|
|
166
|
+
* Resolved name of the Agent named as this Agent's parent (Parent Link).
|
|
167
|
+
* Spawn identity only: it never becomes argv.
|
|
168
|
+
*/
|
|
169
|
+
readonly parent?: string;
|
|
165
170
|
/** Session storage directory. Used by the e2e suite to stay out of ~/.pi (ticket 06). */
|
|
166
171
|
readonly sessionDir?: string;
|
|
167
172
|
/** Resumes an existing pi session, translated to `--session <path>`. */
|
|
@@ -64,14 +64,23 @@ export interface SpawnOptions {
|
|
|
64
64
|
readonly name?: string;
|
|
65
65
|
/** Request a fresh Git worktree. The requested cwd remains the base until spawn resolves. */
|
|
66
66
|
readonly worktree?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Names this Agent's parent in the Run tree (Parent Link). Data only: it is
|
|
69
|
+
* no conversation channel and no lifetime rule.
|
|
70
|
+
*/
|
|
71
|
+
readonly parent?: Handle;
|
|
67
72
|
}
|
|
68
73
|
/**
|
|
69
74
|
* Spawn options after Model Resolution has settled one model and thinking level.
|
|
70
75
|
*
|
|
71
76
|
* This is the settled shape, and it is what the Cassette identity hashes
|
|
72
77
|
* (ADR-0039).
|
|
78
|
+
*
|
|
79
|
+
* `parent` is omitted on purpose: a Handle must never reach this shape, because
|
|
80
|
+
* an Ask records these options into the Cassette. Spawn resolves the Parent
|
|
81
|
+
* Link to a name, which travels in `OpenOptions` and stays out of Ask identity.
|
|
73
82
|
*/
|
|
74
|
-
export interface ResolvedSpawnOptions extends Omit<SpawnOptions, "model" | "thinking"> {
|
|
83
|
+
export interface ResolvedSpawnOptions extends Omit<SpawnOptions, "model" | "thinking" | "parent"> {
|
|
75
84
|
readonly model?: string;
|
|
76
85
|
readonly thinking?: ThinkingLevel;
|
|
77
86
|
}
|
|
@@ -83,6 +92,8 @@ export interface SpawnOverrides {
|
|
|
83
92
|
readonly cwd?: string;
|
|
84
93
|
/** Request a fresh Git worktree. */
|
|
85
94
|
readonly worktree?: boolean;
|
|
95
|
+
/** Names this Agent's parent in the Run tree (Parent Link). Data only. */
|
|
96
|
+
readonly parent?: Handle;
|
|
86
97
|
}
|
|
87
98
|
/**
|
|
88
99
|
* Options for one Ask (ADR-0003).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yaag/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
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.10.0",
|
|
25
|
+
"@yaag/tui": "0.10.0",
|
|
26
26
|
"typebox": "1.3.7"
|
|
27
27
|
}
|
|
28
28
|
}
|
package/src/terminal/render.ts
CHANGED
|
@@ -24,7 +24,7 @@ function renderPlainEvent(event: LifecycleEventBody, mode: PlainRenderMode): str
|
|
|
24
24
|
case "run_start":
|
|
25
25
|
return `[yaag] run ${event.program}`;
|
|
26
26
|
case "agent_spawn":
|
|
27
|
-
return `[${event.agent}] spawned ${event.model} in ${event.cwd}`;
|
|
27
|
+
return `[${event.agent}] spawned ${event.model} in ${event.cwd}${event.parent === undefined ? "" : ` under ${event.parent}`}`;
|
|
28
28
|
case "ask_start":
|
|
29
29
|
return `[${event.agent}] ask #${event.index + 1}${event.replayed === true ? " (replayed)" : ""}${event.promptGist === "" ? "" : ` — ${event.promptGist}`}`;
|
|
30
30
|
case "ask_activity":
|
|
@@ -41,6 +41,8 @@ function renderPlainEvent(event: LifecycleEventBody, mode: PlainRenderMode): str
|
|
|
41
41
|
}
|
|
42
42
|
case "model_fallback":
|
|
43
43
|
return `[${event.agent}] model ${event.failedModel} ${event.reason} — falling back to ${event.resolvedModel}`;
|
|
44
|
+
case "agent_model":
|
|
45
|
+
return `[${event.agent}] model \u2014 now running ${event.model}`;
|
|
44
46
|
case "agent_exit":
|
|
45
47
|
return `[${event.agent}] exit ${tokens(event.tokens)} ${cost(event.cost)}${event.incomplete ? " (killed mid-ask, cost incomplete)" : ""}`;
|
|
46
48
|
case "run_end": {
|
|
@@ -61,6 +63,7 @@ function minimalEvent(type: LifecycleEventBody["type"]): boolean {
|
|
|
61
63
|
type === "ask_start" ||
|
|
62
64
|
type === "ask_end" ||
|
|
63
65
|
type === "model_fallback" ||
|
|
66
|
+
type === "agent_model" ||
|
|
64
67
|
type === "agent_exit" ||
|
|
65
68
|
type === "run_end"
|
|
66
69
|
);
|