@zihanw/pi-forge 0.4.0-beta.1 → 0.4.1
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 +45 -1
- package/PUBLIC_API.md +3 -26
- package/README.md +90 -601
- package/README.zh-CN.md +86 -585
- package/SUBAGENT_ADAPTER_CONTRACT.md +3 -197
- package/dist/agent-profile.d.ts +24 -1
- package/dist/agent-profile.d.ts.map +1 -1
- package/dist/agent-profile.js +146 -36
- package/dist/agent-profile.js.map +1 -1
- package/dist/catalog.d.ts +27 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +59 -0
- package/dist/catalog.js.map +1 -0
- package/dist/forge-config.d.ts +106 -0
- package/dist/forge-config.d.ts.map +1 -1
- package/dist/forge-config.js +305 -18
- package/dist/forge-config.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +55 -8
- package/dist/index.js.map +1 -1
- package/dist/lifecycle.d.ts +2 -1
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +7 -4
- package/dist/lifecycle.js.map +1 -1
- package/dist/loader.d.ts +17 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +84 -25
- package/dist/loader.js.map +1 -1
- package/dist/preset-command.d.ts +1 -1
- package/dist/preset-command.d.ts.map +1 -1
- package/dist/preset-command.js +38 -10
- package/dist/preset-command.js.map +1 -1
- package/dist/profile-command.d.ts.map +1 -1
- package/dist/profile-command.js +46 -21
- package/dist/profile-command.js.map +1 -1
- package/dist/profile-service.d.ts +6 -3
- package/dist/profile-service.d.ts.map +1 -1
- package/dist/profile-service.js +55 -13
- package/dist/profile-service.js.map +1 -1
- package/dist/resource-identity.d.ts +33 -0
- package/dist/resource-identity.d.ts.map +1 -0
- package/dist/resource-identity.js +56 -0
- package/dist/resource-identity.js.map +1 -0
- package/dist/runtime/profile-runtime.d.ts.map +1 -1
- package/dist/runtime/profile-runtime.js +7 -2
- package/dist/runtime/profile-runtime.js.map +1 -1
- package/dist/runtime/prompt-stack-runtime.d.ts +1 -1
- package/dist/runtime/prompt-stack-runtime.d.ts.map +1 -1
- package/dist/runtime/prompt-stack-runtime.js +22 -12
- package/dist/runtime/prompt-stack-runtime.js.map +1 -1
- package/dist/runtime/subagent-runtime.d.ts +23 -8
- package/dist/runtime/subagent-runtime.d.ts.map +1 -1
- package/dist/runtime/subagent-runtime.js +296 -67
- package/dist/runtime/subagent-runtime.js.map +1 -1
- package/dist/storage.d.ts +11 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +51 -2
- package/dist/storage.js.map +1 -1
- package/dist/subagent/canonical.d.ts +19 -7
- package/dist/subagent/canonical.d.ts.map +1 -1
- package/dist/subagent/canonical.js +19 -47
- package/dist/subagent/canonical.js.map +1 -1
- package/dist/subagent/contract.d.ts +1 -2
- package/dist/subagent/contract.d.ts.map +1 -1
- package/dist/subagent/contract.js +1 -2
- package/dist/subagent/contract.js.map +1 -1
- package/dist/subagent/index.d.ts +4 -3
- package/dist/subagent/index.d.ts.map +1 -1
- package/dist/subagent/index.js +4 -3
- package/dist/subagent/index.js.map +1 -1
- package/dist/subagent/plan.d.ts +5 -1
- package/dist/subagent/plan.d.ts.map +1 -1
- package/dist/subagent/plan.js +29 -32
- package/dist/subagent/plan.js.map +1 -1
- package/dist/subagent/request.d.ts.map +1 -1
- package/dist/subagent/request.js +36 -4
- package/dist/subagent/request.js.map +1 -1
- package/dist/subagent/types.d.ts +66 -178
- package/dist/subagent/types.d.ts.map +1 -1
- package/dist/subagent/types.js +1 -1
- package/dist/subagent/types.js.map +1 -1
- package/dist/subagent/validation.d.ts +14 -14
- package/dist/subagent/validation.d.ts.map +1 -1
- package/dist/subagent/validation.js +52 -238
- package/dist/subagent/validation.js.map +1 -1
- package/dist/subagent-command.d.ts +2 -1
- package/dist/subagent-command.d.ts.map +1 -1
- package/dist/subagent-command.js +115 -19
- package/dist/subagent-command.js.map +1 -1
- package/dist/subagent-host.d.ts.map +1 -1
- package/dist/subagent-host.js +43 -16
- package/dist/subagent-host.js.map +1 -1
- package/dist/subagent-profile-tool.d.ts +25 -2
- package/dist/subagent-profile-tool.d.ts.map +1 -1
- package/dist/subagent-profile-tool.js +41 -9
- package/dist/subagent-profile-tool.js.map +1 -1
- package/dist/subagent-tool.d.ts +31 -4
- package/dist/subagent-tool.d.ts.map +1 -1
- package/dist/subagent-tool.js +311 -137
- package/dist/subagent-tool.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/web-editor/client-script.generated.d.ts +1 -1
- package/dist/web-editor/client-script.generated.d.ts.map +1 -1
- package/dist/web-editor/client-script.generated.js +1 -1
- package/dist/web-editor/client-script.generated.js.map +1 -1
- package/dist/web-editor/client-styles.d.ts +2 -0
- package/dist/web-editor/client-styles.d.ts.map +1 -0
- package/dist/web-editor/client-styles.generated.d.ts +2 -0
- package/dist/web-editor/client-styles.generated.d.ts.map +1 -0
- package/dist/web-editor/client-styles.generated.js +3 -0
- package/dist/web-editor/client-styles.generated.js.map +1 -0
- package/dist/web-editor/client-styles.js +2 -0
- package/dist/web-editor/client-styles.js.map +1 -0
- package/dist/web-editor/page.d.ts +2 -0
- package/dist/web-editor/page.d.ts.map +1 -1
- package/dist/web-editor/page.js +11 -73
- package/dist/web-editor/page.js.map +1 -1
- package/dist/web-editor/server.d.ts.map +1 -1
- package/dist/web-editor/server.js +176 -1
- package/dist/web-editor/server.js.map +1 -1
- package/dist/web-editor/styles.d.ts.map +1 -1
- package/dist/web-editor/styles.js +60 -3
- package/dist/web-editor/styles.js.map +1 -1
- package/dist/web-editor/types.d.ts +87 -0
- package/dist/web-editor/types.d.ts.map +1 -1
- package/dist/web-host.d.ts +13 -2
- package/dist/web-host.d.ts.map +1 -1
- package/dist/web-host.js +371 -27
- package/dist/web-host.js.map +1 -1
- package/docs/README.md +41 -0
- package/docs/concepts/agent-profiles.md +60 -0
- package/docs/concepts/prompt-stacks.md +95 -0
- package/docs/design/README.md +17 -0
- package/docs/design/roadmap-0.4-archive.md +216 -0
- package/docs/design/subagents/design-review.md +220 -0
- package/docs/design/subagents/interface-design.md +274 -0
- package/docs/design/subagents/sdk-spike-findings.md +117 -0
- package/docs/development/complexity-review.md +86 -0
- package/docs/development/release.md +31 -0
- package/docs/development/roadmap.md +36 -0
- package/docs/development/scoped-global-profiles-stacks.md +325 -0
- package/docs/development/setup.md +75 -0
- package/docs/getting-started.md +95 -0
- package/docs/guides/custom-macros-and-slots.md +68 -0
- package/docs/guides/debugging.md +39 -0
- package/docs/guides/delegation.md +107 -0
- package/docs/guides/sillytavern-import.md +47 -0
- package/docs/guides/use-cases.md +65 -0
- package/docs/guides/web-editor.md +75 -0
- package/docs/reference/commands.md +60 -0
- package/docs/reference/configuration.md +66 -0
- package/docs/reference/features.md +280 -0
- package/docs/reference/macros-and-slots.md +82 -0
- package/docs/reference/public-api.md +28 -0
- package/docs/reference/stack-schema.md +167 -0
- package/docs/reference/subagent-adapter.md +204 -0
- package/docs/zh-CN/README.md +37 -0
- package/docs/zh-CN/concepts/agent-profiles.md +46 -0
- package/docs/zh-CN/concepts/prompt-stacks.md +42 -0
- package/docs/zh-CN/getting-started.md +81 -0
- package/docs/zh-CN/guides/delegation.md +66 -0
- package/docs/zh-CN/guides/web-editor.md +45 -0
- package/docs/zh-CN/reference/commands.md +60 -0
- package/package.json +29 -15
- package/dist/subagent/backend-registry.d.ts +0 -75
- package/dist/subagent/backend-registry.d.ts.map +0 -1
- package/dist/subagent/backend-registry.js +0 -463
- package/dist/subagent/backend-registry.js.map +0 -1
- package/dist/subagent/diagnostics.d.ts +0 -3
- package/dist/subagent/diagnostics.d.ts.map +0 -1
- package/dist/subagent/diagnostics.js +0 -5
- package/dist/subagent/diagnostics.js.map +0 -1
- package/dist/subagent/pi-model-runtime.d.ts +0 -8
- package/dist/subagent/pi-model-runtime.d.ts.map +0 -1
- package/dist/subagent/pi-model-runtime.js +0 -22
- package/dist/subagent/pi-model-runtime.js.map +0 -1
- package/dist/subagent/pi-sdk-backend.d.ts +0 -23
- package/dist/subagent/pi-sdk-backend.d.ts.map +0 -1
- package/dist/subagent/pi-sdk-backend.js +0 -383
- package/dist/subagent/pi-sdk-backend.js.map +0 -1
- package/dist/subagent/pi-subprocess-backend.d.ts +0 -72
- package/dist/subagent/pi-subprocess-backend.d.ts.map +0 -1
- package/dist/subagent/pi-subprocess-backend.js +0 -756
- package/dist/subagent/pi-subprocess-backend.js.map +0 -1
- package/dist/subagent/subprocess-bridge.d.ts +0 -21
- package/dist/subagent/subprocess-bridge.d.ts.map +0 -1
- package/dist/subagent/subprocess-bridge.js +0 -87
- package/dist/subagent/subprocess-bridge.js.map +0 -1
- package/dist/subagent/subprocess-report.d.ts +0 -4
- package/dist/subagent/subprocess-report.d.ts.map +0 -1
- package/dist/subagent/subprocess-report.js +0 -55
- package/dist/subagent/subprocess-report.js.map +0 -1
- package/dist/subagent-contract.d.ts +0 -8
- package/dist/subagent-contract.d.ts.map +0 -1
- package/dist/subagent-contract.js +0 -8
- package/dist/subagent-contract.js.map +0 -1
- package/dist/web-editor/client/api.d.ts +0 -9
- package/dist/web-editor/client/api.d.ts.map +0 -1
- package/dist/web-editor/client/api.js +0 -26
- package/dist/web-editor/client/api.js.map +0 -1
- package/dist/web-editor/client/dom.d.ts +0 -13
- package/dist/web-editor/client/dom.d.ts.map +0 -1
- package/dist/web-editor/client/dom.js +0 -30
- package/dist/web-editor/client/dom.js.map +0 -1
- package/dist/web-editor/client/inspector.d.ts +0 -22
- package/dist/web-editor/client/inspector.d.ts.map +0 -1
- package/dist/web-editor/client/inspector.js +0 -226
- package/dist/web-editor/client/inspector.js.map +0 -1
- package/dist/web-editor/client/main.d.ts +0 -2
- package/dist/web-editor/client/main.d.ts.map +0 -1
- package/dist/web-editor/client/main.js +0 -1468
- package/dist/web-editor/client/main.js.map +0 -1
- package/dist/web-editor/client/policy-editor.d.ts +0 -16
- package/dist/web-editor/client/policy-editor.d.ts.map +0 -1
- package/dist/web-editor/client/policy-editor.js +0 -330
- package/dist/web-editor/client/policy-editor.js.map +0 -1
- package/dist/web-editor/client/regex-editor.d.ts +0 -19
- package/dist/web-editor/client/regex-editor.d.ts.map +0 -1
- package/dist/web-editor/client/regex-editor.js +0 -281
- package/dist/web-editor/client/regex-editor.js.map +0 -1
- package/dist/web-editor/client/types.d.ts +0 -60
- package/dist/web-editor/client/types.d.ts.map +0 -1
- package/dist/web-editor/client/types.js +0 -2
- package/dist/web-editor/client/types.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagent-profile-tool.js","sourceRoot":"","sources":["../src/subagent-profile-tool.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"subagent-profile-tool.js","sourceRoot":"","sources":["../src/subagent-profile-tool.ts"],"names":[],"mappings":"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"}
|
package/dist/subagent-tool.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { type ExtensionAPI, type ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import
|
|
2
|
+
import { type ForgeSubagentSettings } from "./forge-config.ts";
|
|
3
|
+
import type { LoadedAgentProfile, ResolvedAgentProfile } from "./agent-profile.ts";
|
|
4
|
+
import { type ForgeSubagentProfileSummary } from "./subagent-profile-tool.ts";
|
|
5
|
+
import type { ForgeSubagentPreparedRun, ForgeSubagentRuntime, SubagentBackendExecutionUpdate } from "./runtime/subagent-runtime.ts";
|
|
3
6
|
import type { AgentResponse, SubagentDiagnostic } from "./subagent/contract.ts";
|
|
4
|
-
import type
|
|
5
|
-
import { type PiSubprocessRunReport } from "./subagent/pi-subprocess-backend.ts";
|
|
7
|
+
import { type PiSubprocessRunReport } from "@zihanw/pi-subagent-runtime/backends/subprocess";
|
|
6
8
|
export interface ForgeSubagentApprovalReceipt {
|
|
7
9
|
required: boolean;
|
|
8
10
|
approved: boolean;
|
|
@@ -24,7 +26,10 @@ export interface ForgeSubagentPlanSummary {
|
|
|
24
26
|
systemPromptChars: number;
|
|
25
27
|
messageCount: number;
|
|
26
28
|
messageRoles: string[];
|
|
29
|
+
timeoutMs?: number;
|
|
30
|
+
timeoutEnforcement?: string;
|
|
27
31
|
promptRuntimeFingerprint: string;
|
|
32
|
+
conversationFingerprint: string;
|
|
28
33
|
executionFingerprint: string;
|
|
29
34
|
}
|
|
30
35
|
export interface ForgeSubagentToolDetails {
|
|
@@ -42,9 +47,31 @@ export interface ForgeSubagentApprovalResult {
|
|
|
42
47
|
approved: boolean;
|
|
43
48
|
viewedFullPrompt: boolean;
|
|
44
49
|
}
|
|
45
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Optional refresh-time inputs for the forge_subagent tool description.
|
|
52
|
+
* `summarize` returns the embedded profile summary for a context, or
|
|
53
|
+
* undefined when the summary is disabled or empty; the tool re-registers
|
|
54
|
+
* only when the rendered description would change.
|
|
55
|
+
*/
|
|
56
|
+
export interface ForgeSubagentToolRegistrationOptions {
|
|
57
|
+
summarize?: (ctx: ExtensionContext) => string | undefined;
|
|
58
|
+
}
|
|
59
|
+
export declare function registerForgeSubagentTool(pi: ExtensionAPI, runtime: ForgeSubagentRuntime, profileIds: () => string[], resolveProfileKey: (selector: string) => {
|
|
60
|
+
scope: "global" | "project";
|
|
61
|
+
id: string;
|
|
62
|
+
} | undefined, options?: ForgeSubagentToolRegistrationOptions): (ctx: ExtensionContext) => void;
|
|
63
|
+
/**
|
|
64
|
+
* Compact summary of enabled subagent profiles for the forge_subagent tool
|
|
65
|
+
* description. Rendered only when subagents.summaryInToolDescription
|
|
66
|
+
* is enabled; ready profiles come first, unavailable profiles stay visible so
|
|
67
|
+
* the model does not attempt them. Returns undefined when disabled or when no
|
|
68
|
+
* profile is enabled for delegation.
|
|
69
|
+
*/
|
|
70
|
+
export declare function renderEmbeddedSubagentSummary(settings: ForgeSubagentSettings, profiles: readonly LoadedAgentProfile[], resolve: (loaded: LoadedAgentProfile) => ResolvedAgentProfile): string | undefined;
|
|
71
|
+
export declare function renderEmbeddedSummaryText(summaries: readonly ForgeSubagentProfileSummary[]): string;
|
|
46
72
|
export declare function requestForgeSubagentApproval(prepared: ForgeSubagentPreparedRun, task: string, ctx: ExtensionContext, signal?: AbortSignal): Promise<ForgeSubagentApprovalResult>;
|
|
47
73
|
export declare function summarizeForgeSubagentPlan(prepared: ForgeSubagentPreparedRun, cwd: string): ForgeSubagentPlanSummary;
|
|
48
74
|
export declare function renderApprovalSummary(prepared: ForgeSubagentPreparedRun, task: string, cwd: string): string;
|
|
75
|
+
export declare function renderApprovalDetails(prepared: ForgeSubagentPreparedRun, task: string, cwd: string): string;
|
|
49
76
|
export declare function renderFullForgeSubagentPrompt(prepared: ForgeSubagentPreparedRun): string;
|
|
50
77
|
//# sourceMappingURL=subagent-tool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagent-tool.d.ts","sourceRoot":"","sources":["../src/subagent-tool.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,YAAY,EACjB,KAAK,gBAAgB,EAErB,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"subagent-tool.d.ts","sourceRoot":"","sources":["../src/subagent-tool.ts"],"names":[],"mappings":"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"}
|
package/dist/subagent-tool.js
CHANGED
|
@@ -1,163 +1,295 @@
|
|
|
1
1
|
import { getMarkdownTheme, } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { Container, Markdown, Spacer, Text } from "@earendil-works/pi-tui";
|
|
3
3
|
import { Type } from "typebox";
|
|
4
|
-
import { loadForgeSubagentSettings } from "./forge-config.js";
|
|
5
|
-
import {
|
|
4
|
+
import { loadForgeSubagentSettings, resolveSubagentProfilePolicy } from "./forge-config.js";
|
|
5
|
+
import { formatResourceKey } from "./resource-identity.js";
|
|
6
|
+
import { summarizeProfile } from "./subagent-profile-tool.js";
|
|
7
|
+
import { sanitizePiSubprocessRunReport, } from "@zihanw/pi-subagent-runtime/backends/subprocess";
|
|
8
|
+
import { isRecord } from "@zihanw/pi-subagent-runtime";
|
|
6
9
|
const APPROVE = "Approve and run";
|
|
7
10
|
const VIEW_FULL_PROMPT = "View full prompt";
|
|
8
11
|
const REJECT = "Reject";
|
|
9
12
|
const MAX_PROGRESS_ITEMS = 100;
|
|
13
|
+
const MAX_APPROVAL_TASK_PREVIEW_CHARS = 48;
|
|
14
|
+
const MAX_APPROVAL_EXECUTION_PREVIEW_CHARS = 44;
|
|
15
|
+
const MAX_APPROVAL_PATH_PREVIEW_CHARS = 44;
|
|
16
|
+
const MAX_APPROVAL_FINGERPRINT_PREVIEW_CHARS = 24;
|
|
17
|
+
const MAX_EMBEDDED_PROFILES = 8;
|
|
18
|
+
const MAX_EMBEDDED_SUMMARY_CHARS = 1_000;
|
|
10
19
|
const ForgeSubagentParameters = Type.Object({
|
|
11
20
|
profileId: Type.String({
|
|
12
21
|
minLength: 1,
|
|
13
|
-
description: "ID of a
|
|
22
|
+
description: "ID of a Pi Forge agent profile explicitly enabled for subagent delegation.",
|
|
14
23
|
}),
|
|
15
24
|
task: Type.String({
|
|
16
25
|
minLength: 1,
|
|
17
26
|
description: "The focused task to delegate to the subagent.",
|
|
18
27
|
}),
|
|
28
|
+
backend: Type.Optional(Type.String({
|
|
29
|
+
minLength: 1,
|
|
30
|
+
description: "Backend ID to prepare and execute through (see /forge-agent backends). Honored only for interactively approved runs; trusted-project unattended invocation always uses the configured default backend.",
|
|
31
|
+
})),
|
|
19
32
|
});
|
|
20
|
-
export function registerForgeSubagentTool(pi, runtime, profileIds) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
source: approvalRequired ? "none" : "trusted-project-config",
|
|
46
|
-
},
|
|
47
|
-
diagnostics: configDiagnostics,
|
|
48
|
-
progress: [],
|
|
49
|
-
};
|
|
50
|
-
if (approvalRequired && !ctx.hasUI) {
|
|
51
|
-
return toolResult("Subagent invocation was not run: interactive human approval is unavailable.", { ...baseDetails, status: "cancelled" });
|
|
52
|
-
}
|
|
53
|
-
if (!profileIds().includes(params.profileId)) {
|
|
54
|
-
const available = profileIds().join(", ") || "none";
|
|
55
|
-
return toolResult(`Unknown Pi Forge agent profile: ${params.profileId}. Available profiles: ${available}.`, { ...baseDetails, status: "failed" }, true);
|
|
56
|
-
}
|
|
57
|
-
onUpdate?.(toolResult("Preparing the exact subagent prompt; provider transport is still closed.", baseDetails));
|
|
58
|
-
let prepared;
|
|
59
|
-
try {
|
|
60
|
-
const preparation = await runtime.prepare(params.profileId, params.task, ctx);
|
|
61
|
-
if (!preparation.ok) {
|
|
62
|
-
const diagnostics = [...configDiagnostics, ...preparation.diagnostics];
|
|
63
|
-
return toolResult(`Subagent preparation failed:\n${renderDiagnostics(diagnostics)}`, { ...baseDetails, status: "failed", diagnostics }, true);
|
|
64
|
-
}
|
|
65
|
-
prepared = preparation.prepared;
|
|
66
|
-
const plan = summarizeForgeSubagentPlan(prepared, ctx.cwd);
|
|
67
|
-
const preparedDetails = {
|
|
68
|
-
...baseDetails,
|
|
69
|
-
status: approvalRequired ? "awaiting-approval" : "prepared",
|
|
70
|
-
plan,
|
|
71
|
-
diagnostics: [...configDiagnostics, ...prepared.diagnostics],
|
|
72
|
-
};
|
|
73
|
-
onUpdate?.(toolResult(approvalRequired
|
|
74
|
-
? "The exact plan is ready and awaiting human approval."
|
|
75
|
-
: "The exact plan is ready; per-run approval is bypassed by trusted-project configuration.", preparedDetails));
|
|
76
|
-
const approval = approvalRequired
|
|
77
|
-
? await requestForgeSubagentApproval(prepared, params.task, ctx, signal)
|
|
78
|
-
: { approved: true, viewedFullPrompt: false };
|
|
79
|
-
if (!approval.approved) {
|
|
80
|
-
await runtime.discard(prepared);
|
|
81
|
-
prepared = undefined;
|
|
82
|
-
return toolResult("Subagent invocation was rejected by the human before provider transport.", {
|
|
83
|
-
...preparedDetails,
|
|
84
|
-
status: "cancelled",
|
|
85
|
-
approval: { required: true, approved: false, viewedFullPrompt: approval.viewedFullPrompt, source: "none" },
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
const approvedAt = new Date().toISOString();
|
|
89
|
-
const progress = [];
|
|
90
|
-
const running = {
|
|
91
|
-
...preparedDetails,
|
|
92
|
-
status: "running",
|
|
33
|
+
export function registerForgeSubagentTool(pi, runtime, profileIds, resolveProfileKey, options = {}) {
|
|
34
|
+
// The description is static at registration time; re-registering the tool
|
|
35
|
+
// by name replaces its definition and refreshes the tool registry. Track
|
|
36
|
+
// the last embedded summary so lifecycle refreshes (every turn included)
|
|
37
|
+
// are no-ops unless the profile summary actually changed.
|
|
38
|
+
let lastSummary;
|
|
39
|
+
function register(embedded) {
|
|
40
|
+
pi.registerTool({
|
|
41
|
+
name: "forge_subagent",
|
|
42
|
+
label: "Forge Subagent",
|
|
43
|
+
description: forgeSubagentToolDescription(embedded),
|
|
44
|
+
parameters: ForgeSubagentParameters,
|
|
45
|
+
// Parallel execution lets the parent model issue several subagent calls
|
|
46
|
+
// in one turn. Pi serializes a whole batch only when any call in it is
|
|
47
|
+
// sequential; approvals stay safe because requestForgeSubagentApproval
|
|
48
|
+
// serializes its dialogs internally.
|
|
49
|
+
executionMode: "parallel",
|
|
50
|
+
async execute(_toolCallId, params, signal, onUpdate, ctx) {
|
|
51
|
+
const settings = loadForgeSubagentSettings(ctx);
|
|
52
|
+
const approvalRequired = !settings.allowAgentInvocationWithoutApproval;
|
|
53
|
+
const configDiagnostics = settings.warnings.map((message) => ({ level: "warning", code: "host.config", message }));
|
|
54
|
+
const baseDetails = {
|
|
55
|
+
status: "preparing",
|
|
56
|
+
profileId: params.profileId,
|
|
57
|
+
task: params.task,
|
|
93
58
|
approval: {
|
|
94
59
|
required: approvalRequired,
|
|
95
|
-
approved:
|
|
96
|
-
viewedFullPrompt:
|
|
97
|
-
source: approvalRequired ? "
|
|
98
|
-
executionFingerprint: prepared.plan.executionFingerprint,
|
|
99
|
-
approvedAt,
|
|
60
|
+
approved: false,
|
|
61
|
+
viewedFullPrompt: false,
|
|
62
|
+
source: approvalRequired ? "none" : "trusted-project-config",
|
|
100
63
|
},
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const response = await runtime.execute(prepared, ctx, signal, (update) => {
|
|
104
|
-
progress.push(structuredClone(update));
|
|
105
|
-
if (progress.length > MAX_PROGRESS_ITEMS)
|
|
106
|
-
progress.splice(0, progress.length - MAX_PROGRESS_ITEMS);
|
|
107
|
-
onUpdate?.(toolResult(truncate(update.message, 2_000), { ...running, progress: [...progress] }));
|
|
108
|
-
});
|
|
109
|
-
prepared = undefined;
|
|
110
|
-
const rawReport = runtime.takeReport?.(response.runId);
|
|
111
|
-
const report = rawReport ? sanitizePiSubprocessRunReport(rawReport) : undefined;
|
|
112
|
-
const finalDetails = {
|
|
113
|
-
...running,
|
|
114
|
-
status: toolStatus(response),
|
|
115
|
-
progress: [...progress],
|
|
116
|
-
response,
|
|
117
|
-
report,
|
|
64
|
+
diagnostics: configDiagnostics,
|
|
65
|
+
progress: [],
|
|
118
66
|
};
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
67
|
+
const knownProfileIds = profileIds();
|
|
68
|
+
const enabledProfileIds = knownProfileIds.filter((profileId) => resolveSubagentProfilePolicy(settings, profileId).enabled);
|
|
69
|
+
const profileKey = resolveProfileKey(params.profileId);
|
|
70
|
+
if (!profileKey) {
|
|
71
|
+
const available = enabledProfileIds.join(", ") || "none";
|
|
72
|
+
return toolResult(`Unknown Pi Forge agent profile: ${params.profileId}. Enabled subagent profiles: ${available}.`, { ...baseDetails, status: "failed" }, true);
|
|
73
|
+
}
|
|
74
|
+
const canonicalProfileId = formatResourceKey(profileKey);
|
|
75
|
+
baseDetails.profileId = canonicalProfileId;
|
|
76
|
+
const configuredPolicy = resolveSubagentProfilePolicy(settings, canonicalProfileId);
|
|
77
|
+
if (!configuredPolicy.enabled) {
|
|
78
|
+
return toolResult(`Pi Forge agent profile "${params.profileId}" is not enabled for subagent delegation. Use forge_subagent_profiles to discover enabled profiles.`, { ...baseDetails, status: "failed" }, true);
|
|
79
|
+
}
|
|
80
|
+
const configuredBackend = configuredPolicy.backend;
|
|
81
|
+
if (!approvalRequired && params.backend && params.backend !== configuredBackend.id) {
|
|
82
|
+
return toolResult(`Subagent invocation was not run: unattended invocation is pinned to the configured backend "${configuredBackend.id}". To use "${params.backend}", run interactively or change the trusted subagent configuration.`, {
|
|
83
|
+
...baseDetails,
|
|
84
|
+
status: "failed",
|
|
85
|
+
approval: { required: false, approved: false, viewedFullPrompt: false, source: "trusted-project-config" },
|
|
86
|
+
}, true);
|
|
87
|
+
}
|
|
88
|
+
const runPolicy = resolveSubagentProfilePolicy(settings, canonicalProfileId, approvalRequired ? params.backend : undefined);
|
|
89
|
+
if (approvalRequired && !ctx.hasUI) {
|
|
90
|
+
return toolResult("Subagent invocation was not run: interactive human approval is unavailable.", { ...baseDetails, status: "cancelled" });
|
|
91
|
+
}
|
|
92
|
+
onUpdate?.(toolResult("Preparing the exact subagent prompt; provider transport is still closed.", baseDetails));
|
|
93
|
+
let prepared;
|
|
94
|
+
try {
|
|
95
|
+
const preparation = await runtime.prepare(canonicalProfileId, params.task, ctx, {
|
|
96
|
+
backendId: runPolicy.backend.id,
|
|
97
|
+
timeoutMs: runPolicy.timeout.milliseconds,
|
|
98
|
+
});
|
|
99
|
+
if (!preparation.ok) {
|
|
100
|
+
const diagnostics = [...configDiagnostics, ...preparation.diagnostics];
|
|
101
|
+
return toolResult(`Subagent preparation failed:\n${renderDiagnostics(diagnostics)}`, { ...baseDetails, status: "failed", diagnostics }, true);
|
|
102
|
+
}
|
|
103
|
+
prepared = preparation.prepared;
|
|
104
|
+
const plan = summarizeForgeSubagentPlan(prepared, ctx.cwd);
|
|
105
|
+
const preparedDetails = {
|
|
106
|
+
...baseDetails,
|
|
107
|
+
status: approvalRequired ? "awaiting-approval" : "prepared",
|
|
108
|
+
plan,
|
|
109
|
+
diagnostics: [...configDiagnostics, ...prepared.diagnostics],
|
|
110
|
+
};
|
|
111
|
+
onUpdate?.(toolResult(approvalRequired
|
|
112
|
+
? "The exact plan is ready and awaiting human approval."
|
|
113
|
+
: "The exact plan is ready; per-run approval is bypassed by trusted-project configuration.", preparedDetails));
|
|
114
|
+
const approval = approvalRequired
|
|
115
|
+
? await requestForgeSubagentApproval(prepared, params.task, ctx, signal)
|
|
116
|
+
: { approved: true, viewedFullPrompt: false };
|
|
117
|
+
if (!approval.approved) {
|
|
118
|
+
await runtime.discard(prepared);
|
|
119
|
+
prepared = undefined;
|
|
120
|
+
return toolResult("Subagent invocation was rejected by the human before provider transport.", {
|
|
121
|
+
...preparedDetails,
|
|
122
|
+
status: "cancelled",
|
|
123
|
+
approval: { required: true, approved: false, viewedFullPrompt: approval.viewedFullPrompt, source: "none" },
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
const approvedAt = new Date().toISOString();
|
|
127
|
+
const progress = [];
|
|
128
|
+
const running = {
|
|
129
|
+
...preparedDetails,
|
|
130
|
+
status: "running",
|
|
131
|
+
approval: {
|
|
132
|
+
required: approvalRequired,
|
|
133
|
+
approved: true,
|
|
134
|
+
viewedFullPrompt: approval.viewedFullPrompt,
|
|
135
|
+
source: approvalRequired ? "human" : "trusted-project-config",
|
|
136
|
+
executionFingerprint: prepared.plan.executionFingerprint,
|
|
137
|
+
approvedAt,
|
|
138
|
+
},
|
|
139
|
+
progress,
|
|
140
|
+
};
|
|
141
|
+
const response = await runtime.execute(prepared, ctx, signal, (update) => {
|
|
142
|
+
progress.push(structuredClone(update));
|
|
143
|
+
if (progress.length > MAX_PROGRESS_ITEMS)
|
|
144
|
+
progress.splice(0, progress.length - MAX_PROGRESS_ITEMS);
|
|
145
|
+
onUpdate?.(toolResult(truncate(update.message, 2_000), { ...running, progress: [...progress] }));
|
|
146
|
+
});
|
|
147
|
+
prepared = undefined;
|
|
148
|
+
const rawReport = runtime.takeReport?.(response.runId);
|
|
149
|
+
const report = rawReport ? sanitizePiSubprocessRunReport(rawReport) : undefined;
|
|
150
|
+
const finalDetails = {
|
|
151
|
+
...running,
|
|
152
|
+
status: toolStatus(response),
|
|
153
|
+
progress: [...progress],
|
|
154
|
+
response,
|
|
155
|
+
report,
|
|
156
|
+
};
|
|
157
|
+
return toolResult(renderResponseForModel(response), finalDetails, response.status === "failed");
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
if (prepared)
|
|
161
|
+
await runtime.discard(prepared).catch(() => undefined);
|
|
162
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
163
|
+
return toolResult(`Subagent invocation failed: ${message}`, { ...baseDetails, status: "failed" }, true);
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
renderCall(args, theme) {
|
|
167
|
+
const task = truncate(args.task.replace(/\s+/g, " ").trim(), 100);
|
|
168
|
+
return new Text(`${theme.fg("toolTitle", theme.bold("forge subagent "))}${theme.fg("accent", args.profileId)}\n${theme.fg("dim", task)}`, 0, 0);
|
|
169
|
+
},
|
|
170
|
+
renderResult(result, { expanded, isPartial }, theme) {
|
|
171
|
+
const details = result.details;
|
|
172
|
+
if (!details)
|
|
173
|
+
return new Text(textContent(result) || "(no subagent result)", 0, 0);
|
|
174
|
+
if (!expanded)
|
|
175
|
+
return renderCollapsedResult(result, details, isPartial, theme);
|
|
176
|
+
return renderExpandedResult(result, details, theme);
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
function refresh(ctx) {
|
|
181
|
+
const summary = options.summarize?.(ctx);
|
|
182
|
+
if (summary === lastSummary)
|
|
183
|
+
return;
|
|
184
|
+
lastSummary = summary;
|
|
185
|
+
register(summary);
|
|
186
|
+
}
|
|
187
|
+
register(undefined);
|
|
188
|
+
return refresh;
|
|
141
189
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
190
|
+
function forgeSubagentToolDescription(embedded) {
|
|
191
|
+
const lines = [
|
|
192
|
+
"Delegate one foreground task to a Pi Forge agent profile explicitly enabled in subagents.profiles.",
|
|
193
|
+
"Multiple forge_subagent calls in one turn run concurrently; interactive approvals are serialized one at a time.",
|
|
194
|
+
embedded
|
|
195
|
+
? "The enabled profiles are summarized below; run forge_subagent_profiles for full descriptions, diagnostics, and approval mode."
|
|
196
|
+
: "Use forge_subagent_profiles first when the user has not already specified a profile ID.",
|
|
197
|
+
"Runs require human approval after exact preparation unless the trusted project explicitly enables unattended agent invocation.",
|
|
198
|
+
"The child receives only approved read tools, but runs with the invoking user's OS permissions; read-only is not a sandbox.",
|
|
199
|
+
"The optional backend parameter selects the execution backend for interactively approved runs; unattended invocation always uses the configured default backend.",
|
|
200
|
+
"Use the final report as evidence and do not repeatedly request the same rejected delegation.",
|
|
201
|
+
].join(" ");
|
|
202
|
+
return embedded ? `${lines}\n\n${embedded}` : lines;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Compact summary of enabled subagent profiles for the forge_subagent tool
|
|
206
|
+
* description. Rendered only when subagents.summaryInToolDescription
|
|
207
|
+
* is enabled; ready profiles come first, unavailable profiles stay visible so
|
|
208
|
+
* the model does not attempt them. Returns undefined when disabled or when no
|
|
209
|
+
* profile is enabled for delegation.
|
|
210
|
+
*/
|
|
211
|
+
export function renderEmbeddedSubagentSummary(settings, profiles, resolve) {
|
|
212
|
+
if (!settings.summaryInToolDescription)
|
|
213
|
+
return undefined;
|
|
214
|
+
const summaries = [];
|
|
215
|
+
for (const loaded of profiles) {
|
|
216
|
+
const policy = resolveSubagentProfilePolicy(settings, formatResourceKey(loaded.key));
|
|
217
|
+
if (!policy.enabled)
|
|
149
218
|
continue;
|
|
150
|
-
|
|
151
|
-
return { approved: choice === APPROVE, viewedFullPrompt };
|
|
219
|
+
summaries.push(summarizeProfile(loaded, resolve(loaded), policy));
|
|
152
220
|
}
|
|
153
|
-
|
|
221
|
+
if (summaries.length === 0)
|
|
222
|
+
return undefined;
|
|
223
|
+
const readyFirst = [...summaries].sort((a, b) => statusRank(a.status) - statusRank(b.status));
|
|
224
|
+
return renderEmbeddedSummaryText(readyFirst);
|
|
225
|
+
}
|
|
226
|
+
export function renderEmbeddedSummaryText(summaries) {
|
|
227
|
+
const total = summaries.length;
|
|
228
|
+
const visible = summaries.slice(0, MAX_EMBEDDED_PROFILES);
|
|
229
|
+
const lines = ["Enabled subagent profiles:"];
|
|
230
|
+
for (const profile of visible)
|
|
231
|
+
lines.push(`- ${embeddedProfileLine(profile)}`);
|
|
232
|
+
if (total > visible.length) {
|
|
233
|
+
const omitted = total - visible.length;
|
|
234
|
+
lines.push(`- ... and ${omitted} more enabled profile${omitted === 1 ? "" : "s"} (forge_subagent_profiles lists all)`);
|
|
235
|
+
}
|
|
236
|
+
const text = lines.join("\n");
|
|
237
|
+
return text.length <= MAX_EMBEDDED_SUMMARY_CHARS
|
|
238
|
+
? text
|
|
239
|
+
: `${text.slice(0, Math.max(0, MAX_EMBEDDED_SUMMARY_CHARS - 3))}...`;
|
|
240
|
+
}
|
|
241
|
+
function statusRank(status) {
|
|
242
|
+
return status === "ready" ? 0 : 1;
|
|
243
|
+
}
|
|
244
|
+
function embeddedProfileLine(profile) {
|
|
245
|
+
const label = profile.name ? `${profile.id} — ${compact(profile.name)}` : profile.id;
|
|
246
|
+
const target = `${profile.model.provider}/${profile.model.id} · thinking ${profile.thinkingLevel} · stack ${profile.promptStack ?? "none"}`;
|
|
247
|
+
const execution = `backend ${profile.backend.id} · ${formatTimeoutMs(profile.timeout.milliseconds)}`;
|
|
248
|
+
if (profile.status === "ready")
|
|
249
|
+
return `${label}: ${target}; ${execution}`;
|
|
250
|
+
const reason = profile.diagnostics.find((diagnostic) => diagnostic.level === "error")?.message
|
|
251
|
+
?? "profile resolution failed";
|
|
252
|
+
return `${label}: ${target}; ${execution} (unavailable: ${compact(reason)})`;
|
|
253
|
+
}
|
|
254
|
+
function formatTimeoutMs(milliseconds) {
|
|
255
|
+
return milliseconds % 1_000 === 0 ? `${milliseconds / 1_000}s` : `${milliseconds}ms`;
|
|
256
|
+
}
|
|
257
|
+
// Pi's select/editor UI is a single slot: a second concurrent dialog clears
|
|
258
|
+
// the first component and leaves its promise permanently unresolved. Parallel
|
|
259
|
+
// tool calls must therefore serialize the interactive approval flow through
|
|
260
|
+
// this gate. Execution after each approval is not gated, so approved runs
|
|
261
|
+
// still overlap; unattended invocation never enters the gate.
|
|
262
|
+
let approvalDialogGate = Promise.resolve();
|
|
263
|
+
function withApprovalDialog(run) {
|
|
264
|
+
const next = approvalDialogGate.then(run);
|
|
265
|
+
approvalDialogGate = next.then(() => undefined, () => undefined);
|
|
266
|
+
return next;
|
|
267
|
+
}
|
|
268
|
+
export async function requestForgeSubagentApproval(prepared, task, ctx, signal) {
|
|
269
|
+
return withApprovalDialog(async () => {
|
|
270
|
+
let viewedFullPrompt = false;
|
|
271
|
+
while (!signal?.aborted) {
|
|
272
|
+
const choice = await ctx.ui.select(renderApprovalSummary(prepared, task, ctx.cwd), [APPROVE, VIEW_FULL_PROMPT, REJECT], { signal });
|
|
273
|
+
if (choice === VIEW_FULL_PROMPT) {
|
|
274
|
+
viewedFullPrompt = true;
|
|
275
|
+
await ctx.ui.editor(`Subagent approval details: ${prepared.plan.profile.profileId} (view only; edits are ignored)`, [
|
|
276
|
+
renderApprovalDetails(prepared, task, ctx.cwd),
|
|
277
|
+
"",
|
|
278
|
+
renderFullForgeSubagentPrompt(prepared),
|
|
279
|
+
].join("\n"));
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
return { approved: choice === APPROVE, viewedFullPrompt };
|
|
283
|
+
}
|
|
284
|
+
return { approved: false, viewedFullPrompt };
|
|
285
|
+
});
|
|
154
286
|
}
|
|
155
287
|
export function summarizeForgeSubagentPlan(prepared, cwd) {
|
|
156
288
|
const plan = prepared.plan;
|
|
157
289
|
return {
|
|
158
290
|
backendId: plan.backendId,
|
|
159
|
-
profileId: plan.profile.
|
|
160
|
-
promptStackId: plan.profile.
|
|
291
|
+
profileId: plan.profile.profileId,
|
|
292
|
+
promptStackId: plan.profile.promptStackId,
|
|
161
293
|
provider: plan.model.provider,
|
|
162
294
|
model: plan.model.id,
|
|
163
295
|
thinkingLevel: plan.thinkingLevel,
|
|
@@ -167,19 +299,44 @@ export function summarizeForgeSubagentPlan(prepared, cwd) {
|
|
|
167
299
|
systemPromptChars: plan.systemPrompt.length,
|
|
168
300
|
messageCount: plan.messages.length,
|
|
169
301
|
messageRoles: plan.messages.map((message) => message.role),
|
|
302
|
+
...(plan.limits.timeoutMs ? {
|
|
303
|
+
timeoutMs: plan.limits.timeoutMs.value,
|
|
304
|
+
timeoutEnforcement: plan.limits.timeoutMs.enforcement,
|
|
305
|
+
} : {}),
|
|
170
306
|
promptRuntimeFingerprint: plan.promptRuntimeFingerprint,
|
|
307
|
+
conversationFingerprint: plan.conversationFingerprint,
|
|
171
308
|
executionFingerprint: plan.executionFingerprint,
|
|
172
309
|
};
|
|
173
310
|
}
|
|
174
311
|
export function renderApprovalSummary(prepared, task, cwd) {
|
|
312
|
+
const plan = prepared.plan;
|
|
313
|
+
const summary = summarizeForgeSubagentPlan(prepared, cwd);
|
|
314
|
+
const timeout = summary.timeoutMs === undefined
|
|
315
|
+
? "none"
|
|
316
|
+
: `${summary.timeoutMs} ms ${summary.timeoutEnforcement ?? "unknown enforcement"}`;
|
|
317
|
+
return [
|
|
318
|
+
`Run foreground subagent ${oneLinePreview(summary.profileId, MAX_APPROVAL_EXECUTION_PREVIEW_CHARS)}?`,
|
|
319
|
+
`Task: ${oneLinePreview(task, MAX_APPROVAL_TASK_PREVIEW_CHARS)}`,
|
|
320
|
+
`Backend: ${oneLinePreview(summary.backendId, MAX_APPROVAL_EXECUTION_PREVIEW_CHARS)}`,
|
|
321
|
+
`Model: ${oneLinePreview(`${summary.provider}/${summary.model} · thinking ${summary.thinkingLevel}`, MAX_APPROVAL_EXECUTION_PREVIEW_CHARS)}`,
|
|
322
|
+
`Stack/tools: ${oneLinePreview(`${summary.promptStackId ?? "none"} · ${toolNames(plan).join(", ") || "none"}`, MAX_APPROVAL_EXECUTION_PREVIEW_CHARS)}`,
|
|
323
|
+
`Directory: ${oneLinePreview(summary.workingDirectory, MAX_APPROVAL_PATH_PREVIEW_CHARS)}`,
|
|
324
|
+
`Boundary: ${oneLinePreview(summary.executionBoundary, 16)} · ${timeout}`,
|
|
325
|
+
`Payload: ${summary.systemPromptChars} system chars + ${summary.messageCount} messages`,
|
|
326
|
+
`Execution: ${compactIdentifier(summary.executionFingerprint, MAX_APPROVAL_FINGERPRINT_PREVIEW_CHARS)} (see full prompt)`,
|
|
327
|
+
"No OS sandbox; provider gets prompt/files read by agent.",
|
|
328
|
+
].join("\n");
|
|
329
|
+
}
|
|
330
|
+
export function renderApprovalDetails(prepared, task, cwd) {
|
|
175
331
|
const plan = prepared.plan;
|
|
176
332
|
const summary = summarizeForgeSubagentPlan(prepared, cwd);
|
|
177
333
|
return [
|
|
178
|
-
|
|
334
|
+
"# Subagent approval details",
|
|
179
335
|
"",
|
|
180
336
|
"Agent prompt:",
|
|
181
337
|
indent(truncate(task, 2_000)),
|
|
182
338
|
"",
|
|
339
|
+
`Backend: ${summary.backendId}`,
|
|
183
340
|
`Provider: ${summary.provider}`,
|
|
184
341
|
`Model: ${summary.model}`,
|
|
185
342
|
`Thinking: ${summary.thinkingLevel}`,
|
|
@@ -187,7 +344,10 @@ export function renderApprovalSummary(prepared, task, cwd) {
|
|
|
187
344
|
`Tools: ${toolNames(plan).join(", ") || "none"}`,
|
|
188
345
|
`Working directory: ${summary.workingDirectory}`,
|
|
189
346
|
`Boundary: ${summary.executionBoundary} (read-only tool policy; no OS sandbox)`,
|
|
347
|
+
...(summary.timeoutMs === undefined ? [] : [`Timeout: ${summary.timeoutMs} ms (${summary.timeoutEnforcement ?? "unknown enforcement"})`]),
|
|
190
348
|
`Full payload: ${summary.systemPromptChars} system chars + ${summary.messageCount} messages`,
|
|
349
|
+
`Prompt runtime fingerprint: ${summary.promptRuntimeFingerprint}`,
|
|
350
|
+
`Conversation fingerprint: ${summary.conversationFingerprint}`,
|
|
191
351
|
`Execution fingerprint: ${summary.executionFingerprint}`,
|
|
192
352
|
"",
|
|
193
353
|
"The provider receives the compiled prompt and any files the read tools access.",
|
|
@@ -206,10 +366,12 @@ export function renderFullForgeSubagentPrompt(prepared) {
|
|
|
206
366
|
`# Exact provider-bound subagent prompt`,
|
|
207
367
|
"",
|
|
208
368
|
`Backend: ${plan.backendId}`,
|
|
209
|
-
`Profile: ${plan.profile.
|
|
369
|
+
`Profile: ${plan.profile.profileId}`,
|
|
210
370
|
`Provider/model: ${plan.model.provider}/${plan.model.id}`,
|
|
211
371
|
`Thinking: ${plan.thinkingLevel}`,
|
|
212
372
|
`Tools: ${toolNames(plan).join(", ") || "none"}`,
|
|
373
|
+
`Timeout: ${plan.limits.timeoutMs ? `${plan.limits.timeoutMs.value} ms (${plan.limits.timeoutMs.enforcement})` : "none"}`,
|
|
374
|
+
`Conversation fingerprint: ${plan.conversationFingerprint}`,
|
|
213
375
|
`Execution fingerprint: ${plan.executionFingerprint}`,
|
|
214
376
|
"",
|
|
215
377
|
"## System prompt",
|
|
@@ -246,6 +408,7 @@ function renderExpandedResult(result, details, theme) {
|
|
|
246
408
|
container.addChild(new Text([
|
|
247
409
|
`${theme.fg("muted", "Model:")} ${details.plan.provider}/${details.plan.model} (${details.plan.thinkingLevel})`,
|
|
248
410
|
`${theme.fg("muted", "Boundary:")} ${details.plan.executionBoundary}; read-only model tools`,
|
|
411
|
+
...(details.plan.timeoutMs === undefined ? [] : [`${theme.fg("muted", "Timeout:")} ${details.plan.timeoutMs} ms (${details.plan.timeoutEnforcement ?? "unknown"})`]),
|
|
249
412
|
`${theme.fg("muted", "Tools:")} ${details.plan.effectiveToolIds.join(", ") || "none"}`,
|
|
250
413
|
`${theme.fg("muted", "Fingerprint:")} ${details.plan.executionFingerprint}`,
|
|
251
414
|
`${theme.fg("muted", "Approval:")} ${approvalText(details.approval)}`,
|
|
@@ -376,10 +539,21 @@ function indent(text) {
|
|
|
376
539
|
function truncate(text, maxChars) {
|
|
377
540
|
return text.length <= maxChars ? text : `${text.slice(0, Math.max(0, maxChars - 3))}...`;
|
|
378
541
|
}
|
|
542
|
+
function compact(value) {
|
|
543
|
+
return value.replace(/\s+/g, " ").trim();
|
|
544
|
+
}
|
|
545
|
+
function oneLinePreview(text, maxChars) {
|
|
546
|
+
return truncate(text.replace(/\s+/g, " ").trim(), maxChars);
|
|
547
|
+
}
|
|
548
|
+
function compactIdentifier(value, maxChars) {
|
|
549
|
+
if (value.length <= maxChars)
|
|
550
|
+
return value;
|
|
551
|
+
const visibleChars = Math.max(2, maxChars - 3);
|
|
552
|
+
const startChars = Math.ceil(visibleChars / 2);
|
|
553
|
+
const endChars = Math.floor(visibleChars / 2);
|
|
554
|
+
return `${value.slice(0, startChars)}...${value.slice(-endChars)}`;
|
|
555
|
+
}
|
|
379
556
|
function truncateLines(text, maxLines, maxChars) {
|
|
380
557
|
return truncate(text.split("\n").slice(0, maxLines).join("\n"), maxChars);
|
|
381
558
|
}
|
|
382
|
-
function isRecord(value) {
|
|
383
|
-
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
384
|
-
}
|
|
385
559
|
//# sourceMappingURL=subagent-tool.js.map
|