pi-ultracode 0.10.1 → 0.10.3
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/package.json +4 -2
- package/src/workflow/tool.ts +52 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-ultracode",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.3",
|
|
4
4
|
"description": "Adaptive semantic-depth workflow orchestration for Pi, with focused, standard, and deep modes, isolated subagents, worktree delivery, structured output, and durable resume.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -50,13 +50,15 @@
|
|
|
50
50
|
"typecheck": "tsc --noEmit"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"acorn": "^8.11.0"
|
|
53
|
+
"acorn": "^8.11.0",
|
|
54
|
+
"js-beautify": "^2.0.3"
|
|
54
55
|
},
|
|
55
56
|
"devDependencies": {
|
|
56
57
|
"@earendil-works/pi-agent-core": "^0.99.1",
|
|
57
58
|
"@earendil-works/pi-ai": "^0.99.1",
|
|
58
59
|
"@earendil-works/pi-coding-agent": "^0.99.1",
|
|
59
60
|
"@earendil-works/pi-tui": "^0.99.1",
|
|
61
|
+
"@types/js-beautify": "^1.14.3",
|
|
60
62
|
"@types/node": "^24.12.4",
|
|
61
63
|
"typebox": "1.3.7",
|
|
62
64
|
"typescript": "^5.9.3"
|
package/src/workflow/tool.ts
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
import * as crypto from "node:crypto";
|
|
8
8
|
import * as path from "node:path";
|
|
9
|
-
import { defineTool, type ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
10
|
-
import { Text } from "@earendil-works/pi-tui";
|
|
9
|
+
import { defineTool, highlightCode, type Theme, type ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
10
|
+
import { Box, Container, Spacer, Text } from "@earendil-works/pi-tui";
|
|
11
|
+
import beautify from "js-beautify";
|
|
11
12
|
import { Type } from "typebox";
|
|
12
13
|
import {
|
|
13
14
|
WORKFLOW_GUIDELINES,
|
|
@@ -122,7 +123,10 @@ function nextRunId(): string {
|
|
|
122
123
|
|
|
123
124
|
export function createWorkflowTool(deps: WorkflowToolDeps = {}): ToolDefinition<typeof workflowToolSchema, any> {
|
|
124
125
|
const registry = deps.registry ?? new WorkflowRegistry();
|
|
126
|
+
// Status updates rerender the call; format each completed display source only once.
|
|
127
|
+
let formattedSource: { input: string; output: string } | undefined;
|
|
125
128
|
return defineTool({
|
|
129
|
+
renderShell: "self",
|
|
126
130
|
name: "workflow",
|
|
127
131
|
exposure: "model-only",
|
|
128
132
|
annotations: {
|
|
@@ -603,30 +607,68 @@ export function createWorkflowTool(deps: WorkflowToolDeps = {}): ToolDefinition<
|
|
|
603
607
|
signal?.removeEventListener("abort", onOuterAbort);
|
|
604
608
|
}
|
|
605
609
|
},
|
|
606
|
-
renderCall(args, theme) {
|
|
610
|
+
renderCall(args, theme, { argsComplete }) {
|
|
607
611
|
const title = theme.fg("toolTitle", theme.bold("workflow"));
|
|
608
|
-
// Arguments arrive incrementally; display source without parsing incomplete JavaScript.
|
|
609
612
|
if (typeof args.script === "string" && args.script.length > 0) {
|
|
610
|
-
|
|
613
|
+
let source = safeTranscriptText(args.script, DISPLAY_INPUT_LIMIT);
|
|
614
|
+
// Never format an incomplete stream or change the script used for execution.
|
|
615
|
+
if (argsComplete) {
|
|
616
|
+
if (formattedSource?.input !== source) {
|
|
617
|
+
let output = source;
|
|
618
|
+
try {
|
|
619
|
+
output = beautify.js(source, { indent_size: 2, preserve_newlines: true, wrap_line_length: 100 });
|
|
620
|
+
} catch {
|
|
621
|
+
// A malformed or truncated display source can still be shown verbatim.
|
|
622
|
+
}
|
|
623
|
+
formattedSource = { input: source, output: safeTranscriptText(output, DISPLAY_INPUT_LIMIT) };
|
|
624
|
+
}
|
|
625
|
+
source = formattedSource.output;
|
|
626
|
+
}
|
|
627
|
+
const call = new Container();
|
|
628
|
+
call.addChild(new Text(title, 0, 0));
|
|
629
|
+
call.addChild(new Spacer(1));
|
|
630
|
+
call.addChild(workflowSection("Script · JavaScript", highlightCode(source, "javascript").join("\n"), theme, "toolPendingBg"));
|
|
631
|
+
return call;
|
|
611
632
|
}
|
|
612
633
|
const source = args.scriptPath || args.name;
|
|
613
634
|
return new Text(source ? `${title} ${theme.fg("muted", safeDisplayText(source, 240))}` : title, 0, 0);
|
|
614
635
|
},
|
|
615
|
-
renderResult(result, { isPartial, expanded }, theme) {
|
|
636
|
+
renderResult(result, { isPartial, expanded }, theme, context) {
|
|
616
637
|
const snapshot = result.details as WorkflowSnapshot | undefined;
|
|
638
|
+
const output = new Container();
|
|
639
|
+
output.addChild(new Spacer(1));
|
|
640
|
+
// Pi owns the pending/success/error background of the surrounding tool by
|
|
641
|
+
// default. With self framing, keep these states on the result panel only.
|
|
642
|
+
const background = isPartial ? "toolPendingBg"
|
|
643
|
+
: context.isError || snapshot?.status === "failed" || snapshot?.status === "aborted" ? "toolErrorBg" : "toolSuccessBg";
|
|
617
644
|
if (snapshot?.name) {
|
|
618
|
-
|
|
645
|
+
output.addChild(workflowSection("Status", renderWorkflowText(snapshot, {
|
|
619
646
|
maxAgentRows: expanded ? Number.MAX_SAFE_INTEGER : undefined,
|
|
620
647
|
maxLogs: expanded ? 12 : undefined,
|
|
621
648
|
showResultPreviews: expanded && !isPartial,
|
|
622
|
-
}),
|
|
649
|
+
}), theme, background));
|
|
650
|
+
} else {
|
|
651
|
+
const text = result.content?.[0];
|
|
652
|
+
output.addChild(workflowSection("Result", text?.type === "text" ? text.text : "workflow", theme, background));
|
|
623
653
|
}
|
|
624
|
-
|
|
625
|
-
return new Text(text?.type === "text" ? text.text : theme.fg("muted", "workflow"), 0, 0);
|
|
654
|
+
return output;
|
|
626
655
|
},
|
|
627
656
|
});
|
|
628
657
|
}
|
|
629
658
|
|
|
659
|
+
function workflowSection(
|
|
660
|
+
heading: string,
|
|
661
|
+
content: string,
|
|
662
|
+
theme: Theme,
|
|
663
|
+
background: "toolPendingBg" | "toolSuccessBg" | "toolErrorBg",
|
|
664
|
+
): Box {
|
|
665
|
+
const panel = new Box(1, 1, (text) => theme.bg(background, text));
|
|
666
|
+
panel.addChild(new Text(theme.fg("toolTitle", theme.bold(heading)), 0, 0));
|
|
667
|
+
panel.addChild(new Spacer(1));
|
|
668
|
+
panel.addChild(new Text(content, 0, 0));
|
|
669
|
+
return panel;
|
|
670
|
+
}
|
|
671
|
+
|
|
630
672
|
function resolveScript(
|
|
631
673
|
params: { script?: string; scriptPath?: string; name?: string },
|
|
632
674
|
cwd: string,
|