@oh-my-pi/pi-coding-agent 13.14.0 → 13.15.2

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.
Files changed (90) hide show
  1. package/CHANGELOG.md +140 -0
  2. package/package.json +10 -8
  3. package/src/autoresearch/command-initialize.md +34 -0
  4. package/src/autoresearch/command-resume.md +17 -0
  5. package/src/autoresearch/contract.ts +332 -0
  6. package/src/autoresearch/dashboard.ts +447 -0
  7. package/src/autoresearch/git.ts +243 -0
  8. package/src/autoresearch/helpers.ts +458 -0
  9. package/src/autoresearch/index.ts +693 -0
  10. package/src/autoresearch/prompt.md +227 -0
  11. package/src/autoresearch/resume-message.md +16 -0
  12. package/src/autoresearch/state.ts +386 -0
  13. package/src/autoresearch/tools/init-experiment.ts +310 -0
  14. package/src/autoresearch/tools/log-experiment.ts +833 -0
  15. package/src/autoresearch/tools/run-experiment.ts +640 -0
  16. package/src/autoresearch/types.ts +218 -0
  17. package/src/cli/args.ts +8 -2
  18. package/src/cli/initial-message.ts +58 -0
  19. package/src/config/keybindings.ts +417 -212
  20. package/src/config/model-registry.ts +1 -0
  21. package/src/config/model-resolver.ts +57 -9
  22. package/src/config/settings-schema.ts +38 -10
  23. package/src/config/settings.ts +1 -4
  24. package/src/exec/bash-executor.ts +7 -5
  25. package/src/export/html/template.css +43 -13
  26. package/src/export/html/template.generated.ts +1 -1
  27. package/src/export/html/template.html +1 -0
  28. package/src/export/html/template.js +107 -0
  29. package/src/extensibility/extensions/types.ts +31 -8
  30. package/src/internal-urls/docs-index.generated.ts +1 -1
  31. package/src/lsp/index.ts +1 -1
  32. package/src/main.ts +44 -44
  33. package/src/mcp/oauth-discovery.ts +1 -1
  34. package/src/modes/acp/acp-agent.ts +957 -0
  35. package/src/modes/acp/acp-event-mapper.ts +531 -0
  36. package/src/modes/acp/acp-mode.ts +13 -0
  37. package/src/modes/acp/index.ts +2 -0
  38. package/src/modes/components/agent-dashboard.ts +5 -4
  39. package/src/modes/components/bash-execution.ts +40 -11
  40. package/src/modes/components/custom-editor.ts +47 -47
  41. package/src/modes/components/extensions/extension-dashboard.ts +2 -1
  42. package/src/modes/components/history-search.ts +2 -1
  43. package/src/modes/components/hook-editor.ts +2 -1
  44. package/src/modes/components/hook-input.ts +8 -7
  45. package/src/modes/components/hook-selector.ts +15 -10
  46. package/src/modes/components/keybinding-hints.ts +9 -9
  47. package/src/modes/components/login-dialog.ts +3 -3
  48. package/src/modes/components/mcp-add-wizard.ts +2 -1
  49. package/src/modes/components/model-selector.ts +14 -3
  50. package/src/modes/components/oauth-selector.ts +2 -1
  51. package/src/modes/components/python-execution.ts +2 -3
  52. package/src/modes/components/session-selector.ts +2 -1
  53. package/src/modes/components/settings-selector.ts +2 -1
  54. package/src/modes/components/status-line-segment-editor.ts +2 -1
  55. package/src/modes/components/tool-execution.ts +4 -5
  56. package/src/modes/components/tree-selector.ts +3 -2
  57. package/src/modes/components/user-message-selector.ts +3 -8
  58. package/src/modes/components/user-message.ts +16 -0
  59. package/src/modes/controllers/command-controller.ts +0 -2
  60. package/src/modes/controllers/extension-ui-controller.ts +89 -4
  61. package/src/modes/controllers/input-controller.ts +29 -23
  62. package/src/modes/controllers/mcp-command-controller.ts +1 -1
  63. package/src/modes/index.ts +1 -0
  64. package/src/modes/interactive-mode.ts +17 -5
  65. package/src/modes/print-mode.ts +1 -1
  66. package/src/modes/prompt-action-autocomplete.ts +7 -7
  67. package/src/modes/rpc/rpc-mode.ts +7 -2
  68. package/src/modes/rpc/rpc-types.ts +1 -0
  69. package/src/modes/theme/theme.ts +53 -44
  70. package/src/modes/types.ts +9 -2
  71. package/src/modes/utils/hotkeys-markdown.ts +19 -19
  72. package/src/modes/utils/keybinding-matchers.ts +21 -0
  73. package/src/modes/utils/ui-helpers.ts +1 -1
  74. package/src/patch/hashline.ts +139 -127
  75. package/src/patch/index.ts +77 -59
  76. package/src/patch/shared.ts +19 -11
  77. package/src/prompts/tools/hashline.md +43 -116
  78. package/src/sdk.ts +34 -17
  79. package/src/session/agent-session.ts +123 -30
  80. package/src/session/session-manager.ts +32 -31
  81. package/src/session/streaming-output.ts +87 -37
  82. package/src/tools/ask.ts +56 -30
  83. package/src/tools/bash-interactive.ts +2 -6
  84. package/src/tools/bash-interceptor.ts +1 -39
  85. package/src/tools/bash-skill-urls.ts +1 -1
  86. package/src/tools/browser.ts +1 -1
  87. package/src/tools/gemini-image.ts +1 -1
  88. package/src/tools/python.ts +2 -2
  89. package/src/tools/resolve.ts +1 -1
  90. package/src/utils/child-process.ts +88 -0
@@ -0,0 +1,218 @@
1
+ import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
2
+ import type { ExtensionAPI, ExtensionContext } from "../extensibility/extensions";
3
+ import type { SessionEntry } from "../session/session-manager";
4
+ import type { TruncationResult } from "../session/streaming-output";
5
+
6
+ export type MetricDirection = "lower" | "higher";
7
+ export type ExperimentStatus = "keep" | "discard" | "crash" | "checks_failed";
8
+
9
+ export type ASIValue = string | number | boolean | null | ASIValue[] | { [key: string]: ASIValue };
10
+
11
+ export interface ASIData {
12
+ [key: string]: ASIValue;
13
+ }
14
+
15
+ export interface NumericMetricMap {
16
+ [key: string]: number;
17
+ }
18
+
19
+ export interface MetricDef {
20
+ name: string;
21
+ unit: string;
22
+ }
23
+
24
+ export interface AutoresearchBenchmarkContract {
25
+ command: string | null;
26
+ primaryMetric: string | null;
27
+ metricUnit: string;
28
+ direction: MetricDirection | null;
29
+ secondaryMetrics: string[];
30
+ }
31
+
32
+ export interface AutoresearchContract {
33
+ benchmark: AutoresearchBenchmarkContract;
34
+ scopePaths: string[];
35
+ offLimits: string[];
36
+ constraints: string[];
37
+ }
38
+
39
+ export interface ExperimentResult {
40
+ runNumber: number | null;
41
+ commit: string;
42
+ metric: number;
43
+ metrics: NumericMetricMap;
44
+ status: ExperimentStatus;
45
+ description: string;
46
+ timestamp: number;
47
+ segment: number;
48
+ confidence: number | null;
49
+ asi?: ASIData;
50
+ }
51
+
52
+ export interface ExperimentState {
53
+ results: ExperimentResult[];
54
+ bestMetric: number | null;
55
+ bestDirection: MetricDirection;
56
+ metricName: string;
57
+ metricUnit: string;
58
+ secondaryMetrics: MetricDef[];
59
+ name: string | null;
60
+ currentSegment: number;
61
+ maxExperiments: number | null;
62
+ confidence: number | null;
63
+ benchmarkCommand: string | null;
64
+ scopePaths: string[];
65
+ offLimits: string[];
66
+ constraints: string[];
67
+ segmentFingerprint: string | null;
68
+ }
69
+
70
+ export interface RunExperimentProgressDetails {
71
+ phase: "running";
72
+ elapsed: string;
73
+ truncation?: TruncationResult;
74
+ fullOutputPath?: string;
75
+ runDirectory?: string;
76
+ }
77
+
78
+ export interface RunDetails {
79
+ runNumber: number;
80
+ runDirectory: string;
81
+ benchmarkLogPath: string;
82
+ checksLogPath?: string;
83
+ command: string;
84
+ exitCode: number | null;
85
+ durationSeconds: number;
86
+ passed: boolean;
87
+ crashed: boolean;
88
+ timedOut: boolean;
89
+ tailOutput: string;
90
+ checksPass: boolean | null;
91
+ checksTimedOut: boolean;
92
+ checksOutput: string;
93
+ checksDuration: number;
94
+ parsedMetrics: NumericMetricMap | null;
95
+ parsedPrimary: number | null;
96
+ parsedAsi: ASIData | null;
97
+ metricName: string;
98
+ metricUnit: string;
99
+ truncation?: TruncationResult;
100
+ fullOutputPath?: string;
101
+ }
102
+
103
+ export interface LogDetails {
104
+ experiment: ExperimentResult;
105
+ state: ExperimentState;
106
+ wallClockSeconds: number | null;
107
+ }
108
+
109
+ export interface ChecksResult {
110
+ pass: boolean;
111
+ output: string;
112
+ duration: number;
113
+ }
114
+
115
+ export interface PendingRunSummary {
116
+ checksDurationSeconds: number | null;
117
+ checksPass: boolean | null;
118
+ checksTimedOut: boolean;
119
+ command: string;
120
+ durationSeconds: number | null;
121
+ parsedAsi: ASIData | null;
122
+ parsedMetrics: NumericMetricMap | null;
123
+ parsedPrimary: number | null;
124
+ passed: boolean;
125
+ runDirectory: string;
126
+ runNumber: number;
127
+ }
128
+
129
+ export interface RunningExperiment {
130
+ startedAt: number;
131
+ command: string;
132
+ runDirectory: string;
133
+ runNumber: number;
134
+ }
135
+
136
+ export interface AutoresearchRuntime {
137
+ autoresearchMode: boolean;
138
+ autoResumeArmed: boolean;
139
+ dashboardExpanded: boolean;
140
+ lastAutoResumePendingRunNumber: number | null;
141
+ lastRunChecks: ChecksResult | null;
142
+ lastRunDuration: number | null;
143
+ lastRunAsi: ASIData | null;
144
+ lastRunArtifactDir: string | null;
145
+ lastRunNumber: number | null;
146
+ lastRunSummary: PendingRunSummary | null;
147
+ runningExperiment: RunningExperiment | null;
148
+ state: ExperimentState;
149
+ goal: string | null;
150
+ }
151
+
152
+ export interface AutoresearchConfig {
153
+ maxIterations?: number;
154
+ workingDir?: string;
155
+ }
156
+
157
+ export interface AutoresearchJsonConfigEntry {
158
+ type: "config";
159
+ name?: string;
160
+ metricName?: string;
161
+ metricUnit?: string;
162
+ bestDirection?: MetricDirection;
163
+ benchmarkCommand?: string;
164
+ secondaryMetrics?: string[];
165
+ scopePaths?: string[];
166
+ offLimits?: string[];
167
+ constraints?: string[];
168
+ segmentFingerprint?: string;
169
+ }
170
+
171
+ export interface AutoresearchJsonRunEntry {
172
+ run?: number;
173
+ commit?: string;
174
+ metric?: number;
175
+ metrics?: NumericMetricMap;
176
+ status?: ExperimentStatus;
177
+ description?: string;
178
+ timestamp?: number;
179
+ confidence?: number | null;
180
+ asi?: ASIData;
181
+ }
182
+
183
+ export interface ReconstructedExperimentData {
184
+ hasLog: boolean;
185
+ state: ExperimentState;
186
+ }
187
+
188
+ export interface AutoresearchControlEntryData {
189
+ mode: "on" | "off" | "clear";
190
+ goal?: string;
191
+ }
192
+
193
+ export interface ReconstructedControlState {
194
+ autoresearchMode: boolean;
195
+ goal: string | null;
196
+ lastMode: AutoresearchControlEntryData["mode"] | null;
197
+ }
198
+
199
+ export interface RuntimeStore {
200
+ clear(sessionKey: string): void;
201
+ ensure(sessionKey: string): AutoresearchRuntime;
202
+ }
203
+
204
+ export interface DashboardController {
205
+ clear(ctx: ExtensionContext): void;
206
+ requestRender(): void;
207
+ showOverlay(ctx: ExtensionContext, runtime: AutoresearchRuntime): Promise<void>;
208
+ updateWidget(ctx: ExtensionContext, runtime: AutoresearchRuntime): void;
209
+ }
210
+
211
+ export interface AutoresearchToolFactoryOptions {
212
+ dashboard: DashboardController;
213
+ getRuntime(ctx: ExtensionContext): AutoresearchRuntime;
214
+ pi: ExtensionAPI;
215
+ }
216
+
217
+ export type AutoresearchToolResult<TDetails> = AgentToolResult<TDetails>;
218
+ export type SessionEntries = SessionEntry[];
package/src/cli/args.ts CHANGED
@@ -7,7 +7,7 @@ import chalk from "chalk";
7
7
  import { parseEffort } from "../thinking";
8
8
  import { BUILTIN_TOOLS } from "../tools";
9
9
 
10
- export type Mode = "text" | "json" | "rpc";
10
+ export type Mode = "text" | "json" | "rpc" | "acp";
11
11
 
12
12
  export interface Args {
13
13
  cwd?: string;
@@ -28,6 +28,8 @@ export interface Args {
28
28
  mode?: Mode;
29
29
  noSession?: boolean;
30
30
  sessionDir?: string;
31
+ providerSessionId?: string;
32
+ fork?: string;
31
33
  models?: string[];
32
34
  tools?: string[];
33
35
  noTools?: boolean;
@@ -67,7 +69,7 @@ export function parseArgs(args: string[], extensionFlags?: Map<string, { type: "
67
69
  result.allowHome = true;
68
70
  } else if (arg === "--mode" && i + 1 < args.length) {
69
71
  const mode = args[++i];
70
- if (mode === "text" || mode === "json" || mode === "rpc") {
72
+ if (mode === "text" || mode === "json" || mode === "rpc" || mode === "acp") {
71
73
  result.mode = mode;
72
74
  }
73
75
  } else if (arg === "--continue" || arg === "-c") {
@@ -79,6 +81,8 @@ export function parseArgs(args: string[], extensionFlags?: Map<string, { type: "
79
81
  } else {
80
82
  result.resume = true;
81
83
  }
84
+ } else if (arg === "--fork" && i + 1 < args.length) {
85
+ result.fork = args[++i];
82
86
  } else if (arg === "--provider" && i + 1 < args.length) {
83
87
  result.provider = args[++i];
84
88
  } else if (arg === "--model" && i + 1 < args.length) {
@@ -95,6 +99,8 @@ export function parseArgs(args: string[], extensionFlags?: Map<string, { type: "
95
99
  result.systemPrompt = args[++i];
96
100
  } else if (arg === "--append-system-prompt" && i + 1 < args.length) {
97
101
  result.appendSystemPrompt = args[++i];
102
+ } else if (arg === "--provider-session-id" && i + 1 < args.length) {
103
+ result.providerSessionId = args[++i];
98
104
  } else if (arg === "--no-session") {
99
105
  result.noSession = true;
100
106
  } else if (arg === "--session-dir" && i + 1 < args.length) {
@@ -0,0 +1,58 @@
1
+ import type { ImageContent } from "@oh-my-pi/pi-ai";
2
+ import type { Args } from "./args";
3
+
4
+ export interface InitialMessageInput {
5
+ parsed: Args;
6
+ fileText?: string;
7
+ fileImages?: ImageContent[];
8
+ stdinContent?: string;
9
+ }
10
+
11
+ export interface InitialMessageResult {
12
+ initialMessage?: string;
13
+ initialImages?: ImageContent[];
14
+ }
15
+
16
+ /**
17
+ * Combine stdin content, @file text, and the first CLI message into a single
18
+ * initial prompt for non-interactive mode.
19
+ */
20
+ export function buildInitialMessage({
21
+ parsed,
22
+ fileText,
23
+ fileImages,
24
+ stdinContent,
25
+ }: InitialMessageInput): InitialMessageResult {
26
+ const hasInitialContext = stdinContent !== undefined || fileText !== undefined || (fileImages?.length ?? 0) > 0;
27
+ if (!hasInitialContext) {
28
+ return {
29
+ initialImages: undefined,
30
+ };
31
+ }
32
+
33
+ let body = "";
34
+ if (fileText !== undefined) {
35
+ body += fileText;
36
+ }
37
+
38
+ if (parsed.messages.length > 0) {
39
+ body += parsed.messages[0];
40
+ parsed.messages.shift();
41
+ }
42
+
43
+ const initialMessage =
44
+ stdinContent !== undefined
45
+ ? body.length > 0
46
+ ? `${stdinContent}\n${body}`
47
+ : stdinContent
48
+ : body.length > 0
49
+ ? body
50
+ : fileImages && fileImages.length > 0
51
+ ? ""
52
+ : undefined;
53
+
54
+ return {
55
+ initialMessage,
56
+ initialImages: fileImages && fileImages.length > 0 ? fileImages : undefined,
57
+ };
58
+ }