pi-ui-extend 1.0.39 → 1.0.41
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/README.md +1 -1
- package/dist/app/commands/command-registry.js +2 -2
- package/dist/app/commands/command-session-actions.d.ts +0 -1
- package/dist/app/commands/command-session-actions.js +22 -13
- package/dist/app/icons.d.ts +14 -0
- package/dist/app/icons.js +33 -0
- package/dist/app/rendering/conversation-tool-renderer.js +2 -2
- package/dist/app/rendering/dcp-stats.d.ts +6 -1
- package/dist/app/rendering/dcp-stats.js +214 -46
- package/dist/app/rendering/editor-panels.js +8 -5
- package/dist/app/session/lazy-session-manager.js +12 -1
- package/dist/app/session/tabs-controller.d.ts +2 -5
- package/dist/app/session/tabs-controller.js +12 -21
- package/dist/app/subagents/subagents-model.d.ts +14 -1
- package/dist/app/subagents/subagents-model.js +34 -15
- package/dist/app/types.d.ts +2 -0
- package/dist/bundled-extensions/session-title/config.js +1 -1
- package/dist/markdown-format.js +27 -9
- package/dist/schemas/pi-tools-suite-schema.d.ts +29 -16
- package/dist/schemas/pi-tools-suite-schema.js +46 -31
- package/external/pi-tools-suite/README.md +392 -52
- package/external/pi-tools-suite/docs/browser-qa-subagent.md +31 -21
- package/external/pi-tools-suite/docs/context-gateway-p00-adr.md +216 -0
- package/external/pi-tools-suite/docs/context-gateway-p01n-gate-review.md +122 -0
- package/external/pi-tools-suite/docs/context-gateway-p01n-measurement.md +133 -0
- package/external/pi-tools-suite/docs/context-gateway-p01r-ra-evidence.md +111 -0
- package/external/pi-tools-suite/docs/context-gateway-p01r-rb-evidence.md +100 -0
- package/external/pi-tools-suite/docs/context-gateway-p01r-rc-evidence.md +69 -0
- package/external/pi-tools-suite/docs/context-gateway-p01r-rd-evidence.md +100 -0
- package/external/pi-tools-suite/docs/context-gateway-p01r-re-evidence.md +74 -0
- package/external/pi-tools-suite/docs/context-gateway-p01r-rf-evidence.md +153 -0
- package/external/pi-tools-suite/docs/context-gateway-p01r-rg-evidence.md +235 -0
- package/external/pi-tools-suite/docs/evals.md +684 -0
- package/external/pi-tools-suite/docs/subagent-model-pools.md +109 -0
- package/external/pi-tools-suite/package.json +10 -3
- package/external/pi-tools-suite/src/async-subagents/{private-skills → agents}/browser-qa/scripts/browser-qa-runner.mjs +82 -1
- package/external/pi-tools-suite/src/async-subagents/{private-skills/browser-qa/SKILL.md → agents/browser-qa.md} +261 -12
- package/external/pi-tools-suite/src/async-subagents/agents/implement.md +20 -0
- package/external/pi-tools-suite/src/async-subagents/agents/oracle.md +16 -0
- package/external/pi-tools-suite/src/async-subagents/agents/research.md +18 -0
- package/external/pi-tools-suite/src/async-subagents/agents/verify.md +18 -0
- package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +27 -243
- package/external/pi-tools-suite/src/async-subagents/commands.ts +6 -2
- package/external/pi-tools-suite/src/async-subagents/core/agent-catalog.ts +41 -0
- package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +13 -93
- package/external/pi-tools-suite/src/async-subagents/core/agents-dir.ts +494 -0
- package/external/pi-tools-suite/src/async-subagents/core/browser-qa.ts +9 -0
- package/external/pi-tools-suite/src/async-subagents/core/config.ts +200 -143
- package/external/pi-tools-suite/src/async-subagents/core/model-fallback.ts +1 -1
- package/external/pi-tools-suite/src/async-subagents/core/model-selection.ts +54 -0
- package/external/pi-tools-suite/src/async-subagents/core/prompt.ts +7 -6
- package/external/pi-tools-suite/src/async-subagents/core/routing.ts +52 -45
- package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +12 -4
- package/external/pi-tools-suite/src/async-subagents/index.ts +11 -1
- package/external/pi-tools-suite/src/async-subagents/lib.ts +6 -2
- package/external/pi-tools-suite/src/async-subagents/tools/spawn.ts +46 -18
- package/external/pi-tools-suite/src/async-subagents/tools/subagents.ts +3 -2
- package/external/pi-tools-suite/src/async-subagents/types.ts +2 -0
- package/external/pi-tools-suite/src/coding-discipline/index.ts +41 -142
- package/external/pi-tools-suite/src/config.ts +1 -22
- package/external/pi-tools-suite/src/context-gateway/accounting.ts +151 -0
- package/external/pi-tools-suite/src/context-gateway/config.ts +111 -0
- package/external/pi-tools-suite/src/context-gateway/index.ts +160 -0
- package/external/pi-tools-suite/src/context-gateway/metadata-normalization.ts +88 -0
- package/external/pi-tools-suite/src/context-gateway/storeless-capabilities.ts +89 -0
- package/external/pi-tools-suite/src/context-gateway/telemetry.ts +429 -0
- package/external/pi-tools-suite/src/context-gateway/test-output-parser.ts +326 -0
- package/external/pi-tools-suite/src/context-gateway/types.ts +152 -0
- package/external/pi-tools-suite/src/dcp/auto-compress-budget.ts +106 -0
- package/external/pi-tools-suite/src/dcp/auto-compress.ts +810 -106
- package/external/pi-tools-suite/src/dcp/commands.ts +64 -139
- package/external/pi-tools-suite/src/dcp/compress-tool.ts +369 -35
- package/external/pi-tools-suite/src/dcp/compression-blocks.ts +510 -64
- package/external/pi-tools-suite/src/dcp/compression-preview.ts +113 -0
- package/external/pi-tools-suite/src/dcp/compression-progress.ts +70 -0
- package/external/pi-tools-suite/src/dcp/config.ts +36 -61
- package/external/pi-tools-suite/src/dcp/conversation-index.ts +421 -0
- package/external/pi-tools-suite/src/dcp/debug-log.ts +7 -5
- package/external/pi-tools-suite/src/dcp/index.ts +617 -203
- package/external/pi-tools-suite/src/dcp/journal.ts +566 -0
- package/external/pi-tools-suite/src/dcp/progress-controller.ts +244 -0
- package/external/pi-tools-suite/src/dcp/prompts.ts +10 -7
- package/external/pi-tools-suite/src/dcp/provider-tool-results.ts +189 -0
- package/external/pi-tools-suite/src/dcp/pruner-candidates.ts +298 -78
- package/external/pi-tools-suite/src/dcp/pruner-compression-blocks.ts +173 -281
- package/external/pi-tools-suite/src/dcp/pruner-emergency.ts +2 -4
- package/external/pi-tools-suite/src/dcp/pruner-message-ids.ts +17 -5
- package/external/pi-tools-suite/src/dcp/pruner-metadata.ts +11 -1
- package/external/pi-tools-suite/src/dcp/pruner-nudge.ts +30 -82
- package/external/pi-tools-suite/src/dcp/pruner-tools.ts +22 -133
- package/external/pi-tools-suite/src/dcp/pruner.ts +18 -33
- package/external/pi-tools-suite/src/dcp/recovery.ts +129 -0
- package/external/pi-tools-suite/src/dcp/shadow-plan.ts +127 -0
- package/external/pi-tools-suite/src/dcp/state-transaction.ts +102 -0
- package/external/pi-tools-suite/src/dcp/state.ts +158 -580
- package/external/pi-tools-suite/src/dcp/ui.ts +1 -0
- package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +55 -220
- package/external/pi-tools-suite/src/index.ts +9 -0
- package/external/pi-tools-suite/src/model-tools/index.ts +76 -42
- package/external/pi-tools-suite/src/repo-discovery/index.ts +84 -18
- package/external/pi-tools-suite/src/repo-discovery/native-compact.ts +458 -0
- package/external/pi-tools-suite/src/session-recovery/index.ts +189 -43
- package/external/pi-tools-suite/src/tool-descriptions.ts +43 -38
- package/external/pi-tools-suite/src/truncation-metadata-normalizer/index.ts +17 -0
- package/package.json +6 -6
- package/schemas/pi-tools-suite.json +159 -78
- package/external/pi-tools-suite/src/async-subagents/private-skills/browser-qa/references/auth-scaffold-spec.md +0 -78
- package/external/pi-tools-suite/src/async-subagents/private-skills/browser-qa/references/qa-design.md +0 -223
- package/external/pi-tools-suite/src/dcp/state-persistence.ts +0 -195
- /package/external/pi-tools-suite/src/async-subagents/{private-skills/browser-qa/references → agents/browser-qa/examples}/qa-auth.example.jsonc +0 -0
- /package/external/pi-tools-suite/src/async-subagents/{private-skills/browser-qa/references → agents/browser-qa/examples}/qa-flow.example.jsonc +0 -0
- /package/external/pi-tools-suite/src/async-subagents/{private-skills → agents}/browser-qa/vendor/fflate.LICENSE +0 -0
- /package/external/pi-tools-suite/src/async-subagents/{private-skills → agents}/browser-qa/vendor/fflate.mjs +0 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
CONTEXT_GATEWAY_ENFORCE_UNAVAILABLE,
|
|
5
|
+
loadContextGatewayConfig,
|
|
6
|
+
} from "./config.js";
|
|
7
|
+
import { ContextGatewayTelemetry } from "./telemetry.js";
|
|
8
|
+
import type {
|
|
9
|
+
ContextGatewayEffectiveMode,
|
|
10
|
+
ContextGatewayMode,
|
|
11
|
+
ContextGatewayResolvedConfig,
|
|
12
|
+
ContextGatewayRuntimeState,
|
|
13
|
+
} from "./types.js";
|
|
14
|
+
|
|
15
|
+
export interface RegisterContextGatewayOptions {
|
|
16
|
+
loadConfig?: () => ContextGatewayResolvedConfig;
|
|
17
|
+
telemetry?: ContextGatewayTelemetry;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface RegisteredContextGateway extends ContextGatewayRuntimeState {
|
|
21
|
+
setRuntimeMode(mode: ContextGatewayMode): { ok: boolean; message: string };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function formatStatus(runtime: RegisteredContextGateway): string {
|
|
25
|
+
const telemetry = runtime.telemetry.snapshot();
|
|
26
|
+
return [
|
|
27
|
+
`Context Gateway requested=${runtime.requestedMode}, effective=${runtime.effectiveMode}.`,
|
|
28
|
+
`Observed results=${telemetry.results}, errors=${telemetry.errors}, upstreamTruncated=${telemetry.upstreamTruncatedResults}, overBudget=${telemetry.overBudgetResults}, unbound results=${telemetry.unboundResults}.`,
|
|
29
|
+
`Repeat candidates=${telemetry.repeatCandidateCount}, retrieval calls=${telemetry.retrievalCalls}.`,
|
|
30
|
+
`Native policy results=${telemetry.nativePolicy.results}, refusals=${telemetry.nativePolicy.refusals}, full overrides=${telemetry.nativePolicy.fullOverrides}.`,
|
|
31
|
+
`Observed contentBytes=${telemetry.contentBytes}, textBytes=${telemetry.textBytes}, detailsBytes=${telemetry.detailsBytes}, potentialBytesOverBudget=${telemetry.potentialBytesOverBudget}.`,
|
|
32
|
+
].join("\n");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function formatDoctor(runtime: RegisteredContextGateway): string {
|
|
36
|
+
const lines = [
|
|
37
|
+
`Context Gateway doctor: requested=${runtime.requestedMode}, effective=${runtime.effectiveMode}.`,
|
|
38
|
+
"Capture: read=limited; bash=limited+temp-output; repo_*=suite-adapter-not-wired; ast_grep=suite-adapter-not-wired.",
|
|
39
|
+
"External paths: MCP=current Pix adapter unsupported; direct parent browser capture=unsupported.",
|
|
40
|
+
"Storage: disabled; no durable archive, index, quota reservation, or retrieval tools are active.",
|
|
41
|
+
];
|
|
42
|
+
if (runtime.requestedMode === "enforce") {
|
|
43
|
+
lines.push("BLOCKED: enforce is unavailable in P01; effective mode is off.");
|
|
44
|
+
}
|
|
45
|
+
for (const issue of runtime.config.issues) lines.push(`Config issue: ${issue}`);
|
|
46
|
+
return lines.join("\n");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function notify(ctx: ExtensionContext, message: string, type: "info" | "warning" | "error" = "info"): void {
|
|
50
|
+
ctx.ui.notify(message, type);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function registerContextGateway(
|
|
54
|
+
pi: ExtensionAPI,
|
|
55
|
+
options: RegisterContextGatewayOptions = {},
|
|
56
|
+
): RegisteredContextGateway {
|
|
57
|
+
const config = (options.loadConfig ?? (() => loadContextGatewayConfig()))();
|
|
58
|
+
const telemetry = options.telemetry ?? new ContextGatewayTelemetry();
|
|
59
|
+
let requestedMode = config.mode;
|
|
60
|
+
let effectiveMode: ContextGatewayEffectiveMode = requestedMode === "enforce" ? "off" : requestedMode;
|
|
61
|
+
const inFlightToolCalls = new Set<string>();
|
|
62
|
+
|
|
63
|
+
const resetRuntimeTelemetry = (): void => {
|
|
64
|
+
inFlightToolCalls.clear();
|
|
65
|
+
telemetry.reset();
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const runtime: RegisteredContextGateway = {
|
|
69
|
+
get requestedMode() { return requestedMode; },
|
|
70
|
+
get effectiveMode() { return effectiveMode; },
|
|
71
|
+
config,
|
|
72
|
+
telemetry,
|
|
73
|
+
setRuntimeMode(mode) {
|
|
74
|
+
if (mode === "enforce") {
|
|
75
|
+
return { ok: false, message: CONTEXT_GATEWAY_ENFORCE_UNAVAILABLE };
|
|
76
|
+
}
|
|
77
|
+
if (mode !== effectiveMode && inFlightToolCalls.size > 0) {
|
|
78
|
+
return {
|
|
79
|
+
ok: false,
|
|
80
|
+
message: `Context Gateway mode change requires a safe boundary; ${inFlightToolCalls.size} tool call(s) are still in flight.`,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
requestedMode = mode;
|
|
84
|
+
effectiveMode = mode;
|
|
85
|
+
telemetry.clearTransientBindings();
|
|
86
|
+
return { ok: true, message: `Context Gateway runtime mode set to ${mode}; config was not changed.` };
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
pi.on("tool_call", async (event) => {
|
|
91
|
+
if (typeof event.toolCallId === "string") inFlightToolCalls.add(event.toolCallId);
|
|
92
|
+
if (effectiveMode === "observe") telemetry.recordToolCall(event);
|
|
93
|
+
return undefined;
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
pi.on("tool_result", async (event) => {
|
|
97
|
+
try {
|
|
98
|
+
if (effectiveMode === "observe") telemetry.recordToolResult(event, config.budgets.maxResultBytes);
|
|
99
|
+
} finally {
|
|
100
|
+
if (typeof event.toolCallId === "string") inFlightToolCalls.delete(event.toolCallId);
|
|
101
|
+
}
|
|
102
|
+
return undefined;
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
pi.on("session_start", async () => {
|
|
106
|
+
resetRuntimeTelemetry();
|
|
107
|
+
return undefined;
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
pi.on("session_tree", async () => {
|
|
111
|
+
resetRuntimeTelemetry();
|
|
112
|
+
return undefined;
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
pi.on("session_shutdown", async () => {
|
|
116
|
+
resetRuntimeTelemetry();
|
|
117
|
+
return undefined;
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
pi.registerCommand("context-gateway", {
|
|
121
|
+
description: "Show Context Gateway status/doctor output or change the runtime-only off/observe mode.",
|
|
122
|
+
handler: async (rawArgs, ctx) => {
|
|
123
|
+
const args = rawArgs.trim().split(/\s+/).filter(Boolean);
|
|
124
|
+
const action = (args[0] ?? "status").toLowerCase();
|
|
125
|
+
if (action === "status") {
|
|
126
|
+
notify(ctx, formatStatus(runtime));
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (action === "doctor") {
|
|
130
|
+
notify(ctx, formatDoctor(runtime), runtime.requestedMode === "enforce" ? "warning" : "info");
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (action === "mode") {
|
|
134
|
+
const mode = args[1]?.toLowerCase() as ContextGatewayMode | undefined;
|
|
135
|
+
if (mode !== "off" && mode !== "observe" && mode !== "enforce") {
|
|
136
|
+
notify(ctx, "Usage: /context-gateway mode off|observe|enforce", "error");
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const result = runtime.setRuntimeMode(mode);
|
|
140
|
+
notify(ctx, result.message, result.ok ? "info" : "error");
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
notify(ctx, "Usage: /context-gateway status|doctor|mode off|observe|enforce", "error");
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
return runtime;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export default function contextGatewayExtension(pi: ExtensionAPI): void {
|
|
151
|
+
registerContextGateway(pi);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export { accountContextGatewayParts } from "./accounting.js";
|
|
155
|
+
export { loadContextGatewayConfig } from "./config.js";
|
|
156
|
+
export { normalizeRedundantTruncationMetadata } from "./metadata-normalization.js";
|
|
157
|
+
export { STORELESS_CAPABILITIES, storelessCapability } from "./storeless-capabilities.js";
|
|
158
|
+
export { parseTestBuildOutput, planProspectiveTestOutputDelivery } from "./test-output-parser.js";
|
|
159
|
+
export { ContextGatewayTelemetry, classifyContextGatewayTool, classifyRoleParts, observeToolResult } from "./telemetry.js";
|
|
160
|
+
export type * from "./types.js";
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export interface TruncationMetadataNormalization {
|
|
2
|
+
details: unknown;
|
|
3
|
+
changed: boolean;
|
|
4
|
+
removedBytes: number;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type ToolResultLike = {
|
|
8
|
+
toolName?: unknown;
|
|
9
|
+
content?: unknown;
|
|
10
|
+
details?: unknown;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const KNOWN_TRUNCATION_TOOLS = new Set([
|
|
14
|
+
"read",
|
|
15
|
+
"bash",
|
|
16
|
+
"shell",
|
|
17
|
+
"shell_command",
|
|
18
|
+
"ast_grep",
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
// This allowlist is an applicability/compatibility guard, not a provenance or
|
|
22
|
+
// authorization boundary. `tool_result` exposes a tool name but not a trusted
|
|
23
|
+
// owner identity, so a replacement extension can reuse one of these names. The
|
|
24
|
+
// transform is therefore deliberately limited to removing an exact duplicate
|
|
25
|
+
// of delivered text and preserves every other details field; callers must not
|
|
26
|
+
// infer built-in-tool capabilities, trust, lifetime, or access rights from the
|
|
27
|
+
// name/shape match alone.
|
|
28
|
+
|
|
29
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
30
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function deliveredText(content: unknown): string | undefined {
|
|
34
|
+
if (!Array.isArray(content)) return undefined;
|
|
35
|
+
const parts: string[] = [];
|
|
36
|
+
for (const raw of content) {
|
|
37
|
+
if (!isRecord(raw)) continue;
|
|
38
|
+
if (raw.type === "text" && typeof raw.text === "string") parts.push(raw.text);
|
|
39
|
+
}
|
|
40
|
+
return parts.length > 0 ? parts.join("") : undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type SdkTruncationShape = Record<string, unknown> & {
|
|
44
|
+
content: string;
|
|
45
|
+
truncated: true;
|
|
46
|
+
truncatedBy: "lines" | "bytes";
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
function hasSdkTruncationShape(value: Record<string, unknown>): value is SdkTruncationShape {
|
|
50
|
+
if (value.truncated !== true || typeof value.content !== "string" || value.content.length === 0) return false;
|
|
51
|
+
if (value.truncatedBy !== "lines" && value.truncatedBy !== "bytes") return false;
|
|
52
|
+
for (const key of ["totalLines", "totalBytes", "outputLines", "outputBytes", "maxLines", "maxBytes"] as const) {
|
|
53
|
+
const item = value[key];
|
|
54
|
+
if (typeof item !== "number" || !Number.isFinite(item) || item < 0) return false;
|
|
55
|
+
}
|
|
56
|
+
if (typeof value.lastLinePartial !== "boolean" || typeof value.firstLineExceedsLimit !== "boolean") return false;
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Remove only the known redundant truncation payload copied into tool-result
|
|
62
|
+
* metadata when that payload is also the prefix of the delivered text.
|
|
63
|
+
*
|
|
64
|
+
* This intentionally does not normalize arbitrary `details.truncation.content`
|
|
65
|
+
* fields: custom tools may use a similarly named field for unrelated data.
|
|
66
|
+
*/
|
|
67
|
+
export function normalizeRedundantTruncationMetadata(event: ToolResultLike): TruncationMetadataNormalization {
|
|
68
|
+
const toolName = typeof event.toolName === "string" ? event.toolName.trim().toLowerCase() : "";
|
|
69
|
+
if (!KNOWN_TRUNCATION_TOOLS.has(toolName)) return { details: event.details, changed: false, removedBytes: 0 };
|
|
70
|
+
if (!isRecord(event.details)) return { details: event.details, changed: false, removedBytes: 0 };
|
|
71
|
+
const truncation = event.details.truncation;
|
|
72
|
+
if (!isRecord(truncation) || !hasSdkTruncationShape(truncation)) {
|
|
73
|
+
return { details: event.details, changed: false, removedBytes: 0 };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const text = deliveredText(event.content);
|
|
77
|
+
if (text === undefined || !text.startsWith(truncation.content)) {
|
|
78
|
+
return { details: event.details, changed: false, removedBytes: 0 };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const normalizedTruncation: Record<string, unknown> = { ...truncation };
|
|
82
|
+
delete normalizedTruncation.content;
|
|
83
|
+
return {
|
|
84
|
+
details: { ...event.details, truncation: normalizedTruncation },
|
|
85
|
+
changed: true,
|
|
86
|
+
removedBytes: new TextEncoder().encode(truncation.content).byteLength,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export type StorelessCapabilityStatus = "supported" | "limited" | "unsupported";
|
|
2
|
+
export type StorelessCapabilityStrategy = "native-passthrough" | "metadata-only" | "pure-parser-candidate" | "none";
|
|
3
|
+
|
|
4
|
+
export interface StorelessCapabilityEntry {
|
|
5
|
+
surface:
|
|
6
|
+
| "test-build"
|
|
7
|
+
| "mutation-lsp"
|
|
8
|
+
| "web-document"
|
|
9
|
+
| "structured-json"
|
|
10
|
+
| "subagent-result"
|
|
11
|
+
| "visual"
|
|
12
|
+
| "browser-direct"
|
|
13
|
+
| "mcp-direct";
|
|
14
|
+
status: StorelessCapabilityStatus;
|
|
15
|
+
strategy: StorelessCapabilityStrategy;
|
|
16
|
+
lifetime: "current-result" | "producer-managed" | "visual-message" | "none";
|
|
17
|
+
reason: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Storeless capability claims proven or deliberately limited by P01-R.
|
|
22
|
+
*
|
|
23
|
+
* This table is documentation/doctor-ready metadata only. It does not register
|
|
24
|
+
* adapters, readers, grants, fetchers, parsers, or filesystem capabilities.
|
|
25
|
+
*/
|
|
26
|
+
export const STORELESS_CAPABILITIES: readonly StorelessCapabilityEntry[] = Object.freeze([
|
|
27
|
+
{
|
|
28
|
+
surface: "test-build",
|
|
29
|
+
status: "limited",
|
|
30
|
+
strategy: "pure-parser-candidate",
|
|
31
|
+
lifetime: "current-result",
|
|
32
|
+
reason: "Bun/TAP/bounded TypeScript parsing is observe-only; production delivery remains passthrough without a recovery/lifetime contract.",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
surface: "mutation-lsp",
|
|
36
|
+
status: "supported",
|
|
37
|
+
strategy: "native-passthrough",
|
|
38
|
+
lifetime: "current-result",
|
|
39
|
+
reason: "Execution outcome, actual changedFiles and appended diagnostics stay in the native tool result; Context Gateway adds no diff or mutation retry.",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
surface: "web-document",
|
|
43
|
+
status: "limited",
|
|
44
|
+
strategy: "native-passthrough",
|
|
45
|
+
lifetime: "current-result",
|
|
46
|
+
reason: "Existing web tools own fetch, URL/provider metadata and truncation. Storeless Gateway does not refetch, archive, or claim stable pagination of omitted content.",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
surface: "structured-json",
|
|
50
|
+
status: "limited",
|
|
51
|
+
strategy: "native-passthrough",
|
|
52
|
+
lifetime: "current-result",
|
|
53
|
+
reason: "No generic JSON field-selection adapter is enabled. JSON text/numbers pass through exactly as delivered by the producer.",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
surface: "subagent-result",
|
|
57
|
+
status: "limited",
|
|
58
|
+
strategy: "native-passthrough",
|
|
59
|
+
lifetime: "producer-managed",
|
|
60
|
+
reason: "The producer already returns a compact result and artifact paths. P01-R neither reads internal history nor grants/extends artifact lifetime by path.",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
surface: "visual",
|
|
64
|
+
status: "supported",
|
|
65
|
+
strategy: "native-passthrough",
|
|
66
|
+
lifetime: "visual-message",
|
|
67
|
+
reason: "Image parts remain image parts; storeless text accounting/cleanup does not replace them with textual summaries.",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
surface: "browser-direct",
|
|
71
|
+
status: "unsupported",
|
|
72
|
+
strategy: "none",
|
|
73
|
+
lifetime: "none",
|
|
74
|
+
reason: "Current browser QA executes in a child Pi process without the parent extension result boundary; no direct DOM/network/console Gateway adapter is claimed.",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
surface: "mcp-direct",
|
|
78
|
+
status: "unsupported",
|
|
79
|
+
strategy: "none",
|
|
80
|
+
lifetime: "none",
|
|
81
|
+
reason: "No supported direct MCP execution/result boundary was proven in P00 for the current Pix adapter.",
|
|
82
|
+
},
|
|
83
|
+
]);
|
|
84
|
+
|
|
85
|
+
export function storelessCapability(surface: StorelessCapabilityEntry["surface"]): StorelessCapabilityEntry {
|
|
86
|
+
const entry = STORELESS_CAPABILITIES.find((candidate) => candidate.surface === surface);
|
|
87
|
+
if (!entry) throw new Error(`Unknown storeless capability surface: ${surface}`);
|
|
88
|
+
return entry;
|
|
89
|
+
}
|