@oh-my-pi/pi-coding-agent 17.2.10 → 17.2.12
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 -0
- package/dist/{CHANGELOG-rhwzpexa.md → CHANGELOG-k9ghy5sn.md} +53 -0
- package/dist/cli.js +10775 -10762
- package/dist/types/advisor/runtime.d.ts +1 -1
- package/dist/types/capability/mcp.d.ts +11 -0
- package/dist/types/capability/skill.d.ts +6 -0
- package/dist/types/cli/command-help.d.ts +3 -0
- package/dist/types/commands/share.d.ts +25 -0
- package/dist/types/commit/agentic/index.d.ts +3 -1
- package/dist/types/commit/execute.d.ts +32 -0
- package/dist/types/commit/index.d.ts +2 -1
- package/dist/types/commit/pipeline.d.ts +7 -1
- package/dist/types/config/custom-models.d.ts +31 -0
- package/dist/types/config/model-config-values.d.ts +19 -0
- package/dist/types/config/model-patch.d.ts +93 -0
- package/dist/types/config/model-provider-discovery.d.ts +51 -0
- package/dist/types/config/model-registry.d.ts +9 -52
- package/dist/types/config/settings-schema.d.ts +1 -34
- package/dist/types/config/settings.d.ts +5 -3
- package/dist/types/debug/raw-sse-buffer.d.ts +9 -0
- package/dist/types/discovery/agent-plugin-format.d.ts +136 -0
- package/dist/types/discovery/agent-plugins.d.ts +1 -0
- package/dist/types/discovery/contained-path.d.ts +33 -0
- package/dist/types/discovery/index.d.ts +1 -0
- package/dist/types/eval/executor-base.d.ts +8 -2
- package/dist/types/eval/kernel-session-registry.d.ts +60 -0
- package/dist/types/export/share.d.ts +1 -1
- package/dist/types/extensibility/custom-tools/types.d.ts +2 -2
- package/dist/types/extensibility/extensions/loader.d.ts +7 -0
- package/dist/types/extensibility/extensions/types.d.ts +11 -0
- package/dist/types/extensibility/shared-events.d.ts +3 -2
- package/dist/types/extensibility/skills.d.ts +5 -0
- package/dist/types/lsp/diagnostics.d.ts +96 -0
- package/dist/types/lsp/index.d.ts +7 -128
- package/dist/types/lsp/servers.d.ts +72 -0
- package/dist/types/lsp/tool.d.ts +42 -0
- package/dist/types/lsp/workspace-diagnostics.d.ts +12 -0
- package/dist/types/lsp/writethrough.d.ts +33 -0
- package/dist/types/mcp/transports/header-policy.d.ts +46 -0
- package/dist/types/mcp/types.d.ts +15 -0
- package/dist/types/modes/components/agent-hub-projection.d.ts +2 -7
- package/dist/types/modes/components/agent-hub-renderer.d.ts +0 -7
- package/dist/types/modes/components/agent-hub.d.ts +2 -0
- package/dist/types/modes/components/agent-transcript-viewer.d.ts +2 -0
- package/dist/types/modes/components/chat-transcript-builder.d.ts +2 -0
- package/dist/types/modes/components/custom-editor.d.ts +1 -2
- package/dist/types/modes/components/status-line/types.d.ts +2 -0
- package/dist/types/modes/components/tool-execution.d.ts +2 -0
- package/dist/types/modes/theme/color.d.ts +19 -0
- package/dist/types/modes/theme/loader.d.ts +19 -0
- package/dist/types/modes/theme/schema.d.ts +175 -0
- package/dist/types/modes/theme/symbols.d.ts +28 -0
- package/dist/types/modes/theme/theme-class.d.ts +244 -0
- package/dist/types/modes/theme/theme.d.ts +9 -280
- package/dist/types/modes/theme/tui-adapters.d.ts +13 -0
- package/dist/types/modes/utils/transcript-render-helpers.d.ts +3 -2
- package/dist/types/registry/agent-registry.d.ts +1 -3
- package/dist/types/secrets/index.d.ts +26 -2
- package/dist/types/secrets/message-transform.d.ts +40 -0
- package/dist/types/secrets/obfuscator.d.ts +0 -108
- package/dist/types/secrets/placeholder-scan.d.ts +95 -0
- package/dist/types/secrets/placeholder.d.ts +94 -0
- package/dist/types/secrets/replacement.d.ts +82 -0
- package/dist/types/session/agent-session-events.d.ts +2 -2
- package/dist/types/session/agent-session-types.d.ts +6 -0
- package/dist/types/session/agent-session.d.ts +2 -2
- package/dist/types/session/messages.d.ts +1 -0
- package/dist/types/session/prewalk.d.ts +3 -1
- package/dist/types/session/session-handoff.d.ts +3 -3
- package/dist/types/session/session-manager.d.ts +32 -0
- package/dist/types/session/session-provider-boundary.d.ts +1 -1
- package/dist/types/session/session-tools.d.ts +8 -0
- package/dist/types/session/turn-recovery.d.ts +9 -4
- package/dist/types/slash-commands/builtin-collaboration.d.ts +2 -0
- package/dist/types/slash-commands/builtin-completions.d.ts +36 -0
- package/dist/types/slash-commands/builtin-control.d.ts +2 -0
- package/dist/types/slash-commands/builtin-lifecycle.d.ts +3 -0
- package/dist/types/slash-commands/builtin-marketplace.d.ts +11 -0
- package/dist/types/slash-commands/builtin-modes.d.ts +5 -0
- package/dist/types/slash-commands/builtin-registry.d.ts +1 -1
- package/dist/types/slash-commands/builtin-session.d.ts +2 -0
- package/dist/types/task/index.d.ts +2 -0
- package/dist/types/tools/gh-common.d.ts +69 -0
- package/dist/types/tools/gh-pr-checkout.d.ts +84 -0
- package/dist/types/tools/gh-pr-diff.d.ts +102 -0
- package/dist/types/tools/gh-run-watch.d.ts +78 -0
- package/dist/types/tools/gh-search.d.ts +61 -0
- package/dist/types/tools/gh-types.d.ts +340 -0
- package/dist/types/tools/gh-view.d.ts +88 -0
- package/dist/types/tools/gh.d.ts +4 -201
- package/dist/types/tools/read-archive.d.ts +16 -0
- package/dist/types/tools/read-format.d.ts +104 -0
- package/dist/types/tools/read-path-resolution.d.ts +19 -0
- package/dist/types/tools/read-pdf-images.d.ts +12 -0
- package/dist/types/tools/read-renderer.d.ts +24 -0
- package/dist/types/tools/read-selector.d.ts +27 -0
- package/dist/types/tools/read-sqlite.d.ts +16 -0
- package/dist/types/tools/read-summary.d.ts +19 -0
- package/dist/types/tools/read.d.ts +1 -23
- package/dist/types/tools/shell-tokenize.d.ts +18 -1
- package/dist/types/utils/changelog.d.ts +0 -5
- package/package.json +13 -13
- package/scripts/legacy-pi-virtual-module.ts +4 -1
- package/src/advisor/runtime.ts +12 -7
- package/src/capability/mcp.ts +11 -0
- package/src/capability/skill.ts +6 -0
- package/src/cli/command-help.ts +4 -0
- package/src/cli/gallery-cli.ts +1 -1
- package/src/cli-commands.ts +5 -0
- package/src/commands/commit.ts +16 -3
- package/src/commands/share.ts +71 -0
- package/src/commit/agentic/index.ts +39 -21
- package/src/commit/execute.ts +56 -0
- package/src/commit/index.ts +2 -1
- package/src/commit/pipeline.ts +20 -7
- package/src/config/custom-models.ts +188 -0
- package/src/config/model-config-values.ts +128 -0
- package/src/config/model-discovery.ts +1 -1
- package/src/config/model-patch.ts +252 -0
- package/src/config/model-provider-discovery.ts +132 -0
- package/src/config/model-registry.ts +84 -704
- package/src/config/settings-schema.ts +2 -33
- package/src/config/settings.ts +53 -3
- package/src/debug/raw-sse-buffer.ts +20 -0
- package/src/discovery/agent-plugin-format.ts +551 -0
- package/src/discovery/agent-plugins.ts +341 -0
- package/src/discovery/claude-plugins.ts +21 -5
- package/src/discovery/contained-path.ts +75 -0
- package/src/discovery/helpers.ts +23 -9
- package/src/discovery/index.ts +1 -0
- package/src/discovery/omp-plugins.ts +20 -7
- package/src/edit/hashline/diff.ts +5 -1
- package/src/eval/executor-base.ts +39 -6
- package/src/eval/jl/executor.ts +82 -371
- package/src/eval/kernel-session-registry.ts +398 -0
- package/src/eval/py/executor.ts +53 -261
- package/src/eval/rb/executor.ts +36 -279
- package/src/exec/non-interactive-env.ts +1 -0
- package/src/export/share.ts +2 -1
- package/src/extensibility/custom-tools/types.ts +2 -2
- package/src/extensibility/extensions/loader.ts +78 -14
- package/src/extensibility/extensions/runner.ts +6 -0
- package/src/extensibility/extensions/types.ts +12 -0
- package/src/extensibility/plugins/marketplace/manager.ts +2 -1
- package/src/extensibility/shared-events.ts +3 -2
- package/src/extensibility/skills.ts +9 -0
- package/src/internal-urls/skill-protocol.ts +14 -0
- package/src/internal-urls/vault-protocol.ts +2 -2
- package/src/launch/client.ts +11 -1
- package/src/launch/protocol.ts +7 -2
- package/src/lsp/diagnostics.ts +516 -0
- package/src/lsp/index.ts +20 -2819
- package/src/lsp/servers.ts +296 -0
- package/src/lsp/tool.ts +1352 -0
- package/src/lsp/workspace-diagnostics.ts +170 -0
- package/src/lsp/writethrough.ts +561 -0
- package/src/main.ts +3 -2
- package/src/mcp/config.ts +3 -0
- package/src/mcp/manager.ts +12 -9
- package/src/mcp/transports/header-policy.ts +95 -0
- package/src/mcp/transports/http.ts +35 -52
- package/src/mcp/transports/sse.ts +20 -27
- package/src/mcp/types.ts +15 -0
- package/src/modes/acp/acp-agent.ts +15 -4
- package/src/modes/components/agent-dashboard.ts +2 -0
- package/src/modes/components/agent-hub-projection.ts +2 -2
- package/src/modes/components/agent-hub-renderer.ts +3 -7
- package/src/modes/components/agent-hub.ts +5 -0
- package/src/modes/components/agent-transcript-viewer.ts +3 -0
- package/src/modes/components/chat-transcript-builder.ts +3 -0
- package/src/modes/components/custom-editor.ts +0 -9
- package/src/modes/components/status-line/component.ts +1 -0
- package/src/modes/components/status-line/segments.ts +6 -4
- package/src/modes/components/status-line/types.ts +2 -0
- package/src/modes/components/tool-execution.ts +13 -16
- package/src/modes/components/tree-selector.ts +62 -3
- package/src/modes/controllers/command-controller.ts +8 -2
- package/src/modes/controllers/event-controller.ts +15 -15
- package/src/modes/controllers/input-controller.ts +20 -2
- package/src/modes/controllers/selector-controller.ts +1 -0
- package/src/modes/theme/color.ts +133 -0
- package/src/modes/theme/loader.ts +178 -0
- package/src/modes/theme/schema.ts +263 -0
- package/src/modes/theme/symbols.ts +1000 -0
- package/src/modes/theme/theme-class.ts +611 -0
- package/src/modes/theme/theme.ts +27 -2453
- package/src/modes/theme/tui-adapters.ts +279 -0
- package/src/modes/utils/transcript-render-helpers.ts +4 -2
- package/src/modes/utils/ui-helpers.ts +1 -0
- package/src/registry/agent-registry.ts +2 -2
- package/src/sdk.ts +6 -49
- package/src/secrets/index.ts +51 -6
- package/src/secrets/message-transform.ts +287 -0
- package/src/secrets/obfuscator.ts +39 -1303
- package/src/secrets/placeholder-scan.ts +506 -0
- package/src/secrets/placeholder.ts +309 -0
- package/src/secrets/replacement.ts +216 -0
- package/src/session/agent-session-events.ts +2 -2
- package/src/session/agent-session-types.ts +6 -0
- package/src/session/agent-session.ts +146 -21
- package/src/session/indexed-session-storage.ts +7 -2
- package/src/session/messages.ts +1 -0
- package/src/session/prewalk.ts +57 -17
- package/src/session/session-advisors.ts +32 -34
- package/src/session/session-context.ts +3 -5
- package/src/session/session-handoff.ts +39 -16
- package/src/session/session-manager.ts +67 -3
- package/src/session/session-provider-boundary.ts +3 -6
- package/src/session/session-tools.ts +37 -3
- package/src/session/todo-tracker.ts +11 -1
- package/src/session/turn-recovery.ts +115 -84
- package/src/slash-commands/builtin-collaboration.ts +504 -0
- package/src/slash-commands/builtin-completions.ts +291 -0
- package/src/slash-commands/builtin-control.ts +78 -0
- package/src/slash-commands/builtin-lifecycle.ts +506 -0
- package/src/slash-commands/builtin-marketplace.ts +567 -0
- package/src/slash-commands/builtin-modes.ts +518 -0
- package/src/slash-commands/builtin-registry.ts +21 -2996
- package/src/slash-commands/builtin-session.ts +592 -0
- package/src/task/executor.ts +17 -14
- package/src/task/index.ts +21 -6
- package/src/tools/bash-skill-urls.ts +15 -0
- package/src/tools/bash.ts +10 -11
- package/src/tools/debug.ts +1 -1
- package/src/tools/gh-common.ts +288 -0
- package/src/tools/gh-pr-checkout.ts +679 -0
- package/src/tools/gh-pr-diff.ts +473 -0
- package/src/tools/gh-run-watch.ts +1015 -0
- package/src/tools/gh-search.ts +500 -0
- package/src/tools/gh-types.ts +379 -0
- package/src/tools/gh-view.ts +612 -0
- package/src/tools/gh.ts +109 -3821
- package/src/tools/jtd-to-json-schema.ts +123 -21
- package/src/tools/read-archive.ts +209 -0
- package/src/tools/read-format.ts +593 -0
- package/src/tools/read-path-resolution.ts +36 -0
- package/src/tools/read-pdf-images.ts +250 -0
- package/src/tools/read-renderer.ts +289 -0
- package/src/tools/read-selector.ts +84 -0
- package/src/tools/read-sqlite.ts +215 -0
- package/src/tools/read-summary.ts +199 -0
- package/src/tools/read.ts +82 -1824
- package/src/tools/shell-tokenize.ts +99 -1
- package/src/utils/changelog.ts +1 -1
- package/src/utils/title-generator.ts +3 -1
- package/src/web/search/providers/exa.ts +1 -1
- package/src/web/search/providers/zai.ts +12 -3
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
|
|
2
|
+
import type { ToolSession } from "../sdk.js";
|
|
3
|
+
import { type LineEntry } from "../utils/block-context.js";
|
|
4
|
+
import { type LineRange } from "./path-utils.js";
|
|
5
|
+
import type { ReadToolDetails } from "./read.js";
|
|
6
|
+
export interface HashlineHeaderContext {
|
|
7
|
+
header: string;
|
|
8
|
+
tag: string;
|
|
9
|
+
fullText?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function formatReadHashlineHeader(displayPath: string, tag: string): string;
|
|
12
|
+
export declare function readHashlineHeaderContext(session: ToolSession, absolutePath: string, cwd: string): Promise<HashlineHeaderContext>;
|
|
13
|
+
export declare function hashlineHeaderContext(displayPath: string, tag: string): HashlineHeaderContext;
|
|
14
|
+
export declare function prependHashlineHeader(text: string, context: HashlineHeaderContext | undefined): string;
|
|
15
|
+
export declare function formatTextWithMode(text: string, startNum: number, shouldAddHashLines: boolean, shouldAddLineNumbers: boolean): string;
|
|
16
|
+
export declare const BRACKET_CONTEXT_ELLIPSIS = "\u2026";
|
|
17
|
+
export declare function formatLineEntriesWithMode(entries: readonly LineEntry[], shouldAddHashLines: boolean, shouldAddLineNumbers: boolean): string;
|
|
18
|
+
/**
|
|
19
|
+
* Decide whether the kept lines surrounding an elided range collapse to a
|
|
20
|
+
* single brace-pair line in the rendered summary. Returns true when the head
|
|
21
|
+
* line ends with `{` / `(` / `[` and the tail line is the matching closer
|
|
22
|
+
* (optionally followed by terminating punctuation like `;`, `,`, or further
|
|
23
|
+
* closers — e.g. `};`, `})`, `]);`).
|
|
24
|
+
*/
|
|
25
|
+
export declare function canMergeBracePair(headLine: string, tailLine: string): boolean;
|
|
26
|
+
export declare function formatSingleLine(line: number, text: string, shouldAddHashLines: boolean, shouldAddLineNumbers: boolean): string;
|
|
27
|
+
export declare function formatMergedBraceLine(startLine: number, endLine: number, headText: string, tailText: string, shouldAddHashLines: boolean, shouldAddLineNumbers: boolean): {
|
|
28
|
+
model: string;
|
|
29
|
+
display: string;
|
|
30
|
+
};
|
|
31
|
+
export declare function countTextLines(text: string): number;
|
|
32
|
+
export declare function contiguousLineNumbers(startLine: number, count: number): number[];
|
|
33
|
+
export declare function lineNumbersFromSpans(spans: readonly {
|
|
34
|
+
startLine: number;
|
|
35
|
+
endLine: number;
|
|
36
|
+
}[]): number[];
|
|
37
|
+
/** Inclusive line range describing one elided span in a structural summary. */
|
|
38
|
+
export interface ElidedRange {
|
|
39
|
+
start: number;
|
|
40
|
+
end: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Footer appended to summarized reads telling the model how to recover the
|
|
44
|
+
* elided body. Without this hint, agents either ignore the `…`/`{ … }`
|
|
45
|
+
* markers or burn a turn guessing the right selector (see issue #1046). The
|
|
46
|
+
* footer demonstrates the multi-range selector syntax with concrete sample
|
|
47
|
+
* ranges drawn from the actual elision so the model re-reads only what it
|
|
48
|
+
* needs instead of falling back to `:raw` or whole-file reads.
|
|
49
|
+
*/
|
|
50
|
+
export declare function formatSummaryElisionFooter(readPath: string, elidedRanges: ReadonlyArray<ElidedRange>, elidedLines: number): string;
|
|
51
|
+
export declare const READ_CHUNK_SIZE: number;
|
|
52
|
+
/**
|
|
53
|
+
* Context lines added around an explicit range read. Anchor-stale failures
|
|
54
|
+
* cluster on edits whose anchors land just outside the most recent read
|
|
55
|
+
* window, but the data (`scripts/session-stats/analyze_selector_reads.py`)
|
|
56
|
+
* shows most follow-up reads are disjoint hops, not adjacent extensions —
|
|
57
|
+
* so symmetric padding rarely pays for itself.
|
|
58
|
+
*
|
|
59
|
+
* Leading=1 catches accidental single-line reads where the anchor is the
|
|
60
|
+
* line immediately above the requested start. Trailing=3 buffers the
|
|
61
|
+
* common case where the agent asks for a narrow range and then needs the
|
|
62
|
+
* next few lines to disambiguate an anchor.
|
|
63
|
+
*/
|
|
64
|
+
export declare const RANGE_LEADING_CONTEXT_LINES = 1;
|
|
65
|
+
export declare const RANGE_TRAILING_CONTEXT_LINES = 3;
|
|
66
|
+
export declare function buildInMemoryTextResult(session: ToolSession, text: string, offset: number | undefined, limit: number | undefined, options: {
|
|
67
|
+
details?: ReadToolDetails;
|
|
68
|
+
sourcePath?: string;
|
|
69
|
+
sourceUrl?: string;
|
|
70
|
+
sourceInternal?: string;
|
|
71
|
+
entityLabel: string;
|
|
72
|
+
ignoreResultLimits?: boolean;
|
|
73
|
+
raw?: boolean;
|
|
74
|
+
immutable?: boolean;
|
|
75
|
+
}): AgentToolResult<ReadToolDetails>;
|
|
76
|
+
/**
|
|
77
|
+
* Render a multi-range read against in-memory text. Each range emits a
|
|
78
|
+
* formatted block with its own anchors / line numbers, blocks are joined
|
|
79
|
+
* with an elision separator, and ranges past EOF surface as `[…]` notices
|
|
80
|
+
* so the model can correct the next call. No leading/trailing context is
|
|
81
|
+
* added — multi-range callers always specify exact bounds.
|
|
82
|
+
*/
|
|
83
|
+
export declare function buildInMemoryMultiRangeResult(session: ToolSession, text: string, ranges: readonly LineRange[], options: {
|
|
84
|
+
details?: ReadToolDetails;
|
|
85
|
+
sourcePath?: string;
|
|
86
|
+
sourceUrl?: string;
|
|
87
|
+
sourceInternal?: string;
|
|
88
|
+
entityLabel: string;
|
|
89
|
+
raw?: boolean;
|
|
90
|
+
immutable?: boolean;
|
|
91
|
+
}): AgentToolResult<ReadToolDetails>;
|
|
92
|
+
export declare function decodeUtf8Text(bytes: Uint8Array): string | null;
|
|
93
|
+
export declare function prependSuffixResolutionNotice(text: string, suffixResolution?: {
|
|
94
|
+
from: string;
|
|
95
|
+
to: string;
|
|
96
|
+
}): string;
|
|
97
|
+
/**
|
|
98
|
+
* Tag Markdown reads for the TUI's formatted preview, gated on the opt-in
|
|
99
|
+
* `read.renderMarkdown` setting. Off by default; when disabled, no local
|
|
100
|
+
* read is tagged `text/markdown`, so the renderer output is identical to
|
|
101
|
+
* the pre-setting behavior. Internal-URL reads keep their protocol-supplied
|
|
102
|
+
* `contentType` and render as Markdown regardless of the setting.
|
|
103
|
+
*/
|
|
104
|
+
export declare function markMarkdownContentType(session: ToolSession, details: ReadToolDetails, filePath: string): ReadToolDetails;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ToolSession } from "../sdk.js";
|
|
2
|
+
export declare function isRemoteMountPath(absolutePath: string): boolean;
|
|
3
|
+
export declare function isNotFoundError(error: unknown): boolean;
|
|
4
|
+
/** Per-execute memo of suffix-glob lookups; `null` records a confirmed miss. */
|
|
5
|
+
export type SuffixMatchCache = Map<string, {
|
|
6
|
+
absolutePath: string;
|
|
7
|
+
displayPath: string;
|
|
8
|
+
} | null>;
|
|
9
|
+
/**
|
|
10
|
+
* Memoized {@link findUniqueWorkspaceSuffix} for a single read call. A missing
|
|
11
|
+
* path with archive/sqlite extensions probes the workspace once per stage
|
|
12
|
+
* (archive candidates, sqlite candidates, plain path) — each glob carries a
|
|
13
|
+
* 5s timeout, so repeated lookups of the same string stack into a long
|
|
14
|
+
* stall before erroring. The cache collapses repeats within one execute().
|
|
15
|
+
*/
|
|
16
|
+
export declare function findSuffixMatchCached(session: ToolSession, cache: SuffixMatchCache, rawPath: string, signal?: AbortSignal): Promise<{
|
|
17
|
+
absolutePath: string;
|
|
18
|
+
displayPath: string;
|
|
19
|
+
} | null>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
|
|
2
|
+
import type { ToolSession } from "../sdk.js";
|
|
3
|
+
import type { ReadToolDetails } from "./read.js";
|
|
4
|
+
export declare function rewritePdfImagePlaceholders(markdown: string, pdfPath: string): string;
|
|
5
|
+
export declare function splitPdfImageMemberReadPath(readPath: string): {
|
|
6
|
+
pdfPath: string;
|
|
7
|
+
member: string;
|
|
8
|
+
} | null;
|
|
9
|
+
export declare function readPdfImageMember(session: ToolSession, autoResizeImages: boolean, absolutePdfPath: string, pdfDisplayPath: string, member: string, suffixResolution: {
|
|
10
|
+
from: string;
|
|
11
|
+
to: string;
|
|
12
|
+
} | undefined, signal?: AbortSignal): Promise<AgentToolResult<ReadToolDetails>>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Component } from "@oh-my-pi/pi-tui";
|
|
2
|
+
import type { RenderResultOptions } from "../extensibility/custom-tools/types.js";
|
|
3
|
+
import { type Theme } from "../modes/theme/theme.js";
|
|
4
|
+
import type { ReadToolDetails } from "./read.js";
|
|
5
|
+
interface ReadRenderArgs {
|
|
6
|
+
path?: unknown;
|
|
7
|
+
file_path?: unknown;
|
|
8
|
+
offset?: number;
|
|
9
|
+
limit?: number;
|
|
10
|
+
raw?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare const readToolRenderer: {
|
|
13
|
+
renderCall(args: ReadRenderArgs, _options: RenderResultOptions, uiTheme: Theme): Component;
|
|
14
|
+
renderResult(result: {
|
|
15
|
+
content: Array<{
|
|
16
|
+
type: string;
|
|
17
|
+
text?: string;
|
|
18
|
+
}>;
|
|
19
|
+
details?: ReadToolDetails;
|
|
20
|
+
isError?: boolean;
|
|
21
|
+
}, options: RenderResultOptions, uiTheme: Theme, args?: ReadRenderArgs): Component;
|
|
22
|
+
mergeCallAndResult: boolean;
|
|
23
|
+
};
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { LineRange } from "./path-utils.js";
|
|
2
|
+
/** Parsed representation of a path-embedded selector. */
|
|
3
|
+
export type ParsedSelector = {
|
|
4
|
+
kind: "none";
|
|
5
|
+
} | {
|
|
6
|
+
kind: "raw";
|
|
7
|
+
} | {
|
|
8
|
+
kind: "conflicts";
|
|
9
|
+
} | {
|
|
10
|
+
kind: "lines";
|
|
11
|
+
ranges: [LineRange, ...LineRange[]];
|
|
12
|
+
raw?: boolean;
|
|
13
|
+
};
|
|
14
|
+
/** Returns true when the selector requested verbatim/raw output (alone or combined with a range). */
|
|
15
|
+
export declare function isRawSelector(parsed: ParsedSelector): boolean;
|
|
16
|
+
/** Returns true when the selector requested multiple line ranges. */
|
|
17
|
+
export declare function isMultiRange(parsed: ParsedSelector): boolean;
|
|
18
|
+
export declare function parseSel(sel: string | undefined): ParsedSelector;
|
|
19
|
+
/**
|
|
20
|
+
* Convert a single-range selector to the offset/limit pair used by internal pagination.
|
|
21
|
+
* Returns the FIRST range only — multi-range callers MUST branch on `isMultiRange` before
|
|
22
|
+
* calling this helper.
|
|
23
|
+
*/
|
|
24
|
+
export declare function selToOffsetLimit(parsed: ParsedSelector): {
|
|
25
|
+
offset?: number;
|
|
26
|
+
limit?: number;
|
|
27
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
|
|
2
|
+
import type { ToolSession } from "../sdk.js";
|
|
3
|
+
import type { ReadToolDetails } from "./read.js";
|
|
4
|
+
import { type SuffixMatchCache } from "./read-path-resolution.js";
|
|
5
|
+
interface ResolvedSqliteReadPath {
|
|
6
|
+
absolutePath: string;
|
|
7
|
+
sqliteSubPath: string;
|
|
8
|
+
queryString: string;
|
|
9
|
+
suffixResolution?: {
|
|
10
|
+
from: string;
|
|
11
|
+
to: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare function resolveSqliteReadPath(session: ToolSession, readPath: string, suffixCache: SuffixMatchCache, signal?: AbortSignal): Promise<ResolvedSqliteReadPath | null>;
|
|
15
|
+
export declare function readSqlite(resolvedSqlitePath: ResolvedSqliteReadPath, signal?: AbortSignal): Promise<AgentToolResult<ReadToolDetails>>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type SummaryResult } from "@oh-my-pi/pi-natives";
|
|
2
|
+
import type { ToolSession } from "../sdk.js";
|
|
3
|
+
import { type ElidedRange } from "./read-format.js";
|
|
4
|
+
/**
|
|
5
|
+
* Prose files (Markdown flavors and plain text) skip code-block summarization
|
|
6
|
+
* unless `read.summarize.prose` opts them in.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isProseSummaryPath(filePath: string): boolean;
|
|
9
|
+
export declare function routeReadThroughBridge(session: ToolSession, absolutePath: string, options?: {
|
|
10
|
+
line?: number;
|
|
11
|
+
limit?: number;
|
|
12
|
+
}): Promise<string> | undefined;
|
|
13
|
+
export declare function trySummarize(session: ToolSession, absolutePath: string, fileSize: number, signal?: AbortSignal): Promise<SummaryResult | null>;
|
|
14
|
+
export declare function renderSummary(session: ToolSession, summary: SummaryResult): {
|
|
15
|
+
text: string;
|
|
16
|
+
displayText: string;
|
|
17
|
+
elidedRanges: ElidedRange[];
|
|
18
|
+
elidedLines: number;
|
|
19
|
+
};
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback, ToolTier } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import type { Component } from "@oh-my-pi/pi-tui";
|
|
3
|
-
import type { RenderResultOptions } from "../extensibility/custom-tools/types.js";
|
|
4
|
-
import { type Theme } from "../modes/theme/theme.js";
|
|
5
2
|
import type { ToolSession } from "../sdk.js";
|
|
6
3
|
import { type TruncationResult } from "../session/streaming-output.js";
|
|
7
4
|
import { type OutputMeta } from "./output-meta.js";
|
|
5
|
+
export { readToolRenderer } from "./read-renderer.js";
|
|
8
6
|
declare const readSchema: import("@oh-my-pi/omptype").FluentType<{
|
|
9
7
|
path: string;
|
|
10
8
|
}, {
|
|
@@ -76,23 +74,3 @@ export declare class ReadTool implements AgentTool<typeof readSchema, ReadToolDe
|
|
|
76
74
|
syncInspectImageState(availableOverride?: boolean): boolean;
|
|
77
75
|
execute(_toolCallId: string, params: ReadParams, signal?: AbortSignal, _onUpdate?: AgentToolUpdateCallback<ReadToolDetails>, _toolContext?: AgentToolContext): Promise<AgentToolResult<ReadToolDetails>>;
|
|
78
76
|
}
|
|
79
|
-
interface ReadRenderArgs {
|
|
80
|
-
path?: unknown;
|
|
81
|
-
file_path?: unknown;
|
|
82
|
-
offset?: number;
|
|
83
|
-
limit?: number;
|
|
84
|
-
raw?: boolean;
|
|
85
|
-
}
|
|
86
|
-
export declare const readToolRenderer: {
|
|
87
|
-
renderCall(args: ReadRenderArgs, _options: RenderResultOptions, uiTheme: Theme): Component;
|
|
88
|
-
renderResult(result: {
|
|
89
|
-
content: Array<{
|
|
90
|
-
type: string;
|
|
91
|
-
text?: string;
|
|
92
|
-
}>;
|
|
93
|
-
details?: ReadToolDetails;
|
|
94
|
-
isError?: boolean;
|
|
95
|
-
}, options: RenderResultOptions, uiTheme: Theme, args?: ReadRenderArgs): Component;
|
|
96
|
-
mergeCallAndResult: boolean;
|
|
97
|
-
};
|
|
98
|
-
export {};
|
|
@@ -17,7 +17,7 @@ export declare function tokenizeShellSegments(command: string): string[][];
|
|
|
17
17
|
*
|
|
18
18
|
* @see extractFlatShellCommandSegments
|
|
19
19
|
*/
|
|
20
|
-
|
|
20
|
+
interface FlatShellCommandSegment {
|
|
21
21
|
/** Original segment text with quoting and escaping preserved. */
|
|
22
22
|
text: string;
|
|
23
23
|
/**
|
|
@@ -41,3 +41,20 @@ export interface FlatShellCommandSegment {
|
|
|
41
41
|
* complete input in that case.
|
|
42
42
|
*/
|
|
43
43
|
export declare function extractFlatShellCommandSegments(command: string): FlatShellCommandSegment[];
|
|
44
|
+
/**
|
|
45
|
+
* Parses a leading `cd <path> && ...` prefix so the bash tool can route the
|
|
46
|
+
* target through its structured `cwd` parameter when the model omits it.
|
|
47
|
+
*
|
|
48
|
+
* Returns the single path token (quotes and backslash escapes resolved to their
|
|
49
|
+
* literal value) and the command remainder after the top-level `&&`, or `null`
|
|
50
|
+
* when the command does not begin with exactly `cd`, one path token, and a
|
|
51
|
+
* top-level `&&`. The scanner deliberately bails on anything else in the prefix
|
|
52
|
+
* — redirects (`cd /tmp 2>/dev/null && ...`), extra arguments, or paths needing
|
|
53
|
+
* shell expansion (`$`, backticks, `(`) — leaving the whole command for the
|
|
54
|
+
* shell instead of absorbing shell syntax into `cwd`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function extractLeadingCdTarget(command: string): {
|
|
57
|
+
path: string;
|
|
58
|
+
rest: string;
|
|
59
|
+
} | null;
|
|
60
|
+
export {};
|
|
@@ -38,11 +38,6 @@ export declare function formatStartupChangelogSummary(selection: StartupChangelo
|
|
|
38
38
|
*/
|
|
39
39
|
export declare function resolveBundledChangelogPath(assetPath: string, moduleUrl: string | URL): string | URL;
|
|
40
40
|
export declare function parseChangelog(changelogPath: string | undefined): Promise<ChangelogEntry[]>;
|
|
41
|
-
/**
|
|
42
|
-
* Compare changelog entries by their parsed version parts.
|
|
43
|
-
* Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2
|
|
44
|
-
*/
|
|
45
|
-
export declare function compareChangelogEntries(v1: ChangelogEntry, v2: ChangelogEntry): number;
|
|
46
41
|
/**
|
|
47
42
|
* Parse an omp changelog marker version into comparable parts.
|
|
48
43
|
*/
|
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": "17.2.
|
|
4
|
+
"version": "17.2.12",
|
|
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",
|
|
@@ -50,18 +50,18 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@babel/parser": "^7.29.7",
|
|
53
|
-
"@oh-my-pi/hashline": "17.2.
|
|
54
|
-
"@oh-my-pi/omp-stats": "17.2.
|
|
55
|
-
"@oh-my-pi/omptype": "17.2.
|
|
56
|
-
"@oh-my-pi/pi-agent-core": "17.2.
|
|
57
|
-
"@oh-my-pi/pi-ai": "17.2.
|
|
58
|
-
"@oh-my-pi/pi-catalog": "17.2.
|
|
59
|
-
"@oh-my-pi/pi-mnemopi": "17.2.
|
|
60
|
-
"@oh-my-pi/pi-natives": "17.2.
|
|
61
|
-
"@oh-my-pi/pi-tui": "17.2.
|
|
62
|
-
"@oh-my-pi/pi-utils": "17.2.
|
|
63
|
-
"@oh-my-pi/pi-wire": "17.2.
|
|
64
|
-
"@oh-my-pi/snapcompact": "17.2.
|
|
53
|
+
"@oh-my-pi/hashline": "17.2.12",
|
|
54
|
+
"@oh-my-pi/omp-stats": "17.2.12",
|
|
55
|
+
"@oh-my-pi/omptype": "17.2.12",
|
|
56
|
+
"@oh-my-pi/pi-agent-core": "17.2.12",
|
|
57
|
+
"@oh-my-pi/pi-ai": "17.2.12",
|
|
58
|
+
"@oh-my-pi/pi-catalog": "17.2.12",
|
|
59
|
+
"@oh-my-pi/pi-mnemopi": "17.2.12",
|
|
60
|
+
"@oh-my-pi/pi-natives": "17.2.12",
|
|
61
|
+
"@oh-my-pi/pi-tui": "17.2.12",
|
|
62
|
+
"@oh-my-pi/pi-utils": "17.2.12",
|
|
63
|
+
"@oh-my-pi/pi-wire": "17.2.12",
|
|
64
|
+
"@oh-my-pi/snapcompact": "17.2.12",
|
|
65
65
|
"@opentelemetry/api": "^1.9.1",
|
|
66
66
|
"@opentelemetry/api-logs": "^0.220.0",
|
|
67
67
|
"@opentelemetry/context-async-hooks": "^2.9.0",
|
|
@@ -151,7 +151,10 @@ export async function collectBundledPiEntries(): Promise<BundledPiEntry[]> {
|
|
|
151
151
|
const glob = new Bun.Glob(`**/*${pattern.sourceSuffix}`);
|
|
152
152
|
const matches: string[] = [];
|
|
153
153
|
for await (const match of glob.scan({ cwd: sourceDir, onlyFiles: true })) {
|
|
154
|
-
|
|
154
|
+
// Bun.Glob yields host separators; the export keys and generated
|
|
155
|
+
// identifiers below are `/`-shaped. Same normalization as
|
|
156
|
+
// `generate-docs-index.ts`.
|
|
157
|
+
matches.push(match.split(path.sep).join("/"));
|
|
155
158
|
}
|
|
156
159
|
matches.sort();
|
|
157
160
|
for (const match of matches) {
|
package/src/advisor/runtime.ts
CHANGED
|
@@ -5,7 +5,8 @@ import * as AIError from "@oh-my-pi/pi-ai/error";
|
|
|
5
5
|
import { raceWithSignal } from "@oh-my-pi/pi-ai/utils/abort";
|
|
6
6
|
import { type CursorExecResolvedCarrier, kCursorExecResolved } from "@oh-my-pi/pi-ai/utils/block-symbols";
|
|
7
7
|
import { logger } from "@oh-my-pi/pi-utils";
|
|
8
|
-
import { obfuscateToolArguments
|
|
8
|
+
import { obfuscateToolArguments } from "../secrets/message-transform";
|
|
9
|
+
import type { SecretObfuscator } from "../secrets/obfuscator";
|
|
9
10
|
import {
|
|
10
11
|
formatExecutionSourcePreview,
|
|
11
12
|
formatSessionHistoryMarkdown,
|
|
@@ -970,14 +971,16 @@ export class AdvisorRuntime {
|
|
|
970
971
|
this.#wakeAllWaiters();
|
|
971
972
|
const failedMessages = this.agent.state.messages.slice(messageSnapshot);
|
|
972
973
|
const terminalFailure = this.#terminalAssistantFailure(messageSnapshot);
|
|
973
|
-
const
|
|
974
|
-
(terminalFailure !== undefined && isClassifierRefusal(terminalFailure)) ||
|
|
975
|
-
AIError.is(AIError.classify(err), AIError.Flag.ContentBlocked);
|
|
974
|
+
const rawErrorId = AIError.classify(err);
|
|
976
975
|
const terminalFailureId =
|
|
977
976
|
terminalFailure === undefined ? undefined : AIError.classifyMessage(terminalFailure);
|
|
977
|
+
const classifierRefusal =
|
|
978
|
+
(terminalFailure !== undefined && isClassifierRefusal(terminalFailure)) ||
|
|
979
|
+
(!AIError.is(rawErrorId, AIError.Flag.AccountPolicy) &&
|
|
980
|
+
AIError.is(rawErrorId, AIError.Flag.ContentBlocked));
|
|
978
981
|
const contextOverflow =
|
|
979
982
|
(terminalFailureId !== undefined && AIError.is(terminalFailureId, AIError.Flag.ContextOverflow)) ||
|
|
980
|
-
AIError.is(
|
|
983
|
+
AIError.is(rawErrorId, AIError.Flag.ContextOverflow);
|
|
981
984
|
// A terminal provider failure that is neither retriable nor an
|
|
982
985
|
// overflow (e.g. a blocked prompt) will fail identically on every
|
|
983
986
|
// retry — classify it before rollback so the batch is dropped after
|
|
@@ -1208,12 +1211,14 @@ export class AdvisorRuntime {
|
|
|
1208
1211
|
}
|
|
1209
1212
|
}
|
|
1210
1213
|
|
|
1211
|
-
/** Mirrors turn recovery's refusal classification
|
|
1214
|
+
/** Mirrors turn recovery's refusal classification without treating account eligibility as a model refusal. */
|
|
1212
1215
|
function isClassifierRefusal(message: AssistantMessage): boolean {
|
|
1213
1216
|
if (message.stopReason !== "error") return false;
|
|
1217
|
+
const id = AIError.classifyMessage(message);
|
|
1218
|
+
if (AIError.is(id, AIError.Flag.AccountPolicy)) return false;
|
|
1214
1219
|
const stopType = message.stopDetails?.type;
|
|
1215
1220
|
if (stopType === "refusal" || stopType === "sensitive") return true;
|
|
1216
|
-
return AIError.is(
|
|
1221
|
+
return AIError.is(id, AIError.Flag.ContentBlocked);
|
|
1217
1222
|
}
|
|
1218
1223
|
|
|
1219
1224
|
/**
|
package/src/capability/mcp.ts
CHANGED
|
@@ -27,12 +27,23 @@ export interface MCPServer {
|
|
|
27
27
|
args?: string[];
|
|
28
28
|
/** Environment variables */
|
|
29
29
|
env?: Record<string, string>;
|
|
30
|
+
/**
|
|
31
|
+
* `literal`: env values are opaque plugin package data (Agent Plugins
|
|
32
|
+
* §§4.1/9.2) — exempt from env-name lookup and `!command` resolution.
|
|
33
|
+
*/
|
|
34
|
+
envPolicy?: "literal";
|
|
30
35
|
/** Working directory for stdio transport */
|
|
31
36
|
cwd?: string;
|
|
32
37
|
/** URL (for HTTP/SSE transport) */
|
|
33
38
|
url?: string;
|
|
34
39
|
/** HTTP headers (for HTTP transport) */
|
|
35
40
|
headers?: Record<string, string>;
|
|
41
|
+
/**
|
|
42
|
+
* `origin-locked`: configured headers are literal package data pinned to the
|
|
43
|
+
* configured URL's origin (Agent Plugins §7.2.1) — never expanded, never
|
|
44
|
+
* forwarded cross-origin, and client-generated headers win case-insensitively.
|
|
45
|
+
*/
|
|
46
|
+
headerPolicy?: "origin-locked";
|
|
36
47
|
/** Authentication configuration */
|
|
37
48
|
auth?: {
|
|
38
49
|
type: "oauth" | "apikey";
|
package/src/capability/skill.ts
CHANGED
|
@@ -43,6 +43,12 @@ export interface Skill {
|
|
|
43
43
|
content: string;
|
|
44
44
|
/** Parsed frontmatter */
|
|
45
45
|
frontmatter?: SkillFrontmatter;
|
|
46
|
+
/**
|
|
47
|
+
* Filesystem-resolved plugin root this skill was packaged in (Agent Plugins
|
|
48
|
+
* §4.1). When set, every `skill://` resource access must realpath-resolve
|
|
49
|
+
* within this directory; symlinks may target other files inside it.
|
|
50
|
+
*/
|
|
51
|
+
containRoot?: string;
|
|
46
52
|
/** Source level */
|
|
47
53
|
level: "user" | "project";
|
|
48
54
|
/** Source metadata */
|
package/src/cli/command-help.ts
CHANGED
|
@@ -72,6 +72,10 @@ export const sayHelp = {
|
|
|
72
72
|
|
|
73
73
|
export const searchHelp = { description: "Test web search providers" } satisfies CommandMetadata;
|
|
74
74
|
|
|
75
|
+
export const shareHelp = {
|
|
76
|
+
description: "Share a saved session via an encrypted link (same as /share)",
|
|
77
|
+
} satisfies CommandMetadata;
|
|
78
|
+
|
|
75
79
|
export const setupHelp = {
|
|
76
80
|
description: "Run onboarding setup or install dependencies for optional features",
|
|
77
81
|
} satisfies CommandMetadata;
|
package/src/cli/gallery-cli.ts
CHANGED
|
@@ -153,7 +153,7 @@ export async function renderGalleryState(
|
|
|
153
153
|
const component = new ToolExecutionComponent(
|
|
154
154
|
componentName,
|
|
155
155
|
streamingArgs,
|
|
156
|
-
{ showImages: false },
|
|
156
|
+
{ showImages: false, useBuiltInRenderer: !fixture.customRendered },
|
|
157
157
|
tool,
|
|
158
158
|
ui,
|
|
159
159
|
getProjectDir(),
|
package/src/cli-commands.ts
CHANGED
|
@@ -120,6 +120,11 @@ export const commands: CommandEntry[] = [
|
|
|
120
120
|
load: () => import("./commands/say").then(m => m.default),
|
|
121
121
|
help: commandHelp.sayHelp,
|
|
122
122
|
},
|
|
123
|
+
{
|
|
124
|
+
name: "share",
|
|
125
|
+
load: () => import("./commands/share").then(m => m.default),
|
|
126
|
+
help: commandHelp.shareHelp,
|
|
127
|
+
},
|
|
123
128
|
{
|
|
124
129
|
name: "setup",
|
|
125
130
|
load: () => import("./commands/setup").then(m => m.default),
|
package/src/commands/commit.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { postmortem } from "@oh-my-pi/pi-utils";
|
|
6
6
|
import { Command, Flags } from "@oh-my-pi/pi-utils/cli";
|
|
7
7
|
import { commitHelp as commandHelp } from "../cli/command-help";
|
|
8
|
-
import { runCommitCommand } from "../commit";
|
|
8
|
+
import { CommitAbortedError, runCommitCommand } from "../commit";
|
|
9
9
|
import type { CommitCommandArgs } from "../commit/types";
|
|
10
10
|
import { initTheme } from "../modes/theme/theme";
|
|
11
11
|
|
|
@@ -41,7 +41,20 @@ export default class Commit extends Command {
|
|
|
41
41
|
// is already written. Mirror the `runPrintMode` exit pattern from
|
|
42
42
|
// `main.ts` so the CLI returns to the shell instead of stranding the user
|
|
43
43
|
// on Ctrl+C (issue #1041).
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
let exitCode = 0;
|
|
45
|
+
try {
|
|
46
|
+
const { usedFallback } = await runCommitCommand(cmd);
|
|
47
|
+
// A commit written by the mechanical fallback is a degraded outcome:
|
|
48
|
+
// the agent did not do the work it was asked to do, so the command
|
|
49
|
+
// reports non-zero so callers can distinguish it from a real
|
|
50
|
+
// single-commit decision (issue #7835).
|
|
51
|
+
if (usedFallback) exitCode = 1;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
if (!(error instanceof CommitAbortedError)) throw error;
|
|
54
|
+
// Failure already reported with a readable message; exit non-zero
|
|
55
|
+
// without letting the runtime dump a stack/minified-source blob.
|
|
56
|
+
exitCode = 1;
|
|
57
|
+
}
|
|
58
|
+
await postmortem.quit(exitCode);
|
|
46
59
|
}
|
|
47
60
|
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Share a saved session as an encrypted link without launching the agent.
|
|
3
|
+
*
|
|
4
|
+
* `omp share <session>` accepts a session id (prefix) or a path to a session
|
|
5
|
+
* `.jsonl` and uploads the sealed snapshot exactly like the `/share` slash
|
|
6
|
+
* command, honoring `share.serverUrl`, `share.store`, and
|
|
7
|
+
* `share.redactSecrets`.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { getAgentDir } from "@oh-my-pi/pi-utils";
|
|
11
|
+
import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
|
|
12
|
+
import { shareHelp as commandHelp } from "../cli/command-help";
|
|
13
|
+
import { Settings } from "../config/settings";
|
|
14
|
+
import { shareSession } from "../export/share";
|
|
15
|
+
import { buildSecretObfuscator } from "../secrets";
|
|
16
|
+
import { resolveResumableSession } from "../session/session-listing";
|
|
17
|
+
import { SessionManager } from "../session/session-manager";
|
|
18
|
+
|
|
19
|
+
export default class Share extends Command {
|
|
20
|
+
static description = commandHelp.description;
|
|
21
|
+
static args = {
|
|
22
|
+
session: Args.string({
|
|
23
|
+
description: "Session id (prefix) or path to a session .jsonl",
|
|
24
|
+
required: true,
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
static flags = {
|
|
28
|
+
gist: Flags.boolean({
|
|
29
|
+
description: "Upload to a secret GitHub gist instead of the share server",
|
|
30
|
+
default: false,
|
|
31
|
+
}),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
async run(): Promise<void> {
|
|
35
|
+
const { args, flags } = await this.parse(Share);
|
|
36
|
+
|
|
37
|
+
const sessionArg = args.session ?? "";
|
|
38
|
+
let sessionPath = sessionArg;
|
|
39
|
+
if (!sessionArg.includes("/") && !sessionArg.includes("\\") && !sessionArg.endsWith(".jsonl")) {
|
|
40
|
+
const match = await resolveResumableSession(sessionArg, process.cwd());
|
|
41
|
+
if (!match) {
|
|
42
|
+
process.stderr.write(`Session "${sessionArg}" not found.\n`);
|
|
43
|
+
process.exitCode = 1;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
sessionPath = match.session.path;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const sm = await SessionManager.open(sessionPath);
|
|
50
|
+
// Settings resolve against the session's own project so its
|
|
51
|
+
// share.redactSecrets/secrets.enabled policy governs, not the invoking cwd's.
|
|
52
|
+
const settings = await Settings.loadReadOnly({ cwd: sm.getCwd() });
|
|
53
|
+
// Same leak boundary as /share: a share blob leaves the machine, so honor
|
|
54
|
+
// share.redactSecrets with the full obfuscator built against the session's
|
|
55
|
+
// own project directory (its secrets.yml, not the invoking cwd's).
|
|
56
|
+
const obfuscator =
|
|
57
|
+
settings.get("share.redactSecrets") && settings.get("secrets.enabled")
|
|
58
|
+
? await buildSecretObfuscator(sm.getCwd(), getAgentDir())
|
|
59
|
+
: undefined;
|
|
60
|
+
|
|
61
|
+
const result = await shareSession(sm, {
|
|
62
|
+
serverUrl: settings.get("share.serverUrl"),
|
|
63
|
+
store: flags.gist ? "gist" : settings.get("share.store"),
|
|
64
|
+
obfuscator,
|
|
65
|
+
});
|
|
66
|
+
const lines = [`Share URL: ${result.url}`];
|
|
67
|
+
if (result.gistUrl) lines.push(`Gist: ${result.gistUrl}`);
|
|
68
|
+
if (result.truncated) lines.push("Note: large content was trimmed to fit the share size limit.");
|
|
69
|
+
console.log(lines.join("\n"));
|
|
70
|
+
}
|
|
71
|
+
}
|