@oh-my-pi/pi-coding-agent 15.5.7 → 15.5.9
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 +53 -1
- package/dist/types/cli/auth-gateway-cli.d.ts +8 -0
- package/dist/types/commands/auth-gateway.d.ts +3 -0
- package/dist/types/config/settings-schema.d.ts +10 -10
- package/dist/types/edit/file-snapshot-store.d.ts +9 -6
- package/dist/types/edit/hashline/diff.d.ts +4 -5
- package/dist/types/edit/streaming.d.ts +2 -1
- package/dist/types/eval/py/index.d.ts +1 -0
- package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
- package/dist/types/extensibility/shared-events.d.ts +1 -1
- package/dist/types/internal-urls/index.d.ts +1 -0
- package/dist/types/internal-urls/vault-protocol.d.ts +93 -0
- package/dist/types/mcp/transports/http.d.ts +9 -0
- package/dist/types/modes/components/tool-execution.d.ts +2 -1
- package/dist/types/session/agent-session.d.ts +3 -1
- package/dist/types/tools/match-line-format.d.ts +2 -2
- package/dist/types/tools/render-utils.d.ts +3 -1
- package/dist/types/tools/write.d.ts +2 -0
- package/dist/types/utils/file-mentions.d.ts +2 -0
- package/package.json +8 -8
- package/src/cli/args.ts +2 -0
- package/src/cli/auth-broker-cli.ts +2 -1
- package/src/cli/auth-gateway-cli.ts +210 -9
- package/src/commands/auth-gateway.ts +7 -1
- package/src/config/settings-schema.ts +12 -11
- package/src/edit/file-snapshot-store.ts +9 -6
- package/src/edit/hashline/diff.ts +26 -13
- package/src/edit/hashline/execute.ts +13 -9
- package/src/edit/renderer.ts +9 -9
- package/src/edit/streaming.ts +4 -6
- package/src/eval/py/index.ts +1 -1
- package/src/extensibility/custom-tools/types.ts +1 -1
- package/src/extensibility/shared-events.ts +1 -1
- package/src/internal-urls/docs-index.generated.ts +7 -7
- package/src/internal-urls/index.ts +1 -0
- package/src/internal-urls/router.ts +2 -0
- package/src/internal-urls/vault-protocol.ts +936 -0
- package/src/main.ts +1 -2
- package/src/mcp/transports/http.ts +29 -2
- package/src/modes/components/tool-execution.ts +6 -4
- package/src/modes/controllers/event-controller.ts +10 -3
- package/src/modes/interactive-mode.ts +10 -2
- package/src/modes/utils/ui-helpers.ts +2 -1
- package/src/prompts/system/system-prompt.md +3 -0
- package/src/prompts/tools/ast-edit.md +1 -1
- package/src/prompts/tools/ast-grep.md +1 -1
- package/src/prompts/tools/read.md +3 -3
- package/src/prompts/tools/search.md +1 -1
- package/src/sdk.ts +26 -1
- package/src/session/agent-session.ts +82 -11
- package/src/system-prompt.ts +2 -0
- package/src/tools/ast-edit.ts +10 -7
- package/src/tools/ast-grep.ts +12 -11
- package/src/tools/eval.ts +28 -3
- package/src/tools/match-line-format.ts +2 -2
- package/src/tools/path-utils.ts +2 -0
- package/src/tools/plan-mode-guard.ts +6 -1
- package/src/tools/read.ts +70 -55
- package/src/tools/render-utils.ts +15 -0
- package/src/tools/search.ts +12 -12
- package/src/tools/write.ts +61 -6
- package/src/utils/file-mentions.ts +11 -5
- package/src/web/search/providers/codex.ts +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,58 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [15.5.8] - 2026-05-28
|
|
6
|
+
|
|
7
|
+
### Breaking Changes
|
|
8
|
+
|
|
9
|
+
- Changed hashline edit parsing to require wrapped hunk headers such as `@@ A..B @@` (including `@@ BOF @@` and `@@ EOF @@`), with empty `@@ A..B @@` blocks deleting the anchored range and legacy inline payload forms treated as malformed
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Added `vault.enabled` setting (Tools → Obsidian Vault, default `false`) gating the `vault://` internal URL. When disabled, `VaultProtocolHandler.resolve` / `write`, `resolveVaultUrlToPath`, and `hasObsidian()` all refuse — the latter hides the `vault://` entry from the system prompt's Handlebars `{{#if hasObsidian}}` block. Tests can opt in via `vi.spyOn(vaultProtocol, "isVaultEnabled").mockReturnValue(true)`.
|
|
14
|
+
|
|
15
|
+
- Added support for `vault://` URLs in path resolution utilities, including plan mode and internal selector parsing so `read` and edit paths can target Obsidian vault files directly
|
|
16
|
+
- Added `vault://` internal URLs for editable Obsidian vault files, with filesystem-backed read/write/listing and CLI-backed vault index operations.
|
|
17
|
+
- Added strict-mode indicators to `omp auth-gateway check` output by appending `[strict]` to strict-mode text headers and adding a top-level `strict` field in `--json` output
|
|
18
|
+
- `omp auth-gateway check --strict` exercises each broker-supplied credential against its provider's chat-completion endpoint (cheapest bundled chat model per provider, with 15s/attempt timeout and up to 4 catalog fall-throughs on "model not found / invalid model" errors). Surfaces failures where the usage endpoint reports 200 but the chat endpoint 401s the same bearer (revoked OAuth scope, mislabeled provider row, …). Output gains a `[chat: ok|FAIL|skip]` column in text mode and a `completion` field on each credential in `--json` mode; the chat-failed count contributes to the non-zero exit code.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- Changed hashline apply behavior to preserve duplicated boundary and context lines in replacement and insert payloads instead of auto-absorbing or dropping them
|
|
23
|
+
- Updated hashline syntax: replaced `↑`/`↓` payload sigils with `^` repeat syntax and `|` literal rows for clearer edit semantics
|
|
24
|
+
- Changed hashline delete syntax from bare `A:` or `A-B:` to explicit `A-B:-` inline delete marker
|
|
25
|
+
- Modified hashline anchor syntax to require explicit range notation `A-B:` instead of shorthand `A:` for single-line operations
|
|
26
|
+
- Updated hashline description in settings to clarify pure insert context behavior without arrow notation
|
|
27
|
+
|
|
28
|
+
### Removed
|
|
29
|
+
|
|
30
|
+
- Removed the `edit.hashlineAutoDropPureInsertDuplicates` setting
|
|
31
|
+
- Removed the `edit.hashlineAutoDropPureInsertDuplicates` setting from configuration and execution paths
|
|
32
|
+
- Removed the `edit.hashlineAutoDropPureInsertDuplicates` setting
|
|
33
|
+
- Removed the `edit.hashlineAutoDropPureInsertDuplicates` setting from configuration and execution paths
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- Fixed agent yielding silently on `response.incomplete` (OpenAI Responses / Codex `stopReason: "length"`). The agent now treats output-side incompletion as a recovery case: drops the truncated/reasoning-only assistant turn, attempts context promotion to a larger model, and falls back to compaction or handoff. `AutoCompactionStartEvent.reason` and the custom-tool `auto_compaction_start.trigger` discriminator gain an `"incomplete"` value. The handoff strategy is honored for `"incomplete"` (unlike `"overflow"`, where the input is broken and handoff would hit the same wall).
|
|
38
|
+
- Fixed `eval` tool to resize large displayed images and append dimension notes to text output
|
|
39
|
+
- Fixed `write` tool to strip malformed or loose hashline section headers before writing file content
|
|
40
|
+
- Fixed `eval` tool image rendering to resize displayed images before returning them and append image-dimension notes to text output
|
|
41
|
+
- Fixed `write` tool output sanitation to strip malformed or loose hashline section headers before writing file content
|
|
42
|
+
- Fixed `omp auth-broker serve` crashing at startup with `logger.setTransports is not a function` — switched the call site to `import { setTransports } from "@oh-my-pi/pi-utils/logger"`, bypassing the `logger` namespace re-export that some Bun versions failed to expose at runtime
|
|
43
|
+
- Fixed `omp auth-gateway` returning `502 upstream_error` and refusing to rotate credentials when a provider responded with a non-401 usage-limit error (Codex `usage_limit_reached`, Anthropic `usage_limit_reached`, Google `resource_exhausted`). `classifyGatewayError` now reuses `pi-ai`'s central `isUsageLimitError` heuristic and reports those failures as `429 rate_limit_error`. `streamSimple`'s pre-emit retry hook fires on usage-limit phrasing in addition to HTTP 401; the gateway's refresh callback branches on the error type and calls `AuthStorage.markUsageLimitReached(provider, sessionId, { retryAfterMs })` — temporarily blocking just the exhausted credential and surfacing the next sibling — instead of `invalidateCredentialMatching`, which would have suspect/deleted the row. The same branching is wired into the coding-agent `streamFn` callback so subscription multi-account rotation works the same on both surfaces.
|
|
44
|
+
- Fixed `extractRetryHint` not recognising Codex's `Try again in ~N min.` / `… hour` / `… hours` phrasing, which left the gateway and TUI without a server-suggested retry window when an upstream account hit its usage cap. The shared `try again in` pattern now accepts `min`, `minutes`, `mins`, `h`, `hr`, `hour`, `hours` units in addition to `ms` / `s` / `sec`, and tolerates a leading `~` and embedded whitespace.
|
|
45
|
+
- Fixed the auth-gateway threading `sessionId: undefined` into `AuthStorage.getApiKey`, which left `#sessionLastCredential` empty and made `markUsageLimitReached` a no-op for gateway-mediated requests. Both `/v1/chat/completions`-style endpoints and the `/v1/pi/stream` fast path now derive a stable `sessionId` from the client's `prompt_cache_key` (or the existing model+system+tools+first-message hash when absent) and reuse the same identity for credential-stickiness and prefix-cache routing.
|
|
46
|
+
- Fixed `eval` tool to resize large displayed images and append dimension notes to text output
|
|
47
|
+
- Fixed `write` tool to strip malformed or loose hashline section headers before writing file content
|
|
48
|
+
- Fixed `eval` tool image rendering to resize displayed images before returning them and append image-dimension notes to text output
|
|
49
|
+
- Fixed `write` tool output sanitation to strip malformed or loose hashline section headers before writing file content
|
|
50
|
+
- Fixed `omp auth-broker serve` crashing at startup with `logger.setTransports is not a function` — switched the call site to `import { setTransports } from "@oh-my-pi/pi-utils/logger"`, bypassing the `logger` namespace re-export that some Bun versions failed to expose at runtime
|
|
51
|
+
- Fixed user shortcut Python execution to namespace session IDs like eval, so both paths share one kernel
|
|
52
|
+
|
|
53
|
+
### Security
|
|
54
|
+
|
|
55
|
+
- Secured `vault://` reads and writes by validating URL paths and blocking traversal, absolute paths, and symlink escapes outside the selected vault root
|
|
56
|
+
|
|
5
57
|
## [15.5.7] - 2026-05-27
|
|
6
58
|
### Added
|
|
7
59
|
- `providers.openrouterVariant` setting (Settings → Providers → "OpenRouter Routing") to default OpenRouter requests to a routing-variant suffix (`:nitro`, `:floor`, `:online`, `:exacto`). Selectors that already name a variant (e.g. `openrouter/anthropic/claude-haiku:nitro`) keep precedence.
|
|
@@ -8887,4 +8939,4 @@ Initial public release.
|
|
|
8887
8939
|
- Git branch display in footer
|
|
8888
8940
|
- Message queueing during streaming responses
|
|
8889
8941
|
- OAuth integration for Gmail and Google Calendar access
|
|
8890
|
-
- HTML export with syntax highlighting and collapsible sections
|
|
8942
|
+
- HTML export with syntax highlighting and collapsible sections
|
|
@@ -11,6 +11,14 @@ export interface AuthGatewayCommandArgs {
|
|
|
11
11
|
* to wire token-paste plumbing into every local client.
|
|
12
12
|
*/
|
|
13
13
|
noAuth?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Strict mode for `check` — additionally exercise every credential
|
|
16
|
+
* against its provider's chat-completion endpoint. The usage probe (run
|
|
17
|
+
* unconditionally) can pass while the chat endpoint still 401s the same
|
|
18
|
+
* bearer, so strict mode is the definitive "is this credential
|
|
19
|
+
* actually usable" signal. Slower and consumes a tiny amount of quota.
|
|
20
|
+
*/
|
|
21
|
+
strict?: boolean;
|
|
14
22
|
};
|
|
15
23
|
}
|
|
16
24
|
declare const ACTIONS: readonly AuthGatewayAction[];
|
|
@@ -26,6 +26,9 @@ export default class AuthGateway extends Command {
|
|
|
26
26
|
"no-auth": import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
|
|
27
27
|
description: string;
|
|
28
28
|
};
|
|
29
|
+
strict: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
|
|
30
|
+
description: string;
|
|
31
|
+
};
|
|
29
32
|
};
|
|
30
33
|
static examples: string[];
|
|
31
34
|
run(): Promise<void>;
|
|
@@ -1918,15 +1918,6 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
1918
1918
|
readonly description: "Abort streaming edit tool calls when patch preview fails";
|
|
1919
1919
|
};
|
|
1920
1920
|
};
|
|
1921
|
-
readonly "edit.hashlineAutoDropPureInsertDuplicates": {
|
|
1922
|
-
readonly type: "boolean";
|
|
1923
|
-
readonly default: false;
|
|
1924
|
-
readonly ui: {
|
|
1925
|
-
readonly tab: "editing";
|
|
1926
|
-
readonly label: "Hashline Duplicate Insert Drop";
|
|
1927
|
-
readonly description: "Drop payload lines that duplicate adjacent file context \u2014 2+-line context echoes on `\u2191`/`\u2193` inserts, and a single boundary line at either edge of an `A-B:` replacement";
|
|
1928
|
-
};
|
|
1929
|
-
};
|
|
1930
1921
|
readonly "edit.blockAutoGenerated": {
|
|
1931
1922
|
readonly type: "boolean";
|
|
1932
1923
|
readonly default: true;
|
|
@@ -1951,7 +1942,7 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
1951
1942
|
readonly ui: {
|
|
1952
1943
|
readonly tab: "editing";
|
|
1953
1944
|
readonly label: "Hash Lines";
|
|
1954
|
-
readonly description: "Include
|
|
1945
|
+
readonly description: "Include snapshot-tag headers and line numbers in read output for hashline edit mode (\u00B6PATH#tag plus LINE:content)";
|
|
1955
1946
|
};
|
|
1956
1947
|
};
|
|
1957
1948
|
readonly "read.defaultLimit": {
|
|
@@ -2438,6 +2429,15 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
2438
2429
|
readonly description: "Allow the read tool to fetch and process URLs";
|
|
2439
2430
|
};
|
|
2440
2431
|
};
|
|
2432
|
+
readonly "vault.enabled": {
|
|
2433
|
+
readonly type: "boolean";
|
|
2434
|
+
readonly default: false;
|
|
2435
|
+
readonly ui: {
|
|
2436
|
+
readonly tab: "tools";
|
|
2437
|
+
readonly label: "Obsidian Vault";
|
|
2438
|
+
readonly description: "Enable the vault:// internal URL for reading and editing Obsidian vault content via the Obsidian CLI. When disabled, vault:// resolution is refused and the vault:// entry is omitted from the system prompt.";
|
|
2439
|
+
};
|
|
2440
|
+
};
|
|
2441
2441
|
readonly "github.enabled": {
|
|
2442
2442
|
readonly type: "boolean";
|
|
2443
2443
|
readonly default: false;
|
|
@@ -2,17 +2,20 @@
|
|
|
2
2
|
* Session-bound file snapshot store.
|
|
3
3
|
*
|
|
4
4
|
* Used by `read` and `search` to record exactly what the model saw, and by
|
|
5
|
-
* the hashline patcher to recover from stale section
|
|
6
|
-
* externally between read and edit, or a prior in-session edit
|
|
7
|
-
* the
|
|
5
|
+
* the hashline patcher to verify or recover from stale section tags (file
|
|
6
|
+
* changed externally between read and edit, or a prior in-session edit
|
|
7
|
+
* advanced the tag). The store is the {@link InMemorySnapshotStore}
|
|
8
8
|
* from `@oh-my-pi/hashline`; the only coding-agent-specific concern here
|
|
9
|
-
* is wiring it onto the per-session
|
|
9
|
+
* is wiring it onto the per-session owner object.
|
|
10
10
|
*/
|
|
11
11
|
import { InMemorySnapshotStore } from "@oh-my-pi/hashline";
|
|
12
|
-
|
|
12
|
+
interface FileSnapshotStoreOwner {
|
|
13
|
+
fileSnapshotStore?: InMemorySnapshotStore;
|
|
14
|
+
}
|
|
13
15
|
/**
|
|
14
16
|
* Look up (or lazily create) the file snapshot store attached to a session.
|
|
15
17
|
* Storage lives on `session.fileSnapshotStore` so it ages out exactly with
|
|
16
18
|
* the session itself.
|
|
17
19
|
*/
|
|
18
|
-
export declare function getFileSnapshotStore(session:
|
|
20
|
+
export declare function getFileSnapshotStore(session: FileSnapshotStoreOwner): InMemorySnapshotStore;
|
|
21
|
+
export {};
|
|
@@ -5,13 +5,12 @@
|
|
|
5
5
|
* pair to {@link generateDiffString} so the renderer can show the diff
|
|
6
6
|
* while the tool call is still streaming.
|
|
7
7
|
*
|
|
8
|
-
* Validation is intentionally light: only the section
|
|
8
|
+
* Validation is intentionally light: only the section snapshot tag is checked
|
|
9
9
|
* (so the preview goes red when anchors are stale), no plan-mode guards
|
|
10
10
|
* and no auto-generated-file refusal — those belong on the write path.
|
|
11
11
|
*/
|
|
12
|
-
import { type PatchSection } from "@oh-my-pi/hashline";
|
|
12
|
+
import { type PatchSection, type SnapshotStore } from "@oh-my-pi/hashline";
|
|
13
13
|
export interface HashlineDiffOptions {
|
|
14
|
-
autoDropPureInsertDuplicates?: boolean;
|
|
15
14
|
/**
|
|
16
15
|
* Use the streaming-tolerant applier ({@link PatchSection.applyPartialTo})
|
|
17
16
|
* so trailing in-flight ops do not throw or emit phantom edits. Streaming
|
|
@@ -19,7 +18,7 @@ export interface HashlineDiffOptions {
|
|
|
19
18
|
*/
|
|
20
19
|
streaming?: boolean;
|
|
21
20
|
}
|
|
22
|
-
export declare function computeHashlineSectionDiff(section: PatchSection, cwd: string, options?: HashlineDiffOptions): Promise<{
|
|
21
|
+
export declare function computeHashlineSectionDiff(section: PatchSection, cwd: string, snapshots: SnapshotStore, options?: HashlineDiffOptions): Promise<{
|
|
23
22
|
diff: string;
|
|
24
23
|
firstChangedLine: number | undefined;
|
|
25
24
|
} | {
|
|
@@ -27,7 +26,7 @@ export declare function computeHashlineSectionDiff(section: PatchSection, cwd: s
|
|
|
27
26
|
}>;
|
|
28
27
|
export declare function computeHashlineDiff(input: {
|
|
29
28
|
input: string;
|
|
30
|
-
}, cwd: string, options?: HashlineDiffOptions): Promise<{
|
|
29
|
+
}, cwd: string, snapshots: SnapshotStore, options?: HashlineDiffOptions): Promise<{
|
|
31
30
|
diff: string;
|
|
32
31
|
firstChangedLine: number | undefined;
|
|
33
32
|
} | {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* The shared renderer / `ToolExecutionComponent` consult the strategy via
|
|
13
13
|
* the injected `editMode` rather than probing argument shape.
|
|
14
14
|
*/
|
|
15
|
+
import { type SnapshotStore } from "@oh-my-pi/hashline";
|
|
15
16
|
import type { Theme } from "../modes/theme/theme";
|
|
16
17
|
import { type EditMode, resolveEditMode } from "../utils/edit-mode";
|
|
17
18
|
export interface PerFileDiffPreview {
|
|
@@ -23,9 +24,9 @@ export interface PerFileDiffPreview {
|
|
|
23
24
|
export interface StreamingDiffContext {
|
|
24
25
|
cwd: string;
|
|
25
26
|
signal: AbortSignal;
|
|
27
|
+
snapshots: SnapshotStore;
|
|
26
28
|
fuzzyThreshold?: number;
|
|
27
29
|
allowFuzzy?: boolean;
|
|
28
|
-
hashlineAutoDropPureInsertDuplicates?: boolean;
|
|
29
30
|
/**
|
|
30
31
|
* True while the tool's arguments are still streaming in. Strategies that
|
|
31
32
|
* accept free-form text input (apply_patch, hashline) trim the trailing
|
|
@@ -85,7 +85,7 @@ export type CustomToolSessionEvent = {
|
|
|
85
85
|
previousSessionFile: string | undefined;
|
|
86
86
|
} | {
|
|
87
87
|
reason: "auto_compaction_start";
|
|
88
|
-
trigger: "threshold" | "overflow" | "idle";
|
|
88
|
+
trigger: "threshold" | "overflow" | "idle" | "incomplete";
|
|
89
89
|
action: "context-full" | "handoff";
|
|
90
90
|
} | {
|
|
91
91
|
reason: "auto_compaction_end";
|
|
@@ -159,7 +159,7 @@ export interface TurnEndEvent {
|
|
|
159
159
|
/** Fired when auto-compaction starts */
|
|
160
160
|
export interface AutoCompactionStartEvent {
|
|
161
161
|
type: "auto_compaction_start";
|
|
162
|
-
reason: "threshold" | "overflow" | "idle";
|
|
162
|
+
reason: "threshold" | "overflow" | "idle" | "incomplete";
|
|
163
163
|
action: "context-full" | "handoff";
|
|
164
164
|
}
|
|
165
165
|
/** Fired when auto-compaction ends */
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { InternalResource, InternalUrl, ProtocolHandler, ResolveContext, WriteContext } from "./types";
|
|
2
|
+
type ContentType = InternalResource["contentType"];
|
|
3
|
+
type VaultParamValue = string | true;
|
|
4
|
+
type VaultParams = Record<string, VaultParamValue>;
|
|
5
|
+
type FileOp = "outline" | "backlinks" | "links" | "tags" | "properties" | "tasks" | "wordcount" | "history" | "base";
|
|
6
|
+
type VaultOp = "search" | "daily" | "daily-path" | "tags" | "tag" | "tasks" | "orphans" | "unresolved" | "deadends" | "bases" | "bookmarks" | "recents" | "templates" | "aliases" | "properties" | "property";
|
|
7
|
+
export interface VaultReference {
|
|
8
|
+
vault: string | null;
|
|
9
|
+
active: boolean;
|
|
10
|
+
forwardVault: boolean;
|
|
11
|
+
display: string;
|
|
12
|
+
}
|
|
13
|
+
export type ParsedVaultUrl = {
|
|
14
|
+
kind: "list-vaults";
|
|
15
|
+
url: string;
|
|
16
|
+
params: VaultParams;
|
|
17
|
+
} | {
|
|
18
|
+
kind: "vault-info";
|
|
19
|
+
url: string;
|
|
20
|
+
ref: VaultReference;
|
|
21
|
+
params: VaultParams;
|
|
22
|
+
} | {
|
|
23
|
+
kind: "fs-dir";
|
|
24
|
+
url: string;
|
|
25
|
+
ref: VaultReference;
|
|
26
|
+
relativePath: string;
|
|
27
|
+
params: VaultParams;
|
|
28
|
+
} | {
|
|
29
|
+
kind: "fs-file";
|
|
30
|
+
url: string;
|
|
31
|
+
ref: VaultReference;
|
|
32
|
+
relativePath: string;
|
|
33
|
+
params: VaultParams;
|
|
34
|
+
} | {
|
|
35
|
+
kind: "file-op";
|
|
36
|
+
url: string;
|
|
37
|
+
ref: VaultReference;
|
|
38
|
+
relativePath: string;
|
|
39
|
+
op: FileOp;
|
|
40
|
+
params: VaultParams;
|
|
41
|
+
} | {
|
|
42
|
+
kind: "vault-op";
|
|
43
|
+
url: string;
|
|
44
|
+
ref: VaultReference;
|
|
45
|
+
op: VaultOp;
|
|
46
|
+
params: VaultParams;
|
|
47
|
+
};
|
|
48
|
+
export interface ObsidianSpawnResult {
|
|
49
|
+
stdout: string;
|
|
50
|
+
stderr: string;
|
|
51
|
+
exitCode: number;
|
|
52
|
+
}
|
|
53
|
+
export interface VaultProtocolHandlerOptions {
|
|
54
|
+
spawnObsidian?: typeof spawnObsidian;
|
|
55
|
+
resolveObsidianBinary?: () => string | null;
|
|
56
|
+
}
|
|
57
|
+
interface CliInvocation {
|
|
58
|
+
args: string[];
|
|
59
|
+
contentType: ContentType;
|
|
60
|
+
opLabel: string;
|
|
61
|
+
}
|
|
62
|
+
export declare function parseVaultUrl(input: string | InternalUrl): ParsedVaultUrl;
|
|
63
|
+
export declare function spawnObsidian(bin: string, args: string[], signal?: AbortSignal, timeoutMs?: number): Promise<ObsidianSpawnResult>;
|
|
64
|
+
export declare function resolveObsidianBinary(): string | null;
|
|
65
|
+
/**
|
|
66
|
+
* Whether the `vault://` protocol is enabled in the active settings profile.
|
|
67
|
+
*
|
|
68
|
+
* Reads `vault.enabled` from the global settings singleton. Falls back to the
|
|
69
|
+
* schema default when settings are not yet initialized (e.g. during isolated
|
|
70
|
+
* unit tests that exercise the handler before the host calls `Settings.init`).
|
|
71
|
+
*/
|
|
72
|
+
export declare function isVaultEnabled(): boolean;
|
|
73
|
+
export declare function hasObsidian(): boolean;
|
|
74
|
+
export declare class VaultDisabledError extends Error {
|
|
75
|
+
constructor();
|
|
76
|
+
}
|
|
77
|
+
export declare function resolveVaultUrlToPath(input: string | InternalUrl): string;
|
|
78
|
+
export declare function buildObsidianCliInvocation(parsed: Extract<ParsedVaultUrl, {
|
|
79
|
+
kind: "file-op" | "vault-op";
|
|
80
|
+
}>): CliInvocation;
|
|
81
|
+
export declare class VaultProtocolHandler implements ProtocolHandler {
|
|
82
|
+
#private;
|
|
83
|
+
readonly scheme = "vault";
|
|
84
|
+
readonly immutable = false;
|
|
85
|
+
constructor(options?: VaultProtocolHandlerOptions);
|
|
86
|
+
static resetForTests(): void;
|
|
87
|
+
static setObsidianBinaryForTests(value: string | null | undefined): void;
|
|
88
|
+
static setVaultDirectoryForTests(entries: ReadonlyMap<string, string> | Record<string, string> | undefined): void;
|
|
89
|
+
static setActiveVaultPathForTests(vaultPath: string | undefined): void;
|
|
90
|
+
resolve(url: InternalUrl, context?: ResolveContext): Promise<InternalResource>;
|
|
91
|
+
write(url: InternalUrl, content: string, context?: WriteContext): Promise<void>;
|
|
92
|
+
}
|
|
93
|
+
export {};
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { MCPHttpServerConfig, MCPRequestOptions, MCPSseServerConfig, MCPTransport } from "../../mcp/types";
|
|
2
|
+
/**
|
|
3
|
+
* Best-effort startup deadline for the optional Streamable HTTP GET SSE listener.
|
|
4
|
+
*
|
|
5
|
+
* Returns `0` (disabled) when the operator has explicitly disabled MCP client-side
|
|
6
|
+
* timeouts via `timeout: 0` or `OMP_MCP_TIMEOUT_MS=0`, mirroring the rest of the
|
|
7
|
+
* MCP timeout surface. Otherwise caps the wait at one second and scales below
|
|
8
|
+
* short request timeouts so connect-time never exceeds the request budget.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveSSEConnectTimeoutMs(configTimeout?: number): number;
|
|
2
11
|
/**
|
|
3
12
|
* HTTP transport for MCP servers.
|
|
4
13
|
* Uses POST for requests, supports SSE responses.
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import type { SnapshotStore } from "@oh-my-pi/hashline";
|
|
1
2
|
import type { AgentTool } from "@oh-my-pi/pi-agent-core";
|
|
2
3
|
import { Container, type TUI } from "@oh-my-pi/pi-tui";
|
|
3
4
|
export interface ToolExecutionOptions {
|
|
5
|
+
snapshots?: SnapshotStore;
|
|
4
6
|
showImages?: boolean;
|
|
5
7
|
editFuzzyThreshold?: number;
|
|
6
8
|
editAllowFuzzy?: boolean;
|
|
7
|
-
hashlineAutoDropPureInsertDuplicates?: boolean;
|
|
8
9
|
}
|
|
9
10
|
export interface ToolExecutionHandle {
|
|
10
11
|
updateArgs(args: any, toolCallId?: string): void;
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Modes use this class and add their own I/O layer on top.
|
|
14
14
|
*/
|
|
15
|
+
import type { InMemorySnapshotStore } from "@oh-my-pi/hashline";
|
|
15
16
|
import { type Agent, type AgentEvent, type AgentMessage, type AgentState, type AgentTool, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
16
17
|
import { type CompactionResult } from "@oh-my-pi/pi-agent-core/compaction";
|
|
17
18
|
import type { AssistantMessage, Effort, ImageContent, Message, MessageAttribution, Model, ProviderSessionState, ServiceTier, SimpleStreamOptions, TextContent, ToolChoice, UsageReport } from "@oh-my-pi/pi-ai";
|
|
@@ -48,7 +49,7 @@ import { YieldQueue } from "./yield-queue";
|
|
|
48
49
|
/** Session-specific events that extend the core AgentEvent */
|
|
49
50
|
export type AgentSessionEvent = AgentEvent | {
|
|
50
51
|
type: "auto_compaction_start";
|
|
51
|
-
reason: "threshold" | "overflow" | "idle";
|
|
52
|
+
reason: "threshold" | "overflow" | "idle" | "incomplete";
|
|
52
53
|
action: "context-full" | "handoff";
|
|
53
54
|
} | {
|
|
54
55
|
type: "auto_compaction_end";
|
|
@@ -267,6 +268,7 @@ export declare class AgentSession {
|
|
|
267
268
|
readonly sessionManager: SessionManager;
|
|
268
269
|
readonly settings: Settings;
|
|
269
270
|
readonly yieldQueue: YieldQueue;
|
|
271
|
+
fileSnapshotStore?: InMemorySnapshotStore;
|
|
270
272
|
readonly configWarnings: string[];
|
|
271
273
|
readonly rawSseDebugBuffer: RawSseDebugBuffer;
|
|
272
274
|
constructor(config: AgentSessionConfig);
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Matched lines are prefixed with `*`; context lines are prefixed with a single
|
|
5
5
|
* space so line numbers align in column. In hashline mode the line uses the
|
|
6
|
-
* editable `LINE:content` shape under a
|
|
7
|
-
* the legacy `LINE|content` display-only shape. Line numbers are never padded.
|
|
6
|
+
* editable `LINE:content` shape under a snapshot-tag header; in plain mode it
|
|
7
|
+
* keeps the legacy `LINE|content` display-only shape. Line numbers are never padded.
|
|
8
8
|
*/
|
|
9
9
|
export declare function formatMatchLine(lineNumber: number, line: string, isMatch: boolean, options: {
|
|
10
10
|
useHashLines: boolean;
|
|
@@ -100,7 +100,9 @@ export interface DiffStats {
|
|
|
100
100
|
}
|
|
101
101
|
export declare function getDiffStats(diffText: string): DiffStats;
|
|
102
102
|
export declare function formatDiffStats(added: number, removed: number, hunks: number, theme: Theme): string;
|
|
103
|
-
export declare function truncateDiffByHunk(diffText: string, maxHunks: number, maxLines: number
|
|
103
|
+
export declare function truncateDiffByHunk(diffText: string, maxHunks: number, maxLines: number, options?: {
|
|
104
|
+
fromTail?: boolean;
|
|
105
|
+
}): {
|
|
104
106
|
text: string;
|
|
105
107
|
hiddenHunks: number;
|
|
106
108
|
hiddenLines: number;
|
|
@@ -15,6 +15,8 @@ export type WriteToolInput = z.infer<typeof writeSchema>;
|
|
|
15
15
|
export interface WriteToolDetails {
|
|
16
16
|
diagnostics?: FileDiagnosticsResult;
|
|
17
17
|
meta?: OutputMeta;
|
|
18
|
+
/** Set when the file was auto-chmod'd because content begins with a `#!` shebang. */
|
|
19
|
+
madeExecutable?: boolean;
|
|
18
20
|
}
|
|
19
21
|
type WriteParams = WriteToolInput;
|
|
20
22
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type SnapshotStore } from "@oh-my-pi/hashline";
|
|
1
2
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
2
3
|
/** Extract all @filepath mentions from text */
|
|
3
4
|
export declare function extractFileMentions(text: string): string[];
|
|
@@ -8,4 +9,5 @@ export declare function extractFileMentions(text: string): string[];
|
|
|
8
9
|
export declare function generateFileMentionMessages(filePaths: string[], cwd: string, options?: {
|
|
9
10
|
autoResizeImages?: boolean;
|
|
10
11
|
useHashLines?: boolean;
|
|
12
|
+
snapshotStore?: SnapshotStore;
|
|
11
13
|
}): Promise<AgentMessage[]>;
|
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": "15.5.
|
|
4
|
+
"version": "15.5.9",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -47,13 +47,13 @@
|
|
|
47
47
|
"@agentclientprotocol/sdk": "0.21.0",
|
|
48
48
|
"@babel/parser": "^7.29.3",
|
|
49
49
|
"@mozilla/readability": "^0.6.0",
|
|
50
|
-
"@oh-my-pi/hashline": "15.5.
|
|
51
|
-
"@oh-my-pi/omp-stats": "15.5.
|
|
52
|
-
"@oh-my-pi/pi-agent-core": "15.5.
|
|
53
|
-
"@oh-my-pi/pi-ai": "15.5.
|
|
54
|
-
"@oh-my-pi/pi-natives": "15.5.
|
|
55
|
-
"@oh-my-pi/pi-tui": "15.5.
|
|
56
|
-
"@oh-my-pi/pi-utils": "15.5.
|
|
50
|
+
"@oh-my-pi/hashline": "15.5.9",
|
|
51
|
+
"@oh-my-pi/omp-stats": "15.5.9",
|
|
52
|
+
"@oh-my-pi/pi-agent-core": "15.5.9",
|
|
53
|
+
"@oh-my-pi/pi-ai": "15.5.9",
|
|
54
|
+
"@oh-my-pi/pi-natives": "15.5.9",
|
|
55
|
+
"@oh-my-pi/pi-tui": "15.5.9",
|
|
56
|
+
"@oh-my-pi/pi-utils": "15.5.9",
|
|
57
57
|
"@puppeteer/browsers": "^2.13.0",
|
|
58
58
|
"@types/turndown": "5.0.6",
|
|
59
59
|
"@xterm/headless": "^6.0.0",
|
package/src/cli/args.ts
CHANGED
|
@@ -247,6 +247,8 @@ export function getExtraHelpText(): string {
|
|
|
247
247
|
OPENCODE_API_KEY - OpenCode Zen/OpenCode Go models
|
|
248
248
|
CURSOR_ACCESS_TOKEN - Cursor AI models
|
|
249
249
|
AI_GATEWAY_API_KEY - Vercel AI Gateway
|
|
250
|
+
WAFER_PASS_API_KEY - Wafer Pass (flat-rate subscription; GLM-5.1, Qwen3.5)
|
|
251
|
+
WAFER_SERVERLESS_API_KEY - Wafer Serverless (pay-as-you-go)
|
|
250
252
|
|
|
251
253
|
${chalk.dim("# Cloud Providers")}
|
|
252
254
|
AWS_PROFILE - AWS Bedrock (or AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY)
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
startAuthBroker,
|
|
35
35
|
} from "@oh-my-pi/pi-ai";
|
|
36
36
|
import { $which, APP_NAME, getAgentDbPath, getConfigRootDir, isEnoent, logger, VERSION } from "@oh-my-pi/pi-utils";
|
|
37
|
+
import { setTransports as setLoggerTransports } from "@oh-my-pi/pi-utils/logger";
|
|
37
38
|
import { $ } from "bun";
|
|
38
39
|
import chalk from "chalk";
|
|
39
40
|
import { resolveAuthBrokerConfig } from "../session/auth-broker-config";
|
|
@@ -124,7 +125,7 @@ async function runServe(flags: AuthBrokerCommandArgs["flags"]): Promise<void> {
|
|
|
124
125
|
// The broker is a long-running headless service: route structured logs to
|
|
125
126
|
// stdout so a process supervisor (pm2, journald, k8s) captures them, and
|
|
126
127
|
// skip the rotating ~/.omp/logs/ file the TUI default would have used.
|
|
127
|
-
|
|
128
|
+
setLoggerTransports({ console: true, file: false });
|
|
128
129
|
|
|
129
130
|
const bind = flags.bind ?? DEFAULT_AUTH_BROKER_BIND;
|
|
130
131
|
const token = await ensureToken();
|