@oh-my-pi/pi-coding-agent 14.6.5 → 14.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +47 -0
- package/examples/hooks/handoff.ts +1 -1
- package/examples/hooks/qna.ts +1 -1
- package/examples/sdk/03-custom-prompt.ts +7 -4
- package/examples/sdk/README.md +1 -1
- package/package.json +7 -7
- package/src/autoresearch/index.ts +48 -44
- package/src/cli/read-cli.ts +58 -0
- package/src/cli.ts +1 -0
- package/src/commands/read.ts +40 -0
- package/src/commit/agentic/agent.ts +1 -1
- package/src/commit/analysis/conventional.ts +1 -1
- package/src/commit/analysis/summary.ts +1 -1
- package/src/commit/changelog/generate.ts +1 -1
- package/src/commit/map-reduce/map-phase.ts +1 -1
- package/src/commit/map-reduce/reduce-phase.ts +1 -1
- package/src/config/settings-schema.ts +39 -0
- package/src/edit/line-hash.ts +34 -4
- package/src/edit/modes/hashline.ts +221 -7
- package/src/edit/streaming.ts +4 -1
- package/src/export/html/index.ts +1 -1
- package/src/extensibility/extensions/runner.ts +3 -3
- package/src/extensibility/extensions/types.ts +4 -4
- package/src/main.ts +3 -3
- package/src/memories/index.ts +1 -1
- package/src/modes/components/agent-dashboard.ts +1 -1
- package/src/modes/components/custom-editor.ts +4 -5
- package/src/modes/components/read-tool-group.ts +4 -9
- package/src/modes/components/tool-execution.ts +4 -0
- package/src/modes/controllers/event-controller.ts +2 -0
- package/src/modes/controllers/input-controller.ts +3 -1
- package/src/modes/interactive-mode.ts +24 -0
- package/src/modes/rpc/rpc-types.ts +1 -1
- package/src/modes/utils/context-usage.ts +12 -5
- package/src/modes/utils/ui-helpers.ts +1 -0
- package/src/prompts/system/project-prompt.md +36 -0
- package/src/prompts/system/system-prompt.md +0 -29
- package/src/prompts/tools/github.md +1 -0
- package/src/prompts/tools/hashline.md +24 -6
- package/src/prompts/tools/read.md +15 -14
- package/src/sdk.ts +29 -28
- package/src/session/agent-session.ts +20 -12
- package/src/session/compaction/branch-summarization.ts +1 -1
- package/src/session/compaction/compaction.ts +3 -3
- package/src/session/session-dump-format.ts +10 -5
- package/src/session/session-manager.ts +57 -0
- package/src/session/streaming-output.ts +1 -1
- package/src/system-prompt.ts +35 -3
- package/src/task/executor.ts +4 -3
- package/src/tools/fetch.ts +4 -4
- package/src/tools/gh.ts +187 -0
- package/src/tools/image-gen.ts +3 -1
- package/src/tools/inspect-image.ts +1 -1
- package/src/tools/output-meta.ts +1 -1
- package/src/tools/path-utils.ts +11 -0
- package/src/tools/read.ts +388 -204
- package/src/tools/search.ts +1 -1
- package/src/tools/sqlite-reader.ts +1 -1
- package/src/utils/commit-message-generator.ts +1 -1
- package/src/utils/title-generator.ts +1 -1
- package/src/web/search/providers/anthropic.ts +1 -1
- package/src/workspace-tree.ts +396 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,53 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
|
+
### Added
|
|
5
|
+
|
|
6
|
+
- Added `pr_create` operation to the GitHub tool to create pull requests with title/body (or `fill`), base/head branch, draft, reviewer, assignee, and label options and return a summarized result including the new PR URL
|
|
7
|
+
|
|
8
|
+
## [14.7.0] - 2026-05-04
|
|
9
|
+
### Breaking Changes
|
|
10
|
+
|
|
11
|
+
- Changed session system-prompt APIs to use ordered string block arrays by requiring `buildSystemPrompt`, `CreateAgentSessionOptions.systemPrompt`, `Session.rebuildSystemPrompt`, and extension `before_agent_start`/`getSystemPrompt` hooks to accept and return `systemPrompt: string[]` instead of a plain system-prompt string or separate `projectPrompt` field
|
|
12
|
+
- Changed `buildSystemPrompt` and session `rebuildSystemPrompt` APIs to return `{ systemPrompt, projectPrompt }`, requiring callers expecting a plain system prompt string to update to the new shape
|
|
13
|
+
- Removed the top-level `sel` parameter from the `read` tool schema, requiring callers to migrate to `path`-embedded selectors (for example `path:50-100`, `path:raw`, or `https://...:L1-L40`)
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Added a separate `projectPrompt` artifact containing per-session project context (workstation, context files, AGENTS.md rules, workspace tree, and append prompt) so dynamic context is decoupled from the static system prompt
|
|
18
|
+
- Added `Project prompt` token accounting to context-usage breakdowns and charts
|
|
19
|
+
- Added `tools.elideFileMutationInputs` setting to optionally elide large `write`, `edit`, and `apply_patch` payloads in history after successful mutations
|
|
20
|
+
- Added hashline-style return data for elided `write` calls so tools can include the resulting file content without leaking full input text
|
|
21
|
+
- Added `buildDirectoryTree` and `DirectoryTree` exports to generate configurable directory trees with options for depth, entry limits, hidden-file handling, and truncation caps
|
|
22
|
+
- Added `buildWorkspaceTree` and `WorkspaceTree` exports so callers can precompute and pass a workspace context to prompt generation
|
|
23
|
+
- Added `workspaceTree` support to `buildSystemPrompt` options to reuse a prebuilt directory snapshot
|
|
24
|
+
- Added `read.summarize.enabled`, `read.summarize.minBodyLines`, and `read.summarize.minCommentLines` settings to control whether `read` returns structural summaries and how many multiline body/comment lines are collapsed
|
|
25
|
+
- Added `edit.hashlineAutoDropPureInsertDuplicates` setting to opt into dropping 2+ pure-insert hashline payload lines that duplicate adjacent file context; default is `false`.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Updated session dump and HTML export output to serialize ordered system-prompt blocks (including project context) and removed the dedicated project-prompt dump section
|
|
30
|
+
- Renamed context-usage system-prompt accounting from a separate `projectPrompt` bucket to `systemContext` to match the new multi-block prompt structure
|
|
31
|
+
- Changed prompt delivery to inject non-empty `projectPrompt` as a leading `developer` message before conversation messages instead of merging it into the base system prompt
|
|
32
|
+
- Added `projectPrompt` to session dumps to expose the injected per-session project context separately
|
|
33
|
+
- Changed write success output and preview rendering to display hashline-formatted written content from captured file text when mutation inputs are elided
|
|
34
|
+
- Changed `read` directory rendering to return a two-level recency-sorted directory tree (including nested folders) instead of a flat alphabetical entry list, while still applying configurable truncation
|
|
35
|
+
- Changed generated system prompts to include a working-directory tree block after directory context, showing recent files/directories (depth ≤ 3) and truncation notices when entries are elided
|
|
36
|
+
- Changed `read` summary rendering to merge opening- and closing-brace boundaries around elided sections into a single `..` line (including closers like `};` or `})`), reducing those segments to one concise anchored summary line
|
|
37
|
+
- Changed default `read` output for parseable code files without an explicit selector to return a structural summary instead of full verbatim lines, while still supporting full output for `:raw` and explicit ranges
|
|
38
|
+
- Changed truncation/pagination hints in read, archive, and SQLite outputs to use colon syntax (`Use :<offset>`) when continuing reads
|
|
39
|
+
- Changed the read tool UI preview title to include summary elision counts when a summary is returned
|
|
40
|
+
- Changed hashline pure-insert duplicate auto-drop to be opt-in through `edit.hashlineAutoDropPureInsertDuplicates` instead of always enabled.
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- Fixed selector parsing for colon-containing paths by only splitting `:<sel>` when the suffix matches a valid line-range or `raw` pattern, preventing paths like `db.sqlite:users:42` from being misread as selectors
|
|
45
|
+
|
|
46
|
+
## [14.6.6] - 2026-05-04
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
|
|
50
|
+
- Added Ctrl+D draft persistence: pressing Ctrl+D with text in the editor now exits the app and saves the unsent text as a per-session draft. Resuming the same session (e.g. via `--resume`) restores the draft into the editor (one-shot, removed after restore).
|
|
4
51
|
|
|
5
52
|
## [14.6.4] - 2026-05-03
|
|
6
53
|
### Added
|
|
@@ -94,7 +94,7 @@ export default function (pi: HookAPI) {
|
|
|
94
94
|
|
|
95
95
|
const response = await complete(
|
|
96
96
|
ctx.model!,
|
|
97
|
-
{ systemPrompt: SYSTEM_PROMPT, messages: [userMessage] },
|
|
97
|
+
{ systemPrompt: [SYSTEM_PROMPT], messages: [userMessage] },
|
|
98
98
|
{ apiKey, signal: loader.signal },
|
|
99
99
|
);
|
|
100
100
|
|
package/examples/hooks/qna.ts
CHANGED
|
@@ -85,7 +85,7 @@ export default function (pi: HookAPI) {
|
|
|
85
85
|
|
|
86
86
|
const response = await complete(
|
|
87
87
|
ctx.model!,
|
|
88
|
-
{ systemPrompt: SYSTEM_PROMPT, messages: [userMessage] },
|
|
88
|
+
{ systemPrompt: [SYSTEM_PROMPT], messages: [userMessage] },
|
|
89
89
|
{ apiKey, signal: loader.signal },
|
|
90
90
|
);
|
|
91
91
|
|
|
@@ -7,8 +7,10 @@ import { createAgentSession, SessionManager } from "@oh-my-pi/pi-coding-agent";
|
|
|
7
7
|
|
|
8
8
|
// Option 1: Replace prompt entirely
|
|
9
9
|
const { session: session1 } = await createAgentSession({
|
|
10
|
-
systemPrompt:
|
|
10
|
+
systemPrompt: [
|
|
11
|
+
`You are a helpful assistant that speaks like a pirate.
|
|
11
12
|
Always end responses with "Arrr!"`,
|
|
13
|
+
],
|
|
12
14
|
sessionManager: SessionManager.inMemory(),
|
|
13
15
|
});
|
|
14
16
|
|
|
@@ -24,11 +26,12 @@ console.log("\n");
|
|
|
24
26
|
|
|
25
27
|
// Option 2: Modify default prompt (receives default, returns modified)
|
|
26
28
|
const { session: session2 } = await createAgentSession({
|
|
27
|
-
systemPrompt: defaultPrompt =>
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
systemPrompt: defaultPrompt => [
|
|
30
|
+
...defaultPrompt,
|
|
31
|
+
`## Additional Instructions
|
|
30
32
|
- Always be concise
|
|
31
33
|
- Use bullet points when listing things`,
|
|
34
|
+
],
|
|
32
35
|
sessionManager: SessionManager.inMemory(),
|
|
33
36
|
});
|
|
34
37
|
|
package/examples/sdk/README.md
CHANGED
|
@@ -87,7 +87,7 @@ const { session } = await createAgentSession({
|
|
|
87
87
|
model,
|
|
88
88
|
authStorage: customAuth,
|
|
89
89
|
modelRegistry: customRegistry,
|
|
90
|
-
systemPrompt: "You are helpful.",
|
|
90
|
+
systemPrompt: ["You are helpful."],
|
|
91
91
|
toolNames: ["read", "bash"],
|
|
92
92
|
customTools: [{ tool: myTool }],
|
|
93
93
|
hooks: [{ factory: myHook }],
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
4
|
-
"version": "14.
|
|
4
|
+
"version": "14.7.0",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://github.com/can1357/oh-my-pi",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -46,12 +46,12 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@agentclientprotocol/sdk": "0.20.0",
|
|
48
48
|
"@mozilla/readability": "^0.6.0",
|
|
49
|
-
"@oh-my-pi/omp-stats": "14.
|
|
50
|
-
"@oh-my-pi/pi-agent-core": "14.
|
|
51
|
-
"@oh-my-pi/pi-ai": "14.
|
|
52
|
-
"@oh-my-pi/pi-natives": "14.
|
|
53
|
-
"@oh-my-pi/pi-tui": "14.
|
|
54
|
-
"@oh-my-pi/pi-utils": "14.
|
|
49
|
+
"@oh-my-pi/omp-stats": "14.7.0",
|
|
50
|
+
"@oh-my-pi/pi-agent-core": "14.7.0",
|
|
51
|
+
"@oh-my-pi/pi-ai": "14.7.0",
|
|
52
|
+
"@oh-my-pi/pi-natives": "14.7.0",
|
|
53
|
+
"@oh-my-pi/pi-tui": "14.7.0",
|
|
54
|
+
"@oh-my-pi/pi-utils": "14.7.0",
|
|
55
55
|
"@puppeteer/browsers": "^2.13.0",
|
|
56
56
|
"@sinclair/typebox": "^0.34.49",
|
|
57
57
|
"@xterm/headless": "^6.0.0",
|
|
@@ -356,54 +356,58 @@ export const createAutoresearchExtension: ExtensionFactory = api => {
|
|
|
356
356
|
? null
|
|
357
357
|
: "Heads up: you are not on a dedicated `autoresearch/*` branch. `log_experiment discard` will only revert run-modified files, not reset to baseline — so harness files written before `init_experiment` may not survive a discard. Clean the worktree and re-run `/autoresearch` if you want full revert safety.";
|
|
358
358
|
return {
|
|
359
|
-
systemPrompt:
|
|
360
|
-
|
|
359
|
+
systemPrompt: [
|
|
360
|
+
prompt.render(setupPromptTemplate, {
|
|
361
|
+
base_system_prompt: event.systemPrompt.join("\n\n"),
|
|
362
|
+
has_goal: goal.trim().length > 0,
|
|
363
|
+
goal,
|
|
364
|
+
working_dir: ctx.cwd,
|
|
365
|
+
has_branch: Boolean(currentBranch),
|
|
366
|
+
branch: currentBranch ?? "",
|
|
367
|
+
has_baseline_warning: baselineWarning !== null,
|
|
368
|
+
baseline_warning: baselineWarning ?? "",
|
|
369
|
+
}),
|
|
370
|
+
],
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
return {
|
|
374
|
+
systemPrompt: [
|
|
375
|
+
prompt.render(promptTemplate, {
|
|
376
|
+
base_system_prompt: event.systemPrompt.join("\n\n"),
|
|
361
377
|
has_goal: goal.trim().length > 0,
|
|
362
378
|
goal,
|
|
363
379
|
working_dir: ctx.cwd,
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
380
|
+
default_metric_name: state.metricName,
|
|
381
|
+
metric_name: state.metricName,
|
|
382
|
+
has_branch: Boolean(state.branch),
|
|
383
|
+
branch: state.branch,
|
|
384
|
+
has_baseline_commit: Boolean(state.baselineCommit),
|
|
385
|
+
baseline_commit: state.baselineCommit ? state.baselineCommit.slice(0, 12) : "",
|
|
386
|
+
has_notes: state.notes.trim().length > 0,
|
|
387
|
+
notes: state.notes,
|
|
388
|
+
current_segment: state.currentSegment + 1,
|
|
389
|
+
current_segment_run_count: currentSegmentResults.length,
|
|
390
|
+
has_baseline_metric: baselineMetric !== null,
|
|
391
|
+
baseline_metric_display: formatNum(baselineMetric, state.metricUnit),
|
|
392
|
+
baseline_run_number: baselineRunNumber,
|
|
393
|
+
has_best_result: bestResult !== null && bestMetric !== null,
|
|
394
|
+
best_metric_display: bestMetric !== null ? formatNum(bestMetric, state.metricUnit) : "-",
|
|
395
|
+
best_run_number: bestResult ? (bestResult.runNumber ?? state.results.indexOf(bestResult) + 1) : null,
|
|
396
|
+
has_recent_results: recentResults.length > 0,
|
|
397
|
+
recent_results: recentResults,
|
|
398
|
+
has_unjustified_runs: unjustifiedRuns.length > 0,
|
|
399
|
+
unjustified_runs: unjustifiedRuns,
|
|
400
|
+
has_pending_run: Boolean(pendingRun),
|
|
401
|
+
pending_run_number: pendingRun?.runNumber,
|
|
402
|
+
pending_run_command: pendingRun?.command,
|
|
403
|
+
pending_run_passed: pendingRun?.passed ?? false,
|
|
404
|
+
has_pending_run_metric: pendingRun?.parsedPrimary !== null && pendingRun?.parsedPrimary !== undefined,
|
|
405
|
+
pending_run_metric_display:
|
|
406
|
+
pendingRun?.parsedPrimary !== null && pendingRun?.parsedPrimary !== undefined
|
|
407
|
+
? formatNum(pendingRun.parsedPrimary, state.metricUnit)
|
|
408
|
+
: null,
|
|
368
409
|
}),
|
|
369
|
-
|
|
370
|
-
}
|
|
371
|
-
return {
|
|
372
|
-
systemPrompt: prompt.render(promptTemplate, {
|
|
373
|
-
base_system_prompt: event.systemPrompt,
|
|
374
|
-
has_goal: goal.trim().length > 0,
|
|
375
|
-
goal,
|
|
376
|
-
working_dir: ctx.cwd,
|
|
377
|
-
default_metric_name: state.metricName,
|
|
378
|
-
metric_name: state.metricName,
|
|
379
|
-
has_branch: Boolean(state.branch),
|
|
380
|
-
branch: state.branch,
|
|
381
|
-
has_baseline_commit: Boolean(state.baselineCommit),
|
|
382
|
-
baseline_commit: state.baselineCommit ? state.baselineCommit.slice(0, 12) : "",
|
|
383
|
-
has_notes: state.notes.trim().length > 0,
|
|
384
|
-
notes: state.notes,
|
|
385
|
-
current_segment: state.currentSegment + 1,
|
|
386
|
-
current_segment_run_count: currentSegmentResults.length,
|
|
387
|
-
has_baseline_metric: baselineMetric !== null,
|
|
388
|
-
baseline_metric_display: formatNum(baselineMetric, state.metricUnit),
|
|
389
|
-
baseline_run_number: baselineRunNumber,
|
|
390
|
-
has_best_result: bestResult !== null && bestMetric !== null,
|
|
391
|
-
best_metric_display: bestMetric !== null ? formatNum(bestMetric, state.metricUnit) : "-",
|
|
392
|
-
best_run_number: bestResult ? (bestResult.runNumber ?? state.results.indexOf(bestResult) + 1) : null,
|
|
393
|
-
has_recent_results: recentResults.length > 0,
|
|
394
|
-
recent_results: recentResults,
|
|
395
|
-
has_unjustified_runs: unjustifiedRuns.length > 0,
|
|
396
|
-
unjustified_runs: unjustifiedRuns,
|
|
397
|
-
has_pending_run: Boolean(pendingRun),
|
|
398
|
-
pending_run_number: pendingRun?.runNumber,
|
|
399
|
-
pending_run_command: pendingRun?.command,
|
|
400
|
-
pending_run_passed: pendingRun?.passed ?? false,
|
|
401
|
-
has_pending_run_metric: pendingRun?.parsedPrimary !== null && pendingRun?.parsedPrimary !== undefined,
|
|
402
|
-
pending_run_metric_display:
|
|
403
|
-
pendingRun?.parsedPrimary !== null && pendingRun?.parsedPrimary !== undefined
|
|
404
|
-
? formatNum(pendingRun.parsedPrimary, state.metricUnit)
|
|
405
|
-
: null,
|
|
406
|
-
}),
|
|
410
|
+
],
|
|
407
411
|
};
|
|
408
412
|
});
|
|
409
413
|
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read CLI command handler.
|
|
3
|
+
*
|
|
4
|
+
* Handles `omp read` — invokes the `read` agent tool against a path/URL and
|
|
5
|
+
* prints the resulting content blocks exactly as the model would receive them
|
|
6
|
+
* (including truncation/limit notices appended by the meta-notice wrapper).
|
|
7
|
+
*/
|
|
8
|
+
import { getProjectDir } from "@oh-my-pi/pi-utils";
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
import { Settings } from "../config/settings";
|
|
11
|
+
import type { ToolSession } from "../tools";
|
|
12
|
+
import { wrapToolWithMetaNotice } from "../tools/output-meta";
|
|
13
|
+
import { ReadTool } from "../tools/read";
|
|
14
|
+
import { renderError } from "../tools/tool-errors";
|
|
15
|
+
|
|
16
|
+
export interface ReadCommandArgs {
|
|
17
|
+
path: string;
|
|
18
|
+
timeout?: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function runReadCommand(cmd: ReadCommandArgs): Promise<void> {
|
|
22
|
+
if (!cmd.path) {
|
|
23
|
+
process.stderr.write(chalk.red("error: path is required\n"));
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const cwd = getProjectDir();
|
|
28
|
+
const settings = await Settings.init({ cwd });
|
|
29
|
+
|
|
30
|
+
const session: ToolSession = {
|
|
31
|
+
cwd,
|
|
32
|
+
hasUI: false,
|
|
33
|
+
settings,
|
|
34
|
+
getSessionFile: () => null,
|
|
35
|
+
getSessionSpawns: () => "*",
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const tool = wrapToolWithMetaNotice(new ReadTool(session));
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const result = await tool.execute("omp-read", { path: cmd.path, timeout: cmd.timeout });
|
|
42
|
+
|
|
43
|
+
for (const block of result.content) {
|
|
44
|
+
if (block.type === "text") {
|
|
45
|
+
process.stdout.write(block.text);
|
|
46
|
+
if (!block.text.endsWith("\n")) process.stdout.write("\n");
|
|
47
|
+
} else if (block.type === "image") {
|
|
48
|
+
const decodedBytes = Buffer.from(block.data, "base64").byteLength;
|
|
49
|
+
process.stdout.write(
|
|
50
|
+
chalk.dim(`[image content: ${block.mimeType}, ${decodedBytes} bytes base64-decoded]\n`),
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} catch (err) {
|
|
55
|
+
process.stderr.write(`${chalk.red(renderError(err))}\n`);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
}
|
package/src/cli.ts
CHANGED
|
@@ -53,6 +53,7 @@ const commands: CommandEntry[] = [
|
|
|
53
53
|
{ name: "plugin", load: () => import("./commands/plugin").then(m => m.default) },
|
|
54
54
|
{ name: "setup", load: () => import("./commands/setup").then(m => m.default) },
|
|
55
55
|
{ name: "shell", load: () => import("./commands/shell").then(m => m.default) },
|
|
56
|
+
{ name: "read", load: () => import("./commands/read").then(m => m.default) },
|
|
56
57
|
{ name: "ssh", load: () => import("./commands/ssh").then(m => m.default) },
|
|
57
58
|
{ name: "stats", load: () => import("./commands/stats").then(m => m.default) },
|
|
58
59
|
{ name: "update", load: () => import("./commands/update").then(m => m.default) },
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Show what the read tool will return for a given path.
|
|
3
|
+
*/
|
|
4
|
+
import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
|
|
5
|
+
import { type ReadCommandArgs, runReadCommand } from "../cli/read-cli";
|
|
6
|
+
import { initTheme } from "../modes/theme/theme";
|
|
7
|
+
|
|
8
|
+
export default class Read extends Command {
|
|
9
|
+
static description = "Show what the read tool will return for a path or URL";
|
|
10
|
+
|
|
11
|
+
static args = {
|
|
12
|
+
path: Args.string({
|
|
13
|
+
description: "Path or URL to read (append :sel for line ranges or raw mode, e.g. src/foo.ts:50-100)",
|
|
14
|
+
required: true,
|
|
15
|
+
}),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
static flags = {
|
|
19
|
+
timeout: Flags.integer({ description: "Request timeout in seconds (URLs only)" }),
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
static examples = [
|
|
23
|
+
"omp read src/foo.ts",
|
|
24
|
+
"omp read src/foo.ts:50-100",
|
|
25
|
+
"omp read src/foo.ts:raw",
|
|
26
|
+
"omp read https://example.com",
|
|
27
|
+
"omp read path/to/archive.zip:dir/file.ts",
|
|
28
|
+
"omp read path/to/db.sqlite:users:42",
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
async run(): Promise<void> {
|
|
32
|
+
const { args, flags } = await this.parse(Read);
|
|
33
|
+
const cmd: ReadCommandArgs = {
|
|
34
|
+
path: args.path ?? "",
|
|
35
|
+
timeout: flags.timeout,
|
|
36
|
+
};
|
|
37
|
+
await initTheme();
|
|
38
|
+
await runReadCommand(cmd);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -60,7 +60,7 @@ export async function runCommitAgentSession(input: CommitAgentInput): Promise<Co
|
|
|
60
60
|
settings: input.settings,
|
|
61
61
|
model: input.model,
|
|
62
62
|
thinkingLevel: input.thinkingLevel,
|
|
63
|
-
systemPrompt,
|
|
63
|
+
systemPrompt: [systemPrompt],
|
|
64
64
|
customTools: tools,
|
|
65
65
|
enableLsp: false,
|
|
66
66
|
enableMCP: false,
|
|
@@ -89,7 +89,7 @@ export async function generateConventionalAnalysis({
|
|
|
89
89
|
const response = await completeSimple(
|
|
90
90
|
model,
|
|
91
91
|
{
|
|
92
|
-
systemPrompt: prompt.render(analysisSystemPrompt),
|
|
92
|
+
systemPrompt: [prompt.render(analysisSystemPrompt)],
|
|
93
93
|
messages: [{ role: "user", content: userContent, timestamp: Date.now() }],
|
|
94
94
|
tools: [ConventionalAnalysisTool],
|
|
95
95
|
},
|
|
@@ -58,7 +58,7 @@ export async function generateChangelogEntries({
|
|
|
58
58
|
const response = await completeSimple(
|
|
59
59
|
model,
|
|
60
60
|
{
|
|
61
|
-
systemPrompt: prompt.render(changelogSystemPrompt),
|
|
61
|
+
systemPrompt: [prompt.render(changelogSystemPrompt)],
|
|
62
62
|
messages: [{ role: "user", content: userContent, timestamp: Date.now() }],
|
|
63
63
|
tools: [changelogTool],
|
|
64
64
|
},
|
|
@@ -76,7 +76,7 @@ export async function runReducePhase({
|
|
|
76
76
|
const response = await completeSimple(
|
|
77
77
|
model,
|
|
78
78
|
{
|
|
79
|
-
systemPrompt: prompt.render(reduceSystemPrompt),
|
|
79
|
+
systemPrompt: [prompt.render(reduceSystemPrompt)],
|
|
80
80
|
messages: [{ role: "user", content: userContent, timestamp: Date.now() }],
|
|
81
81
|
tools: [ReduceTool],
|
|
82
82
|
},
|
|
@@ -1419,6 +1419,15 @@ export const SETTINGS_SCHEMA = {
|
|
|
1419
1419
|
},
|
|
1420
1420
|
},
|
|
1421
1421
|
|
|
1422
|
+
"edit.hashlineAutoDropPureInsertDuplicates": {
|
|
1423
|
+
type: "boolean",
|
|
1424
|
+
default: false,
|
|
1425
|
+
ui: {
|
|
1426
|
+
tab: "editing",
|
|
1427
|
+
label: "Hashline Duplicate Insert Drop",
|
|
1428
|
+
description: "Drop 2+ pure-insert payload lines that duplicate adjacent file context",
|
|
1429
|
+
},
|
|
1430
|
+
},
|
|
1422
1431
|
"edit.blockAutoGenerated": {
|
|
1423
1432
|
type: "boolean",
|
|
1424
1433
|
default: true,
|
|
@@ -1466,6 +1475,36 @@ export const SETTINGS_SCHEMA = {
|
|
|
1466
1475
|
},
|
|
1467
1476
|
},
|
|
1468
1477
|
|
|
1478
|
+
"read.summarize.enabled": {
|
|
1479
|
+
type: "boolean",
|
|
1480
|
+
default: true,
|
|
1481
|
+
ui: {
|
|
1482
|
+
tab: "editing",
|
|
1483
|
+
label: "Read Summaries",
|
|
1484
|
+
description: "Return structural code summaries when read is called without an explicit selector",
|
|
1485
|
+
},
|
|
1486
|
+
},
|
|
1487
|
+
|
|
1488
|
+
"read.summarize.minBodyLines": {
|
|
1489
|
+
type: "number",
|
|
1490
|
+
default: 4,
|
|
1491
|
+
ui: {
|
|
1492
|
+
tab: "editing",
|
|
1493
|
+
label: "Read Summary Body Lines",
|
|
1494
|
+
description: "Minimum multiline body or literal length before read summaries collapse it",
|
|
1495
|
+
},
|
|
1496
|
+
},
|
|
1497
|
+
|
|
1498
|
+
"read.summarize.minCommentLines": {
|
|
1499
|
+
type: "number",
|
|
1500
|
+
default: 6,
|
|
1501
|
+
ui: {
|
|
1502
|
+
tab: "editing",
|
|
1503
|
+
label: "Read Summary Comment Lines",
|
|
1504
|
+
description: "Minimum multiline block comment length before read summaries collapse it",
|
|
1505
|
+
},
|
|
1506
|
+
},
|
|
1507
|
+
|
|
1469
1508
|
"read.toolResultPreview": {
|
|
1470
1509
|
type: "boolean",
|
|
1471
1510
|
default: false,
|
package/src/edit/line-hash.ts
CHANGED
|
@@ -783,18 +783,48 @@ export const HL_BODY_SEP = "|";
|
|
|
783
783
|
export const HL_BODY_SEP_RE_RAW = regexEscape(HL_BODY_SEP);
|
|
784
784
|
|
|
785
785
|
const RE_SIGNIFICANT = /[\p{L}\p{N}]/u;
|
|
786
|
+
const RE_STRUCTURAL_STRIP = /[\s{}]/g;
|
|
787
|
+
|
|
788
|
+
/**
|
|
789
|
+
* Bigram returned for lines that contain only whitespace and `{`/`}`.
|
|
790
|
+
* Picks the English ordinal suffix for the line number (`1` → `st`,
|
|
791
|
+
* `2` → `nd`, `3` → `rd`, `11`/`12`/`13` → `th`, else `th`) so the
|
|
792
|
+
* line digits + bigram BPE-merge into a single ordinal token (`1st`, `42nd`,
|
|
793
|
+
* `100th`, …). Brace-only lines therefore cost one token for the whole
|
|
794
|
+
* `LINE+ID` anchor instead of two.
|
|
795
|
+
*/
|
|
796
|
+
function structuralBigram(line: number): string {
|
|
797
|
+
const mod100 = line % 100;
|
|
798
|
+
if (mod100 >= 11 && mod100 <= 13) return "th";
|
|
799
|
+
switch (line % 10) {
|
|
800
|
+
case 1:
|
|
801
|
+
return "st";
|
|
802
|
+
case 2:
|
|
803
|
+
return "nd";
|
|
804
|
+
case 3:
|
|
805
|
+
return "rd";
|
|
806
|
+
default:
|
|
807
|
+
return "th";
|
|
808
|
+
}
|
|
809
|
+
}
|
|
786
810
|
|
|
787
811
|
/**
|
|
788
812
|
* Compute a 2-character hash of a single line via xxHash32 mod 647 over
|
|
789
|
-
* {@link HL_BIGRAMS}. Lines
|
|
790
|
-
*
|
|
791
|
-
*
|
|
792
|
-
*
|
|
813
|
+
* {@link HL_BIGRAMS}. Lines that contain only whitespace and `{`/`}` collapse
|
|
814
|
+
* to an ordinal-suffix bigram (see {@link structuralBigram}) so brace-only
|
|
815
|
+
* structure shares one merged ordinal token (`1st`, `42nd`, `100th`, …).
|
|
816
|
+
* Other lines with no letter or digit mix the line number into the seed so
|
|
817
|
+
* adjacent identical punctuation-only lines get distinct hashes; lines with
|
|
818
|
+
* significant content stay line-number-independent so a line is identifiable
|
|
819
|
+
* across small shifts.
|
|
793
820
|
*
|
|
794
821
|
* The line input should not include a trailing newline.
|
|
795
822
|
*/
|
|
796
823
|
export function computeLineHash(idx: number, line: string): string {
|
|
797
824
|
line = line.replace(/\r/g, "").trimEnd();
|
|
825
|
+
if (line.replace(RE_STRUCTURAL_STRIP, "").length === 0) {
|
|
826
|
+
return structuralBigram(idx);
|
|
827
|
+
}
|
|
798
828
|
const seed = RE_SIGNIFICANT.test(line) ? 0 : idx;
|
|
799
829
|
return HL_BIGRAMS[Bun.hash.xxHash32(line, seed) % HL_BIGRAMS_COUNT];
|
|
800
830
|
}
|