@oh-my-pi/pi-coding-agent 17.1.1 → 17.1.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.
- package/CHANGELOG.md +31 -0
- package/dist/cli.js +6216 -3984
- package/dist/types/cli/bench-cli.d.ts +1 -0
- package/dist/types/config/model-resolver.d.ts +6 -3
- package/dist/types/config/settings-schema.d.ts +4 -0
- package/dist/types/launch/broker-list-order.test.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +2 -6
- package/dist/types/modes/types.d.ts +8 -5
- package/dist/types/modes/utils/ui-helpers.d.ts +1 -6
- package/dist/types/task/executor.d.ts +3 -1
- package/dist/types/task/structured-subagent.d.ts +3 -0
- package/dist/types/task/types.d.ts +11 -11
- package/dist/types/thinking.d.ts +13 -0
- package/dist/types/tools/eval-format/index.d.ts +7 -0
- package/dist/types/tools/eval-format/javascript.d.ts +2 -0
- package/dist/types/tools/eval-format/julia.d.ts +2 -0
- package/dist/types/tools/eval-format/python.d.ts +2 -0
- package/dist/types/tools/eval-format/ruby.d.ts +2 -0
- package/dist/types/tools/resolve.d.ts +7 -0
- package/dist/types/tools/todo.d.ts +4 -1
- package/dist/types/web/search/providers/base.d.ts +16 -0
- package/dist/types/web/search/providers/brave.d.ts +2 -0
- package/dist/types/web/search/providers/firecrawl.d.ts +2 -0
- package/dist/types/web/search/providers/gemini.d.ts +3 -0
- package/dist/types/web/search/providers/jina.d.ts +2 -0
- package/dist/types/web/search/providers/kagi.d.ts +2 -0
- package/dist/types/web/search/providers/kimi.d.ts +2 -0
- package/dist/types/web/search/providers/parallel.d.ts +2 -0
- package/dist/types/web/search/providers/perplexity.d.ts +3 -0
- package/dist/types/web/search/providers/searxng.d.ts +10 -0
- package/dist/types/web/search/providers/tavily.d.ts +8 -0
- package/dist/types/web/search/query.d.ts +190 -0
- package/package.json +12 -12
- package/src/cli/bench-cli.ts +12 -1
- package/src/cli/web-search-cli.ts +7 -0
- package/src/config/model-resolver.ts +17 -6
- package/src/config/settings-schema.ts +5 -0
- package/src/debug/raw-sse-buffer.ts +157 -30
- package/src/export/share.ts +4 -3
- package/src/launch/broker-list-order.test.ts +89 -0
- package/src/launch/broker.ts +49 -8
- package/src/modes/controllers/input-controller.ts +8 -8
- package/src/modes/interactive-mode.ts +60 -5
- package/src/modes/types.ts +9 -4
- package/src/modes/utils/ui-helpers.ts +7 -8
- package/src/prompts/system/resolve-device-reminder.md +1 -1
- package/src/prompts/system/workflow-notice.md +1 -1
- package/src/prompts/tools/ast-edit.md +1 -0
- package/src/prompts/tools/bash.md +1 -0
- package/src/prompts/tools/eval.md +2 -2
- package/src/prompts/tools/task.md +5 -2
- package/src/prompts/tools/web-search.md +2 -0
- package/src/sdk.ts +8 -4
- package/src/session/agent-session.ts +14 -0
- package/src/session/queued-messages.ts +7 -1
- package/src/task/executor.ts +17 -9
- package/src/task/index.ts +14 -34
- package/src/task/structured-subagent.ts +4 -0
- package/src/task/types.ts +15 -13
- package/src/thinking.ts +27 -0
- package/src/tools/ast-edit.ts +4 -1
- package/src/tools/bash.ts +13 -0
- package/src/tools/browser/render.ts +2 -1
- package/src/tools/eval-format/index.ts +24 -0
- package/src/tools/eval-format/javascript.ts +952 -0
- package/src/tools/eval-format/julia.ts +446 -0
- package/src/tools/eval-format/python.ts +544 -0
- package/src/tools/eval-format/ruby.ts +380 -0
- package/src/tools/eval-render.ts +12 -6
- package/src/tools/resolve.ts +10 -1
- package/src/tools/todo.ts +58 -6
- package/src/web/search/index.ts +28 -5
- package/src/web/search/providers/anthropic.ts +62 -4
- package/src/web/search/providers/base.ts +16 -0
- package/src/web/search/providers/brave.ts +30 -3
- package/src/web/search/providers/codex.ts +14 -1
- package/src/web/search/providers/duckduckgo.ts +23 -1
- package/src/web/search/providers/ecosia.ts +5 -1
- package/src/web/search/providers/exa.ts +28 -1
- package/src/web/search/providers/firecrawl.ts +37 -3
- package/src/web/search/providers/gemini.ts +12 -2
- package/src/web/search/providers/google.ts +2 -1
- package/src/web/search/providers/jina.ts +31 -8
- package/src/web/search/providers/kagi.ts +10 -1
- package/src/web/search/providers/kimi.ts +16 -1
- package/src/web/search/providers/mojeek.ts +14 -1
- package/src/web/search/providers/parallel.ts +48 -2
- package/src/web/search/providers/perplexity.ts +94 -6
- package/src/web/search/providers/searxng.ts +145 -9
- package/src/web/search/providers/startpage.ts +8 -2
- package/src/web/search/providers/synthetic.ts +7 -1
- package/src/web/search/providers/tavily.ts +52 -3
- package/src/web/search/providers/tinyfish.ts +6 -1
- package/src/web/search/providers/xai.ts +49 -2
- package/src/web/search/providers/zai.ts +19 -1
- package/src/web/search/query.ts +850 -0
package/src/task/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ import subagentUserPromptTemplate from "../prompts/system/subagent-user-prompt.m
|
|
|
23
23
|
import taskDescriptionTemplate from "../prompts/tools/task.md" with { type: "text" };
|
|
24
24
|
import taskAsyncContractTemplate from "../prompts/tools/task-async-contract.md" with { type: "text" };
|
|
25
25
|
import taskSummaryTemplate from "../prompts/tools/task-summary.md" with { type: "text" };
|
|
26
|
+
import { TASK_EFFORTS, type TaskEffort } from "../thinking";
|
|
26
27
|
import { truncateForPrompt } from "../tools/approval";
|
|
27
28
|
import { isIrcEnabled } from "../tools/hub";
|
|
28
29
|
import { formatBytes, formatDuration } from "../tools/render-utils";
|
|
@@ -231,17 +232,11 @@ function validateShapeParams(batchEnabled: boolean, params: TaskParams): string
|
|
|
231
232
|
* policy later, in `spawnParamsFor`. Returns a problem description, or
|
|
232
233
|
* undefined when valid.
|
|
233
234
|
*/
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
return (
|
|
239
|
-
!selectors ||
|
|
240
|
-
materializedSelectors.length === 0 ||
|
|
241
|
-
materializedSelectors.some(
|
|
242
|
-
selector => typeof selector !== "string" || !selector.split(",").some(pattern => pattern.trim()),
|
|
243
|
-
)
|
|
244
|
-
);
|
|
235
|
+
|
|
236
|
+
/** Reject an out-of-range `effort` selector on internal/stale-transcript calls that bypass the wire schema. */
|
|
237
|
+
function validateEffort(effort: TaskEffort | undefined, label: string): string | undefined {
|
|
238
|
+
if (effort === undefined || TASK_EFFORTS.includes(effort)) return undefined;
|
|
239
|
+
return `${label} has an invalid \`effort\` value ${JSON.stringify(effort)}. Use "lo", "med", or "hi".`;
|
|
245
240
|
}
|
|
246
241
|
|
|
247
242
|
function validateSpawnParams(params: TaskParams, batchEnabled: boolean): string | undefined {
|
|
@@ -259,9 +254,8 @@ function validateSpawnParams(params: TaskParams, batchEnabled: boolean): string
|
|
|
259
254
|
if (!item || typeof item.task !== "string" || item.task.trim() === "") {
|
|
260
255
|
return `Task ${i + 1}${item?.name ? ` (\`${item.name}\`)` : ""} is missing \`task\`. Every task needs complete, self-contained instructions.`;
|
|
261
256
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}
|
|
257
|
+
const effortError = validateEffort(item.effort, `Task ${i + 1}${item.name ? ` (\`${item.name}\`)` : ""}`);
|
|
258
|
+
if (effortError) return effortError;
|
|
265
259
|
}
|
|
266
260
|
const seen = new Map<string, string>();
|
|
267
261
|
for (const item of tasks) {
|
|
@@ -284,10 +278,7 @@ function validateSpawnParams(params: TaskParams, batchEnabled: boolean): string
|
|
|
284
278
|
? "Missing `tasks`. Provide a `tasks` array (one subagent per item) with a shared `context`."
|
|
285
279
|
: "Missing `task`. Provide complete, self-contained instructions for the agent.";
|
|
286
280
|
}
|
|
287
|
-
|
|
288
|
-
return "Invalid `model`. Provide a non-empty selector or a non-empty array of non-empty selectors.";
|
|
289
|
-
}
|
|
290
|
-
return undefined;
|
|
281
|
+
return validateEffort(params.effort, "The call");
|
|
291
282
|
}
|
|
292
283
|
|
|
293
284
|
/**
|
|
@@ -300,9 +291,10 @@ function resolveSpawnItems(params: TaskParams): TaskItem[] {
|
|
|
300
291
|
if (Array.isArray(params.tasks) && params.tasks.length > 0) {
|
|
301
292
|
return params.tasks;
|
|
302
293
|
}
|
|
303
|
-
const item: TaskItem = { name: params.name, agent: params.agent, task: params.task
|
|
294
|
+
const item: TaskItem = { name: params.name, agent: params.agent, task: params.task };
|
|
304
295
|
if ("outputSchema" in params) item.outputSchema = params.outputSchema;
|
|
305
296
|
if ("schemaMode" in params) item.schemaMode = params.schemaMode;
|
|
297
|
+
if ("effort" in params) item.effort = params.effort;
|
|
306
298
|
if ("isolated" in params) item.isolated = params.isolated;
|
|
307
299
|
return [item];
|
|
308
300
|
}
|
|
@@ -320,10 +312,10 @@ function spawnParamsFor(params: TaskParams, item: TaskItem, defaultAgent: string
|
|
|
320
312
|
const spawn: TaskParams = { agent: item.agent?.trim() || defaultAgent };
|
|
321
313
|
if (item.name !== undefined) spawn.name = item.name;
|
|
322
314
|
if (item.task !== undefined) spawn.task = item.task;
|
|
323
|
-
if (item.model !== undefined) spawn.model = item.model;
|
|
324
315
|
if (params.context !== undefined) spawn.context = params.context;
|
|
325
316
|
if ("outputSchema" in item) spawn.outputSchema = item.outputSchema;
|
|
326
317
|
if ("schemaMode" in item) spawn.schemaMode = item.schemaMode;
|
|
318
|
+
if ("effort" in item) spawn.effort = item.effort;
|
|
327
319
|
if (item.isolated !== undefined) {
|
|
328
320
|
spawn.isolated = item.isolated;
|
|
329
321
|
} else if ("isolated" in params) {
|
|
@@ -491,14 +483,6 @@ function discoverAgentsForCreate(cwd: string): Promise<DiscoveryResult> {
|
|
|
491
483
|
return pending;
|
|
492
484
|
}
|
|
493
485
|
|
|
494
|
-
function formatModelForApproval(model: unknown): string | undefined {
|
|
495
|
-
const selectors = typeof model === "string" ? [model] : Array.isArray(model) ? model : [];
|
|
496
|
-
const normalized = selectors.filter(
|
|
497
|
-
(selector): selector is string => typeof selector === "string" && !!selector.trim(),
|
|
498
|
-
);
|
|
499
|
-
return normalized.length > 0 ? truncateForPrompt(normalized.join(" → ")) : undefined;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
486
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
503
487
|
// Tool Class
|
|
504
488
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -522,8 +506,6 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
522
506
|
if (typeof params.name === "string" && params.name.trim()) {
|
|
523
507
|
lines.push(`Name: ${truncateForPrompt(params.name)}`);
|
|
524
508
|
}
|
|
525
|
-
const model = formatModelForApproval(params.model);
|
|
526
|
-
if (model) lines.push(`Model: ${model}`);
|
|
527
509
|
if (typeof params.task === "string") {
|
|
528
510
|
lines.push(`Task:\n${truncateForPrompt(params.task)}`);
|
|
529
511
|
}
|
|
@@ -554,8 +536,6 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
554
536
|
lines.push(`Name: ${truncateForPrompt(firstTask.name)}`);
|
|
555
537
|
}
|
|
556
538
|
lines.push(`Agent: ${truncateForPrompt(effectiveAgent(firstTask))}`);
|
|
557
|
-
const itemModel = formatModelForApproval("model" in firstTask ? firstTask.model : undefined);
|
|
558
|
-
if (itemModel) lines.push(`Model: ${itemModel}`);
|
|
559
539
|
if ("task" in firstTask && typeof firstTask.task === "string") {
|
|
560
540
|
lines.push(`Task:\n${truncateForPrompt(firstTask.task)}`);
|
|
561
541
|
}
|
|
@@ -663,9 +643,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
663
643
|
assignment: (params.task ?? "").trim(),
|
|
664
644
|
context: this.#isBatchEnabled() ? params.context?.trim() || undefined : undefined,
|
|
665
645
|
agent: params.agent,
|
|
666
|
-
model: params.model,
|
|
667
646
|
...(Object.hasOwn(params, "outputSchema") ? { outputSchema: params.outputSchema } : {}),
|
|
668
647
|
...(Object.hasOwn(params, "schemaMode") ? { schemaMode: params.schemaMode } : {}),
|
|
648
|
+
...(params.effort !== undefined ? { effort: params.effort } : {}),
|
|
669
649
|
...("isolated" in params ? { isolation: { requested: params.isolated } } : {}),
|
|
670
650
|
blockedAgent: this.#blockedAgent,
|
|
671
651
|
enableLsp: (this.session.enableLsp ?? true) && this.session.settings.get("task.enableLsp"),
|
|
@@ -1419,9 +1399,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1419
1399
|
assignment,
|
|
1420
1400
|
context,
|
|
1421
1401
|
agent: params.agent,
|
|
1422
|
-
model: params.model,
|
|
1423
1402
|
...(Object.hasOwn(params, "outputSchema") ? { outputSchema: params.outputSchema } : {}),
|
|
1424
1403
|
...(Object.hasOwn(params, "schemaMode") ? { schemaMode: params.schemaMode } : {}),
|
|
1404
|
+
...(params.effort !== undefined ? { effort: params.effort } : {}),
|
|
1425
1405
|
identity: { id: preAllocatedId, label: params.name },
|
|
1426
1406
|
index: spawnIndex,
|
|
1427
1407
|
parentToolCallId: toolCallId,
|
|
@@ -16,6 +16,7 @@ import { loadOverallPlanReference } from "../plan-mode/plan-handoff";
|
|
|
16
16
|
import planModeSubagentPrompt from "../prompts/system/plan-mode-subagent.md" with { type: "text" };
|
|
17
17
|
import subagentUserPromptTemplate from "../prompts/system/subagent-user-prompt.md" with { type: "text" };
|
|
18
18
|
import { MAIN_AGENT_ID } from "../registry/agent-registry";
|
|
19
|
+
import type { TaskEffort } from "../thinking";
|
|
19
20
|
import type { ToolSession } from "../tools";
|
|
20
21
|
import { isIrcEnabled } from "../tools/hub";
|
|
21
22
|
import { buildOutputValidator } from "../tools/output-schema-validator";
|
|
@@ -87,6 +88,8 @@ export interface StructuredSubagentRequest {
|
|
|
87
88
|
/** Presence, rather than truthiness, makes this the highest-priority schema. */
|
|
88
89
|
outputSchema?: unknown;
|
|
89
90
|
schemaMode?: StructuredSubagentSchemaMode;
|
|
91
|
+
/** Per-spawn thinking effort mapped onto the resolved model's supported range; overrides the agent's default selector. */
|
|
92
|
+
effort?: TaskEffort;
|
|
90
93
|
identity?: StructuredSubagentIdentity;
|
|
91
94
|
index?: number;
|
|
92
95
|
parentToolCallId?: string;
|
|
@@ -390,6 +393,7 @@ function buildExecutorOptions(
|
|
|
390
393
|
modelOverride: policy.modelOverride,
|
|
391
394
|
parentActiveModelPattern: policy.parentActiveModelPattern,
|
|
392
395
|
thinkingLevel: policy.effectiveAgent.thinkingLevel,
|
|
396
|
+
effort: request.effort,
|
|
393
397
|
...(policy.schema.source === "none"
|
|
394
398
|
? {}
|
|
395
399
|
: {
|
package/src/task/types.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Usage } from "@oh-my-pi/pi-ai";
|
|
|
2
2
|
import { $env } from "@oh-my-pi/pi-utils";
|
|
3
3
|
import { type BaseType, type } from "arktype";
|
|
4
4
|
import type { AgentSessionEvent } from "../session/agent-session";
|
|
5
|
-
import type { ConfiguredThinkingLevel } from "../thinking";
|
|
5
|
+
import type { ConfiguredThinkingLevel, TaskEffort } from "../thinking";
|
|
6
6
|
import type { NestedRepoPatch } from "./worktree";
|
|
7
7
|
|
|
8
8
|
/** Source of an agent definition */
|
|
@@ -108,12 +108,14 @@ export const LABEL_MAX = 80;
|
|
|
108
108
|
|
|
109
109
|
// Keep this explicit: ArkType serializes `unknown` as a boolean subschema, which llama.cpp grammars reject.
|
|
110
110
|
const outputSchemaInputSchema = type("object | boolean | string | null");
|
|
111
|
+
// Coarse per-spawn thinking effort; must stay in sync with TASK_EFFORTS in ../thinking.
|
|
112
|
+
const effortRule = '"lo" | "med" | "hi"' as const;
|
|
111
113
|
|
|
112
114
|
export const taskItemSchema = type({
|
|
113
115
|
"name?": "string",
|
|
114
116
|
agent: "string = 'task'",
|
|
115
117
|
task: "string",
|
|
116
|
-
"
|
|
118
|
+
"effort?": effortRule,
|
|
117
119
|
"outputSchema?": outputSchemaInputSchema,
|
|
118
120
|
"schemaMode?": '"permissive" | "strict"',
|
|
119
121
|
"+": "delete",
|
|
@@ -122,7 +124,7 @@ const taskItemSchemaIsolated = type({
|
|
|
122
124
|
"name?": "string",
|
|
123
125
|
agent: "string = 'task'",
|
|
124
126
|
task: "string",
|
|
125
|
-
"
|
|
127
|
+
"effort?": effortRule,
|
|
126
128
|
"outputSchema?": outputSchemaInputSchema,
|
|
127
129
|
"schemaMode?": '"permissive" | "strict"',
|
|
128
130
|
"isolated?": "boolean",
|
|
@@ -137,8 +139,8 @@ export interface TaskItem {
|
|
|
137
139
|
agent?: string;
|
|
138
140
|
/** The work; required by the schema. */
|
|
139
141
|
task?: string;
|
|
140
|
-
/**
|
|
141
|
-
|
|
142
|
+
/** Per-spawn thinking effort: lowest/middle/highest level the resolved model supports. Overrides the agent's default selector (e.g. `auto`). */
|
|
143
|
+
effort?: TaskEffort;
|
|
142
144
|
/** Caller-provided output schema; its presence overrides the selected agent's schema. */
|
|
143
145
|
outputSchema?: unknown;
|
|
144
146
|
/** Validation behavior for a caller-provided or inherited output schema. */
|
|
@@ -151,7 +153,7 @@ export const taskSchema = type({
|
|
|
151
153
|
"name?": "string",
|
|
152
154
|
agent: "string = 'task'",
|
|
153
155
|
task: "string",
|
|
154
|
-
"
|
|
156
|
+
"effort?": effortRule,
|
|
155
157
|
"outputSchema?": outputSchemaInputSchema,
|
|
156
158
|
"schemaMode?": '"permissive" | "strict"',
|
|
157
159
|
"isolated?": "boolean",
|
|
@@ -161,7 +163,7 @@ const taskSchemaNoIsolation = type({
|
|
|
161
163
|
"name?": "string",
|
|
162
164
|
agent: "string = 'task'",
|
|
163
165
|
task: "string",
|
|
164
|
-
"
|
|
166
|
+
"effort?": effortRule,
|
|
165
167
|
"outputSchema?": outputSchemaInputSchema,
|
|
166
168
|
"schemaMode?": '"permissive" | "strict"',
|
|
167
169
|
"+": "delete",
|
|
@@ -206,7 +208,7 @@ function createTaskSchema(options: {
|
|
|
206
208
|
"name?": "string",
|
|
207
209
|
agent,
|
|
208
210
|
task: "string",
|
|
209
|
-
"
|
|
211
|
+
"effort?": effortRule,
|
|
210
212
|
"outputSchema?": outputSchemaInputSchema,
|
|
211
213
|
"schemaMode?": '"permissive" | "strict"',
|
|
212
214
|
"isolated?": "boolean",
|
|
@@ -222,7 +224,7 @@ function createTaskSchema(options: {
|
|
|
222
224
|
"name?": "string",
|
|
223
225
|
agent,
|
|
224
226
|
task: "string",
|
|
225
|
-
"
|
|
227
|
+
"effort?": effortRule,
|
|
226
228
|
"outputSchema?": outputSchemaInputSchema,
|
|
227
229
|
"schemaMode?": '"permissive" | "strict"',
|
|
228
230
|
"+": "delete",
|
|
@@ -238,7 +240,7 @@ function createTaskSchema(options: {
|
|
|
238
240
|
"name?": "string",
|
|
239
241
|
agent,
|
|
240
242
|
task: "string",
|
|
241
|
-
"
|
|
243
|
+
"effort?": effortRule,
|
|
242
244
|
"outputSchema?": outputSchemaInputSchema,
|
|
243
245
|
"schemaMode?": '"permissive" | "strict"',
|
|
244
246
|
"isolated?": "boolean",
|
|
@@ -249,7 +251,7 @@ function createTaskSchema(options: {
|
|
|
249
251
|
"name?": "string",
|
|
250
252
|
agent,
|
|
251
253
|
task: "string",
|
|
252
|
-
"
|
|
254
|
+
"effort?": effortRule,
|
|
253
255
|
"outputSchema?": outputSchemaInputSchema,
|
|
254
256
|
"schemaMode?": '"permissive" | "strict"',
|
|
255
257
|
"+": "delete",
|
|
@@ -293,8 +295,8 @@ export interface TaskParams {
|
|
|
293
295
|
agent?: string;
|
|
294
296
|
/** The work (flat form). */
|
|
295
297
|
task?: string;
|
|
296
|
-
/**
|
|
297
|
-
|
|
298
|
+
/** Per-spawn thinking effort (flat form): lowest/middle/highest level the resolved model supports. */
|
|
299
|
+
effort?: TaskEffort;
|
|
298
300
|
/** Caller-provided output schema; its presence overrides the selected agent's schema. */
|
|
299
301
|
outputSchema?: unknown;
|
|
300
302
|
/** Validation behavior for a caller-provided or inherited output schema. */
|
package/src/thinking.ts
CHANGED
|
@@ -220,6 +220,33 @@ export function clampAutoThinkingEffort(model: Model | undefined, effort: Effort
|
|
|
220
220
|
return chosen;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
+
/** Coarse per-spawn effort selectors accepted by the task tool. */
|
|
224
|
+
export const TASK_EFFORTS = ["lo", "med", "hi"] as const;
|
|
225
|
+
|
|
226
|
+
/** Coarse task-spawn effort: the lowest, middle, or highest thinking level the target model supports. */
|
|
227
|
+
export type TaskEffort = (typeof TASK_EFFORTS)[number];
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Maps a coarse task effort onto the model's supported thinking range:
|
|
231
|
+
* `lo` = lowest supported level, `hi` = highest (whatever the model tops out
|
|
232
|
+
* at — high, xhigh, or max), `med` = the middle (lower of the two middles for
|
|
233
|
+
* an even-sized range). Without a model, maps over the full canonical range.
|
|
234
|
+
* Returns `undefined` when the model has no controllable effort surface, so
|
|
235
|
+
* callers fall back to their default selector (e.g. `auto`).
|
|
236
|
+
*/
|
|
237
|
+
export function resolveTaskEffortLevel(model: Model | undefined, effort: TaskEffort): Effort | undefined {
|
|
238
|
+
const supported = model ? getSupportedEfforts(model) : THINKING_EFFORTS;
|
|
239
|
+
if (supported.length === 0) return undefined;
|
|
240
|
+
switch (effort) {
|
|
241
|
+
case "lo":
|
|
242
|
+
return supported[0];
|
|
243
|
+
case "med":
|
|
244
|
+
return supported[(supported.length - 1) >> 1];
|
|
245
|
+
case "hi":
|
|
246
|
+
return supported[supported.length - 1];
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
223
250
|
/**
|
|
224
251
|
* The provisional concrete level shown while `auto` is configured but before a
|
|
225
252
|
* turn has been classified. Prefers the model's `defaultLevel`, otherwise High,
|
package/src/tools/ast-edit.ts
CHANGED
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
formatParseErrorsCountLabel,
|
|
33
33
|
PREVIEW_LIMITS,
|
|
34
34
|
} from "./render-utils";
|
|
35
|
-
import { queueResolveHandler } from "./resolve";
|
|
35
|
+
import { PREVIEW_PENDING_NOTICE, queueResolveHandler } from "./resolve";
|
|
36
36
|
import { ToolError } from "./tool-errors";
|
|
37
37
|
import { toolResult } from "./tool-result";
|
|
38
38
|
|
|
@@ -520,6 +520,9 @@ export class AstEditTool implements AgentTool<typeof astEditSchema, AstEditToolD
|
|
|
520
520
|
return toolResult(appliedDetails).text(text).done();
|
|
521
521
|
},
|
|
522
522
|
});
|
|
523
|
+
// The renderer's ⟨proposed⟩ badge is TUI-only; this line is the model's
|
|
524
|
+
// in-result signal that the diff above is staged, not applied.
|
|
525
|
+
outputLines.unshift(PREVIEW_PENDING_NOTICE, "");
|
|
523
526
|
}
|
|
524
527
|
|
|
525
528
|
const details: AstEditToolDetails = {
|
package/src/tools/bash.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type { Component } from "@oh-my-pi/pi-tui";
|
|
|
10
10
|
import { ImageProtocol, TERMINAL } from "@oh-my-pi/pi-tui";
|
|
11
11
|
import { getProjectDir, isEnoent, logger, prompt } from "@oh-my-pi/pi-utils";
|
|
12
12
|
import { type } from "arktype";
|
|
13
|
+
import type { Settings } from "../config/settings";
|
|
13
14
|
import { applyDirenvPreflight, type BashResult, executeBash } from "../exec/bash-executor";
|
|
14
15
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
15
16
|
import { InternalUrlRouter } from "../internal-urls";
|
|
@@ -85,6 +86,16 @@ export function wrapShellLineForClientTerminal(
|
|
|
85
86
|
return { command: shellConfig.shell, args: [...shellConfig.args, finalLine] };
|
|
86
87
|
}
|
|
87
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Mirrors pi-shell's `uutils_env_disabled` gate for `PI_DISABLE_UUTILS_BUILTINS`:
|
|
91
|
+
* session shell env first, then process env; truthy = present and not "", "0",
|
|
92
|
+
* or "false". Controls whether the prompt advertises the in-process builtins.
|
|
93
|
+
*/
|
|
94
|
+
function shellBuiltinsDisabled(settings: Settings): boolean {
|
|
95
|
+
const raw = settings.getShellConfig().env?.PI_DISABLE_UUTILS_BUILTINS ?? Bun.env.PI_DISABLE_UUTILS_BUILTINS;
|
|
96
|
+
return !!raw && raw !== "0" && raw.toLowerCase() !== "false";
|
|
97
|
+
}
|
|
98
|
+
|
|
88
99
|
/**
|
|
89
100
|
* Bash patterns flagged as safety critical for approval policy.
|
|
90
101
|
*
|
|
@@ -496,6 +507,8 @@ export class BashTool implements AgentTool<typeof bashSchemaBase | typeof bashSc
|
|
|
496
507
|
"eval",
|
|
497
508
|
evalBackends.python || evalBackends.js || evalBackends.ruby || evalBackends.julia,
|
|
498
509
|
),
|
|
510
|
+
hasShellBuiltins: !shellBuiltinsDisabled(this.session.settings),
|
|
511
|
+
isWindows: process.platform === "win32",
|
|
499
512
|
});
|
|
500
513
|
}
|
|
501
514
|
readonly parameters: BashToolSchema;
|
|
@@ -11,6 +11,7 @@ import type { RenderResultOptions } from "../../extensibility/custom-tools/types
|
|
|
11
11
|
import type { Theme } from "../../modes/theme/theme";
|
|
12
12
|
import { Hasher, isFramedBlockComponent, markFramedBlockComponent, renderCodeCell, renderStatusLine } from "../../tui";
|
|
13
13
|
import type { BrowserToolDetails } from "../browser";
|
|
14
|
+
import { formatJavaScriptForDisplay } from "../eval-format/javascript";
|
|
14
15
|
import { formatStyledTruncationWarning, stripOutputNotice } from "../output-meta";
|
|
15
16
|
import { replaceTabs, shortenPath } from "../render-utils";
|
|
16
17
|
|
|
@@ -90,7 +91,7 @@ function renderRunCell(
|
|
|
90
91
|
isError: boolean,
|
|
91
92
|
theme: Theme,
|
|
92
93
|
): Component {
|
|
93
|
-
const code = dropTrailingBlankLines(args.code ?? "");
|
|
94
|
+
const code = formatJavaScriptForDisplay(dropTrailingBlankLines(args.code ?? ""));
|
|
94
95
|
const status = cellStatus(options.isPartial, isError);
|
|
95
96
|
|
|
96
97
|
const titleParts: string[] = [tabLabel(args, details)];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { EvalLanguage } from "../../eval/types";
|
|
2
|
+
import { formatJavaScriptForDisplay } from "./javascript";
|
|
3
|
+
import { formatJuliaForDisplay } from "./julia";
|
|
4
|
+
import { formatPythonForDisplay } from "./python";
|
|
5
|
+
import { formatRubyForDisplay } from "./ruby";
|
|
6
|
+
|
|
7
|
+
export * from "./javascript";
|
|
8
|
+
export * from "./julia";
|
|
9
|
+
export * from "./python";
|
|
10
|
+
export * from "./ruby";
|
|
11
|
+
|
|
12
|
+
/** Formats an arbitrary eval-code prefix for display without changing the executed source. */
|
|
13
|
+
export function formatEvalCodeForDisplay(source: string, language: EvalLanguage): string {
|
|
14
|
+
switch (language) {
|
|
15
|
+
case "js":
|
|
16
|
+
return formatJavaScriptForDisplay(source);
|
|
17
|
+
case "ruby":
|
|
18
|
+
return formatRubyForDisplay(source);
|
|
19
|
+
case "julia":
|
|
20
|
+
return formatJuliaForDisplay(source);
|
|
21
|
+
case "python":
|
|
22
|
+
return formatPythonForDisplay(source);
|
|
23
|
+
}
|
|
24
|
+
}
|