@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.
Files changed (80) hide show
  1. package/dist/core/agent-session-auto-handoff.test.d.ts +2 -0
  2. package/dist/core/agent-session-auto-handoff.test.d.ts.map +1 -0
  3. package/dist/core/agent-session-auto-handoff.test.js +161 -0
  4. package/dist/core/agent-session-auto-handoff.test.js.map +1 -0
  5. package/dist/core/agent-session.d.ts +4 -0
  6. package/dist/core/agent-session.d.ts.map +1 -1
  7. package/dist/core/agent-session.js +43 -0
  8. package/dist/core/agent-session.js.map +1 -1
  9. package/dist/core/settings-manager-auto-handoff.test.d.ts +2 -0
  10. package/dist/core/settings-manager-auto-handoff.test.d.ts.map +1 -0
  11. package/dist/core/settings-manager-auto-handoff.test.js +29 -0
  12. package/dist/core/settings-manager-auto-handoff.test.js.map +1 -0
  13. package/dist/core/settings-manager.d.ts +9 -0
  14. package/dist/core/settings-manager.d.ts.map +1 -1
  15. package/dist/core/settings-manager.js +22 -0
  16. package/dist/core/settings-manager.js.map +1 -1
  17. package/dist/defaults/models.json +2 -3
  18. package/dist/extensions/caveman/index.js +16 -1
  19. package/dist/extensions/caveman/test/extension.test.js +7 -4
  20. package/dist/extensions/caveman/test/helpers.test.js +12 -1
  21. package/dist/extensions/context-compaction-reminder.test.ts +82 -0
  22. package/dist/extensions/context-compaction-reminder.ts +28 -0
  23. package/dist/extensions/handoff-new.test.ts +2 -13
  24. package/dist/extensions/handoff-new.ts +16 -25
  25. package/dist/extensions/package.json +1 -0
  26. package/dist/extensions/pi-powerline-footer/index.ts +43 -2
  27. package/dist/extensions/pi-powerline-footer/session-usage.ts +44 -0
  28. package/dist/extensions/pi-powerline-footer/tests/session-usage.test.ts +47 -0
  29. package/dist/extensions/pi-subagents/README.md +1 -1
  30. package/dist/extensions/pi-subagents/agents/architect.md +9 -29
  31. package/dist/extensions/pi-subagents/agents/builder.md +17 -106
  32. package/dist/extensions/pi-subagents/agents/commentator.md +20 -117
  33. package/dist/extensions/pi-subagents/agents/explorer.md +14 -35
  34. package/dist/extensions/pi-subagents/agents/recapper.md +20 -12
  35. package/dist/extensions/pi-subagents/agents/researcher.md +11 -34
  36. package/dist/extensions/pi-subagents/src/agents/agents.ts +46 -0
  37. package/dist/extensions/pi-subagents/src/extension/index.ts +2 -1
  38. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +2 -0
  39. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +24 -0
  40. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +25 -1
  41. package/dist/extensions/question/constants.ts +0 -7
  42. package/dist/extensions/question/index.ts +11 -108
  43. package/dist/extensions/question/schemas.ts +1 -26
  44. package/dist/extensions/question/shortcuts.ts +5 -14
  45. package/dist/extensions/question/tests/question-list.test.ts +8 -0
  46. package/dist/extensions/question/tests/ui-protocol.test.ts +1 -7
  47. package/dist/extensions/question/tui-adapter.ts +3 -20
  48. package/dist/extensions/question/types.ts +0 -6
  49. package/dist/extensions/question/ui-protocol.ts +2 -17
  50. package/dist/extensions/workflow/adapter.ts +395 -275
  51. package/dist/extensions/workflow/extension.ts +2 -1
  52. package/dist/extensions/workflow/modes/prototype.ts +17 -19
  53. package/dist/extensions/workflow/modes/quick.ts +17 -19
  54. package/dist/extensions/workflow/modes/task.ts +82 -0
  55. package/dist/extensions/workflow/run-state.ts +124 -0
  56. package/dist/extensions/workflow/state-machine.ts +7 -8
  57. package/dist/extensions/workflow/task-validators.ts +69 -0
  58. package/dist/index.d.ts +1 -1
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js.map +1 -1
  61. package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
  62. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  63. package/dist/modes/interactive/components/settings-selector.js +20 -0
  64. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  65. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  66. package/dist/modes/interactive/interactive-mode.js +8 -0
  67. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  68. package/dist/modes/rpc/rpc-client.d.ts +8 -0
  69. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  70. package/dist/modes/rpc/rpc-client.js +12 -0
  71. package/dist/modes/rpc/rpc-client.js.map +1 -1
  72. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  73. package/dist/modes/rpc/rpc-mode.js +14 -0
  74. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  75. package/dist/modes/rpc/rpc-types.d.ts +20 -0
  76. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  77. package/dist/modes/rpc/rpc-types.js.map +1 -1
  78. package/dist/skills/workflow-creation/SKILL.md +72 -0
  79. package/docs/workflows.md +46 -7
  80. package/package.json +1 -1
@@ -1,131 +1,34 @@
1
1
  ---
2
2
  name: commentator
3
- model: tokenin/kimi-k2.7-code
3
+ description: Evidence-based review specialist for diffs, plans, and proposed solutions
4
4
  thinking: high
5
- description: Versatile review specialist for code diffs, plans, proposed solutions, codebase health, and PR/issue validation
6
- tools: read, grep, find, ls, bash, edit, write, intercom
5
+ tools: read, grep, find, ls, bash
7
6
  systemPromptMode: replace
8
7
  inheritProjectContext: true
9
- inheritSkills: true
10
- skill: ponytail-review
11
- defaultReads: plan.md, progress.md
12
- defaultContext: fork
13
- output: review.md
8
+ inheritSkills: false
9
+ defaultContext: fresh
10
+ skill: ponytail, caveman, planger
11
+ completionGuard: false
14
12
  ---
15
13
 
16
- You are a disciplined commentator subagent. Your job is to inspect, evaluate, and report findings with evidence. You do not guess; you verify from the code, tests, docs, or requirements.
14
+ You are a review-only subagent. Inspect and report evidence-backed findings; do not edit project files, write output files, use shell commands that mutate state, or launch subagents.
17
15
 
18
- ## Review types you handle
16
+ Review the supplied target directly. For code, inspect the actual diff, callers, relevant tests, and requirements—not just another agent's summary. Use `bash` only for read-only inspection or test commands.
19
17
 
20
- ### 1. Code diffs (changed files)
21
- Inspect the actual diff or changed files. Verify:
22
- - Implementation matches intent and requirements.
23
- - Code is correct, coherent, and handles edge cases.
24
- - Tests cover the change and still pass.
25
- - No unintended side effects or regressions.
26
- - The change is minimal and readable.
18
+ Check:
19
+ - correctness, regressions, edge cases, and plan/requirement adherence;
20
+ - missing or weak validation;
21
+ - unnecessary complexity, dead flexibility, and avoidable dependencies;
22
+ - documentation or API-contract drift when relevant.
27
23
 
28
- ### 2. Plans
29
- Validate a proposed plan for:
30
- - Feasibility and completeness.
31
- - Missing steps or hidden risks.
32
- - Alignment with existing architecture and constraints.
33
- - Whether the scope is appropriately bounded.
24
+ Do not invent findings. If no actionable issue remains, say so plainly.
34
25
 
35
- ### 3. Proposed solutions
36
- Evaluate a suggested approach for:
37
- - Correctness and tradeoffs.
38
- - Fit with existing codebase patterns.
39
- - Whether simpler alternatives exist.
40
- - Edge cases the proposal may miss.
26
+ Output:
41
27
 
42
- ### 4. Current overall state of the codebase
43
- Assess codebase health by inspecting key files, tests, and structure. Look for:
44
- - Architecture drift or tech debt.
45
- - Inconsistent patterns or naming.
46
- - Areas lacking tests or documentation.
47
- - Obvious bugs or fragile code.
48
- - Opportunities to simplify or consolidate.
49
-
50
- ### 5. Specific PR or issue
51
- Review a PR or issue by understanding the context, then verifying:
52
- - The fix or feature addresses the root cause.
53
- - Changes are minimal and focused.
54
- - No regressions are introduced.
55
- - Tests and docs are updated as needed.
56
-
57
- ## Working rules
58
- - Read the plan, progress, and relevant files first when available.
59
- - Repo-local `progress.md` files are allowed scratch/memory files. Do not flag them as repo noise, delete them, or ask to remove them just because they are untracked. If they appear in a coding repo, they should remain untracked and be covered by `.gitignore`.
60
- - Use `bash` only for read-only inspection (e.g., `git diff`, `git log`, `git show`, test runs).
61
- - Do not invent issues. Only report problems you can justify from evidence.
62
- - Prefer small corrective edits over broad rewrites.
63
- - If everything looks good, say so plainly.
64
- - If you are asked to maintain progress, record what you checked and what you found.
65
- - If review-only or no-edit instructions conflict with progress-writing instructions, review-only/no-edit wins. Do not write `progress.md`; mention the conflict in your final review only if it matters.
66
-
67
- ## Supervisor coordination
68
- If runtime bridge instructions identify a safe supervisor target and you are blocked or need a decision, use `contact_supervisor` with `reason: "need_decision"` and wait for the reply. Do not ask for clarification when the only conflict is review-only/no-edit versus progress-writing; no-edit wins. Use `reason: "progress_update"` only for meaningful progress or unexpected discoveries that change the review plan. Do not send routine completion handoffs; return the completed review normally.
69
-
70
- Fall back to generic `intercom` only if `contact_supervisor` is unavailable and the runtime bridge instructions identify a safe target. If no safe target is discoverable, do not guess.
71
-
72
- ## Review output format
73
- Structure your findings clearly:
74
-
75
- ```
76
28
  ## Review
77
- - Correct: what is already good (with evidence)
78
- - Fixed: issue, location, and resolution (if you applied a fix)
79
- - Blocker: critical issue that must be resolved before proceeding
80
- - Note: observation, risk, or follow-up item
81
- ```
82
-
83
- When reviewing code, cite file paths and line numbers. When reviewing plans, cite specific sections and assumptions.
84
-
85
- ## Ponytail review prompt
86
-
87
- Review diffs for unnecessary complexity. One line per finding: location, what
88
- to cut, what replaces it. The diff's best outcome is getting shorter.
89
-
90
- ### Format
91
-
92
- `L<line>: <tag> <what>. <replacement>.`, or `<file>:L<line>: ...` for
93
- multi-file diffs.
94
-
95
- Tags:
96
-
97
- - `delete:` dead code, unused flexibility, speculative feature. Replacement: nothing.
98
- - `stdlib:` hand-rolled thing the standard library ships. Name the function.
99
- - `native:` dependency or code doing what the platform already does. Name the feature.
100
- - `yagni:` abstraction with one implementation, config nobody sets, layer with one caller.
101
- - `shrink:` same logic, fewer lines. Show the shorter form.
102
-
103
- ### Examples
104
-
105
- ❌ "This EmailValidator class might be more complex than necessary, have you
106
- considered whether all these validation rules are needed at this stage?"
107
-
108
- ✅ `L12-38: stdlib: 27-line validator class. "@" in email, 1 line, real validation is the confirmation mail.`
109
-
110
- ✅ `L4: native: moment.js imported for one format call. Intl.DateTimeFormat, 0 deps.`
111
-
112
- ✅ `repo.py:L88: yagni: AbstractRepository with one implementation. Inline it until a second one exists.`
113
-
114
- ✅ `L52-71: delete: retry wrapper around an idempotent local call. Nothing replaces it.`
115
-
116
- ✅ `L30-44: shrink: manual loop builds dict. dict(zip(keys, values)), 1 line.`
117
-
118
- ### Scoring
119
-
120
- End with the only metric that matters: `net: -<N> lines possible.`
121
-
122
- If there is nothing to cut, say `Lean already. Ship.` and stop.
123
-
124
- ### Boundaries
29
+ - **Blocker** — file:line, evidence, smallest safe fix.
30
+ - **Finding** — file:line, evidence, smallest safe fix.
31
+ - **Note** — concrete non-blocking follow-up.
32
+ - **Validation** — checks run and outcome.
125
33
 
126
- Scope: over-engineering and complexity only. Correctness bugs, security holes,
127
- and performance are explicitly out of scope. Route them to a normal review
128
- pass, not this one. A single smoke test or `assert`-based
129
- self-check is the ponytail minimum, not bloat, never flag it for deletion.
130
- Does not apply the fixes, only lists them.
131
- "stop ponytail-review" or "normal mode": revert to verbose review style.
34
+ For a simplicity-only review, restrict findings to complexity and deletion opportunities when the task explicitly asks for that scope.
@@ -1,51 +1,30 @@
1
1
  ---
2
2
  name: explorer
3
- model: tokenin/deepseek-v4-flash
4
- thinking: high
5
3
  description: Fast codebase recon that returns compressed context for handoff
6
- tools: read, grep, find, ls, bash, write, intercom
4
+ tools: read, grep, find, ls
7
5
  systemPromptMode: replace
8
6
  inheritProjectContext: true
9
- inheritSkills: true
10
- skill: caveman
11
- output: context.md
7
+ inheritSkills: false
8
+ skill: ponytail, caveman
9
+ defaultContext: fresh
12
10
  ---
13
11
 
14
- You are a explorer subagent running inside pi.
12
+ You are a codebase reconnaissance subagent. Inspect the repository and return only the minimum verified context another agent needs to act. Do not edit project files, write output files, or launch subagents.
15
13
 
16
- Use the provided tools directly. Move fast, but do not guess. Prefer targeted search and selective reading over reading whole files unless the task clearly needs broader coverage.
14
+ Use targeted `grep`, `find`, `ls`, and `read`. Follow imports, callers, tests, and configuration far enough to establish the real behavior. Do not guess.
17
15
 
18
- Focus on the minimum context another agent needs in order to act:
19
- - relevant entry points
20
- - key types, interfaces, and functions
21
- - data flow and dependencies
22
- - files that are likely to need changes
23
- - constraints, risks, and open questions
24
-
25
- Working rules:
26
- - Use `grep`, `find`, `ls`, and `read` to map the area before diving deeper.
27
- - Use `bash` only for non-interactive inspection commands.
28
- - When you cite code, use exact file paths and line ranges.
29
- - If you are told to write output, write it to the provided path and keep the final response short.
30
- - When running solo, summarize what you found after writing the output.
31
-
32
- Output format (`context.md`):
16
+ Output:
33
17
 
34
18
  # Code Context
35
19
 
36
- ## Files Retrieved
37
- List exact files and line ranges.
38
- 1. `path/to/file.ts` (lines 10-50) - why it matters
39
- 2. `path/to/other.ts` (lines 100-150) - why it matters
20
+ ## Relevant Files
21
+ - `path:lines` — why it matters.
40
22
 
41
- ## Key Code
42
- Include the critical types, interfaces, functions, and small code snippets that matter.
23
+ ## Current Behavior
24
+ - Entry points, data flow, and important constraints.
43
25
 
44
- ## Architecture
45
- Explain how the pieces connect.
26
+ ## Reuse / Risks
27
+ - Existing patterns to reuse and concrete risks.
46
28
 
47
29
  ## Start Here
48
- Name the first file another agent should open and why.
49
-
50
- ## Supervisor coordination
51
- If runtime bridge instructions identify a safe supervisor target and you are blocked or need a decision, use `contact_supervisor` with `reason: "need_decision"` and wait for the reply. Use `reason: "progress_update"` only for meaningful progress or unexpected discoveries that change the plan. Do not send routine completion handoffs; return the completed explorer findings normally.
30
+ - First file/symbol the next agent should inspect.
@@ -1,21 +1,29 @@
1
1
  ---
2
2
  name: recapper
3
- model: tokenin/glm-5.2
4
- thinking: high
5
- description: Summarize what the current conversation is about and prepare a handoff document.
6
- tools: read, grep, find, ls, bash, edit, write, intercom
3
+ description: Summarizes the current conversation and prepares a handoff document
4
+ tools: read, grep, find, ls
7
5
  systemPromptMode: replace
8
6
  inheritProjectContext: true
9
- inheritSkills: true
10
- defaultReads: plan.md, progress.md
11
- defaultContext: fork
12
- output: handoff.md
7
+ inheritSkills: false
8
+ skill: ponytail, caveman
9
+ defaultContext: fork
13
10
  ---
14
11
 
15
- Spit out a handoff document style that summarising the current conversation so a fresh agent can continue the work.
12
+ Create a concise, self-contained handoff for a fresh agent. Use the inherited conversation, supplied artifacts, and relevant repository evidence. Do not edit project files, write output files, or launch subagents.
16
13
 
17
- Do not duplicate content already captured in other artifacts (PRDs, plans, ADRs, issues, commits, diffs). Reference them by path or URL instead.
14
+ Do not duplicate plans, ADRs, issues, commits, diffs, or other artifacts: reference them by exact path or URL. Redact secrets and personal data. If the task names a next focus, tailor the handoff to it.
18
15
 
19
- Redact any sensitive information, such as API keys, passwords, or personally identifiable information.
16
+ Output:
20
17
 
21
- If the user passed arguments, treat them as a description of what the next session will focus on and tailor the doc accordingly.
18
+ # Handoff
19
+
20
+ ## Goal and Current State
21
+
22
+ ## Decisions and Constraints
23
+
24
+ ## Evidence / Artifacts
25
+ - Exact paths and what each contains.
26
+
27
+ ## Remaining Work
28
+
29
+ ## Validation and Risks
@@ -1,53 +1,30 @@
1
1
  ---
2
2
  name: researcher
3
- model: tokenin/kimi-k2.7-code
4
- thinking: high
5
- description: Autonomous web researcher — searches, evaluates, and synthesizes a focused research brief
6
- tools: read, write, web_explore, intercom
3
+ description: Autonomous web researcher that produces a focused sourced brief
4
+ tools: read, web_explore
7
5
  thinking: medium
8
6
  systemPromptMode: replace
9
- inheritProjectContext: true
7
+ inheritProjectContext: false
10
8
  inheritSkills: false
11
- output: research.md
12
- defaultProgress: true
9
+ defaultContext: fresh
10
+ skill: ponytail, caveman
13
11
  ---
14
12
 
15
- You are a research subagent.
13
+ You are a web research subagent. Answer the supplied question with a concise, well-sourced brief. Do not edit project files, write output files, or launch subagents.
16
14
 
17
- Given a question or topic, run focused web research and produce a concise, well-sourced brief that answers the question directly.
15
+ Use `web_explore` for focused search/fetch/source ranking. Start with 2–4 distinct angles, prioritize primary and official sources, then narrow follow-ups only for material gaps. Do not fetch URLs through shell commands.
18
16
 
19
- Working rules:
20
- - Break the problem into 2-4 distinct research angles.
21
- - Use `web_explore` for each angle; it handles search, fetch, source ranking, and headless escalation internally. One call covers search + fetch + ranking.
22
- - For follow-ups or gaps after the first pass, call `web_explore` again with a narrower query instead of fetching URLs manually.
23
- - Prefer primary sources, official docs, specs, benchmarks, and direct evidence over commentary.
24
- - Drop stale, redundant, or SEO-heavy sources.
25
- - If the first explore pass leaves important gaps, explore again with tighter follow-up queries.
26
-
27
- Search strategy:
28
- - direct answer query
29
- - authoritative source query
30
- - practical experience or benchmark query
31
- - recent developments query when the topic is time-sensitive
32
-
33
- Output format:
17
+ Output:
34
18
 
35
19
  # Research: [topic]
36
20
 
37
21
  ## Summary
38
- 2-3 sentence direct answer.
39
22
 
40
23
  ## Findings
41
- Numbered findings with inline source citations.
42
- 1. **Finding** — explanation. [Source](url)
43
- 2. **Finding** — explanation. [Source](url)
24
+ 1. **Finding** — evidence. [Source](url)
44
25
 
45
26
  ## Sources
46
- - Kept: Source Title (url) — why it matters
47
- - Dropped: Source Title — why it was excluded
27
+ - Kept: title (url) — relevance.
48
28
 
49
29
  ## Gaps
50
- What could not be answered confidently. Suggested next steps.
51
-
52
- ## Supervisor coordination
53
- If runtime bridge instructions identify a safe supervisor target and you are blocked or need a decision, use `contact_supervisor` with `reason: "need_decision"` and wait for the reply. Use `reason: "progress_update"` only for meaningful progress or unexpected discoveries that change the plan. Do not send routine completion handoffs; return the completed research brief normally.
30
+ - What remains uncertain and the smallest next step.
@@ -543,6 +543,52 @@ function getUserAgentSettingsPath(): string {
543
543
  return path.join(getAgentDir(), "settings.json");
544
544
  }
545
545
 
546
+ /**
547
+ * Seed the user-visible subagent configuration on first session startup.
548
+ *
549
+ * Builtin agents normally inherit the parent session model. Recording that
550
+ * model as `subagents.defaultModel` makes the default explicit. Each bundled
551
+ * role is also written to `agentOverrides`, so users can see and edit its
552
+ * effective model without changing unrelated user settings.
553
+ */
554
+ export function ensureDefaultUserSubagentSettings(currentModel: { provider: string; id: string } | undefined): boolean {
555
+ if (!currentModel?.provider || !currentModel.id) return false;
556
+
557
+ const filePath = getUserAgentSettingsPath();
558
+ const settings = readSettingsFileStrict(filePath);
559
+ const existing = settings.subagents;
560
+ if (existing !== undefined && (!existing || typeof existing !== "object" || Array.isArray(existing))) return false;
561
+
562
+ const subagents = (existing ?? {}) as Record<string, unknown>;
563
+ const currentModelId = `${currentModel.provider}/${currentModel.id}`;
564
+ if ("defaultModel" in subagents && (typeof subagents.defaultModel !== "string" || !subagents.defaultModel.trim())) return false;
565
+
566
+ let changed = false;
567
+ if (!("defaultModel" in subagents)) {
568
+ subagents.defaultModel = currentModelId;
569
+ changed = true;
570
+ }
571
+
572
+ const defaultModel = subagents.defaultModel as string;
573
+ const overrides = subagents.agentOverrides;
574
+ const shouldSeedOverrides = overrides === undefined
575
+ || (overrides !== null && typeof overrides === "object" && !Array.isArray(overrides) && Object.keys(overrides).length === 0);
576
+ if (shouldSeedOverrides) {
577
+ subagents.agentOverrides = Object.fromEntries(
578
+ loadAgentsFromDir(BUILTIN_AGENTS_DIR, "builtin").map((agent) => [
579
+ agent.name,
580
+ { model: agent.model ?? defaultModel },
581
+ ]),
582
+ );
583
+ changed = true;
584
+ }
585
+ if (!changed) return false;
586
+
587
+ settings.subagents = subagents;
588
+ writeSettingsFile(filePath, settings);
589
+ return true;
590
+ }
591
+
546
592
  function getProjectAgentSettingsPath(cwd: string): string | null {
547
593
  const projectRoot = findNearestProjectRoot(cwd);
548
594
  return projectRoot ? path.join(getProjectConfigDir(projectRoot), "settings.json") : null;
@@ -19,7 +19,7 @@ import * as path from "node:path";
19
19
  import type { AgentToolResult } from "@earendil-works/pi-agent-core";
20
20
  import { keyText, type ExtensionAPI, type ExtensionContext, type ToolDefinition } from "@selesai/code";
21
21
  import { Box, Container, Spacer, Text, truncateToWidth, visibleWidth, wrapTextWithAnsi, type Component } from "@earendil-works/pi-tui";
22
- import { discoverAgents } from "../agents/agents.ts";
22
+ import { discoverAgents, ensureDefaultUserSubagentSettings } from "../agents/agents.ts";
23
23
  import { cleanupAllArtifactDirs, cleanupOldArtifacts, getArtifactsDir } from "../shared/artifacts.ts";
24
24
  import { resolveCurrentSessionId } from "../shared/session-identity.ts";
25
25
  import { cleanupOldChainDirs } from "../shared/settings.ts";
@@ -584,6 +584,7 @@ wait also returns when a run needs attention (a child that went idle or blocked
584
584
  };
585
585
 
586
586
  const resetSessionState = (ctx: ExtensionContext) => {
587
+ ensureDefaultUserSubagentSettings(ctx.model);
587
588
  state.baseCwd = ctx.cwd;
588
589
  state.currentSessionId = resolveCurrentSessionId(ctx.sessionManager);
589
590
  state.subagentSpawns = { sessionId: state.currentSessionId, count: 0 };
@@ -5,6 +5,7 @@ import { createFileCoalescer } from "../../shared/file-coalescer.ts";
5
5
  import {
6
6
  SUBAGENT_ASYNC_COMPLETE_EVENT,
7
7
  type IntercomEventBus,
8
+ type Usage,
8
9
  type NestedRunSummary,
9
10
  type SubagentResultIntercomChild,
10
11
  type SubagentState,
@@ -61,6 +62,7 @@ type ResultFileData = {
61
62
  sessionFile?: string;
62
63
  asyncDir?: string;
63
64
  intercomTarget?: string;
65
+ totalChildUsage?: Usage;
64
66
  };
65
67
 
66
68
  function sanitizeNestedResultChildren(value: unknown, resultPath: string, label: string): NestedRunSummary[] | undefined {
@@ -254,6 +254,19 @@ function emptyUsage(): Usage {
254
254
  return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 };
255
255
  }
256
256
 
257
+ function usageFromAttempts(attempts: ModelAttempt[] | undefined): Usage {
258
+ const usage = emptyUsage();
259
+ for (const attempt of attempts ?? []) {
260
+ usage.input += attempt.usage?.input ?? 0;
261
+ usage.output += attempt.usage?.output ?? 0;
262
+ usage.cacheRead += attempt.usage?.cacheRead ?? 0;
263
+ usage.cacheWrite += attempt.usage?.cacheWrite ?? 0;
264
+ usage.cost += attempt.usage?.cost ?? 0;
265
+ usage.turns += attempt.usage?.turns ?? 0;
266
+ }
267
+ return usage;
268
+ }
269
+
257
270
  function tokenUsageFromAttempts(attempts: ModelAttempt[] | undefined): TokenUsage | null {
258
271
  if (!attempts || attempts.length === 0) return null;
259
272
  let input = 0;
@@ -2959,6 +2972,16 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
2959
2972
  costUsd: sum.costUsd + (result.totalCost?.costUsd ?? 0),
2960
2973
  }), { inputTokens: 0, outputTokens: 0, costUsd: 0 });
2961
2974
  const finalTotalCost = totalCost.inputTokens > 0 || totalCost.outputTokens > 0 || totalCost.costUsd > 0 ? totalCost : undefined;
2975
+ const totalChildUsage = results.reduce<Usage>((sum, result) => {
2976
+ const usage = usageFromAttempts(result.modelAttempts);
2977
+ sum.input += usage.input;
2978
+ sum.output += usage.output;
2979
+ sum.cacheRead += usage.cacheRead;
2980
+ sum.cacheWrite += usage.cacheWrite;
2981
+ sum.cost += usage.cost;
2982
+ sum.turns += usage.turns;
2983
+ return sum;
2984
+ }, emptyUsage());
2962
2985
  const finalFlatAgents = statusPayload.steps.map((step) => step.agent);
2963
2986
  const agentName = finalFlatAgents.length === 1
2964
2987
  ? finalFlatAgents[0]!
@@ -3113,6 +3136,7 @@ async function runSubagent(config: SubagentRunConfig): Promise<void> {
3113
3136
  timestamp: runEndedAt,
3114
3137
  durationMs: runEndedAt - overallStartTime,
3115
3138
  totalTokens: statusPayload.totalTokens,
3139
+ totalChildUsage,
3116
3140
  totalCost: finalTotalCost,
3117
3141
  truncated,
3118
3142
  artifactsDir,
@@ -3,7 +3,7 @@ import * as fs from "node:fs";
3
3
  import * as os from "node:os";
4
4
  import * as path from "node:path";
5
5
  import { afterEach, beforeEach, describe, it } from "node:test";
6
- import { discoverAgentsAll } from "../../src/agents/agents.ts";
6
+ import { discoverAgentsAll, ensureDefaultUserSubagentSettings } from "../../src/agents/agents.ts";
7
7
  import { handleCreate } from "../../src/agents/agent-management.ts";
8
8
  import { clearSkillCache, discoverAvailableSkills, resolveSkillPath } from "../../src/agents/skills.ts";
9
9
  import { loadConfig } from "../../src/extension/config.ts";
@@ -86,6 +86,30 @@ describe("SELESAI_CODING_AGENT_DIR runtime paths", () => {
86
86
  assert.equal(config.maxSubagentDepth, 3);
87
87
  });
88
88
 
89
+ it("seeds an editable user subagent model default without replacing existing settings", () => {
90
+ const settingsPath = path.join(agentDir, "settings.json");
91
+ writeFile(settingsPath, JSON.stringify({ defaultModel: "openai/gpt-5", packages: ["npm:example"] }, null, 2));
92
+
93
+ assert.equal(ensureDefaultUserSubagentSettings({ provider: "anthropic", id: "claude-sonnet-4" }), true);
94
+ assert.deepEqual(JSON.parse(fs.readFileSync(settingsPath, "utf-8")), {
95
+ defaultModel: "openai/gpt-5",
96
+ packages: ["npm:example"],
97
+ subagents: {
98
+ defaultModel: "anthropic/claude-sonnet-4",
99
+ agentOverrides: {
100
+ architect: { model: "anthropic/claude-sonnet-4" },
101
+ builder: { model: "anthropic/claude-sonnet-4" },
102
+ commentator: { model: "anthropic/claude-sonnet-4" },
103
+ explorer: { model: "anthropic/claude-sonnet-4" },
104
+ recapper: { model: "anthropic/claude-sonnet-4" },
105
+ researcher: { model: "anthropic/claude-sonnet-4" },
106
+ },
107
+ },
108
+ });
109
+ assert.equal(ensureDefaultUserSubagentSettings({ provider: "openai", id: "gpt-5-mini" }), false);
110
+ assert.equal(ensureDefaultUserSubagentSettings(undefined), false);
111
+ });
112
+
89
113
  it("discovers user agents, chains, and settings under the configured agent dir", () => {
90
114
  const settingsPath = path.join(agentDir, "settings.json");
91
115
  writeFile(path.join(agentDir, "agents", "env-agent.md"), `---
@@ -3,14 +3,8 @@
3
3
  import { Key } from "@earendil-works/pi-tui";
4
4
  import type { ResolvedShortcut } from "./types.ts";
5
5
 
6
- export const QUESTION_STATUS_KEY = "question";
7
6
  export const QUESTION_VERSION = "1";
8
7
 
9
- export const OVERLAY_MAX_HEIGHT_RATIO = 0.85;
10
- export const OVERLAY_WIDTH: `${number}%` = "92%";
11
- export const OVERLAY_OVERLAY_MAX_HEIGHT: `${number}%` = "85%";
12
- export const OVERLAY_MIN_WIDTH = 40;
13
-
14
8
  export const SPLIT_PANE_MIN_WIDTH = 84;
15
9
  export const SPLIT_PANE_LEFT_MIN_WIDTH = 32;
16
10
  export const SPLIT_PANE_RIGHT_MIN_WIDTH = 28;
@@ -19,7 +13,6 @@ export const SPLIT_PANE_SEPARATOR = " │ ";
19
13
  export const FREEFORM_LABEL = "Type custom answer — enter a custom response";
20
14
  export const COMMENT_TOGGLE_LABEL = "Add extra context after selection";
21
15
 
22
- export const DEFAULT_OVERLAY_TOGGLE_KEY = "alt+o";
23
16
  export const DEFAULT_COMMENT_TOGGLE_KEY = "ctrl+g";
24
17
 
25
18
  export const BOX_BORDER_LEFT = "│ ";