@cydm/pie 2.6.0 → 2.6.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/dist/builtin/extensions/ask-user/index.js +1 -1
- package/dist/builtin/extensions/computer-use/index.js +10 -3
- package/dist/builtin/extensions/plan-mode/index.js +1 -1
- package/dist/builtin/extensions/subagent/index.js +2 -2
- package/dist/builtin/extensions/todo/index.js +1 -1
- package/dist/chunks/{chunk-AZ336HKF.js → chunk-HT3OYGS7.js} +83 -29
- package/dist/chunks/{chunk-G6KCJA6B.js → chunk-INQMGIKU.js} +1 -1
- package/dist/cli.js +92 -24
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
createAskUserCapability
|
|
4
|
-
} from "../../../chunks/chunk-
|
|
4
|
+
} from "../../../chunks/chunk-HT3OYGS7.js";
|
|
5
5
|
import "../../../chunks/chunk-Y4CYXJR7.js";
|
|
6
6
|
import "../../../chunks/chunk-O2DKMLNX.js";
|
|
7
7
|
import "../../../chunks/chunk-XXGYUYXI.js";
|
|
@@ -7932,7 +7932,7 @@ function currentLookOrThrow() {
|
|
|
7932
7932
|
}
|
|
7933
7933
|
function ensurePointIsInLookImage(x, y, look, errorPrefix = "Coordinates") {
|
|
7934
7934
|
if (!look.image?.jpegBase64) {
|
|
7935
|
-
throw new Error(`${errorPrefix} require an image-bearing root
|
|
7935
|
+
throw new Error(`${errorPrefix} require an image-bearing root, but this look is outline-only. If the action already used an @e ref, that element exposes no semantic action here (text input or picture-only) and fell back to coordinates. Call observe_ui with mode "visual" to capture an image, then act again by @e ref or by coordinates from that image.`);
|
|
7936
7936
|
}
|
|
7937
7937
|
if (!Number.isFinite(x) || !Number.isFinite(y)) {
|
|
7938
7938
|
throw new Error(`${errorPrefix} must be finite numbers.`);
|
|
@@ -8279,6 +8279,13 @@ function validateCondition(params) {
|
|
|
8279
8279
|
if (value && !params.ref) throw new Error("A value UI condition requires an exact ref.");
|
|
8280
8280
|
return { text, role, value, scopeRef, scopeExact: Boolean(params.ref), gone: params.until === "absent", timeoutMs: normalizeWaitTimeoutMs(params.timeoutMs) };
|
|
8281
8281
|
}
|
|
8282
|
+
function expectCondition(expect) {
|
|
8283
|
+
if (!expect) return void 0;
|
|
8284
|
+
const hasMatcher = Boolean(trimOrUndefined(expect.text) ?? trimOrUndefined(expect.role) ?? trimOrUndefined(expect.value));
|
|
8285
|
+
const hasScope = Boolean(conditionScopeRef(expect));
|
|
8286
|
+
if (!hasMatcher && !hasScope) return void 0;
|
|
8287
|
+
return validateCondition(expect);
|
|
8288
|
+
}
|
|
8282
8289
|
function nodeWithinScope(node, scopeRef, scopeExact) {
|
|
8283
8290
|
if (!scopeRef) return true;
|
|
8284
8291
|
if (scopeExact) return node.ref === scopeRef;
|
|
@@ -8696,7 +8703,7 @@ async function performDesktopTransaction(params, actions, signal) {
|
|
|
8696
8703
|
validateStateId(params.stateId);
|
|
8697
8704
|
const look = currentLookOrThrow();
|
|
8698
8705
|
const baseView = { stateId: state.currentCapture.stateId, outline: state.currentOutline };
|
|
8699
|
-
const condition =
|
|
8706
|
+
const condition = expectCondition(params.expect);
|
|
8700
8707
|
const scopeNode = condition ? conditionScopeNode(look.parsedOutline, condition) : void 0;
|
|
8701
8708
|
const target = await ensureTargetWindowId(await resolveCurrentTarget(signal), signal);
|
|
8702
8709
|
const noteBefore = state.currentNote;
|
|
@@ -8759,7 +8766,7 @@ async function performBrowserTransaction(params, actions, signal) {
|
|
|
8759
8766
|
const baseSnapshot = operationState().browserSnapshot;
|
|
8760
8767
|
if (!baseSnapshot) throw new Error("Browser transaction requires a complete base observation.");
|
|
8761
8768
|
const baseView = { stateId: baseSnapshot.snapshotId, outline: baseSnapshot.outline };
|
|
8762
|
-
const condition =
|
|
8769
|
+
const condition = expectCondition(params.expect);
|
|
8763
8770
|
if (condition) conditionScopeNode(restoreOutline(baseSnapshot.outline), condition);
|
|
8764
8771
|
const prepared = actions.map((action) => {
|
|
8765
8772
|
if (!BROWSER_TRANSACTION_ACTIONS.has(action.action)) throw new Error(`Browser transactions do not support '${action.action}'.`);
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
isPlanModeSafeCommand,
|
|
8
8
|
markCompletedPlanSteps,
|
|
9
9
|
restoreExecutionState
|
|
10
|
-
} from "../../../chunks/chunk-
|
|
10
|
+
} from "../../../chunks/chunk-HT3OYGS7.js";
|
|
11
11
|
import "../../../chunks/chunk-Y4CYXJR7.js";
|
|
12
12
|
import "../../../chunks/chunk-O2DKMLNX.js";
|
|
13
13
|
import {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
createCliHostCapabilities
|
|
4
|
-
} from "../../../chunks/chunk-
|
|
4
|
+
} from "../../../chunks/chunk-INQMGIKU.js";
|
|
5
5
|
import {
|
|
6
6
|
createSharedFileSystemTools,
|
|
7
7
|
createSubagentCapability
|
|
8
|
-
} from "../../../chunks/chunk-
|
|
8
|
+
} from "../../../chunks/chunk-HT3OYGS7.js";
|
|
9
9
|
import "../../../chunks/chunk-Y4CYXJR7.js";
|
|
10
10
|
import "../../../chunks/chunk-O2DKMLNX.js";
|
|
11
11
|
import "../../../chunks/chunk-5353DEEC.js";
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
executeManageTodoList,
|
|
9
9
|
executionStateToTodos,
|
|
10
10
|
restoreExecutionState
|
|
11
|
-
} from "../../../chunks/chunk-
|
|
11
|
+
} from "../../../chunks/chunk-HT3OYGS7.js";
|
|
12
12
|
import "../../../chunks/chunk-Y4CYXJR7.js";
|
|
13
13
|
import "../../../chunks/chunk-O2DKMLNX.js";
|
|
14
14
|
import "../../../chunks/chunk-XXGYUYXI.js";
|
|
@@ -1525,6 +1525,9 @@ function buildSubagentPlan(deps, task, name, priority, timeoutSeconds, modelOver
|
|
|
1525
1525
|
};
|
|
1526
1526
|
return { plan, tools: filteredTools, apiKey, model };
|
|
1527
1527
|
}
|
|
1528
|
+
function subagentOutputBudget(model) {
|
|
1529
|
+
return Math.min(model.maxTokens || 8192, 16384);
|
|
1530
|
+
}
|
|
1528
1531
|
function createAgentInstance(deps, systemPrompt, tools, model, apiKey, thinkingLevel) {
|
|
1529
1532
|
if (deps.createAgent) {
|
|
1530
1533
|
return deps.createAgent({
|
|
@@ -1542,7 +1545,14 @@ function createAgentInstance(deps, systemPrompt, tools, model, apiKey, thinkingL
|
|
|
1542
1545
|
tools,
|
|
1543
1546
|
thinkingLevel
|
|
1544
1547
|
},
|
|
1545
|
-
apiKey
|
|
1548
|
+
apiKey,
|
|
1549
|
+
// Subagent turns are single-purpose report generations: request an
|
|
1550
|
+
// explicit output budget (see subagentOutputBudget) instead of leaving
|
|
1551
|
+
// it to endpoint defaults that silently truncate long reports.
|
|
1552
|
+
streamFn: (streamModel, context, options) => streamSimple(streamModel, context, {
|
|
1553
|
+
...options,
|
|
1554
|
+
maxTokens: options?.maxTokens ?? subagentOutputBudget(streamModel)
|
|
1555
|
+
})
|
|
1546
1556
|
});
|
|
1547
1557
|
}
|
|
1548
1558
|
function extractEvidenceFromToolArgs(toolName, args) {
|
|
@@ -1701,7 +1711,20 @@ ${formatSkillsForPrompt(deps.skills ?? [])}`;
|
|
|
1701
1711
|
}
|
|
1702
1712
|
const messages = subagent.state.messages;
|
|
1703
1713
|
deps.log(`[Subagent ${task.name}] Total messages: ${messages.length}`);
|
|
1704
|
-
const
|
|
1714
|
+
const lastAssistant = [...messages].reverse().find((m) => m?.role === "assistant");
|
|
1715
|
+
const terminalStopReason = lastAssistant?.stopReason;
|
|
1716
|
+
const terminalError = typeof lastAssistant?.errorMessage === "string" ? lastAssistant.errorMessage : void 0;
|
|
1717
|
+
const collectedResponse = collectLastAssistantText(messages);
|
|
1718
|
+
if (terminalStopReason === "error" || terminalStopReason === "aborted" || terminalError || !collectedResponse) {
|
|
1719
|
+
const detail = terminalError ? `: ${terminalError.slice(0, 200)}` : "";
|
|
1720
|
+
throw new Error(`Subagent stream interrupted (SSE stream aborted before the report was produced, stopReason=${terminalStopReason ?? "none"}${collectedResponse ? ", partial transcript discarded" : ", no text response"})${detail}`);
|
|
1721
|
+
}
|
|
1722
|
+
let response = collectedResponse;
|
|
1723
|
+
const outputTruncated = terminalStopReason === "length";
|
|
1724
|
+
if (outputTruncated) {
|
|
1725
|
+
task.confidenceSignals.push({ type: "output_truncated", message: "final response hit the provider's output token limit" });
|
|
1726
|
+
response += "\n\n[Incomplete report: the subagent's final response was cut off by the provider's output token limit (stopReason=length). The items above may be a partial list \u2014 rerun the task with a narrower scope, or ask for the remaining items.]";
|
|
1727
|
+
}
|
|
1705
1728
|
const reportedEvidence = extractEvidenceFromText(response).map((evidence) => ({ ...evidence, source: "reported" }));
|
|
1706
1729
|
task.evidence.push(...reportedEvidence.map(({ source: _source, ...evidence }) => evidence));
|
|
1707
1730
|
task.reportedEvidence.push(...reportedEvidence);
|
|
@@ -1715,9 +1738,10 @@ ${formatSkillsForPrompt(deps.skills ?? [])}`;
|
|
|
1715
1738
|
task.details = {
|
|
1716
1739
|
turns: assistantTurns,
|
|
1717
1740
|
toolCalls,
|
|
1718
|
-
durationMs
|
|
1741
|
+
durationMs,
|
|
1742
|
+
...outputTruncated ? { outputTruncated: true } : {}
|
|
1719
1743
|
};
|
|
1720
|
-
task.parentHandoffRequired = isParentHandoffRequired(task);
|
|
1744
|
+
task.parentHandoffRequired = isParentHandoffRequired(task) || outputTruncated;
|
|
1721
1745
|
task.completedAt = Date.now();
|
|
1722
1746
|
reportProgress({ message: `[${task.name}] Completed (${durationMs}ms, ${toolCalls} tools)`, increment: 100 });
|
|
1723
1747
|
} catch (error) {
|
|
@@ -7841,7 +7865,7 @@ var AskUserMultiParamsSchema = Type.Object({
|
|
|
7841
7865
|
}))
|
|
7842
7866
|
});
|
|
7843
7867
|
function buildUnsupportedResult(error) {
|
|
7844
|
-
const message = error instanceof InteractionUnavailableError ? error.message : error instanceof Error ? error.message : String(error);
|
|
7868
|
+
const message = error instanceof InteractionUnavailableError ? `${error.message}. This host has no interactive UI registered (headless or print run) \u2014 do not retry ask_user tools here; proceed without asking, or state the question as plain text.` : error instanceof Error ? error.message : String(error);
|
|
7845
7869
|
return {
|
|
7846
7870
|
content: [{ type: "text", text: `Interaction unavailable: ${message}` }],
|
|
7847
7871
|
details: { unsupported: true, error: message },
|
|
@@ -8057,6 +8081,13 @@ function createAskUserCapability() {
|
|
|
8057
8081
|
parameters: AskUserMultiParamsSchema,
|
|
8058
8082
|
async execute(toolCallIdOrArgs, maybeArgs) {
|
|
8059
8083
|
try {
|
|
8084
|
+
if (!hasInteractionHandler()) {
|
|
8085
|
+
return {
|
|
8086
|
+
content: [{ type: "text", text: "Interaction unavailable: this host has no interactive UI registered (headless or print run). Do not retry ask_user_multi here \u2014 proceed without asking, or state the question as plain text." }],
|
|
8087
|
+
details: { unsupported: true, error: "no interaction handler" },
|
|
8088
|
+
isError: true
|
|
8089
|
+
};
|
|
8090
|
+
}
|
|
8060
8091
|
const args = typeof toolCallIdOrArgs === "string" && maybeArgs !== void 0 ? maybeArgs : toolCallIdOrArgs;
|
|
8061
8092
|
const normalized = normalizeAskUserArgs(args);
|
|
8062
8093
|
if ("error" in normalized) {
|
|
@@ -12844,7 +12875,7 @@ function createGrepTextTool(cwd, options) {
|
|
|
12844
12875
|
Type.Boolean({ description: "Treat pattern as literal string instead of regex (default: false)" })
|
|
12845
12876
|
),
|
|
12846
12877
|
context: Type.Optional(
|
|
12847
|
-
Type.Integer({ minimum: 0, maximum: MAX_GREP_CONTEXT_LINES, description: `Number of lines to show before and after each match (default: 0
|
|
12878
|
+
Type.Integer({ minimum: 0, maximum: MAX_GREP_CONTEXT_LINES * 10, description: `Number of lines to show before and after each match (default: 0; values above ${MAX_GREP_CONTEXT_LINES} are clamped to ${MAX_GREP_CONTEXT_LINES})` })
|
|
12848
12879
|
),
|
|
12849
12880
|
outputMode: Type.Optional(Type.Union([
|
|
12850
12881
|
Type.Literal("content"),
|
|
@@ -12899,8 +12930,7 @@ function createGrepTextTool(cwd, options) {
|
|
|
12899
12930
|
const offset = normalizeNonNegativeInteger(rawOffset, 0, "offset");
|
|
12900
12931
|
const effectiveLimit = normalizeNonNegativeInteger(limit, DEFAULT_LIMIT2, "limit");
|
|
12901
12932
|
if (effectiveLimit < 1 || effectiveLimit > MAX_GREP_RESULT_LIMIT) throw new Error(`Invalid grep_text arguments: limit must be between 1 and ${MAX_GREP_RESULT_LIMIT}.`);
|
|
12902
|
-
const ctx = normalizeNonNegativeInteger(contextLines, 0, "context");
|
|
12903
|
-
if (ctx > MAX_GREP_CONTEXT_LINES) throw new Error(`Invalid grep_text arguments: context must be at most ${MAX_GREP_CONTEXT_LINES}.`);
|
|
12933
|
+
const ctx = Math.min(normalizeNonNegativeInteger(contextLines, 0, "context"), MAX_GREP_CONTEXT_LINES);
|
|
12904
12934
|
let isDir;
|
|
12905
12935
|
try {
|
|
12906
12936
|
const stat = await fs2.stat(searchPath);
|
|
@@ -15343,9 +15373,18 @@ var webResearchSchema = Type.Object({
|
|
|
15343
15373
|
description: "Maximum credible sources to fetch and cite. Defaults to 3."
|
|
15344
15374
|
}))
|
|
15345
15375
|
});
|
|
15376
|
+
function httpStatusFromFailureText(text) {
|
|
15377
|
+
const match2 = /\bHTTP\s?(\d{3})\b/i.exec(text);
|
|
15378
|
+
return match2 ? Number(match2[1]) : void 0;
|
|
15379
|
+
}
|
|
15346
15380
|
var DEFAULT_WEB_RESEARCH_SEARCH_ATTEMPT_TIMEOUT_MS = 45e3;
|
|
15347
|
-
var DEFAULT_WEB_RESEARCH_FETCH_ATTEMPT_TIMEOUT_MS =
|
|
15381
|
+
var DEFAULT_WEB_RESEARCH_FETCH_ATTEMPT_TIMEOUT_MS = 45e3;
|
|
15348
15382
|
var DEFAULT_WEB_RESEARCH_BROWSER_ATTEMPT_TIMEOUT_MS = 45e3;
|
|
15383
|
+
function isTransientFetchFailure(category, text) {
|
|
15384
|
+
if (category === "timeout" || category === "provider_error") return true;
|
|
15385
|
+
if (category === "http_error") return /\bHTTP\s?(5\d\d|429)\b/i.test(text);
|
|
15386
|
+
return false;
|
|
15387
|
+
}
|
|
15349
15388
|
function isRecord5(value) {
|
|
15350
15389
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
15351
15390
|
}
|
|
@@ -16083,36 +16122,48 @@ function createSharedWebResearchTool(deps) {
|
|
|
16083
16122
|
return true;
|
|
16084
16123
|
});
|
|
16085
16124
|
const fetchScoredSource = async (scored) => {
|
|
16086
|
-
const startedAt = Date.now();
|
|
16087
16125
|
onUpdate?.({
|
|
16088
16126
|
content: [{ type: "text", text: `Fetching source: ${scored.source.url}` }],
|
|
16089
16127
|
details: { query, actualQueries: [...new Set(actualQueries)], sources: dedupedSources, fetchedSources, providerAttempts, attempts, qualityScore: qualityScore(fetchedSources, scoredSources), warnings, browserRequiredSources }
|
|
16090
16128
|
});
|
|
16091
|
-
const
|
|
16092
|
-
|
|
16093
|
-
|
|
16094
|
-
|
|
16095
|
-
|
|
16096
|
-
|
|
16097
|
-
|
|
16098
|
-
|
|
16099
|
-
|
|
16100
|
-
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
|
|
16104
|
-
|
|
16105
|
-
|
|
16129
|
+
const fetchOnce = async () => {
|
|
16130
|
+
const startedAt = Date.now();
|
|
16131
|
+
const result = await runWithDeadline(
|
|
16132
|
+
(childSignal) => webFetchTool.execute("web_research_fetch", { url: scored.source.url }, childSignal),
|
|
16133
|
+
fetchAttemptTimeoutMs,
|
|
16134
|
+
`web_research fetch attempt timed out after ${Math.ceil(fetchAttemptTimeoutMs / 1e3)} seconds`,
|
|
16135
|
+
signal
|
|
16136
|
+
).catch((error) => ({
|
|
16137
|
+
content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }],
|
|
16138
|
+
details: {
|
|
16139
|
+
url: scored.source.url,
|
|
16140
|
+
sourceUrl: scored.source.url,
|
|
16141
|
+
durationMs: Date.now() - startedAt,
|
|
16142
|
+
failureCategory: "timeout"
|
|
16143
|
+
},
|
|
16144
|
+
isError: true
|
|
16145
|
+
}));
|
|
16146
|
+
return { result, startedAt, endedAt: Date.now() };
|
|
16147
|
+
};
|
|
16148
|
+
let attempt = await fetchOnce();
|
|
16149
|
+
let attemptTotalMs = attempt.endedAt - attempt.startedAt;
|
|
16150
|
+
if (attempt.result.isError && isTransientFetchFailure(contentDetails(attempt.result).failureCategory, textFromResult(attempt.result))) {
|
|
16151
|
+
attempts.push({ phase: "fetch", url: scored.source.url, status: "failed", failureCategory: contentDetails(attempt.result).failureCategory, failureStatus: httpStatusFromFailureText(textFromResult(attempt.result)), durationMs: attemptTotalMs });
|
|
16152
|
+
attempt = await fetchOnce();
|
|
16153
|
+
attemptTotalMs += attempt.endedAt - attempt.startedAt;
|
|
16154
|
+
}
|
|
16155
|
+
const fetchResult = attempt.result;
|
|
16106
16156
|
const details2 = contentDetails(fetchResult);
|
|
16107
16157
|
const text = textFromResult(fetchResult);
|
|
16108
|
-
fetchDurationMs +=
|
|
16109
|
-
sourceReadDurations.push(
|
|
16158
|
+
fetchDurationMs += attemptTotalMs;
|
|
16159
|
+
sourceReadDurations.push(attemptTotalMs);
|
|
16110
16160
|
attempts.push({
|
|
16111
16161
|
phase: "fetch",
|
|
16112
16162
|
url: scored.source.url,
|
|
16113
16163
|
status: fetchResult.isError ? "failed" : "completed",
|
|
16114
16164
|
failureCategory: details2.failureCategory,
|
|
16115
|
-
|
|
16165
|
+
...fetchResult.isError ? { failureStatus: httpStatusFromFailureText(text) } : {},
|
|
16166
|
+
durationMs: attemptTotalMs
|
|
16116
16167
|
});
|
|
16117
16168
|
if (details2.requiresBrowser) {
|
|
16118
16169
|
const browserEntry = {
|
|
@@ -16219,9 +16270,12 @@ function createSharedWebResearchTool(deps) {
|
|
|
16219
16270
|
}
|
|
16220
16271
|
};
|
|
16221
16272
|
if (fetchedSources.length === 0) {
|
|
16273
|
+
const fetchFailures = details.attempts.filter((attempt) => attempt.phase === "fetch" && attempt.status === "failed").slice(0, 6);
|
|
16274
|
+
const failureSummary = fetchFailures.length ? `
|
|
16275
|
+
Fetch failures: ${fetchFailures.map((attempt) => `${attempt.url} (${attempt.failureCategory || "fetch_failed"}${attempt.failureStatus !== void 0 ? ` ${attempt.failureStatus}` : ""})`).join("; ")}` : "";
|
|
16222
16276
|
const reason = browserRequiredSources.length ? "web_research found candidate sources, but they require browser-rendered reading and no host browser reader completed." : "web_research could not fetch any credible source for this query.";
|
|
16223
16277
|
return {
|
|
16224
|
-
content: [{ type: "text", text: `${reason}
|
|
16278
|
+
content: [{ type: "text", text: `${reason}${failureSummary}
|
|
16225
16279
|
|
|
16226
16280
|
Queries tried: ${details.actualQueries.join("; ") || query}` }],
|
|
16227
16281
|
details,
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
createCliWebResearchHealthStore,
|
|
8
8
|
formatSize,
|
|
9
9
|
truncateHeadTail
|
|
10
|
-
} from "./chunks/chunk-
|
|
10
|
+
} from "./chunks/chunk-INQMGIKU.js";
|
|
11
11
|
import {
|
|
12
12
|
AGENTS_CONTEXT_FILE_NAME,
|
|
13
13
|
AgentSessionController,
|
|
@@ -60,7 +60,7 @@ import {
|
|
|
60
60
|
setExtensionEnabledInSettings,
|
|
61
61
|
shouldPreserveExecutionStateForUserText,
|
|
62
62
|
supersedeExecutionState
|
|
63
|
-
} from "./chunks/chunk-
|
|
63
|
+
} from "./chunks/chunk-HT3OYGS7.js";
|
|
64
64
|
import "./chunks/chunk-Y4CYXJR7.js";
|
|
65
65
|
import {
|
|
66
66
|
Deref,
|
|
@@ -53581,17 +53581,40 @@ function filterEnabledTools(tools, settingsManager) {
|
|
|
53581
53581
|
const disabled = getDisabledToolNames(settingsManager);
|
|
53582
53582
|
return disabled.size > 0 ? tools.filter((tool) => !disabled.has(tool.name)) : [...tools];
|
|
53583
53583
|
}
|
|
53584
|
+
function mergeSnapshotDelta(atLoad, current, onDisk) {
|
|
53585
|
+
const merged = { ...onDisk };
|
|
53586
|
+
const load = atLoad;
|
|
53587
|
+
const cur = current;
|
|
53588
|
+
const allKeys = /* @__PURE__ */ new Set([...Object.keys(load), ...Object.keys(cur)]);
|
|
53589
|
+
for (const key of allKeys) {
|
|
53590
|
+
const before = JSON.stringify(load[key]);
|
|
53591
|
+
const after = JSON.stringify(cur[key]);
|
|
53592
|
+
if (before === after) continue;
|
|
53593
|
+
if (after === void 0) delete merged[key];
|
|
53594
|
+
else merged[key] = cur[key];
|
|
53595
|
+
}
|
|
53596
|
+
return merged;
|
|
53597
|
+
}
|
|
53584
53598
|
var SettingsManager = class {
|
|
53585
53599
|
settingsPath;
|
|
53586
53600
|
legacyConfigPath;
|
|
53587
53601
|
settings;
|
|
53588
53602
|
legacyConfig;
|
|
53603
|
+
/** Last state this instance successfully persisted (starts at the load
|
|
53604
|
+
* snapshot). The delta vs THIS — not vs the load snapshot — is what a
|
|
53605
|
+
* write may persist: a load-time baseline misses in-process
|
|
53606
|
+
* write-after-write (e.g. disable then re-enable must prune the key, not
|
|
53607
|
+
* 'revert to load state = untouched'). */
|
|
53608
|
+
settingsLastWritten;
|
|
53609
|
+
legacyConfigLastWritten;
|
|
53589
53610
|
constructor() {
|
|
53590
53611
|
const configDir = getConfigDir();
|
|
53591
53612
|
this.settingsPath = getSettingsPath();
|
|
53592
53613
|
this.legacyConfigPath = `${configDir}/config.json`;
|
|
53593
53614
|
this.settings = this.loadSettingsFile();
|
|
53615
|
+
this.settingsLastWritten = structuredClone(this.settings);
|
|
53594
53616
|
this.legacyConfig = this.loadLegacyConfigFile();
|
|
53617
|
+
this.legacyConfigLastWritten = structuredClone(this.legacyConfig);
|
|
53595
53618
|
}
|
|
53596
53619
|
readJson(filePath) {
|
|
53597
53620
|
if (!fs4.existsSync(filePath)) return null;
|
|
@@ -53612,7 +53635,38 @@ var SettingsManager = class {
|
|
|
53612
53635
|
}
|
|
53613
53636
|
writeSettings() {
|
|
53614
53637
|
this.ensureDir();
|
|
53615
|
-
|
|
53638
|
+
const written = this.writeMergedOrFull(() => this.settingsPath, () => this.settingsLastWritten, () => this.settings, (value) => this.writeSettingsValue(value));
|
|
53639
|
+
this.settings = structuredClone(written);
|
|
53640
|
+
this.settingsLastWritten = structuredClone(written);
|
|
53641
|
+
}
|
|
53642
|
+
/** Merged write for an explicit candidate state (setters that build a
|
|
53643
|
+
* nextSettings object): writes FIRST (a failed write leaves this
|
|
53644
|
+
* instance's cached state untouched), then returns the value actually
|
|
53645
|
+
* written — callers assign THAT (not their candidate, which lacks keys
|
|
53646
|
+
* preserved from disk) so state and lastWritten never diverge. */
|
|
53647
|
+
writeSettingsWith(next) {
|
|
53648
|
+
const written = this.writeMergedOrFull(() => this.settingsPath, () => this.settingsLastWritten, () => next, (value) => this.writeSettingsValue(value));
|
|
53649
|
+
this.settingsLastWritten = structuredClone(written);
|
|
53650
|
+
return written;
|
|
53651
|
+
}
|
|
53652
|
+
/** Shared write path: merge our delta onto the current on-disk object and
|
|
53653
|
+
* return the value actually written. When the file EXISTS but does not
|
|
53654
|
+
* parse (another process mid-write over a non-atomic writeFileSync),
|
|
53655
|
+
* merging onto {} would silently delete every unrelated key — fall back
|
|
53656
|
+
* to the full candidate write instead. */
|
|
53657
|
+
writeMergedOrFull(path34, lastWritten, current, write) {
|
|
53658
|
+
let onDisk = null;
|
|
53659
|
+
let corrupt = false;
|
|
53660
|
+
if (fs4.existsSync(path34())) {
|
|
53661
|
+
try {
|
|
53662
|
+
onDisk = JSON.parse(fs4.readFileSync(path34(), "utf-8"));
|
|
53663
|
+
} catch {
|
|
53664
|
+
corrupt = true;
|
|
53665
|
+
}
|
|
53666
|
+
}
|
|
53667
|
+
const value = corrupt ? current() : mergeSnapshotDelta(lastWritten(), current(), onDisk ?? {});
|
|
53668
|
+
write(value);
|
|
53669
|
+
return value;
|
|
53616
53670
|
}
|
|
53617
53671
|
writeSettingsValue(settings) {
|
|
53618
53672
|
this.ensureDir();
|
|
@@ -53620,7 +53674,10 @@ var SettingsManager = class {
|
|
|
53620
53674
|
}
|
|
53621
53675
|
writeLegacyConfig() {
|
|
53622
53676
|
this.ensureDir();
|
|
53623
|
-
|
|
53677
|
+
this.writeMergedOrFull(() => this.legacyConfigPath, () => this.legacyConfigLastWritten, () => this.legacyConfig, (value) => {
|
|
53678
|
+
fs4.writeFileSync(this.legacyConfigPath, JSON.stringify(value, null, 2));
|
|
53679
|
+
this.legacyConfigLastWritten = structuredClone(value);
|
|
53680
|
+
});
|
|
53624
53681
|
}
|
|
53625
53682
|
getLegacyApiKey() {
|
|
53626
53683
|
return this.legacyConfig.apiKey;
|
|
@@ -53690,6 +53747,13 @@ var SettingsManager = class {
|
|
|
53690
53747
|
this.settings.calmMode = enabled;
|
|
53691
53748
|
this.writeSettings();
|
|
53692
53749
|
}
|
|
53750
|
+
getToolOutputExpanded() {
|
|
53751
|
+
return this.settings.toolOutputExpanded === true;
|
|
53752
|
+
}
|
|
53753
|
+
setToolOutputExpanded(expanded) {
|
|
53754
|
+
this.settings.toolOutputExpanded = expanded;
|
|
53755
|
+
this.writeSettings();
|
|
53756
|
+
}
|
|
53693
53757
|
// ==========================================================================
|
|
53694
53758
|
// Extension enablement (user ~/.pie/settings.json + project ./.pie/settings.json)
|
|
53695
53759
|
// ==========================================================================
|
|
@@ -53734,8 +53798,7 @@ var SettingsManager = class {
|
|
|
53734
53798
|
extensions: this.settings.extensions ? { ...this.settings.extensions } : void 0
|
|
53735
53799
|
};
|
|
53736
53800
|
setExtensionEnabledInSettings(nextSettings, identity, enabled);
|
|
53737
|
-
this.
|
|
53738
|
-
this.settings = nextSettings;
|
|
53801
|
+
this.settings = this.writeSettingsWith(nextSettings);
|
|
53739
53802
|
}
|
|
53740
53803
|
/** Raw skill enablement map. */
|
|
53741
53804
|
getSkillSettings() {
|
|
@@ -53749,8 +53812,7 @@ var SettingsManager = class {
|
|
|
53749
53812
|
setSkillEnabled(name, enabled) {
|
|
53750
53813
|
const nextSettings = { ...this.settings };
|
|
53751
53814
|
setEnablementInMap(nextSettings, "skills", name, enabled);
|
|
53752
|
-
this.
|
|
53753
|
-
this.settings = nextSettings;
|
|
53815
|
+
this.settings = this.writeSettingsWith(nextSettings);
|
|
53754
53816
|
}
|
|
53755
53817
|
/** Disabled runtime tool names (may contain names no longer installed). */
|
|
53756
53818
|
getDisabledTools() {
|
|
@@ -53772,8 +53834,7 @@ var SettingsManager = class {
|
|
|
53772
53834
|
if (Object.keys(nextTools).length === 0) {
|
|
53773
53835
|
delete nextSettings.tools;
|
|
53774
53836
|
}
|
|
53775
|
-
this.
|
|
53776
|
-
this.settings = nextSettings;
|
|
53837
|
+
this.settings = this.writeSettingsWith(nextSettings);
|
|
53777
53838
|
}
|
|
53778
53839
|
};
|
|
53779
53840
|
|
|
@@ -63776,11 +63837,15 @@ function sanitizeNotificationText(text) {
|
|
|
63776
63837
|
function buildDesktopNotificationSequences(title, body) {
|
|
63777
63838
|
const sanitizedTitle = sanitizeNotificationText(title);
|
|
63778
63839
|
const sanitizedBody = sanitizeNotificationText(body);
|
|
63779
|
-
|
|
63780
|
-
|
|
63781
|
-
|
|
63782
|
-
`\x1B]99;i=1:d=0;${sanitizedBody}\x07`
|
|
63783
|
-
|
|
63840
|
+
const program = process.env.TERM_PROGRAM ?? "";
|
|
63841
|
+
const term = process.env.TERM ?? "";
|
|
63842
|
+
if (/kitty/i.test(program) || /^xterm-kitty/.test(term)) {
|
|
63843
|
+
return [`\x1B]99;i=1:d=0;${sanitizedBody}\x07`];
|
|
63844
|
+
}
|
|
63845
|
+
if (/rxvt|terminology/i.test(program) || /^rxvt-unicode/.test(term)) {
|
|
63846
|
+
return [`\x1B]777;notify;${sanitizedTitle};${sanitizedBody}\x07`];
|
|
63847
|
+
}
|
|
63848
|
+
return [`\x1B]9;${sanitizedTitle}: ${sanitizedBody}\x07`];
|
|
63784
63849
|
}
|
|
63785
63850
|
|
|
63786
63851
|
// src/extensions/runner.ts
|
|
@@ -72844,12 +72909,6 @@ async function loadSession(host, sessionId) {
|
|
|
72844
72909
|
host.agentSessionController?.drainQueuedInputsForEditor();
|
|
72845
72910
|
host.updatePendingMessagesDisplay();
|
|
72846
72911
|
renderChatHistory(host, messages);
|
|
72847
|
-
if (messages.length > 50) {
|
|
72848
|
-
host.chatContainer.addChild(new Spacer(1));
|
|
72849
|
-
host.chatContainer.addChild(
|
|
72850
|
-
new Text(theme.fg("dim", `... (${messages.length - 50} earlier messages hidden)`), 1, 0)
|
|
72851
|
-
);
|
|
72852
|
-
}
|
|
72853
72912
|
host.chatContainer.addChild(new Spacer(1));
|
|
72854
72913
|
host.chatContainer.addChild(
|
|
72855
72914
|
new Text(theme.fg("accent", `\u2713 Loaded session: ${sessionId.slice(0, 8)}...`), 1, 0)
|
|
@@ -73073,7 +73132,7 @@ async function navigateToEntry(host, entryId) {
|
|
|
73073
73132
|
}
|
|
73074
73133
|
}
|
|
73075
73134
|
function renderChatHistory(host, messages) {
|
|
73076
|
-
const messagesToShow = messages
|
|
73135
|
+
const messagesToShow = messages;
|
|
73077
73136
|
const toolResultMap = /* @__PURE__ */ new Map();
|
|
73078
73137
|
for (const msg of messages) {
|
|
73079
73138
|
if (msg.role === "toolResult") {
|
|
@@ -78441,6 +78500,7 @@ function createInteractiveAgentSessionController(host) {
|
|
|
78441
78500
|
}
|
|
78442
78501
|
let retryElapsedTicker;
|
|
78443
78502
|
let retryElapsedStartedAt = 0;
|
|
78503
|
+
let pendingSettleKind;
|
|
78444
78504
|
const stopRetryElapsedTicker = () => {
|
|
78445
78505
|
if (retryElapsedTicker !== void 0) {
|
|
78446
78506
|
clearInterval(retryElapsedTicker);
|
|
@@ -78584,10 +78644,14 @@ function createInteractiveAgentSessionController(host) {
|
|
|
78584
78644
|
host.appendWarningSummary(outcome.terminalSummary);
|
|
78585
78645
|
}
|
|
78586
78646
|
host.sessionTrace.completeTurn(event.message, false);
|
|
78587
|
-
|
|
78647
|
+
pendingSettleKind = "completed";
|
|
78588
78648
|
host._semanticTurnIndex++;
|
|
78589
78649
|
} else if (event.type === "turn_settled") {
|
|
78590
78650
|
host.setControllerBusy(false);
|
|
78651
|
+
if (pendingSettleKind === "completed") {
|
|
78652
|
+
ringTurnSettledBell(host);
|
|
78653
|
+
}
|
|
78654
|
+
pendingSettleKind = void 0;
|
|
78591
78655
|
} else if (event.type === "turn_failed_terminal") {
|
|
78592
78656
|
host.clearContinuationTimeout("turn_failed_terminal");
|
|
78593
78657
|
if (event.message) {
|
|
@@ -78623,6 +78687,7 @@ function createInteractiveAgentSessionController(host) {
|
|
|
78623
78687
|
}
|
|
78624
78688
|
host.showError(event.failure.message);
|
|
78625
78689
|
host.ringAttentionBell?.("turn-failed");
|
|
78690
|
+
pendingSettleKind = "failed";
|
|
78626
78691
|
host.setControllerBusy(false);
|
|
78627
78692
|
} else if (event.type === "turn_cancelled") {
|
|
78628
78693
|
const outcome = host.executionState.abort();
|
|
@@ -78639,6 +78704,7 @@ function createInteractiveAgentSessionController(host) {
|
|
|
78639
78704
|
if (outcome.terminalSummary) {
|
|
78640
78705
|
host.appendWarningSummary(outcome.terminalSummary);
|
|
78641
78706
|
}
|
|
78707
|
+
pendingSettleKind = "cancelled";
|
|
78642
78708
|
host.setControllerBusy(false);
|
|
78643
78709
|
} else if (event.type === "runtime_guard_advisory") {
|
|
78644
78710
|
host.noteRuntimeGuardAdvisory(event);
|
|
@@ -79839,6 +79905,7 @@ var InteractiveMode = class {
|
|
|
79839
79905
|
this.skillsSection = formatSkillsForPrompt(options.skills);
|
|
79840
79906
|
this.knowledgeSection = buildCliProjectContextSection(options.cwd);
|
|
79841
79907
|
this.calmMode = options.settingsManager.getCalmModeEnabled();
|
|
79908
|
+
this.toolOutputExpanded = options.settingsManager.getToolOutputExpanded();
|
|
79842
79909
|
}
|
|
79843
79910
|
options;
|
|
79844
79911
|
get runtimeEventHost() {
|
|
@@ -80391,7 +80458,8 @@ var InteractiveMode = class {
|
|
|
80391
80458
|
return interactiveCommands.some((cmd) => commandPath.startsWith(cmd));
|
|
80392
80459
|
}
|
|
80393
80460
|
toggleToolsExpansion() {
|
|
80394
|
-
|
|
80461
|
+
toggleToolsExpansion(this.uiHelperHost);
|
|
80462
|
+
this.options.settingsManager.setToolOutputExpanded(this.toolOutputExpanded);
|
|
80395
80463
|
}
|
|
80396
80464
|
showSelector(create) {
|
|
80397
80465
|
return showSelector(this.uiHelperHost, create);
|