@selesai/code 0.5.13 → 0.5.14
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/README.md +186 -0
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/extensions/package.json +4 -3
- package/dist/extensions/pi-powerline-footer/README.md +1 -1
- package/dist/extensions/pi-powerline-footer/guide.ts +227 -0
- package/dist/extensions/pi-powerline-footer/index.ts +88 -55
- package/dist/extensions/pi-powerline-footer/tests/editor-responsiveness.test.ts +0 -78
- package/dist/extensions/pi-powerline-footer/tests/guide.test.ts +102 -0
- package/dist/extensions/pi-powerline-footer/welcome.ts +65 -30
- package/dist/skills/caveman/SKILL.md +1 -0
- package/dist/skills/handoff/SKILL.md +1 -0
- package/dist/skills/handoff-text/SKILL.md +1 -0
- package/dist/skills/implanger/SKILL.md +1 -0
- package/dist/skills/improve-codebase/SKILL.md +1 -0
- package/dist/skills/planger/SKILL.md +1 -0
- package/dist/skills/ponytail/SKILL.md +1 -0
- package/dist/skills/ponytail-audit/SKILL.md +1 -0
- package/dist/skills/ponytail-debt/SKILL.md +1 -0
- package/dist/skills/ponytail-gain/SKILL.md +1 -0
- package/dist/skills/ponytail-help/SKILL.md +1 -0
- package/dist/skills/ponytail-review/SKILL.md +1 -0
- package/dist/skills/workflow-creation/SKILL.md +1 -0
- package/package.json +23 -2
- package/dist/agents/architect.md +0 -217
- package/dist/agents/builder.md +0 -120
- package/dist/agents/commentator.md +0 -130
- package/dist/agents/explorer.md +0 -51
- package/dist/agents/recapper.md +0 -26
- package/dist/extensions/gitignore-guard.ts +0 -132
- package/dist/extensions/hooks/claude-codex-hooks.json +0 -44
- package/dist/extensions/hooks/copilot-hooks.json +0 -21
- package/dist/extensions/hooks/ponytail-activate.js +0 -91
- package/dist/extensions/hooks/ponytail-config.js +0 -122
- package/dist/extensions/hooks/ponytail-instructions.js +0 -94
- package/dist/extensions/hooks/ponytail-mode-tracker.js +0 -55
- package/dist/extensions/hooks/ponytail-runtime.js +0 -68
- package/dist/extensions/hooks/ponytail-statusline.ps1 +0 -21
- package/dist/extensions/hooks/ponytail-statusline.sh +0 -12
- package/dist/extensions/hooks/ponytail-subagent.js +0 -22
- package/dist/extensions/pi-extension/index.js +0 -189
- package/dist/extensions/pi-extension/package.json +0 -8
- package/dist/extensions/pi-extension/test/extension.test.js +0 -167
- package/dist/extensions/pi-extension/test/helpers.test.js +0 -92
- package/dist/extensions/pi-powerline-footer/welcome-dismiss.ts +0 -34
- package/dist/extensions/pi-subagents/agents/context-builder.md +0 -46
- package/dist/extensions/pi-subagents/agents/delegate.md +0 -12
- package/dist/extensions/pi-subagents/agents/oracle.md +0 -73
- package/dist/extensions/pi-subagents/agents/planner.md +0 -55
- package/dist/extensions/pi-subagents/agents/reviewer.md +0 -79
- package/dist/extensions/pi-subagents/agents/scout.md +0 -50
- package/dist/extensions/pi-subagents/agents/worker.md +0 -55
- package/dist/extensions/pi-subagents/src/runs/shared/spawn-timing.ts +0 -46
- package/dist/extensions/pi-subagents/test/unit/spawn-timing.test.ts +0 -45
- package/dist/extensions/pi-subagents/tsconfig.runner.json +0 -17
- package/dist/extensions/ponytail-pi-extension/index.js +0 -189
- package/dist/extensions/ponytail-pi-extension/package.json +0 -8
- package/dist/extensions/ponytail-pi-extension/test/extension.test.js +0 -167
- package/dist/extensions/ponytail-pi-extension/test/helpers.test.js +0 -92
- package/dist/extensions/prototype.ts +0 -713
- package/dist/extensions/question.ts +0 -350
- package/dist/extensions/quick.ts +0 -630
- package/dist/extensions/tps-tracker.ts +0 -280
- package/dist/extensions/workflow/task-validators.ts +0 -69
- package/dist/skills/selesai-default/SKILL.md +0 -16
package/README.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Selesai
|
|
2
|
+
|
|
3
|
+
Selesai is a maintained, extension-first fork of the [Pi coding agent](https://github.com/earendil-works/pi). It keeps Pi's small, hackable coding harness and ships a coordinated set of extensions, skills, and display improvements as part of the application.
|
|
4
|
+
|
|
5
|
+
The goal is simple: make a capable coding agent useful out of the box, maximize token utilization, and get better or comparable results with fewer tokens and lower cost—without making every user install and trust a long list of unrelated extensions.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g --ignore-scripts @selesai/code
|
|
11
|
+
selesai
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
For a one-off run using the latest published package:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npx @selesai/code
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The published npm package is **`@selesai/code`** and its executable is **`selesai`**. Selesai uses `~/.selesai/agent` for user state and `.selesai/` for project-local settings and resources.
|
|
21
|
+
|
|
22
|
+
Start with a prompt:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
selesai "Explain this repository and tell me how to run its checks"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or run a non-interactive request:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
selesai -p "Review the current git diff without editing files"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## What Selesai adds to Pi
|
|
35
|
+
|
|
36
|
+
### Built-in delegation and orchestration
|
|
37
|
+
|
|
38
|
+
`pi-subagents` is bundled and adapted to the Selesai runtime. It provides:
|
|
39
|
+
|
|
40
|
+
- in-tree focused agent roles: `architect`, `builder`, `commentator`, `explorer`, `recapper`, and `researcher`
|
|
41
|
+
- extensible user, project, and package agent definitions with model/tool/skill controls
|
|
42
|
+
- foreground, background, parallel, and chained runs
|
|
43
|
+
- async status, transcripts, lifecycle artifacts, scheduling, interruption, steering, and resuming
|
|
44
|
+
- structured output, output files, tool/turn budgets, model overrides, fallbacks, and model scopes
|
|
45
|
+
- worktree isolation for parallel implementation tasks
|
|
46
|
+
- native supervisor communication, so a delegated agent can ask the main session for a decision instead of guessing
|
|
47
|
+
- reusable prompt workflows and agent management commands
|
|
48
|
+
|
|
49
|
+
Useful prompts:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
Ask the architect to challenge this plan before we implement it.
|
|
53
|
+
Run parallel commentator agents for correctness, tests, and unnecessary complexity.
|
|
54
|
+
Have the builder implement this plan, then review the result.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Durable workflows
|
|
58
|
+
|
|
59
|
+
Selesai includes a workflow engine with three modes:
|
|
60
|
+
|
|
61
|
+
| Mode | Flow | Best for |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| `prototype` | grill → research → plan → reuse → handoff → build/review loop → audit | New prototypes that need discovery and external research |
|
|
64
|
+
| `quick` | grill → plan → reuse → handoff → build/review loop → audit | Smaller prototypes with less ceremony |
|
|
65
|
+
| `task` | plan → reuse → handoff → build/review loop | Direct implementation work |
|
|
66
|
+
|
|
67
|
+
Workflows persist their state and phase artifacts on disk, can be resumed explicitly, and require an explicit close step. Use `/workflow-prototype`, `/workflow-quick`, or `/workflow-task`, or ask Selesai to start the appropriate workflow.
|
|
68
|
+
|
|
69
|
+
### Web research
|
|
70
|
+
|
|
71
|
+
The bundled web-agent provides one high-level `web_explore` tool for research that needs current sources. It handles bounded search and fetch passes, source ranking, readable extraction, and targeted headless-browser escalation. It is intended for current documentation, technical discussions, comparisons, and recommendations—not for silently making arbitrary network calls from shell commands.
|
|
72
|
+
|
|
73
|
+
DuckDuckGo works as the default search path. Optional first-run onboarding can configure Brave Search with DuckDuckGo fallback. To register for Brave Search API access, visit the [Brave Search API page](https://brave.com/search/api/) and then create a key in the [Brave API dashboard](https://api-dashboard.search.brave.com/app/keys). `/web-agent` exposes backend and presentation settings plus diagnostics.
|
|
74
|
+
|
|
75
|
+
### Interactive questions
|
|
76
|
+
|
|
77
|
+
The bundled `question` tool gives the agent a real TUI for decisions instead of forcing every clarification through plain text. It supports:
|
|
78
|
+
|
|
79
|
+
- single- and multi-select options
|
|
80
|
+
- descriptions and context summaries
|
|
81
|
+
- freeform answers and optional comments
|
|
82
|
+
- keyboard navigation, filtering, cancellation, and image/info question types
|
|
83
|
+
|
|
84
|
+
This is the interaction layer used by the workflow modes and available to normal agent requests too.
|
|
85
|
+
|
|
86
|
+
### A richer terminal workspace
|
|
87
|
+
|
|
88
|
+
The bundled `pi-powerline-footer` improves the interactive display with:
|
|
89
|
+
|
|
90
|
+
- a powerline status bar for model, thinking level, path, git state, context, tokens, cost, cache, and session data
|
|
91
|
+
- a fixed-editor layout that keeps the editor and status area visible while chat scrolls
|
|
92
|
+
- a recurring `/guide` tour with compact and remembered-dismissal modes, covering workflows, delegation/research prompts, skills, handoff, and recovery
|
|
93
|
+
- persistent bash mode with shell state, transcript output, history, and ghost suggestions
|
|
94
|
+
- editor stash/restore, prompt history, clipboard shortcuts, and message-jump shortcuts
|
|
95
|
+
- themed working-vibe messages, Nerd Font detection, and configurable presets
|
|
96
|
+
|
|
97
|
+
### Coordination between sessions
|
|
98
|
+
|
|
99
|
+
`pi-intercom` is an agent tool for local 1:1 session coordination, not a skill or part of the quick guide. Ask Selesai to use it when another local session should review an idea, receive progress, or answer a question. Agents can `send`, `ask`, `reply`, inspect pending messages, and share attachments; delegated agents can use the native supervisor channel to request decisions or report meaningful progress.
|
|
100
|
+
|
|
101
|
+
Give sessions clear names so humans and delegated agents can find the right conversation:
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
/name CalculatorProject
|
|
105
|
+
/name DiscussionMaster
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
For example, run two sessions in the same folder with different models. Ask `DiscussionMaster` to critique an implementation idea, challenge its assumptions, and suggest improvements before you commit to it.
|
|
109
|
+
|
|
110
|
+
### Recovery and continuity
|
|
111
|
+
|
|
112
|
+
Selesai also bundles small extensions that solve common coding-agent failures:
|
|
113
|
+
|
|
114
|
+
- **Rewind** — exact git-backed file checkpoints across `/fork`, `/tree`, resumed sessions, and session lineage
|
|
115
|
+
- **Undo** — turn-level undo for tracked edits, writes, and detected mutating shell commands (`/undo`)
|
|
116
|
+
- **Handoff** — `/handoff-new` creates an editable continuation prompt in a clean session. Keeping context small improves result quality and reduces token consumption and cost
|
|
117
|
+
- **Context reminder** — warns when a conversation grows large and suggests a handoff before quality degrades
|
|
118
|
+
- **Copy turn** — copy a user or assistant result by hash with `/cp <hash>`
|
|
119
|
+
- **grep.app** — search public GitHub code and fetch the matching source without leaving the agent
|
|
120
|
+
- **RTK integration** — if `rtk` is installed, compatible shell commands can be rewritten to reduce noisy command output and token use
|
|
121
|
+
|
|
122
|
+
### Built-in skills
|
|
123
|
+
|
|
124
|
+
Skills are shipped with Selesai and loaded at boot. They include:
|
|
125
|
+
|
|
126
|
+
- `ponytail` and `caveman` for minimal and compressed communication modes
|
|
127
|
+
- `grill-me` for requirement and design stress-testing
|
|
128
|
+
- `planger` and `implanger` for decomposed planning and execution
|
|
129
|
+
- `handoff` and `handoff-text` for session continuity
|
|
130
|
+
- `improve-codebase` for architecture and maintainability reviews
|
|
131
|
+
- `ponytail-review`, `ponytail-audit`, `ponytail-gain`, `ponytail-debt`, and `ponytail-help`
|
|
132
|
+
- `workflow-creation` for building durable workflow modes
|
|
133
|
+
|
|
134
|
+
Invoke one with `/skill:<name>`.
|
|
135
|
+
|
|
136
|
+
## Why the extensions are bundled
|
|
137
|
+
|
|
138
|
+
Pi has a broad extension ecosystem, but installing many separate packages also means tracking their maintenance, compatibility, and supply-chain boundaries. Selesai carries the extensions that define its experience in `src/extensions/`, adapts them to the Selesai host, tests them with the application, and ships them with each release.
|
|
139
|
+
|
|
140
|
+
Selesai is a fork project, not a loose collection of upstream Pi plugins. Some in-tree components began as separate projects or forked code, but Selesai adapts, tests, versions, and maintains them as part of this repository. Keeping them in-tree makes the source visible, reviewable, and auditable in one place, and avoids requiring a fresh external extension install for core Selesai features.
|
|
141
|
+
|
|
142
|
+
This reduces extension supply-chain exposure; it does not eliminate risk. Selesai still has runtime dependencies, and users should review dependency and extension changes like any other code.
|
|
143
|
+
|
|
144
|
+
## Pi-compatible core
|
|
145
|
+
|
|
146
|
+
Selesai retains Pi's useful base capabilities:
|
|
147
|
+
|
|
148
|
+
- terminal-first interactive coding with `read`, `bash`, `edit`, `write`, `grep`, `find`, and `ls`
|
|
149
|
+
- multiple model providers, API keys, OAuth, thinking levels, images, and retries
|
|
150
|
+
- persistent sessions with resume, fork, tree navigation, compaction, and export
|
|
151
|
+
- print, JSON event-stream, and RPC modes
|
|
152
|
+
- TypeScript extensions, skills, prompt templates, themes, packages, and an embeddable Node.js SDK
|
|
153
|
+
- project trust and configurable resource loading
|
|
154
|
+
|
|
155
|
+
See [`docs/`](docs/) for the Pi-compatible CLI, extension, SDK, settings, and session references. The Selesai-specific behavior and bundled resources are documented here and in `src/extensions/`.
|
|
156
|
+
|
|
157
|
+
## Repository map
|
|
158
|
+
|
|
159
|
+
```text
|
|
160
|
+
src/
|
|
161
|
+
core/ agent runtime, sessions, tools, packages, and extension loading
|
|
162
|
+
modes/ interactive TUI, print, JSON, and RPC modes
|
|
163
|
+
extensions/ Selesai's bundled extensions and their tests
|
|
164
|
+
skills/ Selesai's bundled skills
|
|
165
|
+
themes/ bundled terminal themes
|
|
166
|
+
defaults/ first-run defaults
|
|
167
|
+
|
|
168
|
+
docs/ CLI and SDK documentation
|
|
169
|
+
examples/ extension and SDK examples
|
|
170
|
+
test/ core tests
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Development
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
npm install
|
|
177
|
+
npm run build
|
|
178
|
+
node dist/cli.js --help
|
|
179
|
+
node dist/cli.js --version
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Changes to bundled extensions belong in `src/extensions/`; the build copies them into `dist/extensions/` for the published package.
|
|
183
|
+
|
|
184
|
+
## Contributing
|
|
185
|
+
|
|
186
|
+
Selesai is maintained in this repository. When changing a bundled extension, keep its host integration, config paths, tests, and user-facing documentation aligned. Prefer the existing Selesai runtime and installed dependencies before adding another package.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAyB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAyB,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,wBAAwB;IACxC,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,uCAAuC;IACvC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,gCAAgC;IAChC,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,yBAAyB;IACzB,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,oCAAoC;IACpC,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC;CACxB;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,MAAM,CAwJ3E","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.ts\";\nimport { formatAgentsForPrompt, type AgentPersona } from \"./agents.ts\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.ts\";\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n\t/** Pre-loaded subagent personas. */\n\tagents?: AgentPersona[];\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t} = options;\n\tconst resolvedCwd = cwd;\n\tconst promptCwd = resolvedCwd.replace(/\\\\/g, \"/\");\n\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = String(now.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(now.getDate()).padStart(2, \"0\");\n\tconst date = `${year}-${month}-${day}`;\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\tconst agents = options.agents ?? [];\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `<project_instructions path=\"${filePath}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t\t}\n\t\t\tprompt += \"</project_context>\\n\";\n\t\t}\n\n\t\t// Append skills section (only if read tool is available)\n\t\tconst customPromptHasRead = !selectedTools || selectedTools.includes(\"read\");\n\t\tif (customPromptHasRead && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\t\tif (customPromptHasRead && agents.length > 0) {\n\t\t\tprompt += formatAgentsForPrompt(agents);\n\t\t}\n\n\t\t// Add date and working directory last\n\t\tprompt += `\\nCurrent date: ${date}`;\n\t\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation and examples\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\n\t// Build tools list based on selected tools.\n\t// A tool appears in Available tools only when the caller provides a one-line snippet.\n\tconst tools = selectedTools || [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst visibleTools = tools.filter((name) => !!toolSnippets?.[name]);\n\tconst toolsList =\n\t\tvisibleTools.length > 0 ? visibleTools.map((name) => `- ${name}: ${toolSnippets![name]}`).join(\"\\n\") : \"(none)\";\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\tconst addGuideline = (guideline: string): void => {\n\t\tif (guidelinesSet.has(guideline)) {\n\t\t\treturn;\n\t\t}\n\t\tguidelinesSet.add(guideline);\n\t\tguidelinesList.push(guideline);\n\t};\n\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst hasRead = tools.includes(\"read\");\n\n\t// File exploration guidelines\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\taddGuideline(\"Use bash for file operations like ls, rg, find\");\n\t}\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) {\n\t\t\taddGuideline(normalized);\n\t\t}\n\t}\n\n\t// Always include these\n\taddGuideline(\"Be concise in your responses\");\n\taddGuideline(\"Show file paths clearly when working with files\");\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tlet prompt = `You are an expert coding assistant operating inside
|
|
1
|
+
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAyB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAyB,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,wBAAwB;IACxC,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,uCAAuC;IACvC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,gCAAgC;IAChC,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,yBAAyB;IACzB,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,oCAAoC;IACpC,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC;CACxB;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,MAAM,CAwJ3E","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.ts\";\nimport { formatAgentsForPrompt, type AgentPersona } from \"./agents.ts\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.ts\";\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n\t/** Pre-loaded subagent personas. */\n\tagents?: AgentPersona[];\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t} = options;\n\tconst resolvedCwd = cwd;\n\tconst promptCwd = resolvedCwd.replace(/\\\\/g, \"/\");\n\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = String(now.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(now.getDate()).padStart(2, \"0\");\n\tconst date = `${year}-${month}-${day}`;\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\tconst agents = options.agents ?? [];\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `<project_instructions path=\"${filePath}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t\t}\n\t\t\tprompt += \"</project_context>\\n\";\n\t\t}\n\n\t\t// Append skills section (only if read tool is available)\n\t\tconst customPromptHasRead = !selectedTools || selectedTools.includes(\"read\");\n\t\tif (customPromptHasRead && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\t\tif (customPromptHasRead && agents.length > 0) {\n\t\t\tprompt += formatAgentsForPrompt(agents);\n\t\t}\n\n\t\t// Add date and working directory last\n\t\tprompt += `\\nCurrent date: ${date}`;\n\t\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation and examples\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\n\t// Build tools list based on selected tools.\n\t// A tool appears in Available tools only when the caller provides a one-line snippet.\n\tconst tools = selectedTools || [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst visibleTools = tools.filter((name) => !!toolSnippets?.[name]);\n\tconst toolsList =\n\t\tvisibleTools.length > 0 ? visibleTools.map((name) => `- ${name}: ${toolSnippets![name]}`).join(\"\\n\") : \"(none)\";\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\tconst addGuideline = (guideline: string): void => {\n\t\tif (guidelinesSet.has(guideline)) {\n\t\t\treturn;\n\t\t}\n\t\tguidelinesSet.add(guideline);\n\t\tguidelinesList.push(guideline);\n\t};\n\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst hasRead = tools.includes(\"read\");\n\n\t// File exploration guidelines\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\taddGuideline(\"Use bash for file operations like ls, rg, find\");\n\t}\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) {\n\t\t\taddGuideline(normalized);\n\t\t}\n\t}\n\n\t// Always include these\n\taddGuideline(\"Be concise in your responses\");\n\taddGuideline(\"Show file paths clearly when working with files\");\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tlet prompt = `You are an expert coding assistant operating inside SelesaiCode fork of Pi, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n${toolsList}\n\nIn addition to the tools above, you may have access to other custom tools depending on the project.\n\nGuidelines:\n${guidelines}\n\nPi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):\n- Main documentation: ${readmePath}\n- Additional docs: ${docsPath}\n- Examples: ${examplesPath} (extensions, custom tools, SDK)\n- When reading pi docs or examples, resolve docs/... under Additional docs and examples/... under Examples, not the current working directory\n- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md)\n- When working on pi topics, read the docs and examples, and follow .md cross-references before implementing\n- Always read pi .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\t// Append project context files\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `<project_instructions path=\"${filePath}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t}\n\t\tprompt += \"</project_context>\\n\";\n\t}\n\n\t// Append skills section (only if read tool is available)\n\tif (hasRead && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\tif (hasRead && agents.length > 0) {\n\t\tprompt += formatAgentsForPrompt(agents);\n\t}\n\n\t// Add date and working directory last\n\tprompt += `\\nCurrent date: ${date}`;\n\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\treturn prompt;\n}\n"]}
|
|
@@ -83,7 +83,7 @@ export function buildSystemPrompt(options) {
|
|
|
83
83
|
addGuideline("Be concise in your responses");
|
|
84
84
|
addGuideline("Show file paths clearly when working with files");
|
|
85
85
|
const guidelines = guidelinesList.map((g) => `- ${g}`).join("\n");
|
|
86
|
-
let prompt = `You are an expert coding assistant operating inside
|
|
86
|
+
let prompt = `You are an expert coding assistant operating inside SelesaiCode fork of Pi, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.
|
|
87
87
|
|
|
88
88
|
Available tools:
|
|
89
89
|
${toolsList}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.ts\";\nimport { formatAgentsForPrompt, type AgentPersona } from \"./agents.ts\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.ts\";\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n\t/** Pre-loaded subagent personas. */\n\tagents?: AgentPersona[];\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t} = options;\n\tconst resolvedCwd = cwd;\n\tconst promptCwd = resolvedCwd.replace(/\\\\/g, \"/\");\n\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = String(now.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(now.getDate()).padStart(2, \"0\");\n\tconst date = `${year}-${month}-${day}`;\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\tconst agents = options.agents ?? [];\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `<project_instructions path=\"${filePath}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t\t}\n\t\t\tprompt += \"</project_context>\\n\";\n\t\t}\n\n\t\t// Append skills section (only if read tool is available)\n\t\tconst customPromptHasRead = !selectedTools || selectedTools.includes(\"read\");\n\t\tif (customPromptHasRead && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\t\tif (customPromptHasRead && agents.length > 0) {\n\t\t\tprompt += formatAgentsForPrompt(agents);\n\t\t}\n\n\t\t// Add date and working directory last\n\t\tprompt += `\\nCurrent date: ${date}`;\n\t\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation and examples\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\n\t// Build tools list based on selected tools.\n\t// A tool appears in Available tools only when the caller provides a one-line snippet.\n\tconst tools = selectedTools || [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst visibleTools = tools.filter((name) => !!toolSnippets?.[name]);\n\tconst toolsList =\n\t\tvisibleTools.length > 0 ? visibleTools.map((name) => `- ${name}: ${toolSnippets![name]}`).join(\"\\n\") : \"(none)\";\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\tconst addGuideline = (guideline: string): void => {\n\t\tif (guidelinesSet.has(guideline)) {\n\t\t\treturn;\n\t\t}\n\t\tguidelinesSet.add(guideline);\n\t\tguidelinesList.push(guideline);\n\t};\n\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst hasRead = tools.includes(\"read\");\n\n\t// File exploration guidelines\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\taddGuideline(\"Use bash for file operations like ls, rg, find\");\n\t}\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) {\n\t\t\taddGuideline(normalized);\n\t\t}\n\t}\n\n\t// Always include these\n\taddGuideline(\"Be concise in your responses\");\n\taddGuideline(\"Show file paths clearly when working with files\");\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tlet prompt = `You are an expert coding assistant operating inside pi, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n${toolsList}\n\nIn addition to the tools above, you may have access to other custom tools depending on the project.\n\nGuidelines:\n${guidelines}\n\nPi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):\n- Main documentation: ${readmePath}\n- Additional docs: ${docsPath}\n- Examples: ${examplesPath} (extensions, custom tools, SDK)\n- When reading pi docs or examples, resolve docs/... under Additional docs and examples/... under Examples, not the current working directory\n- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md)\n- When working on pi topics, read the docs and examples, and follow .md cross-references before implementing\n- Always read pi .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\t// Append project context files\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `<project_instructions path=\"${filePath}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t}\n\t\tprompt += \"</project_context>\\n\";\n\t}\n\n\t// Append skills section (only if read tool is available)\n\tif (hasRead && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\tif (hasRead && agents.length > 0) {\n\t\tprompt += formatAgentsForPrompt(agents);\n\t}\n\n\t// Add date and working directory last\n\tprompt += `\\nCurrent date: ${date}`;\n\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\treturn prompt;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAqB,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAc,MAAM,aAAa,CAAC;AAuBhE,kEAAkE;AAClE,MAAM,UAAU,iBAAiB,CAAC,OAAiC,EAAU;IAC5E,MAAM,EACL,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,GAAG,EACH,YAAY,EAAE,oBAAoB,EAClC,MAAM,EAAE,cAAc,GACtB,GAAG,OAAO,CAAC;IACZ,MAAM,WAAW,GAAG,GAAG,CAAC;IACxB,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAElD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;IAEvC,MAAM,aAAa,GAAG,kBAAkB,CAAC,CAAC,CAAC,OAAO,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAE5E,MAAM,YAAY,GAAG,oBAAoB,IAAI,EAAE,CAAC;IAChD,MAAM,MAAM,GAAG,cAAc,IAAI,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;IAEpC,IAAI,YAAY,EAAE,CAAC;QAClB,IAAI,MAAM,GAAG,YAAY,CAAC;QAE1B,IAAI,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,aAAa,CAAC;QACzB,CAAC;QAED,+BAA+B;QAC/B,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,2BAA2B,CAAC;YACtC,MAAM,IAAI,mDAAmD,CAAC;YAC9D,KAAK,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,YAAY,EAAE,CAAC;gBACxD,MAAM,IAAI,+BAA+B,QAAQ,OAAO,OAAO,+BAA+B,CAAC;YAChG,CAAC;YACD,MAAM,IAAI,sBAAsB,CAAC;QAClC,CAAC;QAED,yDAAyD;QACzD,MAAM,mBAAmB,GAAG,CAAC,aAAa,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC7E,IAAI,mBAAmB,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,MAAM,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,mBAAmB,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,MAAM,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC;QAED,sCAAsC;QACtC,MAAM,IAAI,mBAAmB,IAAI,EAAE,CAAC;QACpC,MAAM,IAAI,gCAAgC,SAAS,EAAE,CAAC;QAEtD,OAAO,MAAM,CAAC;IACf,CAAC;IAED,mDAAmD;IACnD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IAEvC,4CAA4C;IAC5C,sFAAsF;IACtF,MAAM,KAAK,GAAG,aAAa,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACjE,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IACpE,MAAM,SAAS,GACd,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,KAAK,YAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEjH,+DAA+D;IAC/D,MAAM,cAAc,GAAa,EAAE,CAAC;IACpC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,MAAM,YAAY,GAAG,CAAC,SAAiB,EAAQ,EAAE,CAAC;QACjD,IAAI,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAClC,OAAO;QACR,CAAC;QACD,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC7B,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAAA,CAC/B,CAAC;IAEF,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEvC,8BAA8B;IAC9B,IAAI,OAAO,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;QAC/C,YAAY,CAAC,gDAAgD,CAAC,CAAC;IAChE,CAAC;IAED,KAAK,MAAM,SAAS,IAAI,gBAAgB,IAAI,EAAE,EAAE,CAAC;QAChD,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,YAAY,CAAC,UAAU,CAAC,CAAC;QAC1B,CAAC;IACF,CAAC;IAED,uBAAuB;IACvB,YAAY,CAAC,8BAA8B,CAAC,CAAC;IAC7C,YAAY,CAAC,iDAAiD,CAAC,CAAC;IAEhE,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAElE,IAAI,MAAM,GAAG;;;EAGZ,SAAS;;;;;EAKT,UAAU;;;wBAGY,UAAU;qBACb,QAAQ;cACf,YAAY;;;;0GAIgF,CAAC;IAE1G,IAAI,aAAa,EAAE,CAAC;QACnB,MAAM,IAAI,aAAa,CAAC;IACzB,CAAC;IAED,+BAA+B;IAC/B,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,2BAA2B,CAAC;QACtC,MAAM,IAAI,mDAAmD,CAAC;QAC9D,KAAK,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,YAAY,EAAE,CAAC;YACxD,MAAM,IAAI,+BAA+B,QAAQ,OAAO,OAAO,+BAA+B,CAAC;QAChG,CAAC;QACD,MAAM,IAAI,sBAAsB,CAAC;IAClC,CAAC;IAED,yDAAyD;IACzD,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,sCAAsC;IACtC,MAAM,IAAI,mBAAmB,IAAI,EAAE,CAAC;IACpC,MAAM,IAAI,gCAAgC,SAAS,EAAE,CAAC;IAEtD,OAAO,MAAM,CAAC;AAAA,CACd","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.ts\";\nimport { formatAgentsForPrompt, type AgentPersona } from \"./agents.ts\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.ts\";\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n\t/** Pre-loaded subagent personas. */\n\tagents?: AgentPersona[];\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t} = options;\n\tconst resolvedCwd = cwd;\n\tconst promptCwd = resolvedCwd.replace(/\\\\/g, \"/\");\n\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = String(now.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(now.getDate()).padStart(2, \"0\");\n\tconst date = `${year}-${month}-${day}`;\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\tconst agents = options.agents ?? [];\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `<project_instructions path=\"${filePath}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t\t}\n\t\t\tprompt += \"</project_context>\\n\";\n\t\t}\n\n\t\t// Append skills section (only if read tool is available)\n\t\tconst customPromptHasRead = !selectedTools || selectedTools.includes(\"read\");\n\t\tif (customPromptHasRead && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\t\tif (customPromptHasRead && agents.length > 0) {\n\t\t\tprompt += formatAgentsForPrompt(agents);\n\t\t}\n\n\t\t// Add date and working directory last\n\t\tprompt += `\\nCurrent date: ${date}`;\n\t\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation and examples\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\n\t// Build tools list based on selected tools.\n\t// A tool appears in Available tools only when the caller provides a one-line snippet.\n\tconst tools = selectedTools || [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst visibleTools = tools.filter((name) => !!toolSnippets?.[name]);\n\tconst toolsList =\n\t\tvisibleTools.length > 0 ? visibleTools.map((name) => `- ${name}: ${toolSnippets![name]}`).join(\"\\n\") : \"(none)\";\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\tconst addGuideline = (guideline: string): void => {\n\t\tif (guidelinesSet.has(guideline)) {\n\t\t\treturn;\n\t\t}\n\t\tguidelinesSet.add(guideline);\n\t\tguidelinesList.push(guideline);\n\t};\n\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst hasRead = tools.includes(\"read\");\n\n\t// File exploration guidelines\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\taddGuideline(\"Use bash for file operations like ls, rg, find\");\n\t}\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) {\n\t\t\taddGuideline(normalized);\n\t\t}\n\t}\n\n\t// Always include these\n\taddGuideline(\"Be concise in your responses\");\n\taddGuideline(\"Show file paths clearly when working with files\");\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tlet prompt = `You are an expert coding assistant operating inside SelesaiCode fork of Pi, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n${toolsList}\n\nIn addition to the tools above, you may have access to other custom tools depending on the project.\n\nGuidelines:\n${guidelines}\n\nPi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):\n- Main documentation: ${readmePath}\n- Additional docs: ${docsPath}\n- Examples: ${examplesPath} (extensions, custom tools, SDK)\n- When reading pi docs or examples, resolve docs/... under Additional docs and examples/... under Examples, not the current working directory\n- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md)\n- When working on pi topics, read the docs and examples, and follow .md cross-references before implementing\n- Always read pi .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\t// Append project context files\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `<project_instructions path=\"${filePath}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t}\n\t\tprompt += \"</project_context>\\n\";\n\t}\n\n\t// Append skills section (only if read tool is available)\n\tif (hasRead && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\tif (hasRead && agents.length > 0) {\n\t\tprompt += formatAgentsForPrompt(agents);\n\t}\n\n\t// Add date and working directory last\n\tprompt += `\\nCurrent date: ${date}`;\n\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\treturn prompt;\n}\n"]}
|
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
"description": "Built-in extensions shipped with @selesai/code, loaded via additionalExtensionPaths at boot.",
|
|
6
6
|
"pi": {
|
|
7
7
|
"extensions": [
|
|
8
|
+
"./caveman/index.js",
|
|
8
9
|
"./copy-turn.ts",
|
|
9
10
|
"./context-compaction-reminder.ts",
|
|
10
|
-
"./
|
|
11
|
+
"./pi-intercom/index.ts",
|
|
12
|
+
"./ponytail/index.js",
|
|
11
13
|
"./question",
|
|
12
14
|
"./grep-app",
|
|
13
15
|
"./handoff-new.ts",
|
|
@@ -18,8 +20,7 @@
|
|
|
18
20
|
"./pi-subagents",
|
|
19
21
|
"./pi-web-agent",
|
|
20
22
|
"./web-agent-onboarding.ts",
|
|
21
|
-
"./pi-powerline-footer"
|
|
22
|
-
"./pi-extension"
|
|
23
|
+
"./pi-powerline-footer"
|
|
23
24
|
]
|
|
24
25
|
}
|
|
25
26
|
}
|
|
@@ -14,7 +14,7 @@ Customizes the default [pi](https://github.com/badlogic/pi-mono) editor with a p
|
|
|
14
14
|
|
|
15
15
|
**Working Vibes** — AI-generated themed loading messages. Set `/vibe star trek` and your "Working..." becomes "Running diagnostics..." or "Engaging warp drive...". Supports any theme: pirate, zen, noir, cowboy, etc.
|
|
16
16
|
|
|
17
|
-
**Welcome
|
|
17
|
+
**Welcome and guide** — A recurring Selesai guide appears on startup, new, resumed, and forked sessions. It maps workflow commands, delegation and research prompts, skills, handoff, recovery, and settings to concrete next steps. Use `/guide` to reopen it, `/guide compact` for a small header, `/guide off` to remember dismissal, or `/guide reset` to restore the full tour. New guide features are called out after upgrades; only the guide mode and version marker are persisted.
|
|
18
18
|
|
|
19
19
|
**Rounded box design** — Status renders directly in the editor's top border, not as a separate footer.
|
|
20
20
|
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
|
|
4
|
+
export type GuideMode = "full" | "compact" | "off";
|
|
5
|
+
export type GuideDisplayMode = "full" | "compact" | "none";
|
|
6
|
+
|
|
7
|
+
export interface GuideFeature {
|
|
8
|
+
id: string;
|
|
9
|
+
section?: string;
|
|
10
|
+
title: string;
|
|
11
|
+
example: string;
|
|
12
|
+
introducedIn: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface GuidePreferences {
|
|
16
|
+
mode: GuideMode;
|
|
17
|
+
lastSeenVersion?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface GuidePreferencesUpdate {
|
|
21
|
+
mode?: GuideMode;
|
|
22
|
+
lastSeenVersion?: string | null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Keep this map useful, not exhaustive: each row points at a real command, shortcut,
|
|
26
|
+
// or prompt from the root README without reproducing the README in the overlay.
|
|
27
|
+
export const GUIDE_FEATURES: readonly GuideFeature[] = [
|
|
28
|
+
{
|
|
29
|
+
id: "workflow-task",
|
|
30
|
+
section: "Start here",
|
|
31
|
+
title: "Task",
|
|
32
|
+
example: '/workflow-task "<goal>"',
|
|
33
|
+
introducedIn: "0.5.13",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "workflow-quick",
|
|
37
|
+
section: "Start here",
|
|
38
|
+
title: "Quick",
|
|
39
|
+
example: '/workflow-quick "<goal>"',
|
|
40
|
+
introducedIn: "0.5.13",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: "workflow-prototype",
|
|
44
|
+
section: "Start here",
|
|
45
|
+
title: "Prototype",
|
|
46
|
+
example: '/workflow-prototype "<goal>"',
|
|
47
|
+
introducedIn: "0.5.13",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "settings",
|
|
51
|
+
section: "Start here",
|
|
52
|
+
title: "Settings",
|
|
53
|
+
example: "/settings · /guide compact|off|reset · /reload",
|
|
54
|
+
introducedIn: "0.5.13",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: "subagents",
|
|
58
|
+
section: "Delegate / research",
|
|
59
|
+
title: "Plan",
|
|
60
|
+
example: '"Ask the architect to challenge this plan..."',
|
|
61
|
+
introducedIn: "0.5.13",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: "parallel-review",
|
|
65
|
+
section: "Delegate / research",
|
|
66
|
+
title: "Review",
|
|
67
|
+
example: '"Run parallel commentator agents for correctness..."',
|
|
68
|
+
introducedIn: "0.5.13",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: "web-research",
|
|
72
|
+
section: "Delegate / research",
|
|
73
|
+
title: "Research",
|
|
74
|
+
example: '"Ask the researcher to research <topic> and cite sources."',
|
|
75
|
+
introducedIn: "0.5.13",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: "skills",
|
|
79
|
+
section: "Delegate / research",
|
|
80
|
+
title: "Skills",
|
|
81
|
+
example: "/skill:*",
|
|
82
|
+
introducedIn: "0.5.13",
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: "recovery",
|
|
86
|
+
section: "Recover",
|
|
87
|
+
title: "Recover",
|
|
88
|
+
example: "/undo · /tree · /fork · /cp <hash>",
|
|
89
|
+
introducedIn: "0.5.13",
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: "handoff",
|
|
93
|
+
section: "Recover",
|
|
94
|
+
title: "Handoff",
|
|
95
|
+
example: "/handoff-new Next: fix <problem>; start with a coding plan.",
|
|
96
|
+
introducedIn: "0.5.13",
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
export const GUIDE_DISMISS_HINT = "Press any key to continue";
|
|
101
|
+
|
|
102
|
+
export const GUIDE_COMPACT_LINES = [
|
|
103
|
+
"/guide full · /settings",
|
|
104
|
+
'/workflow-task "<goal>" · /workflow-quick "<goal>"',
|
|
105
|
+
'/workflow-prototype "<goal>"',
|
|
106
|
+
'"Ask the researcher to research <topic>."',
|
|
107
|
+
"/skill:* · /undo · /handoff-new <next focus>",
|
|
108
|
+
] as const;
|
|
109
|
+
|
|
110
|
+
export type GuideLine =
|
|
111
|
+
| { kind: "section"; text: string }
|
|
112
|
+
| { kind: "feature"; feature: GuideFeature };
|
|
113
|
+
|
|
114
|
+
export function getGuideFeatureLines(features: readonly GuideFeature[] = GUIDE_FEATURES): GuideLine[] {
|
|
115
|
+
return features.flatMap((feature, index) => {
|
|
116
|
+
const previous = features[index - 1];
|
|
117
|
+
const section = feature.section && feature.section !== previous?.section
|
|
118
|
+
? [{ kind: "section" as const, text: feature.section }]
|
|
119
|
+
: [];
|
|
120
|
+
return [...section, { kind: "feature" as const, feature }];
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
125
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function isGuideMode(value: unknown): value is GuideMode {
|
|
129
|
+
return value === "full" || value === "compact" || value === "off";
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function versionParts(version: string): [number, number, number] {
|
|
133
|
+
const match = version.trim().match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
134
|
+
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : [0, 0, 0];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function compareGuideVersions(left: string, right: string): number {
|
|
138
|
+
const leftParts = versionParts(left);
|
|
139
|
+
const rightParts = versionParts(right);
|
|
140
|
+
for (let i = 0; i < leftParts.length; i++) {
|
|
141
|
+
if (leftParts[i] !== rightParts[i]) return leftParts[i] - rightParts[i];
|
|
142
|
+
}
|
|
143
|
+
return 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function getGuidePreferences(settings: unknown): GuidePreferences {
|
|
147
|
+
const raw = isRecord(settings) && isRecord(settings.selesaiGuide)
|
|
148
|
+
? settings.selesaiGuide
|
|
149
|
+
: {};
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
mode: isGuideMode(raw.mode) ? raw.mode : "full",
|
|
153
|
+
lastSeenVersion: typeof raw.lastSeenVersion === "string" ? raw.lastSeenVersion : undefined,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function getNewGuideFeatures(
|
|
158
|
+
lastSeenVersion: string | undefined,
|
|
159
|
+
currentVersion: string,
|
|
160
|
+
features: readonly GuideFeature[] = GUIDE_FEATURES,
|
|
161
|
+
): GuideFeature[] {
|
|
162
|
+
if (!lastSeenVersion || compareGuideVersions(lastSeenVersion, currentVersion) >= 0) {
|
|
163
|
+
return [];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return features.filter((feature) => (
|
|
167
|
+
compareGuideVersions(feature.introducedIn, lastSeenVersion) > 0
|
|
168
|
+
&& compareGuideVersions(feature.introducedIn, currentVersion) <= 0
|
|
169
|
+
));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function resolveGuideDisplayMode(options: {
|
|
173
|
+
reason: string;
|
|
174
|
+
hasUI: boolean;
|
|
175
|
+
guideMode: GuideMode;
|
|
176
|
+
}): GuideDisplayMode {
|
|
177
|
+
if (!options.hasUI || options.reason === "reload" || options.guideMode === "off") {
|
|
178
|
+
return "none";
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return options.guideMode === "compact" ? "compact" : "full";
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function readSettingsFile(settingsPath: string): Record<string, unknown> | null {
|
|
185
|
+
if (!existsSync(settingsPath)) return {};
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
const parsed = JSON.parse(readFileSync(settingsPath, "utf8"));
|
|
189
|
+
return isRecord(parsed) ? parsed : null;
|
|
190
|
+
} catch {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export function saveGuidePreferences(
|
|
196
|
+
update: GuidePreferencesUpdate,
|
|
197
|
+
settingsPath: string,
|
|
198
|
+
): boolean {
|
|
199
|
+
const settings = readSettingsFile(settingsPath);
|
|
200
|
+
if (!settings) return false;
|
|
201
|
+
|
|
202
|
+
const current = getGuidePreferences(settings);
|
|
203
|
+
const next: Record<string, unknown> = {
|
|
204
|
+
mode: update.mode ?? current.mode,
|
|
205
|
+
};
|
|
206
|
+
const lastSeenVersion = update.lastSeenVersion === null
|
|
207
|
+
? undefined
|
|
208
|
+
: update.lastSeenVersion ?? current.lastSeenVersion;
|
|
209
|
+
if (lastSeenVersion) next.lastSeenVersion = lastSeenVersion;
|
|
210
|
+
|
|
211
|
+
settings.selesaiGuide = next;
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
mkdirSync(dirname(settingsPath), { recursive: true });
|
|
215
|
+
writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\n`, "utf8");
|
|
216
|
+
return true;
|
|
217
|
+
} catch {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function markGuideVersionSeen(
|
|
223
|
+
version: string,
|
|
224
|
+
settingsPath: string,
|
|
225
|
+
): boolean {
|
|
226
|
+
return saveGuidePreferences({ lastSeenVersion: version }, settingsPath);
|
|
227
|
+
}
|