pi-landstrip 0.18.9 → 0.18.11
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/dist/index.ts +102 -5
- package/package.json +4 -4
package/dist/index.ts
CHANGED
|
@@ -1865,6 +1865,7 @@ function taskDetails(task, state = task.state) {
|
|
|
1865
1865
|
currentTool: task.currentTool,
|
|
1866
1866
|
toolCalls: task.toolCalls,
|
|
1867
1867
|
retryAttempt: task.retryAttempt,
|
|
1868
|
+
usage: task.usage ? { ...task.usage } : undefined,
|
|
1868
1869
|
startedAt: task.startedAt,
|
|
1869
1870
|
finishedAt: task.finishedAt,
|
|
1870
1871
|
output: task.output,
|
|
@@ -1878,6 +1879,78 @@ function taskDuration(details) {
|
|
|
1878
1879
|
const seconds = Math.max(0, end - details.startedAt) / 1000;
|
|
1879
1880
|
return seconds < 10 ? `${seconds.toFixed(1)}s` : `${Math.round(seconds)}s`;
|
|
1880
1881
|
}
|
|
1882
|
+
function usageNumber(value) {
|
|
1883
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
1884
|
+
}
|
|
1885
|
+
function isTaskUsage(value) {
|
|
1886
|
+
return isRecord2(value) && usageNumber(value.input) && usageNumber(value.output) && usageNumber(value.cacheRead) && usageNumber(value.cacheWrite) && usageNumber(value.cost) && usageNumber(value.turns) && Number.isInteger(value.turns);
|
|
1887
|
+
}
|
|
1888
|
+
function taskUsageFromMessage(message) {
|
|
1889
|
+
if (!isRecord2(message) || message.role !== "assistant" || !isRecord2(message.usage))
|
|
1890
|
+
return;
|
|
1891
|
+
const usage = message.usage;
|
|
1892
|
+
if (!usageNumber(usage.input) || !usageNumber(usage.output) || !usageNumber(usage.cacheRead) || !usageNumber(usage.cacheWrite) || !isRecord2(usage.cost) || !usageNumber(usage.cost.total)) {
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1895
|
+
return {
|
|
1896
|
+
input: usage.input,
|
|
1897
|
+
output: usage.output,
|
|
1898
|
+
cacheRead: usage.cacheRead,
|
|
1899
|
+
cacheWrite: usage.cacheWrite,
|
|
1900
|
+
cost: usage.cost.total,
|
|
1901
|
+
turns: 1
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1904
|
+
function addTaskUsage(current, added) {
|
|
1905
|
+
return {
|
|
1906
|
+
input: (current?.input ?? 0) + added.input,
|
|
1907
|
+
output: (current?.output ?? 0) + added.output,
|
|
1908
|
+
cacheRead: (current?.cacheRead ?? 0) + added.cacheRead,
|
|
1909
|
+
cacheWrite: (current?.cacheWrite ?? 0) + added.cacheWrite,
|
|
1910
|
+
cost: (current?.cost ?? 0) + added.cost,
|
|
1911
|
+
turns: (current?.turns ?? 0) + added.turns
|
|
1912
|
+
};
|
|
1913
|
+
}
|
|
1914
|
+
function formatTokens(count) {
|
|
1915
|
+
if (count < 1000)
|
|
1916
|
+
return String(count);
|
|
1917
|
+
if (count < 1e4)
|
|
1918
|
+
return `${(count / 1000).toFixed(1)}k`;
|
|
1919
|
+
if (count < 1e6)
|
|
1920
|
+
return `${Math.round(count / 1000)}k`;
|
|
1921
|
+
if (count < 1e7)
|
|
1922
|
+
return `${(count / 1e6).toFixed(1)}M`;
|
|
1923
|
+
return `${Math.round(count / 1e6)}M`;
|
|
1924
|
+
}
|
|
1925
|
+
function formatTaskUsage(usage) {
|
|
1926
|
+
if (!usage)
|
|
1927
|
+
return;
|
|
1928
|
+
const parts = [];
|
|
1929
|
+
if (usage.turns)
|
|
1930
|
+
parts.push(`${usage.turns} turn${usage.turns === 1 ? "" : "s"}`);
|
|
1931
|
+
if (usage.input)
|
|
1932
|
+
parts.push(`in:${formatTokens(usage.input)}`);
|
|
1933
|
+
if (usage.output)
|
|
1934
|
+
parts.push(`out:${formatTokens(usage.output)}`);
|
|
1935
|
+
if (usage.cacheRead)
|
|
1936
|
+
parts.push(`R${formatTokens(usage.cacheRead)}`);
|
|
1937
|
+
if (usage.cacheWrite)
|
|
1938
|
+
parts.push(`W${formatTokens(usage.cacheWrite)}`);
|
|
1939
|
+
if (usage.cost)
|
|
1940
|
+
parts.push(`$${usage.cost.toFixed(4)}`);
|
|
1941
|
+
return parts.length > 0 ? parts.join(" ") : undefined;
|
|
1942
|
+
}
|
|
1943
|
+
function formatTaskUsageSummary(usage) {
|
|
1944
|
+
if (!usage)
|
|
1945
|
+
return;
|
|
1946
|
+
const parts = [];
|
|
1947
|
+
const tokens = usage.input + usage.output;
|
|
1948
|
+
if (tokens)
|
|
1949
|
+
parts.push(`${formatTokens(tokens)} tok`);
|
|
1950
|
+
if (usage.cost)
|
|
1951
|
+
parts.push(`$${usage.cost.toFixed(4)}`);
|
|
1952
|
+
return parts.length > 0 ? parts.join(" ") : undefined;
|
|
1953
|
+
}
|
|
1881
1954
|
function activeTaskRecords(tasks) {
|
|
1882
1955
|
const byId = new Map(tasks.map((task) => [task.id, task]));
|
|
1883
1956
|
const visibleIds = new Set;
|
|
@@ -1905,6 +1978,9 @@ function taskProgress(task) {
|
|
|
1905
1978
|
if (task.toolCalls !== undefined) {
|
|
1906
1979
|
progress.push(`${task.toolCalls} call${task.toolCalls === 1 ? "" : "s"}`);
|
|
1907
1980
|
}
|
|
1981
|
+
const usage = formatTaskUsageSummary(task.usage);
|
|
1982
|
+
if (usage)
|
|
1983
|
+
progress.push(usage);
|
|
1908
1984
|
const duration = taskDuration(taskDetails(task));
|
|
1909
1985
|
if (duration)
|
|
1910
1986
|
progress.push(duration);
|
|
@@ -2256,8 +2332,10 @@ function parseControlResponse(value) {
|
|
|
2256
2332
|
if (response.value !== undefined && typeof response.value !== "string") {
|
|
2257
2333
|
throw new Error("Invalid supervisor response value");
|
|
2258
2334
|
}
|
|
2259
|
-
if (response.task !== undefined
|
|
2260
|
-
|
|
2335
|
+
if (response.task !== undefined) {
|
|
2336
|
+
if (!isRecord2(response.task) || typeof response.task.taskId !== "string" || typeof response.task.state !== "string" || !TASK_STATES.has(response.task.state) || typeof response.task.agent !== "string" || response.task.usage !== undefined && !isTaskUsage(response.task.usage)) {
|
|
2337
|
+
throw new Error("Invalid supervisor task response");
|
|
2338
|
+
}
|
|
2261
2339
|
}
|
|
2262
2340
|
return response;
|
|
2263
2341
|
}
|
|
@@ -2675,11 +2753,13 @@ ${this.primaryAgent.prompt}` };
|
|
|
2675
2753
|
task.toolCalls === undefined ? undefined : `${task.toolCalls} tool call${task.toolCalls === 1 ? "" : "s"}`,
|
|
2676
2754
|
duration
|
|
2677
2755
|
].filter(Boolean);
|
|
2756
|
+
const usage = formatTaskUsage(task.usage);
|
|
2678
2757
|
const lines = [
|
|
2679
2758
|
tabs,
|
|
2680
2759
|
"",
|
|
2681
2760
|
`${theme.fg("accent", theme.bold(`@${task.agent}`))} ${theme.fg("text", task.description)}`,
|
|
2682
2761
|
`${taskState(theme, task)} ${theme.fg("dim", metrics.join(" · "))} ${theme.fg("dim", "·")} ${theme.fg(follow ? "accent" : "muted", `Follow: ${follow ? "on" : "off"}`)}`,
|
|
2762
|
+
...usage ? [theme.fg("dim", usage)] : [],
|
|
2683
2763
|
"",
|
|
2684
2764
|
...shown.map((line) => theme.fg("toolOutput", line))
|
|
2685
2765
|
];
|
|
@@ -3086,6 +3166,9 @@ ${descriptions}` : ""),
|
|
|
3086
3166
|
const duration = taskDuration(details);
|
|
3087
3167
|
if (duration)
|
|
3088
3168
|
metrics.push(duration);
|
|
3169
|
+
const usage = formatTaskUsage(details.usage);
|
|
3170
|
+
if (usage)
|
|
3171
|
+
metrics.push(usage);
|
|
3089
3172
|
if (metrics.length > 0)
|
|
3090
3173
|
text += `
|
|
3091
3174
|
${theme.fg("dim", metrics.join(" · "))}`;
|
|
@@ -3334,6 +3417,15 @@ ${catalog.diagnostics.join(`
|
|
|
3334
3417
|
update(streamedText);
|
|
3335
3418
|
}
|
|
3336
3419
|
}
|
|
3420
|
+
if (event.type === "message_end") {
|
|
3421
|
+
const usage = taskUsageFromMessage(event.message);
|
|
3422
|
+
if (usage) {
|
|
3423
|
+
task.usage = addTaskUsage(task.usage, usage);
|
|
3424
|
+
this.persist(task);
|
|
3425
|
+
this.updateTaskWidget(ctx);
|
|
3426
|
+
update(streamedText || "Subagent running");
|
|
3427
|
+
}
|
|
3428
|
+
}
|
|
3337
3429
|
if (event.type === "tool_execution_start" && typeof event.toolName === "string") {
|
|
3338
3430
|
task.currentTool = event.toolName;
|
|
3339
3431
|
task.toolCalls = (task.toolCalls ?? 0) + 1;
|
|
@@ -3750,11 +3842,15 @@ ${renderTaskResult(task.id, "error", message)}`);
|
|
|
3750
3842
|
render: (width) => {
|
|
3751
3843
|
const header = theme.fg("accent", theme.bold("Subagents")) + theme.fg("dim", ` ${summary}`);
|
|
3752
3844
|
const tree = taskTreeLines(visible, (task) => {
|
|
3845
|
+
const state = taskState(theme, task);
|
|
3753
3846
|
const agent = theme.fg("accent", `@${task.agent}`);
|
|
3754
|
-
const
|
|
3755
|
-
const progress = taskProgress(
|
|
3847
|
+
const record = byId.get(task.id);
|
|
3848
|
+
const progress = taskProgress(record);
|
|
3756
3849
|
const suffix = progress.length > 0 ? theme.fg("dim", ` · ${progress.join(" · ")}`) : "";
|
|
3757
|
-
|
|
3850
|
+
const indentWidth = 3 + Math.max(0, record.depth) * 3;
|
|
3851
|
+
const descriptionWidth = Math.max(1, width - indentWidth - visibleWidth2(`${state} ${agent} ${suffix}`));
|
|
3852
|
+
const description = theme.fg("text", truncateToWidth2(task.description, descriptionWidth));
|
|
3853
|
+
return `${state} ${agent} ${description}${suffix}`;
|
|
3758
3854
|
});
|
|
3759
3855
|
const shown = tree.slice(0, 8);
|
|
3760
3856
|
if (tree.length > shown.length) {
|
|
@@ -3775,6 +3871,7 @@ ${renderTaskResult(task.id, "error", message)}`);
|
|
|
3775
3871
|
continue;
|
|
3776
3872
|
this.tasks.set(task.id, {
|
|
3777
3873
|
...task,
|
|
3874
|
+
usage: isTaskUsage(task.usage) ? { ...task.usage } : undefined,
|
|
3778
3875
|
state: task.state === "running" || task.state === "queued" ? "interrupted" : task.state
|
|
3779
3876
|
});
|
|
3780
3877
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-landstrip",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.11",
|
|
4
4
|
"description": "Sandboxed Bash and process-backed agents for Pi",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"landstrip",
|
|
@@ -39,16 +39,16 @@
|
|
|
39
39
|
"ci:test": "npm run test"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@landstrip/landstrip": "^0.18.
|
|
42
|
+
"@landstrip/landstrip": "^0.18.11",
|
|
43
43
|
"jsonc-parser": "^3.3.1",
|
|
44
44
|
"minimatch": "^10.2.5",
|
|
45
45
|
"yaml": "^2.9.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@earendil-works/pi-coding-agent": "^0.82.0",
|
|
49
|
-
"@earendil-works/pi-tui": "^0.
|
|
49
|
+
"@earendil-works/pi-tui": "^0.82.1",
|
|
50
50
|
"@types/node": "^24.0.0",
|
|
51
|
-
"oxfmt": "^0.
|
|
51
|
+
"oxfmt": "^0.61.0",
|
|
52
52
|
"oxlint": "^1.68.0",
|
|
53
53
|
"typebox": "^1.3.6",
|
|
54
54
|
"typescript": "^5.0.0",
|