@selesai/code 0.3.10 → 0.5.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/core/agent-session-auto-handoff.test.d.ts +2 -0
- package/dist/core/agent-session-auto-handoff.test.d.ts.map +1 -0
- package/dist/core/agent-session-auto-handoff.test.js +161 -0
- package/dist/core/agent-session-auto-handoff.test.js.map +1 -0
- package/dist/core/agent-session.d.ts +4 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +43 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/settings-manager-auto-handoff.test.d.ts +2 -0
- package/dist/core/settings-manager-auto-handoff.test.d.ts.map +1 -0
- package/dist/core/settings-manager-auto-handoff.test.js +29 -0
- package/dist/core/settings-manager-auto-handoff.test.js.map +1 -0
- package/dist/core/settings-manager.d.ts +9 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +22 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/defaults/models.json +2 -3
- package/dist/extensions/caveman/index.js +16 -1
- package/dist/extensions/caveman/test/extension.test.js +7 -4
- package/dist/extensions/caveman/test/helpers.test.js +12 -1
- package/dist/extensions/context-compaction-reminder.test.ts +82 -0
- package/dist/extensions/context-compaction-reminder.ts +28 -0
- package/dist/extensions/handoff-new.test.ts +2 -13
- package/dist/extensions/handoff-new.ts +16 -25
- package/dist/extensions/package.json +1 -0
- package/dist/extensions/pi-powerline-footer/index.ts +43 -2
- package/dist/extensions/pi-powerline-footer/session-usage.ts +44 -0
- package/dist/extensions/pi-powerline-footer/tests/session-usage.test.ts +47 -0
- package/dist/extensions/pi-subagents/README.md +1 -1
- package/dist/extensions/pi-subagents/agents/architect.md +9 -29
- package/dist/extensions/pi-subagents/agents/builder.md +17 -106
- package/dist/extensions/pi-subagents/agents/commentator.md +20 -117
- package/dist/extensions/pi-subagents/agents/explorer.md +14 -35
- package/dist/extensions/pi-subagents/agents/recapper.md +20 -12
- package/dist/extensions/pi-subagents/agents/researcher.md +11 -34
- package/dist/extensions/pi-subagents/src/agents/agents.ts +46 -0
- package/dist/extensions/pi-subagents/src/extension/index.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +2 -0
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +24 -0
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +25 -1
- package/dist/extensions/question/constants.ts +0 -7
- package/dist/extensions/question/index.ts +11 -108
- package/dist/extensions/question/schemas.ts +1 -26
- package/dist/extensions/question/shortcuts.ts +5 -14
- package/dist/extensions/question/tests/question-list.test.ts +8 -0
- package/dist/extensions/question/tests/ui-protocol.test.ts +1 -7
- package/dist/extensions/question/tui-adapter.ts +3 -20
- package/dist/extensions/question/types.ts +0 -6
- package/dist/extensions/question/ui-protocol.ts +2 -17
- package/dist/extensions/workflow/adapter.ts +395 -275
- package/dist/extensions/workflow/extension.ts +2 -1
- package/dist/extensions/workflow/modes/prototype.ts +17 -19
- package/dist/extensions/workflow/modes/quick.ts +17 -19
- package/dist/extensions/workflow/modes/task.ts +82 -0
- package/dist/extensions/workflow/run-state.ts +124 -0
- package/dist/extensions/workflow/state-machine.ts +7 -8
- package/dist/extensions/workflow/task-validators.ts +69 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +20 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +8 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +8 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +12 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +14 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +20 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/skills/workflow-creation/SKILL.md +72 -0
- package/docs/workflows.md +46 -7
- package/package.json +1 -1
|
@@ -28,11 +28,10 @@ function createPiHarness() {
|
|
|
28
28
|
return { commands };
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
test("registers
|
|
31
|
+
test("registers handoff-new only", () => {
|
|
32
32
|
const { commands } = createPiHarness();
|
|
33
33
|
assert.ok(commands.has("handoff-new"));
|
|
34
|
-
assert.
|
|
35
|
-
assert.equal(commands.get("handoff-new")?.handler, commands.get("handover-new")?.handler);
|
|
34
|
+
assert.equal(commands.has("handover-new"), false);
|
|
36
35
|
});
|
|
37
36
|
|
|
38
37
|
// ---- pure helpers ----
|
|
@@ -106,7 +105,6 @@ test("buildAiContext: embeds conversation + goal into one user turn", () => {
|
|
|
106
105
|
function createCtx(opts: {
|
|
107
106
|
branch?: SessionEntry[];
|
|
108
107
|
model?: any;
|
|
109
|
-
editorResult?: string;
|
|
110
108
|
customResult?: string | null;
|
|
111
109
|
mode?: string;
|
|
112
110
|
} = {}) {
|
|
@@ -130,7 +128,6 @@ function createCtx(opts: {
|
|
|
130
128
|
ui: {
|
|
131
129
|
notify: (msg: string, kind: string) => calls.notify.push({ msg, kind }),
|
|
132
130
|
custom: async <T>(_factory: any): Promise<T> => (opts.customResult === undefined ? "HANDOFF PROMPT" : opts.customResult) as unknown as T,
|
|
133
|
-
editor: async (_title: string, prefill?: string) => ("editorResult" in opts ? opts.editorResult : prefill),
|
|
134
131
|
setEditorText: (text: string) => {
|
|
135
132
|
calls.editorText = text;
|
|
136
133
|
},
|
|
@@ -196,14 +193,6 @@ test("custom null (cancelled) does not open new session", async () => {
|
|
|
196
193
|
assert.ok(calls.notify.some((n) => /Cancelled/.test(n.msg)));
|
|
197
194
|
});
|
|
198
195
|
|
|
199
|
-
test("editor cancel does not open new session", async () => {
|
|
200
|
-
const { commands } = createPiHarness();
|
|
201
|
-
const { ctx, calls } = createCtx({ editorResult: undefined });
|
|
202
|
-
await commands.get("handoff-new")!.handler("goal", ctx);
|
|
203
|
-
assert.equal(calls.newSession, null);
|
|
204
|
-
assert.ok(calls.notify.some((n) => /Cancelled/.test(n.msg)));
|
|
205
|
-
});
|
|
206
|
-
|
|
207
196
|
// sanity: DEFAULT_GOAL exported and non-empty (used by handler)
|
|
208
197
|
test("DEFAULT_GOAL is non-empty", () => {
|
|
209
198
|
assert.ok(DEFAULT_GOAL.length > 0);
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* /handoff-new — generate a handoff prompt and open a clean new session with
|
|
3
|
-
* that content as the
|
|
3
|
+
* that content as the first unsent prompt (editor text, not hidden system
|
|
4
4
|
* prompt). Sibling of examples/extensions/handoff.ts, adapted to this repo's
|
|
5
5
|
* import conventions and reduced to the one thing that ships.
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
8
|
* /handoff-new continue implementing the workflow fix
|
|
9
|
-
* /handover-new ship plan 2
|
|
10
9
|
*
|
|
11
|
-
* If no goal argument is given, a default goal is used. The
|
|
12
|
-
*
|
|
10
|
+
* If no goal argument is given, a default goal is used. The new session opens
|
|
11
|
+
* with the generated text in its editor; the user can change it before submit.
|
|
13
12
|
*/
|
|
14
13
|
|
|
15
14
|
import type { AgentMessage } from "@earendil-works/pi-agent-core";
|
|
@@ -17,14 +16,15 @@ import { complete, type Context } from "@earendil-works/pi-ai/compat";
|
|
|
17
16
|
import type { ExtensionAPI, ExtensionCommandContext, SessionEntry } from "@selesai/code";
|
|
18
17
|
import { BorderedLoader, convertToLlm, serializeConversation } from "@selesai/code";
|
|
19
18
|
|
|
20
|
-
const SYSTEM_PROMPT = `
|
|
19
|
+
const SYSTEM_PROMPT = `Write a handoff document summarising the current conversation so a fresh agent can continue the work. Save to the temporary directory of the user's OS - not the current workspace.
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
2. Lists any relevant files that were discussed or modified
|
|
24
|
-
3. Clearly states the next task based on the user's goal
|
|
25
|
-
4. Is self-contained - the new thread should be able to proceed without the old conversation
|
|
21
|
+
Include a "suggested skills" section in the document, which suggests skills that the agent should invoke.
|
|
26
22
|
|
|
27
|
-
|
|
23
|
+
Do not duplicate content already captured in other artifacts (PRDs, plans, ADRs, issues, commits, diffs). Reference them by path or URL instead.
|
|
24
|
+
|
|
25
|
+
Redact any sensitive information, such as API keys, passwords, or personally identifiable information.
|
|
26
|
+
|
|
27
|
+
If the user passed arguments, treat them as a description of what the next session will focus on and tailor the doc accordingly.`;
|
|
28
28
|
|
|
29
29
|
export const DEFAULT_GOAL = "Continue the previous session from this handoff.";
|
|
30
30
|
|
|
@@ -85,13 +85,10 @@ export function buildAiContext(conversationText: string, goal: string): Context
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
export default function (pi: ExtensionAPI) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
handler: handoffNew,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
88
|
+
pi.registerCommand("handoff-new", {
|
|
89
|
+
description: "Generate a handoff prompt and open a clean new session with it as the first draft",
|
|
90
|
+
handler: handoffNew,
|
|
91
|
+
});
|
|
95
92
|
}
|
|
96
93
|
|
|
97
94
|
async function handoffNew(args: string, ctx: ExtensionCommandContext) {
|
|
@@ -151,17 +148,11 @@ async function handoffNew(args: string, ctx: ExtensionCommandContext) {
|
|
|
151
148
|
return;
|
|
152
149
|
}
|
|
153
150
|
|
|
154
|
-
|
|
155
|
-
if (editedPrompt === undefined) {
|
|
156
|
-
ctx.ui.notify("Cancelled", "info");
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Editor text, NOT a hidden system prompt: the user reviews and submits.
|
|
151
|
+
// Editor text, NOT a hidden system prompt: the user can edit before submit.
|
|
161
152
|
const newSessionResult = await ctx.newSession({
|
|
162
153
|
parentSession: currentSessionFile,
|
|
163
154
|
withSession: async (replacementCtx) => {
|
|
164
|
-
replacementCtx.ui.setEditorText(
|
|
155
|
+
replacementCtx.ui.setEditorText(result);
|
|
165
156
|
replacementCtx.ui.notify("Handoff ready. Submit when ready.", "info");
|
|
166
157
|
},
|
|
167
158
|
});
|
|
@@ -62,6 +62,7 @@ import {
|
|
|
62
62
|
generateVibesBatch,
|
|
63
63
|
} from "./working-vibes.ts";
|
|
64
64
|
import { setupTpsTracker } from "./tps.ts";
|
|
65
|
+
import { readAsyncSubagentUsage, readSubagentToolResultUsage } from "./session-usage.ts";
|
|
65
66
|
|
|
66
67
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
67
68
|
// Configuration
|
|
@@ -928,6 +929,7 @@ export default function powerlineFooter(pi: ExtensionAPI) {
|
|
|
928
929
|
let getThinkingLevelFn: (() => string) | null = null;
|
|
929
930
|
let currentThinkingLevel: string | null = null;
|
|
930
931
|
let liveAssistantUsage: SessionAssistantUsage | null = null;
|
|
932
|
+
const completedAsyncSubagentUsage = new Map<string, { input: number; output: number; cacheRead: number; cacheWrite: number; cost: number }>();
|
|
931
933
|
let isStreaming = false;
|
|
932
934
|
let tuiRef: any = null;
|
|
933
935
|
let restoreFooterStatusRepaintHook: (() => void) | null = null;
|
|
@@ -1181,6 +1183,7 @@ export default function powerlineFooter(pi: ExtensionAPI) {
|
|
|
1181
1183
|
lastUserPrompt = "";
|
|
1182
1184
|
isStreaming = false;
|
|
1183
1185
|
liveAssistantUsage = null;
|
|
1186
|
+
completedAsyncSubagentUsage.clear();
|
|
1184
1187
|
stashedEditorText = null;
|
|
1185
1188
|
|
|
1186
1189
|
const settings = readSettings(ctx.cwd);
|
|
@@ -1222,6 +1225,7 @@ export default function powerlineFooter(pi: ExtensionAPI) {
|
|
|
1222
1225
|
|
|
1223
1226
|
pi.on("session_shutdown", async () => {
|
|
1224
1227
|
sessionGeneration++;
|
|
1228
|
+
completedAsyncSubagentUsage.clear();
|
|
1225
1229
|
dismissWelcomeOverlay?.();
|
|
1226
1230
|
dismissWelcomeOverlay = null;
|
|
1227
1231
|
welcomeHeaderActive = false;
|
|
@@ -1246,6 +1250,16 @@ export default function powerlineFooter(pi: ExtensionAPI) {
|
|
|
1246
1250
|
resetLayoutCache();
|
|
1247
1251
|
});
|
|
1248
1252
|
|
|
1253
|
+
pi.events.on("subagent:async-complete", (event) => {
|
|
1254
|
+
const completed = readAsyncSubagentUsage(event);
|
|
1255
|
+
const sessionId = currentCtx?.sessionManager?.getSessionId?.();
|
|
1256
|
+
if (!completed || !sessionId || completed.sessionId !== sessionId) return;
|
|
1257
|
+
|
|
1258
|
+
completedAsyncSubagentUsage.set(completed.runId, completed.usage);
|
|
1259
|
+
layoutDirty = true;
|
|
1260
|
+
requestImmediateStatusRender({ deferDuringTyping: false });
|
|
1261
|
+
});
|
|
1262
|
+
|
|
1249
1263
|
// Check if a bash command might change git branch
|
|
1250
1264
|
const mightChangeGitBranch = (cmd: string): boolean => {
|
|
1251
1265
|
const gitBranchPatterns = [
|
|
@@ -1256,7 +1270,12 @@ export default function powerlineFooter(pi: ExtensionAPI) {
|
|
|
1256
1270
|
};
|
|
1257
1271
|
|
|
1258
1272
|
// Invalidate git status on file changes, trigger re-render on potential branch changes
|
|
1259
|
-
pi.on("tool_result", async (event) => {
|
|
1273
|
+
pi.on("tool_result", async (event, ctx) => {
|
|
1274
|
+
if (event.toolName === "subagent") {
|
|
1275
|
+
currentCtx = ctx;
|
|
1276
|
+
layoutDirty = true;
|
|
1277
|
+
requestImmediateStatusRender({ deferDuringTyping: false });
|
|
1278
|
+
}
|
|
1260
1279
|
if (event.toolName === "write" || event.toolName === "edit") {
|
|
1261
1280
|
invalidateGitStatus();
|
|
1262
1281
|
}
|
|
@@ -2051,7 +2070,21 @@ export default function powerlineFooter(pi: ExtensionAPI) {
|
|
|
2051
2070
|
thinkingLevelFromSession = e.thinkingLevel;
|
|
2052
2071
|
}
|
|
2053
2072
|
|
|
2054
|
-
if (e.type !== "message"
|
|
2073
|
+
if (e.type !== "message") {
|
|
2074
|
+
continue;
|
|
2075
|
+
}
|
|
2076
|
+
|
|
2077
|
+
const subagentUsage = readSubagentToolResultUsage(e.message);
|
|
2078
|
+
if (subagentUsage) {
|
|
2079
|
+
input += subagentUsage.input;
|
|
2080
|
+
output += subagentUsage.output;
|
|
2081
|
+
cacheRead += subagentUsage.cacheRead;
|
|
2082
|
+
cacheWrite += subagentUsage.cacheWrite;
|
|
2083
|
+
cost += subagentUsage.cost;
|
|
2084
|
+
continue;
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
if (!isSessionAssistantMessage(e.message)) {
|
|
2055
2088
|
continue;
|
|
2056
2089
|
}
|
|
2057
2090
|
|
|
@@ -2069,6 +2102,14 @@ export default function powerlineFooter(pi: ExtensionAPI) {
|
|
|
2069
2102
|
}
|
|
2070
2103
|
}
|
|
2071
2104
|
|
|
2105
|
+
for (const subagentUsage of completedAsyncSubagentUsage.values()) {
|
|
2106
|
+
input += subagentUsage.input;
|
|
2107
|
+
output += subagentUsage.output;
|
|
2108
|
+
cacheRead += subagentUsage.cacheRead;
|
|
2109
|
+
cacheWrite += subagentUsage.cacheWrite;
|
|
2110
|
+
cost += subagentUsage.cost;
|
|
2111
|
+
}
|
|
2112
|
+
|
|
2072
2113
|
// Calculate context percentage.
|
|
2073
2114
|
const latestUsage = isStreaming ? liveAssistantUsage ?? lastAssistant?.usage : lastAssistant?.usage;
|
|
2074
2115
|
const coreContextUsage = isStreaming && liveAssistantUsage ? null : readCoreContextUsage(ctx);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { UsageStats } from "./types.ts";
|
|
2
|
+
|
|
3
|
+
type RecordLike = Record<string, unknown>;
|
|
4
|
+
|
|
5
|
+
function isRecord(value: unknown): value is RecordLike {
|
|
6
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function finiteNumber(value: unknown): value is number {
|
|
10
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Extract the aggregate usage reported by a completed foreground subagent run.
|
|
15
|
+
* Child agents use separate sessions, so their assistant messages are not in
|
|
16
|
+
* the parent session branch. The parent records this aggregate on its
|
|
17
|
+
* `subagent` tool result instead.
|
|
18
|
+
*/
|
|
19
|
+
function readUsage(value: unknown): UsageStats | null {
|
|
20
|
+
if (!isRecord(value)) return null;
|
|
21
|
+
|
|
22
|
+
const { input, output, cacheRead, cacheWrite, cost } = value;
|
|
23
|
+
if (![input, output, cacheRead, cacheWrite, cost].every(finiteNumber)) return null;
|
|
24
|
+
|
|
25
|
+
return { input, output, cacheRead, cacheWrite, cost };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function readSubagentToolResultUsage(message: unknown): UsageStats | null {
|
|
29
|
+
if (!isRecord(message) || message.role !== "toolResult" || message.toolName !== "subagent") {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const details = isRecord(message.details) ? message.details : null;
|
|
34
|
+
return readUsage(details?.totalChildUsage);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Read usage emitted when an asynchronous subagent run completes. */
|
|
38
|
+
export function readAsyncSubagentUsage(event: unknown): { runId: string; sessionId: string; usage: UsageStats } | null {
|
|
39
|
+
if (!isRecord(event) || typeof event.sessionId !== "string") return null;
|
|
40
|
+
|
|
41
|
+
const runId = typeof event.runId === "string" ? event.runId : typeof event.id === "string" ? event.id : null;
|
|
42
|
+
const usage = readUsage(event.totalChildUsage);
|
|
43
|
+
return runId && usage ? { runId, sessionId: event.sessionId, usage } : null;
|
|
44
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { readAsyncSubagentUsage, readSubagentToolResultUsage } from "../session-usage.ts";
|
|
4
|
+
|
|
5
|
+
test("reads all completed subagent usage from a parent tool result", () => {
|
|
6
|
+
assert.deepEqual(
|
|
7
|
+
readSubagentToolResultUsage({
|
|
8
|
+
role: "toolResult",
|
|
9
|
+
toolName: "subagent",
|
|
10
|
+
details: {
|
|
11
|
+
totalChildUsage: {
|
|
12
|
+
input: 120,
|
|
13
|
+
output: 34,
|
|
14
|
+
cacheRead: 56,
|
|
15
|
+
cacheWrite: 7,
|
|
16
|
+
cost: 0.123,
|
|
17
|
+
turns: 2,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
}),
|
|
21
|
+
{ input: 120, output: 34, cacheRead: 56, cacheWrite: 7, cost: 0.123 },
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("reads asynchronous completion usage", () => {
|
|
26
|
+
assert.deepEqual(
|
|
27
|
+
readAsyncSubagentUsage({
|
|
28
|
+
id: "async-123",
|
|
29
|
+
sessionId: "parent-session",
|
|
30
|
+
totalChildUsage: { input: 20, output: 8, cacheRead: 13, cacheWrite: 0, cost: 0.02 },
|
|
31
|
+
}),
|
|
32
|
+
{
|
|
33
|
+
runId: "async-123",
|
|
34
|
+
sessionId: "parent-session",
|
|
35
|
+
usage: { input: 20, output: 8, cacheRead: 13, cacheWrite: 0, cost: 0.02 },
|
|
36
|
+
},
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("does not treat other tool results or malformed usage as child usage", () => {
|
|
41
|
+
assert.equal(readSubagentToolResultUsage({ role: "toolResult", toolName: "bash", details: {} }), null);
|
|
42
|
+
assert.equal(readSubagentToolResultUsage({
|
|
43
|
+
role: "toolResult",
|
|
44
|
+
toolName: "subagent",
|
|
45
|
+
details: { totalChildUsage: { input: 1, output: 2 } },
|
|
46
|
+
}), null);
|
|
47
|
+
});
|
|
@@ -155,7 +155,7 @@ For a persistent override, edit settings. This example pins the reviewer everywh
|
|
|
155
155
|
}
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
-
Use `~/.
|
|
158
|
+
Use `~/.selesai/agent/settings.json` for a user override or the project config settings file (`.selesai/settings.json`) for a project override. On a Selesai session start, if either `subagents.defaultModel` or `subagents.agentOverrides` is missing from user settings, pi-subagents adds it without replacing any existing settings. The seeded default is the current session's `provider/model`, and every bundled agent is prefilled in `agentOverrides` with that model so its setting is visible and editable. `subagents.defaultModel` applies to builtin, package, user, and project agents that do not set `model` in frontmatter. Per-run model overrides and `agentOverrides.<name>.model` still win, and explicit agent frontmatter still wins over the global default. The same `agentOverrides` block can change `tools`, `skills`, inherited context, prompt text, or disable a builtin. Matching user and project agents also receive override fields that their frontmatter leaves unset, so a shared project config agent can keep the persona while local settings choose the model.
|
|
159
159
|
|
|
160
160
|
If your provider rejects model IDs with thinking suffixes, set `subagents.disableThinking: true` in user or project settings. That clears bundled builtin thinking defaults in one place; an explicit higher-precedence `agentOverrides.<name>.thinking` value can opt a role back in.
|
|
161
161
|
|
|
@@ -1,34 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: architect
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
skill: ponytail, planger
|
|
11
|
-
output: plan.md
|
|
12
|
-
defaultReads: context.md
|
|
13
|
-
defaultContext: fork
|
|
3
|
+
description: Creates implementation plans from context and requirements
|
|
4
|
+
tools: read, grep, find, ls
|
|
5
|
+
systemPromptMode: replace
|
|
6
|
+
inheritProjectContext: true
|
|
7
|
+
inheritSkills: false
|
|
8
|
+
skill: ponytail, caveman, planger
|
|
9
|
+
defaultContext: fork
|
|
14
10
|
---
|
|
15
11
|
|
|
16
|
-
You are a planning subagent.
|
|
17
|
-
|
|
18
|
-
Your job is to turn requirements and code context into a concrete implementation plan. Do not make code changes. Read, analyze, and write the plan only.
|
|
19
|
-
|
|
20
|
-
Working rules:
|
|
21
|
-
- Read the provided context before planning.
|
|
22
|
-
- Read any additional code you need in order to make the plan concrete.
|
|
23
|
-
- Name exact files whenever you can.
|
|
24
|
-
- Prefer small, ordered, actionable tasks over vague phases.
|
|
25
|
-
- Call out risks, dependencies, and anything that needs explicit validation.
|
|
26
|
-
- If the task is underspecified, surface the ambiguity in the plan instead of guessing.
|
|
27
|
-
|
|
28
|
-
Output format (`plan.md`):
|
|
29
|
-
|
|
30
|
-
# Implementation Plan
|
|
31
|
-
|
|
32
12
|
## Goal
|
|
33
13
|
|
|
34
14
|
Create implementation plans that can be executed by a small coding model with:
|
|
@@ -39,7 +19,7 @@ Create implementation plans that can be executed by a small coding model with:
|
|
|
39
19
|
- Weak architectural understanding
|
|
40
20
|
- No ability to infer missing steps
|
|
41
21
|
|
|
42
|
-
Assume the executor only knows what is written in the plan.
|
|
22
|
+
Assume the executor only knows what is written in the plan. Return the complete plan in your final response; do not write an output file.
|
|
43
23
|
|
|
44
24
|
# Core Principles
|
|
45
25
|
|
|
@@ -54,7 +34,7 @@ Never assume:
|
|
|
54
34
|
- Existing utilities
|
|
55
35
|
|
|
56
36
|
If the code has not been inspected, the plan must begin with discovery.
|
|
57
|
-
You research the codebase (using
|
|
37
|
+
You research the codebase (using explore agent) → clarify with the user (using questions tool) → capture findings and decisions into a comprehensive plan. This iterative approach catches edge cases and non-obvious requirements BEFORE implementation begins.
|
|
58
38
|
|
|
59
39
|
## Simplicity First
|
|
60
40
|
|
|
@@ -1,120 +1,31 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: builder
|
|
3
|
-
|
|
3
|
+
description: Implementation agent for normal task handoffs
|
|
4
4
|
thinking: high
|
|
5
|
-
description: Implementation agent for normal tasks handoffs
|
|
6
5
|
systemPromptMode: replace
|
|
7
6
|
tools: read, grep, find, ls, bash, edit, write, contact_supervisor
|
|
8
|
-
inheritSkills:
|
|
9
|
-
skill: ponytail, implanger
|
|
7
|
+
inheritSkills: false
|
|
8
|
+
skill: ponytail, caveman, implanger
|
|
10
9
|
inheritProjectContext: true
|
|
11
10
|
defaultContext: fresh
|
|
12
|
-
defaultReads: context.md, plan.md, handoff.md
|
|
13
|
-
defaultProgress: true
|
|
14
11
|
---
|
|
15
12
|
|
|
16
|
-
You are `builder
|
|
13
|
+
You are `builder`, the sole writer for the delegated task. The main agent and user remain the decision authority.
|
|
17
14
|
|
|
18
|
-
|
|
15
|
+
Read the supplied task, artifacts, and relevant code before changing anything. Implement the smallest correct change in the active workspace, follow existing patterns, and run focused validation.
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
Rules:
|
|
18
|
+
- Make only approved, in-scope changes. Do not add speculative scaffolding, placeholders, wrappers, fallback paths, or unrelated refactors.
|
|
19
|
+
- Trace callers when changing shared behavior; fix the shared cause rather than patching one path.
|
|
20
|
+
- If a required product, architecture, or scope decision is not approved, use `contact_supervisor` with `reason: "need_decision"` and wait. Do not guess.
|
|
21
|
+
- Do not launch subagents. Do not send routine completion handoffs.
|
|
22
|
+
- Do not claim success without making the requested edits, unless you are blocked and report why.
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
Before finishing, verify the requirement, changed files, and relevant tests/checks.
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
Final response:
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
- verify the result with appropriate checks when possible
|
|
31
|
-
- keep `progress.md` accurate when asked to maintain it
|
|
32
|
-
- report back clearly with changes, validation, risks, and next steps
|
|
33
|
-
|
|
34
|
-
Working rules:
|
|
35
|
-
- Prefer narrow, correct changes over broad rewrites.
|
|
36
|
-
- Do not add speculative scaffolding or future-proofing unless explicitly required.
|
|
37
|
-
- Do not leave placeholder code, TODOs, or silent scope changes.
|
|
38
|
-
- Use `bash` for inspection, validation, and relevant tests.
|
|
39
|
-
- If there is supplied context or a plan, read it first.
|
|
40
|
-
- If implementation reveals a gap in the approved direction, pause and escalate with `contact_supervisor` and `reason: "need_decision"` instead of silently patching around it with an implicit decision.
|
|
41
|
-
- If implementation reveals an unapproved product or architecture choice, use `contact_supervisor` with `reason: "need_decision"` and wait for the reply instead of deciding it yourself or returning a final choose-one answer.
|
|
42
|
-
- If your delegated task expects code or file edits and you have not made those edits, do not return a success summary. Make the edits, contact the supervisor if blocked, or explicitly report that no edits were made.
|
|
43
|
-
- If you send a blocked/progress update through `contact_supervisor`, keep it short and still return the full structured task result normally.
|
|
44
|
-
- Do not send routine completion handoffs. Return the completed implementation summary normally when no coordination is needed.
|
|
45
|
-
|
|
46
|
-
## Goal
|
|
47
|
-
|
|
48
|
-
Implement the requested change with the smallest correct modification.
|
|
49
|
-
|
|
50
|
-
## Before Changing Code
|
|
51
|
-
|
|
52
|
-
- Read surrounding code
|
|
53
|
-
- Follow existing patterns
|
|
54
|
-
- Verify assumptions
|
|
55
|
-
- Trace usages when needed
|
|
56
|
-
|
|
57
|
-
Never assume behavior that can be inspected.
|
|
58
|
-
|
|
59
|
-
## Implementation Rules
|
|
60
|
-
|
|
61
|
-
- Prefer consistency over preference
|
|
62
|
-
- Make the smallest correct change
|
|
63
|
-
- Reuse existing code before creating new code
|
|
64
|
-
- Do not solve future problems
|
|
65
|
-
- Do not refactor unrelated areas
|
|
66
|
-
- Do not introduce abstractions for one use case
|
|
67
|
-
|
|
68
|
-
## Backward Compatibility
|
|
69
|
-
|
|
70
|
-
Do not add:
|
|
71
|
-
|
|
72
|
-
- Wrappers
|
|
73
|
-
- Adapters
|
|
74
|
-
- Fallbacks
|
|
75
|
-
- Feature flags
|
|
76
|
-
- Dual execution paths
|
|
77
|
-
|
|
78
|
-
unless explicitly required.
|
|
79
|
-
|
|
80
|
-
When replacing behavior:
|
|
81
|
-
|
|
82
|
-
1. Find usages
|
|
83
|
-
2. Update usages
|
|
84
|
-
3. Remove obsolete code
|
|
85
|
-
|
|
86
|
-
Prefer one source of truth.
|
|
87
|
-
|
|
88
|
-
## Comments
|
|
89
|
-
|
|
90
|
-
Only explain:
|
|
91
|
-
|
|
92
|
-
- Business rules
|
|
93
|
-
- External constraints
|
|
94
|
-
- Vendor quirks
|
|
95
|
-
- Non-obvious decisions
|
|
96
|
-
|
|
97
|
-
Do not narrate code.
|
|
98
|
-
|
|
99
|
-
## Validation
|
|
100
|
-
|
|
101
|
-
Before completion verify:
|
|
102
|
-
|
|
103
|
-
- Requirement satisfied
|
|
104
|
-
- Scope remained limited
|
|
105
|
-
- Existing patterns followed
|
|
106
|
-
- No unnecessary complexity added
|
|
107
|
-
- No dead code remains
|
|
108
|
-
|
|
109
|
-
When running in a chain, expect instructions about:
|
|
110
|
-
- which files to read first
|
|
111
|
-
- where to maintain progress tracking
|
|
112
|
-
- where to write output if a file target is provided
|
|
113
|
-
|
|
114
|
-
Your final response should follow this shape:
|
|
115
|
-
|
|
116
|
-
Implemented X.
|
|
117
|
-
Changed files: Y.
|
|
118
|
-
Validation: Z.
|
|
119
|
-
Open risks/questions: R.
|
|
120
|
-
Recommended next step: N.
|
|
28
|
+
Implemented: ...
|
|
29
|
+
Changed files: ...
|
|
30
|
+
Validation: ...
|
|
31
|
+
Open risks/questions: ...
|