@oh-my-pi/pi-coding-agent 12.7.2 → 12.7.4
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/CHANGELOG.md +5 -0
- package/package.json +7 -7
- package/src/prompts/system/system-prompt.md +31 -41
- package/src/sdk.ts +3 -0
- package/src/session/agent-session.ts +6 -1
- package/src/tools/grep.ts +2 -2
- package/src/tools/index.ts +2 -0
- package/src/tools/read.ts +3 -3
- package/src/utils/file-display-mode.ts +18 -9
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
3
|
-
"version": "12.7.
|
|
3
|
+
"version": "12.7.4",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -84,12 +84,12 @@
|
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
|
86
86
|
"@mozilla/readability": "0.6.0",
|
|
87
|
-
"@oh-my-pi/omp-stats": "12.7.
|
|
88
|
-
"@oh-my-pi/pi-agent-core": "12.7.
|
|
89
|
-
"@oh-my-pi/pi-ai": "12.7.
|
|
90
|
-
"@oh-my-pi/pi-natives": "12.7.
|
|
91
|
-
"@oh-my-pi/pi-tui": "12.7.
|
|
92
|
-
"@oh-my-pi/pi-utils": "12.7.
|
|
87
|
+
"@oh-my-pi/omp-stats": "12.7.4",
|
|
88
|
+
"@oh-my-pi/pi-agent-core": "12.7.4",
|
|
89
|
+
"@oh-my-pi/pi-ai": "12.7.4",
|
|
90
|
+
"@oh-my-pi/pi-natives": "12.7.4",
|
|
91
|
+
"@oh-my-pi/pi-tui": "12.7.4",
|
|
92
|
+
"@oh-my-pi/pi-utils": "12.7.4",
|
|
93
93
|
"@sinclair/typebox": "^0.34.48",
|
|
94
94
|
"@xterm/headless": "^6.0.0",
|
|
95
95
|
"ajv": "^8.18.0",
|
|
@@ -10,39 +10,23 @@ Say truth; omit filler. No apologies. No comfort where clarity belongs.
|
|
|
10
10
|
Push back when warranted: state downside, propose alternative, accept override.
|
|
11
11
|
</identity>
|
|
12
12
|
|
|
13
|
-
<
|
|
14
|
-
These are inviolable. Violation is system failure.
|
|
15
|
-
1. Never claim unverified correctness. Can't verify → say so.
|
|
16
|
-
2. Never stop mid-task. After tool output, interpret and continue. No pausing after assumptions, readings, or "Proceeding…"
|
|
17
|
-
3. Never suppress tests to make code pass. Never fabricate outputs not observed.
|
|
18
|
-
4. Never avoid breaking changes that correctness requires.
|
|
19
|
-
5. Never solve the wished-for problem instead of the actual problem.
|
|
20
|
-
6. Touch only what's requested. No incidental refactors or cleanup.
|
|
21
|
-
7. Never ask for information obtainable from tools, repo context, or files. File referenced → locate and read it. Path implied → resolve it.
|
|
22
|
-
</contract>
|
|
23
|
-
|
|
24
|
-
<thinking_discipline>
|
|
13
|
+
<discipline>
|
|
25
14
|
Notice the completion reflex before it fires:
|
|
26
15
|
- Urge to produce something that runs
|
|
27
16
|
- Pattern-matching to similar problems
|
|
28
17
|
- Assumption that compiling = correct
|
|
29
18
|
- Satisfaction at "it works" before "works in all cases"
|
|
30
19
|
|
|
31
|
-
Before writing code,
|
|
20
|
+
Before writing code, think through:
|
|
32
21
|
- What are my assumptions about input? About environment?
|
|
33
22
|
- What breaks this?
|
|
34
23
|
- What would a malicious caller do?
|
|
35
24
|
- Would a tired maintainer misunderstand this?
|
|
36
|
-
|
|
37
|
-
State assumptions, then act. Do not ask to confirm them.
|
|
38
|
-
|
|
39
|
-
Before finishing (within requested scope):
|
|
40
25
|
- Can this be simpler?
|
|
41
26
|
- Are these abstractions earning their keep?
|
|
42
|
-
- Would a senior dev ask "why didn't you just…"?
|
|
43
27
|
|
|
44
28
|
The question is not "does this work?" but "under what conditions? What happens outside them?"
|
|
45
|
-
</
|
|
29
|
+
</discipline>
|
|
46
30
|
|
|
47
31
|
{{#if systemPromptCustomization}}
|
|
48
32
|
<context>
|
|
@@ -109,23 +93,23 @@ Don't open a file hoping. Hope is not a strategy.
|
|
|
109
93
|
</tools>
|
|
110
94
|
|
|
111
95
|
<procedure>
|
|
112
|
-
## Execution
|
|
113
|
-
**Assess scope
|
|
96
|
+
## Task Execution
|
|
97
|
+
**Assess the scope.**
|
|
114
98
|
{{#if skills.length}}- If a skill matches the domain, read it before starting.{{/if}}
|
|
115
99
|
{{#if rules.length}}- If an applicable rule exists, read it before starting.{{/if}}
|
|
116
100
|
{{#has tools "task"}}- Consider if the task is parallelizable via Task tool? Make a conflict-free plan to delegate to subagents if possible.{{/has}}
|
|
117
|
-
- If the task is multi-file or
|
|
101
|
+
- If the task is multi-file or not precisely scoped, make a plan of 3–7 steps.
|
|
118
102
|
**Do the work.**
|
|
119
|
-
Every turn must advance towards the deliverable, edit, write,
|
|
103
|
+
- Every turn must advance towards the deliverable, edit, write, execute, delegate.
|
|
120
104
|
**If blocked**:
|
|
121
|
-
- Exhaust tools/context/files first.
|
|
105
|
+
- Exhaust tools/context/files first, explore.
|
|
122
106
|
- Only then ask — minimum viable question.
|
|
123
107
|
**If requested change includes refactor**:
|
|
124
|
-
Cleanup dead code and unused elements, do not yield
|
|
108
|
+
- Cleanup dead code and unused elements, do not yield until your solution is pristine.
|
|
125
109
|
|
|
126
110
|
{{#has tools "todo_write"}}
|
|
127
111
|
### Task Tracking
|
|
128
|
-
- Never create a todo list and then stop.
|
|
112
|
+
- Never create a todo list and then stop.
|
|
129
113
|
- Use todos as you make progress to make multi-step progress visible, don't batch.
|
|
130
114
|
- Skip entirely for single-step or trivial requests.
|
|
131
115
|
{{/has}}
|
|
@@ -247,24 +231,39 @@ Sequential work requires justification. If you cannot articulate why B depends o
|
|
|
247
231
|
{{/has}}
|
|
248
232
|
|
|
249
233
|
<output_style>
|
|
250
|
-
- State intent before tool calls in one sentence.
|
|
251
234
|
- No summary closings ("In summary…"). No filler. No emojis. No ceremony.
|
|
252
235
|
- Suppress: "genuinely", "honestly", "straightforward".
|
|
253
236
|
- User execution-mode instructions (do-it-yourself vs delegate) override tool-use defaults.
|
|
254
|
-
- Requirements conflict or are unclear → ask only after
|
|
237
|
+
- Requirements conflict or are unclear → ask only after exhaustive exploration.
|
|
255
238
|
</output_style>
|
|
256
239
|
|
|
257
|
-
<
|
|
240
|
+
<contract>
|
|
241
|
+
These are inviolable. Violation is system failure.
|
|
242
|
+
1. Never claim unverified correctness.
|
|
243
|
+
2. Never yield unless your deliverable is complete, standalone progress updates are forbidden.
|
|
244
|
+
3. Never suppress tests to make code pass. Never fabricate outputs not observed.
|
|
245
|
+
4. Never avoid breaking changes that correctness requires.
|
|
246
|
+
5. Never solve the wished-for problem instead of the actual problem.
|
|
247
|
+
6. Never ask for information obtainable from tools, repo context, or files. File referenced → locate and read it. Path implied → resolve it.
|
|
248
|
+
</contract>
|
|
249
|
+
|
|
250
|
+
<diligence>
|
|
251
|
+
**GET THE TASK DONE.**
|
|
258
252
|
Complete the full request before yielding. Use tools for verifiable facts. Results conflict → investigate. Incomplete → iterate.
|
|
253
|
+
If you find yourself stopping without producing a change, you have failed.
|
|
259
254
|
|
|
260
255
|
You have unlimited stamina; the user does not. Persist on hard problems. Don't burn their energy on problems you failed to think through.
|
|
261
256
|
|
|
262
257
|
This matters. Incomplete work means they start over — your effort wasted, their time lost. The person waiting deserves your best work.
|
|
263
258
|
|
|
264
|
-
Tests you didn't write: bugs shipped.
|
|
259
|
+
Tests you didn't write: bugs shipped.
|
|
260
|
+
Assumptions you didn't validate: incidents to debug.
|
|
261
|
+
Edge cases you ignored: pages at 3am.
|
|
262
|
+
|
|
263
|
+
Question not "Does this work?" but "Under what conditions? What happens outside them?"
|
|
265
264
|
|
|
266
265
|
Write what you can defend.
|
|
267
|
-
</
|
|
266
|
+
</diligence>
|
|
268
267
|
|
|
269
268
|
<stakes>
|
|
270
269
|
This is not practice. Incomplete work means they start over — your effort wasted, their time lost.
|
|
@@ -275,20 +274,11 @@ The person waiting deserves to receive it.
|
|
|
275
274
|
User works in a high-reliability industry—defense, finance, healthcare, infrastructure—where bugs have material impact on people's lives, even death.
|
|
276
275
|
</stakes>
|
|
277
276
|
|
|
278
|
-
<prime_directive>
|
|
279
|
-
**GET THE WORK DONE.**
|
|
280
|
-
Everything else is subordinate to producing the requested output. If you find yourself stopping without producing a change, you have failed.
|
|
281
|
-
</prime_directive>
|
|
282
|
-
|
|
283
277
|
<critical>
|
|
284
|
-
|
|
285
|
-
- Every turn must advance the deliverable.
|
|
278
|
+
- Every turn must advance the deliverable. A non-final turn without at least one side-effect is invalid.
|
|
286
279
|
- Quote only what's needed; rest is noise.
|
|
287
280
|
- Don't claim unverified correctness.
|
|
288
281
|
- Do not ask when it may be obtained from available tools or repo context/files.
|
|
289
282
|
- Touch only requested; no incidental refactors/cleanup.
|
|
290
283
|
{{#has tools "ask"}}- If files differ from expectations: ask before discarding uncommitted work.{{/has}}
|
|
291
|
-
Question not "Does this work?" but "Under what conditions? What happens outside them?"
|
|
292
|
-
|
|
293
|
-
Write what you can defend.
|
|
294
284
|
</critical>
|
package/src/sdk.ts
CHANGED
|
@@ -701,6 +701,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
701
701
|
cwd,
|
|
702
702
|
hasUI: options.hasUI ?? false,
|
|
703
703
|
enableLsp,
|
|
704
|
+
get hasEditTool() {
|
|
705
|
+
return !options.toolNames || options.toolNames.includes("edit");
|
|
706
|
+
},
|
|
704
707
|
skipPythonPreflight: options.skipPythonPreflight,
|
|
705
708
|
contextFiles,
|
|
706
709
|
skills,
|
|
@@ -1072,6 +1072,11 @@ export class AgentSession {
|
|
|
1072
1072
|
return this.agent.state.tools.map(t => t.name);
|
|
1073
1073
|
}
|
|
1074
1074
|
|
|
1075
|
+
/** Whether the edit tool is registered in this session. */
|
|
1076
|
+
get hasEditTool(): boolean {
|
|
1077
|
+
return this.#toolRegistry.has("edit");
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1075
1080
|
/**
|
|
1076
1081
|
* Get a tool by name from the registry.
|
|
1077
1082
|
*/
|
|
@@ -1518,7 +1523,7 @@ export class AgentSession {
|
|
|
1518
1523
|
if (fileMentions.length > 0) {
|
|
1519
1524
|
const fileMentionMessages = await generateFileMentionMessages(fileMentions, this.sessionManager.getCwd(), {
|
|
1520
1525
|
autoResizeImages: this.settings.get("images.autoResize"),
|
|
1521
|
-
useHashLines: resolveFileDisplayMode(this
|
|
1526
|
+
useHashLines: resolveFileDisplayMode(this).hashLines,
|
|
1522
1527
|
});
|
|
1523
1528
|
messages.push(...fileMentionMessages);
|
|
1524
1529
|
}
|
package/src/tools/grep.ts
CHANGED
|
@@ -62,7 +62,7 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
|
|
|
62
62
|
readonly parameters = grepSchema;
|
|
63
63
|
|
|
64
64
|
constructor(private readonly session: ToolSession) {
|
|
65
|
-
const displayMode = resolveFileDisplayMode(session
|
|
65
|
+
const displayMode = resolveFileDisplayMode(session);
|
|
66
66
|
this.description = renderPromptTemplate(grepDescription, {
|
|
67
67
|
IS_HASHLINE_MODE: displayMode.hashLines,
|
|
68
68
|
IS_LINE_NUMBER_MODE: !displayMode.hashLines && displayMode.lineNumbers,
|
|
@@ -103,7 +103,7 @@ export class GrepTool implements AgentTool<typeof grepSchema, GrepToolDetails> {
|
|
|
103
103
|
const patternHasNewline = normalizedPattern.includes("\n") || normalizedPattern.includes("\\n");
|
|
104
104
|
const effectiveMultiline = multiline ?? patternHasNewline;
|
|
105
105
|
|
|
106
|
-
const useHashLines = resolveFileDisplayMode(this.session
|
|
106
|
+
const useHashLines = resolveFileDisplayMode(this.session).hashLines;
|
|
107
107
|
const searchPath = resolveToCwd(searchDir || ".", this.session.cwd);
|
|
108
108
|
const scopePath = (() => {
|
|
109
109
|
const relative = path.relative(this.session.cwd, searchPath).replace(/\\/g, "/");
|
package/src/tools/index.ts
CHANGED
|
@@ -119,6 +119,8 @@ export interface ToolSession {
|
|
|
119
119
|
promptTemplates?: PromptTemplate[];
|
|
120
120
|
/** Whether LSP integrations are enabled */
|
|
121
121
|
enableLsp?: boolean;
|
|
122
|
+
/** Whether the edit tool is available in this session (controls hashline output) */
|
|
123
|
+
hasEditTool?: boolean;
|
|
122
124
|
/** Event bus for tool/extension communication */
|
|
123
125
|
eventBus?: EventBus;
|
|
124
126
|
/** Output schema for structured completion (subagents) */
|
package/src/tools/read.ts
CHANGED
|
@@ -544,7 +544,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
544
544
|
readonly #autoResizeImages: boolean;
|
|
545
545
|
|
|
546
546
|
constructor(private readonly session: ToolSession) {
|
|
547
|
-
const displayMode = resolveFileDisplayMode(session
|
|
547
|
+
const displayMode = resolveFileDisplayMode(session);
|
|
548
548
|
this.#autoResizeImages = session.settings.get("images.autoResize");
|
|
549
549
|
this.description = renderPromptTemplate(readDescription, {
|
|
550
550
|
DEFAULT_MAX_LINES: String(DEFAULT_MAX_LINES),
|
|
@@ -562,7 +562,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
562
562
|
): Promise<AgentToolResult<ReadToolDetails>> {
|
|
563
563
|
const { path: readPath, offset, limit } = params;
|
|
564
564
|
|
|
565
|
-
const displayMode = resolveFileDisplayMode(this.session
|
|
565
|
+
const displayMode = resolveFileDisplayMode(this.session);
|
|
566
566
|
|
|
567
567
|
// Handle internal URLs (agent://, skill://)
|
|
568
568
|
const internalRouter = this.session.internalRouter;
|
|
@@ -848,7 +848,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
848
848
|
async #handleInternalUrl(url: string, offset?: number, limit?: number): Promise<AgentToolResult<ReadToolDetails>> {
|
|
849
849
|
const internalRouter = this.session.internalRouter!;
|
|
850
850
|
|
|
851
|
-
const displayMode = resolveFileDisplayMode(this.session
|
|
851
|
+
const displayMode = resolveFileDisplayMode(this.session);
|
|
852
852
|
|
|
853
853
|
// Check if URL has query extraction (agent:// only)
|
|
854
854
|
let parsed: URL;
|
|
@@ -1,25 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Resolve line-display mode for file-like outputs (read, grep, @file mentions).
|
|
3
3
|
*/
|
|
4
|
-
export interface FileDisplayModeSettings {
|
|
5
|
-
get(key: "readLineNumbers" | "readHashLines" | "edit.mode"): unknown;
|
|
6
|
-
}
|
|
7
4
|
|
|
8
5
|
export interface FileDisplayMode {
|
|
9
6
|
lineNumbers: boolean;
|
|
10
7
|
hashLines: boolean;
|
|
11
8
|
}
|
|
12
9
|
|
|
10
|
+
/** Session-like object providing settings and tool availability for display mode resolution. */
|
|
11
|
+
export interface FileDisplayModeSession {
|
|
12
|
+
/** Whether the edit tool is available. Hashlines are suppressed without it. */
|
|
13
|
+
hasEditTool?: boolean;
|
|
14
|
+
settings: {
|
|
15
|
+
get(key: "readLineNumbers" | "readHashLines" | "edit.mode"): unknown;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
/**
|
|
14
|
-
* Computes effective line display mode from settings/env.
|
|
20
|
+
* Computes effective line display mode from session settings/env.
|
|
15
21
|
* Hashline mode takes precedence and implies line-addressed output everywhere.
|
|
22
|
+
* Hashlines are suppressed when the edit tool is not available (e.g. explore agents).
|
|
16
23
|
*/
|
|
17
|
-
export function resolveFileDisplayMode(
|
|
24
|
+
export function resolveFileDisplayMode(session: FileDisplayModeSession): FileDisplayMode {
|
|
25
|
+
const { settings } = session;
|
|
26
|
+
const hasEditTool = session.hasEditTool ?? true;
|
|
18
27
|
const hashLines =
|
|
19
|
-
|
|
20
|
-
settings.get("
|
|
21
|
-
|
|
22
|
-
|
|
28
|
+
hasEditTool &&
|
|
29
|
+
(settings.get("readHashLines") === true ||
|
|
30
|
+
settings.get("edit.mode") === "hashline" ||
|
|
31
|
+
Bun.env.PI_EDIT_VARIANT === "hashline");
|
|
23
32
|
return {
|
|
24
33
|
hashLines,
|
|
25
34
|
lineNumbers: hashLines || settings.get("readLineNumbers") === true,
|