mirror of
https://github.com/aiclientproxy/proxycast.git
synced 2026-10-16 15:34:08 +08:00
9377 lines
363 KiB
JavaScript
9377 lines
363 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import process from "node:process";
|
|
import {
|
|
checkMcpRuntimeCurrentContracts,
|
|
checkWorkspaceRightSurfaceCurrentContracts,
|
|
} from "./mcp/lib/contract-guards.mjs";
|
|
|
|
const repoRoot = process.cwd();
|
|
function normalizeContractSnippet(value) {
|
|
return value
|
|
.replace(/\b(?:protocol|appServer|constants)\./gu, "")
|
|
.replace(/(\w+)\s*:\s*([A-Za-z0-9_<>,\[\]\s|&]+)\s*=\s*\{\}/gu, "$1?: $2")
|
|
.replace(/\basync\s+(?=[A-Za-z_$][\w$]*\()/gu, "")
|
|
.replace(/\.await\b/gu, "")
|
|
.replace(/\.boxed\(\)/gu, "")
|
|
.replace(/\bready\(/gu, "")
|
|
.replace(/,\s*\)/gu, ")")
|
|
.replace(/\s+/gu, "");
|
|
}
|
|
|
|
function contractContentIncludes(content, snippet) {
|
|
if (content.includes(snippet)) {
|
|
return true;
|
|
}
|
|
const normalizedContent = normalizeContractSnippet(content);
|
|
const normalizedSnippet = normalizeContractSnippet(snippet);
|
|
if (normalizedContent.includes(normalizedSnippet)) {
|
|
return true;
|
|
}
|
|
|
|
const importedTypeSnippet = snippet.match(/^type\s+([A-Za-z0-9_]+),$/u);
|
|
if (importedTypeSnippet) {
|
|
return normalizedContent.includes(
|
|
normalizeContractSnippet(`protocol.${importedTypeSnippet[1]}`),
|
|
);
|
|
}
|
|
|
|
const dynamicClientCall = snippet.match(
|
|
/^this\.client\.([A-Za-z0-9_]+)\(params\)$/u,
|
|
);
|
|
if (dynamicClientCall) {
|
|
const clientMethodName = dynamicClientCall[1];
|
|
return (
|
|
(content.includes(`clientMethod: "${clientMethodName}"`) ||
|
|
content.includes(`name: "${clientMethodName}"`)) &&
|
|
content.includes("APP_SERVER_REQUEST_CLIENT_METHODS") &&
|
|
content.includes("client[spec.clientMethod](...clientArgs)")
|
|
);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
const appServerClientIndexFile = "packages/app-server-client/src/index.ts";
|
|
const appServerGeneratedProtocolFile =
|
|
"packages/app-server-client/src/generated/protocol-types.ts";
|
|
const appServerClientSplitSourceFiles = [
|
|
appServerClientIndexFile,
|
|
"packages/app-server-client/src/request-client.ts",
|
|
"packages/app-server-client/src/request-client-methods.ts",
|
|
"packages/app-server-client/src/connection.ts",
|
|
"packages/app-server-client/src/connection-methods.ts",
|
|
"packages/app-server-client/src/sidecar.ts",
|
|
"packages/app-server-client/src/sidecar-types.ts",
|
|
"packages/app-server-client/src/sidecar-manifest.ts",
|
|
"packages/app-server-client/src/sidecar-process.ts",
|
|
"packages/app-server-client/src/sidecar-lifecycle.ts",
|
|
"packages/app-server-client/src/agent-runtime.ts",
|
|
];
|
|
const rendererAppServerIndexFile = "src/lib/api/appServer.ts";
|
|
const rendererAppServerSplitSourceFiles = [
|
|
rendererAppServerIndexFile,
|
|
"src/lib/api/appServerConstants.ts",
|
|
"src/lib/api/appServerTypes.ts",
|
|
"src/lib/api/appServerTransport.ts",
|
|
"src/lib/api/appServerResponse.ts",
|
|
"src/lib/api/appServerClient.ts",
|
|
"src/lib/api/appServerClientMethods.ts",
|
|
"src/lib/api/appServerClientMethodSpecs.ts",
|
|
];
|
|
const rendererQueuedTurnWriteSurfaceRoots = [
|
|
"src/components/agent/chat",
|
|
"src/lib/api/agentRuntime",
|
|
];
|
|
const rendererQueuedTurnWriteSurfaceForbiddenSnippets = [
|
|
'"agentSession/queuedTurn/promote"',
|
|
'"agentSession/queuedTurn/remove"',
|
|
"promoteAgentRuntimeQueuedTurn",
|
|
"removeAgentRuntimeQueuedTurn",
|
|
"promoteAgentSessionQueuedTurn",
|
|
"removeAgentSessionQueuedTurn",
|
|
"onPromoteQueuedTurn",
|
|
"onRemoveQueuedTurn",
|
|
"QueuedTurnSnapshot",
|
|
"normalizeQueuedTurnSnapshots",
|
|
"queued_turns",
|
|
];
|
|
const retiredAgentStreamToolMessageSynthesisFiles = [
|
|
"src/components/agent/chat/hooks/agentStreamToolItemMessageSync.ts",
|
|
"src/components/agent/chat/hooks/agentStreamToolItemMessageSync.unit.test.ts",
|
|
];
|
|
const retiredAgentStreamToolMessageSynthesisSnippets = [
|
|
"syncMessageToolCallFromThreadItem",
|
|
"toolCallStateFromThreadItem",
|
|
"mergeToolCallStateFromItem",
|
|
"agentStreamToolItemMessageSync",
|
|
];
|
|
const retiredPublicQueuedTurnSurfaceSpecs = [
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v0/agent_session.rs",
|
|
snippets: [
|
|
"AgentSessionQueuedTurnRemoveParams",
|
|
"AgentSessionQueuedTurnRemoveResponse",
|
|
"AgentSessionQueuedTurnPromoteParams",
|
|
"AgentSessionQueuedTurnPromoteResponse",
|
|
],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v0/method_names.rs",
|
|
snippets: [
|
|
"AGENT_SESSION_QUEUED_TURN_REMOVE",
|
|
"AGENT_SESSION_QUEUED_TURN_PROMOTE",
|
|
'"agentSession/queuedTurn/remove"',
|
|
'"agentSession/queuedTurn/promote"',
|
|
],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v0/client_request.rs",
|
|
snippets: ["AgentSessionQueuedTurnRemove", "AgentSessionQueuedTurnPromote"],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v0/catalog.rs",
|
|
snippets: [
|
|
"AgentSessionQueuedTurnRemove",
|
|
"AgentSessionQueuedTurnPromote",
|
|
'"agentSession/queuedTurn/remove"',
|
|
'"agentSession/queuedTurn/promote"',
|
|
],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v0/schema_types.rs",
|
|
snippets: [
|
|
"AgentSessionQueuedTurnRemoveParams",
|
|
"AgentSessionQueuedTurnPromoteParams",
|
|
],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server/src/processor/agent_session.rs",
|
|
snippets: [
|
|
"handle_agent_session_queued_turn_remove",
|
|
"handle_agent_session_queued_turn_promote",
|
|
],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server/src/runtime/session_control.rs",
|
|
snippets: [
|
|
"remove_agent_session_queued_turn",
|
|
"promote_agent_session_queued_turn",
|
|
"promote_queued_turn_in_session",
|
|
],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v2/turn.rs",
|
|
snippets: ["queue_if_busy", "TurnQueuePromote"],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v2/common.rs",
|
|
snippets: ["TurnQueueState", "pub queue:"],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v2/methods.rs",
|
|
snippets: ['"turn/queue/promote"', "METHOD_TURN_QUEUE_PROMOTE"],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v2/envelopes.rs",
|
|
snippets: ["TurnQueuePromote"],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server/src/processor/dispatch.rs",
|
|
snippets: ["METHOD_TURN_QUEUE_PROMOTE"],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server/src/processor/dispatch/v2_ingress.rs",
|
|
snippets: ["TurnQueuePromote"],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server/src/processor/turn.rs",
|
|
snippets: ["handle_turn_queue_promote_v2_impl", "params.queue_if_busy"],
|
|
},
|
|
{
|
|
file: "packages/app-server-client/src/generated/protocol-types.ts",
|
|
snippets: [
|
|
'"turn/queue/promote"',
|
|
"TurnQueuePromote",
|
|
'"agentSession/queuedTurn/remove"',
|
|
'"agentSession/queuedTurn/promote"',
|
|
"AgentSessionQueuedTurnRemove",
|
|
"AgentSessionQueuedTurnPromote",
|
|
],
|
|
},
|
|
{
|
|
file: "packages/app-server-client/src/request-client.ts",
|
|
snippets: [
|
|
"promoteQueuedTurn",
|
|
"TurnQueuePromote",
|
|
"promoteAgentSessionQueuedTurn",
|
|
"removeAgentSessionQueuedTurn",
|
|
],
|
|
},
|
|
{
|
|
file: "packages/app-server-client/src/request-client-methods.ts",
|
|
snippets: [
|
|
"promoteQueuedTurn",
|
|
"METHOD_TURN_QUEUE_PROMOTE",
|
|
"promoteAgentSessionQueuedTurn",
|
|
"removeAgentSessionQueuedTurn",
|
|
],
|
|
},
|
|
{
|
|
file: "packages/app-server-client/src/connection-methods.ts",
|
|
snippets: [
|
|
"promoteQueuedTurn",
|
|
"TurnQueuePromote",
|
|
"promoteAgentSessionQueuedTurn",
|
|
"removeAgentSessionQueuedTurn",
|
|
],
|
|
},
|
|
{
|
|
file: "src/lib/api/appServerConstants.ts",
|
|
snippets: [
|
|
"APP_SERVER_METHOD_TURN_QUEUE_PROMOTE",
|
|
"APP_SERVER_METHOD_AGENT_SESSION_QUEUED_TURN_REMOVE",
|
|
"APP_SERVER_METHOD_AGENT_SESSION_QUEUED_TURN_PROMOTE",
|
|
],
|
|
},
|
|
{
|
|
file: "src/lib/api/appServerTypes.ts",
|
|
snippets: [
|
|
"AppServerTurnQueuePromote",
|
|
"AppServerAgentSessionQueuedTurnRemove",
|
|
"AppServerAgentSessionQueuedTurnPromote",
|
|
],
|
|
},
|
|
{
|
|
file: "src/lib/api/appServerClientMethods.ts",
|
|
snippets: [
|
|
"promoteQueuedTurn",
|
|
"promoteAgentSessionQueuedTurn",
|
|
"removeAgentSessionQueuedTurn",
|
|
],
|
|
},
|
|
{
|
|
file: "src/lib/api/appServerClientMethodSpecs.ts",
|
|
snippets: [
|
|
"promoteQueuedTurn",
|
|
"APP_SERVER_METHOD_TURN_QUEUE_PROMOTE",
|
|
"promoteAgentSessionQueuedTurn",
|
|
"removeAgentSessionQueuedTurn",
|
|
],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/schema/json/app_server_protocol.schemas.json",
|
|
snippets: ['"turn/queue/promote"', "TurnQueuePromote"],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/schema/json/manifest.json",
|
|
snippets: ['"turn/queue/promote"', "TurnQueuePromote"],
|
|
},
|
|
];
|
|
const retiredPublicQueuedTurnSchemaFiles = [
|
|
"lime-rs/crates/app-server-protocol/schema/json/v0/AgentSessionQueuedTurnRemoveParams.json",
|
|
"lime-rs/crates/app-server-protocol/schema/json/v0/AgentSessionQueuedTurnRemoveResponse.json",
|
|
"lime-rs/crates/app-server-protocol/schema/json/v0/AgentSessionQueuedTurnPromoteParams.json",
|
|
"lime-rs/crates/app-server-protocol/schema/json/v0/AgentSessionQueuedTurnPromoteResponse.json",
|
|
"lime-rs/crates/app-server-protocol/schema/json/v2/TurnQueuePromoteParams.json",
|
|
"lime-rs/crates/app-server-protocol/schema/json/v2/TurnQueuePromoteResponse.json",
|
|
];
|
|
const retiredRendererQueuedTurnFiles = [
|
|
"src/lib/api/queuedTurn.ts",
|
|
"src/lib/api/queuedTurn.test.ts",
|
|
"src/lib/api/queuedTurn.d.ts",
|
|
];
|
|
const retiredPendingSteerFixtureFiles = [
|
|
"scripts/agent-runtime/claw-chat-current-fixture-inputbar-pending-steer.mjs",
|
|
"scripts/agent-runtime/claw-chat-current-fixture-pending-steer-gui-actions.mjs",
|
|
"scripts/agent-runtime/claw-chat-current-fixture-pending-steer-read-model.mjs",
|
|
"scripts/agent-runtime/claw-chat-current-fixture-pending-steer-assertions.mjs",
|
|
];
|
|
const retiredPendingSteerScenarios = [
|
|
"inputbar-pending-steer-rich-restore",
|
|
"inputbar-pending-steer-multi-queue",
|
|
"inputbar-pending-steer-pop-front-resume",
|
|
];
|
|
const retiredExecutionProcessFiles = [
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/execution_process.rs",
|
|
"src/lib/api/executionProcess.ts",
|
|
"src/lib/api/executionProcess.test.ts",
|
|
...[
|
|
"DrainOutputParams",
|
|
"DrainOutputResponse",
|
|
"EmptyResponse",
|
|
"IdParams",
|
|
"OutputDelta",
|
|
"OutputKind",
|
|
"Snapshot",
|
|
"StartParams",
|
|
"StartResponse",
|
|
"Status",
|
|
"StatusResponse",
|
|
"WriteStdinParams",
|
|
].map(
|
|
(name) =>
|
|
`lime-rs/crates/app-server-protocol/schema/json/v0/ExecutionProcess${name}.json`,
|
|
),
|
|
];
|
|
const retiredFileSystemFiles = [
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/file_system.rs",
|
|
"lime-rs/crates/app-server/src/processor/file.rs",
|
|
"lime-rs/crates/app-server/src/processor/tests/file.rs",
|
|
"lime-rs/crates/app-server/src/runtime/file_system.rs",
|
|
"lime-rs/crates/app-server/src/services/file_browser_service.rs",
|
|
"lime-rs/crates/services/src/file_browser_service.rs",
|
|
...[
|
|
"CreateDirectoryParams",
|
|
"CreateFileParams",
|
|
"DeleteFileParams",
|
|
"DirectoryListing",
|
|
"FileEntry",
|
|
"FilePreview",
|
|
"ListDirectoryParams",
|
|
"MutationResponse",
|
|
"ReadFilePreviewParams",
|
|
"RenameFileParams",
|
|
].map(
|
|
(name) =>
|
|
`lime-rs/crates/app-server-protocol/schema/json/v0/FileSystem${name}.json`,
|
|
),
|
|
];
|
|
const retiredFileSystemSurfaceSpecs = [
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v0.rs",
|
|
snippets: ["mod file_system;", "pub use file_system::*;"],
|
|
},
|
|
{
|
|
files: [
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/method_names.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/client_request.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/catalog.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/schema_types.rs",
|
|
"lime-rs/crates/app-server-protocol/src/schema_export/registry.rs",
|
|
],
|
|
snippets: [
|
|
"METHOD_FILE_SYSTEM_",
|
|
'"fileSystem/',
|
|
"FileSystemListDirectoryParams",
|
|
"FileSystemReadFilePreviewParams",
|
|
"FileSystemMutationResponse",
|
|
],
|
|
},
|
|
{
|
|
files: [
|
|
"lime-rs/crates/app-server-client/src/lib.rs",
|
|
"packages/app-server-client/src/protocol.ts",
|
|
"packages/app-server-client/src/request-client.ts",
|
|
"packages/app-server-client/src/request-client-methods.ts",
|
|
"packages/app-server-client/src/connection-methods.ts",
|
|
"packages/app-server-client/src/generated/protocol-types.ts",
|
|
...rendererAppServerSplitSourceFiles,
|
|
],
|
|
snippets: [
|
|
"METHOD_FILE_SYSTEM_",
|
|
'"fileSystem/',
|
|
"FileSystemListDirectoryParams",
|
|
"FileSystemReadFilePreviewParams",
|
|
"FileSystemMutationResponse",
|
|
"readFilePreview",
|
|
"renameFile",
|
|
"deleteFile",
|
|
],
|
|
},
|
|
{
|
|
files: [
|
|
"lime-rs/crates/app-server-protocol/schema/json/app_server_protocol.schemas.json",
|
|
"lime-rs/crates/app-server-protocol/schema/json/manifest.json",
|
|
],
|
|
snippets: [
|
|
'"fileSystem/',
|
|
"FileSystemListDirectoryParams",
|
|
"FileSystemReadFilePreviewParams",
|
|
"FileSystemMutationResponse",
|
|
],
|
|
},
|
|
];
|
|
const retiredExecutionProcessSurfaceSpecs = [
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v0.rs",
|
|
snippets: ["mod execution_process;", "pub use execution_process::*;"],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v0/method_names.rs",
|
|
snippets: ["METHOD_EXECUTION_PROCESS_", '"executionProcess/'],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v0/client_request.rs",
|
|
snippets: ["ExecutionProcessStart", "ExecutionProcessDrainOutput"],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v0/catalog.rs",
|
|
snippets: ["ExecutionProcessStart", '"executionProcess/'],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/protocol/v0/schema_types.rs",
|
|
snippets: [
|
|
"ExecutionProcessStartParams",
|
|
"ExecutionProcessDrainOutputResponse",
|
|
],
|
|
},
|
|
{
|
|
file: "lime-rs/crates/app-server-protocol/src/schema_export/registry.rs",
|
|
snippets: [
|
|
"ExecutionProcessStartParams",
|
|
"ExecutionProcessDrainOutputResponse",
|
|
],
|
|
},
|
|
{
|
|
file: "packages/app-server-client/src/generated/protocol-types.ts",
|
|
snippets: [
|
|
"METHOD_EXECUTION_PROCESS_",
|
|
'"executionProcess/',
|
|
"ExecutionProcessStartParams",
|
|
"ExecutionProcessDrainOutputResponse",
|
|
],
|
|
},
|
|
{
|
|
files: [
|
|
"packages/app-server-client/src/protocol.ts",
|
|
"packages/app-server-client/src/request-client.ts",
|
|
"packages/app-server-client/src/request-client-methods.ts",
|
|
"packages/app-server-client/src/connection-methods.ts",
|
|
],
|
|
snippets: [
|
|
"startExecutionProcess",
|
|
"writeExecutionProcessStdin",
|
|
"interruptExecutionProcess",
|
|
"terminateExecutionProcess",
|
|
"readExecutionProcessStatus",
|
|
"drainExecutionProcessOutput",
|
|
],
|
|
},
|
|
{
|
|
files: rendererAppServerSplitSourceFiles,
|
|
snippets: ["APP_SERVER_METHOD_EXECUTION_PROCESS_", '"executionProcess/'],
|
|
},
|
|
{
|
|
files: [
|
|
"lime-rs/crates/app-server-protocol/schema/json/app_server_protocol.schemas.json",
|
|
"lime-rs/crates/app-server-protocol/schema/json/manifest.json",
|
|
],
|
|
snippets: [
|
|
'"executionProcess/',
|
|
"ExecutionProcessStartParams",
|
|
"ExecutionProcessDrainOutputResponse",
|
|
],
|
|
},
|
|
];
|
|
|
|
function expandContractFiles(files) {
|
|
return [
|
|
...new Set(
|
|
files.flatMap((file) => {
|
|
if (file === appServerClientIndexFile) {
|
|
return appServerClientSplitSourceFiles;
|
|
}
|
|
if (file === rendererAppServerIndexFile) {
|
|
return rendererAppServerSplitSourceFiles;
|
|
}
|
|
return [file];
|
|
}),
|
|
),
|
|
];
|
|
}
|
|
|
|
function requiredContractContent(files, content) {
|
|
if (!files.includes("packages/app-server-client/src/protocol.ts")) {
|
|
return content;
|
|
}
|
|
const generatedPath = path.join(repoRoot, appServerGeneratedProtocolFile);
|
|
if (!fs.existsSync(generatedPath)) {
|
|
return content;
|
|
}
|
|
return `${content}\n${fs.readFileSync(generatedPath, "utf8")}`;
|
|
}
|
|
|
|
function collectRustFiles(relativeDir) {
|
|
const absoluteDir = path.join(repoRoot, relativeDir);
|
|
return fs
|
|
.readdirSync(absoluteDir, { withFileTypes: true })
|
|
.flatMap((entry) => {
|
|
const relativePath = `${relativeDir}/${entry.name}`;
|
|
if (entry.isDirectory()) {
|
|
return collectRustFiles(relativePath);
|
|
}
|
|
return entry.isFile() && entry.name.endsWith(".rs") ? [relativePath] : [];
|
|
})
|
|
.sort();
|
|
}
|
|
|
|
const protocolV0ModuleFiles = collectRustFiles(
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0",
|
|
);
|
|
const protocolV2ModuleFiles = collectRustFiles(
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v2",
|
|
);
|
|
const schemaExportModuleFiles = collectRustFiles(
|
|
"lime-rs/crates/app-server-protocol/src/schema_export",
|
|
);
|
|
const appServerRuntimeFiles = [
|
|
"lime-rs/crates/app-server/src/runtime.rs",
|
|
...collectRustFiles("lime-rs/crates/app-server/src/runtime"),
|
|
];
|
|
const appServerRuntimeThreadReadProjectionFiles = [
|
|
"lime-rs/crates/app-server/src/runtime/load_context.rs",
|
|
"lime-rs/crates/app-server/src/runtime/session_lifecycle.rs",
|
|
"lime-rs/crates/app-server/src/runtime/read_model.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tool_item_projection.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tool_item_projection/extract.rs",
|
|
"lime-rs/crates/app-server/src/runtime/artifact_projection.rs",
|
|
"lime-rs/crates/app-server/src/runtime/output_refs.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tests/read_model/tool_calls.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tests/read_model/imports_items.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tests/read_model/artifacts.rs",
|
|
];
|
|
const appServerRuntimeBackendFiles = [
|
|
"lime-rs/crates/app-server/src/runtime_backend.rs",
|
|
...collectRustFiles("lime-rs/crates/app-server/src/runtime_backend"),
|
|
];
|
|
const appServerRuntimeBackendExecutionChainFiles = [
|
|
"lime-rs/crates/app-server/src/runtime_backend.rs",
|
|
"lime-rs/crates/app-server/src/runtime/turn_execution.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/action_response.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/event_mapper.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/execution_backend.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/provider_config.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/request_context.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/request_context/session_config.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/request_context/turn_context.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/request_context/workspace_scope.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/tool_events.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/tool_process_runtime_metadata.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/initialization_tests.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/tests.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/tests/coding_event_projection.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/tests/model_selection.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/tests/tool_policy_context.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/tests/tool_surface.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/tests/turn_flows.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/tests/workspace_scope_context.rs",
|
|
];
|
|
const appServerProcessorFiles = [
|
|
"lime-rs/crates/app-server/src/processor/mod.rs",
|
|
...collectRustFiles("lime-rs/crates/app-server/src/processor"),
|
|
];
|
|
const agentRuntimeBoundaryFiles = [
|
|
"lime-rs/crates/agent/src/lib.rs",
|
|
"lime-rs/crates/agent/src/runtime_state.rs",
|
|
"lime-rs/crates/agent/src/runtime_state_support.rs",
|
|
"lime-rs/crates/agent/src/provider_configuration.rs",
|
|
"lime-rs/crates/agent/src/session_configuration.rs",
|
|
"lime-rs/crates/agent/src/turn_context_configuration.rs",
|
|
"lime-rs/crates/agent/src/current_provider_turn.rs",
|
|
"lime-rs/crates/agent/src/current_provider_turn/tool_executor.rs",
|
|
"lime-rs/crates/agent/src/direct_text_generation.rs",
|
|
"lime-rs/crates/agent/src/turn_execution.rs",
|
|
];
|
|
const agentRequestToolPolicyFiles = [
|
|
"lime-rs/crates/agent/src/request_tool_policy.rs",
|
|
...collectRustFiles("lime-rs/crates/agent/src/request_tool_policy"),
|
|
];
|
|
const rustProtocolFiles = [
|
|
"lime-rs/crates/app-server-protocol/src/lib.rs",
|
|
"lime-rs/crates/app-server-protocol/src/jsonrpc_lite.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0.rs",
|
|
...protocolV0ModuleFiles,
|
|
...protocolV2ModuleFiles,
|
|
"lime-rs/crates/app-server-protocol/src/schema_export.rs",
|
|
...schemaExportModuleFiles,
|
|
"lime-rs/crates/app-server-protocol/src/schema_fixtures.rs",
|
|
];
|
|
const retiredTreeProjectionNames = [
|
|
["View", "Tree"].join(""),
|
|
["View", "tree"].join(""),
|
|
["view", "tree"].join(""),
|
|
["Process", "Tree"].join(""),
|
|
["Process", "tree"].join(""),
|
|
["process", "tree"].join(""),
|
|
];
|
|
const canonicalAgentUiPackages = [
|
|
"@limecloud/agent-runtime-client",
|
|
"@limecloud/agent-ui-contracts",
|
|
"@limecloud/agent-runtime-projection",
|
|
"@limecloud/agent-runtime-ui",
|
|
];
|
|
const retiredAgentUiPackageNames = [
|
|
"@limecloud/agent-ui-projection",
|
|
"@limecloud/agent-ui-react",
|
|
];
|
|
const agentUiPackageNamingGuardFiles = [
|
|
"package.json",
|
|
"package-lock.json",
|
|
"pnpm-lock.yaml",
|
|
"tsconfig.json",
|
|
"vite.config.ts",
|
|
];
|
|
const retiredAgentRuntimeSessionFacadeSnippets = [
|
|
"AGENT_RUNTIME_COMMANDS.createSession",
|
|
"AGENT_RUNTIME_COMMANDS.listSessions",
|
|
"AGENT_RUNTIME_COMMANDS.getSession",
|
|
"AGENT_RUNTIME_COMMANDS.updateSession",
|
|
'createSession: "agent_runtime_create_session"',
|
|
'listSessions: "agent_runtime_list_sessions"',
|
|
'getSession: "agent_runtime_get_session"',
|
|
'updateSession: "agent_runtime_update_session"',
|
|
'readonly createSession: "agent_runtime_create_session"',
|
|
'readonly listSessions: "agent_runtime_list_sessions"',
|
|
'readonly getSession: "agent_runtime_get_session"',
|
|
'readonly updateSession: "agent_runtime_update_session"',
|
|
'"agent_runtime_create_session"',
|
|
'"agent_runtime_list_sessions"',
|
|
'"agent_runtime_get_session"',
|
|
'"agent_runtime_update_session"',
|
|
];
|
|
const retiredAgentRuntimeSessionFacadeProductionFiles = [
|
|
"electron/hostCommands.ts",
|
|
"electron/ipcChannels.ts",
|
|
"src/lib/dev-bridge/commandPolicy.ts",
|
|
"src/lib/governance/agentCommandCatalog.json",
|
|
];
|
|
const retiredAgentRuntimeEvidenceExportFacadeSnippets = [
|
|
"AGENT_RUNTIME_COMMANDS.exportEvidencePack",
|
|
'exportEvidencePack: "agent_runtime_export_evidence_pack"',
|
|
'readonly exportEvidencePack: "agent_runtime_export_evidence_pack"',
|
|
'"agent_runtime_export_evidence_pack"',
|
|
];
|
|
const retiredAgentRuntimeEvidenceExportFacadeProductionFiles = [
|
|
"electron/hostCommands.ts",
|
|
"electron/ipcChannels.ts",
|
|
"src/lib/dev-bridge/commandPolicy.ts",
|
|
"src/lib/governance/agentCommandCatalog.json",
|
|
];
|
|
const retiredAgentRuntimeThreadReadFacadeSnippets = [
|
|
"AGENT_RUNTIME_COMMANDS.getThreadRead",
|
|
'getThreadRead: "agent_runtime_get_thread_read"',
|
|
'readonly getThreadRead: "agent_runtime_get_thread_read"',
|
|
'"agent_runtime_get_thread_read"',
|
|
];
|
|
const retiredAgentRuntimeThreadReadFacadeProductionFiles =
|
|
retiredAgentRuntimeEvidenceExportFacadeProductionFiles;
|
|
const retiredAgentRuntimeSubmitTurnFacadeSnippets = [
|
|
"AGENT_RUNTIME_COMMANDS.submitTurn",
|
|
'submitTurn: "agent_runtime_submit_turn"',
|
|
'readonly submitTurn: "agent_runtime_submit_turn"',
|
|
'"agent_runtime_submit_turn"',
|
|
];
|
|
const retiredAgentRuntimeSubmitTurnFacadeProductionFiles =
|
|
retiredAgentRuntimeEvidenceExportFacadeProductionFiles;
|
|
const retiredAgentRuntimeInterruptTurnFacadeSnippets = [
|
|
"AGENT_RUNTIME_COMMANDS.interruptTurn",
|
|
'interruptTurn: "agent_runtime_interrupt_turn"',
|
|
'readonly interruptTurn: "agent_runtime_interrupt_turn"',
|
|
'"agent_runtime_interrupt_turn"',
|
|
];
|
|
const retiredAgentRuntimeInterruptTurnFacadeProductionFiles =
|
|
retiredAgentRuntimeEvidenceExportFacadeProductionFiles;
|
|
const retiredAgentRuntimeRespondActionFacadeSnippets = [
|
|
"AGENT_RUNTIME_COMMANDS.respondAction",
|
|
'respondAction: "agent_runtime_respond_action"',
|
|
'readonly respondAction: "agent_runtime_respond_action"',
|
|
'"agent_runtime_respond_action"',
|
|
];
|
|
const retiredAgentRuntimeRespondActionFacadeProductionFiles =
|
|
retiredAgentRuntimeEvidenceExportFacadeProductionFiles;
|
|
const activeAgentRuntimeAipromptFiles = [
|
|
"AGENTS.md",
|
|
...fs
|
|
.readdirSync(path.join(repoRoot, "internal/aiprompts"), {
|
|
withFileTypes: true,
|
|
})
|
|
.filter((entry) => entry.isFile() && entry.name.endsWith(".md"))
|
|
.map((entry) => `internal/aiprompts/${entry.name}`)
|
|
.sort(),
|
|
];
|
|
const activeAgentRuntimeMarkdownFiles = [
|
|
...activeAgentRuntimeAipromptFiles,
|
|
...collectMarkdownFiles("src"),
|
|
...collectMarkdownFiles("packages"),
|
|
...collectMarkdownFiles("electron"),
|
|
];
|
|
const allowedRetiredAgentRuntimeDocContextPattern =
|
|
/(旧|已删除|retired|legacy|历史|history|迁移|migration|compat|deprecated|dead|guard|test-only|fixture|只允许|不得|禁止|不再|不能|不要|not|forbid|forbidden|retire|退场|退役|残留|residual|reference|参考|cleanup|删除|现有迁移锚点)/i;
|
|
const forbiddenAgentRuntimeCurrentDocContextPattern =
|
|
/(current|主链|事实源|唯一|继续收敛|新增|新增能力|当前.*入口|当前.*主路径|必须回到|继续走|default tool surface|统一提交|统一会话管理|统一中断|统一响应)/i;
|
|
const retiredAgentRuntimeScriptCallPatterns = [
|
|
/\bcmd\s*:\s*["'`]agent_runtime_[A-Za-z0-9_]+["'`]/u,
|
|
/\bcommand\s*:\s*["'`]agent_runtime_[A-Za-z0-9_]+["'`]/u,
|
|
/\b(?:safeInvoke|invoke|invokeCommand|invokeAgentRuntimeBridge|bridgeInvoke|invokeViaHttp|postInvoke|postJson)\s*\([^)]*["'`]agent_runtime_[A-Za-z0-9_]+["'`]/su,
|
|
];
|
|
const agentRuntimeThinGatewayForbiddenSnippets = [
|
|
{
|
|
snippet: "mockPriorityCommands",
|
|
reason:
|
|
"frontend agentRuntime gateway cannot import renderer mock priority commands",
|
|
},
|
|
{
|
|
snippet: "defaultMocks",
|
|
reason:
|
|
"frontend agentRuntime gateway cannot use default mocks as fallback",
|
|
},
|
|
{
|
|
snippet: "invokeMockOnly",
|
|
reason: "frontend agentRuntime gateway cannot call test-only desktop mocks",
|
|
},
|
|
{
|
|
snippet: "explicitMockFallback",
|
|
reason:
|
|
"frontend agentRuntime gateway cannot use explicit renderer mock fallback",
|
|
},
|
|
{
|
|
snippet: "invokeExplicitMock",
|
|
reason:
|
|
"frontend agentRuntime gateway cannot invoke renderer mock fallback",
|
|
},
|
|
{
|
|
snippet: "listenExplicitMock",
|
|
reason:
|
|
"frontend agentRuntime gateway cannot listen to renderer mock fallback",
|
|
},
|
|
{
|
|
snippet: "mockCommand",
|
|
reason:
|
|
"frontend agentRuntime gateway cannot register renderer mock commands",
|
|
},
|
|
{
|
|
snippet: "clearMocks",
|
|
reason: "frontend agentRuntime gateway cannot clear renderer mock commands",
|
|
},
|
|
{
|
|
snippet: "fetch(",
|
|
reason:
|
|
"frontend agentRuntime gateway cannot call Provider or backend HTTP directly",
|
|
},
|
|
{
|
|
snippet: "XMLHttpRequest",
|
|
reason:
|
|
"frontend agentRuntime gateway cannot call Provider or backend HTTP directly",
|
|
},
|
|
{
|
|
snippet: "EventSource",
|
|
reason:
|
|
"frontend agentRuntime gateway cannot open a parallel stream transport",
|
|
},
|
|
{
|
|
snippet: "new WebSocket",
|
|
reason:
|
|
"frontend agentRuntime gateway cannot open a parallel stream transport",
|
|
},
|
|
{
|
|
snippet: "/v1/chat/completions",
|
|
reason: "frontend agentRuntime gateway cannot call model APIs directly",
|
|
},
|
|
{
|
|
snippet: "/v1/messages",
|
|
reason: "frontend agentRuntime gateway cannot call model APIs directly",
|
|
},
|
|
{
|
|
snippet: "chat/completions",
|
|
reason: "frontend agentRuntime gateway cannot call model APIs directly",
|
|
},
|
|
{
|
|
snippet: "LIME_GATEWAY",
|
|
reason: "frontend agentRuntime gateway cannot receive Gateway credentials",
|
|
},
|
|
{
|
|
snippet: "APP_SERVER_BACKEND_MODE=mock",
|
|
reason:
|
|
"frontend agentRuntime gateway cannot depend on App Server mock backend",
|
|
},
|
|
{
|
|
snippet: 'APP_SERVER_BACKEND_MODE: "mock"',
|
|
reason:
|
|
"frontend agentRuntime gateway cannot depend on App Server mock backend",
|
|
},
|
|
{
|
|
snippet: "APP_SERVER_BACKEND_MODE: 'mock'",
|
|
reason:
|
|
"frontend agentRuntime gateway cannot depend on App Server mock backend",
|
|
},
|
|
];
|
|
const retiredSkillExecutionSurfaceFiles = [
|
|
"src/hooks/useSkillExecution.ts",
|
|
"src/components/skills/SkillExecutionDialog.tsx",
|
|
"src/components/skills/SkillExecutionDialog.test.tsx",
|
|
];
|
|
const retiredAgentRuntimeMockFiles = [
|
|
"src/lib/desktop-host/agentRuntimeMocks.ts",
|
|
"src/lib/desktop-host/agentRuntimeMocks.d.ts",
|
|
"src/lib/desktop-host/agentRuntimeObjectiveMocks.ts",
|
|
"src/lib/desktop-host/agentRuntimeMocks.test.ts",
|
|
"src/lib/desktop-host/agentRuntimeObjectiveMocks.test.ts",
|
|
];
|
|
const retiredAgentRuntimeCommandManifestFiles = [
|
|
"src/lib/governance/agentRuntimeCommandSchema.json",
|
|
"src/lib/api/agentRuntime/commandManifest.generated.ts",
|
|
"src/lib/api/agentRuntime/commandManifest.generated.d.ts",
|
|
"scripts/generate-agent-runtime-clients.mjs",
|
|
];
|
|
const retiredAgentRuntimeAdapterFiles = [
|
|
"lime-rs/crates/app-server/src/runtime_backend_adapter.rs",
|
|
"lime-rs/crates/agent/src/message_content_adapter.rs",
|
|
"lime-rs/crates/agent/src/event_converter.rs",
|
|
];
|
|
const retiredRendererProjectionFiles = [
|
|
"src/lib/api/agentRuntime/canonicalApprovalItemProjection.ts",
|
|
"src/lib/api/agentRuntime/canonicalApprovalItemProjection.test.ts",
|
|
"src/lib/api/agentRuntime/appServerEventPayloadProjection.ts",
|
|
"src/components/agent/chat/projection/queueProjection.ts",
|
|
"src/components/agent/chat/projection/queueProjection.test.ts",
|
|
"packages/agent-runtime-projection/src/queueEvents.ts",
|
|
"src/components/agent/chat/hooks/agentStreamReadModelParsing.ts",
|
|
"src/components/agent/chat/hooks/agentQueuedTurnProjection.ts",
|
|
"src/components/agent/chat/hooks/agentQueuedTurnProjection.unit.test.ts",
|
|
];
|
|
const retiredRendererQueuedTurnProjectionProductionFiles = [
|
|
"src/lib/api/agentProtocolEventTypes.ts",
|
|
"src/lib/api/agentProtocol.d.ts",
|
|
"src/lib/api/agentProtocolRuntimeParsers.ts",
|
|
"src/components/agent/chat/projection/agentUiEventProjection.ts",
|
|
"src/components/agent/chat/hooks/agentStreamRuntimeLifecycleEvents.ts",
|
|
"src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts",
|
|
];
|
|
const retiredRendererQueuedTurnProjectionSnippets = [
|
|
"AgentEventQueueAdded",
|
|
"AgentEventQueueRemoved",
|
|
"AgentEventQueueStarted",
|
|
"AgentEventQueueCleared",
|
|
'case "queue_added"',
|
|
'case "queue_removed"',
|
|
'case "queue_started"',
|
|
'case "queue_cleared"',
|
|
"buildQueueProjectionEvents",
|
|
"handleAgentStreamQueueEvent",
|
|
];
|
|
const retiredRendererQueuedTurnSecondaryProjectionSpecs = [
|
|
{
|
|
file: "src/components/agent/chat/projection/threadReadActivity.ts",
|
|
snippets: [
|
|
"includeQueuedActivity",
|
|
'"queued_turns"',
|
|
'"queuedTurns"',
|
|
"hasPendingOrQueuedActivity",
|
|
],
|
|
},
|
|
{
|
|
file: "src/components/agent/chat/hooks/agentSessionTopicViewModel.ts",
|
|
snippets: [
|
|
"shouldAutoResumeHydratedRuntimeThread",
|
|
"resolveRuntimePreviewFromSessionDetail",
|
|
".queued_turns",
|
|
],
|
|
},
|
|
{
|
|
file: "src/components/agent/chat/hooks/agentChatHistoryNormalize.ts",
|
|
snippets: [".queued_turns"],
|
|
},
|
|
{
|
|
file: "src/lib/api/agentRuntime/sessionClient.ts",
|
|
snippets: ["queuedTurnsCount:"],
|
|
},
|
|
{
|
|
file: "src/components/agent/chat/hooks/agentSessionState.ts",
|
|
snippets: [
|
|
"QueuedTurnSnapshot",
|
|
"normalizeQueuedTurnSnapshots",
|
|
"queuedTurns:",
|
|
],
|
|
},
|
|
{
|
|
file: "src/components/agent/chat/hooks/agentSessionRefresh.ts",
|
|
snippets: [
|
|
"QueuedTurnSnapshot",
|
|
"normalizeQueuedTurnSnapshots",
|
|
"queuedTurns:",
|
|
],
|
|
},
|
|
{
|
|
file: "src/components/agent/chat/hooks/useAgentSession.ts",
|
|
snippets: ["QueuedTurnSnapshot", "setQueuedTurns", "queuedTurns:"],
|
|
},
|
|
{
|
|
file: "src/components/agent/chat/hooks/useAgentChat.ts",
|
|
snippets: ["session.queuedTurns", "queuedTurns: session.queuedTurns"],
|
|
},
|
|
{
|
|
file: "src/components/agent/chat/workspace/useAgentChatWorkspaceSetupRuntime.ts",
|
|
snippets: ["queuedTurns = []", "queuedTurns,"],
|
|
},
|
|
{
|
|
file: "src/components/agent/chat/workspace/useAgentChatWorkspaceCommandRuntime.ts",
|
|
snippets: ["queuedTurns.length"],
|
|
},
|
|
];
|
|
const retiredAgentRuntimeLegacyQueueFiles = [
|
|
"lime-rs/crates/core/src/database/agent_runtime_queue_repository.rs",
|
|
"lime-rs/crates/agent/src/agent_runtime_support.rs",
|
|
];
|
|
const retiredAgentRuntimeLegacyQueueSurfaceFiles = [
|
|
"lime-rs/crates/core/src/database/mod.rs",
|
|
"src/lib/governance/legacySurfaceCatalog.json",
|
|
];
|
|
const retiredAgentUiResumeContractFiles = [
|
|
"packages/agent-ui-contracts/schemas/agent-runtime-resume-contract.v0.1.schema.json",
|
|
];
|
|
const retiredAgentRuntimeLegacyQueueSnippets = [
|
|
"agent_runtime_queued_turns",
|
|
"agent_runtime_queue_repository",
|
|
"migrate_legacy_runtime_queue_to_agent_store",
|
|
"LegacyRuntimeQueueMigrationReport",
|
|
"LegacyRuntimeQueuedTurn",
|
|
];
|
|
const retiredAgentRuntimeToolInventoryMockFiles = [
|
|
"src/lib/desktop-host/runtimeToolInventoryMocks.ts",
|
|
"src/lib/desktop-host/runtimeToolInventoryMocks.d.ts",
|
|
];
|
|
|
|
const checks = [
|
|
{
|
|
name: "Rust protocol exposes capability discovery request and response DTOs",
|
|
files: rustProtocolFiles,
|
|
snippets: [
|
|
"schemars::JsonSchema",
|
|
'pub const METHOD_CAPABILITY_LIST: &str = "capability/list"',
|
|
"pub struct CapabilityListParams",
|
|
"pub app_id: Option<String>",
|
|
"pub workspace_id: Option<String>",
|
|
"pub session_id: Option<String>",
|
|
"pub cursor: Option<String>",
|
|
"pub limit: Option<u32>",
|
|
"pub struct CapabilityListResponse",
|
|
"pub next_cursor: Option<String>",
|
|
"pub struct CapabilityDescriptor",
|
|
"pub enum AppServerMethodKind",
|
|
"pub struct AppServerMethodSpec",
|
|
"pub const APP_SERVER_METHODS: &[AppServerMethodSpec]",
|
|
"pub enum AppServerRequestSerializationScope",
|
|
"pub struct AppServerRequestSerializationScopeSpec",
|
|
"pub const APP_SERVER_REQUEST_SERIALIZATION_SCOPES",
|
|
"pub fn app_server_request_serialization_scope",
|
|
"pub fn is_app_server_request_method(method: &str) -> bool",
|
|
"pub fn is_app_server_notification_method(method: &str) -> bool",
|
|
"pub const CAPABILITY_DENIED: i64 = -32020",
|
|
'#[serde(rename_all = "camelCase")]',
|
|
],
|
|
},
|
|
{
|
|
name: "Rust protocol exports JSON schema fixtures for JSON-RPC, v0, and v2 DTOs",
|
|
files: rustProtocolFiles,
|
|
snippets: [
|
|
"pub const JSONRPC_SCHEMA_TYPE_NAMES: &[&str]",
|
|
"pub const V0_SCHEMA_TYPE_NAMES: &[&str]",
|
|
"pub const V2_SCHEMA_TYPE_NAMES: &[&str]",
|
|
"JsonRpcRequest",
|
|
"AgentSessionTurnStartParams",
|
|
"RuntimeOptions",
|
|
"pub include_protocol_types: bool",
|
|
"fn jsonrpc_schemas() -> Vec<GeneratedJsonSchema>",
|
|
"fn v0_schemas() -> Vec<GeneratedJsonSchema>",
|
|
"fn v2_schemas() -> Vec<GeneratedJsonSchema>",
|
|
'typed_schema::<AppServerRequestSerializationScope>("AppServerRequestSerializationScope")',
|
|
'typed_schema::<AppServerRequestSerializationScopeSpec>("AppServerRequestSerializationScopeSpec")',
|
|
'typed_schema::<AgentSessionTurnStartParams>("AgentSessionTurnStartParams")',
|
|
'PathBuf::from("json")',
|
|
'.join("v0")',
|
|
'.join("v2")',
|
|
'.join("jsonrpc")',
|
|
'"schemas": {',
|
|
"schema_registry_matches_declared_type_names",
|
|
],
|
|
},
|
|
{
|
|
name: "configWarning stays current from v2 producer through Electron and Renderer toast",
|
|
files: [
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v2/config.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v2/envelopes.rs",
|
|
"lime-rs/crates/app-server-protocol/schema/json/v2/ConfigWarningNotification.json",
|
|
appServerGeneratedProtocolFile,
|
|
"lime-rs/crates/app-server/src/processor/config_warning.rs",
|
|
"packages/app-server-client/tests/client.test.mjs",
|
|
"electron/appServerHost.test.ts",
|
|
"src/lib/api/appServerResponse.ts",
|
|
"src/lib/api/appServerClient.ts",
|
|
"src/lib/api/appServerConfigWarnings.ts",
|
|
"src/components/AppServerConfigWarningToastBridge.tsx",
|
|
"src/App.tsx",
|
|
"src/i18n/__tests__/loadNamespace.test.ts",
|
|
],
|
|
snippets: [
|
|
"pub struct ConfigWarningNotification",
|
|
"ConfigWarning(ConfigWarningNotification)",
|
|
'"title": "ConfigWarningNotification"',
|
|
'export const METHOD_CONFIG_WARNING = "configWarning"',
|
|
'method: "configWarning"',
|
|
"isAppServerNotificationMethod(METHOD_CONFIG_WARNING), true",
|
|
"ConfigWarningScope::Initialize",
|
|
"connected.connection.nextNotification(",
|
|
"warmup 后应保留 initialize 阶段已缓冲的 configWarning",
|
|
"readAppServerConfigWarnings",
|
|
"publishAppServerConfigWarnings",
|
|
"subscribeAppServerConfigWarnings",
|
|
"AppServerConfigWarningToastBridge",
|
|
"<AppServerConfigWarningToastBridge />",
|
|
"common.app.configWarning.descriptionWithPathAndDetails",
|
|
],
|
|
},
|
|
{
|
|
name: "runtime.warning stays typed from App Server projection through localized Renderer warning",
|
|
files: [
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v2/notification.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v2/envelopes.rs",
|
|
"lime-rs/crates/app-server-protocol/schema/json/v2/WarningNotification.json",
|
|
appServerGeneratedProtocolFile,
|
|
"lime-rs/crates/app-server/src/processor/v2_notifications.rs",
|
|
"lime-rs/crates/app-server/src/processor/v2_notifications/warning.rs",
|
|
"lime-rs/crates/app-server/src/runtime/read_model/runtime_items.rs",
|
|
"src/lib/api/agentRuntime/appServerV2Notification.ts",
|
|
"src/lib/api/agentRuntime/eventSequenceGate.ts",
|
|
"src/lib/api/agentRuntime/appServerEventStream.test.ts",
|
|
"packages/app-server-client/tests/client.test.mjs",
|
|
],
|
|
snippets: [
|
|
"pub struct WarningNotification",
|
|
"Warning(WarningNotification)",
|
|
'export const METHOD_WARNING = "warning"',
|
|
'"runtime.warning" => return warning::project(event)',
|
|
"ServerNotification::Warning",
|
|
"runtime_warning_code_from_event",
|
|
'case "warning"',
|
|
'notification.method === "warning"',
|
|
'"runtime.warning",',
|
|
"isAppServerNotificationMethod(METHOD_WARNING), true",
|
|
],
|
|
},
|
|
{
|
|
name: "runtime errors stay typed from App Server retry policy through Renderer state",
|
|
files: [
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v2/common.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v2/notification.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v2/envelopes.rs",
|
|
"lime-rs/crates/app-server-protocol/schema/json/v2/ErrorNotification.json",
|
|
appServerGeneratedProtocolFile,
|
|
"packages/app-server-client/src/server-notifications.ts",
|
|
"packages/app-server-client/src/agent-runtime.ts",
|
|
"lime-rs/crates/app-server/src/processor/v2_notifications.rs",
|
|
"lime-rs/crates/app-server/src/processor/v2_notifications/error.rs",
|
|
"src/lib/api/agentRuntime/appServerV2Notification.ts",
|
|
"src/components/agent/chat/hooks/agentStreamTypedErrorController.ts",
|
|
"src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts",
|
|
],
|
|
snippets: [
|
|
"pub enum CodexErrorInfo",
|
|
'#[serde(rename = "httpStatusCode")]',
|
|
'#[serde(rename = "turnKind")]',
|
|
"pub struct ErrorNotification",
|
|
"Error(ErrorNotification)",
|
|
'export const METHOD_ERROR = "error"',
|
|
"export interface ErrorNotification",
|
|
"httpStatusCode?: number | null;",
|
|
"turnKind: NonSteerableTurnKind;",
|
|
'"runtime.error" => return self.project_error(event, None)',
|
|
"error::project(event, Some(false))",
|
|
"ServerNotification::Error",
|
|
"isErrorNotification(notification)",
|
|
"notification && !isAgentRuntimeSignalNotification(notification)",
|
|
'params.event.protocol_method !== "error"',
|
|
'typeof params.event.will_retry !== "boolean"',
|
|
"buildAgentStreamTypedErrorPlan",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer turn binding cannot restore raw runtime error fallback",
|
|
file: "src/components/agent/chat/hooks/agentStreamTurnEventBinding.ts",
|
|
snippets: ["handleTurnStreamEvent"],
|
|
absentSnippets: [
|
|
'"runtime_error"',
|
|
'"runtime.error"',
|
|
"readRuntimeErrorMessage",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust App Server gates AgentUI runtime events before storage",
|
|
files: [
|
|
"lime-rs/crates/app-server/src/lib.rs",
|
|
"lime-rs/crates/app-server/src/agent_ui_event_schema.rs",
|
|
"lime-rs/crates/app-server/src/agent_ui_sequence_verifier.rs",
|
|
"lime-rs/crates/app-server/src/runtime.rs",
|
|
"lime-rs/crates/app-server/src/runtime/event_store.rs",
|
|
"lime-rs/crates/app-server/src/runtime/event_store/validation.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tool_lifecycle.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tool_lifecycle_tests.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tests.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tests/external_events.rs",
|
|
...collectRustFiles(
|
|
"lime-rs/crates/app-server/src/runtime/tests/external_events",
|
|
),
|
|
],
|
|
snippets: [
|
|
"mod agent_ui_event_schema;",
|
|
"mod agent_ui_sequence_verifier;",
|
|
"mod tool_lifecycle;",
|
|
"agent-runtime-event.v0.1.schema.json",
|
|
"agent-runtime-state-delta.v0.1.schema.json",
|
|
"jsonschema::validator_for",
|
|
"mod validation;",
|
|
"use self::validation::EventValidationContext;",
|
|
"EventValidationContext::from_events(&stored.events, session_id, turn_id)",
|
|
"agent_ui_event_schema::validate_agent_event(&event).map_err(RuntimeCoreError::Backend)?",
|
|
"validation.validate_and_observe(",
|
|
"events.push(event)",
|
|
"stored.events.push(event)",
|
|
"struct EventValidationContext",
|
|
"AgentEventSequenceValidator::from_events",
|
|
"ToolLifecycleValidator::from_events",
|
|
"self.sequence.validate_and_observe(event)?",
|
|
"self.tool_lifecycle.validate_and_observe(event)?",
|
|
"agent runtime event sequence validation failed",
|
|
"agent runtime tool lifecycle validation failed",
|
|
"rejects_policy_event_for_inactive_tool",
|
|
"rejects_tool_output_before_action_resolution",
|
|
"rejects_tool_result_after_action_denial",
|
|
"rejects_tool_result_owner_mismatch",
|
|
"append_external_runtime_events_rejects_invalid_state_delta_before_storage",
|
|
"invalid state.delta must fail closed",
|
|
"append_external_runtime_events_rejects_canonical_tool_completed_without_start",
|
|
"append_external_runtime_events_rejects_duplicate_canonical_tool_start",
|
|
"append_external_runtime_events_rejects_retired_raw_tool_wire",
|
|
"append_external_runtime_events_rejects_retired_raw_tool_wire_with_import_markers",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust protocol exposes agentSession/action/respond DTOs and method catalog",
|
|
files: rustProtocolFiles,
|
|
snippets: [
|
|
'pub const METHOD_AGENT_SESSION_ACTION_RESPOND: &str = "agentSession/action/respond"',
|
|
"pub enum AgentSessionActionType",
|
|
"ToolConfirmation",
|
|
"AskUser",
|
|
"Elicitation",
|
|
"pub struct AgentSessionActionScope",
|
|
"pub struct AgentSessionActionRespondParams",
|
|
"pub request_id: String",
|
|
"pub action_type: AgentSessionActionType",
|
|
"pub confirmed: bool",
|
|
"pub response: Option<String>",
|
|
"pub user_data: Option<serde_json::Value>",
|
|
"pub metadata: Option<serde_json::Value>",
|
|
"pub event_name: Option<String>",
|
|
"pub action_scope: Option<AgentSessionActionScope>",
|
|
"pub struct AgentSessionActionRespondResponse",
|
|
"method: METHOD_AGENT_SESSION_ACTION_RESPOND,",
|
|
"agent_session_action_respond_request_matches_protocol_fixture_shape",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust protocol exposes artifact/read DTOs and method catalog",
|
|
files: rustProtocolFiles,
|
|
snippets: [
|
|
'pub const METHOD_ARTIFACT_READ: &str = "artifact/read"',
|
|
"pub struct ArtifactReadParams",
|
|
"pub session_id: String",
|
|
"pub turn_id: Option<String>",
|
|
"pub artifact_ref: Option<String>",
|
|
"pub include_content: Option<bool>",
|
|
"pub struct ArtifactSummary",
|
|
"pub artifact_ref: String",
|
|
"pub event_id: String",
|
|
"pub content: Option<String>",
|
|
"pub enum ArtifactContentStatus",
|
|
"pub content_status: ArtifactContentStatus",
|
|
"pub metadata: Option<serde_json::Value>",
|
|
"pub struct ArtifactReadResponse",
|
|
"pub artifacts: Vec<ArtifactSummary>",
|
|
"method: METHOD_ARTIFACT_READ,",
|
|
"artifact_read_request_matches_protocol_fixture_shape",
|
|
"artifact_summary_content_status_matches_protocol_fixture_shape",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust protocol exposes exact fs DTOs and method catalog",
|
|
files: rustProtocolFiles,
|
|
snippets: [
|
|
'pub const METHOD_FS_READ_FILE: &str = "fs/readFile"',
|
|
'pub const METHOD_FS_WRITE_FILE: &str = "fs/writeFile"',
|
|
'pub const METHOD_FS_CREATE_DIRECTORY: &str = "fs/createDirectory"',
|
|
'pub const METHOD_FS_GET_METADATA: &str = "fs/getMetadata"',
|
|
'pub const METHOD_FS_READ_DIRECTORY: &str = "fs/readDirectory"',
|
|
'pub const METHOD_FS_REMOVE: &str = "fs/remove"',
|
|
'pub const METHOD_FS_COPY: &str = "fs/copy"',
|
|
'pub const METHOD_FS_WATCH: &str = "fs/watch"',
|
|
'pub const METHOD_FS_UNWATCH: &str = "fs/unwatch"',
|
|
'pub const METHOD_FS_CHANGED: &str = "fs/changed"',
|
|
"pub struct FsReadFileParams",
|
|
"pub struct FsReadFileResponse",
|
|
"pub data_base64: String",
|
|
"pub struct FsWriteFileParams",
|
|
"pub struct FsCreateDirectoryParams",
|
|
"pub struct FsGetMetadataResponse",
|
|
"pub struct FsReadDirectoryResponse",
|
|
"pub struct FsRemoveParams",
|
|
"pub recursive: Option<bool>",
|
|
"pub force: Option<bool>",
|
|
"pub struct FsCopyParams",
|
|
"pub source_path: String",
|
|
"pub destination_path: String",
|
|
"pub struct FsWatchParams",
|
|
"pub watch_id: String",
|
|
"pub struct FsChangedNotification",
|
|
"pub changed_paths: Vec<String>",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust server initializes capability discovery and dispatches capability/list",
|
|
files: appServerProcessorFiles,
|
|
snippets: [
|
|
"METHOD_CAPABILITY_LIST => self.handle_capability_list(params)",
|
|
"let params: CapabilityListParams = parse_params(params)?",
|
|
".list_capabilities(params)",
|
|
".map_err(to_jsonrpc_error)?",
|
|
"capability_discovery: true",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust JSON-RPC router dispatches agentSession/action/respond into RuntimeCore",
|
|
files: appServerProcessorFiles,
|
|
snippets: [
|
|
"METHOD_AGENT_SESSION_ACTION_RESPOND => self.handle_action_respond(params).await",
|
|
"let params: AgentSessionActionRespondParams = parse_params(params)?",
|
|
".respond_action(params, host)",
|
|
"dispatch_result_with_events(output.response, output.events)",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust JSON-RPC router dispatches artifact/read into RuntimeCore",
|
|
files: appServerProcessorFiles,
|
|
snippets: [
|
|
"METHOD_ARTIFACT_READ => self.handle_artifact_read(params)",
|
|
"fn handle_artifact_read(",
|
|
"let params: ArtifactReadParams = parse_params(params)?",
|
|
".read_artifacts(params)",
|
|
"artifact: true",
|
|
"artifact_read_requires_initialized_and_returns_artifact_summaries",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust JSON-RPC router dispatches exact fs methods into FsServer",
|
|
files: appServerProcessorFiles,
|
|
snippets: [
|
|
"v2::METHOD_FS_READ_FILE => self.handle_fs_read_file_impl(params).boxed()",
|
|
"v2::METHOD_FS_WRITE_FILE => self.handle_fs_write_file_impl(params).boxed()",
|
|
"v2::METHOD_FS_CREATE_DIRECTORY => self.handle_fs_create_directory_impl(params).boxed()",
|
|
"v2::METHOD_FS_GET_METADATA => self.handle_fs_get_metadata_impl(params).boxed()",
|
|
"v2::METHOD_FS_READ_DIRECTORY => self.handle_fs_read_directory_impl(params).boxed()",
|
|
"v2::METHOD_FS_REMOVE => self.handle_fs_remove_impl(params).boxed()",
|
|
"v2::METHOD_FS_COPY => self.handle_fs_copy_impl(params).boxed()",
|
|
".handle_fs_watch_impl(params, connection_request_id.clone())",
|
|
".handle_fs_unwatch_impl(params, connection_request_id.clone())",
|
|
"let params: FsReadFileParams = parse_params(params)?",
|
|
"let params: FsWriteFileParams = parse_params(params)?",
|
|
"let params: FsCreateDirectoryParams = parse_params(params)?",
|
|
"let params: FsGetMetadataParams = parse_params(params)?",
|
|
"let params: FsReadDirectoryParams = parse_params(params)?",
|
|
"let params: FsRemoveParams = parse_params(params)?",
|
|
"let params: FsCopyParams = parse_params(params)?",
|
|
"let params: FsWatchParams = parse_params(params)?",
|
|
"let params: FsUnwatchParams = parse_params(params)?",
|
|
"dispatch_result(self.fs.read_file(params).await?)",
|
|
"dispatch_result(self.fs.unwatch(connection_id(request)?, params).await?)",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust capability module exposes host-independent inventory source",
|
|
file: "lime-rs/crates/app-server/src/capability.rs",
|
|
snippets: [
|
|
"pub struct CapabilityInventoryRecord",
|
|
"pub struct CapabilityInventorySource",
|
|
"pub struct CapabilityListContext",
|
|
"pub app_id: Option<String>",
|
|
"pub workspace_id: Option<String>",
|
|
"pub session_id: Option<String>",
|
|
"pub fn executable_agent_turn(",
|
|
"pub fn capability_descriptor_allows_agent_turn_start(",
|
|
"pub fn for_sessions(",
|
|
"pub trait CapabilitySource",
|
|
"fn list_capabilities(&self, context: &CapabilityListContext) -> Vec<CapabilityDescriptor>",
|
|
"fn scope_matches",
|
|
"inventory_source_filters_by_session_scope",
|
|
'id: "agent.session".to_string()',
|
|
"METHOD_TURN_START.to_string()",
|
|
"METHOD_TURN_INTERRUPT.to_string()",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust runtime uses injected capability source",
|
|
files: appServerRuntimeFiles,
|
|
snippets: [
|
|
"capability_source: Arc<dyn CapabilitySource>",
|
|
"pub fn with_backend_and_capability_source(",
|
|
"capability_source: Arc<dyn CapabilitySource>",
|
|
"CapabilityInventorySource::default()",
|
|
"pub fn list_capabilities(",
|
|
"Result<CapabilityListResponse, RuntimeCoreError>",
|
|
"fn capability_list_context(",
|
|
"SessionNotFound(session_id.clone())",
|
|
"session_id: Some(session_id)",
|
|
"self.capability_source.list_capabilities(&context)",
|
|
"capability_descriptor_allows_agent_turn_start(capability)",
|
|
"fn paginate_capabilities(",
|
|
"next_cursor",
|
|
"fn ensure_capability_allowed_with_context(",
|
|
"METHOD_TURN_START",
|
|
"capability_list_with_session_id_uses_stored_session_scope",
|
|
"start_turn_allows_session_scoped_capability_id",
|
|
"RuntimeCoreError::CapabilityDenied",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust runtime routes action responses through injected backend",
|
|
files: appServerRuntimeFiles,
|
|
snippets: [
|
|
"pub struct ActionRespondRequest",
|
|
"async fn respond_action(",
|
|
"pub async fn respond_action(",
|
|
"params: AgentSessionActionRespondParams",
|
|
"AgentSessionActionRespondResponse",
|
|
"RuntimeCoreError::TurnNotActive",
|
|
"ActionRespondRequest {",
|
|
"action_scope: params.action_scope",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust FsServer owns exact file IO and connection-scoped watches",
|
|
files: [
|
|
"lime-rs/crates/app-server/src/fs.rs",
|
|
"lime-rs/crates/app-server/src/fs/tests.rs",
|
|
],
|
|
snippets: [
|
|
"pub(crate) struct FsServer",
|
|
"pub(crate) async fn read_file(",
|
|
'absolute_path(¶ms.path, "fs/readFile.path")',
|
|
"STANDARD.encode(bytes)",
|
|
"pub(crate) async fn write_file(",
|
|
"STANDARD.decode(params.data_base64)",
|
|
"pub(crate) async fn create_directory(",
|
|
"pub(crate) async fn get_metadata(",
|
|
"pub(crate) async fn read_directory(",
|
|
"pub(crate) async fn remove(",
|
|
"pub(crate) async fn copy(",
|
|
"pub(crate) async fn watch(",
|
|
"pub(crate) async fn unwatch(",
|
|
"ServerNotification::FsChanged(FsChangedNotification {",
|
|
"watch_ids_are_connection_scoped_and_disconnect_cleans_only_the_owner",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust runtime indexes artifact summaries from stored events",
|
|
files: appServerRuntimeFiles,
|
|
snippets: [
|
|
"pub fn read_artifacts(",
|
|
"params: ArtifactReadParams",
|
|
"Result<ArtifactReadResponse, RuntimeCoreError>",
|
|
"ArtifactContentProvider",
|
|
"ArtifactContentRequest",
|
|
"InlineArtifactContentProvider",
|
|
"FilesystemArtifactContentProvider",
|
|
"DEFAULT_ARTIFACT_CONTENT_MAX_BYTES",
|
|
"ArtifactContentStatus::Available",
|
|
"ArtifactContentStatus::Unavailable",
|
|
"ArtifactContentStatus::NotRequested",
|
|
"with_backend_capability_source_and_artifact_content_provider",
|
|
"fn read_limited_relative_utf8_file(",
|
|
"fn is_safe_relative_path(",
|
|
"fn paginate_artifact_summaries(",
|
|
"fn artifact_summary_from_event(",
|
|
"fn string_field(",
|
|
"read_artifacts_indexes_latest_artifact_events_for_session",
|
|
"read_artifacts_uses_injected_content_provider_for_current_page",
|
|
"filesystem_artifact_content_provider_reads_allowed_relative_path",
|
|
"filesystem_artifact_content_provider_rejects_escape_and_oversized_files",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust App Server keeps retired backend adapter out of RuntimeBackend",
|
|
files: [
|
|
"lime-rs/crates/app-server/src/main.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend.rs",
|
|
"lime-rs/crates/app-server/src/runtime_factory.rs",
|
|
],
|
|
snippets: [
|
|
"parse_args_rejects_runtime_backend_for_standalone_binary",
|
|
"unsupported app-server backend mode: agent",
|
|
"RuntimeBackend::with_execution_process_server",
|
|
"RuntimeBackend::with_db_and_execution_process_server",
|
|
],
|
|
absentSnippets: [
|
|
"RuntimeBackendAdapter",
|
|
"RuntimeBackendHost",
|
|
"runtime_adapter_core",
|
|
],
|
|
},
|
|
{
|
|
name: "Standalone App Server local data source implements workspace and skill surfaces",
|
|
files: [
|
|
"lime-rs/crates/app-server/src/runtime/app_data.rs",
|
|
"lime-rs/crates/app-server/src/runtime/app_data/skills.rs",
|
|
"lime-rs/crates/app-server/src/runtime/app_data/workspaces.rs",
|
|
"lime-rs/crates/app-server/src/local_data_source.rs",
|
|
"lime-rs/crates/app-server/src/local_data_source/impls/skills.rs",
|
|
"lime-rs/crates/app-server/src/local_data_source/impls/workspace_skill_bindings.rs",
|
|
"lime-rs/crates/app-server/src/local_data_source/impls/workspaces.rs",
|
|
"lime-rs/crates/app-server/src/local_data_source/workspaces.rs",
|
|
"lime-rs/crates/app-server/src/local_data_source/skills/workspace.rs",
|
|
],
|
|
snippets: [
|
|
"pub struct LocalAppDataSource",
|
|
"pub trait AppDataSource:",
|
|
"impl<T> AppDataSource for T where",
|
|
"pub trait WorkspaceAppDataSource: Send + Sync",
|
|
"pub trait SkillAppDataSource: Send + Sync",
|
|
"pub trait WorkspaceSkillBindingAppDataSource: Send + Sync",
|
|
"impl WorkspaceAppDataSource for LocalAppDataSource",
|
|
"impl SkillAppDataSource for LocalAppDataSource",
|
|
"impl WorkspaceSkillBindingAppDataSource for LocalAppDataSource",
|
|
"async fn list_workspaces(&self) -> Result<WorkspaceListResponse, RuntimeCoreError>",
|
|
"async fn read_workspace(",
|
|
"async fn read_workspace_by_path(",
|
|
"async fn ensure_workspace_ready(",
|
|
"async fn read_workspace_projects_root(",
|
|
"async fn resolve_workspace_project_path(",
|
|
"async fn read_skill(",
|
|
"async fn list_workspace_skill_bindings(",
|
|
"fn row_to_workspace_value(row: &Row<'_>)",
|
|
"fn ensure_current_default_workspace(",
|
|
"fn list_workspace_skill_bindings_value(",
|
|
'"当前只返回 workspace 本地注册 Skill 的只读 readiness;不会 reload Skill,也不会注入默认工具面。"',
|
|
],
|
|
},
|
|
{
|
|
name: "Runtime projection store preserves current session list cwd filters",
|
|
files: [
|
|
"lime-rs/crates/app-server/src/runtime/session_lifecycle.rs",
|
|
"lime-rs/crates/app-server/src/runtime/session_list_scope.rs",
|
|
"lime-rs/crates/app-server/src/runtime/projection_store.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tests/session_list_projection.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tests/sessions.rs",
|
|
],
|
|
snippets: [
|
|
"pub struct SessionListScope",
|
|
"pub fn from_params(params: &AgentSessionListParams) -> Self",
|
|
"normalize_cwd_filter(params.cwd.as_ref())",
|
|
"workspace_id_filters: normalize_id_filter(params.workspace_id.as_deref())",
|
|
"pub fn matches_session(&self, workspace_id: Option<&str>, cwd: Option<&str>) -> bool",
|
|
"let scope = SessionListScope::from_params(params);",
|
|
"let cwd_filters = scope.cwd_filters();",
|
|
'Some(format!("working_dir IN ({placeholders})"))',
|
|
'format!(" AND (({cwd}) OR ({workspace_id}))")',
|
|
"params.include_archived.unwrap_or(false)",
|
|
"params.archived_only.unwrap_or(false)",
|
|
"(?1 = 1 AND archived_at IS NOT NULL)",
|
|
"(?1 = 0 AND (?2 = 1 OR archived_at IS NULL))",
|
|
"pub fn list_session_overviews(",
|
|
".list_session_overviews(¶ms)",
|
|
"list_agent_sessions_filters_projection_by_cwd",
|
|
],
|
|
absentSnippets: [
|
|
"pub(crate) fn list_current_timeline_sessions(",
|
|
"pub(crate) fn resolve_session_list_scope(",
|
|
"fn query_current_timeline_session_overviews(",
|
|
"pub fn archive_many_sessions(",
|
|
".archive_many_sessions(",
|
|
],
|
|
},
|
|
{
|
|
name: "App Server protocol exposes current app data surface methods and DTOs",
|
|
files: rustProtocolFiles,
|
|
snippets: [
|
|
'pub const METHOD_KNOWLEDGE_PACK_LIST: &str = "knowledgePack/list"',
|
|
'pub const METHOD_KNOWLEDGE_PACK_READ: &str = "knowledgePack/read"',
|
|
'pub const METHOD_KNOWLEDGE_SOURCE_IMPORT: &str = "knowledgePack/source/import"',
|
|
'pub const METHOD_KNOWLEDGE_PACK_COMPILE: &str = "knowledgePack/compile"',
|
|
'pub const METHOD_KNOWLEDGE_PACK_DEFAULT_SET: &str = "knowledgePack/default/set"',
|
|
'pub const METHOD_KNOWLEDGE_PACK_STATUS_UPDATE: &str = "knowledgePack/status/update"',
|
|
'pub const METHOD_KNOWLEDGE_CONTEXT_RESOLVE: &str = "knowledgeContext/resolve"',
|
|
'pub const METHOD_KNOWLEDGE_CONTEXT_RUN_VALIDATE: &str = "knowledgeContextRun/validate"',
|
|
'pub const METHOD_SCHEDULED_TASK_LIST: &str = "scheduledTask/list"',
|
|
'pub const METHOD_PROJECT_MEMORY_READ: &str = "projectMemory/read"',
|
|
'pub const METHOD_MEMORY_STORE_LIST: &str = "memoryStore/list"',
|
|
'pub const METHOD_MEMORY_STORE_READ: &str = "memoryStore/read"',
|
|
'pub const METHOD_MEMORY_STORE_SEARCH: &str = "memoryStore/search"',
|
|
'pub const METHOD_MEMORY_STORE_ADD_NOTE: &str = "memoryStore/addNote"',
|
|
'pub const METHOD_MEMORY_STORE_CONSOLIDATE: &str = "memoryStore/consolidate"',
|
|
'pub const METHOD_MEMORY_STORE_REVIEW_LIST: &str = "memoryStore/review/list"',
|
|
'pub const METHOD_MEMORY_STORE_REVIEW_RESOLVE: &str = "memoryStore/review/resolve"',
|
|
'pub const METHOD_MEMORY_STORE_HEALTH: &str = "memoryStore/health"',
|
|
'pub const METHOD_MEMORY_RESET: &str = "memory/reset"',
|
|
'pub const METHOD_MEMORY_STORE_INDEX_REBUILD: &str = "memoryStore/index/rebuild"',
|
|
"pub struct KnowledgeListPacksParams",
|
|
"pub working_dir: String",
|
|
"pub include_archived: bool",
|
|
"pub struct KnowledgeListPacksResponse",
|
|
"pub root_path: String",
|
|
"pub packs: Vec<serde_json::Value>",
|
|
"pub struct KnowledgeReadPackParams",
|
|
"pub name: String",
|
|
"pub struct KnowledgeReadPackResponse",
|
|
"pub pack: serde_json::Value",
|
|
"pub struct KnowledgeImportSourceParams",
|
|
"pub pack_name: String",
|
|
"pub source_text: Option<String>",
|
|
"pub struct KnowledgeImportSourceResponse",
|
|
"pub source: serde_json::Value",
|
|
"pub struct KnowledgeCompilePackParams",
|
|
"pub builder_runtime: Option<serde_json::Value>",
|
|
"pub struct KnowledgeCompilePackResponse",
|
|
"pub selected_source_count: u32",
|
|
"pub compiled_view: serde_json::Value",
|
|
"pub struct KnowledgeSetDefaultPackParams",
|
|
"pub struct KnowledgeSetDefaultPackResponse",
|
|
"pub default_pack_name: String",
|
|
"pub struct KnowledgeUpdatePackStatusParams",
|
|
"pub status: String",
|
|
"pub struct KnowledgeUpdatePackStatusResponse",
|
|
"pub previous_status: String",
|
|
"pub struct KnowledgeResolveContextParams",
|
|
"pub struct KnowledgeContextResolutionResponse",
|
|
"pub fenced_context: String",
|
|
"pub struct KnowledgeValidateContextRunParams",
|
|
"pub struct KnowledgeValidateContextRunResponse",
|
|
"pub valid: bool",
|
|
"pub struct ScheduledTaskListResponse",
|
|
"pub items: Vec<ScheduledTaskSummary>",
|
|
"pub struct ProjectMemoryReadParams",
|
|
"pub project_id: String",
|
|
"pub struct ProjectMemoryReadResponse",
|
|
"pub memory: serde_json::Value",
|
|
"pub struct MemoryStoreListParams",
|
|
"pub struct MemoryStoreReadParams",
|
|
"pub struct MemoryStoreSearchParams",
|
|
"pub struct MemoryStoreAddNoteParams",
|
|
"pub struct MemoryStoreConsolidateParams",
|
|
"pub struct MemoryStoreReviewListParams",
|
|
"pub enum MemoryStoreReviewResolveAction",
|
|
"pub struct MemoryStoreReviewResolveParams",
|
|
"pub struct MemoryResetResponse",
|
|
"pub struct MemoryStoreListResponse",
|
|
"pub struct MemoryStoreReadResponse",
|
|
"pub struct MemoryStoreSearchResponse",
|
|
"pub struct MemoryStoreAddNoteResponse",
|
|
"pub struct MemoryStoreConsolidateResponse",
|
|
"pub struct MemoryStoreReviewNote",
|
|
"pub struct MemoryStoreReviewListResponse",
|
|
"pub struct MemoryStoreReviewResolveResponse",
|
|
"pub struct MemoryStoreHealthResponse",
|
|
"method: METHOD_KNOWLEDGE_PACK_LIST,",
|
|
"method: METHOD_KNOWLEDGE_PACK_READ,",
|
|
"method: METHOD_SCHEDULED_TASK_LIST,",
|
|
"method: METHOD_PROJECT_MEMORY_READ,",
|
|
"method: METHOD_MEMORY_STORE_LIST,",
|
|
"method: METHOD_MEMORY_STORE_READ,",
|
|
"method: METHOD_MEMORY_STORE_SEARCH,",
|
|
"method: METHOD_MEMORY_STORE_ADD_NOTE,",
|
|
"method: METHOD_MEMORY_STORE_CONSOLIDATE,",
|
|
"method: METHOD_MEMORY_STORE_REVIEW_LIST,",
|
|
"method: METHOD_MEMORY_STORE_REVIEW_RESOLVE,",
|
|
"method: METHOD_MEMORY_STORE_HEALTH,",
|
|
"method: METHOD_MEMORY_STORE_INDEX_REBUILD,",
|
|
"KnowledgeListPacksParams",
|
|
"KnowledgeListPacksResponse",
|
|
"KnowledgeReadPackParams",
|
|
"KnowledgeReadPackResponse",
|
|
"ScheduledTaskListResponse",
|
|
"ProjectMemoryReadParams",
|
|
"ProjectMemoryReadResponse",
|
|
"MemoryStoreListParams",
|
|
"MemoryStoreReadParams",
|
|
"MemoryStoreSearchParams",
|
|
"MemoryStoreAddNoteParams",
|
|
"MemoryStoreConsolidateParams",
|
|
"MemoryStoreReviewListParams",
|
|
"MemoryStoreReviewResolveAction",
|
|
"MemoryStoreReviewResolveParams",
|
|
"MemoryResetResponse",
|
|
"MemoryStoreListResponse",
|
|
"MemoryStoreReadResponse",
|
|
"MemoryStoreSearchResponse",
|
|
"MemoryStoreAddNoteResponse",
|
|
"MemoryStoreConsolidateResponse",
|
|
"MemoryStoreReviewNote",
|
|
"MemoryStoreReviewListResponse",
|
|
"MemoryStoreReviewResolveResponse",
|
|
"MemoryStoreHealthResponse",
|
|
],
|
|
absentSnippets: [
|
|
"UnifiedMemory",
|
|
"unifiedMemory/list",
|
|
"unifiedMemory/create",
|
|
"unifiedMemory/update",
|
|
"unifiedMemory/delete",
|
|
"unifiedMemory/search",
|
|
"unifiedMemory/stats",
|
|
"unifiedMemory/analyze",
|
|
"unifiedMemory/semanticSearch",
|
|
"METHOD_AUTOMATION_",
|
|
"AutomationJobListResponse",
|
|
"automationJob/",
|
|
"automationSchedule/",
|
|
"automationScheduler/",
|
|
"unifiedMemory/hybridSearch",
|
|
"METHOD_PLUGIN_INSTALLED_LIST",
|
|
"METHOD_PLUGIN_HOST_LIFECYCLE_LIST",
|
|
"METHOD_PLUGIN_SHELL_PREPARE",
|
|
"METHOD_PLUGIN_UI_RUNTIME_START",
|
|
"METHOD_PLUGIN_UI_RUNTIME_STATUS",
|
|
"METHOD_PLUGIN_UI_RUNTIME_STOP",
|
|
'"pluginInstalled/list"',
|
|
'"pluginHostLifecycle/list"',
|
|
'"pluginShell/prepare"',
|
|
'"pluginUiRuntime/start"',
|
|
'"pluginUiRuntime/status"',
|
|
'"pluginUiRuntime/stop"',
|
|
"PluginInstalledListResponse",
|
|
"PluginShellPrepareParams",
|
|
"PluginUiRuntimeStartParams",
|
|
"PluginUiRuntimeStatusParams",
|
|
"PluginUiRuntimeStopParams",
|
|
"PluginUiRuntimeStatusResponse",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust App Server runtime and data source expose current app data surface",
|
|
files: [
|
|
"lime-rs/crates/app-server/src/runtime.rs",
|
|
"lime-rs/crates/app-server/src/runtime/plugins.rs",
|
|
"lime-rs/crates/app-server/src/runtime/app_data.rs",
|
|
"lime-rs/crates/app-server/src/runtime/automation.rs",
|
|
"lime-rs/crates/app-server/src/runtime/knowledge.rs",
|
|
"lime-rs/crates/app-server/src/runtime/memory.rs",
|
|
"lime-rs/crates/app-server/src/local_data_source.rs",
|
|
"lime-rs/crates/app-server/src/local_data_source/automation.rs",
|
|
"lime-rs/crates/app-server/src/local_data_source/impls/plugins.rs",
|
|
"lime-rs/crates/app-server/src/local_data_source/impls/automation_overview.rs",
|
|
"lime-rs/crates/app-server/src/local_data_source/impls/memory.rs",
|
|
"lime-rs/crates/app-server/src/local_data_source/knowledge.rs",
|
|
],
|
|
snippets: [
|
|
"async fn list_knowledge_packs(",
|
|
"params: KnowledgeListPacksParams",
|
|
"Result<KnowledgeListPacksResponse, RuntimeCoreError>",
|
|
"async fn read_knowledge_pack(",
|
|
"params: KnowledgeReadPackParams",
|
|
"Result<KnowledgeReadPackResponse, RuntimeCoreError>",
|
|
"async fn import_knowledge_source(",
|
|
"params: KnowledgeImportSourceParams",
|
|
"Result<KnowledgeImportSourceResponse, RuntimeCoreError>",
|
|
"async fn compile_knowledge_pack(",
|
|
"params: KnowledgeCompilePackParams",
|
|
"Result<KnowledgeCompilePackResponse, RuntimeCoreError>",
|
|
"async fn set_default_knowledge_pack(",
|
|
"params: KnowledgeSetDefaultPackParams",
|
|
"async fn update_knowledge_pack_status(",
|
|
"params: KnowledgeUpdatePackStatusParams",
|
|
"async fn resolve_knowledge_context(",
|
|
"params: KnowledgeResolveContextParams",
|
|
"async fn validate_knowledge_context_run(",
|
|
"params: KnowledgeValidateContextRunParams",
|
|
"async fn list_scheduled_tasks(",
|
|
"Result<ScheduledTaskListResponse, RuntimeCoreError>",
|
|
"async fn read_project_memory(",
|
|
"params: ProjectMemoryReadParams",
|
|
"Result<ProjectMemoryReadResponse, RuntimeCoreError>",
|
|
"async fn list_memory_store(",
|
|
"params: MemoryStoreListParams",
|
|
"Result<MemoryStoreListResponse, RuntimeCoreError>",
|
|
"async fn read_memory_store(",
|
|
"params: MemoryStoreReadParams",
|
|
"Result<MemoryStoreReadResponse, RuntimeCoreError>",
|
|
"async fn search_memory_store(",
|
|
"params: MemoryStoreSearchParams",
|
|
"Result<MemoryStoreSearchResponse, RuntimeCoreError>",
|
|
"async fn add_memory_store_note(",
|
|
"params: MemoryStoreAddNoteParams",
|
|
"Result<MemoryStoreAddNoteResponse, RuntimeCoreError>",
|
|
"async fn consolidate_memory_store(",
|
|
"params: MemoryStoreConsolidateParams",
|
|
"Result<MemoryStoreConsolidateResponse, RuntimeCoreError>",
|
|
"async fn list_memory_store_review_notes(",
|
|
"params: MemoryStoreReviewListParams",
|
|
"Result<MemoryStoreReviewListResponse, RuntimeCoreError>",
|
|
"async fn resolve_memory_store_review_note(",
|
|
"params: MemoryStoreReviewResolveParams",
|
|
"Result<MemoryStoreReviewResolveResponse, RuntimeCoreError>",
|
|
"async fn health_memory_store(",
|
|
"params: MemoryStoreRootParams",
|
|
"Result<MemoryStoreHealthResponse, RuntimeCoreError>",
|
|
"async fn reset_memory(&self) -> Result<(), RuntimeCoreError>",
|
|
"self.app_data_source.list_knowledge_packs(params).await",
|
|
"self.app_data_source.read_knowledge_pack(params).await",
|
|
"self.app_data_source.import_knowledge_source(params).await",
|
|
"lime_knowledge::plan_knowledge_builder_runtime(&request)",
|
|
"self.knowledge_builder_runtime_executor",
|
|
"self.app_data_source.compile_knowledge_pack(request).await",
|
|
".set_default_knowledge_pack(params)",
|
|
".update_knowledge_pack_status(params)",
|
|
"self.app_data_source.resolve_knowledge_context(params).await",
|
|
".validate_knowledge_context_run(params)",
|
|
"self.app_data_source.list_scheduled_tasks(params).await",
|
|
"self.app_data_source.read_project_memory(params).await",
|
|
"self.app_data_source.list_memory_store(params).await",
|
|
"self.app_data_source.read_memory_store(params).await",
|
|
"self.app_data_source.search_memory_store(params).await",
|
|
"self.app_data_source.add_memory_store_note(params).await",
|
|
"self.app_data_source.consolidate_memory_store(params).await",
|
|
"self.app_data_source.health_memory_store(params).await",
|
|
"self.app_data_source.reset_memory().await",
|
|
"lime_knowledge::list_knowledge_packs(lime_knowledge::KnowledgeListPacksRequest",
|
|
"lime_knowledge::get_knowledge_pack(lime_knowledge::KnowledgeGetPackRequest",
|
|
"lime_knowledge::import_knowledge_source(lime_knowledge::KnowledgeImportSourceRequest",
|
|
"lime_knowledge::compile_knowledge_pack(request)",
|
|
"lime_knowledge::set_default_knowledge_pack(",
|
|
"lime_knowledge::update_knowledge_pack_status(",
|
|
"lime_knowledge::resolve_knowledge_context(",
|
|
"lime_knowledge::validate_knowledge_context_run(",
|
|
"automation::list_scheduled_tasks(&self.db, params)",
|
|
"lime_core::memory::read_project_memory(self.db.clone(), ¶ms.project_id)",
|
|
"LocalMemoryBackend::new(data_root)",
|
|
"memory_backend: Arc<dyn MemoryBackend>",
|
|
],
|
|
absentSnippets: [
|
|
"list_plugin_installed",
|
|
"prepare_plugin_shell",
|
|
"start_plugin_ui_runtime",
|
|
"plugin_ui_runtime_status",
|
|
"stop_plugin_ui_runtime",
|
|
"PluginInstalledListResponse",
|
|
"PluginShellPrepareParams",
|
|
"PluginUiRuntimeStartParams",
|
|
"PluginUiRuntimeStatusParams",
|
|
"PluginUiRuntimeStopParams",
|
|
"PluginUiRuntimeStatusResponse",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust JSON-RPC router dispatches current app data surface into RuntimeCore",
|
|
files: appServerProcessorFiles,
|
|
snippets: [
|
|
"METHOD_KNOWLEDGE_PACK_LIST => self.handle_knowledge_pack_list_impl(params).await",
|
|
"METHOD_KNOWLEDGE_PACK_READ => self.handle_knowledge_pack_read_impl(params).await",
|
|
"METHOD_KNOWLEDGE_SOURCE_IMPORT =>",
|
|
"METHOD_KNOWLEDGE_PACK_COMPILE =>",
|
|
"METHOD_KNOWLEDGE_PACK_DEFAULT_SET =>",
|
|
"METHOD_KNOWLEDGE_PACK_STATUS_UPDATE =>",
|
|
"METHOD_KNOWLEDGE_CONTEXT_RESOLVE =>",
|
|
"self.handle_knowledge_context_resolve_impl(params).await",
|
|
"METHOD_KNOWLEDGE_CONTEXT_RUN_VALIDATE =>",
|
|
"METHOD_SCHEDULED_TASK_LIST => self.handle_scheduled_task_list_impl(params).boxed()",
|
|
"METHOD_PROJECT_MEMORY_READ => self.handle_project_memory_read_impl(params).await",
|
|
"METHOD_MEMORY_STORE_LIST => self.handle_memory_store_list_impl(params).await",
|
|
"METHOD_MEMORY_STORE_READ => self.handle_memory_store_read_impl(params).await",
|
|
"METHOD_MEMORY_STORE_SEARCH => self.handle_memory_store_search_impl(params).await",
|
|
"METHOD_MEMORY_STORE_ADD_NOTE =>",
|
|
"METHOD_MEMORY_STORE_CONSOLIDATE =>",
|
|
"METHOD_MEMORY_STORE_HEALTH => self.handle_memory_store_health_impl(params).await",
|
|
"METHOD_MEMORY_RESET => {",
|
|
"self.handle_memory_reset_impl().boxed()",
|
|
"METHOD_MEMORY_STORE_INDEX_REBUILD =>",
|
|
"let params: KnowledgeListPacksParams = parse_params(params)?",
|
|
".list_knowledge_packs(params)",
|
|
"let params: KnowledgeReadPackParams = parse_params(params)?",
|
|
".read_knowledge_pack(params)",
|
|
"let params: KnowledgeImportSourceParams = parse_params(params)?",
|
|
".import_knowledge_source(params)",
|
|
"let params: KnowledgeCompilePackParams = parse_params(params)?",
|
|
".compile_knowledge_pack(params)",
|
|
"let params: KnowledgeSetDefaultPackParams = parse_params(params)?",
|
|
".set_default_knowledge_pack(params)",
|
|
"let params: KnowledgeUpdatePackStatusParams = parse_params(params)?",
|
|
".update_knowledge_pack_status(params)",
|
|
"let params: KnowledgeResolveContextParams = parse_params(params)?",
|
|
".resolve_knowledge_context(params)",
|
|
"let params: KnowledgeValidateContextRunParams = parse_params(params)?",
|
|
".validate_knowledge_context_run(params)",
|
|
"async fn handle_scheduled_task_list_impl(",
|
|
".list_scheduled_tasks(params)",
|
|
"let params: ProjectMemoryReadParams = parse_params(params)?",
|
|
".read_project_memory(params)",
|
|
"let params: MemoryStoreListParams = parse_params(params)?",
|
|
".list_memory_store(params)",
|
|
"let params: MemoryStoreReadParams = parse_params(params)?",
|
|
".read_memory_store(params)",
|
|
"let params: MemoryStoreSearchParams = parse_params(params)?",
|
|
".search_memory_store(params)",
|
|
"let params: MemoryStoreAddNoteParams = parse_params(params)?",
|
|
".add_memory_store_note(params)",
|
|
"let params: MemoryStoreConsolidateParams = parse_params(params)?",
|
|
".consolidate_memory_store(params)",
|
|
"let params: MemoryStoreReviewListParams = parse_params(params)?",
|
|
".list_memory_store_review_notes(params)",
|
|
"let params: MemoryStoreReviewResolveParams = parse_params(params)?",
|
|
".resolve_memory_store_review_note(params)",
|
|
"let params: MemoryStoreRootParams = parse_params(params)?",
|
|
".health_memory_store(params)",
|
|
"async fn handle_memory_reset_impl(&self)",
|
|
"self.runtime.reset_memory().await",
|
|
],
|
|
absentSnippets: [
|
|
"mod unified;",
|
|
"processor/unified.rs",
|
|
'METHOD_MEMORY_STORE_RESET: &str = "memoryStore/reset"',
|
|
"MemoryStoreResetParams",
|
|
"MemoryStoreResetResponse",
|
|
"handle_memory_store_reset_impl",
|
|
"reset_memory_store",
|
|
"METHOD_PLUGIN_INSTALLED_LIST",
|
|
"METHOD_PLUGIN_SHELL_PREPARE",
|
|
"METHOD_PLUGIN_UI_RUNTIME_START",
|
|
"METHOD_PLUGIN_UI_RUNTIME_STATUS",
|
|
"METHOD_PLUGIN_UI_RUNTIME_STOP",
|
|
"handle_plugin_installed_list_impl",
|
|
"handle_plugin_shell_prepare_impl",
|
|
"handle_plugin_ui_runtime_start_impl",
|
|
"handle_plugin_ui_runtime_status_impl",
|
|
"handle_plugin_ui_runtime_stop_impl",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust app-server-client exposes typed helpers for current app data surface",
|
|
file: "lime-rs/crates/app-server-client/src/lib.rs",
|
|
snippets: [
|
|
"pub use app_server_protocol::KnowledgeListPacksParams",
|
|
"pub use app_server_protocol::KnowledgeListPacksResponse",
|
|
"pub use app_server_protocol::KnowledgeReadPackParams",
|
|
"pub use app_server_protocol::KnowledgeReadPackResponse",
|
|
"pub use app_server_protocol::KnowledgeImportSourceParams",
|
|
"pub use app_server_protocol::KnowledgeImportSourceResponse",
|
|
"pub use app_server_protocol::KnowledgeCompilePackParams",
|
|
"pub use app_server_protocol::KnowledgeCompilePackResponse",
|
|
"pub use app_server_protocol::KnowledgeSetDefaultPackParams",
|
|
"pub use app_server_protocol::KnowledgeSetDefaultPackResponse",
|
|
"pub use app_server_protocol::KnowledgeUpdatePackStatusParams",
|
|
"pub use app_server_protocol::KnowledgeUpdatePackStatusResponse",
|
|
"pub use app_server_protocol::KnowledgeResolveContextParams",
|
|
"pub use app_server_protocol::KnowledgeContextResolutionResponse",
|
|
"pub use app_server_protocol::KnowledgeValidateContextRunParams",
|
|
"pub use app_server_protocol::KnowledgeValidateContextRunResponse",
|
|
"pub use app_server_protocol::ProjectMemoryReadParams",
|
|
"pub use app_server_protocol::ProjectMemoryReadResponse",
|
|
"pub use app_server_protocol::MemoryStoreListParams",
|
|
"pub use app_server_protocol::MemoryStoreReadParams",
|
|
"pub use app_server_protocol::MemoryStoreSearchParams",
|
|
"pub use app_server_protocol::MemoryStoreAddNoteParams",
|
|
"pub use app_server_protocol::MemoryStoreConsolidateParams",
|
|
"pub use app_server_protocol::MemoryStoreReviewListParams",
|
|
"pub use app_server_protocol::MemoryStoreReviewResolveAction",
|
|
"pub use app_server_protocol::MemoryStoreReviewResolveParams",
|
|
"pub use app_server_protocol::MemoryResetResponse",
|
|
"pub use app_server_protocol::MemoryStoreListResponse",
|
|
"pub use app_server_protocol::MemoryStoreReadResponse",
|
|
"pub use app_server_protocol::MemoryStoreSearchResponse",
|
|
"pub use app_server_protocol::MemoryStoreAddNoteResponse",
|
|
"pub use app_server_protocol::MemoryStoreConsolidateResponse",
|
|
"pub use app_server_protocol::MemoryStoreReviewNote",
|
|
"pub use app_server_protocol::MemoryStoreReviewListResponse",
|
|
"pub use app_server_protocol::MemoryStoreReviewResolveResponse",
|
|
"pub use app_server_protocol::MemoryStoreHealthResponse",
|
|
"pub use app_server_protocol::METHOD_KNOWLEDGE_PACK_LIST",
|
|
"pub use app_server_protocol::METHOD_KNOWLEDGE_PACK_READ",
|
|
"pub use app_server_protocol::METHOD_PROJECT_MEMORY_READ",
|
|
"pub use app_server_protocol::METHOD_MEMORY_STORE_LIST",
|
|
"pub use app_server_protocol::METHOD_MEMORY_STORE_READ",
|
|
"pub use app_server_protocol::METHOD_MEMORY_STORE_SEARCH",
|
|
"pub use app_server_protocol::METHOD_MEMORY_STORE_ADD_NOTE",
|
|
"pub use app_server_protocol::METHOD_MEMORY_STORE_CONSOLIDATE",
|
|
"pub use app_server_protocol::METHOD_MEMORY_STORE_HEALTH",
|
|
"pub use app_server_protocol::METHOD_MEMORY_RESET",
|
|
"pub use app_server_protocol::METHOD_MEMORY_STORE_INDEX_REBUILD",
|
|
"pub fn list_knowledge_packs(",
|
|
"pub fn read_knowledge_pack(",
|
|
"pub fn read_project_memory(",
|
|
"pub fn list_memory_store(",
|
|
"pub fn read_memory_store(",
|
|
"pub fn search_memory_store(",
|
|
"pub fn add_memory_store_note(",
|
|
"pub fn consolidate_memory_store(",
|
|
"pub fn health_memory_store(",
|
|
"pub fn reset_memory(&mut self)",
|
|
"TypedRequest::new(METHOD_KNOWLEDGE_PACK_LIST, params)",
|
|
"TypedRequest::new(METHOD_KNOWLEDGE_PACK_READ, params)",
|
|
"TypedRequest::new(METHOD_KNOWLEDGE_SOURCE_IMPORT, params)",
|
|
"TypedRequest::new(METHOD_KNOWLEDGE_PACK_COMPILE, params)",
|
|
"TypedRequest::new(METHOD_KNOWLEDGE_PACK_DEFAULT_SET, params)",
|
|
"TypedRequest::new(METHOD_KNOWLEDGE_PACK_STATUS_UPDATE, params)",
|
|
"TypedRequest::new(METHOD_KNOWLEDGE_CONTEXT_RESOLVE, params)",
|
|
"TypedRequest::new(METHOD_KNOWLEDGE_CONTEXT_RUN_VALIDATE, params)",
|
|
"TypedRequest::new(METHOD_PROJECT_MEMORY_READ, params)",
|
|
"TypedRequest::new(METHOD_MEMORY_STORE_LIST, params)",
|
|
"TypedRequest::new(METHOD_MEMORY_STORE_READ, params)",
|
|
"TypedRequest::new(METHOD_MEMORY_STORE_SEARCH, params)",
|
|
"TypedRequest::new(METHOD_MEMORY_STORE_ADD_NOTE, params)",
|
|
"TypedRequest::new(METHOD_MEMORY_STORE_CONSOLIDATE, params)",
|
|
"TypedRequest::new(METHOD_MEMORY_STORE_HEALTH, params)",
|
|
"TypedRequest::new(METHOD_MEMORY_RESET, serde_json::json!({}))",
|
|
"TypedRequest::new(METHOD_MEMORY_STORE_INDEX_REBUILD, params)",
|
|
"fn app_data_surface_helpers_use_current_methods()",
|
|
],
|
|
absentSnippets: [
|
|
"PluginInstalledListResponse",
|
|
"PluginLocalPackageExportParams",
|
|
"PluginLocalPackageExportResponse",
|
|
"PluginShellPrepareParams",
|
|
"PluginUiRuntimeStartParams",
|
|
"PluginUiRuntimeStatusParams",
|
|
"PluginUiRuntimeStopParams",
|
|
"METHOD_PLUGIN_INSTALLED_LIST",
|
|
"METHOD_PLUGIN_LOCAL_PACKAGE_EXPORT",
|
|
"METHOD_PLUGIN_SHELL_PREPARE",
|
|
"METHOD_PLUGIN_UI_RUNTIME_START",
|
|
"METHOD_PLUGIN_UI_RUNTIME_STATUS",
|
|
"METHOD_PLUGIN_UI_RUNTIME_STOP",
|
|
"list_plugin_installed",
|
|
"export_plugin_local_package",
|
|
"prepare_plugin_shell",
|
|
"plugin_ui_runtime",
|
|
"AutomationJob",
|
|
"AutomationSchedule",
|
|
"AutomationScheduler",
|
|
"METHOD_AUTOMATION_",
|
|
"automation_job",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript app-server-client mirrors current app data surface",
|
|
files: [
|
|
"packages/app-server-client/src/protocol.ts",
|
|
"packages/app-server-client/src/generated/protocol-types.ts",
|
|
"packages/app-server-client/src/index.ts",
|
|
"packages/app-server-client/tests/client.test.mjs",
|
|
],
|
|
snippets: [
|
|
'export const METHOD_KNOWLEDGE_PACK_LIST = "knowledgePack/list"',
|
|
'export const METHOD_KNOWLEDGE_PACK_READ = "knowledgePack/read"',
|
|
'export const METHOD_KNOWLEDGE_SOURCE_IMPORT = "knowledgePack/source/import"',
|
|
'export const METHOD_KNOWLEDGE_PACK_COMPILE = "knowledgePack/compile"',
|
|
'export const METHOD_KNOWLEDGE_PACK_DEFAULT_SET = "knowledgePack/default/set"',
|
|
"export const METHOD_KNOWLEDGE_PACK_STATUS_UPDATE =",
|
|
'export const METHOD_KNOWLEDGE_CONTEXT_RESOLVE = "knowledgeContext/resolve"',
|
|
"export const METHOD_KNOWLEDGE_CONTEXT_RUN_VALIDATE =",
|
|
'export const METHOD_SCHEDULED_TASK_LIST = "scheduledTask/list"',
|
|
'export const METHOD_PROJECT_MEMORY_READ = "projectMemory/read"',
|
|
'export const METHOD_MEMORY_STORE_LIST = "memoryStore/list"',
|
|
'export const METHOD_MEMORY_STORE_READ = "memoryStore/read"',
|
|
'export const METHOD_MEMORY_STORE_SEARCH = "memoryStore/search"',
|
|
'export const METHOD_MEMORY_STORE_ADD_NOTE = "memoryStore/addNote"',
|
|
'export const METHOD_MEMORY_STORE_CONSOLIDATE = "memoryStore/consolidate"',
|
|
'export const METHOD_MEMORY_STORE_REVIEW_LIST = "memoryStore/review/list"',
|
|
"export const METHOD_MEMORY_STORE_REVIEW_RESOLVE =",
|
|
'export const METHOD_MEMORY_STORE_HEALTH = "memoryStore/health"',
|
|
'export const METHOD_MEMORY_RESET = "memory/reset"',
|
|
'export const METHOD_MEMORY_STORE_INDEX_REBUILD = "memoryStore/index/rebuild"',
|
|
"export type KnowledgeListPacksParams",
|
|
"export type KnowledgeListPacksResponse",
|
|
"export type KnowledgeReadPackParams",
|
|
"export type KnowledgeReadPackResponse",
|
|
"export type KnowledgeImportSourceParams",
|
|
"export type KnowledgeImportSourceResponse",
|
|
"export type KnowledgeCompilePackParams",
|
|
"export type KnowledgeCompilePackResponse",
|
|
"export type KnowledgeSetDefaultPackParams",
|
|
"export type KnowledgeSetDefaultPackResponse",
|
|
"export type KnowledgeUpdatePackStatusParams",
|
|
"export type KnowledgeUpdatePackStatusResponse",
|
|
"export type KnowledgeResolveContextParams",
|
|
"export type KnowledgeContextResolutionResponse",
|
|
"export type KnowledgeValidateContextRunParams",
|
|
"export type KnowledgeValidateContextRunResponse",
|
|
"export interface ScheduledTaskListResponse",
|
|
"export type ProjectMemoryReadParams",
|
|
"export type ProjectMemoryReadResponse",
|
|
"export interface MemoryStoreListParams",
|
|
"export interface MemoryStoreReadParams",
|
|
"export interface MemoryStoreSearchParams",
|
|
"export interface MemoryStoreAddNoteParams",
|
|
"export interface MemoryStoreConsolidateParams",
|
|
"export interface MemoryStoreReviewListParams",
|
|
"export type MemoryStoreReviewResolveAction",
|
|
"export interface MemoryStoreReviewResolveParams",
|
|
"export type MemoryResetResponse",
|
|
"export interface MemoryStoreListResponse",
|
|
"export interface MemoryStoreReadResponse",
|
|
"export interface MemoryStoreSearchResponse",
|
|
"export interface MemoryStoreAddNoteResponse",
|
|
"export interface MemoryStoreConsolidateResponse",
|
|
"export interface MemoryStoreReviewNote",
|
|
"export interface MemoryStoreReviewListResponse",
|
|
"export interface MemoryStoreReviewResolveResponse",
|
|
"export interface MemoryStoreHealthResponse",
|
|
"listKnowledgePacks(params: protocol.KnowledgeListPacksParams): protocol.JsonRpcRequest",
|
|
"readKnowledgePack(params: protocol.KnowledgeReadPackParams): protocol.JsonRpcRequest",
|
|
"importKnowledgeSource(params: protocol.KnowledgeImportSourceParams): protocol.JsonRpcRequest",
|
|
"compileKnowledgePack(params: protocol.KnowledgeCompilePackParams): protocol.JsonRpcRequest",
|
|
"setDefaultKnowledgePack(",
|
|
"updateKnowledgePackStatus(",
|
|
"resolveKnowledgeContext(",
|
|
"validateKnowledgeContextRun(",
|
|
"readProjectMemory(params: protocol.ProjectMemoryReadParams): protocol.JsonRpcRequest",
|
|
"listMemoryStore(params: protocol.MemoryStoreListParams): protocol.JsonRpcRequest",
|
|
"readMemoryStore(params: protocol.MemoryStoreReadParams): protocol.JsonRpcRequest",
|
|
"searchMemoryStore(params: protocol.MemoryStoreSearchParams): protocol.JsonRpcRequest",
|
|
"addMemoryStoreNote(params: protocol.MemoryStoreAddNoteParams): protocol.JsonRpcRequest",
|
|
"consolidateMemoryStore(params: protocol.MemoryStoreConsolidateParams): protocol.JsonRpcRequest",
|
|
"listMemoryStoreReviewNotes(",
|
|
"resolveMemoryStoreReviewNote(",
|
|
"healthMemoryStore(params: protocol.MemoryStoreRootParams): protocol.JsonRpcRequest",
|
|
"resetMemory(): protocol.JsonRpcRequest",
|
|
"builds app data surface requests with current methods",
|
|
"assert.equal(knowledge.method, METHOD_KNOWLEDGE_PACK_LIST)",
|
|
"assert.equal(knowledgeDetail.method, METHOD_KNOWLEDGE_PACK_READ)",
|
|
"assert.equal(importedKnowledgeSource.method, METHOD_KNOWLEDGE_SOURCE_IMPORT)",
|
|
"assert.equal(compiledKnowledgePack.method, METHOD_KNOWLEDGE_PACK_COMPILE)",
|
|
"assert.equal(defaultKnowledgePack.method, METHOD_KNOWLEDGE_PACK_DEFAULT_SET)",
|
|
"METHOD_KNOWLEDGE_PACK_STATUS_UPDATE",
|
|
"assert.equal(knowledgeContext.method, METHOD_KNOWLEDGE_CONTEXT_RESOLVE)",
|
|
"METHOD_KNOWLEDGE_CONTEXT_RUN_VALIDATE",
|
|
"assert.equal(memory.method, METHOD_PROJECT_MEMORY_READ)",
|
|
"assert.equal(memoryStoreList.method, METHOD_MEMORY_STORE_LIST)",
|
|
"assert.equal(memoryStoreRead.method, METHOD_MEMORY_STORE_READ)",
|
|
"assert.equal(memoryStoreSearch.method, METHOD_MEMORY_STORE_SEARCH)",
|
|
"assert.equal(memoryStoreAddNote.method, METHOD_MEMORY_STORE_ADD_NOTE)",
|
|
"assert.equal(memoryStoreConsolidate.method, METHOD_MEMORY_STORE_CONSOLIDATE)",
|
|
"assert.equal(memoryStoreReviewList.method, METHOD_MEMORY_STORE_REVIEW_LIST)",
|
|
"memoryStoreReviewResolve.method",
|
|
"METHOD_MEMORY_STORE_REVIEW_RESOLVE",
|
|
"assert.equal(memoryStoreHealth.method, METHOD_MEMORY_STORE_HEALTH)",
|
|
"assert.equal(memoryReset.method, METHOD_MEMORY_RESET)",
|
|
"METHOD_MEMORY_STORE_INDEX_REBUILD",
|
|
],
|
|
absentSnippets: [
|
|
"METHOD_UNIFIED_MEMORY",
|
|
"UnifiedMemory",
|
|
"unifiedMemory/",
|
|
"listUnifiedMemories(",
|
|
"createUnifiedMemory(",
|
|
"updateUnifiedMemory(",
|
|
"METHOD_AUTOMATION_",
|
|
"AutomationJobListResponse",
|
|
"listAutomationJobs",
|
|
"automationJob/",
|
|
"automationSchedule/",
|
|
"automationScheduler/",
|
|
"deleteUnifiedMemory(",
|
|
'METHOD_MEMORY_STORE_RESET = "memoryStore/reset"',
|
|
"MemoryStoreResetParams",
|
|
"MemoryStoreResetResponse",
|
|
"resetMemoryStore(",
|
|
"METHOD_PLUGIN_INSTALLED_LIST",
|
|
"METHOD_PLUGIN_HOST_LIFECYCLE_LIST",
|
|
"METHOD_PLUGIN_SHELL_PREPARE",
|
|
"METHOD_PLUGIN_UI_RUNTIME_START",
|
|
"METHOD_PLUGIN_UI_RUNTIME_STATUS",
|
|
"METHOD_PLUGIN_UI_RUNTIME_STOP",
|
|
"PluginInstalledListResponse",
|
|
"PluginShellPrepareParams",
|
|
"PluginUiRuntimeStartParams",
|
|
"PluginUiRuntimeStatusParams",
|
|
"PluginUiRuntimeStopParams",
|
|
"listPluginInstalled(",
|
|
"startPluginUiRuntime(",
|
|
"getPluginUiRuntimeStatus(",
|
|
"stopPluginUiRuntime(",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer project memory aggregate read uses App Server projectMemory/read",
|
|
file: "src/lib/api/projectMemory.ts",
|
|
snippets: [
|
|
'import { AppServerClient } from "@/lib/api/appServer"',
|
|
"METHOD_PROJECT_MEMORY_READ",
|
|
'from "../../../packages/app-server-client/src/protocol"',
|
|
'export type ProjectMemoryAppServerClient = Pick<AppServerClient, "request">',
|
|
"type ProjectMemoryReadResponse = Omit<",
|
|
"AppServerProjectMemoryReadResponse",
|
|
"memory?: ProjectMemory | null",
|
|
"projectId is required to read App Server project memory",
|
|
"const appServerClient = options.appServerClient ?? new AppServerClient()",
|
|
"appServerClient.request<ProjectMemoryReadResponse>",
|
|
"METHOD_PROJECT_MEMORY_READ",
|
|
"{ projectId: normalizedProjectId }",
|
|
"App Server projectMemory/read did not return project memory",
|
|
"projectMemoryCache.set(normalizedProjectId",
|
|
"projectMemoryInflight.set(normalizedProjectId",
|
|
],
|
|
absentSnippets: [
|
|
'"project_memory_get"',
|
|
'const APP_SERVER_METHOD_PROJECT_MEMORY_READ = "projectMemory/read"',
|
|
"safeInvoke<ProjectMemory>",
|
|
"invokeMockOnly",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer project memory tests lock App Server current path and no legacy fallback",
|
|
file: "src/lib/api/projectMemory.test.ts",
|
|
snippets: [
|
|
"createProjectMemoryClient",
|
|
"ProjectMemoryAppServerClient",
|
|
"projectMemory/read",
|
|
"并发读取同一项目上下文时应复用同一个 projectMemory/read",
|
|
"项目上下文读取缺少 projectId 时应 fail closed",
|
|
"App Server 未返回项目上下文时不应返回空对象",
|
|
"projectId is required to read App Server project memory",
|
|
"App Server projectMemory/read did not return project memory",
|
|
],
|
|
},
|
|
{
|
|
name: "Workspace Right Surface uses App Server current JSON-RPC contract",
|
|
files: [
|
|
...rustProtocolFiles,
|
|
...appServerRuntimeFiles,
|
|
...appServerProcessorFiles,
|
|
"lime-rs/crates/app-server-client/src/lib.rs",
|
|
"packages/app-server-client/src/protocol.ts",
|
|
"packages/app-server-client/src/generated/protocol-types.ts",
|
|
"packages/app-server-client/src/index.ts",
|
|
"packages/app-server-client/tests/client.test.mjs",
|
|
"src/lib/api/appServer.ts",
|
|
"src/lib/api/appServer.test.ts",
|
|
"src/lib/api/workspaceRightSurface.ts",
|
|
"src/lib/api/workspaceRightSurface.test.ts",
|
|
"src/lib/governance/agentCommandCatalog.json",
|
|
],
|
|
snippets: [
|
|
'pub const METHOD_WORKSPACE_RIGHT_SURFACE_REQUEST: &str = "workspaceRightSurface/request"',
|
|
'"workspaceRightSurface/pending/list"',
|
|
'"workspaceRightSurface/pending/consume"',
|
|
'"workspaceRightSurface/pending/dismiss"',
|
|
'"workspaceRightSurface/pendingChanged"',
|
|
"pub struct WorkspaceRightSurfaceRequestParams",
|
|
"pub struct WorkspaceRightSurfacePendingListParams",
|
|
"pub struct WorkspaceRightSurfacePendingConsumeParams",
|
|
"pub struct WorkspaceRightSurfacePendingDismissParams",
|
|
"pub struct WorkspaceRightSurfacePendingRequest",
|
|
"pub struct WorkspaceRightSurfaceRequestResponse",
|
|
"pub struct WorkspaceRightSurfacePendingListResponse",
|
|
"pub struct WorkspaceRightSurfacePendingConsumeResponse",
|
|
"pub struct WorkspaceRightSurfacePendingDismissResponse",
|
|
"pub struct WorkspaceRightSurfacePendingChangedParams",
|
|
"method: METHOD_WORKSPACE_RIGHT_SURFACE_REQUEST,",
|
|
"method: METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_LIST,",
|
|
"method: METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_CONSUME,",
|
|
"method: METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_DISMISS,",
|
|
"method: METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_CHANGED,",
|
|
"request_workspace_right_surface(",
|
|
"list_workspace_right_surface_pending(",
|
|
"consume_workspace_right_surface_pending(",
|
|
"dismiss_workspace_right_surface_pending(",
|
|
"METHOD_WORKSPACE_RIGHT_SURFACE_REQUEST =>",
|
|
"METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_LIST =>",
|
|
"METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_CONSUME =>",
|
|
"METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_DISMISS =>",
|
|
"handle_workspace_right_surface_request_impl",
|
|
"handle_workspace_right_surface_pending_list_impl",
|
|
"handle_workspace_right_surface_pending_consume_impl",
|
|
"handle_workspace_right_surface_pending_dismiss_impl",
|
|
"pub use app_server_protocol::WorkspaceRightSurfaceRequestParams",
|
|
"pub use app_server_protocol::WorkspaceRightSurfacePendingConsumeParams",
|
|
"pub use app_server_protocol::WorkspaceRightSurfacePendingDismissParams",
|
|
"pub use app_server_protocol::WorkspaceRightSurfacePendingChangedParams",
|
|
"pub use app_server_protocol::METHOD_WORKSPACE_RIGHT_SURFACE_REQUEST",
|
|
"pub use app_server_protocol::METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_CONSUME",
|
|
"pub use app_server_protocol::METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_DISMISS",
|
|
"pub use app_server_protocol::METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_CHANGED",
|
|
"export const METHOD_WORKSPACE_RIGHT_SURFACE_REQUEST =",
|
|
"METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_CONSUME",
|
|
"METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_DISMISS",
|
|
"METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_CHANGED",
|
|
"export interface WorkspaceRightSurfaceRequestParams",
|
|
"export interface WorkspaceRightSurfacePendingListResponse",
|
|
"export interface WorkspaceRightSurfacePendingConsumeResponse",
|
|
"export interface WorkspaceRightSurfacePendingDismissResponse",
|
|
"export interface WorkspaceRightSurfacePendingChangedParams",
|
|
"workspaceRightSurfacePendingChangedNotification(",
|
|
"requestWorkspaceRightSurface(",
|
|
"listWorkspaceRightSurfacePending(",
|
|
"consumeWorkspaceRightSurfacePending(",
|
|
"dismissWorkspaceRightSurfacePending(",
|
|
"APP_SERVER_METHOD_WORKSPACE_RIGHT_SURFACE_REQUEST",
|
|
"APP_SERVER_METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_CONSUME",
|
|
"APP_SERVER_METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_DISMISS",
|
|
"APP_SERVER_METHOD_WORKSPACE_RIGHT_SURFACE_PENDING_CHANGED",
|
|
'import { AppServerClient } from "@/lib/api/appServer"',
|
|
"export type WorkspaceRightSurfaceAppServerClient = Pick<",
|
|
"App Server workspaceRightSurface/request did not return a valid pending request",
|
|
"App Server workspaceRightSurface/pending/list did not return valid pending requests",
|
|
"App Server workspaceRightSurface/pending/consume did not return consumed request ids",
|
|
"App Server workspaceRightSurface/pending/dismiss did not return dismissed request ids",
|
|
"workspaceRightSurface methods 应通过 App Server JSON-RPC 调度右侧 surface",
|
|
"Right Surface 请求应走 App Server current method",
|
|
'"appServerWorkspaceRightSurfaceMethods"',
|
|
'"workspaceRightSurface/request"',
|
|
'"workspaceRightSurface/pending/list"',
|
|
'"workspaceRightSurface/pending/consume"',
|
|
'"workspaceRightSurface/pending/dismiss"',
|
|
'"workspaceRightSurface/pendingChanged"',
|
|
],
|
|
absentSnippets: [
|
|
'"agent_runtime_request_right_surface"',
|
|
'"right_surface_request"',
|
|
"invokeMockOnly",
|
|
"defaultMocks",
|
|
"mockPriorityCommands",
|
|
],
|
|
},
|
|
{
|
|
name: "Retired Browser Session protocol stays out of current contracts",
|
|
files: [
|
|
...rustProtocolFiles,
|
|
...appServerRuntimeFiles,
|
|
...appServerProcessorFiles,
|
|
"lime-rs/Cargo.toml",
|
|
"lime-rs/crates/app-server/Cargo.toml",
|
|
"packages/app-server-client/src/generated/protocol-types.ts",
|
|
"packages/app-server-client/src/request-client.ts",
|
|
"packages/app-server-client/src/request-client-methods.ts",
|
|
"packages/app-server-client/src/connection-methods.ts",
|
|
"packages/app-server-client/tests/client.test.mjs",
|
|
"src/lib/governance/agentCommandCatalog.json",
|
|
],
|
|
snippets: [],
|
|
absentSnippets: [
|
|
"browserSession/",
|
|
"METHOD_BROWSER_SESSION",
|
|
"BrowserSessionTargetListParams",
|
|
"BrowserSessionOpenParams",
|
|
"BrowserSessionActionExecuteParams",
|
|
"listBrowserSessionTargets",
|
|
"openBrowserSession",
|
|
"executeBrowserSessionAction",
|
|
"lime-browser-runtime",
|
|
"lime_browser_runtime",
|
|
'"appServerBrowserSessionMethods"',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer project workspace read and ensure use App Server current methods",
|
|
file: "src/lib/api/project.ts",
|
|
snippets: [
|
|
'import { AppServerClient } from "@/lib/api/appServer"',
|
|
"METHOD_WORKSPACE_LIST",
|
|
"METHOD_WORKSPACE_READ",
|
|
"METHOD_WORKSPACE_BY_PATH_READ",
|
|
"METHOD_WORKSPACE_ENSURE",
|
|
"METHOD_WORKSPACE_DEFAULT_READ",
|
|
"METHOD_WORKSPACE_DEFAULT_ENSURE",
|
|
"METHOD_WORKSPACE_PROJECTS_ROOT_READ",
|
|
"METHOD_WORKSPACE_PROJECT_PATH_RESOLVE",
|
|
"METHOD_WORKSPACE_ENSURE_READY",
|
|
'from "../../../packages/app-server-client/src/protocol"',
|
|
'type ProjectAppServerClient = Pick<AppServerClient, "request">',
|
|
"async function requestProjectAppServer<T>",
|
|
"appServerClient.request<T>(method, params)",
|
|
"return response.result",
|
|
"METHOD_WORKSPACE_PROJECTS_ROOT_READ",
|
|
"METHOD_WORKSPACE_PROJECT_PATH_RESOLVE",
|
|
"METHOD_WORKSPACE_LIST",
|
|
"METHOD_WORKSPACE_DEFAULT_READ",
|
|
"METHOD_WORKSPACE_ENSURE",
|
|
"METHOD_WORKSPACE_ENSURE_READY",
|
|
"METHOD_WORKSPACE_DEFAULT_ENSURE",
|
|
"METHOD_WORKSPACE_BY_PATH_READ",
|
|
"METHOD_WORKSPACE_READ",
|
|
"workspace id is required to ensure App Server workspace",
|
|
"workspace rootPath is required to ensure project",
|
|
"App Server workspace/projectsRoot/read did not return rootPath",
|
|
"App Server workspace/projectPath/resolve did not return rootPath",
|
|
"App Server workspace/ensure did not return workspace",
|
|
"App Server workspace/ensureReady did not return result",
|
|
"App Server workspace/default/ensure did not return workspace",
|
|
],
|
|
absentSnippets: [
|
|
'const APP_SERVER_METHOD_WORKSPACE_LIST = "workspace/list"',
|
|
'"workspace_get_projects_root"',
|
|
'"workspace_resolve_project_path"',
|
|
'"workspace_get_by_path"',
|
|
'"workspace_get_default"',
|
|
'"workspace_ensure_ready"',
|
|
'"workspace_ensure_default_ready"',
|
|
'"get_or_create_default_project"',
|
|
'"workspace_list"',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer project workspace tests lock App Server current path and no legacy fallback",
|
|
file: "src/lib/api/project.test.ts",
|
|
snippets: [
|
|
"appServerRequestMock",
|
|
'vi.mock("@/lib/api/appServer"',
|
|
"应该通过 App Server 获取 workspace 根目录",
|
|
"应该通过 App Server 解析项目目录",
|
|
"应该通过 App Server 按路径获取项目",
|
|
"应该通过 App Server ensure 本地项目工作区",
|
|
"应该通过 App Server 获取并标准化默认项目",
|
|
"应该通过 App Server 确保工作区目录就绪",
|
|
"确保默认工作区目录就绪时应先 ensure 默认 workspace 再 ensureReady",
|
|
"workspace read/ensure 缺少必需 App Server result 时不应回退 legacy",
|
|
"ensureWorkspaceReady 缺少 workspace id 时应 fail closed",
|
|
'"workspace/projectsRoot/read"',
|
|
'"workspace/projectPath/resolve"',
|
|
'"workspace/byPath/read"',
|
|
'"workspace/ensure"',
|
|
'"workspace/default/read"',
|
|
'"workspace/default/ensure"',
|
|
'"workspace/ensureReady"',
|
|
'"workspace/list"',
|
|
'"workspace/read"',
|
|
'"workspace_get_projects_root"',
|
|
'"workspace_resolve_project_path"',
|
|
'"workspace_ensure_ready"',
|
|
'"get_or_create_default_project"',
|
|
"expect(safeInvoke).not.toHaveBeenCalledWith(",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer model registry reads use App Server current methods",
|
|
file: "src/lib/api/modelRegistry.ts",
|
|
snippets: [
|
|
'import { AppServerClient } from "@/lib/api/appServer"',
|
|
"METHOD_MODEL_LIST",
|
|
"METHOD_MODEL_PREFERENCES_LIST",
|
|
"METHOD_MODEL_PROVIDER_ALIAS_LIST",
|
|
"METHOD_MODEL_PROVIDER_ALIAS_READ",
|
|
"METHOD_MODEL_PROVIDER_FETCH_MODELS",
|
|
"METHOD_MODEL_SYNC_STATE_READ",
|
|
'from "../../../packages/app-server-client/src/protocol"',
|
|
'type ModelRegistryAppServerClient = Pick<AppServerClient, "request">',
|
|
"async function requestModelRegistryAppServer<T>",
|
|
"appServerClient.request<T>(method, params)",
|
|
"return response.result",
|
|
"async function readModelsFromAppServer(",
|
|
"METHOD_MODEL_LIST",
|
|
"METHOD_MODEL_PREFERENCES_LIST",
|
|
"METHOD_MODEL_SYNC_STATE_READ",
|
|
"METHOD_MODEL_PROVIDER_ALIAS_READ",
|
|
"METHOD_MODEL_PROVIDER_ALIAS_LIST",
|
|
"METHOD_MODEL_PROVIDER_FETCH_MODELS",
|
|
"App Server model/list did not return data",
|
|
"response.nextCursor",
|
|
"includeHidden",
|
|
"App Server modelPreferences/list did not return preferences",
|
|
"App Server modelSyncState/read did not return syncState",
|
|
"App Server modelProviderAlias/list did not return configs",
|
|
],
|
|
absentSnippets: [
|
|
'"get_model_registry"',
|
|
'"get_model_preferences"',
|
|
'"get_model_sync_state"',
|
|
'"get_models_for_provider"',
|
|
'"get_models_by_tier"',
|
|
'"get_provider_alias_config"',
|
|
'"get_all_alias_configs"',
|
|
'"fetch_provider_models_auto"',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer model registry tests lock App Server current path and no legacy fallback",
|
|
file: "src/lib/api/modelRegistry.test.ts",
|
|
snippets: [
|
|
"appServerRequestMock",
|
|
'vi.mock("@/lib/api/appServer"',
|
|
"getModelRegistry 应缓存并复用同一轮读取结果",
|
|
"getModelRegistry 应聚合 model/list 的全部分页",
|
|
"getModelRegistry 遇到重复 cursor 时应 fail closed",
|
|
"getModelRegistry 应隔离默认目录与 includeHidden 缓存",
|
|
"模型偏好与同步状态读取应走 App Server current",
|
|
"单个 provider alias 应通过 App Server 读取并缓存",
|
|
"App Server 模型读链缺少必需 result 时不应回退 legacy",
|
|
'"model/list"',
|
|
'"modelPreferences/list"',
|
|
'"modelSyncState/read"',
|
|
'"modelProviderAlias/read"',
|
|
'"modelProviderAlias/list"',
|
|
'"modelProvider/fetchModels"',
|
|
"App Server model/list did not return data",
|
|
"App Server model/list repeated cursor: 1",
|
|
"includeHidden: true",
|
|
"App Server modelPreferences/list did not return preferences",
|
|
"App Server modelSyncState/read did not return syncState",
|
|
"App Server modelProviderAlias/list did not return configs",
|
|
"expect(safeInvoke).not.toHaveBeenCalledWith(",
|
|
'"get_model_registry"',
|
|
'"get_model_preferences"',
|
|
'"get_model_sync_state"',
|
|
'"get_all_alias_configs"',
|
|
'"fetch_provider_models_auto"',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer API key provider uses App Server modelProvider methods",
|
|
file: "src/lib/api/apiKeyProvider.ts",
|
|
snippets: [
|
|
'import { AppServerClient } from "@/lib/api/appServer"',
|
|
"METHOD_MODEL_PROVIDER_CATALOG_LIST",
|
|
"METHOD_MODEL_PROVIDER_CONFIG_EXPORT",
|
|
"METHOD_MODEL_PROVIDER_CONFIG_IMPORT",
|
|
"METHOD_MODEL_PROVIDER_CREATE",
|
|
"METHOD_MODEL_PROVIDER_DELETE",
|
|
"METHOD_MODEL_PROVIDER_KEY_CREATE",
|
|
"METHOD_MODEL_PROVIDER_KEY_DELETE",
|
|
"METHOD_MODEL_PROVIDER_KEY_UPDATE",
|
|
"METHOD_MODEL_PROVIDER_LIST",
|
|
"METHOD_MODEL_PROVIDER_READ",
|
|
"METHOD_MODEL_PROVIDER_SORT_ORDERS_UPDATE",
|
|
"METHOD_MODEL_PROVIDER_TEST_CHAT",
|
|
"METHOD_MODEL_PROVIDER_TEST_CONNECTION",
|
|
"METHOD_MODEL_PROVIDER_UI_STATE_READ",
|
|
"METHOD_MODEL_PROVIDER_UI_STATE_WRITE",
|
|
"METHOD_MODEL_PROVIDER_UPDATE",
|
|
'from "../../../packages/app-server-client/src/protocol"',
|
|
'type ApiKeyProviderAppServerClient = Pick<AppServerClient, "request">',
|
|
"async function requestApiKeyProviderAppServer<T>",
|
|
"appServerClient.request<T>(method, params)",
|
|
"return response.result",
|
|
"function normalizeModelProviderListResponse(",
|
|
"function normalizeModelProviderCatalogListResponse(",
|
|
"METHOD_MODEL_PROVIDER_LIST",
|
|
"METHOD_MODEL_PROVIDER_CATALOG_LIST",
|
|
"App Server modelProvider/list did not return providers",
|
|
"App Server modelProvider/catalog/list did not return providers",
|
|
],
|
|
absentSnippets: [
|
|
'"get_api_key_providers"',
|
|
'"get_system_provider_catalog"',
|
|
'"get_api_key_provider"',
|
|
'"add_custom_api_key_provider"',
|
|
'"update_api_key_provider"',
|
|
'"delete_custom_api_key_provider"',
|
|
'"add_api_key"',
|
|
'"delete_api_key"',
|
|
'"toggle_api_key"',
|
|
'"update_api_key_alias"',
|
|
'"get_next_api_key"',
|
|
'"record_api_key_usage"',
|
|
'"record_api_key_error"',
|
|
'"modelProviderKey/next"',
|
|
'"modelProviderKey/usage/record"',
|
|
'"modelProviderKey/error/record"',
|
|
'"get_provider_ui_state"',
|
|
'"set_provider_ui_state"',
|
|
'"update_provider_sort_orders"',
|
|
'"export_api_key_providers"',
|
|
'"import_api_key_providers"',
|
|
'"test_api_key_provider_connection"',
|
|
'"test_api_key_provider_chat"',
|
|
'safeInvoke<ProviderWithKeysDisplay[]>("get_api_key_providers"',
|
|
'safeInvoke("get_system_provider_catalog"',
|
|
"safeInvoke(",
|
|
"invokeMockOnly",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer API key provider tests lock App Server current read/write path",
|
|
file: "src/lib/api/apiKeyProvider.test.ts",
|
|
snippets: [
|
|
"appServerRequestMock",
|
|
'vi.mock("@/lib/api/appServer"',
|
|
"Provider 列表应通过 App Server modelProvider/list 读取",
|
|
"系统 Provider Catalog 应通过 App Server modelProvider/catalog/list 读取",
|
|
"Provider 读链缺少必需 result 时不应回退 legacy",
|
|
"Provider 读取失败时不应注入本地 mock 或写入缓存",
|
|
"写操作成功后应失效缓存",
|
|
'"modelProvider/list"',
|
|
'"modelProvider/catalog/list"',
|
|
'"modelProviderKey/create"',
|
|
'"modelProvider/testConnection"',
|
|
"App Server modelProvider/list did not return providers",
|
|
"App Server modelProvider/catalog/list did not return providers",
|
|
"expect(safeInvoke).not.toHaveBeenCalledWith(",
|
|
'"get_api_key_providers"',
|
|
'"get_system_provider_catalog"',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer knowledge gateway uses App Server Knowledge current methods",
|
|
file: "src/lib/api/knowledge.ts",
|
|
snippets: [
|
|
'import { AppServerClient } from "@/lib/api/appServer"',
|
|
"METHOD_KNOWLEDGE_PACK_LIST",
|
|
"METHOD_KNOWLEDGE_PACK_READ",
|
|
"METHOD_KNOWLEDGE_SOURCE_IMPORT",
|
|
"METHOD_KNOWLEDGE_PACK_COMPILE",
|
|
"METHOD_KNOWLEDGE_PACK_DEFAULT_SET",
|
|
"METHOD_KNOWLEDGE_PACK_STATUS_UPDATE",
|
|
"METHOD_KNOWLEDGE_CONTEXT_RESOLVE",
|
|
"METHOD_KNOWLEDGE_CONTEXT_RUN_VALIDATE",
|
|
'from "../../../packages/app-server-client/src/protocol"',
|
|
'export type KnowledgeAppServerClient = Pick<AppServerClient, "request">',
|
|
"async function requestKnowledgeAppServer<T>",
|
|
"appServerClient.request<T>(method, params)",
|
|
"return response.result",
|
|
"function normalizeKnowledgeListPacksResponse(",
|
|
"function normalizeKnowledgeReadPackResponse(",
|
|
"function normalizeKnowledgeImportSourceResponse(",
|
|
"function normalizeKnowledgeCompilePackResponse(",
|
|
"function normalizeKnowledgeSetDefaultPackResponse(",
|
|
"function normalizeKnowledgeUpdatePackStatusResponse(",
|
|
"function normalizeKnowledgeContextResolutionResponse(",
|
|
"function normalizeKnowledgeValidateContextRunResponse(",
|
|
"workingDir is required to list App Server knowledge packs",
|
|
"workingDir is required to read App Server knowledge pack",
|
|
"name is required to read App Server knowledge pack",
|
|
"workingDir is required to import App Server knowledge source",
|
|
"workingDir is required to compile App Server knowledge pack",
|
|
"METHOD_KNOWLEDGE_PACK_LIST",
|
|
"METHOD_KNOWLEDGE_PACK_READ",
|
|
"METHOD_KNOWLEDGE_SOURCE_IMPORT",
|
|
"METHOD_KNOWLEDGE_PACK_COMPILE",
|
|
"METHOD_KNOWLEDGE_PACK_DEFAULT_SET",
|
|
"METHOD_KNOWLEDGE_PACK_STATUS_UPDATE",
|
|
"METHOD_KNOWLEDGE_CONTEXT_RESOLVE",
|
|
"METHOD_KNOWLEDGE_CONTEXT_RUN_VALIDATE",
|
|
"workingDir: normalizedWorkingDir",
|
|
"name: normalizedName",
|
|
"includeArchived: request.includeArchived ?? false",
|
|
"App Server knowledgePack/list did not return packs",
|
|
"App Server knowledgePack/list did not return rootPath",
|
|
"App Server knowledgePack/list did not return workingDir",
|
|
"App Server knowledgePack/read did not return pack",
|
|
],
|
|
absentSnippets: [
|
|
'"knowledge_list_packs"',
|
|
'"knowledge_get_pack"',
|
|
'"knowledge_import_source"',
|
|
'"knowledge_compile_pack"',
|
|
'"knowledge_set_default_pack"',
|
|
'"knowledge_update_pack_status"',
|
|
'"knowledge_resolve_context"',
|
|
'"knowledge_validate_context_run"',
|
|
'safeInvoke("knowledge_list_packs"',
|
|
'safeInvoke("knowledge_get_pack"',
|
|
"safeInvoke",
|
|
"invokeKnowledgeCommand",
|
|
"invokeMockOnly",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer knowledge tests lock App Server current path and no legacy fallback",
|
|
file: "src/lib/api/knowledge.test.ts",
|
|
snippets: [
|
|
"appServerRequestMock",
|
|
'vi.mock("@/lib/api/appServer"',
|
|
"知识包列表应通过 App Server knowledgePack/list 读取",
|
|
"应通过 App Server current 网关代理全部知识包命令",
|
|
'"knowledgePack/read"',
|
|
'"knowledgePack/source/import"',
|
|
'"knowledgePack/compile"',
|
|
'"knowledgePack/default/set"',
|
|
'"knowledgePack/status/update"',
|
|
'"knowledgeContext/resolve"',
|
|
'"knowledgeContextRun/validate"',
|
|
"知识包列表应透传 includeArchived 到 App Server",
|
|
"知识包列表缺少 workingDir 时应 fail closed",
|
|
"App Server 知识包列表缺少 packs 时应 fail closed",
|
|
"App Server Knowledge 详情缺少 pack 时应 fail closed",
|
|
'"knowledgePack/list"',
|
|
"workingDir is required to list App Server knowledge packs",
|
|
"App Server knowledgePack/list did not return packs",
|
|
"knowledgePack/read did not return a knowledge pack detail",
|
|
],
|
|
absentSnippets: [
|
|
"safeInvoke",
|
|
'"knowledge_get_pack"',
|
|
'"knowledge_import_source"',
|
|
'"knowledge_compile_pack"',
|
|
'"knowledge_set_default_pack"',
|
|
'"knowledge_update_pack_status"',
|
|
'"knowledge_resolve_context"',
|
|
'"knowledge_validate_context_run"',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer skill execution reads use App Server skills/list and skill/read",
|
|
file: "src/lib/api/skill-execution.ts",
|
|
snippets: [
|
|
'import { AppServerClient } from "@/lib/api/appServer"',
|
|
"METHOD_SKILLS_LIST",
|
|
"METHOD_SKILL_READ",
|
|
'from "../../../packages/app-server-client/src/protocol"',
|
|
'type SkillExecutionAppServerClient = Pick<AppServerClient, "request">',
|
|
"async function requestSkillExecutionAppServer<T>",
|
|
"appServerClient.request<T>(method, params)",
|
|
"return response.result",
|
|
"function normalizeSkillListResponse(",
|
|
"function normalizeSkillReadResponse(",
|
|
"METHOD_SKILLS_LIST",
|
|
"METHOD_SKILL_READ",
|
|
"App Server skills/list did not return data",
|
|
"App Server skill/read did not return skill",
|
|
],
|
|
absentSnippets: [
|
|
"executeSkill",
|
|
"EXECUTE_SKILL_RETIRED_ERROR",
|
|
"ExecuteSkillRequest",
|
|
"SkillExecutionResult",
|
|
"skill:step_start",
|
|
"skill:step_complete",
|
|
"skill:step_error",
|
|
"skill:complete",
|
|
"safeInvoke",
|
|
"invokeSkillExecutionCommand",
|
|
'safeInvoke("list_executable_skills"',
|
|
'safeInvoke("get_skill_detail"',
|
|
'safeInvoke("execute_skill"',
|
|
"invokeMockOnly",
|
|
"METHOD_SKILL_LIST",
|
|
'"skill/list"',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer skill execution tests lock App Server current read path and retired execute boundary",
|
|
file: "src/lib/api/skill-execution.test.ts",
|
|
snippets: [
|
|
"appServerRequestMock",
|
|
'vi.mock("@/lib/api/appServer"',
|
|
"可执行 Skill 列表应通过 App Server skills/list 读取并过滤禁用项",
|
|
"Skill 详情应通过 App Server skill/read 读取",
|
|
"App Server Skill 读链缺少必需 result 时不应回退 legacy",
|
|
"Skill 独立执行 API 不再暴露 executeSkill",
|
|
'"skills/list"',
|
|
'"skill/read"',
|
|
"App Server skills/list did not return data",
|
|
"App Server skill/read did not return skill",
|
|
"expect(safeInvoke).not.toHaveBeenCalledWith(",
|
|
'"list_executable_skills"',
|
|
'"get_skill_detail"',
|
|
],
|
|
absentSnippets: [
|
|
"Skill 执行 side-effect 仍保持 Desktop compat 命令",
|
|
'toHaveBeenCalledWith("execute_skill"',
|
|
"EXECUTE_SKILL_RETIRED_ERROR",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer slash skill command parser stays execution-free",
|
|
file: "src/components/agent/chat/hooks/skillCommand.ts",
|
|
snippets: [
|
|
"export interface ParsedSkillCommand",
|
|
"export function parseSkillSlashCommand(",
|
|
"Skill 执行必须走 Agent Runtime turn / SkillTool current 主链",
|
|
],
|
|
absentSnippets: [
|
|
"tryExecuteSlashSkillCommand",
|
|
"skillExecutionApi",
|
|
"safeListen",
|
|
"execute_skill",
|
|
"skill:step_start",
|
|
"skill-exec-",
|
|
"SKILL_INLINE_PROCESS_RETENTION",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer slash skill command tests stay parser-only",
|
|
file: "src/components/agent/chat/hooks/skillCommand.test.ts",
|
|
snippets: [
|
|
'describe("parseSkillSlashCommand"',
|
|
"解析英文 slash skill 与参数",
|
|
"中文 scene slash 不应被旧 slash skill 解析器误判",
|
|
],
|
|
absentSnippets: [
|
|
"tryExecuteSlashSkillCommand",
|
|
"executeSkill",
|
|
"safeListen",
|
|
"execute_skill",
|
|
"skill-exec-",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Plugin catalog uses current App Server JSON-RPC methods",
|
|
files: [
|
|
"src/lib/api/pluginCatalog.ts",
|
|
"src/lib/api/appServerClientMethods.ts",
|
|
"src/lib/api/appServerClientMethodSpecs.ts",
|
|
"src/lib/api/appServerConstants.ts",
|
|
"packages/app-server-client/src/request-client.ts",
|
|
"packages/app-server-client/src/request-client-methods.ts",
|
|
"packages/app-server-client/src/generated/protocol-types.ts",
|
|
],
|
|
snippets: [
|
|
"listPluginCatalog",
|
|
"searchPlugins",
|
|
"readPluginCatalog",
|
|
"installPluginCatalog",
|
|
"uninstallPluginCatalog",
|
|
"listInstalledPluginCatalog",
|
|
"setPluginCatalogEnabled",
|
|
"METHOD_PLUGIN_LIST",
|
|
"METHOD_PLUGIN_SEARCH",
|
|
"METHOD_PLUGIN_READ",
|
|
"METHOD_PLUGIN_INSTALL",
|
|
"METHOD_PLUGIN_UNINSTALL",
|
|
"METHOD_PLUGIN_INSTALLED",
|
|
"METHOD_PLUGIN_ENABLED_SET",
|
|
'"plugin/list"',
|
|
'"plugin/search"',
|
|
'"plugin/read"',
|
|
'"plugin/install"',
|
|
'"plugin/uninstall"',
|
|
'"plugin/installed"',
|
|
'"plugin/enabled/set"',
|
|
],
|
|
absentSnippets: [
|
|
"pluginInstalled/list",
|
|
"pluginHostLifecycle/list",
|
|
"pluginShell/prepare",
|
|
"pluginUiRuntime/start",
|
|
"pluginUiRuntime/status",
|
|
"pluginUiRuntime/stop",
|
|
"pluginLocalPackage/inspect",
|
|
"pluginLocalPackage/export",
|
|
"pluginPackage/fetchCloud",
|
|
"pluginInstalled/save",
|
|
"pluginInstalled/disabled/set",
|
|
"pluginInstalled/uninstall/rehearsal",
|
|
"pluginInstalled/uninstall",
|
|
"plugin_runtime_",
|
|
"plugin_worker",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Scheduled Tasks gateway uses current App Server methods",
|
|
file: "src/lib/api/scheduledTasks.ts",
|
|
snippets: [
|
|
'import { AppServerClient } from "@/lib/api/appServer"',
|
|
"METHOD_SCHEDULED_TASK_LIST",
|
|
"METHOD_SCHEDULED_TASK_READ",
|
|
"METHOD_SCHEDULED_TASK_CREATE",
|
|
"METHOD_SCHEDULED_TASK_UPDATE",
|
|
"METHOD_SCHEDULED_TASK_DELETE",
|
|
"METHOD_SCHEDULED_TASK_ENABLED_SET",
|
|
"METHOD_SCHEDULED_TASK_RUN_START",
|
|
"METHOD_SCHEDULED_TASK_RUN_LIST",
|
|
"METHOD_SCHEDULED_TASK_SCHEDULE_PREVIEW",
|
|
'from "../../../packages/app-server-client/src/protocol"',
|
|
'type ScheduledTaskAppServerClient = Pick<AppServerClient, "request">',
|
|
"async function requestScheduledTask<T>",
|
|
"client.request<T>(method, params)",
|
|
"return response.result",
|
|
"createScheduledTasksApi",
|
|
"did not return items",
|
|
"did not return runs",
|
|
],
|
|
absentSnippets: [
|
|
"safeInvoke",
|
|
"invokeMockOnly",
|
|
"METHOD_AUTOMATION_",
|
|
"automationJob/",
|
|
"automationSchedule/",
|
|
"automationScheduler/",
|
|
"getAutomationJobs",
|
|
"createAutomationJob",
|
|
"runAutomationJobNow",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Scheduled Tasks tests lock current methods and fail-closed validation",
|
|
file: "src/lib/api/scheduledTasks.test.ts",
|
|
snippets: [
|
|
'describe("scheduledTasks gateway"',
|
|
"通过 exact App Server method 读取任务目录",
|
|
"创建时保留 typed task envelope",
|
|
"运行历史形状无效时 fail closed",
|
|
"只投影严格的 typed Scheduled Task notifications",
|
|
"METHOD_SCHEDULED_TASK_LIST",
|
|
"METHOD_SCHEDULED_TASK_CREATE",
|
|
"METHOD_SCHEDULED_TASK_RUN_LIST",
|
|
],
|
|
absentSnippets: [
|
|
"safeInvoke",
|
|
"METHOD_AUTOMATION_",
|
|
"automationJob/",
|
|
"automationSchedule/",
|
|
"automationScheduler/",
|
|
"get_automation_jobs",
|
|
"create_automation_job",
|
|
"run_automation_job_now",
|
|
],
|
|
},
|
|
{
|
|
name: "Electron Desktop Host keeps retired Plugin and Knowledge facades out of the current bridge",
|
|
files: ["electron/hostCommands.ts", "electron/ipcChannels.ts"],
|
|
snippets: [],
|
|
absentSnippets: [
|
|
"plugin_runtime_start_task",
|
|
"plugin_runtime_get_task",
|
|
"plugin_runtime_cancel_task",
|
|
"plugin_runtime_submit_host_response",
|
|
"plugin_start_ui_runtime",
|
|
"plugin_get_ui_runtime_status",
|
|
"plugin_stop_ui_runtime",
|
|
"plugin_list_installed",
|
|
"plugin_save_installed_state",
|
|
"plugin_set_disabled",
|
|
"plugin_uninstall_rehearsal",
|
|
"plugin_uninstall",
|
|
"METHOD_PROJECT_MEMORY_READ",
|
|
'case "project_memory_get":',
|
|
"return await this.#readProjectMemory(args)",
|
|
"async #readProjectMemory(args: HostArgs)",
|
|
'"project_memory_get"',
|
|
"METHOD_KNOWLEDGE_PACK_LIST",
|
|
"METHOD_KNOWLEDGE_PACK_READ",
|
|
"METHOD_KNOWLEDGE_SOURCE_IMPORT",
|
|
"METHOD_KNOWLEDGE_PACK_COMPILE",
|
|
"METHOD_KNOWLEDGE_PACK_DEFAULT_SET",
|
|
"METHOD_KNOWLEDGE_PACK_STATUS_UPDATE",
|
|
"METHOD_KNOWLEDGE_CONTEXT_RESOLVE",
|
|
"METHOD_KNOWLEDGE_CONTEXT_RUN_VALIDATE",
|
|
'case "plugin_list_installed":',
|
|
"return await this.#listPluginInstalled()",
|
|
"async #listPluginInstalled()",
|
|
'"plugin_list_installed"',
|
|
'case "knowledge_list_packs":',
|
|
'case "knowledge_get_pack":',
|
|
'case "knowledge_import_source":',
|
|
'case "knowledge_compile_pack":',
|
|
'case "knowledge_set_default_pack":',
|
|
'case "knowledge_update_pack_status":',
|
|
'case "knowledge_resolve_context":',
|
|
'case "knowledge_validate_context_run":',
|
|
"return await this.#listKnowledgePacks(args)",
|
|
"return await this.#readKnowledgePack(args)",
|
|
"return await this.#importKnowledgeSource(args)",
|
|
"return await this.#compileKnowledgePack(args)",
|
|
"return await this.#setDefaultKnowledgePack(args)",
|
|
"return await this.#updateKnowledgePackStatus(args)",
|
|
"return await this.#resolveKnowledgeContext(args)",
|
|
"return await this.#validateKnowledgeContextRun(args)",
|
|
"async #listKnowledgePacks(args: HostArgs)",
|
|
"async #readKnowledgePack(args: HostArgs)",
|
|
"async #importKnowledgeSource(args: HostArgs)",
|
|
"async #compileKnowledgePack(args: HostArgs)",
|
|
"async #setDefaultKnowledgePack(args: HostArgs)",
|
|
"async #updateKnowledgePackStatus(args: HostArgs)",
|
|
"async #resolveKnowledgeContext(args: HostArgs)",
|
|
"async #validateKnowledgeContextRun(args: HostArgs)",
|
|
],
|
|
},
|
|
{
|
|
name: "Electron Desktop Host tests lock retired Knowledge legacy facade",
|
|
files: ["electron/hostCommands.test.ts", "electron/ipcChannels.test.ts"],
|
|
snippets: [
|
|
"ElectronHostCommands retired Knowledge legacy facade",
|
|
"已从 Electron Host 退场,生产只能走 App Server JSONL current",
|
|
"expect(isElectronHostCommand(command)).toBe(false)",
|
|
'"knowledge_list_packs"',
|
|
'"knowledge_get_pack"',
|
|
'"knowledge_import_source"',
|
|
'"knowledge_compile_pack"',
|
|
'"knowledge_set_default_pack"',
|
|
'"knowledge_update_pack_status"',
|
|
'"knowledge_resolve_context"',
|
|
'"knowledge_validate_context_run"',
|
|
],
|
|
absentSnippets: [
|
|
"METHOD_KNOWLEDGE_PACK_LIST",
|
|
"METHOD_KNOWLEDGE_PACK_READ",
|
|
"METHOD_KNOWLEDGE_SOURCE_IMPORT",
|
|
"METHOD_KNOWLEDGE_PACK_COMPILE",
|
|
"METHOD_KNOWLEDGE_PACK_DEFAULT_SET",
|
|
"METHOD_KNOWLEDGE_PACK_STATUS_UPDATE",
|
|
"METHOD_KNOWLEDGE_CONTEXT_RESOLVE",
|
|
"METHOD_KNOWLEDGE_CONTEXT_RUN_VALIDATE",
|
|
'case "knowledge_list_packs":',
|
|
'case "knowledge_get_pack":',
|
|
'case "knowledge_import_source":',
|
|
'case "knowledge_compile_pack":',
|
|
'case "knowledge_set_default_pack":',
|
|
'case "knowledge_update_pack_status":',
|
|
'case "knowledge_resolve_context":',
|
|
'case "knowledge_validate_context_run":',
|
|
"return await this.#listKnowledgePacks(args)",
|
|
"return await this.#readKnowledgePack(args)",
|
|
"return await this.#importKnowledgeSource(args)",
|
|
"return await this.#compileKnowledgePack(args)",
|
|
"return await this.#setDefaultKnowledgePack(args)",
|
|
"return await this.#updateKnowledgePackStatus(args)",
|
|
"return await this.#resolveKnowledgeContext(args)",
|
|
"return await this.#validateKnowledgeContextRun(args)",
|
|
"async #listKnowledgePacks(args: HostArgs)",
|
|
"async #readKnowledgePack(args: HostArgs)",
|
|
"async #importKnowledgeSource(args: HostArgs)",
|
|
"async #compileKnowledgePack(args: HostArgs)",
|
|
"async #setDefaultKnowledgePack(args: HostArgs)",
|
|
"async #updateKnowledgePackStatus(args: HostArgs)",
|
|
"async #resolveKnowledgeContext(args: HostArgs)",
|
|
"async #validateKnowledgeContextRun(args: HostArgs)",
|
|
],
|
|
},
|
|
{
|
|
name: "Electron Desktop Host automation legacy facade is retired",
|
|
files: [
|
|
"electron/hostCommands.ts",
|
|
"electron/hostCommands.test.ts",
|
|
"electron/ipcChannels.ts",
|
|
"electron/ipcChannels.test.ts",
|
|
],
|
|
snippets: [
|
|
'describe("ElectronHostCommands retired automation facade"',
|
|
"get_automation_scheduler_config",
|
|
"get_automation_status",
|
|
"get_automation_health",
|
|
"get_automation_jobs",
|
|
'isElectronHostCommand("get_automation_jobs")',
|
|
"toBe(false)",
|
|
],
|
|
absentSnippets: [
|
|
'case "get_automation_scheduler_config":',
|
|
'case "get_automation_status":',
|
|
'case "get_automation_job":',
|
|
'case "create_automation_job":',
|
|
'case "update_automation_job":',
|
|
'case "delete_automation_job":',
|
|
'case "run_automation_job_now":',
|
|
'case "get_automation_health":',
|
|
'case "get_automation_run_history":',
|
|
'case "preview_automation_schedule":',
|
|
'case "validate_automation_schedule":',
|
|
"return await this.#listAutomationJobs()",
|
|
"async #listAutomationJobs()",
|
|
],
|
|
},
|
|
{
|
|
name: "App Server exposes full Agent runtime tool inventory current method",
|
|
files: [
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/method_names.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/catalog.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/agent_session.rs",
|
|
"lime-rs/crates/app-server/src/processor/mod.rs",
|
|
"lime-rs/crates/app-server/src/processor/agent_session.rs",
|
|
"lime-rs/crates/app-server/src/processor/dispatch.rs",
|
|
"lime-rs/crates/app-server/src/runtime.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/execution_backend.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/tool_inventory.rs",
|
|
"lime-rs/crates/agent/src/agent_tools/inventory.rs",
|
|
"lime-rs/crates/agent/src/agent_tools/tool_inventory_runtime_snapshot.rs",
|
|
"packages/app-server-client/src/protocol.ts",
|
|
"packages/app-server-client/src/index.ts",
|
|
"src/lib/api/appServer.ts",
|
|
],
|
|
snippets: [
|
|
'METHOD_AGENT_SESSION_TOOL_INVENTORY_READ: &str = "agentSession/toolInventory/read"',
|
|
"method: METHOD_AGENT_SESSION_TOOL_INVENTORY_READ,",
|
|
"pub struct AgentSessionToolInventoryReadParams",
|
|
"pub struct AgentSessionToolInventoryReadResponse",
|
|
"METHOD_AGENT_SESSION_TOOL_INVENTORY_READ =>",
|
|
"handle_tool_inventory_read_impl",
|
|
"read_agent_session_tool_inventory",
|
|
"ToolInventoryReadRequest",
|
|
"async fn read_tool_inventory(",
|
|
"read_agent_tool_inventory_runtime_snapshot",
|
|
"build_tool_inventory(AgentToolInventoryBuildInput",
|
|
'METHOD_AGENT_SESSION_TOOL_INVENTORY_READ =\n "agentSession/toolInventory/read"',
|
|
"readAgentSessionToolInventory(",
|
|
"APP_SERVER_METHOD_AGENT_SESSION_TOOL_INVENTORY_READ",
|
|
],
|
|
},
|
|
{
|
|
name: "App Server session read projects runtime events into thread_read",
|
|
files: appServerRuntimeThreadReadProjectionFiles,
|
|
snippets: [
|
|
"let detail = read_model::runtime_session_read_detail_with_options(",
|
|
"detail: Some(detail)",
|
|
"pub(super) fn runtime_session_read_detail_with_options(",
|
|
"pub(super) fn from_params(params: &AgentSessionReadParams) -> Self",
|
|
"fn runtime_thread_read_from_stored_session_with_usage_events(",
|
|
"fn runtime_events_with_workflow_audit<'a>(",
|
|
"article_workspace: Option<serde_json::Value>",
|
|
'"thread_read": thread_read',
|
|
'"tool_calls": tool_item_projection::tool_calls_from_events(&stored.events)',
|
|
"items.extend(tool_item_projection::tool_items_from_events(stored))",
|
|
'"artifacts": artifact_projection::stored_artifact_summaries_for_turn(stored, None)',
|
|
'"outputs": output_refs::read_model_outputs(stored.output_blobs.values(), None)',
|
|
"pub(super) fn tool_calls_from_events(events: &[AgentEvent]) -> Vec<Value>",
|
|
"pub(super) fn tool_items_from_events(stored: &StoredSession) -> Vec<Value>",
|
|
"pub(super) fn current_tool_item_from_event(event: &AgentEvent) -> Option<CurrentToolItem>",
|
|
"fn apply_current_item(",
|
|
"ToolState::from_current_item(",
|
|
"self.tools[index].merge_current_item(event, item)",
|
|
'"item.started" | "item.updated" | "item.completed"',
|
|
"read_session_projects_runtime_events_into_thread_read_tool_calls",
|
|
"read_session_merges_tool_started_arguments_into_completed_tool_calls",
|
|
"canonical_tool_projection_does_not_downgrade_completed_item_with_late_update",
|
|
"read_session_keeps_workspace_patch_in_thread_read_artifacts_only",
|
|
'"artifact.snapshot"',
|
|
'"workspacePatch"',
|
|
'assert_eq!(web_fetch["status"], "completed")',
|
|
'assert_eq!(web_search["status"], "completed")',
|
|
'assert_eq!(artifacts[0]["artifactRef"], "artifact-content-batch")',
|
|
'assert_eq!(artifacts[0]["contentStatus"], "notRequested")',
|
|
],
|
|
absentSnippets: [
|
|
'tool_name: "WebFetch"',
|
|
'tool_name: "WebSearch"',
|
|
"success: true",
|
|
],
|
|
},
|
|
{
|
|
name: "App Server default capability source exposes current runtime tool catalog",
|
|
files: [
|
|
"lime-rs/crates/app-server/src/capability.rs",
|
|
"lime-rs/crates/app-server/src/runtime_factory.rs",
|
|
],
|
|
snippets: [
|
|
"lime_agent::agent_tools::catalog",
|
|
"tool_catalog_entries_for_surface",
|
|
"WorkspaceToolSurface::workbench()",
|
|
"ToolLifecycle::Current",
|
|
"pub fn default_current_surface() -> Self",
|
|
"current_tool_capability_record(tool.name)",
|
|
"fn current_tool_capability_record(tool_name: &str) -> CapabilityInventoryRecord",
|
|
'format!("tool.{tool_name}")',
|
|
"default_inventory_source_exposes_current_tool_capabilities",
|
|
"factory_default_mock_runtime_uses_inventory_capability_source",
|
|
'"tool.WebFetch"',
|
|
'"tool.WebSearch"',
|
|
],
|
|
absentSnippets: [
|
|
"workbench_with_browser_assist",
|
|
"APP_SERVER_BACKEND_MODE=mock",
|
|
'"backend": "mock"',
|
|
],
|
|
},
|
|
{
|
|
name: "Conversation import preserves tools after canonical Item lowering",
|
|
files: [
|
|
"lime-rs/crates/app-server/src/runtime/conversation_import/commit.rs",
|
|
"lime-rs/crates/app-server/src/runtime/conversation_import/codex/history_builder.rs",
|
|
"lime-rs/crates/app-server/src/runtime/conversation_import/codex/canonical_items.rs",
|
|
"lime-rs/crates/app-server/src/runtime/conversation_import/tests/runtime_events.rs",
|
|
],
|
|
snippets: [
|
|
"build_canonical_history_events",
|
|
"project_rollout_events_to_canonical",
|
|
'"item.started"',
|
|
'"item.completed"',
|
|
"commit_preserves_codex_tool_command_and_patch_timeline",
|
|
"commit_preserves_high_volume_codex_tool_events_in_canonical_projection",
|
|
"commit_preserves_imported_commands_across_turns_without_projection_budget",
|
|
"commit_preserves_imported_assistant_message_order_between_runtime_events",
|
|
"commit_delays_imported_turn_terminal_until_after_late_runtime_events",
|
|
"commit_preserves_imported_update_plan_timeline_item",
|
|
"commit_imports_user_and_agent_items_with_canonical_lifecycle",
|
|
"commit_projects_codex_runtime_specialized_items_into_existing_timeline_types",
|
|
"commit_closes_incomplete_imported_lifecycles_as_failed_timeline_items",
|
|
],
|
|
absentSnippets: ["lower_imported_runtime_events_for_commit"],
|
|
},
|
|
{
|
|
name: "Request tool policy validates required WebSearch from current item lifecycle",
|
|
files: agentRequestToolPolicyFiles,
|
|
snippets: [
|
|
"pub struct RequestToolPolicy",
|
|
"pub fn resolve_request_tool_policy_with_mode(",
|
|
"pub struct WebSearchExecutionTracker",
|
|
"record_tool_item",
|
|
"observed_item_lifecycle",
|
|
"validate_web_search_requirement",
|
|
],
|
|
absentSnippets: [
|
|
"PreflightSearchPlan",
|
|
"PlannedWebSearchQuery",
|
|
"build_preflight_queries",
|
|
"should_run_web_search_preflight",
|
|
".execute(&preflight_tool_name",
|
|
],
|
|
},
|
|
{
|
|
name: "Electron session history fixture proves v2 archive lifecycle and current history read path",
|
|
file: "scripts/electron/session-history-fixture-smoke.mjs",
|
|
snippets: [
|
|
"[smoke:agent-session-history-electron-fixture]",
|
|
"import { _electron as electron }",
|
|
"electron.launch({",
|
|
'"--use-mock-keychain"',
|
|
'APP_SERVER_BACKEND_MODE: "unavailable"',
|
|
'LIME_ELECTRON_DEV_HTTP_BRIDGE: "0"',
|
|
"window.__LIME_ELECTRON__ === true",
|
|
"window.electronAPI.supportsCommand",
|
|
'const APP_SERVER_HANDLE_JSON_LINES_COMMAND = "app_server_handle_json_lines"',
|
|
'"initialize"',
|
|
'"thread/start"',
|
|
'"thread/archive"',
|
|
'"thread/unarchive"',
|
|
'"thread/read"',
|
|
'"thread/list"',
|
|
'"thread/turns/list"',
|
|
'"thread/resume"',
|
|
"const FORBIDDEN_METHODS = [",
|
|
'"agentSession/update"',
|
|
'"agentSession/archiveMany"',
|
|
"SQLITE3_BINARY",
|
|
"launchElectronFixture",
|
|
"closeElectronFixture",
|
|
"runThreadArchivePhase",
|
|
"assertThreadArchivePhase",
|
|
"runThreadUnarchivePhase",
|
|
"assertThreadUnarchivePhase",
|
|
"findRolloutPaths",
|
|
"threadArchiveSummary",
|
|
"threadUnarchiveSummary",
|
|
"archivedRolloutPaths",
|
|
"restoredRolloutPaths",
|
|
"archivedRolloutPaths.active.length === 0",
|
|
"archivedRolloutPaths.archived.length === 1",
|
|
"restoredRolloutPaths.active.length === 1",
|
|
"restoredRolloutPaths.archived.length === 0",
|
|
"seedThreadReadPageIsomorphicCanonicalThread",
|
|
"runThreadReadPageIsomorphicReadPhase",
|
|
"runThreadReadPageIsomorphicDomOracle",
|
|
"LAST_PROJECT_ID_KEY",
|
|
"APP_SIDEBAR_COLLAPSED_STORAGE_KEY",
|
|
"databaseBootstrapRestart",
|
|
],
|
|
absentSnippets: [
|
|
'APP_SERVER_BACKEND_MODE: "mock"',
|
|
'APP_SERVER_BACKEND_MODE: "external"',
|
|
"APP_SERVER_BACKEND_COMMAND",
|
|
"--allow-live-provider",
|
|
"agent_runtime_",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
"invokeMockOnly",
|
|
'backendMode: "mock"',
|
|
'call("agentSession/update"',
|
|
'call("agentSession/archiveMany"',
|
|
],
|
|
},
|
|
{
|
|
name: "Electron code artifact workbench fixture proves App Server current artifact path",
|
|
file: "scripts/electron/code-artifact-workbench-fixture-smoke.mjs",
|
|
snippets: [
|
|
"[smoke:code-artifact-workbench-electron-fixture]",
|
|
"import { _electron as electron }",
|
|
"electron.launch({",
|
|
'"--use-mock-keychain"',
|
|
'APP_SERVER_BACKEND_MODE: "external"',
|
|
"APP_SERVER_BACKEND_COMMAND: process.execPath",
|
|
"writeFixtureBackend(",
|
|
"function persistBackendLedgerEvidence(",
|
|
"writeJsonFile(evidencePath",
|
|
'LIME_ELECTRON_DEV_HTTP_BRIDGE: "0"',
|
|
"window.__LIME_ELECTRON__ === true",
|
|
"window.electronAPI.supportsCommand",
|
|
'const APP_SERVER_HANDLE_JSON_LINES_COMMAND = "app_server_handle_json_lines"',
|
|
'"thread/start"',
|
|
'"turn/start"',
|
|
'"thread/read"',
|
|
'"thread/list"',
|
|
'type: "artifact.snapshot"',
|
|
'type: "turn.completed"',
|
|
'kind: "backendEvents"',
|
|
"backendEmittedEventTypes",
|
|
"backendEmittedCurrentTerminal",
|
|
"backendDidNotEmitLegacyTerminal",
|
|
"Hello Lime Workbench",
|
|
"openFixtureSessionFromSidebar",
|
|
"openWorkbench",
|
|
"workbenchOpened",
|
|
"artifactPersisted",
|
|
"appServerJsonRpcUsed",
|
|
"externalFixtureBackendUsed",
|
|
"liveProviderNotUsed",
|
|
"noInvokeErrors",
|
|
],
|
|
absentSnippets: [
|
|
'APP_SERVER_BACKEND_MODE: "mock"',
|
|
'backendMode: "mock"',
|
|
"--allow-live-provider",
|
|
"agent_runtime_",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
"invokeMockOnly",
|
|
"explicitMockFallback",
|
|
'type: "turn.final_done"',
|
|
'"agentSession/update"',
|
|
],
|
|
},
|
|
{
|
|
name: "npm exposes explicit Electron current fixture smokes",
|
|
file: "package.json",
|
|
snippets: [
|
|
'"smoke:agent-session-history-electron-fixture"',
|
|
"scripts/electron/session-history-fixture-smoke.mjs",
|
|
'"smoke:codex-import-continuation-electron-fixture"',
|
|
"scripts/electron/codex-import-continuation-fixture-smoke.mjs",
|
|
'"smoke:codex-import-click-through-electron-fixture"',
|
|
"scripts/electron/codex-import-click-through-fixture-smoke.mjs",
|
|
'"smoke:code-artifact-workbench-electron-fixture"',
|
|
"scripts/electron/code-artifact-workbench-fixture-smoke.mjs",
|
|
],
|
|
},
|
|
{
|
|
name: "Electron local history import click-through fixture launches current Desktop Host path",
|
|
file: "scripts/electron/codex-import-click-through-fixture-smoke.mjs",
|
|
snippets: [
|
|
"[smoke:codex-import-click-through-fixture]",
|
|
"import { _electron as electron }",
|
|
"electron.launch({",
|
|
'"--use-mock-keychain"',
|
|
'APP_SERVER_BACKEND_MODE: "external"',
|
|
"APP_SERVER_BACKEND_COMMAND: process.execPath",
|
|
'LIME_ELECTRON_DEV_HTTP_BRIDGE: "0"',
|
|
"createClickThroughFixtureRuntimeEnv",
|
|
"REQUIRED_BACKEND_METHODS",
|
|
'"thread/read"',
|
|
"导入细节还原",
|
|
"waitForImportedSessionDetails",
|
|
"sendFollowUpFromGui",
|
|
"CODEX_IMPORT_CLICK_THROUGH_DONE",
|
|
"backendMetadataImported",
|
|
"backendCwd === IMPORTED_CWD",
|
|
],
|
|
absentSnippets: [
|
|
'APP_SERVER_BACKEND_MODE: "mock"',
|
|
'backendMode: "mock"',
|
|
"--allow-live-provider",
|
|
"agent_runtime_",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
"invokeMockOnly",
|
|
"explicitMockFallback",
|
|
],
|
|
},
|
|
{
|
|
name: "Electron local history import click-through fixture owns source data and backend methods",
|
|
file: "scripts/electron/lib/local-history-import-click-through-fixture.mjs",
|
|
snippets: [
|
|
"writeFixtureBackend(",
|
|
"session_index.jsonl",
|
|
"CODEX_HOME: sourceRoot",
|
|
'"conversationImport/source/scan"',
|
|
'"conversationImport/thread/preview"',
|
|
'"conversationImport/thread/commit"',
|
|
'"thread/read"',
|
|
'"turn/start"',
|
|
"IMPORTED_REASONING_TEXT",
|
|
"IMPORTED_CWD",
|
|
"readBackendLedger(",
|
|
],
|
|
absentSnippets: [
|
|
'APP_SERVER_BACKEND_MODE: "mock"',
|
|
'backendMode: "mock"',
|
|
"--allow-live-provider",
|
|
"agent_runtime_",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
"invokeMockOnly",
|
|
"explicitMockFallback",
|
|
],
|
|
},
|
|
{
|
|
name: "Electron local history import click-through fixture owns sidebar dialog selectors",
|
|
file: "scripts/electron/lib/local-history-import-click-through-gui.mjs",
|
|
snippets: [
|
|
"app-sidebar-import-conversation-button",
|
|
"app-sidebar-conversation-import-dialog",
|
|
"app-sidebar-conversation-import-confirm",
|
|
'textarea[name="agent-chat-message"]',
|
|
"waitForImportPreview",
|
|
"confirmImport",
|
|
"waitForImportedSessionDetails",
|
|
"sendFollowUpFromGui",
|
|
"collectImportedSessionVisualAudit",
|
|
],
|
|
absentSnippets: [
|
|
'APP_SERVER_BACKEND_MODE: "mock"',
|
|
'backendMode: "mock"',
|
|
"--allow-live-provider",
|
|
"agent_runtime_",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
"invokeMockOnly",
|
|
"explicitMockFallback",
|
|
],
|
|
},
|
|
{
|
|
name: "Electron local history import click-through fixture owns App Server bridge readiness checks",
|
|
file: "scripts/electron/lib/local-history-import-smoke-utils.mjs",
|
|
snippets: [
|
|
"window.__LIME_ELECTRON__ === true",
|
|
"window.electronAPI.supportsCommand",
|
|
'export const APP_SERVER_HANDLE_JSON_LINES_COMMAND =\n "app_server_handle_json_lines"',
|
|
"invokeAppServerFromPage",
|
|
'jsonrpc: "2.0"',
|
|
"initializeAppServer",
|
|
],
|
|
absentSnippets: [
|
|
'APP_SERVER_BACKEND_MODE: "mock"',
|
|
'backendMode: "mock"',
|
|
"--allow-live-provider",
|
|
"agent_runtime_",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
"invokeMockOnly",
|
|
"explicitMockFallback",
|
|
],
|
|
},
|
|
{
|
|
name: "Electron session messages fixture proves App Server read detail messages after turn",
|
|
file: "scripts/smoke/agent-session-messages-electron-fixture-smoke.mjs",
|
|
snippets: [
|
|
"[smoke:agent-session-messages-electron-fixture]",
|
|
"import { _electron as electron }",
|
|
"electron.launch({",
|
|
'"--use-mock-keychain"',
|
|
'APP_SERVER_BACKEND_MODE: "external"',
|
|
"APP_SERVER_BACKEND_COMMAND: process.execPath",
|
|
"APP_SERVER_BACKEND_ARGS: JSON.stringify",
|
|
'LIME_ELECTRON_DEV_HTTP_BRIDGE: "0"',
|
|
"window.__LIME_ELECTRON__ === true",
|
|
"window.electronAPI.supportsCommand",
|
|
'const APP_SERVER_HANDLE_JSON_LINES_COMMAND = "app_server_handle_json_lines"',
|
|
'"initialize"',
|
|
'"thread/start"',
|
|
'"turn/start"',
|
|
'"thread/read"',
|
|
"writeFixtureBackend(",
|
|
"readBackendLedger(",
|
|
'input.kind === "turnStart"',
|
|
'type: "message.delta"',
|
|
"waitForReadModel",
|
|
"readModelConverged",
|
|
"readSnapshots",
|
|
"detail?.messages_count",
|
|
"detailMessagesLength",
|
|
"contentTextFromMessage",
|
|
"summary.detailMessagesCount === 2",
|
|
"summary.detailMessagesLength === 2",
|
|
"summary.userMessageText === USER_TEXT",
|
|
"summary.assistantMessageText === ASSISTANT_TEXT",
|
|
"用户消息未从 App Server detail.messages 恢复",
|
|
"助手消息未从 message.delta 投影",
|
|
"backendTurnStartSeen",
|
|
],
|
|
absentSnippets: [
|
|
'APP_SERVER_BACKEND_MODE: "mock"',
|
|
'backendMode: "mock"',
|
|
"--allow-live-provider",
|
|
"agent_runtime_",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
"invokeMockOnly",
|
|
"explicitMockFallback",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust v2 router rejects legacy turn shape and RuntimeCore denies hidden capabilities",
|
|
files: [
|
|
"lime-rs/crates/app-server/src/lib.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tests/turn_lifecycle.rs",
|
|
],
|
|
snippets: [
|
|
"turn_start_rejects_legacy_session_shape_before_runtime_dispatch",
|
|
"capability_list_with_session_id_uses_stored_session_scope",
|
|
"error_codes::INVALID_PARAMS",
|
|
"error_codes::SESSION_NOT_FOUND",
|
|
'assert!(error.error.message.contains("threadId"))',
|
|
"start_turn_rejects_hidden_capability_id_without_persisting_turn",
|
|
"RuntimeCoreError::CapabilityDenied(capability_id)",
|
|
'assert_eq!(capability_id, "content.draft.generate")',
|
|
"assert!(read.turns.is_empty())",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust runtime backend initializes current Agent runtime before action responses",
|
|
file: "lime-rs/crates/app-server/src/runtime_backend/initialization_tests.rs",
|
|
snippets: [
|
|
"respond_action_initializes_agent_before_runtime_resume",
|
|
"ExecutionBackend::respond_action",
|
|
"ActionRespondRequest",
|
|
"AgentSessionActionType::AskUser",
|
|
"assert!(backend.agent_state.is_initialized().await)",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust runtime backend flow tests cover current turn and action response events",
|
|
files: appServerRuntimeBackendFiles,
|
|
snippets: [
|
|
"handle_action_response",
|
|
"respond_action_tool_confirmation_resumes_pending_agent_tool_future",
|
|
'"action.resolved"',
|
|
"run_agent_turn_with_policy",
|
|
"AgentTurnExecutionRequest",
|
|
'"turn.completed"',
|
|
],
|
|
},
|
|
{
|
|
name: "Rust app-server facade reexports artifact/read protocol types",
|
|
file: "lime-rs/crates/app-server/src/lib.rs",
|
|
snippets: [
|
|
"pub use app_server_protocol::ArtifactReadParams",
|
|
"pub use app_server_protocol::ArtifactReadResponse",
|
|
"pub use app_server_protocol::ArtifactContentStatus",
|
|
"pub use app_server_protocol::ArtifactSummary",
|
|
"pub use runtime::FilesystemArtifactContentProvider",
|
|
"pub use app_server_protocol::METHOD_ARTIFACT_READ",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust runtime factory can inject capability source without host dependencies",
|
|
file: "lime-rs/crates/app-server/src/runtime_factory.rs",
|
|
snippets: [
|
|
"pub fn mock_runtime_core_with_capability_source(",
|
|
"pub fn mock_app_server_with_capability_source(",
|
|
"capability_source: Arc<dyn CapabilitySource>",
|
|
"RuntimeCore::with_backend_and_capability_source",
|
|
"pub fn unavailable_runtime_core_with_capability_source(",
|
|
"pub fn unavailable_app_server_with_capability_source(",
|
|
"factory_builds_unavailable_runtime_with_injected_capability_source",
|
|
"pub fn runtime_backend_core_with_capability_source(",
|
|
"pub fn runtime_backend_core_with_db_and_capability_source(",
|
|
"pub fn runtime_app_server_with_capability_source(",
|
|
"artifact_content_provider: Arc<dyn ArtifactContentProvider>",
|
|
"Arc::new(RuntimeBackend::with_execution_process_server(",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust app policy manifest builds standalone capability source",
|
|
file: "lime-rs/crates/app-server/src/capability.rs",
|
|
snippets: [
|
|
"pub struct AppPolicyManifest",
|
|
"pub struct AppPolicyCapability",
|
|
"pub enum AppPolicyManifestError",
|
|
"pub fn capability_source_from_app_policy_json(",
|
|
"impl TryFrom<AppPolicyManifest> for CapabilityInventorySource",
|
|
"app_policy_manifest_builds_scoped_capability_source",
|
|
"app_policy_manifest_rejects_incomplete_capabilities",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust app-server facade reexports app policy source types",
|
|
file: "lime-rs/crates/app-server/src/lib.rs",
|
|
snippets: [
|
|
"pub use capability::capability_source_from_app_policy_json",
|
|
"pub use capability::AppPolicyCapability",
|
|
"pub use capability::AppPolicyLoadError",
|
|
"pub use capability::AppPolicyManifest",
|
|
"pub use capability::AppPolicyManifestError",
|
|
],
|
|
},
|
|
{
|
|
name: "Standalone App Server exposes explicit unavailable backend mode",
|
|
file: "lime-rs/crates/app-server/src/runtime_factory.rs",
|
|
snippets: [
|
|
"pub enum AppServerBackendMode",
|
|
"Unavailable",
|
|
'Self::Unavailable => "unavailable"',
|
|
'"unavailable" => Ok(Self::Unavailable)',
|
|
"pub fn unavailable_runtime_core() -> RuntimeCore",
|
|
"pub fn unavailable_app_server() -> AppServer",
|
|
"factory_builds_unavailable_runtime_without_host_dependencies",
|
|
],
|
|
},
|
|
{
|
|
name: "Standalone App Server CLI accepts unavailable backend mode",
|
|
file: "lime-rs/crates/app-server/src/main.rs",
|
|
snippets: [
|
|
"let mut backend_mode = AppServerBackendMode::Unavailable",
|
|
"parse_args_defaults_to_stdio_unavailable_backend",
|
|
"(AppServerBackendMode::Unavailable, Some(capability_source))",
|
|
"AppServerRuntimeFactory::unavailable_runtime_core_with_capability_source(",
|
|
"AppServerRuntimeFactory::unavailable_runtime_core()",
|
|
"--backend external|runtime|mock|unavailable",
|
|
"--app-policy path",
|
|
"app_policy_path: Option<String>",
|
|
".map(load_app_policy_source)",
|
|
".transpose()?",
|
|
"parse_args_accepts_app_policy_path",
|
|
"load_app_policy_source_reads_scoped_capabilities",
|
|
"parse_args_accepts_explicit_unavailable_backend",
|
|
"unsupported app-server backend mode: agent",
|
|
],
|
|
},
|
|
{
|
|
name: "Standalone App Server CLI accepts external backend launch options",
|
|
file: "lime-rs/crates/app-server/src/main.rs",
|
|
snippets: [
|
|
"(AppServerBackendMode::External, Some(capability_source))",
|
|
"AppServerRuntimeFactory::external_runtime_core_with_capability_source(",
|
|
"AppServerRuntimeFactory::external_runtime_core(config.external_backend_config()?)",
|
|
"external_backend_config",
|
|
"--backend-command is required when --backend external",
|
|
"ExternalBackendConfig::new(command.clone())",
|
|
"--backend-command",
|
|
"--backend-arg",
|
|
"--backend-timeout-ms",
|
|
"invalid --backend-timeout-ms",
|
|
"--backend external|runtime|mock|unavailable",
|
|
"[--backend-command path]",
|
|
"[--backend-arg value]",
|
|
"[--backend-timeout-ms ms]",
|
|
"parse_args_accepts_external_backend_command",
|
|
"external_backend_requires_command",
|
|
],
|
|
},
|
|
{
|
|
name: "Standalone App Server runtime exposes App Server RuntimeBackend mode",
|
|
file: "lime-rs/crates/app-server/src/runtime_factory.rs",
|
|
snippets: [
|
|
"Runtime",
|
|
'Self::Runtime => "runtime"',
|
|
'"runtime" => Ok(Self::Runtime)',
|
|
"pub fn runtime_backend_core() -> RuntimeCore",
|
|
"pub fn runtime_backend_core_with_capability_source(",
|
|
"pub fn runtime_app_server() -> AppServer",
|
|
"factory_builds_runtime_backend_without_host_dependencies",
|
|
"factory_builds_runtime_backend_with_injected_capability_source",
|
|
],
|
|
},
|
|
{
|
|
name: "Standalone App Server external backend keeps command args and timeout explicit",
|
|
file: "lime-rs/crates/app-server/src/external_backend.rs",
|
|
snippets: [
|
|
"pub struct ExternalBackendConfig",
|
|
"pub command: String",
|
|
"pub args: Vec<String>",
|
|
"pub timeout_ms: u64",
|
|
"pub const DEFAULT_EXTERNAL_BACKEND_TIMEOUT_MS",
|
|
"pub fn with_args(",
|
|
"pub fn with_timeout_ms(",
|
|
"external app-server backend timed out after {timeout_ms}ms while {phase}",
|
|
"stdout_lines.next_line()",
|
|
"cleanup_external_backend_after_timeout(",
|
|
"let _ = child.start_kill()",
|
|
"let _ = child.wait().await",
|
|
"external_backend_stderr_summary(stderr_task).await",
|
|
"emit_external_backend_line(&line, sink)",
|
|
"fn emit_external_backend_line(",
|
|
"external_backend_config_keeps_command_and_args_separate",
|
|
"external_backend_reads_jsonl_event_stream",
|
|
"external_backend_timeout_kills_process_and_reports_stderr_while_reading_stdout",
|
|
"external_backend_timeout_kills_process_and_reports_stderr_while_waiting_for_exit",
|
|
],
|
|
absentSnippets: ["child.wait_with_output()"],
|
|
},
|
|
{
|
|
name: "Standalone App Server current runtime backend delegates Claw Agent execution chain",
|
|
files: [
|
|
...agentRuntimeBoundaryFiles,
|
|
...agentRequestToolPolicyFiles,
|
|
"lime-rs/crates/app-server/src/lib.rs",
|
|
...appServerRuntimeBackendExecutionChainFiles,
|
|
],
|
|
snippets: [
|
|
"mod runtime_backend;",
|
|
"pub use runtime_backend::RuntimeBackend",
|
|
"pub struct RuntimeBackend",
|
|
"impl ExecutionBackend for RuntimeBackend",
|
|
"init_agent_with_db(",
|
|
"AgentRuntimeState::new()",
|
|
"session_loops.get_or_create(",
|
|
"execute_backend_via_session_loop(",
|
|
"direct_provider_config_from_request",
|
|
"configure_provider_for_session(",
|
|
"install_provider_for_session(agent_state, request.session_id, &runtime_config).await?",
|
|
"create_configured_reply_provider(config, &self.provider_health)?",
|
|
"provider_for_session(request.session_id)",
|
|
"close_provider_session(session_id).await",
|
|
"configure_model_route_provider_for_session_with_provider_and_credential_ref(",
|
|
"pub struct SessionProviderConfig",
|
|
"ProviderConfigurationRequest",
|
|
"session_provider_config_to_runtime_provider_config(",
|
|
"config.route_protocol = request.route_protocol.or(config.route_protocol)",
|
|
"route_protocol_from_session_provider_config",
|
|
"ProtocolKind::OpenaiResponses",
|
|
"ModelProviderProtocol::Responses",
|
|
"RuntimeProviderProtocol::Responses",
|
|
"build_agent_session_config(",
|
|
"AgentSessionConfigurationRequest",
|
|
"SessionConfigBuilder",
|
|
"build_agent_turn_context(",
|
|
"AgentTurnContextConfigurationRequest",
|
|
"set_agent_turn_output_schema(",
|
|
"TurnContextOverride",
|
|
"TurnOutputSchemaSource",
|
|
"impl RuntimeToolExecutor for CurrentTurnToolExecutor",
|
|
"fn execute<'a>(",
|
|
"RuntimeToolExecutionRequest<'a>",
|
|
"run_agent_turn_with_policy",
|
|
"AgentTurnExecutionRequest",
|
|
"stream_runtime_reply_with_policy(",
|
|
"runtime_events_from_agent_event",
|
|
"runtime_event_type_for_agent_event",
|
|
'"item.started"',
|
|
'"item.completed"',
|
|
'"failureCategory"',
|
|
"canonical_tool_item(event)",
|
|
"canonical_arguments_value",
|
|
"final_done_raw_runtime_event_does_not_map_to_current_terminal_event",
|
|
"canonical_tool_start_without_arguments_emits_only_item",
|
|
"canonical_tool_start_emits_only_typed_item_arguments",
|
|
"canonical_tool_completion_preserves_output_and_metadata",
|
|
"runtime_agent_failed_shell_tool_is_mirrored_to_coding_facts",
|
|
"request_tool_policy_from_request",
|
|
"RequestToolPolicyMode::Auto",
|
|
"resolve_request_tool_policy_with_mode(web_search, search_mode)",
|
|
"natural_language_news_turn_exposes_search_tool_surface_by_default",
|
|
"explicit_auto_search_mode_uses_model_tool_choice",
|
|
"direct_host_provider_config_allows_localhost_fixture_without_database_provider",
|
|
"if request.api_key.is_none() && request.base_url.is_none() {",
|
|
'"message.delta"',
|
|
'"turn.completed"',
|
|
"selection_from_explicit_preferences",
|
|
"selection_from_host_provider_config",
|
|
"selection_from_session_default",
|
|
'"/providerSelector"',
|
|
'"/modelName"',
|
|
"session_extension_data_provider_routing_is_used_as_session_default",
|
|
"let provider = session_default_provider(metadata)?;",
|
|
"let model = session_default_model(metadata)?;",
|
|
"RuntimeCoreError::pending_route_for_session(",
|
|
"RuntimeCoreError::RouteRejected",
|
|
'reason_code == "provider_and_model_missing"',
|
|
'reason_code == "capability_snapshot_missing"',
|
|
],
|
|
absentSnippets: [
|
|
".configure_provider(",
|
|
"configure_provider_from_pool(",
|
|
"impl From<SessionProviderConfig> for StateProviderConfig",
|
|
".complete(&system, &messages, &[])",
|
|
"message_requires_fresh_web_search",
|
|
"mode_default",
|
|
"unwrap_or(mode_default)",
|
|
"(None, None) if mode_default",
|
|
"resolve_request_tool_policy_with_mode(web_search, search_mode, true)",
|
|
"resolve_request_tool_policy_with_mode(web_search, search_mode, false)",
|
|
"fresh_news_request_promotes_search_to_required",
|
|
"selection_from_enabled_provider_catalog",
|
|
"selection_from_cached_provider_models",
|
|
"enabled_provider_custom_model",
|
|
"cached_provider_models",
|
|
"ModelRegistryService",
|
|
"tauri::",
|
|
"APP_SERVER_BACKEND_MODE=mock",
|
|
'"backend": "mock"',
|
|
"mockPriorityCommands",
|
|
],
|
|
},
|
|
{
|
|
name: "App Server runtime backend delegates Agent streaming loop to lime-agent",
|
|
file: "lime-rs/crates/app-server/src/runtime_backend.rs",
|
|
snippets: ["run_agent_turn_with_policy(", "AgentTurnExecutionRequest"],
|
|
absentSnippets: [
|
|
"stream_reply_with_policy(",
|
|
"create_cancel_token(",
|
|
"remove_cancel_token(",
|
|
],
|
|
},
|
|
{
|
|
name: "Request tool policy avoids freshness keyword hard-code for preflight",
|
|
files: ["lime-rs/crates/agent/src/lib.rs", ...agentRequestToolPolicyFiles],
|
|
snippets: [
|
|
"pub fn resolve_request_tool_policy_with_mode(",
|
|
"record_tool_item",
|
|
"observed_item_lifecycle",
|
|
"pub struct RequestToolPolicy",
|
|
"pub struct WebSearchExecutionTracker",
|
|
"validate_web_search_requirement",
|
|
],
|
|
absentSnippets: [
|
|
"message_requires_fresh_web_search",
|
|
"pub fn message_requires_fresh_web_search(",
|
|
"pub use request_tool_policy::message_requires_fresh_web_search",
|
|
"merge_system_prompt_with_web_search_preflight_context, message_requires_fresh_web_search",
|
|
"fresh_news_request_promotes_search_to_required",
|
|
],
|
|
},
|
|
{
|
|
name: "App Server stdio streams direct v2 lifecycle before turn response",
|
|
files: [
|
|
"lime-rs/crates/app-server/src/lib.rs",
|
|
"lime-rs/crates/app-server/src/processor/mod.rs",
|
|
"lime-rs/crates/app-server/src/runtime.rs",
|
|
"lime-rs/crates/app-server/src/runtime/turn_execution.rs",
|
|
"lime-rs/crates/app-server-transport/src/lib.rs",
|
|
],
|
|
snippets: [
|
|
"pub use transport::start_stdio_connection",
|
|
"type StreamedTransportMessage",
|
|
"pub async fn handle_message_streaming",
|
|
"handle_request_streaming",
|
|
"start_turn_with_event_callback",
|
|
"AppendingRuntimeEventSink",
|
|
"fn emit_failure(&mut self, error: &RuntimeCoreError) -> Result<(), RuntimeCoreError>",
|
|
'"turn.failed"',
|
|
"mpsc::unbounded_channel::<StreamedTransportMessage>()",
|
|
"json_lines_loop_streams_external_backend_events_before_turn_response",
|
|
"json_lines_loop_streams_turn_failed_after_partial_external_backend_events",
|
|
"assert_next_direct_delta_notification",
|
|
'notification.method != "turn/completed"',
|
|
'assert_eq!(params["turn"]["status"], "failed")',
|
|
"external backend crashed after partial output",
|
|
],
|
|
},
|
|
{
|
|
name: "App Server stdio uses transport lifecycle and per-connection writer queues",
|
|
files: [
|
|
"lime-rs/crates/app-server/src/lib.rs",
|
|
"lime-rs/crates/app-server-transport/src/lib.rs",
|
|
"lime-rs/crates/app-server-transport/src/transport/stdio.rs",
|
|
],
|
|
snippets: [
|
|
"pub use transport::start_stdio_connection",
|
|
"start_stdio_connection(transport_event_tx, reader, writer).await?",
|
|
"TransportEvent::ConnectionOpened",
|
|
"TransportEvent::StdioClientInitialized",
|
|
"TransportEvent::ConnectionClosed",
|
|
"TransportEvent::IncomingMessage",
|
|
"server.register_transport_writer(",
|
|
"disconnect_sender",
|
|
"server.unregister_transport_writer(connection_id)",
|
|
"send_to_transport_connection",
|
|
"QueuedOutgoingMessage::new(OutgoingMessage::from(message))",
|
|
"enqueue_transport_outbound_message(",
|
|
"disconnects: &TransportDisconnects",
|
|
"initialized: &TransportInitialized",
|
|
"tokio::spawn(async move",
|
|
"writer.try_send(queued)",
|
|
"stdio_connection_emits_lifecycle_events_and_writes_queue_messages",
|
|
],
|
|
absentSnippets: [
|
|
"broadcast::error::RecvError::Lagged",
|
|
"try_send(QueuedOutgoingMessage",
|
|
],
|
|
},
|
|
{
|
|
name: "App Server test client launch-stdio runs a real stdio smoke harness",
|
|
files: [
|
|
"lime-rs/crates/app-server-test-client/src/harness.rs",
|
|
"lime-rs/crates/app-server-test-client/src/lib.rs",
|
|
"lime-rs/crates/app-server-test-client/src/main.rs",
|
|
],
|
|
snippets: [
|
|
"LaunchStdio {",
|
|
"extra_args: Vec<String>",
|
|
"pub struct StdioSmokeReport",
|
|
"pub fn run_stdio_smoke(",
|
|
"config\n .command()",
|
|
".spawn()",
|
|
"read_response(&mut stdout, RequestId::Integer(1))",
|
|
"read_response(&mut stdout, RequestId::Integer(2))",
|
|
"wait_for_exit(child, Duration::from_secs(2))",
|
|
"cleanup_child(&mut child)",
|
|
"run_stdio_smoke(config, &lines)",
|
|
"stdio_smoke_report_summary_is_stable",
|
|
],
|
|
},
|
|
{
|
|
name: "Standalone App Server stdio smoke isolates persistent state",
|
|
file: "scripts/app-server/stdio-smoke.mjs",
|
|
snippets: [
|
|
'mkdtemp(path.join(tmpdir(), "app-server-stdio-"))',
|
|
'stdioSidecar(binaryPath, undefined, path.join(tempDir, "data"))',
|
|
"nextResponseForRequest(",
|
|
"rm(tempDir, { recursive: true, force: true })",
|
|
],
|
|
},
|
|
{
|
|
name: "Standalone App Server external backend smoke proves controlled fixture event bridge",
|
|
file: "scripts/app-server/external-backend-smoke.mjs",
|
|
snippets: [
|
|
"[smoke:app-server-external-backend] ok",
|
|
"connectAppServerSidecar",
|
|
'stdioSidecar(binaryPath, policyPath, path.join(tempDir, "data"))',
|
|
'backendMode: "external"',
|
|
"backendCommand: process.execPath",
|
|
"backendArgs: [backendPath]",
|
|
"content.draft.generate",
|
|
"METHOD_AGENT_SESSION_EVENT",
|
|
"connection.listCapabilities",
|
|
"connection.startSession",
|
|
"connection.startTurn",
|
|
"connection.readSession",
|
|
"connection.readArtifacts",
|
|
"message.delta",
|
|
"artifact.snapshot",
|
|
"turn.completed",
|
|
'assertEqual(readTurns.length, 1, "read turn count")',
|
|
'assertEqual(readTurn.status, "completed", "read turn status")',
|
|
"content-draft-smoke",
|
|
],
|
|
absentSnippets: ["turn.final_done"],
|
|
},
|
|
{
|
|
name: "npm exposes standalone external backend smoke",
|
|
file: "package.json",
|
|
snippets: [
|
|
'"smoke:app-server-external-backend"',
|
|
"scripts/app-server/external-backend-smoke.mjs",
|
|
'npm --prefix \\"packages/app-server-client\\" run build',
|
|
],
|
|
},
|
|
{
|
|
name: "RuntimeCore rolls back turn state when backend start fails",
|
|
files: appServerRuntimeFiles,
|
|
snippets: [
|
|
"pub struct UnavailableBackend",
|
|
"standalone app-server backend is not configured",
|
|
"fn rollback_started_turn(",
|
|
"stored.turns.retain(|turn| turn.turn_id != turn_id)",
|
|
"unavailable_backend_rejects_turn_without_persisting_fake_turn",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust app-server host boundary guard covers capability source",
|
|
file: "lime-rs/crates/app-server/tests/host_boundary_guard.rs",
|
|
snippets: [
|
|
"src/capability.rs",
|
|
"app-server crate 不能直接依赖桌面宿主壳层",
|
|
"app-server 公共后端边界只能暴露 RuntimeEvent",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust client exposes typed capability/list helper",
|
|
file: "lime-rs/crates/app-server-client/src/lib.rs",
|
|
snippets: [
|
|
"pub fn list_capabilities(",
|
|
"params: CapabilityListParams",
|
|
"pub fn list_capabilities_default(&mut self) -> Result<JsonRpcRequest, ClientError>",
|
|
"TypedRequest<CapabilityListParams>",
|
|
"TypedRequest::new(METHOD_CAPABILITY_LIST, params)",
|
|
"pub use app_server_protocol::app_server_method_catalog",
|
|
"pub use app_server_protocol::is_app_server_request_method",
|
|
"reexports_protocol_method_catalog_for_consumers",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust client exposes typed artifact/read helper",
|
|
file: "lime-rs/crates/app-server-client/src/lib.rs",
|
|
snippets: [
|
|
"use app_server_protocol::ArtifactReadParams",
|
|
"use app_server_protocol::METHOD_ARTIFACT_READ",
|
|
"pub fn read_artifacts(",
|
|
"typed::read_artifacts(params)",
|
|
"TypedRequest<ArtifactReadParams>",
|
|
"TypedRequest::new(METHOD_ARTIFACT_READ, params)",
|
|
"read_artifacts_preserves_filter_and_stable_method",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust client exposes typed exact fs helpers",
|
|
file: "lime-rs/crates/app-server-client/src/lib.rs",
|
|
snippets: [
|
|
"FsChangedNotification, FsCopyParams, FsCopyResponse, FsCreateDirectoryParams,",
|
|
"FsReadDirectoryParams, FsReadDirectoryResponse, FsReadFileParams, FsReadFileResponse,",
|
|
"FsRemoveParams, FsRemoveResponse, FsUnwatchParams, FsUnwatchResponse, FsWatchParams,",
|
|
"METHOD_FS_GET_METADATA, METHOD_FS_READ_DIRECTORY, METHOD_FS_READ_FILE, METHOD_FS_REMOVE,",
|
|
"METHOD_FS_UNWATCH, METHOD_FS_WATCH, METHOD_FS_WRITE_FILE",
|
|
"pub fn read_file(",
|
|
"typed::read_file(params)",
|
|
"TypedRequest<FsReadFileParams>",
|
|
"TypedRequest::new(METHOD_FS_READ_FILE, params)",
|
|
"pub fn write_file(",
|
|
"typed::write_file(params)",
|
|
"TypedRequest<FsWriteFileParams>",
|
|
"TypedRequest::new(METHOD_FS_WRITE_FILE, params)",
|
|
"pub fn create_directory(",
|
|
"typed::create_directory(params)",
|
|
"TypedRequest<FsCreateDirectoryParams>",
|
|
"TypedRequest::new(METHOD_FS_CREATE_DIRECTORY, params)",
|
|
"pub fn get_metadata(",
|
|
"typed::get_metadata(params)",
|
|
"pub fn read_directory(",
|
|
"typed::read_directory(params)",
|
|
"pub fn remove(",
|
|
"typed::remove(params)",
|
|
"pub fn copy(",
|
|
"typed::copy(params)",
|
|
"pub fn watch(",
|
|
"typed::watch(params)",
|
|
"pub fn unwatch(",
|
|
"typed::unwatch(params)",
|
|
"fn fs_helpers_use_exact_v2_methods()",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript protocol exposes typed capability/list contract",
|
|
file: "packages/app-server-client/src/protocol.ts",
|
|
snippets: [
|
|
"GENERATED_APP_SERVER_METHODS,",
|
|
"GENERATED_APP_SERVER_REQUEST_SERIALIZATION_SCOPES,",
|
|
'export type AppServerMethodKind = "request" | "notification"',
|
|
"export type AppServerMethodSpec = {",
|
|
"export const APP_SERVER_METHODS =",
|
|
"GENERATED_APP_SERVER_METHODS satisfies readonly AppServerMethodSpec[]",
|
|
"export type AppServerRequestSerializationScope =",
|
|
"export type AppServerRequestSerializationScopeSpec = {",
|
|
"export const APP_SERVER_REQUEST_SERIALIZATION_SCOPES =",
|
|
"GENERATED_APP_SERVER_REQUEST_SERIALIZATION_SCOPES satisfies readonly AppServerRequestSerializationScopeSpec[]",
|
|
"export function getAppServerRequestSerializationScope(",
|
|
"export function isAppServerRequestMethod(method: string): boolean",
|
|
"export function isAppServerNotificationMethod(method: string): boolean",
|
|
"capabilityDenied: -32020",
|
|
"export type CapabilityListParams = {",
|
|
"appId?: string",
|
|
"workspaceId?: string",
|
|
"sessionId?: string",
|
|
"cursor?: string",
|
|
"limit?: number",
|
|
"export type CapabilityDescriptor = {",
|
|
"nextCursor?: string",
|
|
"requestSerializationScopes: AppServerRequestSerializationScopeSpec[]",
|
|
],
|
|
absentSnippets: [
|
|
'export const METHOD_INITIALIZE = "initialize"',
|
|
'export const METHOD_CAPABILITY_LIST = "capability/list"',
|
|
"DEFAULT_LISTEN_URL",
|
|
"DEFAULT_RELEASE_MANIFEST_NAME",
|
|
"DEFAULT_PROTOCOL_SCHEMA_MANIFEST_NAME",
|
|
],
|
|
},
|
|
{
|
|
name: "Generated TypeScript protocol exposes Rust-owned method constants and v2 typed envelopes",
|
|
file: "packages/app-server-client/src/generated/protocol-types.ts",
|
|
snippets: [
|
|
'export const METHOD_INITIALIZE = "initialize";',
|
|
'export const METHOD_CAPABILITY_LIST = "capability/list";',
|
|
"export type AppServerClientRequest =",
|
|
'method: "initialize";',
|
|
"export type ClientRequest =",
|
|
'method: "thread/start";',
|
|
'method: "turn/start";',
|
|
"export type ClientNotification =",
|
|
'method: "initialized";',
|
|
"export type ServerNotification =",
|
|
'method: "turn/started";',
|
|
'method: "turn/completed";',
|
|
"export type ServerRequest =",
|
|
'method: "mcpServer/elicitation/request";',
|
|
"params: McpServerElicitationRequestParams;",
|
|
'method: "item/commandExecution/requestApproval";',
|
|
"params: CommandExecutionRequestApprovalParams;",
|
|
'method: "item/fileChange/requestApproval";',
|
|
"params: FileChangeRequestApprovalParams;",
|
|
'method: "item/tool/requestUserInput";',
|
|
"params: ToolRequestUserInputParams;",
|
|
"export interface McpServerElicitationRequestResponse",
|
|
"export interface FileChangeRequestApprovalResponse",
|
|
"export interface ToolRequestUserInputResponse",
|
|
"export interface McpToolCallResult",
|
|
"export interface McpToolCallError",
|
|
'type: "inputAudio";',
|
|
"error: null | {",
|
|
"result: null | {",
|
|
'export type MessagePhase = "commentary" | "final_answer";',
|
|
],
|
|
absentSnippets: [
|
|
"export interface AppServerClientRequest",
|
|
"method: AppServerRequestMethod;",
|
|
"export type AppServerNotification =",
|
|
"export interface McpServerElicitationResponse",
|
|
'type: "audio";',
|
|
'type: "localAudio";',
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript client wraps typed capability/list helper with single-pump response routing",
|
|
file: "packages/app-server-client/src/index.ts",
|
|
snippets: [
|
|
'export * from "./protocol.js"',
|
|
'export * from "./request-client-methods.js"',
|
|
'from "./protocol.js"',
|
|
"METHOD_CAPABILITY_LIST",
|
|
"export class AppServerRequestError extends Error",
|
|
"readonly response: JsonRpcErrorResponse",
|
|
"readonly notifications: JsonRpcNotification[]",
|
|
"readonly messages: JsonRpcMessage[]",
|
|
"new AppServerRequestError(",
|
|
"method,",
|
|
"#readPump: Promise<void> | null = null",
|
|
"#pendingRequests = new Map<protocol.RequestId, PendingRequestRead>()",
|
|
"notifications: [],",
|
|
"messages: [message],",
|
|
"listCapabilities(params: CapabilityListParams = {}): JsonRpcRequest",
|
|
"this.client.listCapabilities(params)",
|
|
"Promise<AppServerRequestResult<CapabilityListResponse>>",
|
|
],
|
|
absentSnippets: ['export const METHOD_CAPABILITY_LIST = "capability/list"'],
|
|
},
|
|
{
|
|
name: "Media task artifact video create is wired through App Server current clients",
|
|
files: [
|
|
"packages/app-server-client/src/protocol.ts",
|
|
"packages/app-server-client/src/index.ts",
|
|
"src/lib/api/appServer.ts",
|
|
"src/lib/api/mediaTasks.ts",
|
|
"src/lib/api/videoGeneration.ts",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/method_names.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/media.rs",
|
|
"lime-rs/crates/app-server/src/processor/mod.rs",
|
|
"lime-rs/crates/app-server/src/processor/media.rs",
|
|
"lime-rs/crates/app-server/src/runtime.rs",
|
|
"lime-rs/crates/app-server/src/media_task.rs",
|
|
],
|
|
snippets: [
|
|
"mediaTaskArtifact/video/create",
|
|
"mediaTaskArtifact/image/complete",
|
|
"METHOD_MEDIA_TASK_ARTIFACT_VIDEO_CREATE",
|
|
"METHOD_MEDIA_TASK_ARTIFACT_IMAGE_COMPLETE",
|
|
"MediaTaskArtifactVideoCreateParams",
|
|
"MediaTaskArtifactCompletedImageInput",
|
|
"MediaTaskArtifactImageCompleteParams",
|
|
"createVideoMediaTaskArtifact",
|
|
"completeImageMediaTaskArtifact",
|
|
"createVideoGenerationTaskArtifact",
|
|
"completeImageGenerationTaskArtifact",
|
|
"create_video_media_task_artifact",
|
|
"complete_image_media_task_artifact",
|
|
"create_video_generation_task_artifact",
|
|
"complete_image_generation_task_artifact",
|
|
"MediaTaskType::VideoGenerate",
|
|
"video_generation_model",
|
|
],
|
|
absentSnippets: [
|
|
'"create_video_generation_task"',
|
|
'"get_video_generation_task"',
|
|
'"list_video_generation_tasks"',
|
|
'"cancel_video_generation_task"',
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript protocol exposes typed agentSession/action/respond contract",
|
|
file: "packages/app-server-client/src/protocol.ts",
|
|
snippets: [
|
|
"export const METHOD_AGENT_SESSION_ACTION_RESPOND =",
|
|
'"agentSession/action/respond"',
|
|
"export type AgentSessionActionType =",
|
|
'"tool_confirmation"',
|
|
'"ask_user"',
|
|
'"elicitation"',
|
|
"export type AgentSessionActionScope = {",
|
|
"export type AgentSessionActionRespondParams = {",
|
|
"export type AgentSessionActionRespondResponse = Record<string, never>",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript client wraps typed agentSession/action/respond helper",
|
|
file: "packages/app-server-client/src/index.ts",
|
|
snippets: [
|
|
"METHOD_AGENT_SESSION_ACTION_RESPOND",
|
|
"respondAction(params: AgentSessionActionRespondParams): JsonRpcRequest",
|
|
"this.client.respondAction(params)",
|
|
"Promise<AppServerRequestResult<AgentSessionActionRespondResponse>>",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript protocol exposes typed artifact/read contract",
|
|
file: "packages/app-server-client/src/protocol.ts",
|
|
snippets: [
|
|
'export const METHOD_ARTIFACT_READ = "artifact/read"',
|
|
"export type ArtifactReadParams = {",
|
|
"artifactRef?: string",
|
|
"includeContent?: boolean",
|
|
"export type ArtifactSummary = {",
|
|
"artifactRef: string",
|
|
"content?: string",
|
|
"contentStatus: ArtifactContentStatus",
|
|
"export type ArtifactReadResponse = {",
|
|
"artifacts: ArtifactSummary[]",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript protocol exposes typed exact fs contract",
|
|
file: "packages/app-server-client/src/protocol.ts",
|
|
snippets: [
|
|
'export const METHOD_FS_READ_FILE = "fs/readFile"',
|
|
'export const METHOD_FS_WRITE_FILE = "fs/writeFile"',
|
|
'export const METHOD_FS_CREATE_DIRECTORY = "fs/createDirectory"',
|
|
'export const METHOD_FS_GET_METADATA = "fs/getMetadata"',
|
|
'export const METHOD_FS_READ_DIRECTORY = "fs/readDirectory"',
|
|
'export const METHOD_FS_REMOVE = "fs/remove"',
|
|
'export const METHOD_FS_COPY = "fs/copy"',
|
|
'export const METHOD_FS_WATCH = "fs/watch"',
|
|
'export const METHOD_FS_UNWATCH = "fs/unwatch"',
|
|
'export const METHOD_FS_CHANGED = "fs/changed"',
|
|
"export interface FsReadFileParams",
|
|
"dataBase64: string",
|
|
"export interface FsWriteFileParams",
|
|
"export interface FsCreateDirectoryParams",
|
|
"export interface FsGetMetadataResponse",
|
|
"export interface FsReadDirectoryResponse",
|
|
"entries: FsReadDirectoryEntry[]",
|
|
"export interface FsRemoveParams",
|
|
"force?: boolean | null",
|
|
"export interface FsCopyParams",
|
|
"sourcePath: string",
|
|
"destinationPath: string",
|
|
"export interface FsWatchParams",
|
|
"export interface FsChangedNotification",
|
|
"changedPaths: string[]",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript client wraps typed artifact/read helper",
|
|
file: "packages/app-server-client/src/index.ts",
|
|
snippets: [
|
|
"METHOD_ARTIFACT_READ",
|
|
"readArtifacts(params: ArtifactReadParams): JsonRpcRequest",
|
|
"this.client.readArtifacts(params)",
|
|
"Promise<AppServerRequestResult<ArtifactReadResponse>>",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript client wraps typed exact fs helpers",
|
|
file: "packages/app-server-client/src/index.ts",
|
|
snippets: [
|
|
"readFile(params: protocol.FsReadFileParams): protocol.JsonRpcRequest",
|
|
"writeFile(params: protocol.FsWriteFileParams): protocol.JsonRpcRequest",
|
|
"params: protocol.FsCreateDirectoryParams",
|
|
"getMetadata(params: protocol.FsGetMetadataParams): protocol.JsonRpcRequest",
|
|
"params: protocol.FsReadDirectoryParams",
|
|
"remove(params: protocol.FsRemoveParams): protocol.JsonRpcRequest",
|
|
"copy(params: protocol.FsCopyParams): protocol.JsonRpcRequest",
|
|
"watch(params: protocol.FsWatchParams): protocol.JsonRpcRequest",
|
|
"unwatch(params: protocol.FsUnwatchParams): protocol.JsonRpcRequest",
|
|
"method: protocol.METHOD_FS_READ_FILE",
|
|
"method: protocol.METHOD_FS_WRITE_FILE",
|
|
"method: protocol.METHOD_FS_CREATE_DIRECTORY",
|
|
"method: protocol.METHOD_FS_GET_METADATA",
|
|
"method: protocol.METHOD_FS_READ_DIRECTORY",
|
|
"method: protocol.METHOD_FS_REMOVE",
|
|
"method: protocol.METHOD_FS_COPY",
|
|
"method: protocol.METHOD_FS_WATCH",
|
|
"method: protocol.METHOD_FS_UNWATCH",
|
|
"this.client.readFile(params)",
|
|
"this.client.writeFile(params)",
|
|
"this.client.createDirectory(params)",
|
|
"this.client.getMetadata(params)",
|
|
"this.client.readDirectory(params)",
|
|
"this.client.remove(params)",
|
|
"this.client.copy(params)",
|
|
"this.client.watch(params)",
|
|
"this.client.unwatch(params)",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript protocol exposes typed agentSession derived export contracts",
|
|
file: "packages/app-server-client/src/protocol.ts",
|
|
snippets: [
|
|
"export const METHOD_AGENT_SESSION_REPLAY_CASE_EXPORT =",
|
|
'"agentSession/replayCase/export"',
|
|
"export const METHOD_AGENT_SESSION_ANALYSIS_HANDOFF_EXPORT =",
|
|
'"agentSession/analysisHandoff/export"',
|
|
"export const METHOD_AGENT_SESSION_REVIEW_DECISION_TEMPLATE_EXPORT =",
|
|
'"agentSession/reviewDecisionTemplate/export"',
|
|
"export const METHOD_AGENT_SESSION_REVIEW_DECISION_SAVE =",
|
|
'"agentSession/reviewDecision/save"',
|
|
"export type AgentSessionReplayCaseExportParams = {",
|
|
"export type AgentSessionReplayCaseExportResponse = {",
|
|
"export type AgentSessionAnalysisHandoffExportParams = {",
|
|
"export type AgentSessionAnalysisHandoffExportResponse = {",
|
|
"export type AgentSessionReviewDecisionTemplateExportParams = {",
|
|
"export type AgentSessionReviewDecisionSaveParams = {",
|
|
"export type AgentSessionReviewDecisionTemplateExportResponse = {",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript client wraps typed agentSession derived export helpers",
|
|
file: "packages/app-server-client/src/index.ts",
|
|
snippets: [
|
|
"METHOD_AGENT_SESSION_REPLAY_CASE_EXPORT",
|
|
"METHOD_AGENT_SESSION_ANALYSIS_HANDOFF_EXPORT",
|
|
"METHOD_AGENT_SESSION_REVIEW_DECISION_TEMPLATE_EXPORT",
|
|
"METHOD_AGENT_SESSION_REVIEW_DECISION_SAVE",
|
|
"exportReplayCase(params: AgentSessionReplayCaseExportParams): JsonRpcRequest",
|
|
"exportAnalysisHandoff(",
|
|
"exportReviewDecisionTemplate(",
|
|
"this.client.exportReplayCase(params)",
|
|
"this.client.exportAnalysisHandoff(params)",
|
|
"this.client.exportReviewDecisionTemplate(params)",
|
|
"this.client.saveReviewDecision(params)",
|
|
"Promise<AppServerRequestResult<AgentSessionReplayCaseExportResponse>>",
|
|
"Promise<\n AppServerRequestResult<AgentSessionReviewDecisionTemplateExportResponse>",
|
|
],
|
|
normalizedSnippets: [
|
|
"saveReviewDecision(params: AgentSessionReviewDecisionSaveParams,): JsonRpcRequest",
|
|
"Promise<AppServerRequestResult<AgentSessionAnalysisHandoffExportResponse>>",
|
|
],
|
|
},
|
|
{
|
|
name: "Retired recent Team selection is absent from current session contracts",
|
|
files: [
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/session_admin.rs",
|
|
"lime-rs/crates/app-server/src/runtime/session_lifecycle.rs",
|
|
"lime-rs/crates/app-server/src/runtime/projection_store.rs",
|
|
"lime-rs/crates/app-server/src/runtime/read_model/session_metadata.rs",
|
|
"lime-rs/crates/agent-runtime/src/session_execution.rs",
|
|
"lime-rs/crates/agent-runtime/src/session_recent.rs",
|
|
"packages/app-server-client/src/protocol.ts",
|
|
"packages/app-server-client/src/generated/protocol-types.ts",
|
|
"src/lib/api/agentExecutionRuntime.ts",
|
|
"src/lib/api/agentRuntime/requestTypes.ts",
|
|
"src/lib/api/agentRuntime/appServerSessionClient.ts",
|
|
],
|
|
snippets: [],
|
|
absentSnippets: [
|
|
"recent_team_selection",
|
|
"recentTeamSelection",
|
|
"RecentTeamSelection",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript protocol exposes typed thread archive lifecycle contract",
|
|
file: "packages/app-server-client/src/protocol.ts",
|
|
snippets: [
|
|
'export const METHOD_THREAD_ARCHIVE = "thread/archive"',
|
|
'export const METHOD_THREAD_UNARCHIVE = "thread/unarchive"',
|
|
"export interface ThreadArchiveParams {",
|
|
"export type ThreadArchiveResponse = Record<string, unknown>",
|
|
"export interface ThreadUnarchiveParams {",
|
|
"export interface ThreadUnarchiveResponse {",
|
|
],
|
|
absentSnippets: [
|
|
'"agentSession/archiveMany"',
|
|
"AgentSessionArchiveManyParams",
|
|
"AgentSessionArchiveManyResponse",
|
|
],
|
|
},
|
|
{
|
|
name: "Retired agent session mutation methods stay absent from current protocol",
|
|
files: [
|
|
...protocolV0ModuleFiles,
|
|
...protocolV2ModuleFiles,
|
|
...schemaExportModuleFiles,
|
|
"lime-rs/crates/app-server-protocol/schema/json/app_server_protocol.schemas.json",
|
|
"lime-rs/crates/app-server-protocol/schema/json/manifest.json",
|
|
"packages/app-server-client/src/protocol.ts",
|
|
"packages/app-server-client/src/generated/protocol-types.ts",
|
|
],
|
|
snippets: [],
|
|
absentSnippets: [
|
|
'"agentSession/archiveMany"',
|
|
"AgentSessionArchiveManyParams",
|
|
"AgentSessionArchiveManyResponse",
|
|
'"agentSession/update"',
|
|
"METHOD_AGENT_SESSION_UPDATE",
|
|
"AgentSessionUpdateParams",
|
|
"AgentSessionUpdateResponse",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript client wraps typed thread archive lifecycle helpers",
|
|
file: "packages/app-server-client/src/index.ts",
|
|
snippets: [
|
|
"METHOD_THREAD_ARCHIVE",
|
|
"METHOD_THREAD_UNARCHIVE",
|
|
"archiveThread(params: ThreadArchiveParams): JsonRpcRequest",
|
|
"unarchiveThread(params: ThreadUnarchiveParams): JsonRpcRequest",
|
|
"this.client.archiveThread(params)",
|
|
"this.client.unarchiveThread(params)",
|
|
"Promise<AppServerRequestResult<ThreadArchiveResponse>>",
|
|
"Promise<AppServerRequestResult<ThreadUnarchiveResponse>>",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript protocol exposes typed thread/delete contract",
|
|
file: "packages/app-server-client/src/generated/protocol-types.ts",
|
|
snippets: [
|
|
'export const METHOD_THREAD_DELETE = "thread/delete"',
|
|
"export interface ThreadDeleteParams {",
|
|
"threadId: string",
|
|
"export type ThreadDeleteResponse = Record<string, unknown>;",
|
|
],
|
|
absentSnippets: [
|
|
"METHOD_AGENT_SESSION_DELETE",
|
|
"AgentSessionDeleteParams",
|
|
"AgentSessionDeleteResponse",
|
|
'"agentSession/delete"',
|
|
],
|
|
},
|
|
{
|
|
name: "skills/changed keeps a strict generated notification contract",
|
|
files: [
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v2/methods.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v2/notification.rs",
|
|
"lime-rs/crates/app-server-protocol/schema/json/v2/SkillsChangedNotification.json",
|
|
"packages/app-server-client/src/generated/protocol-types.ts",
|
|
"packages/app-server-client/src/server-notifications.ts",
|
|
],
|
|
snippets: [
|
|
'METHOD_SKILLS_CHANGED: &str = "skills/changed"',
|
|
"pub struct SkillsChangedNotification {}",
|
|
'"additionalProperties": false',
|
|
'export const METHOD_SKILLS_CHANGED = "skills/changed"',
|
|
"export type SkillsChangedNotification = Record<string, never>;",
|
|
"skillsChangedServerNotification",
|
|
"Object.keys(params).length !== 0",
|
|
],
|
|
},
|
|
{
|
|
name: "media/read is the only production media sidecar read contract",
|
|
files: [
|
|
...rustProtocolFiles,
|
|
"lime-rs/crates/app-server/src/lib.rs",
|
|
"lime-rs/crates/app-server/src/processor/agent_session.rs",
|
|
"lime-rs/crates/app-server/src/processor/dispatch.rs",
|
|
"lime-rs/crates/app-server/src/processor/dispatch/v2_ingress.rs",
|
|
"lime-rs/crates/app-server/src/runtime/session_media_reader.rs",
|
|
"lime-rs/crates/app-server/src/runtime/session_media_refs.rs",
|
|
"lime-rs/crates/app-server-protocol/schema/json/v0/AgentSessionMediaReadParams.json",
|
|
"lime-rs/crates/app-server-protocol/schema/json/v0/AgentSessionMediaReadResponse.json",
|
|
"packages/app-server-client/src/generated/protocol-types.ts",
|
|
"packages/app-server-client/src/protocol.ts",
|
|
"packages/app-server-client/src/request-client.ts",
|
|
"packages/app-server-client/src/request-client-methods.ts",
|
|
"packages/app-server-client/src/connection-methods.ts",
|
|
"src/lib/api/appServerConstants.ts",
|
|
"src/lib/api/appServerTypes.ts",
|
|
"src/lib/api/appServerClientMethods.ts",
|
|
"src/lib/api/appServerClientMethodSpecs.ts",
|
|
"src/components/agent/chat/components/MessageImageAttachments.tsx",
|
|
"src/components/agent/chat/workspace/mediaReferencePreviewArtifacts.ts",
|
|
"src/components/agent/chat/workspace/mediaReferencePreviewPagination.ts",
|
|
"src/components/agent/chat/workspace/useWorkspaceMediaReferencePreviewRuntime.ts",
|
|
],
|
|
allowMissingFiles: true,
|
|
snippets: [],
|
|
absentSnippets: [
|
|
'"agentSession/media/read"',
|
|
"METHOD_AGENT_SESSION_MEDIA_READ",
|
|
"AgentSessionMediaReadParams",
|
|
"AgentSessionMediaReadResponse",
|
|
"readAgentSessionMedia",
|
|
"buildAgentSessionMediaReadParams",
|
|
"APP_SERVER_METHOD_AGENT_SESSION_MEDIA_READ",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript protocol and clients expose typed media/read contract",
|
|
files: [
|
|
"packages/app-server-client/src/generated/protocol-types.ts",
|
|
"packages/app-server-client/src/request-client.ts",
|
|
"packages/app-server-client/src/request-client-methods.ts",
|
|
"packages/app-server-client/src/connection-methods.ts",
|
|
"src/lib/api/appServerConstants.ts",
|
|
"src/lib/api/appServerTypes.ts",
|
|
"src/lib/api/appServerClientMethods.ts",
|
|
"src/lib/api/appServerClientMethodSpecs.ts",
|
|
],
|
|
snippets: [
|
|
'export const METHOD_MEDIA_READ = "media/read"',
|
|
"export interface MediaReadParams",
|
|
"threadId: string",
|
|
"export interface MediaReadResponse",
|
|
"readMedia(",
|
|
"METHOD_MEDIA_READ",
|
|
"APP_SERVER_METHOD_MEDIA_READ",
|
|
"AppServerMediaReadParams",
|
|
"AppServerMediaReadResponse",
|
|
],
|
|
},
|
|
{
|
|
name: "media/read uses one typed range response path without raw transient events",
|
|
files: [
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v2/media.rs",
|
|
"lime-rs/crates/app-server/src/processor/agent_session.rs",
|
|
"lime-rs/crates/app-server/src/runtime/session_media_reader.rs",
|
|
"lime-rs/crates/app-server/src/runtime/sidecar_store.rs",
|
|
"lime-rs/crates/app-server/src/lib.rs",
|
|
"packages/app-server-client/src/protocol.ts",
|
|
"packages/app-server-client/src/agent-runtime.ts",
|
|
"packages/agent-runtime-client/src/runtimeClient.ts",
|
|
"packages/agent-runtime-client/src/sessionGateway.ts",
|
|
"src/components/agent/chat/workspace/mediaReferencePreviewArtifacts.ts",
|
|
"src/components/agent/chat/workspace/useWorkspaceMediaReferencePreviewRuntime.ts",
|
|
"src/lib/api/agentRuntime/appServerEventStreamProjection.ts",
|
|
"src/lib/api/agentRuntime/eventSequenceGate.ts",
|
|
],
|
|
snippets: [
|
|
"pub struct MediaReadParams",
|
|
"read_media_with_cancel",
|
|
"read_bytes_range_verified_with_cancel",
|
|
"createMediaReferenceChunkedObjectUrlPreviewArtifact",
|
|
],
|
|
absentSnippets: [
|
|
'"media.read.chunk"',
|
|
'"media.read.completed"',
|
|
"MediaReadEventNotification",
|
|
"mediaReadEventNotification",
|
|
"read_media_streaming_with_cancel",
|
|
"stream_bytes_range_verified_with_cancel",
|
|
"should_stream_transport_request",
|
|
"subscribeMediaReferencePreviewReadProgress",
|
|
"emitStreamingMediaReadProgress",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript client wraps typed thread/delete helper",
|
|
file: "packages/app-server-client/src/index.ts",
|
|
snippets: [
|
|
"METHOD_THREAD_DELETE",
|
|
"deleteThread(params: ThreadDeleteParams): JsonRpcRequest",
|
|
"this.client.deleteThread(params)",
|
|
"Promise<AppServerRequestResult<ThreadDeleteResponse>>",
|
|
],
|
|
absentSnippets: [
|
|
"METHOD_AGENT_SESSION_DELETE",
|
|
"deleteSession(params: AgentSessionDeleteParams)",
|
|
],
|
|
},
|
|
{
|
|
name: "Managed Objective protocol and client surface stays deleted",
|
|
files: [
|
|
...rustProtocolFiles,
|
|
"lime-rs/crates/app-server/src/objective.rs",
|
|
"lime-rs/crates/app-server/src/runtime/objectives.rs",
|
|
"packages/app-server-client/src/protocol.ts",
|
|
"packages/app-server-client/src/generated/protocol-types.ts",
|
|
"packages/app-server-client/src/index.ts",
|
|
"packages/app-server-client/src/request-client-methods.ts",
|
|
"src/lib/api/appServerTypes.ts",
|
|
"src/lib/api/agentRuntime/clientFactory.ts",
|
|
"src/lib/api/agentRuntime/objectiveClient.ts",
|
|
"src/lib/api/agentRuntime/sessionTypes.ts",
|
|
],
|
|
allowMissingFiles: true,
|
|
snippets: [],
|
|
absentSnippets: [
|
|
"agentSession/objective/",
|
|
"AgentSessionObjective",
|
|
"ManagedObjective",
|
|
"AgentRuntimeObjectiveAppServerClient",
|
|
"createObjectiveClient",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript connection methods derive from request client protocol specs",
|
|
file: "packages/app-server-client/src/connection-methods.ts",
|
|
snippets: [
|
|
"APP_SERVER_REQUEST_CLIENT_METHODS.filter(",
|
|
"CONNECTION_CLIENT_METHOD_EXCLUSIONS",
|
|
'spec.kind === "request"',
|
|
"clientMethod: spec.name",
|
|
"method: spec.method",
|
|
"params: spec.params",
|
|
],
|
|
absentSnippets: ["method: protocol.METHOD_"],
|
|
},
|
|
{
|
|
name: "TypeScript request client exposes the single wrapper protocol spec",
|
|
file: "packages/app-server-client/src/request-client-methods.ts",
|
|
snippets: [
|
|
"export type AppServerRequestClientMethodSpec",
|
|
"export const APP_SERVER_REQUEST_CLIENT_METHODS",
|
|
"installAppServerRequestClientMethods(",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript capability/list tests lock helper and connection shape",
|
|
file: "packages/app-server-client/tests/client.test.mjs",
|
|
snippets: [
|
|
"APP_SERVER_METHODS",
|
|
"METHOD_CAPABILITY_LIST",
|
|
"builds capability list requests with empty params",
|
|
"exports app-server method catalog from checked-in Rust manifest",
|
|
"METHOD_THREAD_DELETE",
|
|
"assert.equal(deleteThread.method, METHOD_THREAD_DELETE)",
|
|
"isAppServerRequestMethod(METHOD_TURN_START)",
|
|
"isAppServerNotificationMethod(METHOD_AGENT_SESSION_EVENT)",
|
|
"connection wraps capability list response",
|
|
"connection keeps streamed notifications independent from request error context",
|
|
"error instanceof AppServerRequestError",
|
|
"assert.equal(error.notifications.length, 0)",
|
|
'assert.equal(partial.params.event.type, "message.delta")',
|
|
'assert.equal(failed.params.event.type, "turn.failed")',
|
|
"assert.deepEqual(capabilities.params, {})",
|
|
"assert.deepEqual(scopedCapabilities.params, {",
|
|
'appId: "content-studio"',
|
|
'workspaceId: "default"',
|
|
'sessionId: "sess_external"',
|
|
'cursor: "2"',
|
|
"limit: 25",
|
|
'assert.equal(result.result.nextCursor, "1")',
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript action respond tests lock helper and connection shape",
|
|
file: "packages/app-server-client/tests/client.test.mjs",
|
|
snippets: [
|
|
"METHOD_AGENT_SESSION_ACTION_RESPOND",
|
|
"builds action respond requests for host action resolution",
|
|
"connection wraps action respond response",
|
|
'actionType: "tool_confirmation"',
|
|
"assert.equal(response.method, METHOD_AGENT_SESSION_ACTION_RESPOND)",
|
|
"assert.equal(sent[0].method, METHOD_AGENT_SESSION_ACTION_RESPOND)",
|
|
'assert.equal(sent[0].params.actionScope.turnId, "turn_external")',
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript artifact/read tests lock helper and connection shape",
|
|
file: "packages/app-server-client/tests/client.test.mjs",
|
|
snippets: [
|
|
"METHOD_ARTIFACT_READ",
|
|
"builds artifact read requests with optional content lookup",
|
|
"connection wraps artifact read response",
|
|
"assert.equal(artifacts.method, METHOD_ARTIFACT_READ)",
|
|
"assert.equal(sent[0].method, METHOD_ARTIFACT_READ)",
|
|
'artifactRef: "artifact-document:req-1"',
|
|
"includeContent: true",
|
|
'assert.equal(result.result.artifacts[0].content, "# Report")',
|
|
'assert.equal(result.result.artifacts[0].contentStatus, "available")',
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript exact fs tests lock helper and connection shape",
|
|
file: "packages/app-server-client/tests/client.test.mjs",
|
|
snippets: [
|
|
"METHOD_FS_READ_FILE",
|
|
"METHOD_FS_WRITE_FILE",
|
|
"METHOD_FS_CREATE_DIRECTORY",
|
|
"METHOD_FS_GET_METADATA",
|
|
"METHOD_FS_READ_DIRECTORY",
|
|
"METHOD_FS_REMOVE",
|
|
"METHOD_FS_COPY",
|
|
"METHOD_FS_WATCH",
|
|
"METHOD_FS_UNWATCH",
|
|
'test("builds exact fs requests"',
|
|
"assert.equal(readFile.method, METHOD_FS_READ_FILE)",
|
|
"assert.equal(writeFile.method, METHOD_FS_WRITE_FILE)",
|
|
"assert.equal(createDirectory.method, METHOD_FS_CREATE_DIRECTORY)",
|
|
"assert.equal(getMetadata.method, METHOD_FS_GET_METADATA)",
|
|
"assert.equal(readDirectory.method, METHOD_FS_READ_DIRECTORY)",
|
|
"assert.equal(remove.method, METHOD_FS_REMOVE)",
|
|
"assert.equal(copy.method, METHOD_FS_COPY)",
|
|
"assert.equal(watch.method, METHOD_FS_WATCH)",
|
|
"assert.equal(unwatch.method, METHOD_FS_UNWATCH)",
|
|
'test("connection wraps exact fs responses"',
|
|
'assert.equal(readFileResult.result.dataBase64, "IyBMaW1l")',
|
|
'assert.equal(directoryResult.result.entries[0].fileName, "README.md")',
|
|
'assert.equal(watchResult.result.path, "/workspace")',
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript derived export tests lock helper and connection shape",
|
|
file: "packages/app-server-client/tests/client.test.mjs",
|
|
snippets: [
|
|
"METHOD_AGENT_SESSION_REPLAY_CASE_EXPORT",
|
|
"METHOD_AGENT_SESSION_ANALYSIS_HANDOFF_EXPORT",
|
|
"METHOD_AGENT_SESSION_REVIEW_DECISION_TEMPLATE_EXPORT",
|
|
"METHOD_AGENT_SESSION_REVIEW_DECISION_SAVE",
|
|
"builds derived export requests",
|
|
"assert.equal(replay.method, METHOD_AGENT_SESSION_REPLAY_CASE_EXPORT)",
|
|
"assert.equal(analysis.method, METHOD_AGENT_SESSION_ANALYSIS_HANDOFF_EXPORT)",
|
|
"assert.equal(save.method, METHOD_AGENT_SESSION_REVIEW_DECISION_SAVE)",
|
|
"connection wraps derived agent session export responses",
|
|
"connection.exportReplayCase",
|
|
"connection.exportAnalysisHandoff",
|
|
"connection.exportReviewDecisionTemplate",
|
|
"connection.saveReviewDecision",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer-safe App Server helper aliases capability/list protocol types",
|
|
file: "src/lib/api/appServer.ts",
|
|
snippets: [
|
|
"APP_SERVER_METHOD_CAPABILITY_LIST = protocol.METHOD_CAPABILITY_LIST",
|
|
"export type AppServerCapabilityListParams = protocol.CapabilityListParams;",
|
|
"export type AppServerCapabilityListResponse = protocol.CapabilityListResponse;",
|
|
"listCapabilities(params?: appServer.AppServerCapabilityListParams)",
|
|
'{ name: "listCapabilities", method: constants.APP_SERVER_METHOD_CAPABILITY_LIST',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer-safe App Server helper aliases exact fs protocol types",
|
|
file: "src/lib/api/appServer.ts",
|
|
snippets: [
|
|
"export const APP_SERVER_METHOD_FS_READ_FILE = protocol.METHOD_FS_READ_FILE",
|
|
"export const APP_SERVER_METHOD_FS_WRITE_FILE = protocol.METHOD_FS_WRITE_FILE",
|
|
"protocol.METHOD_FS_CREATE_DIRECTORY",
|
|
"protocol.METHOD_FS_GET_METADATA",
|
|
"protocol.METHOD_FS_READ_DIRECTORY",
|
|
"export const APP_SERVER_METHOD_FS_REMOVE = protocol.METHOD_FS_REMOVE",
|
|
"export const APP_SERVER_METHOD_FS_COPY = protocol.METHOD_FS_COPY",
|
|
"export const APP_SERVER_METHOD_FS_WATCH = protocol.METHOD_FS_WATCH",
|
|
"export const APP_SERVER_METHOD_FS_UNWATCH = protocol.METHOD_FS_UNWATCH",
|
|
"export const APP_SERVER_METHOD_FS_CHANGED = protocol.METHOD_FS_CHANGED",
|
|
"export type AppServerFsReadFileParams = protocol.FsReadFileParams",
|
|
"export type AppServerFsWriteFileParams = protocol.FsWriteFileParams",
|
|
"protocol.FsCreateDirectoryParams",
|
|
"export type AppServerFsGetMetadataParams = protocol.FsGetMetadataParams",
|
|
"export type AppServerFsReadDirectoryParams = protocol.FsReadDirectoryParams",
|
|
"export type AppServerFsRemoveParams = protocol.FsRemoveParams",
|
|
"export type AppServerFsCopyParams = protocol.FsCopyParams",
|
|
"export type AppServerFsWatchParams = protocol.FsWatchParams",
|
|
"export type AppServerFsUnwatchParams = protocol.FsUnwatchParams",
|
|
"export type AppServerFsChangedNotification = protocol.FsChangedNotification",
|
|
"readFile(params: appServer.AppServerFsReadFileParams)",
|
|
'{ name: "readFile", method: constants.APP_SERVER_METHOD_FS_READ_FILE',
|
|
"writeFile(params: appServer.AppServerFsWriteFileParams)",
|
|
'{ name: "writeFile", method: constants.APP_SERVER_METHOD_FS_WRITE_FILE',
|
|
"createDirectory(params: appServer.AppServerFsCreateDirectoryParams)",
|
|
'{ name: "createDirectory", method: constants.APP_SERVER_METHOD_FS_CREATE_DIRECTORY',
|
|
"getMetadata(params: appServer.AppServerFsGetMetadataParams)",
|
|
'{ name: "getMetadata", method: constants.APP_SERVER_METHOD_FS_GET_METADATA',
|
|
"readDirectory(params: appServer.AppServerFsReadDirectoryParams)",
|
|
'{ name: "readDirectory", method: constants.APP_SERVER_METHOD_FS_READ_DIRECTORY',
|
|
"remove(params: appServer.AppServerFsRemoveParams)",
|
|
'{ name: "remove", method: constants.APP_SERVER_METHOD_FS_REMOVE',
|
|
"copy(params: appServer.AppServerFsCopyParams)",
|
|
'{ name: "copy", method: constants.APP_SERVER_METHOD_FS_COPY',
|
|
"watch(params: appServer.AppServerFsWatchParams)",
|
|
'{ name: "watch", method: constants.APP_SERVER_METHOD_FS_WATCH',
|
|
"unwatch(params: appServer.AppServerFsUnwatchParams)",
|
|
'{ name: "unwatch", method: constants.APP_SERVER_METHOD_FS_UNWATCH',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer file browser uses exact fs current path and no legacy fallback",
|
|
file: "src/lib/api/fileBrowser.test.ts",
|
|
snippets: [
|
|
"appServerReadDirectoryMock",
|
|
"appServerReadFileMock",
|
|
"appServerWriteFileMock",
|
|
"appServerCreateDirectoryMock",
|
|
"appServerGetMetadataMock",
|
|
"appServerCopyMock",
|
|
"appServerRemoveMock",
|
|
"应通过 App Server current 主链获取目录列表与文件预览",
|
|
"文件预览应在 renderer 解码、截断文本并识别二进制",
|
|
"应代理文件增删改命令",
|
|
"文件写命令应透传 App Server RPC 错误",
|
|
"创建目录时应原样传递 Windows 原生路径",
|
|
"expect(appServerReadFileMock).toHaveBeenCalledWith(",
|
|
"expect(appServerWriteFileMock).toHaveBeenCalledWith(",
|
|
"expect(appServerCopyMock).toHaveBeenCalledWith(",
|
|
"expect(appServerRemoveMock).toHaveBeenNthCalledWith(",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer-safe App Server helper aliases action respond protocol types",
|
|
file: "src/lib/api/appServer.ts",
|
|
snippets: [
|
|
"export const APP_SERVER_METHOD_AGENT_SESSION_ACTION_RESPOND =",
|
|
"protocol.METHOD_AGENT_SESSION_ACTION_RESPOND;",
|
|
"export type AppServerAgentSessionActionType = protocol.AgentSessionActionType;",
|
|
"export type AppServerAgentSessionActionRespondParams =\n AgentSessionActionRespondParams;",
|
|
"export type AppServerAgentSessionActionRespondResponse =\n protocol.AgentSessionActionRespondResponse;",
|
|
"respondAction(params: appServer.AppServerAgentSessionActionRespondParams)",
|
|
'{ name: "respondAction", method: constants.APP_SERVER_METHOD_AGENT_SESSION_ACTION_RESPOND',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer-safe App Server helper aliases turn cancel protocol types",
|
|
file: "src/lib/api/appServer.ts",
|
|
snippets: [
|
|
"export const APP_SERVER_METHOD_TURN_INTERRUPT =",
|
|
"protocol.METHOD_TURN_INTERRUPT;",
|
|
"export type AppServerAgentSessionTurnCancelParams =\n protocol.AgentSessionTurnCancelParams;",
|
|
"export type AppServerAgentSessionTurnCancelResponse =\n protocol.AgentSessionTurnCancelResponse;",
|
|
"cancelTurn(params: appServer.AppServerAgentSessionTurnCancelParams)",
|
|
'{ name: "cancelTurn", method: constants.APP_SERVER_METHOD_TURN_INTERRUPT',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer-safe App Server helper exposes typed turn steer",
|
|
file: "src/lib/api/appServer.ts",
|
|
snippets: [
|
|
"export const APP_SERVER_METHOD_TURN_STEER = protocol.METHOD_TURN_STEER;",
|
|
"export type AppServerTurnSteerParams = protocol.TurnSteerParams;",
|
|
"export type AppServerTurnSteerResponse = protocol.TurnSteerResponse;",
|
|
"steerTurn(params: appServer.AppServerTurnSteerParams)",
|
|
'{ name: "steerTurn", method: constants.APP_SERVER_METHOD_TURN_STEER',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime thread client requires centralized App Server bridge availability",
|
|
files: [
|
|
"src/lib/api/agentRuntime/threadClient.ts",
|
|
"src/lib/api/agentRuntime/appServerEventStream.ts",
|
|
"src/lib/api/agentRuntime/appServerEventStreamRouting.ts",
|
|
"src/lib/api/agentRuntime/appServerEventStreamProjection.ts",
|
|
"src/lib/api/agentRuntime/appServerV2Notification.ts",
|
|
"src/lib/api/agentRuntime/appServerEventTimelineReaders.ts",
|
|
],
|
|
snippets: [
|
|
"isAppServerBridgeAvailable",
|
|
"export type AgentRuntimeAppServerClient = Pick<",
|
|
"appServerClient = new AppServerClient()",
|
|
"isAppServerTurnLifecycleAvailable = defaultIsAppServerTurnLifecycleAvailable",
|
|
"assertAppServerTurnLifecycleAvailable(isAppServerTurnLifecycleAvailable)",
|
|
"Agent Runtime requires the App Server current lifecycle channel",
|
|
"appServerClient.startTurn(",
|
|
"standardRuntimeClient.startTurn(params)",
|
|
"createAppServerAgentRuntimeLifecycleClient(",
|
|
"appServerClient.cancelTurn(",
|
|
"appServerTurnCancelParamsFromRequest(request)",
|
|
"request.turn_id",
|
|
"appServerClient.startThreadCompaction(",
|
|
"const params: ThreadResumeParams",
|
|
"appServerClient.resumeThread(params)",
|
|
"findPendingTypedServerRequestAction(",
|
|
"replayedActionViewFromPendingAction(",
|
|
"respondPendingTypedServerRequest(request)",
|
|
"generic agentSession/action/respond is retired",
|
|
"publishAppServerAgentSessionNotifications(",
|
|
'from "./appServerEventStream"',
|
|
"projectAppServerAgentEventPayload(",
|
|
"APP_SERVER_METHOD_AGENT_SESSION_EVENT",
|
|
"publishProcessedAgentRuntimeEvent(eventName, payload)",
|
|
'"thread/started"',
|
|
'"turn/started"',
|
|
'"turn/completed"',
|
|
'"item/started"',
|
|
'"item/completed"',
|
|
'"item/agentMessage/delta"',
|
|
'type: "text_delta"',
|
|
'"item_completed"',
|
|
'type: "runtime_status"',
|
|
'return "turn_completed"',
|
|
'return "turn_failed"',
|
|
'return "turn_canceled"',
|
|
],
|
|
absentSnippets: [
|
|
'const APP_SERVER_HANDLE_JSON_LINES_COMMAND = "app_server_handle_json_lines"',
|
|
"isElectronHostCommandAvailable(APP_SERVER_HANDLE_JSON_LINES_COMMAND)",
|
|
"AGENT_RUNTIME_COMMANDS.submitTurn",
|
|
"AGENT_RUNTIME_COMMANDS.respondAction",
|
|
"appServerClient.respondAction(",
|
|
"standardRuntimeClient.respondAction(",
|
|
"appServerActionRespondParamsFromRequest",
|
|
"AGENT_RUNTIME_COMMANDS.compactSession",
|
|
"AGENT_RUNTIME_COMMANDS.resumeThread",
|
|
"AGENT_RUNTIME_COMMANDS.removeQueuedTurn",
|
|
"AGENT_RUNTIME_COMMANDS.promoteQueuedTurn",
|
|
'"agent_runtime_compact_session"',
|
|
'"agent_runtime_resume_thread"',
|
|
'"agent_runtime_remove_queued_turn"',
|
|
'"agent_runtime_promote_queued_turn"',
|
|
"resumeAgentSessionThread",
|
|
"resumeAgentRuntimeThread",
|
|
"RuntimeResumeContract",
|
|
"runtimeRequest: {",
|
|
"appServerTurnStartParamsFromRequest",
|
|
"appServerRuntimeRequestFromRequest",
|
|
"turnConfig",
|
|
"turn_config",
|
|
"agentChatRequest",
|
|
"agent_chat_request",
|
|
"hostOptions",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer App Server bridge availability centralizes legacy IPC command name",
|
|
file: "src/lib/api/appServerBridgeAvailability.ts",
|
|
snippets: [
|
|
'const APP_SERVER_HANDLE_JSON_LINES_COMMAND = "app_server_handle_json_lines"',
|
|
"isElectronHostCommandAvailable(APP_SERVER_HANDLE_JSON_LINES_COMMAND)",
|
|
"isDevBridgeAvailable()",
|
|
"export function isAppServerBridgeAvailable(): boolean",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer user input op owns one typed turn/start payload",
|
|
files: [
|
|
"src/lib/api/agentProtocolOps.ts",
|
|
"src/lib/api/agentProtocol.d.ts",
|
|
],
|
|
snippets: [
|
|
"export interface AgentUserInputOp {",
|
|
"turn: TurnStartParams;",
|
|
"const { additionalContext: turnContext, ...turn } = op.turn",
|
|
],
|
|
absentSnippets: [
|
|
"AgentUserPreferences",
|
|
"preferences?:",
|
|
"providerConfig?:",
|
|
"providerPreference?:",
|
|
"webSearch?:",
|
|
"searchMode?:",
|
|
"systemPrompt?:",
|
|
"workspaceId?:",
|
|
"queueIfBusy?:",
|
|
"skipPreSubmitResume?:",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer submit builder emits typed turn fields instead of runtime preferences",
|
|
file: "src/components/agent/chat/utils/buildUserInputSubmitOp.ts",
|
|
snippets: [
|
|
"turn: {",
|
|
"threadId: currentThreadId",
|
|
"input: buildTurnInput(",
|
|
"compaction.shouldSubmitModel",
|
|
"approvalPolicy: runtimePolicies.approvalPolicy",
|
|
"permissions: permissionProfileIdFromAccessMode(effectiveAccessMode)",
|
|
"const collaborationMode = buildCollaborationMode(",
|
|
"metadata: compaction.metadata",
|
|
"collaborationMode ? { collaborationMode } : {}",
|
|
"? { additionalContext }",
|
|
],
|
|
absentSnippets: [
|
|
"preferences: {",
|
|
"providerConfig: compaction.providerConfig",
|
|
"providerPreference: compaction.shouldSubmitProviderPreference",
|
|
"webSearch: compaction.shouldSubmitWebSearch",
|
|
"executionStrategy: compaction.shouldSubmitExecutionStrategy",
|
|
"autoContinue,",
|
|
"systemPrompt,",
|
|
"workspaceId,",
|
|
"turnId,",
|
|
"lowerCollaborationMode",
|
|
"collaboration_mode",
|
|
"sandboxPolicy: runtimePolicies.sandboxPolicy",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer submit compaction owns only metadata sanitizing and typed model decisions",
|
|
files: [
|
|
"src/components/agent/chat/utils/submitOpRuntimeCompaction.ts",
|
|
"src/components/agent/chat/utils/submitOpRuntimeCompaction.test.ts",
|
|
],
|
|
snippets: [
|
|
"export interface SubmitOpRuntimeCompactionResult {",
|
|
"shouldSubmitModel: boolean",
|
|
"sanitizeSubmitMetadata(options)",
|
|
"shouldSubmitModel: shouldSubmitTurnModel(options, metadata)",
|
|
"RETIRED_TOOL_PREFERENCE_PATH",
|
|
"existsSync(resolve(process.cwd(), RETIRED_TOOL_PREFERENCE_PATH))",
|
|
],
|
|
absentSnippets: [
|
|
'from "./submitOpToolPreferenceCompaction"',
|
|
"RuntimeProviderConfig",
|
|
"providerConfig?:",
|
|
"shouldSubmitProviderPreference",
|
|
"shouldSubmitModelPreference",
|
|
"shouldSubmitExecutionStrategy",
|
|
"shouldSubmitWebSearch",
|
|
"shouldSubmitThinking",
|
|
"webSearchPreference",
|
|
"thinkingPreference",
|
|
"requestedWebSearch",
|
|
"requestedThinking",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime thread client keeps current turn/start typed",
|
|
file: "src/lib/api/agentRuntime/threadClient.test.ts",
|
|
snippets: [
|
|
"App Server submit 参数只保留 typed Turn 配置与业务 metadata",
|
|
'model: "deepseek-v4-pro"',
|
|
'effort: "high"',
|
|
'approvalPolicy: "on-request"',
|
|
'sandboxPolicy: "workspace-write"',
|
|
"metadata: {",
|
|
"outputSchema,",
|
|
],
|
|
absentSnippets: [
|
|
"runtimeRequest?: Record<string, unknown>",
|
|
"queueIfBusy?: boolean",
|
|
"skipPreSubmitResume?: boolean",
|
|
'queuedTurnId: "queued-claw"',
|
|
'providerPreference: "deepseek"',
|
|
"providerConfig: {",
|
|
"thinkingEnabled: true",
|
|
"webSearch: true",
|
|
'searchMode: "required"',
|
|
'executionStrategy: "react"',
|
|
"autoContinue: true",
|
|
'systemPrompt: "保留 Claw 原始系统提示"',
|
|
'workspaceId: "workspace-claw"',
|
|
"hostOptions: {",
|
|
"agentChatRequest",
|
|
"agent_chat_request",
|
|
"turn_config",
|
|
"turnConfig",
|
|
],
|
|
},
|
|
{
|
|
name: "Current Turn submission accepts only RuntimeRequest across renderer and smoke evidence",
|
|
files: [
|
|
"src/lib/api/agentProtocolOps.ts",
|
|
"src/components/agent/chat/hooks/agentRuntimeAdapter.ts",
|
|
"src/lib/api/agentRuntime/threadClient.ts",
|
|
"scripts/claw-chat-ready-streaming-smoke.mjs",
|
|
"scripts/lib/agent-runtime-smoke-core.mjs",
|
|
"scripts/agent-runtime/claw-chat-current-fixture-backend-script.mjs",
|
|
"scripts/agent-runtime/claw-chat-current-fixture-backend-ledger.mjs",
|
|
],
|
|
snippets: ["runtimeRequest", "AgentSessionTurnStartParams"],
|
|
absentSnippets: [
|
|
"agentChatRequest",
|
|
"agent_chat_request",
|
|
"turn_config",
|
|
"turnConfig",
|
|
"hostOptions",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime client factory forwards App Server lifecycle deps",
|
|
file: "src/lib/api/agentRuntime/clientFactory.ts",
|
|
snippets: [
|
|
'import type { AppServerSessionRpcClient } from "./appServerSessionClient"',
|
|
"type AgentRuntimeExportAppServerClient",
|
|
"type AgentRuntimeWorkspaceSkillBindingsAppServerClient",
|
|
"type AgentRuntimeThreadClientDeps",
|
|
"export type AgentRuntimeAppServerClient =",
|
|
'AgentRuntimeThreadClientDeps["appServerClient"] &',
|
|
"AppServerSessionRpcClient &",
|
|
"AgentRuntimeExportAppServerClient &",
|
|
"AgentRuntimeWorkspaceSkillBindingsAppServerClient;",
|
|
"appServerClient?: AgentRuntimeAppServerClient",
|
|
'isAppServerTurnLifecycleAvailable?: AgentRuntimeThreadClientDeps["isAppServerTurnLifecycleAvailable"]',
|
|
"appServerClient,",
|
|
"isAppServerTurnLifecycleAvailable,",
|
|
"...createExportClient({",
|
|
"appServerClient,",
|
|
"...createInventoryClient({",
|
|
"appServerClient,",
|
|
"...createSessionClient({",
|
|
"appServerClient,",
|
|
"...createThreadClient({",
|
|
"appServerClient,",
|
|
"isAppServerTurnLifecycleAvailable,",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime inventory client uses App Server workspace skill bindings",
|
|
file: "src/lib/api/agentRuntime/inventoryClient.ts",
|
|
snippets: [
|
|
'import { AppServerClient } from "@/lib/api/appServer"',
|
|
"METHOD_WORKSPACE_SKILL_BINDINGS_LIST",
|
|
'from "../../../../packages/app-server-client/src/protocol"',
|
|
"export type AgentRuntimeWorkspaceSkillBindingsAppServerClient = Pick<",
|
|
"AppServerClient,",
|
|
'"request"',
|
|
"appServerClient = new AppServerClient()",
|
|
"const workspaceRoot = request.workspaceRoot.trim()",
|
|
'throw new Error(\n "workspaceRoot is required to list App Server workspace skill bindings"',
|
|
"appServerClient.request<AppServerWorkspaceSkillBindingsListResponse>",
|
|
"METHOD_WORKSPACE_SKILL_BINDINGS_LIST",
|
|
"workspaceSkillBindingsListParamsFromRequest(request, workspaceRoot)",
|
|
"App Server workspaceSkillBindings/list did not return bindings",
|
|
"return response.result.bindings",
|
|
],
|
|
absentSnippets: [
|
|
"APP_SERVER_METHOD_WORKSPACE_SKILL_BINDINGS_LIST",
|
|
"AGENT_RUNTIME_COMMANDS.listWorkspaceSkillBindings",
|
|
'"agent_runtime_list_workspace_skill_bindings"',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Capability Drafts registered skills discovery uses App Server current method",
|
|
file: "src/lib/api/capabilityDrafts.ts",
|
|
snippets: [
|
|
'import { AppServerClient } from "@/lib/api/appServer"',
|
|
"METHOD_WORKSPACE_REGISTERED_SKILLS_LIST",
|
|
'from "../../../packages/app-server-client/src/protocol"',
|
|
'type CapabilityDraftsAppServerClient = Pick<AppServerClient, "request">',
|
|
"appServerClient: new AppServerClient() as CapabilityDraftsAppServerClient",
|
|
"const workspaceRoot = request.workspaceRoot.trim()",
|
|
'throw new Error(\n "workspaceRoot is required to list App Server workspace registered skills"',
|
|
"this.appServerClient.request<",
|
|
"METHOD_WORKSPACE_REGISTERED_SKILLS_LIST",
|
|
"App Server workspaceRegisteredSkills/list did not return skills",
|
|
"return response.result.skills.map(normalizeWorkspaceRegisteredSkill)",
|
|
],
|
|
absentSnippets: ['"capability_draft_list_registered_skills"'],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime tool inventory uses App Server current method",
|
|
file: "src/lib/api/agentRuntime/inventoryClient.ts",
|
|
snippets: [
|
|
"async function getAgentRuntimeToolInventory(",
|
|
"METHOD_AGENT_SESSION_TOOL_INVENTORY_READ",
|
|
"appServerClient.request<AppServerToolInventoryReadResponse>",
|
|
"toolInventoryParamsFromRequest(request)",
|
|
"App Server agentSession/toolInventory/read did not return tool inventory",
|
|
],
|
|
absentSnippets: [
|
|
"APP_SERVER_METHOD_CAPABILITY_LIST",
|
|
"listCapabilities(",
|
|
"AGENT_RUNTIME_COMMANDS.getToolInventory",
|
|
"agent_runtime_get_tool_inventory",
|
|
"invokeCommand<AgentRuntimeToolInventory>",
|
|
],
|
|
},
|
|
{
|
|
name: "Agent Runtime workspace skill bindings legacy command is retired from production command surfaces",
|
|
files: [
|
|
"electron/hostCommands.ts",
|
|
"electron/ipcChannels.ts",
|
|
"src/lib/dev-bridge/commandPolicy.ts",
|
|
"src/lib/governance/agentCommandCatalog.json",
|
|
],
|
|
snippets: [],
|
|
absentSnippets: ['"agent_runtime_list_workspace_skill_bindings"'],
|
|
},
|
|
{
|
|
name: "Agent Runtime retired subagent facade names stay out of production gateway policy",
|
|
file: "src/lib/dev-bridge/commandPolicy.ts",
|
|
snippets: [],
|
|
absentSnippets: [
|
|
'"agent_runtime_spawn_subagent"',
|
|
'"agent_runtime_send_subagent_input"',
|
|
'"agent_runtime_wait_subagents"',
|
|
'"agent_runtime_resume_subagent"',
|
|
'"agent_runtime_close_subagent"',
|
|
'command.startsWith("agent_runtime_")',
|
|
],
|
|
},
|
|
{
|
|
name: "Prompt-to-artifact smoke uses App Server current discovery and binding readiness",
|
|
file: "scripts/prompt-to-artifact-smoke.mjs",
|
|
snippets: [
|
|
"writeWorkspaceSkillFixture",
|
|
"registrationSurface",
|
|
"direct-workspace-skill-fixture",
|
|
"retiredCommandSurface",
|
|
"dead/guard-only",
|
|
'"app_server_handle_json_lines"',
|
|
'"workspaceRegisteredSkills/list"',
|
|
'"workspaceSkillBindings/list"',
|
|
],
|
|
absentSnippets: [
|
|
'"capability_draft_list_registered_skills"',
|
|
'"capability_draft_create"',
|
|
'"capability_draft_verify"',
|
|
'"capability_draft_register"',
|
|
'"agent_runtime_list_workspace_skill_bindings"',
|
|
],
|
|
},
|
|
{
|
|
name: "Read-only HTTP API smoke no longer invokes retired Capability Draft authoring commands",
|
|
file: "scripts/readonly-http-api-smoke.mjs",
|
|
snippets: [
|
|
"buildReadonlyHttpApiGeneratedFiles",
|
|
"writeWorkspaceSkillFixture",
|
|
"registrationSurface",
|
|
"direct-workspace-skill-fixture",
|
|
"retiredCommandSurface",
|
|
"dead/guard-only",
|
|
'"app_server_handle_json_lines"',
|
|
'"workspaceRegisteredSkills/list"',
|
|
'"workspaceSkillBindings/list"',
|
|
],
|
|
absentSnippets: [
|
|
'"capability_draft_create"',
|
|
'"capability_draft_verify"',
|
|
'"capability_draft_register"',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime session client uses App Server session facade",
|
|
file: "src/lib/api/agentRuntime/sessionClient.ts",
|
|
snippets: [
|
|
"import {",
|
|
"createAppServerSessionClient",
|
|
"type AppServerSessionClient",
|
|
"type AppServerSessionRpcClient",
|
|
"const defaultAppServerSessionClient = createAppServerSessionClient()",
|
|
"deps.appServerSessionClient ??",
|
|
"createAppServerSessionClient({ appServerClient: deps.appServerClient })",
|
|
"appServerSessionClient.createAgentRuntimeSession(",
|
|
"appServerSessionClient.listAgentRuntimeSessions({",
|
|
"appServerSessionClient.getAgentRuntimeSession(",
|
|
"appServerSessionClient.updateAgentRuntimeThreadToolPreferences(",
|
|
"appServerSessionClient.archiveAgentRuntimeSession(sessionId)",
|
|
"appServerSessionClient.unarchiveAgentRuntimeSession(sessionId)",
|
|
"async function deleteAgentRuntimeSession(sessionId: string): Promise<void>",
|
|
"appServerSessionClient.deleteAgentRuntimeSession(sessionId)",
|
|
'reason: "deleted"',
|
|
'"deleted"',
|
|
"AGENT_RUNTIME_SESSIONS_CHANGED_EVENT",
|
|
"notifyAgentRuntimeSessionsChanged(",
|
|
],
|
|
absentSnippets: [
|
|
"AGENT_RUNTIME_COMMANDS.createSession",
|
|
"AGENT_RUNTIME_COMMANDS.listSessions",
|
|
"AGENT_RUNTIME_COMMANDS.getSession",
|
|
"AGENT_RUNTIME_COMMANDS.updateSession",
|
|
"AGENT_RUNTIME_COMMANDS.deleteSession",
|
|
'"agent_runtime_create_session"',
|
|
'"agent_runtime_list_sessions"',
|
|
'"agent_runtime_get_session"',
|
|
'"agent_runtime_update_session"',
|
|
'"agent_runtime_delete_session"',
|
|
"updateAgentRuntimeSession",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer App Server session facade and history window use protocol method constants",
|
|
files: [
|
|
"src/lib/api/agentRuntime/appServerSessionClient.ts",
|
|
"src/lib/api/agentRuntime/canonicalThreadHistoryWindow.ts",
|
|
],
|
|
snippets: [
|
|
"METHOD_THREAD_LIST,",
|
|
"METHOD_THREAD_ITEMS_LIST,",
|
|
"METHOD_THREAD_TURNS_LIST,",
|
|
"export type AppServerSessionRpcClient = Pick<",
|
|
'| "startSession"',
|
|
'| "readThread"',
|
|
'| "updateThreadSettings"',
|
|
'| "archiveThread"',
|
|
'| "unarchiveThread"',
|
|
'| "deleteThread"',
|
|
'| "request"',
|
|
"client.request<AppServerThreadListResponse>",
|
|
"METHOD_THREAD_LIST",
|
|
"listCanonicalSessionOverviews(",
|
|
"appServerThreadReadParams(threadId, false)",
|
|
"appServerClient.readThread(",
|
|
"appServerClient.updateThreadSettings(",
|
|
"appServerClient.archiveThread(",
|
|
"appServerClient.unarchiveThread(",
|
|
"appServerClient.deleteThread(",
|
|
'"thread/settings/update"',
|
|
'"thread/archive"',
|
|
'"thread/unarchive"',
|
|
'"thread/delete"',
|
|
],
|
|
absentSnippets: [
|
|
"APP_SERVER_METHOD_THREAD_LIST",
|
|
'const APP_SERVER_METHOD_THREAD_LIST = "thread/list"',
|
|
"readAppServerAgentSessionReadResponse",
|
|
"readSessionDetail",
|
|
"appServerClient.readSession(",
|
|
'"agent_runtime_list_sessions"',
|
|
'"agent_runtime_get_session"',
|
|
'"agent_runtime_create_session"',
|
|
'"agent_runtime_update_session"',
|
|
"appServerClient.updateSession(",
|
|
"updateAgentRuntimeSession",
|
|
"appServerSessionUpdateParamsFromRequest",
|
|
"recentTeamSelection",
|
|
"recent_team_selection",
|
|
"archiveManySessions",
|
|
"agentSession/archiveMany",
|
|
"appServerClient.deleteSession(",
|
|
'"agentSession/delete"',
|
|
"request.archived",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer App Server session facade tests reject legacy read envelopes",
|
|
file: "src/lib/api/agentRuntime/appServerSessionClient.test.ts",
|
|
snippets: [
|
|
"get 应从 canonical Thread items 恢复消息并分离排队回合",
|
|
"get 遇到旧 session envelope 时应显式拒绝,不恢复兼容解析",
|
|
"appServerClient.readThread",
|
|
'threadId: "session-codex"',
|
|
"includeTurns: false",
|
|
"thread/read did not return canonical session detail",
|
|
],
|
|
absentSnippets: [
|
|
"appServerClient.readSession",
|
|
"readSessionResult",
|
|
'"agent_runtime_get_session"',
|
|
"invokeMockOnly",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer chat history hydration tests consume App Server read detail messages",
|
|
file: "src/components/agent/chat/hooks/agentChatHistory.test.ts",
|
|
snippets: [
|
|
"App Server read detail.messages 当前形状应直接恢复用户与助手消息",
|
|
"messages_count: 2",
|
|
"history_cursor: {",
|
|
"loaded_count: 2",
|
|
"请整理 App Server 对话历史",
|
|
"已从 App Server detail.messages 读取。",
|
|
"hydrateSessionDetailMessages(",
|
|
"session-app-server-messages-0",
|
|
"session-app-server-messages-1",
|
|
"contentParts: [",
|
|
],
|
|
absentSnippets: [
|
|
"agent_runtime_get_session",
|
|
"invokeMockOnly",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer fresh Agent sessions persist provider model defaults before first turn",
|
|
files: [
|
|
"src/components/agent/chat/hooks/useAgentSession.ts",
|
|
"src/components/agent/chat/hooks/useAgentChat.test.tsx",
|
|
"src/components/agent/chat/hooks/useAgentChat.test/slashSkillExecution.case.tsx",
|
|
],
|
|
snippets: [
|
|
"function buildFreshSessionProviderModelMetadata(",
|
|
"const providerSelector = providerType.trim()",
|
|
"const modelName = model.trim()",
|
|
"executionRuntime: {",
|
|
"extensionData: {",
|
|
'"lime_provider_routing.v0": {',
|
|
"metadata: buildFreshSessionProviderModelMetadata(",
|
|
"首条发送创建新会话时不应额外回写 provider/model 或 accessMode",
|
|
"providerSelector: selectedProvider",
|
|
"modelName: selectedModel",
|
|
"mockUpdateAgentRuntimeThreadSettings).not.toHaveBeenCalled",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime thread lifecycle uses standard AgentRuntimeClient facade",
|
|
file: "src/lib/api/agentRuntime/threadClient.ts",
|
|
snippets: [
|
|
'import type { AgentRuntimeClient as StandardAgentRuntimeClient } from "@limecloud/agent-runtime-client"',
|
|
"export type AgentRuntimeLifecycleClient = Pick<",
|
|
'"startTurn" | "steerTurn" | "cancelTurn" | "readThread"',
|
|
"standardRuntimeClient?: AgentRuntimeLifecycleClient",
|
|
"createAppServerAgentRuntimeLifecycleClient(appServerClient)",
|
|
"async function getAgentRuntimeThreadRead(",
|
|
"assertAppServerTurnLifecycleAvailable(isAppServerTurnLifecycleAvailable)",
|
|
"appServerClient.readThread({",
|
|
"return projectAppServerThreadReadResult(response.result)",
|
|
"async function readAgentRuntimeThread(",
|
|
"includeTurns: true",
|
|
],
|
|
absentSnippets: [
|
|
"AGENT_RUNTIME_COMMANDS.getThreadRead",
|
|
'"agent_runtime_get_thread_read"',
|
|
'"startTurn" | "steerTurn" | "cancelTurn" | "respondAction" | "readThread"',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI projection store delegates event selectors to standard projection package",
|
|
file: "src/components/agent/chat/projection/conversationProjectionStore.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"type ConversationAgentUiProjectionSlice = AgentUiProjectionEventStoreState",
|
|
"createEmptyAgentUiProjectionEventStoreState()",
|
|
"indexAgentUiProjectionEvents(nextEvents)",
|
|
"selectAgentUiProjectionEventsForScopeFromStore(state.agentUi, filter)",
|
|
"selectLatestAgentUiProjectionEventForArtifactFromStore(",
|
|
],
|
|
absentSnippets: [
|
|
"function hasAgentUiProjectionScopeFilter",
|
|
"function matchesAgentUiProjectionScopeValue",
|
|
"function matchesAgentUiProjectionScope(",
|
|
"function normalizeAgentUiRunKey",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI projection summary delegates host-neutral selectors to standard projection package",
|
|
file: "src/components/agent/chat/projection/agentUiProjectionSummary.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"summarizeAgentUiSubagentsSurfaceLanesBase",
|
|
"summarizeAgentUiSubagentsSurfacesBase",
|
|
"findLatestAgentUiProjectionEventForArtifact",
|
|
"summarizeAgentUiProjectionEvents",
|
|
"summarizeAgentUiSubagentsProjectionEvents",
|
|
],
|
|
absentSnippets: [
|
|
"export const AGENT_UI_ACTION_EVENT_TYPES = new Set",
|
|
"export const AGENT_UI_TASK_EVENT_TYPES = new Set",
|
|
"export const AGENT_UI_ARTIFACT_EVENT_TYPES = new Set",
|
|
"export const AGENT_UI_DIAGNOSTIC_EVENT_TYPES = new Set",
|
|
"export const AGENT_UI_EVIDENCE_EVENT_TYPES = new Set",
|
|
"export const AGENT_UI_SUBAGENTS_SURFACES = new Set",
|
|
"export const AGENT_UI_NOTABLE_EVENT_TYPES = new Set",
|
|
"export function summarizeAgentUiProjectionEvents(",
|
|
"export function summarizeAgentUiSubagentsProjectionEvents(",
|
|
"export function findLatestAgentUiProjectionEventForArtifact(",
|
|
"function normalizeLookupKey",
|
|
],
|
|
},
|
|
{
|
|
name: "Agent UI contracts package keeps index as barrel exports",
|
|
file: "packages/agent-ui-contracts/src/index.ts",
|
|
snippets: [
|
|
'export type * from "./events"',
|
|
'export type * from "./graph"',
|
|
'export type * from "./messages"',
|
|
'export type * from "./projection"',
|
|
'export type * from "./runtime"',
|
|
'export type * from "./timeline"',
|
|
],
|
|
absentSnippets: [
|
|
"function ",
|
|
"interface ",
|
|
"const ",
|
|
"import ",
|
|
"AgentRuntimeExecutionEventKind",
|
|
"AgentUiProjectionEvent",
|
|
"AgentUiProjectionState",
|
|
],
|
|
},
|
|
{
|
|
name: "Agent UI contracts package keeps type modules split by responsibility",
|
|
files: [
|
|
"packages/agent-ui-contracts/src/events.ts",
|
|
"packages/agent-ui-contracts/src/runtime.ts",
|
|
"packages/agent-ui-contracts/src/projection.ts",
|
|
"packages/agent-ui-contracts/src/messages.ts",
|
|
"packages/agent-ui-contracts/src/timeline.ts",
|
|
"packages/agent-ui-contracts/src/graph.ts",
|
|
],
|
|
snippets: [
|
|
"export type AgentUiEventClass",
|
|
"export interface AgentUiProjectionEvent",
|
|
"export interface AgentRuntimeExecutionEvent",
|
|
"export interface AgentRuntimeEventProjection",
|
|
"actions?: AgentRuntimeActionProjection[]",
|
|
"export interface AgentUiProjectionState",
|
|
"export interface UIMessagePart",
|
|
"export interface ProcessTimelineEntry",
|
|
"export interface ExecutionGraphNode",
|
|
],
|
|
absentSnippets: [
|
|
'from "@/',
|
|
'from "src/',
|
|
'from "react"',
|
|
"React",
|
|
"safeInvoke",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
"invokeMockOnly",
|
|
"EventSource",
|
|
"new WebSocket",
|
|
"fetch(",
|
|
"XMLHttpRequest",
|
|
],
|
|
},
|
|
{
|
|
name: "Agent UI contracts exclude retired runtime resume contract",
|
|
files: [
|
|
"packages/agent-ui-contracts/src/capabilities.ts",
|
|
"packages/agent-ui-contracts/src/validation.ts",
|
|
"packages/agent-ui-contracts/src/schemas.ts",
|
|
"packages/agent-ui-contracts/tests/contracts.test.mjs",
|
|
],
|
|
snippets: [
|
|
"AgentRuntimeCapabilityManifest",
|
|
"validateRuntimeCapabilityManifest",
|
|
"AGENT_RUNTIME_CAPABILITY_MANIFEST_SCHEMA",
|
|
'"hitl.actions"',
|
|
],
|
|
absentSnippets: [
|
|
"AgentRuntimeResumeMode",
|
|
"AgentRuntimeResumeActionDecision",
|
|
"AgentRuntimeResumeContract",
|
|
"validateRuntimeResumeContract",
|
|
"collectRuntimeResumeContractValidationIssues",
|
|
"AGENT_RUNTIME_RESUME_CONTRACT_SCHEMA",
|
|
"runtimeResumeContract",
|
|
'"hitl.resume"',
|
|
"lime-runtime-resume-contract/v0.1",
|
|
],
|
|
},
|
|
{
|
|
name: "Capability projection does not recreate retired HITL resume",
|
|
files: [
|
|
"src/lib/api/agentRuntime/capabilityContract.ts",
|
|
"lime-rs/crates/app-server/src/runtime/capabilities.rs",
|
|
],
|
|
snippets: ['"hitl.actions"'],
|
|
absentSnippets: [
|
|
'"hitl.resume"',
|
|
'id.includes("resume")',
|
|
'id.contains("resume")',
|
|
],
|
|
},
|
|
{
|
|
name: "Agent Runtime projection package keeps index as barrel exports",
|
|
files: [
|
|
"packages/agent-runtime-projection/src/index.ts",
|
|
"packages/agent-runtime-projection/src/index.js",
|
|
"packages/agent-runtime-projection/src/index.d.ts",
|
|
],
|
|
snippets: [
|
|
'from "./contracts.js"',
|
|
'export * from "./actions.js"',
|
|
'export * from "./artifactEvents.js"',
|
|
'export * from "./contextEvents.js"',
|
|
'export * from "./conversationEvents.js"',
|
|
'export * from "./diagnosticEvents.js"',
|
|
'export * from "./envelope.js"',
|
|
'export * from "./eventStore.js"',
|
|
'export * from "./hydrationEvents.js"',
|
|
'export * from "./lifecycle.js"',
|
|
'export * from "./normalization.js"',
|
|
'export * from "./planApproval.js"',
|
|
'export * from "./permissionEvents.js"',
|
|
'export * from "./refs.js"',
|
|
'export * from "./routing.js"',
|
|
'export * from "./runtimeFacts.js"',
|
|
'export * from "./summary.js"',
|
|
'export * from "./threadItems.js"',
|
|
'export * from "./toolEvents.js"',
|
|
'export * from "./readModel.js"',
|
|
'export * from "./uiState.js"',
|
|
],
|
|
absentSnippets: [
|
|
"function ",
|
|
"interface ",
|
|
"const ",
|
|
"import ",
|
|
"@limecloud/agent-ui-contracts",
|
|
],
|
|
},
|
|
{
|
|
name: "Agent Runtime projection package keeps host-neutral modules split by responsibility",
|
|
files: [
|
|
"packages/agent-runtime-projection/src/actions.ts",
|
|
"packages/agent-runtime-projection/src/artifactEvents.ts",
|
|
"packages/agent-runtime-projection/src/contextEvents.ts",
|
|
"packages/agent-runtime-projection/src/conversationEvents.ts",
|
|
"packages/agent-runtime-projection/src/contracts.ts",
|
|
"packages/agent-runtime-projection/src/diagnosticEvents.ts",
|
|
"packages/agent-runtime-projection/src/envelope.ts",
|
|
"packages/agent-runtime-projection/src/eventStore.ts",
|
|
"packages/agent-runtime-projection/src/hydrationEvents.ts",
|
|
"packages/agent-runtime-projection/src/lifecycle.ts",
|
|
"packages/agent-runtime-projection/src/normalization.ts",
|
|
"packages/agent-runtime-projection/src/planApproval.ts",
|
|
"packages/agent-runtime-projection/src/permissionEvents.ts",
|
|
"packages/agent-runtime-projection/src/refs.ts",
|
|
"packages/agent-runtime-projection/src/routing.ts",
|
|
"packages/agent-runtime-projection/src/runtimeFacts.ts",
|
|
"packages/agent-runtime-projection/src/summary.ts",
|
|
"packages/agent-runtime-projection/src/threadItems.ts",
|
|
"packages/agent-runtime-projection/src/toolEvents.ts",
|
|
"packages/agent-runtime-projection/src/readModel.ts",
|
|
"packages/agent-runtime-projection/src/uiState.ts",
|
|
],
|
|
snippets: [
|
|
'from "@limecloud/agent-ui-contracts"',
|
|
"buildAgentUiActionRequiredEvent",
|
|
"buildAgentUiActionResolvedEvent",
|
|
"buildAgentUiArtifactSnapshotEvent",
|
|
"buildAgentUiContextTraceEvent",
|
|
"buildAgentUiTurnContextEvents",
|
|
"buildAgentUiMessageSnapshotEvent",
|
|
"buildAgentUiTextDeltaEvent",
|
|
"buildAgentUiReasoningDeltaEvent",
|
|
"buildAgentUiWarningEvent",
|
|
"buildAgentUiCostMetricEvent",
|
|
"buildAgentUiHistoricalHydrationEvents",
|
|
"buildAgentUiPlanApprovalRequiredEvent",
|
|
"buildAgentUiPlanApprovalResolvedEvent",
|
|
"buildAgentUiRuntimePermissionChangedEvent",
|
|
"buildAgentUiRoutingStatusEvent",
|
|
"buildAgentUiProjectionBase",
|
|
"buildAgentUiThreadStartedEvent",
|
|
"buildAgentUiRuntimeStatusEvent",
|
|
"buildAgentUiRunStartedEvent",
|
|
"buildAgentUiRunFinishedEvent",
|
|
"buildAgentUiRunFailedEvent",
|
|
"buildAgentUiModelChangeEvent",
|
|
"buildAgentUiTaskProfileResolvedEvent",
|
|
"buildAgentUiThreadItemBase",
|
|
"buildAgentUiThreadItemActionEvent",
|
|
"buildAgentUiThreadItemSubagentActivityEvent",
|
|
"buildAgentUiThreadItemEvent",
|
|
"buildAgentUiToolStartEvents",
|
|
"buildAgentUiToolEndEvent",
|
|
"buildAgentUiToolEndEvents",
|
|
"buildAgentUiToolProgressEvent",
|
|
"buildAgentUiToolOutputDeltaEvent",
|
|
"buildAgentUiToolInputDeltaEvent",
|
|
"extractAgentUiPlanApprovalProjection",
|
|
"extractAgentUiPlanApprovalResponseProjection",
|
|
"extractAgentUiTaskOwnerChangeProjection",
|
|
"sequenceAgentUiProjectionEvents",
|
|
"AgentUiProjectionEventStoreState",
|
|
"definedString",
|
|
"extractArtifactRefs",
|
|
"buildRoutingDecisionPayload",
|
|
"inferAgentUiRuntimeEntity",
|
|
"resolveAgentUiThreadItemPhase",
|
|
"summarizeAgentUiProjectionEvents",
|
|
"projectAgentRuntimeReadModel",
|
|
"projectAgentUiState",
|
|
],
|
|
absentSnippets: [
|
|
'from "@/',
|
|
'from "src/',
|
|
'from "../../src',
|
|
'from "../../../src',
|
|
"React",
|
|
"safeInvoke",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
"invokeMockOnly",
|
|
"EventSource",
|
|
"new WebSocket",
|
|
"fetch(",
|
|
"XMLHttpRequest",
|
|
"buildAgentUiThreadItemSubagentWorkerNotificationEvent",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI projection base delegates envelope and sequence to standard projection package",
|
|
file: "src/components/agent/chat/projection/projectionBase.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"buildAgentUiProjectionBase as buildStandardAgentUiProjectionBase",
|
|
"sequenceAgentUiProjectionEvents",
|
|
'typeof event.item?.type === "string"',
|
|
"return buildStandardAgentUiProjectionBase(",
|
|
"return sequenceAgentUiProjectionEvents(events, startSequence)",
|
|
],
|
|
absentSnippets: [
|
|
"function inferRuntimeEntityFromSource",
|
|
"inferAgentUiRuntimeEntity",
|
|
"definedString(context",
|
|
"sessionId: definedString",
|
|
"threadId: definedString",
|
|
"runId: definedString",
|
|
"turnId: definedString",
|
|
"messageId: definedString",
|
|
"taskId: definedString",
|
|
"events.map((event, index)",
|
|
"startSequence + index",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI conversation event projection delegates message and delta builders to standard projection package",
|
|
file: "src/components/agent/chat/projection/conversationEventProjection.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"buildAgentUiMessageSnapshotEvent",
|
|
"buildAgentUiTextDeltaEvent",
|
|
"buildAgentUiReasoningDeltaEvent",
|
|
"return buildAgentUiMessageSnapshotEvent(",
|
|
"return buildAgentUiTextDeltaEvent(",
|
|
"return buildAgentUiReasoningDeltaEvent(",
|
|
"sourceType: event.type",
|
|
"role: event.message.role",
|
|
"partCount: event.message.content.length",
|
|
"text: event.text",
|
|
"chunkCount: event.chunks.length",
|
|
"boundary: event.boundary",
|
|
],
|
|
absentSnippets: [
|
|
"buildAgentUiProjectionBase",
|
|
"truncateText",
|
|
'type: "messages.snapshot"',
|
|
'type: "text.delta"',
|
|
'type: "reasoning.delta"',
|
|
'owner: "session"',
|
|
'owner: "model"',
|
|
'scope: "message"',
|
|
'scope: "part"',
|
|
'phase: "hydrating"',
|
|
'phase: "producing"',
|
|
'phase: "reasoning"',
|
|
'surface: "conversation"',
|
|
'surface: "inline_process"',
|
|
'persistence: "snapshot"',
|
|
'persistence: "transcript"',
|
|
'persistence: "ephemeral_live"',
|
|
"textLength:",
|
|
"preview:",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI artifact projection delegates artifact and context builders to standard projection package",
|
|
file: "src/components/agent/chat/projection/artifactProjection.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"buildAgentUiArtifactSnapshotEvent",
|
|
"buildAgentUiContextTraceEvent",
|
|
"return buildAgentUiArtifactSnapshotEvent(",
|
|
"return buildAgentUiContextTraceEvent(",
|
|
"sourceType: event.type",
|
|
"artifactId: event.artifact.artifactId",
|
|
"filePath: event.artifact.filePath",
|
|
"content: event.artifact.content",
|
|
"metadata: event.artifact.metadata",
|
|
"steps: event.steps",
|
|
],
|
|
absentSnippets: [
|
|
"buildAgentUiProjectionBase",
|
|
"truncateText",
|
|
'type: "artifact.preview.ready"',
|
|
'type: "artifact.updated"',
|
|
'type: "context.changed"',
|
|
'owner: "artifact"',
|
|
'owner: "context"',
|
|
'scope: "artifact"',
|
|
'scope: "turn"',
|
|
'phase: "completed"',
|
|
'phase: "producing"',
|
|
'phase: "preparing"',
|
|
'surface: "artifact_workspace"',
|
|
'surface: "runtime_status"',
|
|
'persistence: "artifact_store"',
|
|
'persistence: "snapshot"',
|
|
"contentLength:",
|
|
"metadataKeys:",
|
|
"stepCount:",
|
|
"latestStage:",
|
|
"latestDetailPreview:",
|
|
"artifactIds:",
|
|
"artifactPaths:",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI turn context projection delegates context and permission builders to standard projection package",
|
|
file: "src/components/agent/chat/projection/contextProjection.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"buildAgentUiTurnContextEvents",
|
|
"return buildAgentUiTurnContextEvents(",
|
|
"sessionId: event.session_id",
|
|
"threadId: event.thread_id",
|
|
"turnId: event.turn_id",
|
|
"sourceType: event.type",
|
|
"outputSchemaRuntime: event.output_schema_runtime",
|
|
"contextSummary: buildTurnContextSummaryInput(event.context_summary)",
|
|
"approvalPolicy: event.approval_policy",
|
|
"sandboxPolicy: event.sandbox_policy",
|
|
],
|
|
absentSnippets: [
|
|
"buildAgentUiProjectionBase",
|
|
'type: "context.changed"',
|
|
'type: "permission.changed"',
|
|
'owner: "context"',
|
|
'owner: "policy"',
|
|
'scope: "turn"',
|
|
'phase: "preparing"',
|
|
'surface: "runtime_status"',
|
|
'persistence: "snapshot"',
|
|
"outputSchemaAvailable:",
|
|
"contextSummaryAvailable:",
|
|
"memoryBudget:",
|
|
"missingContext:",
|
|
"retrievalRefs:",
|
|
"teamMemoryRefs:",
|
|
"contextSourceIds:",
|
|
"teamMemoryKeys:",
|
|
"sourceEvent:",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI action projection delegates HITL builders to standard projection package",
|
|
file: "src/components/agent/chat/projection/actionProjection.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"buildAgentUiActionRequiredEvent",
|
|
"buildAgentUiActionResolvedEvent",
|
|
"sourceType: event.type",
|
|
"requestId: event.request_id",
|
|
"actionType: event.action_type",
|
|
"sessionId: event.scope?.session_id",
|
|
"return buildAgentUiActionRequiredEvent(",
|
|
"return buildAgentUiActionResolvedEvent(",
|
|
],
|
|
absentSnippets: [
|
|
"function actionControl",
|
|
"function resolvedActionControl",
|
|
"metadataKeys",
|
|
"readBooleanField",
|
|
"readRecord",
|
|
"readStringField",
|
|
"truncateText",
|
|
'owner: "action"',
|
|
'scope: "action_request"',
|
|
'surface: "hitl"',
|
|
"control: ",
|
|
],
|
|
absentSnippets: ["buildAgentUiRuntimeTeamChangedEvent"],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI runtime lifecycle projection delegates lifecycle builders to standard projection package",
|
|
file: "src/components/agent/chat/projection/runtimeLifecycleProjection.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"buildAgentUiThreadStartedEvent",
|
|
"buildAgentUiRunStartedEvent",
|
|
"buildAgentUiRunFinishedEvent",
|
|
"buildAgentUiRunFailedEvent",
|
|
"buildAgentUiRuntimeStatusEvent",
|
|
"buildAgentUiModelChangeEvent",
|
|
"buildAgentUiTaskProfileResolvedEvent",
|
|
"return buildAgentUiThreadStartedEvent(",
|
|
"return buildAgentUiRunStartedEvent(",
|
|
"return buildAgentUiRunFinishedEvent(",
|
|
"return buildAgentUiRunFailedEvent(",
|
|
"buildAgentUiRuntimeStatusEvent(",
|
|
"return buildAgentUiModelChangeEvent(",
|
|
"return buildAgentUiTaskProfileResolvedEvent(",
|
|
"sourceType: event.type",
|
|
"threadId: event.thread_id",
|
|
"threadId: event.turn.thread_id",
|
|
"turnId: event.turn.id",
|
|
"promptText: event.turn.prompt_text",
|
|
"metadata: event.status.metadata",
|
|
"model: event.model",
|
|
"mode: event.mode",
|
|
"kind: event.task_profile.kind",
|
|
"permissionProfileKeys: event.task_profile.permissionProfileKeys ?? []",
|
|
],
|
|
absentSnippets: [
|
|
"buildAgentUiRuntimeTeamChangedEvent",
|
|
"buildAgentUiProjectionBase",
|
|
"buildTeamRuntimeFacts",
|
|
'type: "team.changed"',
|
|
"compactProjectionFields",
|
|
"metadataKeys",
|
|
"normalizeRuntimePhaseFromRuntimeStatusPhase",
|
|
"normalizeRuntimeStatusFromRuntimePhase",
|
|
"truncateText",
|
|
'type: "session.opened"',
|
|
'type: "run.started"',
|
|
'type: "run.finished"',
|
|
'type: "run.failed"',
|
|
'type: "task.changed"',
|
|
'owner: "session"',
|
|
'owner: "runtime"',
|
|
'owner: "task"',
|
|
'scope: "thread"',
|
|
'scope: "run"',
|
|
'phase: "accepted"',
|
|
'phase: "routing"',
|
|
'surface: "session_tabs"',
|
|
'surface: "runtime_status"',
|
|
'surface: "task_capsule"',
|
|
'persistence: "snapshot"',
|
|
"runtimeStatus:",
|
|
"latestTurnStatus:",
|
|
"checkpointCount:",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Team control projection emits task and handoff facts only",
|
|
file: "src/components/agent/chat/projection/teamControlProjection.ts",
|
|
snippets: [
|
|
"buildAgentUiTeamControlProjectionEvents",
|
|
'type: "task.changed"',
|
|
'type: "agent.handoff"',
|
|
'sourceType: "team_control_projection"',
|
|
],
|
|
absentSnippets: ['type: "team.changed"', 'owner: "team"', 'scope: "team"'],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI permission projection delegates runtime permission builders to standard projection package",
|
|
file: "src/components/agent/chat/projection/permissionProjection.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"buildAgentUiRuntimePermissionChangedEvent",
|
|
"return buildAgentUiRuntimePermissionChangedEvent(",
|
|
"sourceType: event.type",
|
|
"phase: event.status.phase",
|
|
"metadata: event.status.metadata",
|
|
],
|
|
absentSnippets: [
|
|
"buildAgentUiProjectionBase",
|
|
"definedString",
|
|
"readStringArray",
|
|
"normalizeRuntimePhaseFromRuntimeStatusPhase",
|
|
"function hasPermissionProjectionMetadata",
|
|
"function normalizePermissionPhase",
|
|
'type: "permission.changed"',
|
|
'owner: "policy"',
|
|
'scope: "run"',
|
|
'surface: "hitl"',
|
|
'surface: "runtime_status"',
|
|
'persistence: "snapshot"',
|
|
'control: "approve"',
|
|
"permissionStatus:",
|
|
"confirmationStatus:",
|
|
"requiredProfileKeys:",
|
|
"askProfileKeys:",
|
|
"blockingProfileKeys:",
|
|
"declaredOnly:",
|
|
"turnGating:",
|
|
"sourcePhase:",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI plan approval projection remains a thin standard-package adapter",
|
|
file: "src/components/agent/chat/projection/planApprovalProjection.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"buildAgentUiPlanApprovalRequiredEvent as buildPlanApprovalRequiredEvent",
|
|
"buildAgentUiPlanApprovalResolvedEvent as buildPlanApprovalResolvedEvent",
|
|
"extractAgentUiPlanApprovalProjection as extractPlanApprovalProjection",
|
|
"extractAgentUiPlanApprovalResponseProjection as extractPlanApprovalResponseProjection",
|
|
"AgentUiPlanApprovalProjection as PlanApprovalProjection",
|
|
"AgentUiPlanApprovalResponseProjection as PlanApprovalResponseProjection",
|
|
],
|
|
absentSnippets: [
|
|
"readBooleanField",
|
|
"readRecord",
|
|
"readStringField",
|
|
"truncateText",
|
|
"function ",
|
|
"interface ",
|
|
'type: "action.required"',
|
|
'type: "action.resolved"',
|
|
'scope: "action_request"',
|
|
'decisionKind: "plan_approval_request"',
|
|
'decisionKind: "plan_approval_response"',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI diagnostic projection delegates warning and cost builders to standard projection package",
|
|
file: "src/components/agent/chat/projection/diagnosticProjection.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"buildAgentUiWarningEvent",
|
|
"buildAgentUiCostMetricEvent",
|
|
"return buildAgentUiWarningEvent(",
|
|
"return buildAgentUiCostMetricEvent(",
|
|
"sourceType: event.type",
|
|
"code: event.code",
|
|
"message: event.message",
|
|
"metricEvent: event.type",
|
|
"costState: event.cost_state",
|
|
],
|
|
absentSnippets: [
|
|
"buildAgentUiProjectionBase",
|
|
"truncateText",
|
|
'type: "diagnostic.changed"',
|
|
'type: "metric.changed"',
|
|
'owner: "diagnostics"',
|
|
'scope: "run"',
|
|
'phase: "acting"',
|
|
'surface: "diagnostics"',
|
|
'persistence: "diagnostics_log"',
|
|
"messagePreview:",
|
|
"estimatedCostClass:",
|
|
"estimatedTotalCost:",
|
|
"cachedInputTokens:",
|
|
"cacheCreationInputTokens:",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI historical hydration projection delegates snapshot builders to standard projection package",
|
|
file: "src/components/agent/chat/projection/historicalMessageHydrationProjection.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"buildAgentUiHistoricalHydrationEvents",
|
|
"return buildAgentUiHistoricalHydrationEvents(input, context)",
|
|
"isHistoricalAssistantMessageHydrationCandidate",
|
|
"buildHistoricalMarkdownHydrationTargets",
|
|
"countDeferredHistoricalContentParts",
|
|
"countDeferredHistoricalMarkdown",
|
|
],
|
|
absentSnippets: [
|
|
"buildAgentUiProjectionBase",
|
|
'type: "session.hydrated"',
|
|
'type: "messages.snapshot"',
|
|
'type: "diagnostic.changed"',
|
|
'owner: "session"',
|
|
'owner: "diagnostics"',
|
|
'scope: "session"',
|
|
'scope: "thread"',
|
|
'phase: "hydrating"',
|
|
'phase: "completed"',
|
|
'surface: "session_tabs"',
|
|
'surface: "conversation"',
|
|
'surface: "diagnostics"',
|
|
'persistence: "snapshot"',
|
|
'persistence: "diagnostics_log"',
|
|
"historical_hydration_stale_window",
|
|
"diagnosticKey:",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI routing projection delegates run status builder to standard projection package",
|
|
file: "src/components/agent/chat/projection/routingProjection.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"buildAgentUiRoutingStatusEvent",
|
|
"return buildAgentUiRoutingStatusEvent(",
|
|
"sourceType: event.type",
|
|
"runtimeEvent: event.type",
|
|
"routingDecision: event.routing_decision",
|
|
"limitState: event.limit_state",
|
|
"limitEvent: event.limit_event",
|
|
],
|
|
absentSnippets: [
|
|
"buildAgentUiProjectionBase",
|
|
"buildRoutingDecisionPayload",
|
|
"truncateText",
|
|
'type: "run.status"',
|
|
'owner: "runtime"',
|
|
'scope: "run"',
|
|
'phase: "routing"',
|
|
'phase: "failed"',
|
|
'surface: "runtime_status"',
|
|
'persistence: "snapshot"',
|
|
"limitStatus:",
|
|
"singleCandidateOnly:",
|
|
"providerLocked:",
|
|
"settingsLocked:",
|
|
"oemLocked:",
|
|
"limitEventKind:",
|
|
"messagePreview:",
|
|
"retryable:",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI thread item projection delegates host-neutral builders to standard projection package",
|
|
file: "src/components/agent/chat/projection/threadItemProjection.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"buildAgentUiThreadItemBase as buildStandardThreadItemBase",
|
|
"buildAgentUiThreadItemEvent",
|
|
"extractAgentUiTaskOwnerChangeProjection",
|
|
"return buildStandardThreadItemBase(sourceType, item, context)",
|
|
"return buildAgentUiThreadItemEvent(sourceType, item, context)",
|
|
"const taskOwnerProjection = extractAgentUiTaskOwnerChangeProjection(",
|
|
"extractPlanApprovalProjection(item.metadata)",
|
|
"buildTaskOwnerChangeProjectionEvents(sourceType, item, context)",
|
|
],
|
|
absentSnippets: [
|
|
"function threadItemPhase",
|
|
"function threadItemToolResultType",
|
|
"function threadItemToolPhase",
|
|
"function normalizeProjectionToolName",
|
|
"function isTaskUpdateToolName",
|
|
"readRecord",
|
|
"readStringArrayField",
|
|
"readStringField",
|
|
"owner_change",
|
|
"ownerChange",
|
|
"updated_fields",
|
|
"updatedFields",
|
|
"metadataKeys",
|
|
"extractArtifactRefs",
|
|
'type: "plan.final"',
|
|
'type: "reasoning.summary"',
|
|
'type: "tool.result"',
|
|
'type: "tool.progress"',
|
|
'type: "artifact.preview.ready"',
|
|
'type: "context.compaction.completed"',
|
|
'type: "state.snapshot"',
|
|
'type: "diagnostic.changed"',
|
|
'type: "action.required"',
|
|
'type: "action.resolved"',
|
|
'type: "agent.changed"',
|
|
'type: "worker.notification"',
|
|
"buildAgentUiThreadItemSubagentWorkerNotificationEvent",
|
|
'owner: "tool"',
|
|
'scope: "tool_call"',
|
|
'scope: "action_request"',
|
|
'runtimeEntity: "subagent_turn"',
|
|
"workerNotificationId:",
|
|
'notificationKind: "worker_result"',
|
|
"summaryPreview:",
|
|
"promptPreview:",
|
|
"hasResponse:",
|
|
"commandPreview:",
|
|
"outputPreview:",
|
|
"errorPreview:",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent UI tool event projection delegates host-neutral builders to standard projection package",
|
|
file: "src/components/agent/chat/projection/toolEventProjection.ts",
|
|
snippets: [
|
|
'from "@limecloud/agent-runtime-projection"',
|
|
"buildAgentUiToolStartEvents",
|
|
"buildAgentUiToolEndEvents",
|
|
"buildAgentUiToolProgressEvent",
|
|
"buildAgentUiToolOutputDeltaEvent",
|
|
"buildAgentUiToolInputDeltaEvent",
|
|
"return buildAgentUiToolStartEvents(",
|
|
"return buildAgentUiToolEndEvents(",
|
|
"return buildAgentUiToolProgressEvent(",
|
|
"return buildAgentUiToolOutputDeltaEvent(",
|
|
"return buildAgentUiToolInputDeltaEvent(",
|
|
"sourceType: event.type",
|
|
"toolCallId: event.tool_id",
|
|
"toolName: event.tool_name",
|
|
"input: event.arguments",
|
|
"result: event.result",
|
|
"progress: event.progress",
|
|
"outputKind: event.output_kind",
|
|
"accumulatedInput: event.accumulated_arguments",
|
|
],
|
|
absentSnippets: [
|
|
"buildAgentUiProjectionBase",
|
|
"buildPlanApprovalRequiredEvent",
|
|
"buildPlanApprovalResolvedEvent",
|
|
"extractPlanApprovalProjection",
|
|
"extractPlanApprovalResponseProjection",
|
|
"extractArtifactRefs",
|
|
"metadataKeys",
|
|
"truncateText",
|
|
"function buildToolEndEvent(",
|
|
'type: "tool.started"',
|
|
'type: "tool.args"',
|
|
'type: "tool.result"',
|
|
'type: "tool.failed"',
|
|
'type: "tool.progress"',
|
|
'type: "tool.output.delta"',
|
|
'type: "tool.args.delta"',
|
|
'owner: "tool"',
|
|
'scope: "tool_call"',
|
|
'surface: "tool_ui"',
|
|
'persistence: "ephemeral_live"',
|
|
'persistence: "archive"',
|
|
"outputPreview:",
|
|
"errorPreview:",
|
|
"metadataKeys:",
|
|
"diagnosticKeys:",
|
|
],
|
|
},
|
|
{
|
|
name: "Agent Runtime UI package keeps index as barrel exports",
|
|
file: "packages/agent-runtime-ui/src/index.ts",
|
|
snippets: [
|
|
'export type * from "./types.js"',
|
|
'export * from "./messages.js"',
|
|
'export * from "./processTimeline.js"',
|
|
'export * from "./executionGraph.js"',
|
|
'export * from "./runtimeFacts.js"',
|
|
'export * from "./projectionView.js"',
|
|
],
|
|
absentSnippets: [
|
|
"function ",
|
|
"interface ",
|
|
"const ",
|
|
"import ",
|
|
"@limecloud/agent-ui-contracts",
|
|
"safeInvoke",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
"invokeMockOnly",
|
|
],
|
|
},
|
|
{
|
|
name: "Agent Runtime UI package keeps React primitives split by responsibility",
|
|
files: [
|
|
"packages/agent-runtime-ui/src/types.ts",
|
|
"packages/agent-runtime-ui/src/labels.ts",
|
|
"packages/agent-runtime-ui/src/messages.tsx",
|
|
"packages/agent-runtime-ui/src/processTimeline.tsx",
|
|
"packages/agent-runtime-ui/src/executionGraph.tsx",
|
|
"packages/agent-runtime-ui/src/runtimeFacts.tsx",
|
|
"packages/agent-runtime-ui/src/projectionView.tsx",
|
|
],
|
|
snippets: [
|
|
"AgentTimelineProps",
|
|
"defaultMessageTitle",
|
|
"UIMessagePartsView",
|
|
"ProcessTimelineView",
|
|
"ExecutionGraphView",
|
|
"RuntimeFactCard",
|
|
"AgentUiProjectionView",
|
|
],
|
|
absentSnippets: [
|
|
'from "@/',
|
|
'from "src/',
|
|
'from "../../src',
|
|
'from "../../../src',
|
|
"safeInvoke",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
"invokeMockOnly",
|
|
"EventSource",
|
|
"new WebSocket",
|
|
"fetch(",
|
|
"XMLHttpRequest",
|
|
],
|
|
},
|
|
{
|
|
name: "Agent Runtime UI labels stay injectable and host-neutral",
|
|
files: [
|
|
"packages/agent-runtime-ui/src/types.ts",
|
|
"packages/agent-runtime-ui/src/labels.ts",
|
|
"packages/agent-runtime-ui/src/messages.tsx",
|
|
"packages/agent-runtime-ui/src/processTimeline.tsx",
|
|
"packages/agent-runtime-ui/src/executionGraph.tsx",
|
|
"packages/agent-runtime-ui/src/runtimeFacts.tsx",
|
|
"packages/agent-runtime-ui/src/projectionView.tsx",
|
|
],
|
|
snippets: [
|
|
"AgentUiProjectionViewLabels",
|
|
"messagePartsAriaLabel",
|
|
"processTimelineAriaLabel",
|
|
"actionButtonLabel",
|
|
"eventStatusLabel",
|
|
"data-action-decision",
|
|
"event.actions?.length",
|
|
"Open model settings",
|
|
"Message parts",
|
|
"Process timeline",
|
|
"Execution graph",
|
|
],
|
|
absentSnippets: [
|
|
"消息部分",
|
|
"过程时间线",
|
|
"工具调用",
|
|
"待处理动作",
|
|
"协作事实摘要",
|
|
"打开模型设置",
|
|
"补输入源",
|
|
],
|
|
},
|
|
{
|
|
name: "Agent UI Runtime standard document is the current package and host integration fact source",
|
|
files: [
|
|
"internal/aiprompts/agent-ui-runtime-standard.md",
|
|
"internal/aiprompts/README.md",
|
|
"internal/aiprompts/agent-protocol-standards-map.md",
|
|
"internal/prd/next/implementation-roadmap.md",
|
|
"packages/agent-runtime-projection/README.md",
|
|
],
|
|
snippets: [
|
|
"agent-ui-runtime-standard.md",
|
|
"@limecloud/agent-runtime-client",
|
|
"@limecloud/agent-ui-contracts",
|
|
"@limecloud/agent-runtime-projection",
|
|
"@limecloud/agent-runtime-ui",
|
|
"Standard Package Layering",
|
|
"Source Layout",
|
|
"src/envelope.ts",
|
|
"src/normalization.ts",
|
|
"src/refs.ts",
|
|
"src/routing.ts",
|
|
"src/runtimeFacts.ts",
|
|
"buildAgentUiProjectionBase",
|
|
"sequenceAgentUiProjectionEvents",
|
|
"AgentRuntimeClient -> projectAgentUiState -> AgentUiProjectionView",
|
|
"主聊天 projection 迁移分类",
|
|
"projection package `index` 只能做 barrel exports",
|
|
"barrel exports only",
|
|
"src/components/agent/chat/projection/**",
|
|
"agentUiEventProjection.ts",
|
|
"conversationProjectionStore.ts",
|
|
"agentUiProjectionSummary.ts",
|
|
"不得新增第二套 runtime fact source",
|
|
],
|
|
absentSnippets: [
|
|
...retiredTreeProjectionNames,
|
|
"直接套用外部 SDK",
|
|
"新增 Agent Runtime 能力可以落到 legacy desktop facade",
|
|
"主聊天目录可以重新实现标准 projection selector",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime derived exports use App Server agentSession export methods",
|
|
file: "src/lib/api/agentRuntime/exportClient.ts",
|
|
snippets: [
|
|
"APP_SERVER_METHOD_AGENT_SESSION_HANDOFF_BUNDLE_EXPORT",
|
|
"APP_SERVER_METHOD_AGENT_SESSION_REPLAY_CASE_EXPORT",
|
|
"APP_SERVER_METHOD_AGENT_SESSION_ANALYSIS_HANDOFF_EXPORT",
|
|
"APP_SERVER_METHOD_AGENT_SESSION_REVIEW_DECISION_TEMPLATE_EXPORT",
|
|
"APP_SERVER_METHOD_AGENT_SESSION_REVIEW_DECISION_SAVE",
|
|
'"exportHandoffBundle"',
|
|
'"exportReplayCase"',
|
|
'"exportAnalysisHandoff"',
|
|
'"exportReviewDecisionTemplate"',
|
|
'"saveReviewDecision"',
|
|
"appServerClient.exportHandoffBundle({",
|
|
"appServerClient.exportReplayCase({",
|
|
"appServerClient.exportAnalysisHandoff({",
|
|
"appServerClient.exportReviewDecisionTemplate({",
|
|
"appServerClient.saveReviewDecision({",
|
|
"sessionId: normalizedSessionId",
|
|
"decisionStatus: request.decision_status",
|
|
"decisionSummary: request.decision_summary",
|
|
"chosenFixStrategy: request.chosen_fix_strategy",
|
|
"riskLevel: request.risk_level",
|
|
],
|
|
absentSnippets: [
|
|
"AGENT_RUNTIME_COMMANDS.exportHandoffBundle",
|
|
"AGENT_RUNTIME_COMMANDS.exportReplayCase",
|
|
"AGENT_RUNTIME_COMMANDS.exportAnalysisHandoff",
|
|
"AGENT_RUNTIME_COMMANDS.exportReviewDecisionTemplate",
|
|
"AGENT_RUNTIME_COMMANDS.saveReviewDecision",
|
|
'"agent_runtime_export_handoff_bundle"',
|
|
'"agent_runtime_export_replay_case"',
|
|
'"agent_runtime_export_analysis_handoff"',
|
|
'"agent_runtime_export_review_decision_template"',
|
|
'"agent_runtime_save_review_decision"',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime derived export tests lock App Server path and fail closed behavior",
|
|
file: "src/lib/api/agentRuntime/exportClient.test.ts",
|
|
snippets: [
|
|
"analysis / replay / review current 导出应走 App Server",
|
|
"appServerClient.exportAnalysisHandoff",
|
|
"appServerClient.exportReplayCase",
|
|
"appServerClient.exportReviewDecisionTemplate",
|
|
"appServerClient.saveReviewDecision",
|
|
"agentSession/analysisHandoff/export did not return runtime analysis handoff",
|
|
"agentSession/replayCase/export did not return runtime replay case",
|
|
"agentSession/reviewDecisionTemplate/export did not return runtime review decision template",
|
|
"agentSession/reviewDecision/save did not return runtime review decision template",
|
|
"缺少 sessionId 时派生导出应 fail closed",
|
|
],
|
|
absentSnippets: [
|
|
"analysis / replay / review compat 导出",
|
|
"agent_runtime_export_analysis_handoff did not return",
|
|
"agent_runtime_export_replay_case did not return",
|
|
"agent_runtime_export_review_decision_template did not return",
|
|
"agent_runtime_save_review_decision did not return",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime tests lock App Server lifecycle and direct v2 notification behavior",
|
|
files: [
|
|
"src/lib/api/agentRuntime/threadClient.test.ts",
|
|
"src/lib/api/agentRuntime/serverRequestReplay.unit.test.ts",
|
|
"src/lib/api/agentRuntime/appServerV2Notification.test.ts",
|
|
"src/lib/api/agentRuntime/appServerEventStream.test.ts",
|
|
],
|
|
snippets: [
|
|
"App Server 可用时 submit 应进入 turn/start",
|
|
"App Server 不可用时 submit 应 fail closed,不回退 legacy command",
|
|
"App Server 可用且 turn_id 存在时 interrupt 应进入 turn/interrupt",
|
|
"App Server 不可用时 interrupt 应 fail closed,不回退 legacy command",
|
|
"缺少 turn_id 时 interrupt 应 fail closed,不回退 legacy command",
|
|
"typed pending 不存在时 respond action 应 fail closed,不回退旧 action/respond",
|
|
"App Server 不可用时 respond action 应 fail closed,不回退 legacy command",
|
|
"projects direct lifecycle notifications into the existing GUI payloads",
|
|
"routes drained direct notifications and closes on turn/completed",
|
|
"拒绝 retired agentSession/event wrapper",
|
|
"即使 wrapper 携带 canonicalEvent/typedEvent 也应 fail closed",
|
|
"request projection 应在未传可选项时保持精简 App Server 参数",
|
|
"replay request 无当前 typed server-request 时应 fail closed 且不调用旧 action/replay",
|
|
"listenAgentRuntimeEvent",
|
|
"appServerClient.startTurn",
|
|
"appServerClient.cancelTurn",
|
|
"appServerClient.startThreadCompaction",
|
|
"appServerClient.resumeThread",
|
|
"findPendingTypedServerRequestAction",
|
|
"respondPendingTypedServerRequest",
|
|
"同作用域 AskUser typed pending 应由 controller settle",
|
|
"typed pending scope 不匹配时 fail closed",
|
|
"App Server turn lifecycle is unavailable; Agent Runtime requires the App Server current lifecycle channel.",
|
|
"expect(invokeCommand).not.toHaveBeenCalled()",
|
|
],
|
|
absentSnippets: [
|
|
"App Server 不可用时 submit 应保留 legacy fallback",
|
|
"缺少 turn_id 时 interrupt 应回退 legacy command",
|
|
"AGENT_RUNTIME_COMMANDS",
|
|
"publishAgentRuntimeEvent",
|
|
"resumeAgentSessionThread",
|
|
"resumeAgentRuntimeThread",
|
|
"RuntimeResumeContract",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent API facade locks lifecycle to Electron IPC App Server JSON-RPC",
|
|
file: "src/lib/api/agent.test.ts",
|
|
snippets: [
|
|
'expect(call?.[0]).toBe("app_server_handle_json_lines")',
|
|
"APP_SERVER_METHOD_TURN_START",
|
|
"APP_SERVER_METHOD_THREAD_DELETE",
|
|
"APP_SERVER_METHOD_THREAD_RESUME",
|
|
"submitAgentRuntimeTurn 应经 Electron IPC 调 App Server turn/start",
|
|
"replayAgentRuntimeRequest 无当前 typed pending 时应 fail closed",
|
|
"respondAgentRuntimeAction 缺少 typed pending 时应 fail closed,不发旧 action/respond",
|
|
"resumeThread 应经 Electron IPC 调 App Server thread/resume",
|
|
"mockIsElectronHostCommandAvailable.mockReturnValue(true)",
|
|
"expectAppServerRequest(1, APP_SERVER_METHOD_TURN_START",
|
|
"expectAppServerRequest(2, APP_SERVER_METHOD_THREAD_DELETE",
|
|
"generic agentSession/action/respond is retired",
|
|
"expectAppServerRequest(1, APP_SERVER_METHOD_THREAD_RESUME",
|
|
],
|
|
absentSnippets: [
|
|
"submitAgentRuntimeTurn 应走统一 runtime submit 命令",
|
|
"respondAgentRuntimeAction 应走统一 action 响应命令",
|
|
'"agent_runtime_submit_turn"',
|
|
'"agent_runtime_interrupt_turn"',
|
|
'"agent_runtime_respond_action"',
|
|
'"agent_runtime_export_evidence_pack"',
|
|
"resumeAgentSessionThread",
|
|
"resumeAgentRuntimeThread",
|
|
"RuntimeResumeContract",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime client factory prevents lifecycle and queue bridgeInvoke fallback",
|
|
file: "src/lib/api/agentRuntime/clientFactory.test.ts",
|
|
snippets: [
|
|
"queue/session control 应走 App Server current,且不再暴露 retired site adapter surface",
|
|
"queue/session control 不应回退到 legacy bridgeInvoke",
|
|
"appServerClient.resumeThread",
|
|
'expect(client).not.toHaveProperty("siteListAdapters")',
|
|
'expect(client).not.toHaveProperty("siteRunAdapter")',
|
|
"expect(invoke).not.toHaveBeenCalled()",
|
|
"turn lifecycle 应走 App Server client,不复用 legacy bridgeInvoke",
|
|
"appServerClient.startTurn",
|
|
"expect(bridgeInvoke).not.toHaveBeenCalled()",
|
|
],
|
|
absentSnippets: [
|
|
'"agent_runtime_submit_turn"',
|
|
'"agent_runtime_interrupt_turn"',
|
|
'"agent_runtime_respond_action"',
|
|
"resumeAgentSessionThread",
|
|
"resumeAgentRuntimeThread",
|
|
"RuntimeResumeContract",
|
|
],
|
|
},
|
|
{
|
|
name: "Agent runtime client package exposes session gateway adapter",
|
|
files: [
|
|
"packages/agent-runtime-client/package.json",
|
|
"packages/agent-runtime-client/README.md",
|
|
"packages/agent-runtime-client/src/index.ts",
|
|
"packages/agent-runtime-client/src/sessionGateway.ts",
|
|
"packages/agent-runtime-client/tests/client.test.mjs",
|
|
"tsconfig.json",
|
|
"vite.config.ts",
|
|
],
|
|
snippets: [
|
|
'"./sessionGateway"',
|
|
"@limecloud/agent-runtime-client/sessionGateway",
|
|
"./packages/agent-runtime-client/src/sessionGateway.ts",
|
|
"./packages/app-server-client/src/browser.ts",
|
|
"browser-safe 子路径",
|
|
"createAgentRuntimeClientFromSessionGateway",
|
|
"type AgentRuntimeLifecycleClient",
|
|
"type AgentRuntimeSessionGateway",
|
|
'"startTurn" | "steerTurn" | "readThread" | "cancelTurn" | "respondAction"',
|
|
"readThread:",
|
|
"callAgentRuntimeSessionGateway(gateway.readThread, params, options)",
|
|
"if (options === undefined)",
|
|
"createAgentRuntimeClientFromSessionGateway(...)` 只适配现有 session gateway",
|
|
"readThread",
|
|
"timeoutMs: 120_000",
|
|
],
|
|
absentSnippets: [
|
|
"safeInvoke",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
"invokeMockOnly",
|
|
"plugin_runtime_",
|
|
"agent_runtime_submit_turn",
|
|
"fetch(",
|
|
"XMLHttpRequest",
|
|
],
|
|
},
|
|
{
|
|
name: "Desktop Host renderer invoke does not fall back to default mocks",
|
|
file: "src/lib/desktop-host/core.ts",
|
|
snippets: [
|
|
"Frontend -> Electron Desktop Host IPC -> App Server JSON-RPC -> RuntimeCore / backend",
|
|
"生产 invoke 不再回退 mock",
|
|
"export async function invokeMockOnly<T = any>",
|
|
"return invokeDefaultMock<T>(cmd, args)",
|
|
"export async function invoke<T = any>",
|
|
"const electronHost = getElectronHostBridge()",
|
|
"return electronHost.invoke<T>(cmd, args)",
|
|
"return await invokeViaHttp<T>(cmd, args)",
|
|
"throw normalizeDevBridgeError(cmd, error)",
|
|
"无法进入 App Server JSON-RPC 主链",
|
|
],
|
|
absentSnippets: [
|
|
"shouldPreferMockInBrowser",
|
|
"shouldDisallowMockFallbackInBrowser",
|
|
"fallback 使用",
|
|
],
|
|
},
|
|
{
|
|
name: "Desktop Host tests lock production fail-closed and explicit mock-only boundary",
|
|
file: "src/lib/desktop-host/core.test.ts",
|
|
snippets: [
|
|
"HTTP bridge 失败时 production invoke 直接抛出规范化错误",
|
|
"无 Electron host 且无 HTTP bridge 时 production invoke fail-closed",
|
|
"测试注册的配置 mock",
|
|
"知识库 legacy 显式 mock 已退场",
|
|
"工具库存 legacy 显式 mock 已退场",
|
|
"显式 mock 入口可返回默认工作区数据已退场",
|
|
"媒体任务 artifact 默认 mock 已退场并 fail closed",
|
|
'invokeMockOnly("agent_runtime_get_tool_inventory"',
|
|
'未注册命令 "agent_runtime_get_tool_inventory"',
|
|
"expect(mocks.invokeViaHttp).not.toHaveBeenCalled()",
|
|
],
|
|
absentSnippets: [
|
|
"shouldPreferMockInBrowser",
|
|
"mock 优先命令直接返回默认 mock",
|
|
"bridge 失败且命令存在 mock 时回退默认 mock 数据",
|
|
"fallback mock 应",
|
|
"命令在 bridge 失败时应回退",
|
|
"媒体任务显式 mock 应返回统一 task file 协议",
|
|
"音频任务显式 mock 应返回 voice_generation task file 协议",
|
|
],
|
|
},
|
|
{
|
|
name: "Desktop Host core no longer loads Agent Runtime default mocks",
|
|
file: "src/lib/desktop-host/core.ts",
|
|
snippets: [
|
|
"生产 invoke 不再回退 mock",
|
|
"export async function invokeMockOnly<T = any>",
|
|
"const defaultMocks = await loadDefaultMocks()",
|
|
],
|
|
absentSnippets: [
|
|
'import("./agentRuntimeMocks")',
|
|
'import("./agentRuntimeObjectiveMocks")',
|
|
"agentRuntime.agentRuntimeMocks",
|
|
"agentRuntimeObjective.resetAgentRuntimeObjectiveMocks",
|
|
"agent_runtime_submit_turn:",
|
|
"agent_runtime_interrupt_turn:",
|
|
"agent_runtime_respond_action:",
|
|
],
|
|
},
|
|
{
|
|
name: "Frontend integration matrix forbids legacy or mock turn lifecycle evidence",
|
|
file: "internal/roadmap/appserver/frontend-integration-matrix.md",
|
|
snippets: [
|
|
"Frontend -> Electron Desktop Host bridge -> App Server JSON-RPC -> RuntimeCore / backend",
|
|
"真正的后端事实源只有一个:App Server JSON-RPC",
|
|
"submit / cancel / respond 已改为 App Server current-only",
|
|
"当 `app_server_handle_json_lines` 不可用时 fail closed,不再回退 `agent_runtime_*`",
|
|
"生产不能 mock,只有测试才 mock",
|
|
"`scripts/check-command-contracts.mjs` 必须扫描 `src / electron / packages` 的生产源码",
|
|
"禁止 `explicitMockFallback`、`invokeMockOnly`、`mockCommand`、`clearMocks`、`invokeExplicitMock`、`listenExplicitMock` 进入生产路径",
|
|
"不能把 initialize smoke 或 hook 测试误判成完整聊天闭环",
|
|
"`agent_runtime_submit_turn` / `agent_runtime_interrupt_turn` / `agent_runtime_respond_action`",
|
|
"只能作为负向回归扫描对象,不能作为 Agent turn lifecycle 的完成证据",
|
|
"`claw-chat-ready-streaming` 是用户显式发起的 live E2E 入口,不再要求 `--allow-live-provider` 二次授权",
|
|
"证明 `WebSearch` / `WebFetch` 同一 turn 的真实工具事件与 read model 输出",
|
|
"不能用 mock、无模型探针、Provider 自动探测或 renderer fallback 替代真实业务闭环",
|
|
"handoff bundle / replay case / analysis handoff / review decision template / save review decision 已分别通过",
|
|
"| canonical read model / derived exports",
|
|
"| `wired`",
|
|
],
|
|
absentSnippets: [
|
|
"Electron truth adapter",
|
|
"legacy facade 投影作为完成路线",
|
|
"mock-only 成功作为完成证据",
|
|
],
|
|
},
|
|
{
|
|
name: "Command contract scans production mock-only usage outside tests",
|
|
file: "scripts/check-command-contracts.mjs",
|
|
snippets: [
|
|
'const sourceRoots = ["src"]',
|
|
'const productionRuntimeRoots = ["src", "electron", "packages"]',
|
|
"function collectFrontendCommandUsage()",
|
|
"for (const root of sourceRoots)",
|
|
"function collectProductionMockOnlyUsageFailures()",
|
|
"for (const root of productionRuntimeRoots)",
|
|
"function isAllowedTestMockFixtureSource(relativePath)",
|
|
"生产源码不能调用测试 mock invoke 入口",
|
|
"生产源码不能注册 renderer mock command",
|
|
"生产源码不能清理测试 mock command",
|
|
"生产源码不能调用显式 renderer mock fallback",
|
|
"生产源码不能调用显式 renderer event mock fallback",
|
|
"生产源码不能导入显式 renderer mock fallback",
|
|
"生产源码不能导入 desktop-host 测试 mock 入口",
|
|
"failures.push(...collectProductionMockOnlyUsageFailures())",
|
|
],
|
|
absentSnippets: [
|
|
'for (const root of productionRuntimeRoots) {\n const absoluteRoot = path.join(repoRoot, root);\n for (const relativePath of walkDirectory(absoluteRoot)) {\n const absolutePath = path.join(repoRoot, relativePath);\n const sourceCode = fs.readFileSync(absolutePath, "utf8");',
|
|
],
|
|
},
|
|
{
|
|
name: "Execution plan records Agent turn lifecycle as current-only after P3.122",
|
|
file: "internal/exec-plans/app-server-implementation-plan.md",
|
|
snippets: [
|
|
"P3.135 Agent turn lifecycle current-only 文档 / 契约守卫",
|
|
"该诊断已由 P3.122 之后的 current-only 改造收口",
|
|
"后续不得再把该旧路径作为可选实现或完成证据",
|
|
"后续结论已由 P3.122 确定",
|
|
"前端 Agent turn lifecycle 必须直接经 `src/lib/api/appServer.ts -> app_server_handle_json_lines -> App Server JSON-RPC`",
|
|
"legacy facade 只可作为已退役兼容残留,不再作为二选一实现路径",
|
|
],
|
|
absentSnippets: [
|
|
"后续实现时优先二选一",
|
|
"legacy facade 投影到 App Server method,禁止两条路同时长",
|
|
],
|
|
},
|
|
{
|
|
name: "Execution plan records production mock and live-provider smoke gates",
|
|
file: "internal/exec-plans/app-server-implementation-plan.md",
|
|
snippets: [
|
|
"P3.137 production mock / live-provider gate 收口",
|
|
"生产不能 mock,只有测试才 mock",
|
|
"`scripts/check-command-contracts.mjs` 的生产 mock-only 扫描已覆盖 `src / electron / packages`",
|
|
"前端命令统计仍只扫描 `src`",
|
|
"P3.308 Claw live E2E 二次授权 gate 清理",
|
|
"`claw-chat-ready-streaming` 是用户显式发起的 live Provider / WebSearch-WebFetch E2E 入口",
|
|
"不再要求 `--allow-live-provider` 二次授权",
|
|
"P3.316 Claw live E2E 二次授权残留清理",
|
|
"P3.316 live E2E 自动选型修正",
|
|
"历史早期 P3.137/P3.194/P3.220 等记录只作为 historical evidence,不再作为 current 执行指令",
|
|
],
|
|
},
|
|
{
|
|
name: "Claw chat streaming smoke proves GUI turn lifecycle through App Server JSON-RPC",
|
|
file: "scripts/claw-chat-ready-streaming-smoke.mjs",
|
|
snippets: [
|
|
'const APP_SERVER_HANDLE_JSON_LINES_COMMAND = "app_server_handle_json_lines"',
|
|
"const APP_SERVER_METHOD_TURN_START",
|
|
'"turn/start"',
|
|
"const APP_SERVER_METHOD_TURN_INTERRUPT",
|
|
'"turn/interrupt"',
|
|
'const APP_SERVER_METHOD_THREAD_READ = "thread/read"',
|
|
'const APP_SERVER_METHOD_AGENT_SESSION_EVENT = "agentSession/event"',
|
|
"attachAppServerRequestMessages(",
|
|
"attachAppServerResponsePayload(",
|
|
"function findAppServerMethodRecord(",
|
|
"function appServerMethodSeen(",
|
|
"function isSmokeDiagnosticJsonRpcId(",
|
|
"function appServerSessionReadAfterEventEvidence(",
|
|
"async function readAppServerSession(",
|
|
"async function readAppServerThreadRead(",
|
|
"async function cancelAppServerTurn(",
|
|
"等待长 turn App Server submit",
|
|
"等待 App Server turn cancel invoke",
|
|
"等待恢复 turn App Server submit",
|
|
"DevBridge transport must be electron-host",
|
|
"summary.longSubmitAppServer",
|
|
"summary.interruptAppServer",
|
|
"summary.followSubmitAppServer",
|
|
"summary.appServerEvidence =",
|
|
"appServerTurnStartSeen",
|
|
"appServerTurnCancelSeen",
|
|
"longTurnFastCompleteAccepted",
|
|
"longTurnCanBeInterrupted",
|
|
"appServerSessionReadSeen",
|
|
"appServerEventSeen",
|
|
"appServerSessionReadAfterEventSeen",
|
|
'electronHostBridge: health?.transport === "electron-host"',
|
|
"readAfterEvent: appServerReadAfterEvent",
|
|
"interruptedTurnCanceled",
|
|
"summary.assertions.appServerTurnStartSeen &&",
|
|
"(summary.assertions.longTurnCanBeInterrupted ||",
|
|
"summary.assertions.longTurnFastCompleteAccepted) &&",
|
|
"summary.assertions.appServerSessionReadSeen &&",
|
|
"summary.assertions.appServerEventSeen &&",
|
|
"summary.assertions.appServerSessionReadAfterEventSeen &&",
|
|
"summary.assertions.electronHostBridge &&",
|
|
],
|
|
absentSnippets: [
|
|
'item.cmd === "agent_runtime_submit_turn"',
|
|
'item.cmd === "agent_runtime_interrupt_turn"',
|
|
'"agent_runtime_promote_queued_turn"',
|
|
'"agent_runtime_get_session"',
|
|
'"agent_runtime_get_thread_read"',
|
|
"interruptCommandSeen",
|
|
"interruptedTurnAborted",
|
|
],
|
|
},
|
|
{
|
|
name: "Claw chat streaming smoke is explicit live E2E without duplicate provider gate",
|
|
file: "scripts/claw-chat-ready-streaming-smoke.mjs",
|
|
snippets: [
|
|
'logStage("wait-health")',
|
|
'logStage("prepare-runtime")',
|
|
'"modelProvider/list"',
|
|
'"modelProvider/testChat"',
|
|
"LIVE_WEB_TOOL_PROMPT",
|
|
"REQUIRED_LIVE_WEB_TOOL_NAMES",
|
|
"function modelLooksLightweight(",
|
|
"function modelLooksExpensive(",
|
|
"function modelLooksToolReliable(",
|
|
"modelLooksToolReliable(value)",
|
|
"modelLooksLightweight(model)",
|
|
"modelLooksExpensive(model)",
|
|
"modelPenalty",
|
|
"@搜索 关键词:联网工具验证",
|
|
"webSearch=true",
|
|
'searchMode="required"',
|
|
"liveWebExplicitSearchRequired",
|
|
],
|
|
absentSnippets: [
|
|
'from "./lib/live-provider-smoke-gate.mjs"',
|
|
"assertLiveProviderSmokeAllowed({",
|
|
"liveProviderSmokeAllowed(",
|
|
"allowLiveProvider",
|
|
"--allow-live-provider",
|
|
],
|
|
},
|
|
{
|
|
name: "Social Workbench smoke uses App Server current session read model",
|
|
file: "scripts/social-workbench-e2e-smoke.mjs",
|
|
snippets: [
|
|
'const APP_SERVER_HANDLE_JSON_LINES_COMMAND = "app_server_handle_json_lines"',
|
|
'const METHOD_THREAD_READ = "thread/read"',
|
|
"async function readAgentSession(sessionId)",
|
|
"function projectWorkbenchState(sessionRead, limit)",
|
|
"function projectRunDetail(sessionRead, runId)",
|
|
"await invokeAppServerJsonRpc(METHOD_THREAD_READ",
|
|
"thread/read 未能投影运行详情",
|
|
],
|
|
absentSnippets: [
|
|
'"execution_run_get_theme_workbench_state"',
|
|
'"execution_run_get"',
|
|
],
|
|
},
|
|
{
|
|
name: "Electron Desktop Host records Connect deep links from startup and second-instance args",
|
|
file: "electron/main.ts",
|
|
snippets: [
|
|
"function normalizeDeepLinkUrl(",
|
|
'trimmed.startsWith("lime://")',
|
|
"function collectDeepLinkUrls(",
|
|
"function recordDeepLinkUrls(",
|
|
"recordDeepLinkUrls(collectDeepLinkUrls(process.argv))",
|
|
"recordDeepLinkUrls(collectDeepLinkUrls(argv))",
|
|
"ELECTRON_E2E_USER_DATA_DIR",
|
|
'app.setPath("userData", resolvedUserDataDir)',
|
|
],
|
|
absentSnippets: [
|
|
'const url = argv.find((arg) => arg.startsWith("lime://"))',
|
|
"handle_deep_link",
|
|
"handle_open_deep_link",
|
|
],
|
|
},
|
|
{
|
|
name: "Connect deep link current smoke proves Electron preload to App Server JSON-RPC path",
|
|
file: "scripts/connect-deep-link-current-smoke.mjs",
|
|
snippets: [
|
|
'import { _electron as electron } from "playwright"',
|
|
'const APP_SERVER_HANDLE_JSON_LINES_COMMAND = "app_server_handle_json_lines"',
|
|
'const REQUIRED_APP_SERVER_METHOD = "connectDeepLink/resolve"',
|
|
"const FORBIDDEN_CONNECT_COMMANDS = [",
|
|
'"handle_deep_link"',
|
|
'"handle_open_deep_link"',
|
|
'"save_relay_api_key"',
|
|
'"send_connect_callback"',
|
|
'"list_relay_providers"',
|
|
'"refresh_relay_registry"',
|
|
"window.__LIME_ELECTRON__ === true",
|
|
"window.electronAPI?.deepLink?.getCurrent",
|
|
"await window.electronAPI.deepLink.getCurrent()",
|
|
'args: ["--use-mock-keychain", ".", options.deepLinkUrl]',
|
|
"ELECTRON_E2E_USER_DATA_DIR: tmpUserDataDir",
|
|
"appServerHandleJsonLinesSeen",
|
|
"connectDeepLinkResolveSeen",
|
|
"forbiddenCommandsSeen.length === 0",
|
|
"await cancelConnectDialog(page)",
|
|
],
|
|
absentSnippets: [
|
|
"invokeViaHttp",
|
|
"chromium.launch",
|
|
"agent_runtime_",
|
|
"safeInvoke",
|
|
],
|
|
},
|
|
{
|
|
name: "Connect deep link save smoke proves API Key save and callback current path",
|
|
file: "scripts/connect-deep-link-save-current-smoke.mjs",
|
|
snippets: [
|
|
'import { _electron as electron } from "playwright"',
|
|
'const APP_SERVER_HANDLE_JSON_LINES_COMMAND = "app_server_handle_json_lines"',
|
|
'"connectDeepLink/resolve"',
|
|
'"connectRelayApiKey/save"',
|
|
'"connectCallback/send"',
|
|
"seedConnectRegistryCaches(",
|
|
"registryPayload()",
|
|
"HOME: home",
|
|
"XDG_DATA_HOME: xdgDataHome",
|
|
"APPDATA: appData",
|
|
"LOCALAPPDATA: localAppData",
|
|
"LIME_AGENT_RUNTIME_ROOT: agentRoot",
|
|
"ELECTRON_E2E_USER_DATA_DIR: tmpUserDataDir",
|
|
'args: ["--use-mock-keychain", ".", options.deepLinkUrl]',
|
|
"LIME_ELECTRON_E2E",
|
|
"callbackNetworkDeliveryVerified: false",
|
|
"await clickConfirm(page)",
|
|
"waitForSaveEvidence(page, options)",
|
|
"dialogClosedAfterConfirm",
|
|
"missingRequiredAppServerMethods.length === 0",
|
|
"databaseFiles.length > 0",
|
|
"const FORBIDDEN_CONNECT_COMMANDS = [",
|
|
'"handle_deep_link"',
|
|
'"handle_open_deep_link"',
|
|
'"save_relay_api_key"',
|
|
'"send_connect_callback"',
|
|
'"list_relay_providers"',
|
|
'"refresh_relay_registry"',
|
|
"forbiddenCommandsSeen.length === 0",
|
|
],
|
|
absentSnippets: [
|
|
"invokeViaHttp",
|
|
"chromium.launch",
|
|
"agent_runtime_",
|
|
"safeInvoke",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
"invokeMockOnly",
|
|
],
|
|
},
|
|
{
|
|
name: "Connect open deep link smoke proves website entry current path",
|
|
file: "scripts/connect-open-deep-link-current-smoke.mjs",
|
|
snippets: [
|
|
'import { _electron as electron } from "playwright"',
|
|
'const APP_SERVER_HANDLE_JSON_LINES_COMMAND = "app_server_handle_json_lines"',
|
|
'const REQUIRED_APP_SERVER_METHOD = "connectOpenDeepLink/resolve"',
|
|
"const EXPECTED_BANNER_TEXT =",
|
|
"const EXPECTED_PROMPT_TEXT =",
|
|
"const FORBIDDEN_CONNECT_COMMANDS = [",
|
|
'"handle_deep_link"',
|
|
'"handle_open_deep_link"',
|
|
'"save_relay_api_key"',
|
|
'"send_connect_callback"',
|
|
'"list_relay_providers"',
|
|
'"refresh_relay_registry"',
|
|
"window.__LIME_ELECTRON__ === true",
|
|
"window.electronAPI?.deepLink?.getCurrent",
|
|
"await window.electronAPI.deepLink.getCurrent()",
|
|
"websiteOpenBannerVisible",
|
|
"websitePromptVisible",
|
|
"connectOpenDeepLinkResolveSeen",
|
|
"connectDialogVisible",
|
|
"appServerHandleJsonLinesSeen",
|
|
"forbiddenCommandsSeen.length === 0",
|
|
"HOME: home",
|
|
"XDG_DATA_HOME: xdgDataHome",
|
|
"APPDATA: appData",
|
|
"LOCALAPPDATA: localAppData",
|
|
"LIME_AGENT_RUNTIME_ROOT: agentRoot",
|
|
"ELECTRON_E2E_USER_DATA_DIR: tmpUserDataDir",
|
|
'args: ["--use-mock-keychain", ".", options.deepLinkUrl]',
|
|
"LIME_ELECTRON_E2E",
|
|
],
|
|
absentSnippets: [
|
|
"invokeViaHttp",
|
|
"chromium.launch",
|
|
"agent_runtime_",
|
|
"safeInvoke",
|
|
"mockPriorityCommands",
|
|
"defaultMocks",
|
|
"invokeMockOnly",
|
|
"saveConnectRelayApiKey",
|
|
"sendConnectCallback",
|
|
],
|
|
},
|
|
{
|
|
name: "Agent runtime tool surface page smoke uses App Server current runtime methods",
|
|
file: "scripts/agent-runtime/tool-surface-page-smoke.mjs",
|
|
snippets: [
|
|
'const APP_SERVER_HANDLE_JSON_LINES_COMMAND = "app_server_handle_json_lines"',
|
|
'const APP_SERVER_METHOD_THREAD_START = "thread/start"',
|
|
'const APP_SERVER_METHOD_THREAD_SETTINGS_UPDATE = "thread/settings/update"',
|
|
'const APP_SERVER_METHOD_THREAD_READ = "thread/read"',
|
|
'const APP_SERVER_METHOD_THREAD_LIST = "thread/list"',
|
|
"const APP_SERVER_METHOD_TURN_START =",
|
|
'"turn/start"',
|
|
"const APP_SERVER_METHOD_ITEM_COMMAND_EXECUTION_REQUEST_APPROVAL =",
|
|
'"item/commandExecution/requestApproval"',
|
|
'const APP_SERVER_METHOD_SERVER_REQUEST_RESOLVED = "serverRequest/resolved"',
|
|
"const APP_SERVER_METHOD_AGENT_SESSION_FILE_CHECKPOINT_LIST =",
|
|
'"agentSession/fileCheckpoint/list"',
|
|
"const APP_SERVER_METHOD_AGENT_SESSION_FILE_CHECKPOINT_GET =",
|
|
'"agentSession/fileCheckpoint/get"',
|
|
"const APP_SERVER_METHOD_AGENT_SESSION_FILE_CHECKPOINT_DIFF =",
|
|
'"agentSession/fileCheckpoint/diff"',
|
|
"const APP_SERVER_METHOD_AGENT_SESSION_FILE_CHECKPOINT_RESTORE =",
|
|
'"agentSession/fileCheckpoint/restore"',
|
|
"FORBIDDEN_AGENT_RUNTIME_CURRENT_METHOD_COMMANDS",
|
|
"legacy_agent_runtime_current_method_command",
|
|
"hasAppServerMethodCount(",
|
|
"APP_SERVER_METHOD_TURN_START",
|
|
"APP_SERVER_METHOD_ITEM_COMMAND_EXECUTION_REQUEST_APPROVAL",
|
|
"APP_SERVER_METHOD_SERVER_REQUEST_RESOLVED",
|
|
"buildCodeRuntimeApprovalServerRequest()",
|
|
"isExpectedApprovalServerRequestResponse(",
|
|
"APP_SERVER_METHOD_AGENT_SESSION_TOOL_INVENTORY_READ",
|
|
"APP_SERVER_METHOD_AGENT_SESSION_FILE_CHECKPOINT_RESTORE",
|
|
"findForbiddenAgentRuntimeCurrentMethodCommands(finalDiagnostics)",
|
|
],
|
|
absentSnippets: [
|
|
'command === "agent_runtime_get_thread_read"',
|
|
'command === "agent_runtime_submit_turn"',
|
|
'command === "agent_runtime_respond_action"',
|
|
'"agentSession/action/respond"',
|
|
'command === "agent_runtime_create_session"',
|
|
'command === "agent_runtime_update_session"',
|
|
'command === "agent_runtime_list_file_checkpoints"',
|
|
'command === "agent_runtime_diff_file_checkpoint"',
|
|
'command === "agent_runtime_restore_file_checkpoint"',
|
|
'"agent_runtime_get_thread_read")',
|
|
'"agent_runtime_submit_turn")',
|
|
'"agent_runtime_respond_action")',
|
|
],
|
|
},
|
|
{
|
|
name: "Code runtime fixture smoke uses App Server JSON-RPC current runtime path",
|
|
file: "scripts/code-runtime-fixture-smoke.mjs",
|
|
snippets: [
|
|
'const APP_SERVER_HANDLE_JSON_LINES_COMMAND = "app_server_handle_json_lines"',
|
|
'const APP_SERVER_METHOD_THREAD_START = "thread/start"',
|
|
'const APP_SERVER_METHOD_THREAD_SETTINGS_UPDATE = "thread/settings/update"',
|
|
'const APP_SERVER_METHOD_TURN_START = "turn/start"',
|
|
'const APP_SERVER_METHOD_THREAD_READ = "thread/read"',
|
|
"const APP_SERVER_METHOD_AGENT_SESSION_FILE_CHECKPOINT_LIST =",
|
|
'"agentSession/fileCheckpoint/list"',
|
|
"const APP_SERVER_METHOD_AGENT_SESSION_FILE_CHECKPOINT_DIFF =",
|
|
'"agentSession/fileCheckpoint/diff"',
|
|
"async function invokeAppServer(",
|
|
"APP_SERVER_METHOD_THREAD_START",
|
|
"APP_SERVER_METHOD_THREAD_SETTINGS_UPDATE",
|
|
"APP_SERVER_METHOD_TURN_START",
|
|
"APP_SERVER_METHOD_THREAD_READ",
|
|
"APP_SERVER_METHOD_AGENT_SESSION_FILE_CHECKPOINT_LIST",
|
|
"APP_SERVER_METHOD_AGENT_SESSION_FILE_CHECKPOINT_DIFF",
|
|
"function buildRuntimeRequest({",
|
|
"runtimeRequest,",
|
|
"providerConfig: fixture.provider.providerConfig",
|
|
"usesAppServerJsonRpcSubmitTurn",
|
|
"usesAppServerSessionRead",
|
|
"usesAppServerFileCheckpointCurrent",
|
|
],
|
|
absentSnippets: [
|
|
'"agent_runtime_create_session"',
|
|
'"agent_runtime_update_session"',
|
|
'"agent_runtime_submit_turn"',
|
|
'"agent_runtime_get_session"',
|
|
'"agent_runtime_get_thread_read"',
|
|
'"agent_runtime_export_evidence_pack"',
|
|
'"agent_runtime_list_file_checkpoints"',
|
|
'"agent_runtime_diff_file_checkpoint"',
|
|
"usesCurrentRuntimeSubmitTurn",
|
|
"usesFileCheckpointCompat",
|
|
"turnConfig",
|
|
"turn_config",
|
|
"agentChatRequest",
|
|
"agent_chat_request",
|
|
"hostOptions",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime event source accepts App Server local fanout",
|
|
file: "src/lib/api/agentRuntimeEvents.ts",
|
|
snippets: [
|
|
"export function publishAgentRuntimeEvent",
|
|
"localRuntimeEventListeners",
|
|
"listenLocalAgentRuntimeEvent(",
|
|
"projectAgentRuntimeSequenceGatePayloads(",
|
|
"handler({ payload: projectedPayload })",
|
|
"const unlistenLocal = listenLocalAgentRuntimeEvent(",
|
|
"const bridgeHandler: AgentRuntimeEventHandler<TPayload> = (event) => {",
|
|
"const unlistenBridge = await listen(",
|
|
"unlistenLocal();",
|
|
"unlistenBridge();",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime event tests lock App Server local fanout",
|
|
file: "src/lib/api/agentRuntimeEvents.test.ts",
|
|
snippets: [
|
|
"应把本地发布的 App Server runtime 事件投递给现有 listener",
|
|
'publishAgentRuntimeEvent("agent_stream_message-1"',
|
|
'type: "text_delta"',
|
|
"App Server delta",
|
|
"应在 Lime runtime event 网关阻断未配对的 App Server tool.result",
|
|
"tool-orphan",
|
|
"unlisten();",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent chat sync refreshes session detail from current App Server turn events",
|
|
file: "src/components/agent/chat/hooks/useAgentRuntimeSyncEffects.ts",
|
|
snippets: [
|
|
"currentTurnEventName?: string | null",
|
|
"const normalizedCurrentTurnEventName = currentTurnEventName?.trim() || null",
|
|
"function resolveRefreshRequestForTurnEventPayload(",
|
|
"function preferRuntimeRefreshRequest(",
|
|
"deferredRuntimeRefreshRequestRef",
|
|
'case "action_required":',
|
|
'case "action_resolved":',
|
|
'case "artifact_snapshot":',
|
|
'case "runtime_status":',
|
|
'case "turn_completed":',
|
|
'case "turn_canceled":',
|
|
'case "turn_failed":',
|
|
"runtime.listenToTurnEvents(",
|
|
"normalizedCurrentTurnEventName",
|
|
"!refreshRequest",
|
|
"refreshSessionDetail(targetSessionId, request)",
|
|
"RUNTIME_SYNC_REFRESH_REQUESTS.sendSettled",
|
|
"RUNTIME_SYNC_REFRESH_REQUESTS.event",
|
|
"RUNTIME_SYNC_REFRESH_REQUESTS.terminalEvent",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent chat sync centralizes App Server bridge availability",
|
|
file: "src/components/agent/chat/hooks/useAgentRuntimeSyncEffects.ts",
|
|
snippets: [
|
|
"isAppServerBridgeAvailable",
|
|
"const APP_SERVER_BRIDGE_RUNTIME_POLL_MS = 1000",
|
|
"const shouldUseAppServerBridgeRuntimePolling",
|
|
"isAppServerBridgeAvailable()",
|
|
"!hasRuntimeEventListenerCapability",
|
|
],
|
|
absentSnippets: [
|
|
"isDevBridgeAvailable(",
|
|
"app_server_handle_json_lines",
|
|
"DEV_BRIDGE_RUNTIME_POLL_MS",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent chat sync tests lock App Server event session-detail refresh boundary",
|
|
file: "src/components/agent/chat/hooks/useAgentRuntimeSyncEffects.test.tsx",
|
|
snippets: [
|
|
"收到当前 turn 的 App Server runtime event 后应刷新会话详情",
|
|
"当前 turn 的 text_delta 不应触发完整 read model 刷新",
|
|
"App Server turn notification 应通过当前 stream event 触发会话详情刷新",
|
|
"createThreadClient",
|
|
"listenAgentRuntimeEvent(name, handler)",
|
|
'method: "turn/completed"',
|
|
'currentTurnEventName: "agent_stream_assistant-1"',
|
|
'type: "runtime_status"',
|
|
'type: "text_delta"',
|
|
'type: "turn.completed"',
|
|
'type: "turn.failed"',
|
|
'type: "turn.canceled"',
|
|
'terminalRefreshRequest("runtimeSync.event")',
|
|
'runtimeSyncRefreshRequest("runtimeSync.sendSettled")',
|
|
"expect(refreshSessionDetail).not.toHaveBeenCalled()",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent task status keeps turn.completed non-terminal while assistant awaits final response",
|
|
file: "src/components/agent/chat/utils/agentTaskRuntime.ts",
|
|
snippets: [
|
|
"export function isAssistantAwaitingFinalResponse(",
|
|
'latestAssistant.runtimeStatus?.phase !== "failed"',
|
|
'latestAssistant.runtimeStatus?.phase !== "cancelled"',
|
|
'case "completed":\n if (isAssistantAwaitingFinalResponse(latestAssistant)) {\n return "running";',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer inputbar status reuses assistant final-response guard",
|
|
file: "src/components/agent/chat/utils/inputbarRuntimeStatusLine.ts",
|
|
snippets: [
|
|
"isAssistantAwaitingFinalResponse",
|
|
"function resolveVisibleCompletedAt(",
|
|
'status === "completed" || status === "failed" || status === "aborted"',
|
|
'case "completed":\n if (isAssistantAwaitingFinalResponse(latestAssistant)) {\n return "running";',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent task runtime tests lock turn.completed first-token waiting state",
|
|
file: "src/components/agent/chat/utils/agentTaskRuntime.test.ts",
|
|
snippets: [
|
|
"turn_completed 没有可见输出时不应把等待首个输出的助手草稿标记为已完成",
|
|
'phase: "routing"',
|
|
'status: "completed" as const',
|
|
'expect(taskModel?.status).toBe("running")',
|
|
'expect(inputbarModel?.status).toBe("running")',
|
|
"expect(inputbarModel?.completedAt).toBeNull()",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent stream handler projects canonical Item lifecycle through ConversationProjection",
|
|
files: [
|
|
"src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts",
|
|
"src/components/agent/chat/hooks/agentStreamRuntimeHandlerTypes.ts",
|
|
"src/components/agent/chat/hooks/agentStreamRuntimeLifecycleEvents.ts",
|
|
"src/components/agent/chat/hooks/agentStreamConversationProjection.ts",
|
|
],
|
|
snippets: [
|
|
"applyAgentStreamConversationProjection",
|
|
"conversationProjectionOwner",
|
|
"reconcileAgentStreamProjectionItems",
|
|
"getThreadItems?: () => readonly AgentThreadItem[]",
|
|
'case "item_completed":',
|
|
"projectedItems:",
|
|
],
|
|
absentSnippets: [
|
|
"syncMessageToolCallFromThreadItem",
|
|
"agentStreamToolItemMessageSync",
|
|
"toolCallStateFromThreadItem",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer MessageList gates legacy message.toolCalls behind missing process timeline",
|
|
files: [
|
|
"src/components/agent/chat/components/messageListItemProjection.ts",
|
|
"src/components/agent/chat/components/messageListItemProjection.unit.test.ts",
|
|
"src/components/agent/chat/components/messageListItemProjection.legacyTools.unit.test.ts",
|
|
],
|
|
snippets: [
|
|
"const hasProcessTimelineItems = hasTimelineProcessItems(rawTimelineItems)",
|
|
"const shouldAllowLegacyToolCallsProcess =",
|
|
"message.toolCalls",
|
|
"timeline 已有工具 item 时不应再把 legacy message.toolCalls 作为第二套过程源",
|
|
"无 timeline 时应继续允许 legacy message.toolCalls 作为兼容过程源",
|
|
"turn_summary",
|
|
"timeline 过程项未生成 tool_use part 时仍应禁用 legacy message.toolCalls",
|
|
],
|
|
normalizedSnippets: [
|
|
'constshouldAllowLegacyToolCallsProcess=message.role==="assistant"&&includeInlineProcessFlow&&!hasProcessTimelineItems;',
|
|
"constconversationToolCalls=shouldAllowLegacyToolCallsProcess?message.toolCalls:undefined;",
|
|
"preserveToolUseParts:!hasProcessTimelineItems,",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent stream handler tests canonical Item terminal ownership",
|
|
file: "src/components/agent/chat/hooks/agentStreamRuntimeHandler.unit.test.ts",
|
|
snippets: [
|
|
"item_completed 只更新 canonical ThreadItem,不再改写 legacy Message 工具卡",
|
|
'type: "item_completed"',
|
|
'type: "tool_call"',
|
|
'source: "item_lifecycle"',
|
|
"getThreadItems: () => threadItems",
|
|
'status: "completed"',
|
|
'output: "权威评测摘要"',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent chat passes active stream event into runtime sync",
|
|
file: "src/components/agent/chat/hooks/useAgentChat.ts",
|
|
snippets: [
|
|
"const currentStreamingEventNameRef = useRef<string | null>(null)",
|
|
"currentTurnEventName: stream.activeStreamEventName",
|
|
"refreshSessionDetail: session.refreshSessionDetail",
|
|
"getThreadItems: session.getThreadItems",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer-safe App Server helper aliases artifact/read protocol types",
|
|
file: "src/lib/api/appServer.ts",
|
|
snippets: [
|
|
"METHOD_ARTIFACT_READ,",
|
|
"type ArtifactReadParams,",
|
|
"type ArtifactSummary,",
|
|
"type ArtifactReadResponse,",
|
|
"export const APP_SERVER_METHOD_ARTIFACT_READ = METHOD_ARTIFACT_READ;",
|
|
"export type AppServerArtifactReadParams = ArtifactReadParams;",
|
|
"export type AppServerArtifactSummary = ArtifactSummary;",
|
|
"export type AppServerArtifactReadResponse = ArtifactReadResponse;",
|
|
"async readArtifacts(",
|
|
"APP_SERVER_METHOD_ARTIFACT_READ",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime artifact client reads timeline content through App Server artifact/read",
|
|
file: "src/lib/api/agentRuntime/appServerArtifactClient.ts",
|
|
snippets: [
|
|
'Pick<AppServerClient, "readArtifacts">',
|
|
"appServerArtifactReadParamsFromTimelineItem",
|
|
"appServerArtifactReadParamsFromArtifactPreview",
|
|
"hasAgentRuntimeArtifactPreviewScope",
|
|
"readAgentRuntimeTimelineArtifactContent",
|
|
"readAgentRuntimeArtifactPreviewContent",
|
|
"appServerClient.readArtifacts(params)",
|
|
"includeContent: true",
|
|
"limit: 1",
|
|
"projectTimelineArtifactContentFromAppServerSummaries",
|
|
"projectArtifactPreviewContentFromAppServerSummaries",
|
|
'selected.contentStatus !== "available"',
|
|
"return null",
|
|
],
|
|
absentSnippets: [
|
|
"AGENT_RUNTIME_COMMANDS",
|
|
"invokeAgentRuntimeCommand",
|
|
"agent_runtime_",
|
|
"invokeMockOnly",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Agent Runtime artifact client tests lock artifact/read fail-closed behavior",
|
|
file: "src/lib/api/agentRuntime/appServerArtifactClient.test.ts",
|
|
snippets: [
|
|
"应从 timeline metadata 构造 artifact/read includeContent 请求",
|
|
"缺少 sessionId 时应 fail closed,不生成 App Server 请求",
|
|
"应从 Workbench artifact meta 构造 artifact/read includeContent 请求",
|
|
"Workbench artifact 缺少 sessionId 时应 fail closed,不进入 App Server",
|
|
"应通过 App Server artifact/read 读取 timeline artifact 正文",
|
|
"应通过 App Server artifact/read 读取 Workbench artifact preview 正文",
|
|
"App Server 未返回可用 content 时不伪造 artifact 正文",
|
|
"Workbench artifact preview 的 contentStatus 不可用时不伪造正文",
|
|
"hasAgentRuntimeArtifactPreviewScope",
|
|
"projectArtifactPreviewContentFromAppServerSummaries",
|
|
"readArtifacts: vi.fn().mockResolvedValue",
|
|
'artifactRef: "artifact-report"',
|
|
"includeContent: true",
|
|
'contentStatus: "available"',
|
|
'contentStatus: "unavailable"',
|
|
],
|
|
absentSnippets: ["agent_runtime_"],
|
|
},
|
|
{
|
|
name: "Renderer Artifact timeline card hydrates omitted content through App Server artifact client",
|
|
file: "src/components/agent/chat/components/AgentThreadTimelineArtifactCard.tsx",
|
|
snippets: [
|
|
"readAgentRuntimeTimelineArtifactContent",
|
|
"readTimelineArtifactContent = readAgentRuntimeTimelineArtifactContent",
|
|
"const resolveOpenTarget = async",
|
|
"const artifactContent = await readTimelineArtifactContent(item)",
|
|
"artifactContent?.content.trim()",
|
|
"void openTimelineTarget(",
|
|
"void readTimelineArtifactContent(item)",
|
|
],
|
|
absentSnippets: [
|
|
"AGENT_RUNTIME_COMMANDS",
|
|
"invokeAgentRuntimeCommand",
|
|
"agent_runtime_",
|
|
"invokeMockOnly",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer Artifact timeline card tests lock App Server hydration on omitted content",
|
|
file: "src/components/agent/chat/components/AgentThreadTimelineArtifactCard.test.tsx",
|
|
snippets: [
|
|
"首屏省略 artifact 正文时点击打开应通过 App Server artifact/read 补齐内容",
|
|
"readTimelineArtifactContent",
|
|
'session_id: "session-1"',
|
|
'artifact_ref: "artifact-document:demo"',
|
|
"这里是 App Server 返回的完整正文",
|
|
"expect(readTimelineArtifactContent).toHaveBeenCalledWith",
|
|
"expect(onOpenArtifactFromTimeline).toHaveBeenCalledWith",
|
|
],
|
|
absentSnippets: ["agent_runtime_"],
|
|
},
|
|
{
|
|
name: "Renderer-safe App Server excludes Lime-only evidence/export",
|
|
files: rendererAppServerSplitSourceFiles,
|
|
snippets: ["APP_SERVER_METHOD_ARTIFACT_READ"],
|
|
absentSnippets: [
|
|
"METHOD_EVIDENCE_EXPORT",
|
|
"APP_SERVER_METHOD_EVIDENCE_EXPORT",
|
|
"EvidenceExportParams",
|
|
"EvidenceExportResponse",
|
|
"EvidencePackSummary",
|
|
"EvidencePackArtifact",
|
|
"exportEvidence(",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer-safe App Server tests lock capability/list session scope",
|
|
file: "src/lib/api/appServer.test.ts",
|
|
snippets: [
|
|
"APP_SERVER_METHOD_CAPABILITY_LIST",
|
|
"listCapabilities 应透传 sessionId scope",
|
|
'sessionId: "session-1"',
|
|
"method: APP_SERVER_METHOD_CAPABILITY_LIST",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer-safe App Server tests lock action respond JSON-RPC path",
|
|
file: "src/lib/api/appServer.test.ts",
|
|
snippets: [
|
|
"APP_SERVER_METHOD_AGENT_SESSION_ACTION_RESPOND",
|
|
"respondAction 应通过 App Server JSON-RPC 响应 action.required",
|
|
"method: APP_SERVER_METHOD_AGENT_SESSION_ACTION_RESPOND",
|
|
'actionType: "tool_confirmation"',
|
|
'eventName: "agentSession/event/session-1"',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer-safe App Server tests lock artifact/read JSON-RPC path",
|
|
file: "src/lib/api/appServer.test.ts",
|
|
snippets: [
|
|
"APP_SERVER_METHOD_ARTIFACT_READ",
|
|
"readArtifacts 应通过 App Server JSON-RPC 读取 artifact summary/content",
|
|
"method: APP_SERVER_METHOD_ARTIFACT_READ",
|
|
'artifactRef: "artifact-report"',
|
|
"includeContent: true",
|
|
'expect(result.result.artifacts[0].content).toBe("# Report")',
|
|
'expect(result.result.artifacts[0].contentStatus).toBe("available")',
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer workspace artifact preview reads scoped content through App Server artifact/read",
|
|
file: "src/components/agent/chat/workspace/useWorkspaceArtifactPreviewActions.ts",
|
|
snippets: [
|
|
"hasAgentRuntimeArtifactPreviewScope",
|
|
"readAgentRuntimeArtifactPreviewContent",
|
|
"artifact?: Artifact",
|
|
"hasAgentRuntimeArtifactPreviewScope(artifact, normalizedPath)",
|
|
"const appServerContent = await readAgentRuntimeArtifactPreviewContent(",
|
|
"App Server artifact 内容不可用",
|
|
"handleHarnessLoadFilePreview(\n artifactPath,\n artifact,",
|
|
],
|
|
absentSnippets: [
|
|
"AppServerClient",
|
|
"readArtifacts(",
|
|
"new AppServerClient()",
|
|
"mockReadArtifacts",
|
|
"invokeMockOnly",
|
|
"invokeAgentRuntimeCommand",
|
|
"AGENT_RUNTIME_COMMANDS",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer workspace artifact preview tests lock App Server current path and fail-closed behavior",
|
|
file: "src/components/agent/chat/workspace/useWorkspaceArtifactPreviewActions.test.tsx",
|
|
snippets: [
|
|
"mockHasArtifactPreviewScope",
|
|
"mockReadArtifactPreviewContent",
|
|
"读取带 App Server scope 的 artifact 时应走 artifact/read current 主链",
|
|
"带 App Server scope 的 artifact 内容不可用时不应回退旧文件预览",
|
|
'sessionId: "session-1"',
|
|
'turnId: "turn-1"',
|
|
'artifactRef: "artifact-report"',
|
|
"expect(mockReadArtifactPreviewContent).toHaveBeenCalledWith",
|
|
'error: "App Server artifact 内容不可用"',
|
|
"expect(readFilePreviewSpy).not.toHaveBeenCalled()",
|
|
],
|
|
},
|
|
{
|
|
name: "Renderer artifact snapshot metadata carries App Server artifact/read scope",
|
|
file: "src/components/agent/chat/hooks/agentStreamEventProcessorAuxiliary.ts",
|
|
snippets: [
|
|
"activeSessionId,",
|
|
"sessionId: activeSessionId",
|
|
"artifactId: data.artifact.artifactId",
|
|
"artifactRef: data.artifact.artifactId || artifactPath",
|
|
'source: "artifact_snapshot"',
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript client exposes release manifest file helpers",
|
|
file: "packages/app-server-client/src/index.ts",
|
|
snippets: [
|
|
"export async function readReleaseManifest(",
|
|
"path: string,",
|
|
"Promise<AppServerReleaseManifest>",
|
|
"export async function resolveSidecarFromReleaseManifestFile(",
|
|
"await readReleaseManifest(manifestPath)",
|
|
"resolveSidecarFromReleaseManifest(",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript manifest file tests lock independent app sidecar resolution",
|
|
file: "packages/app-server-client/tests/client.test.mjs",
|
|
snippets: [
|
|
"readReleaseManifest",
|
|
"resolveSidecarFromReleaseManifestFile",
|
|
"resolves sidecar config from release manifest file",
|
|
"app-server.release.json",
|
|
'resourcesPath: "/app/resources"',
|
|
'binaryPathSource, "resources"',
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript client consumes Rust protocol schema manifest",
|
|
file: "packages/app-server-client/src/index.ts",
|
|
snippets: [
|
|
"DEFAULT_PROTOCOL_SCHEMA_MANIFEST_NAME",
|
|
"type AppServerProtocolSchemaManifest,",
|
|
"type AppServerMethodSpec,",
|
|
"type ProtocolSchemaGroup,",
|
|
'export * from "./protocol.js"',
|
|
'from "./protocol.js"',
|
|
"export async function readProtocolSchemaManifest(",
|
|
"export function assertCompatibleProtocolSchemaManifest(",
|
|
"manifest.protocolVersion !== expectedProtocolVersion",
|
|
"manifest.jsonRpc.version !== JSONRPC_VERSION",
|
|
"normalizeMethodSpecs(manifest.methods)",
|
|
"normalizeMethodSpecs(expectedMethods)",
|
|
"app-server schema method catalog mismatch",
|
|
"export function protocolSchemaFilePath(",
|
|
"export function listProtocolSchemaFiles(",
|
|
'(["jsonrpc", "v0", "v2"] as const).flatMap',
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript client tests lock checked-in Rust schema consumption",
|
|
file: "packages/app-server-client/tests/client.test.mjs",
|
|
snippets: [
|
|
"DEFAULT_PROTOCOL_SCHEMA_MANIFEST_NAME",
|
|
"readProtocolSchemaManifest",
|
|
"assertCompatibleProtocolSchemaManifest",
|
|
"defaultProtocolSchemaManifestPath",
|
|
"protocolSchemaFilePath",
|
|
"listProtocolSchemaFiles",
|
|
"reads and validates protocol schema manifest metadata",
|
|
"consumes checked-in Rust protocol schema manifest",
|
|
"AgentSessionTurnStartParams",
|
|
"ThreadStartParams",
|
|
"TurnStartParams",
|
|
"JsonRpcRequest",
|
|
"schema method catalog mismatch",
|
|
],
|
|
absentSnippets: ["EvidenceExportResponse", "evidence/export"],
|
|
},
|
|
{
|
|
name: "Rust daemon probes stdio sidecar readiness before handing it to hosts",
|
|
file: "lime-rs/crates/app-server-daemon/src/lib.rs",
|
|
snippets: [
|
|
"pub fn probe_readiness(",
|
|
"pub struct SidecarReadinessReport",
|
|
"pub enum SidecarReadinessError",
|
|
"pub fn probe_sidecar_readiness(",
|
|
"initialize_probe_request(client_version)",
|
|
"initialized_notification()",
|
|
"probe_info_from_initialize_response(&message)",
|
|
"write_jsonrpc_line(stdin, &initialize)",
|
|
"write_jsonrpc_line(stdin, &initialized)",
|
|
"drop(child.stdin.take())",
|
|
"wait_for_sidecar_exit(child, Duration::from_secs(2))",
|
|
"drain_child_stderr(child, &stderr_log_file)",
|
|
"if result.is_err()",
|
|
"readiness_probe_drains_stderr_when_sidecar_exits_before_initialize_response",
|
|
"cleanup_sidecar_child(&mut child)",
|
|
"readiness_probe_rejects_sha256_mismatch_before_process_start",
|
|
"readiness_probe_smokes_real_app_server_when_env_is_set",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust daemon sidecar launch config mirrors standalone backend options",
|
|
files: [
|
|
"lime-rs/crates/app-server-daemon/src/lib.rs",
|
|
"lime-rs/crates/app-server-daemon/src/backend.rs",
|
|
],
|
|
snippets: [
|
|
"pub enum SidecarBackendMode",
|
|
"External",
|
|
"Mock",
|
|
"Unavailable",
|
|
"pub backend_mode: SidecarBackendMode",
|
|
"pub backend_command: Option<String>",
|
|
"pub backend_args: Vec<String>",
|
|
"pub backend_timeout_ms: Option<u64>",
|
|
"pub app_policy_path: Option<PathBuf>",
|
|
'args.push("--backend".to_string())',
|
|
"args.push(self.backend_mode.as_str().to_string())",
|
|
'args.push("--backend-command".to_string())',
|
|
'args.push("--backend-arg".to_string())',
|
|
'args.push("--backend-timeout-ms".to_string())',
|
|
'args.push("--app-policy".to_string())',
|
|
"release_manifest_resolution_preserves_backend_launch_options",
|
|
"sidecar_args_follow_standalone_backend_cli",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust daemon settings persist external backend launch options",
|
|
file: "lime-rs/crates/app-server-daemon/src/settings.rs",
|
|
snippets: [
|
|
"pub backend_mode: Option<String>",
|
|
"pub backend_command: Option<String>",
|
|
"pub backend_args: Vec<String>",
|
|
"pub backend_timeout_ms: Option<u64>",
|
|
"pub app_policy_path: Option<PathBuf>",
|
|
'value["backendCommand"]',
|
|
'value["backendArgs"][0]',
|
|
'value["backendTimeoutMs"]',
|
|
"daemon_settings_round_trips_external_backend_launch_options",
|
|
"resources/app-server/backend/content-backend.mjs",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust daemon applies settings to sidecar launch resolution",
|
|
file: "lime-rs/crates/app-server-daemon/src/lib.rs",
|
|
snippets: [
|
|
"pub fn apply_daemon_settings(&mut self, settings: &DaemonSettings) -> Result<(), String>",
|
|
"pub fn with_daemon_settings(mut self, settings: &DaemonSettings) -> Result<Self, String>",
|
|
"pub fn with_daemon_state_paths(",
|
|
"let settings = DaemonSettings::load(&state_paths.settings_file)?",
|
|
"self.allow_env_override = settings.allow_env_override",
|
|
"self.resource_relative_path = settings.resource_relative_path.clone()",
|
|
"self.backend_mode = SidecarBackendMode::parse(backend_mode.trim())?",
|
|
"self.backend_command = settings.backend_command.clone()",
|
|
"self.backend_args = settings.backend_args.clone()",
|
|
"self.backend_timeout_ms = settings.backend_timeout_ms",
|
|
"self.app_policy_path = settings.app_policy_path.clone()",
|
|
"pub fn resolve_sidecar_from_release_manifest_path_with_daemon_state(",
|
|
"options.with_daemon_state_paths(state_paths)?",
|
|
"daemon_settings_apply_to_sidecar_binary_options_and_manifest_resolution",
|
|
"with_daemon_state_paths_loads_settings_file_into_manifest_resolution",
|
|
"with_daemon_state_paths_missing_settings_uses_default_resolution",
|
|
"daemon_settings_reject_unsupported_backend_mode_before_launch_resolution",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust daemon lifecycle keeps operation lock and pid backend explicit",
|
|
files: [
|
|
"lime-rs/crates/app-server-daemon/src/backend.rs",
|
|
"lime-rs/crates/app-server-daemon/src/lifecycle.rs",
|
|
],
|
|
snippets: [
|
|
"pub fn is_supported(self) -> bool",
|
|
"matches!(self, Self::Sidecar)",
|
|
"pub fn unsupported_reason(self) -> Option<&'static str>",
|
|
"pid backend is not supported until local socket lifecycle is enabled",
|
|
"pub struct OperationLock",
|
|
"File::options()",
|
|
".create_new(true)",
|
|
"OperationLockError::AlreadyLocked",
|
|
"impl Drop for OperationLock",
|
|
"fs::remove_file(&self.path)",
|
|
"pub fn acquire_operation_lock(",
|
|
"pid_backend_is_explicitly_unsupported_until_local_socket_lifecycle_exists",
|
|
"operation_lock_serializes_lifecycle_actions_and_releases_on_drop",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript client exposes sidecar lifecycle backoff",
|
|
file: "packages/app-server-client/src/index.ts",
|
|
snippets: [
|
|
"export type SidecarRestartPolicy = {",
|
|
"export class AppServerSidecarLifecycle",
|
|
"export function sidecarRestartDelayMs(",
|
|
"export function shouldRestartSidecar(",
|
|
"async #connectWithRetry(",
|
|
"onRestartScheduled?: (event: SidecarRestartScheduledEvent) => void",
|
|
"onRestarted?: (connected: ConnectedAppServerSidecar, attempt: number) => void",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript sidecar launch config supports standalone backend options",
|
|
file: "packages/app-server-client/src/index.ts",
|
|
snippets: [
|
|
"export const DEFAULT_STANDALONE_BACKEND_MODE",
|
|
'= "unavailable"',
|
|
'backendMode?: "external" | "runtime" | "mock" | "unavailable"',
|
|
"backendCommand?: string",
|
|
"backendArgs?: string[]",
|
|
"backendTimeoutMs?: number",
|
|
"appPolicyPath?: string",
|
|
'backendMode?: SidecarLaunchConfig["backendMode"]',
|
|
"backendCommand?: string",
|
|
"backendArgs?: string[]",
|
|
"backendTimeoutMs?: number",
|
|
'backendMode: SidecarLaunchConfig["backendMode"] = DEFAULT_STANDALONE_BACKEND_MODE',
|
|
"backendMode: DEFAULT_STANDALONE_BACKEND_MODE",
|
|
"config.backendMode ?? DEFAULT_STANDALONE_BACKEND_MODE",
|
|
'args.push("--backend-command", config.backendCommand)',
|
|
'args.push("--backend-arg", backendArg)',
|
|
'args.push("--backend-timeout-ms", String(config.backendTimeoutMs))',
|
|
'args.push("--app-policy", config.appPolicyPath)',
|
|
"backendMode: options.backendMode ?? DEFAULT_STANDALONE_BACKEND_MODE",
|
|
"backendCommand: options.backendCommand",
|
|
"backendArgs: options.backendArgs",
|
|
"backendTimeoutMs: options.backendTimeoutMs",
|
|
"appPolicyPath: options.appPolicyPath",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript sidecar launch tests lock unavailable mock and external args",
|
|
file: "packages/app-server-client/tests/client.test.mjs",
|
|
snippets: [
|
|
"DEFAULT_STANDALONE_BACKEND_MODE",
|
|
"uses agent-style stdio sidecar launch args",
|
|
"assert.equal(config.backendMode, DEFAULT_STANDALONE_BACKEND_MODE)",
|
|
'"--stdio"',
|
|
'"--backend"',
|
|
'"unavailable"',
|
|
'backendMode: "runtime"',
|
|
'"runtime"',
|
|
"policyConfig.appPolicyPath",
|
|
'"--app-policy"',
|
|
'"/tmp/content-studio.policy.json"',
|
|
'backendMode: "mock"',
|
|
'"mock"',
|
|
'backendMode: "external"',
|
|
'backendCommand: "/usr/local/bin/content-backend"',
|
|
'backendArgs: ["--workspace", "/tmp/content-studio", "--json"]',
|
|
"backendTimeoutMs: 30_000",
|
|
'"--backend-command"',
|
|
'"--backend-arg"',
|
|
'"--backend-timeout-ms"',
|
|
'"30000"',
|
|
'appPolicyPath: "/app/content-studio.policy.json"',
|
|
'backendArgs: ["--workspace", "/app/workspace"]',
|
|
"backendTimeoutMs: 45_000",
|
|
],
|
|
},
|
|
{
|
|
name: "Electron dev sidecars default to App Server runtime backend and only keep explicit external override",
|
|
files: [
|
|
"scripts/lib/electron-dev-sidecar.mjs",
|
|
"scripts/lib/electron-dev-sidecar.test.mjs",
|
|
"scripts/electron/run-dev.mjs",
|
|
],
|
|
snippets: [
|
|
"resolveDevAppServerBackendEnv",
|
|
'defaultMode = "runtime"',
|
|
"APP_SERVER_BACKEND_MODE: defaultMode",
|
|
"APP_SERVER_BACKEND_MODE: requestedMode",
|
|
'APP_SERVER_BACKEND_MODE: "external"',
|
|
"APP_SERVER_BACKEND_COMMAND",
|
|
"APP_SERVER_BACKEND_TIMEOUT_MS",
|
|
"默认 dev App Server backend 使用 App Server 内部 runtime",
|
|
"显式 unavailable 时 dev App Server backend 不接 external",
|
|
"调用 cargo build 成组构建 app-server 与 code-mode host",
|
|
],
|
|
absentSnippets: [
|
|
"resolveDevAppServerAgentBackendBinary",
|
|
"shouldUseDevAppServerExternalBackend",
|
|
"appServerAgentBackendBinaryName",
|
|
"localAppServerAgentBackendBinaryPath",
|
|
"app-server-agent-backend",
|
|
'APP_SERVER_BACKEND_MODE: "mock"',
|
|
'backendMode: "mock"',
|
|
],
|
|
},
|
|
{
|
|
name: "Windows test workflow builds both App Server sidecars with pinned Rust and shared linker inputs",
|
|
file: ".github/workflows/build-windows-test.yml",
|
|
snippets: [
|
|
"dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # 1.95.0",
|
|
"Configure Windows MSVC linker",
|
|
"./scripts/lib/windows-msvc-linker.ps1 -Target x86_64-pc-windows-msvc",
|
|
"Refresh sandboxed rusty_v8 artifacts",
|
|
"node scripts/lib/rusty-v8-artifacts.mjs --github-env",
|
|
"cargo clean --manifest-path lime-rs/Cargo.toml -p v8",
|
|
"code-mode-host sidecars",
|
|
],
|
|
},
|
|
{
|
|
name: "Windows quality links both App Server sidecar binaries with pinned Rust and shared inputs",
|
|
file: ".github/workflows/quality.yml",
|
|
snippets: [
|
|
"dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # 1.95.0",
|
|
"Configure Windows MSVC linker",
|
|
"./scripts/lib/windows-msvc-linker.ps1 -Target x86_64-pc-windows-msvc",
|
|
"Refresh sandboxed rusty_v8 artifacts",
|
|
"node scripts/lib/rusty-v8-artifacts.mjs --github-env",
|
|
"cargo clean --manifest-path lime-rs/Cargo.toml -p v8",
|
|
"Prepare sherpa-onnx runtime",
|
|
"node scripts/prepare-sherpa-onnx-runtime.mjs --target x86_64-pc-windows-msvc",
|
|
"Build Windows app-server, code-mode-host, and sandbox sidecars",
|
|
"cargo build --manifest-path lime-rs/Cargo.toml --target x86_64-pc-windows-msvc -p app-server --bin app-server -p tool-runtime --bin code-mode-host --bin windows-sandbox-setup --bin windows-sandbox-runner",
|
|
],
|
|
absentSnippets: [
|
|
"cargo check --manifest-path lime-rs/Cargo.toml -p app-server --bin app-server -p tool-runtime --bin code-mode-host",
|
|
],
|
|
},
|
|
{
|
|
name: "Release workflow uses pinned Rust and shared Windows linker inputs",
|
|
file: ".github/workflows/release.yml",
|
|
snippets: [
|
|
"dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # 1.95.0",
|
|
"Configure Windows MSVC linker",
|
|
"./scripts/lib/windows-msvc-linker.ps1 -Target x86_64-pc-windows-msvc",
|
|
"Refresh sandboxed rusty_v8 artifacts",
|
|
"node scripts/lib/rusty-v8-artifacts.mjs --github-env",
|
|
"cargo clean --manifest-path lime-rs/Cargo.toml -p v8",
|
|
],
|
|
absentSnippets: ["dtolnay/rust-toolchain@stable"],
|
|
},
|
|
{
|
|
name: "Existing GitHub release is retargeted when a stable tag is rebuilt",
|
|
file: ".github/workflows/release.yml",
|
|
snippets: [
|
|
'TARGET_REF="${{ github.event.inputs.source_ref || github.sha }}"',
|
|
'gh release edit "$TAG"',
|
|
'--target "$TARGET_REF"',
|
|
'--notes-file "$NOTES_FILE"',
|
|
],
|
|
},
|
|
{
|
|
name: "Rust Full configures sandboxed V8 artifacts before testing the workspace",
|
|
file: ".github/workflows/quality.yml",
|
|
snippets: [
|
|
"quality-rust-full",
|
|
"Refresh sandboxed rusty_v8 artifacts",
|
|
"node scripts/lib/rusty-v8-artifacts.mjs --github-env",
|
|
"cargo clean --manifest-path lime-rs/Cargo.toml -p v8",
|
|
"Build standalone Code Mode host and Windows sandbox setup helper",
|
|
"cargo build --manifest-path lime-rs/Cargo.toml -p tool-runtime --bin code-mode-host --bin windows-sandbox-setup",
|
|
"npm run test:rust",
|
|
],
|
|
},
|
|
{
|
|
name: "GUI smoke refreshes sandboxed V8 artifacts after restoring the Rust cache",
|
|
file: ".github/workflows/quality.yml",
|
|
snippets: [
|
|
"quality-gui-smoke",
|
|
"Refresh sandboxed rusty_v8 artifacts",
|
|
"node scripts/lib/rusty-v8-artifacts.mjs --github-env",
|
|
"cargo clean --manifest-path lime-rs/Cargo.toml -p v8",
|
|
"npm run verify:gui-smoke -- --timeout-ms 1800000",
|
|
],
|
|
},
|
|
{
|
|
name: "Repository Rust toolchain stays pinned to the Windows V8 release toolchain",
|
|
file: "rust-toolchain.toml",
|
|
snippets: [
|
|
'channel = "1.95.0"',
|
|
'components = ["clippy", "rustfmt", "rust-src"]',
|
|
],
|
|
},
|
|
{
|
|
name: "Windows MSVC builds use the static CRT required by the sandbox V8 artifact",
|
|
file: "scripts/lib/rusty-v8-artifacts.mjs",
|
|
snippets: [
|
|
"CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUSTFLAGS",
|
|
'"-C target-feature=+crt-static"',
|
|
],
|
|
absentSnippets: ["/FORCE:MULTIPLE", "/NODEFAULTLIB"],
|
|
},
|
|
{
|
|
name: "Windows MSVC linker setup exports the complete SDK environment and native linker",
|
|
file: "scripts/lib/windows-msvc-linker.ps1",
|
|
snippets: [
|
|
"VsDevCmd.bat",
|
|
"-arch=x64 -host_arch=x64",
|
|
'"INCLUDE"',
|
|
'"LIB"',
|
|
'"LIBPATH"',
|
|
'"UCRTVersion"',
|
|
'"WindowsSdkDir"',
|
|
'throw "VsDevCmd.bat did not export $RequiredVariable"',
|
|
'"bin\\Hostx64\\x64\\link.exe"',
|
|
'"CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER=$Linker"',
|
|
],
|
|
absentSnippets: ["/FORCE:MULTIPLE", "/NODEFAULTLIB"],
|
|
},
|
|
{
|
|
name: "Rust changed-scope selection treats the root toolchain as workspace-wide",
|
|
file: "scripts/lib/rust-test-scope-core.mjs",
|
|
snippets: [
|
|
'relPath === "rust-toolchain.toml"',
|
|
'relPath === "rust-toolchain"',
|
|
'relPath === "lime-rs/rust-toolchain.toml"',
|
|
],
|
|
},
|
|
{
|
|
name: "Retired App Server agent backend crate stays deleted",
|
|
file: "lime-rs/Cargo.lock",
|
|
snippets: ['name = "app-server"'],
|
|
absentSnippets: ['name = "app-server-agent-backend"'],
|
|
},
|
|
{
|
|
name: "Electron App Server host preserves external backend env for resources manifest",
|
|
file: "electron/appServerHost.ts",
|
|
snippets: [
|
|
'resolveRuntimeBackendLaunchOptions("runtime")',
|
|
"...resolveRuntimeBackendLaunchOptions(defaultBackendMode)",
|
|
'const APP_SERVER_TURN_START_METHOD = "turn/start"',
|
|
"APP_SERVER_BACKEND_TIMEOUT_GRACE_MS",
|
|
"process.env.APP_SERVER_BACKEND_TIMEOUT_MS",
|
|
"process.env.APP_SERVER_BACKEND_COMMAND?.trim()",
|
|
"parseBackendArgs(process.env.APP_SERVER_BACKEND_ARGS)",
|
|
"parsePositiveInteger(",
|
|
'normalized === "mock"',
|
|
"throw new Error(",
|
|
],
|
|
normalizedSnippets: [
|
|
"resolveAppServerRequestTimeoutMs(proxiedMessage.message.method,request.timeoutMs,)",
|
|
],
|
|
absentSnippets: [
|
|
'backendMode: "mock"',
|
|
'backendMode: "unavailable",',
|
|
"#requestStreamingTurnStart",
|
|
"#readCanonicalTurnIdentity",
|
|
"#recentTurnStartedIdentity",
|
|
"APP_SERVER_STREAMING_TURN_ACK_GRACE_MS",
|
|
"APP_SERVER_STREAMING_TURN_IDENTITY_READ_RETRY_MS",
|
|
"streamingTurnStartAcceptedResponse",
|
|
"turnIdentityFromThreadRead",
|
|
"requestUntilFirstNotificationOrResponse",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript client exposes one-step packaged sidecar lifecycle",
|
|
file: "packages/app-server-client/src/index.ts",
|
|
snippets: [
|
|
"DEFAULT_RELEASE_MANIFEST_NAME",
|
|
'export * from "./protocol.js"',
|
|
'from "./protocol.js"',
|
|
"export type PackagedSidecarLifecycleOptions",
|
|
"export type StartedPackagedAppServerSidecar",
|
|
"export function defaultReleaseManifestPath(",
|
|
"export async function startPackagedAppServerSidecar(",
|
|
"allowEnvOverride: options.allowEnvOverride ?? false",
|
|
"const lifecycle = new AppServerSidecarLifecycle(",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript sidecar lifecycle tests lock crash restart behavior",
|
|
file: "packages/app-server-client/tests/client.test.mjs",
|
|
snippets: [
|
|
"calculates sidecar restart backoff policy",
|
|
"sidecar lifecycle restarts once after crash",
|
|
"sidecar lifecycle retries initial handshake failure",
|
|
"new AppServerSidecarLifecycle(",
|
|
"restartPolicy: {",
|
|
"onRestartScheduled(event)",
|
|
"onRestarted(connected, attempt)",
|
|
"onRestartFailed(event)",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript packaged lifecycle tests lock resources manifest entrypoint",
|
|
file: "packages/app-server-client/tests/client.test.mjs",
|
|
snippets: [
|
|
"starts packaged sidecar lifecycle from resources manifest",
|
|
"DEFAULT_RELEASE_MANIFEST_NAME",
|
|
"defaultReleaseManifestPath(resourcesPath)",
|
|
"startPackagedAppServerSidecar(",
|
|
'binaryPathSource, "resources"',
|
|
"initialized-packaged",
|
|
],
|
|
},
|
|
{
|
|
name: "Sidecar lifecycle smoke verifies packaged manifest flow and unavailable backend fail-closed behavior",
|
|
file: "scripts/app-server/sidecar-lifecycle-smoke.mjs",
|
|
snippets: [
|
|
"startPackagedAppServerSidecar",
|
|
"defaultReleaseManifestPath",
|
|
"resourcesPath",
|
|
'dataDir: path.join(tempDir, "data")',
|
|
'backendMode: "unavailable"',
|
|
"connection.listCapabilities",
|
|
"connection.startSession",
|
|
"connection.startTurn",
|
|
"expectStartTurnFailClosed",
|
|
"standalone app-server backend is not configured",
|
|
"backend=unavailable",
|
|
"turn=fail-closed",
|
|
"[smoke:app-server-sidecar-lifecycle] ok",
|
|
],
|
|
absentSnippets: [
|
|
"AppServerAgentEventRouter",
|
|
"const idleNotificationPromise = connection.nextNotification(5_000)",
|
|
"projectedEvents.length",
|
|
"turn.accepted",
|
|
'backendMode: "mock"',
|
|
],
|
|
},
|
|
{
|
|
name: "Root scripts expose sidecar lifecycle smoke",
|
|
file: "package.json",
|
|
snippets: [
|
|
'"smoke:app-server-sidecar-lifecycle"',
|
|
"node scripts/app-server/sidecar-lifecycle-smoke.mjs",
|
|
],
|
|
},
|
|
{
|
|
name: "Packaged sidecar failure smoke drains streamed failure through read model",
|
|
file: "scripts/app-server/packaged-external-backend-failure-smoke.mjs",
|
|
snippets: [
|
|
"[smoke:app-server-packaged-external-backend-failure] ok",
|
|
"startPackagedAppServerSidecar",
|
|
'backendMode: "external"',
|
|
"backendCommand: process.execPath",
|
|
"backendArgs: [backendPath]",
|
|
'dataDir: path.join(tempDir, "data")',
|
|
"copyElectronAppServerRuntimeLibraries",
|
|
"writeFailingExternalBackend(backendPath)",
|
|
"packaged external backend crashed after partial output",
|
|
'historyMode: "paginated"',
|
|
'model: "fixture-model"',
|
|
'modelProvider: "fixture-provider"',
|
|
"collectRuntimeNotificationsUntilFailure(",
|
|
"connection.nextNotification(remainingMs)",
|
|
'notification.method === "item/agentMessage/delta"',
|
|
'notification.method === "turn/completed"',
|
|
"const clientFailure = assertDirectFailureNotifications(",
|
|
"connection.readThread",
|
|
"{ threadId, includeTurns: true }",
|
|
"readResult.result.thread.turns",
|
|
'assertEqual(readTurns.length, 1, "read failed turn count")',
|
|
'assertEqual(readTurn.status, "failed", "read failed turn status")',
|
|
"read failed turn ${turnId} is missing completedAt",
|
|
'clientNotifications=${clientNotifications.map((notification) => notification.method).join(",")}',
|
|
"readTurnStatus=${readTurn.status}",
|
|
],
|
|
absentSnippets: [
|
|
'backendMode: "mock"',
|
|
"AppServerRequestError",
|
|
"METHOD_AGENT_SESSION_EVENT",
|
|
"connection.readSession",
|
|
],
|
|
},
|
|
{
|
|
name: "Root package gate runs packaged external backend failure smoke",
|
|
file: "package.json",
|
|
snippets: [
|
|
'"smoke:app-server-packaged-external-backend-failure"',
|
|
"scripts/app-server/packaged-external-backend-failure-smoke.mjs",
|
|
'npm --prefix \\"packages/app-server-client\\" run build',
|
|
'"electron:package:dir"',
|
|
"node scripts/electron/run-package-dir.mjs",
|
|
'"electron:verify:package"',
|
|
"scripts/electron/verify-package-resources.mjs && npm run smoke:app-server-packaged-external-backend-failure",
|
|
],
|
|
},
|
|
{
|
|
name: "Electron directory package uses Forge package",
|
|
file: "scripts/electron/run-package-dir.mjs",
|
|
snippets: [
|
|
'"electron-forge"',
|
|
'"package"',
|
|
'"--platform"',
|
|
'"--arch"',
|
|
'shell: process.platform === "win32"',
|
|
],
|
|
},
|
|
{
|
|
name: "Rust turn start params expose caller supplied turn_id",
|
|
files: rustProtocolFiles,
|
|
snippets: [
|
|
"pub struct AgentSessionTurnStartParams",
|
|
"pub turn_id: Option<String>",
|
|
"pub queue_if_busy: bool",
|
|
"pub skip_pre_submit_resume: bool",
|
|
],
|
|
},
|
|
{
|
|
name: "RuntimeCore keeps one active turn while App Server turn/start steers parallel input",
|
|
files: [
|
|
"lime-rs/crates/app-server-protocol/src/jsonrpc_lite.rs",
|
|
"lime-rs/crates/app-server/src/runtime.rs",
|
|
"lime-rs/crates/app-server/src/runtime/error.rs",
|
|
"lime-rs/crates/app-server/src/runtime/turn_execution.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tests/queue.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tests/sessions.rs",
|
|
"lime-rs/crates/app-server/src/lib.rs",
|
|
],
|
|
snippets: [
|
|
"pub const TURN_ALREADY_ACTIVE",
|
|
"TurnAlreadyActive",
|
|
"turn already active",
|
|
"second_active_turn_without_queue_fails_closed",
|
|
"turn_start_steers_parallel_input_into_active_turn",
|
|
"steer_input_event_payload",
|
|
"steer-client-parallel-1",
|
|
],
|
|
},
|
|
{
|
|
name: "Rust runtime options expose Turn envelope and typed RuntimeRequest",
|
|
files: rustProtocolFiles,
|
|
snippets: [
|
|
"pub struct RuntimeOptions",
|
|
"pub event_name: Option<String>",
|
|
"pub queued_turn_id: Option<String>",
|
|
"pub runtime_request: Option<RuntimeRequest>",
|
|
"pub expected_output: Option<serde_json::Value>",
|
|
"pub structured_output: Option<StructuredOutputContract>",
|
|
"pub output_schema: Option<serde_json::Value>",
|
|
"pub struct RuntimeRequest",
|
|
"pub provider_preference: Option<String>",
|
|
"pub model_preference: Option<String>",
|
|
"pub metadata: Option<serde_json::Value>",
|
|
],
|
|
absentSnippets: ["pub host_options: Option<serde_json::Value>"],
|
|
},
|
|
{
|
|
name: "TypeScript turn start params mirror Rust wire fields",
|
|
file: "packages/app-server-client/src/protocol.ts",
|
|
snippets: [
|
|
"export interface TurnStartParams {",
|
|
"threadId: string",
|
|
"input: UserInput[]",
|
|
"clientUserMessageId?: null | string",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript client exposes canonical v2 thread resume only",
|
|
files: [
|
|
"packages/app-server-client/src/index.ts",
|
|
"packages/app-server-client/src/protocol.ts",
|
|
],
|
|
snippets: [
|
|
"resumeThread(params: protocol.ThreadResumeParams)",
|
|
'name: "resumeThread"',
|
|
"method: protocol.METHOD_THREAD_RESUME",
|
|
"params: protocol.ThreadResumeParams",
|
|
"AppServerRequestResult<protocol.ThreadResumeResponse>",
|
|
'export const METHOD_THREAD_RESUME = "thread/resume"',
|
|
],
|
|
absentSnippets: [
|
|
"resumeAgentSessionThread",
|
|
"resumeAgentRuntimeThread",
|
|
"AgentSessionThreadResumeParams",
|
|
"AgentSessionThreadResumeResponse",
|
|
"RuntimeResumeContract",
|
|
"RuntimeResumeActionDecision",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript request builder test locks canonical thread resume shape",
|
|
file: "packages/app-server-client/tests/client.test.mjs",
|
|
snippets: [
|
|
"const resume = client.resumeThread({",
|
|
'threadId: "thread_1"',
|
|
"excludeTurns: true",
|
|
"initialTurnsPage: {",
|
|
"assert.equal(resume.method, METHOD_THREAD_RESUME)",
|
|
"assert.deepEqual(resume.params, {",
|
|
],
|
|
absentSnippets: [
|
|
"resumeAgentSessionThread",
|
|
"RuntimeResumeContract",
|
|
'sessionId: "sess_1",\n resumeContract:',
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript runtime options mirror Rust wire fields",
|
|
file: "packages/app-server-client/src/protocol.ts",
|
|
snippets: [
|
|
"export type RuntimeOptions = {",
|
|
"eventName?: string",
|
|
"queuedTurnId?: string",
|
|
"runtimeRequest?: RuntimeRequest",
|
|
"expectedOutput?: unknown",
|
|
"structuredOutput?: StructuredOutputContract",
|
|
"outputSchema?: unknown",
|
|
],
|
|
absentSnippets: ["hostOptions?: unknown"],
|
|
},
|
|
{
|
|
name: "TypeScript request builder test locks caller supplied turnId",
|
|
file: "packages/app-server-client/tests/client.test.mjs",
|
|
snippets: [
|
|
'threadId: "thread_external"',
|
|
'assert.equal(turn.params.threadId, "thread_external")',
|
|
'assert.deepEqual(turn.params.input, [{ type: "text", text: "draft" }])',
|
|
'assert.equal(turn.params.model, "gpt-5-codex")',
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript client exposes direct lifecycle projection router",
|
|
file: "packages/app-server-client/src/index.ts",
|
|
snippets: [
|
|
"agentRuntimeLifecycleNotification",
|
|
'export * from "./protocol.js"',
|
|
'from "./protocol.js"',
|
|
"export class AppServerAgentEventRouter",
|
|
"async dispatch(message: JsonRpcMessage): Promise<boolean>",
|
|
],
|
|
absentSnippets: ["AgentRuntimeEventListener", "subscribeEvents("],
|
|
},
|
|
{
|
|
name: "TypeScript event router tests lock direct lifecycle projection shape",
|
|
file: "packages/app-server-client/tests/client.test.mjs",
|
|
snippets: [
|
|
"AppServerAgentEventRouter",
|
|
"agentRuntimeLifecycleNotification(notification)",
|
|
"routes direct lifecycle notifications without wrapper projection",
|
|
"connection buffers request responses read by idle notification loop",
|
|
"assert.equal(await router.dispatch(notification), true)",
|
|
"assert.deepEqual(lifecycleRouted, [",
|
|
],
|
|
},
|
|
{
|
|
name: "TypeScript README documents independent app event projection",
|
|
file: "packages/app-server-client/README.md",
|
|
snippets: [
|
|
"AppServerAgentEventRouter",
|
|
'mainWindow.webContents.send("agent:lifecycle", notification)',
|
|
"await eventRouter.dispatch(await connection.nextNotification())",
|
|
"project events into their own renderer state",
|
|
],
|
|
},
|
|
{
|
|
name: "Runtime client readThread stays on canonical thread/read",
|
|
files: [
|
|
"packages/app-server-client/src/agent-runtime.ts",
|
|
"packages/agent-runtime-client/src/runtimeClient.ts",
|
|
"packages/agent-runtime-client/src/sessionGateway.ts",
|
|
],
|
|
snippets: ["connection.readThread", "gateway.readThread"],
|
|
absentSnippets: ["readSession", '"thread/read"'],
|
|
},
|
|
{
|
|
name: "Runtime client root exports canonical thread read types only",
|
|
file: "packages/agent-runtime-client/src/index.ts",
|
|
snippets: ["type ThreadReadParams", "type ThreadReadResponse"],
|
|
absentSnippets: ["AgentSessionReadParams", "AgentSessionReadResponse"],
|
|
},
|
|
{
|
|
name: "Standard runtime client excludes Lime-only evidence/export",
|
|
files: [
|
|
"packages/agent-runtime-client/src/index.ts",
|
|
"packages/agent-runtime-client/src/runtimeClient.ts",
|
|
"packages/agent-runtime-client/src/sessionGateway.ts",
|
|
],
|
|
snippets: ["readThread"],
|
|
absentSnippets: [
|
|
"EvidenceExportParams",
|
|
"EvidenceExportResponse",
|
|
"exportEvidence",
|
|
"evidence/export",
|
|
],
|
|
},
|
|
];
|
|
|
|
const failures = [];
|
|
|
|
for (const check of checks) {
|
|
const files = expandContractFiles(check.files ?? [check.file]);
|
|
const location = files.join(", ");
|
|
const existingFiles = files.filter((file) =>
|
|
fs.existsSync(path.join(repoRoot, file)),
|
|
);
|
|
if (check.allowMissingFiles && existingFiles.length === 0) {
|
|
continue;
|
|
}
|
|
const missingFiles = files.filter((file) => !existingFiles.includes(file));
|
|
if (missingFiles.length > 0 && !check.allowMissingFiles) {
|
|
failures.push(
|
|
`${check.name}: missing file(s) ${missingFiles.join(", ")} in ${location}`,
|
|
);
|
|
continue;
|
|
}
|
|
const content = existingFiles
|
|
.map((file) => fs.readFileSync(path.join(repoRoot, file), "utf8"))
|
|
.join("\n");
|
|
const requiredContent = requiredContractContent(existingFiles, content);
|
|
for (const snippet of check.snippets) {
|
|
if (!contractContentIncludes(requiredContent, snippet)) {
|
|
failures.push(
|
|
`${check.name}: missing ${JSON.stringify(snippet)} in ${location}`,
|
|
);
|
|
}
|
|
}
|
|
const normalizedContent = normalizeContractSnippet(requiredContent);
|
|
for (const snippet of check.normalizedSnippets ?? []) {
|
|
if (!normalizedContent.includes(normalizeContractSnippet(snippet))) {
|
|
failures.push(
|
|
`${check.name}: missing normalized ${JSON.stringify(snippet)} in ${location}`,
|
|
);
|
|
}
|
|
}
|
|
for (const snippet of check.absentSnippets ?? []) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`${check.name}: forbidden ${JSON.stringify(snippet)} in ${location}`,
|
|
);
|
|
}
|
|
}
|
|
let orderedSearchOffset = 0;
|
|
for (const snippet of check.orderedSnippets ?? []) {
|
|
const foundIndex = content.indexOf(snippet, orderedSearchOffset);
|
|
if (foundIndex < 0) {
|
|
failures.push(
|
|
`${check.name}: ordered snippet ${JSON.stringify(snippet)} missing after offset ${orderedSearchOffset} in ${location}`,
|
|
);
|
|
break;
|
|
}
|
|
orderedSearchOffset = foundIndex + snippet.length;
|
|
}
|
|
}
|
|
|
|
checkRetiredExecutionProcessSurface();
|
|
checkRetiredFileSystemSurface();
|
|
checkRetiredAgentRuntimeSessionFacadeSurface();
|
|
checkAgentRuntimeThinGatewayContracts();
|
|
checkRetiredPluginRuntimeRendererFacade();
|
|
checkRetiredAgentRuntimeMockFiles();
|
|
checkRetiredAgentRuntimeCommandManifestFiles();
|
|
checkRetiredAgentRuntimeAdapterFiles();
|
|
checkRetiredAgentSessionUpdateSurface();
|
|
checkRetiredRendererProjectionFiles();
|
|
checkRetiredAgentStreamToolMessageSynthesisSurface();
|
|
checkRetiredRendererQueuedTurnProjectionSurface();
|
|
checkRetiredRendererQueuedTurnSecondaryProjectionSurface();
|
|
checkRetiredAgentUiResumeContractFiles();
|
|
checkRetiredAgentRuntimeLegacyQueueSurface();
|
|
checkRetiredSkillExecutionSurfaceFiles();
|
|
checkRetiredAgentRuntimeToolInventoryMockFiles();
|
|
checkRetiredAgentRuntimeEvidenceExportFacadeSurface();
|
|
checkRetiredAgentRuntimeThreadReadFacadeSurface();
|
|
checkRetiredAgentRuntimeSubmitTurnFacadeSurface();
|
|
checkRetiredAgentRuntimeInterruptTurnFacadeSurface();
|
|
checkRetiredAgentRuntimeRespondActionFacadeSurface();
|
|
checkRendererQueuedTurnWriteSurface();
|
|
checkRetiredPublicQueuedTurnSurface();
|
|
checkActiveAipromptsDoNotPromoteRetiredAgentRuntimeCommands();
|
|
checkScriptsDoNotCallRetiredAgentRuntimeCommands();
|
|
checkMcpRuntimeCurrentContracts({ repoRoot, failures });
|
|
checkWorkspaceRightSurfaceCurrentContracts({ repoRoot, failures });
|
|
checkKnowledgeBuilderRuntimeCurrentContracts();
|
|
checkRetiredAppServerAgentBackendCrate();
|
|
checkRetiredRuntimeCoreMapperSurface();
|
|
checkRetiredAgentRuntimeClientShells();
|
|
checkRetiredToolWireSurface();
|
|
checkOrchestratorHostBoundary();
|
|
checkCanonicalRendererSequenceGate();
|
|
checkAgentUiPackageCanonicalNaming();
|
|
|
|
if (failures.length > 0) {
|
|
console.error("[app-server-client-contract] failed");
|
|
for (const failure of failures) {
|
|
console.error(`- ${failure}`);
|
|
}
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log(`[app-server-client-contract] ok (${checks.length + 35} checks)`);
|
|
|
|
function checkAgentUiPackageCanonicalNaming() {
|
|
const packageManifestFiles = fs
|
|
.readdirSync(path.join(repoRoot, "packages"), { withFileTypes: true })
|
|
.filter((entry) => entry.isDirectory())
|
|
.map((entry) => `packages/${entry.name}/package.json`)
|
|
.filter((relativePath) => fs.existsSync(path.join(repoRoot, relativePath)));
|
|
|
|
const files = [
|
|
...agentUiPackageNamingGuardFiles.filter((relativePath) =>
|
|
fs.existsSync(path.join(repoRoot, relativePath)),
|
|
),
|
|
...packageManifestFiles,
|
|
];
|
|
const contentByFile = new Map(
|
|
files.map((relativePath) => [
|
|
relativePath,
|
|
fs.readFileSync(path.join(repoRoot, relativePath), "utf8"),
|
|
]),
|
|
);
|
|
|
|
const combinedContent = Array.from(contentByFile.values()).join("\n");
|
|
for (const packageName of canonicalAgentUiPackages) {
|
|
if (!combinedContent.includes(packageName)) {
|
|
failures.push(
|
|
`Agent UI package canonical naming: missing canonical package ${packageName}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
for (const [relativePath, content] of contentByFile.entries()) {
|
|
for (const packageName of retiredAgentUiPackageNames) {
|
|
if (content.includes(packageName)) {
|
|
failures.push(
|
|
`Agent UI package canonical naming: ${relativePath} must not reference retired package name ${packageName}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkKnowledgeBuilderRuntimeCurrentContracts() {
|
|
const currentFiles = [
|
|
"lime-rs/crates/app-server/src/runtime.rs",
|
|
"lime-rs/crates/app-server/src/local_data_source.rs",
|
|
"lime-rs/crates/app-server/src/knowledge_builder_runtime.rs",
|
|
];
|
|
const content = currentFiles
|
|
.map((file) => fs.readFileSync(path.join(repoRoot, file), "utf8"))
|
|
.join("\n");
|
|
const forbidden = [
|
|
"builderRuntime is not available in App Server current path",
|
|
"builder_runtime_requested(",
|
|
"knowledge_cmd",
|
|
"execute_knowledge_builder_skill",
|
|
];
|
|
for (const snippet of forbidden) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`Knowledge builderRuntime current contract: forbidden ${JSON.stringify(
|
|
snippet,
|
|
)} in ${currentFiles.join(", ")}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAppServerAgentBackendCrate() {
|
|
const retiredCratePath = "lime-rs/crates/app-server-agent-backend";
|
|
if (fs.existsSync(path.join(repoRoot, retiredCratePath))) {
|
|
failures.push(
|
|
`retired App Server agent backend crate must stay deleted: ${retiredCratePath}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
function checkRetiredRuntimeCoreMapperSurface() {
|
|
const retiredPaths = [
|
|
"lime-rs/crates/runtime-core/src/llm_protocol/mapper",
|
|
"lime-rs/crates/runtime-core/src/llm_protocol/types.rs",
|
|
"lime-rs/crates/runtime-core/src/llm_protocol/events.rs",
|
|
"lime-rs/crates/runtime-core/src/llm_protocol/tests.rs",
|
|
"lime-rs/crates/model-provider/src/lowering/anthropic_messages.rs",
|
|
"lime-rs/crates/model-provider/src/lowering/gemini.rs",
|
|
"lime-rs/crates/model-provider/src/lowering/ollama_chat.rs",
|
|
"lime-rs/crates/model-provider/src/lowering/openai_chat.rs",
|
|
"lime-rs/crates/model-provider/src/lowering/openai_responses.rs",
|
|
];
|
|
for (const relativePath of retiredPaths) {
|
|
if (fs.existsSync(path.join(repoRoot, relativePath))) {
|
|
failures.push(
|
|
`retired provider dual-algebra path must stay deleted: ${relativePath}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
const protocolFiles = [
|
|
"lime-rs/crates/runtime-core/src/llm_protocol.rs",
|
|
"lime-rs/crates/runtime-core/src/lib.rs",
|
|
];
|
|
for (const relativePath of protocolFiles) {
|
|
const content = fs.readFileSync(path.join(repoRoot, relativePath), "utf8");
|
|
for (const snippet of [
|
|
"mod mapper",
|
|
"pub use mapper",
|
|
"build_provider_wire_request",
|
|
"runtime_event_from_llm_event",
|
|
"ProviderWireRequest",
|
|
"LlmRuntimeEvent",
|
|
]) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired runtime-core mapper export must stay absent: ${relativePath} contains ${JSON.stringify(snippet)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
const currentOllamaProtocolFiles = [
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/model.rs",
|
|
"lime-rs/crates/runtime-core/src/model_route.rs",
|
|
"lime-rs/crates/model-provider/src/runtime_provider.rs",
|
|
"lime-rs/crates/agent/src/provider_configuration.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/model_route_contract.rs",
|
|
"lime-rs/crates/app-server/src/runtime_backend/model_routing.rs",
|
|
];
|
|
for (const relativePath of currentOllamaProtocolFiles) {
|
|
const content = fs.readFileSync(path.join(repoRoot, relativePath), "utf8");
|
|
for (const snippet of ["OllamaChat", "ollama_chat"]) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired Ollama chat protocol must stay absent: ${relativePath} contains ${JSON.stringify(snippet)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
const loweringRoot = path.join(
|
|
repoRoot,
|
|
"lime-rs/crates/model-provider/src/lowering",
|
|
);
|
|
for (const relativePath of walkSourceFiles(loweringRoot)) {
|
|
if (!relativePath.endsWith(".rs")) {
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(path.join(repoRoot, relativePath), "utf8");
|
|
for (const snippet of [
|
|
"LlmRequest",
|
|
"ProviderWireRequest",
|
|
"build_provider_wire_request",
|
|
"build_responses_image_generation_wire_request",
|
|
]) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired provider dual algebra must stay absent: ${relativePath} contains ${JSON.stringify(snippet)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredToolWireSurface() {
|
|
const retiredPaths = [
|
|
"lime-rs/crates/agent/src/agent_tools/workspace_patch_runtime_adapter.rs",
|
|
"lime-rs/crates/agent/src/agent_tools/tool_lifecycle.rs",
|
|
"lime-rs/crates/agent/src/agent_tools/tool_orchestrator.rs",
|
|
"lime-rs/crates/tool-runtime/src/tool_batch.rs",
|
|
"lime-rs/crates/agent/src/tool_output_truncation.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tests/external_events/actions.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tests/external_events/owner_terminal.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tests/external_events/tool_lifecycle.rs",
|
|
"lime-rs/crates/app-server/src/backend_event.rs",
|
|
"lime-rs/crates/tool-runtime/src/collab_agent.rs",
|
|
"lime-rs/crates/tool-runtime/src/collab_agent/execution.rs",
|
|
"lime-rs/crates/tool-runtime/src/collab_agent/execution_tests.rs",
|
|
"lime-rs/crates/tool-runtime/src/collab_agent/projection.rs",
|
|
"lime-rs/crates/tool-runtime/src/collab_agent/tests.rs",
|
|
"lime-rs/crates/tool-runtime/src/collab_agent/validation.rs",
|
|
];
|
|
for (const relativePath of retiredPaths) {
|
|
if (fs.existsSync(path.join(repoRoot, relativePath))) {
|
|
failures.push(`retired raw tool wire must stay deleted: ${relativePath}`);
|
|
}
|
|
}
|
|
|
|
for (const relativePath of [
|
|
"lime-rs/crates/app-server/src/runtime/event_store.rs",
|
|
"lime-rs/crates/app-server/src/runtime/tests/external_events/canonical_tool_items.rs",
|
|
]) {
|
|
const content = fs.readFileSync(path.join(repoRoot, relativePath), "utf8");
|
|
if (!content.includes('"tool_end"')) {
|
|
failures.push(
|
|
`retired tool_end alias must stay fail-closed: ${relativePath} has no explicit guard`,
|
|
);
|
|
}
|
|
}
|
|
|
|
const currentFiles = [
|
|
{
|
|
path: "lime-rs/crates/app-server/src/runtime/event_store.rs",
|
|
forbidden: [
|
|
'"tool.started" =>',
|
|
'"tool.result" =>',
|
|
'"tool.failed" =>',
|
|
"is_imported_tool_wire_payload",
|
|
],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/app-server/src/lib.rs",
|
|
forbidden: ["mod backend_event;", "runtime_event_type_from_backend_type"],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/core/src/agent/types.rs",
|
|
forbidden: [
|
|
"pub enum StreamEvent {",
|
|
"pub struct ToolExecutionResult {",
|
|
"pub struct StreamResult {",
|
|
],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/app-server/src/runtime/projection_item_events.rs",
|
|
forbidden: ['"tool.started"', '"tool.result"', '"tool.failed"'],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/app-server/src/runtime/tests/external_events/canonical_tool_items.rs",
|
|
forbidden: [
|
|
"append_external_runtime_events_allows_explicit_import_tool_compat",
|
|
],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/app-server/src/runtime_backend/tool_events.rs",
|
|
forbidden: ['"tool.args"', "runtime_tool_args_event_payload"],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/app-server/src/runtime/tool_item_projection.rs",
|
|
forbidden: [
|
|
"LegacyToolEvent",
|
|
"legacy_tool_event_from_event",
|
|
"apply_legacy_tool_event",
|
|
"find_legacy_match_for_current",
|
|
"find_legacy_index",
|
|
"from_legacy_event",
|
|
"merge_legacy_event",
|
|
"has_current_item",
|
|
'"tool.started"',
|
|
'"tool.result"',
|
|
'"tool.failed"',
|
|
],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/app-server/src/runtime/tool_item_projection/extract.rs",
|
|
forbidden: [
|
|
"LegacyToolEvent",
|
|
"legacy_tool_event_from_event",
|
|
"legacy_tool_id",
|
|
"is_imported_legacy_tool_event",
|
|
"normalize_tool_name_for_id",
|
|
'"tool.started"',
|
|
'"tool.result"',
|
|
'"tool.failed"',
|
|
],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/app-server/src/runtime/output_refs.rs",
|
|
forbidden: [
|
|
"largest_legacy_tool_output",
|
|
"nested_result_output",
|
|
"nested_runtime_event_result_output",
|
|
"truncate_result_output_field",
|
|
"truncate_runtime_event_result_output_field",
|
|
],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/app-server/src/runtime/thread_item_projection.rs",
|
|
forbidden: ['"tool.started"', '"tool.result"', '"tool.failed"'],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/app-server/src/runtime/tests/coding_events/output_snapshots.rs",
|
|
forbidden: [
|
|
'"tool.started"',
|
|
'"tool.result"',
|
|
'"tool.failed"',
|
|
'"tool_end"',
|
|
],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/agent/src/agent_tools/mod.rs",
|
|
forbidden: ["pub mod tool_orchestrator;", "mod tool_lifecycle;"],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/agent/src/lib.rs",
|
|
forbidden: ["mod tool_output_truncation;"],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/agent/src/protocol.rs",
|
|
forbidden: ["ToolStart {", "ToolEnd {"],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/tool-runtime/src/lib.rs",
|
|
forbidden: ["pub mod tool_batch;", "pub mod collab_agent;"],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/agent/src/agent_tools/catalog.rs",
|
|
forbidden: [
|
|
'name: "Agent",',
|
|
'name: "SendMessage",',
|
|
'name: "TeamCreate",',
|
|
'name: "TeamDelete",',
|
|
'name: "ListPeers",',
|
|
'=> "Agent"',
|
|
'=> "SendMessage"',
|
|
'=> "TeamCreate"',
|
|
'=> "TeamDelete"',
|
|
'=> "ListPeers"',
|
|
],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/core/src/tool_calling.rs",
|
|
forbidden: [
|
|
'canonical_name: "Agent",',
|
|
'canonical_name: "SendMessage",',
|
|
'canonical_name: "TeamCreate",',
|
|
'canonical_name: "TeamDelete",',
|
|
'canonical_name: "ListPeers",',
|
|
],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/tool-runtime/src/turn_tool_surface.rs",
|
|
forbidden: [
|
|
"SUBAGENT_TEAMMATE_ALLOWED_TOOL_NAMES",
|
|
"SUBAGENT_ALLOWED_NATIVE_TOOL_NAMES",
|
|
"SUBAGENT_ALLOWED_COORDINATION_TOOL_NAMES",
|
|
"runtime_turn_tool_exposure_allows_tool_name(",
|
|
],
|
|
},
|
|
];
|
|
for (const currentFile of currentFiles) {
|
|
const content = fs.readFileSync(
|
|
path.join(repoRoot, currentFile.path),
|
|
"utf8",
|
|
);
|
|
for (const snippet of currentFile.forbidden) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired raw tool wire export must stay absent: ${currentFile.path} contains ${JSON.stringify(snippet)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
const nativeOverlayProduction = fs
|
|
.readFileSync(
|
|
path.join(repoRoot, "lime-rs/crates/tool-runtime/src/native_overlay.rs"),
|
|
"utf8",
|
|
)
|
|
.split("#[cfg(test)]", 1)[0];
|
|
for (const retiredName of [
|
|
"Agent",
|
|
"SendMessage",
|
|
"TeamCreate",
|
|
"TeamDelete",
|
|
"ListPeers",
|
|
]) {
|
|
if (nativeOverlayProduction.includes(`"${retiredName}"`)) {
|
|
failures.push(
|
|
`retired Team tool must stay out of the native registry allowlist: ${retiredName}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
for (const bridgeSurface of [
|
|
{
|
|
path: "lime-rs/crates/tool-runtime/src/mcp_connection.rs",
|
|
forbidden: [
|
|
"async fn list_resources(",
|
|
"async fn read_resource(",
|
|
"async fn list_prompts(",
|
|
"async fn get_prompt(",
|
|
"fn get_info(",
|
|
],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/tool-runtime/src/mcp_connection/registry.rs",
|
|
forbidden: [
|
|
"pub struct McpConnectionSummary",
|
|
"pub async fn supports_resources(",
|
|
"pub async fn summaries(",
|
|
"pub async fn dispatch(",
|
|
"pub async fn list_prompts(",
|
|
"pub async fn get_prompt(",
|
|
],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/mcp/src/bridge_client.rs",
|
|
forbidden: [
|
|
"pub fn server_info(",
|
|
"pub async fn list_resources(",
|
|
"pub async fn read_resource(",
|
|
"pub async fn list_prompts(",
|
|
"pub async fn get_prompt(",
|
|
],
|
|
},
|
|
{
|
|
path: "lime-rs/crates/agent/src/mcp_bridge.rs",
|
|
forbidden: [
|
|
"async fn list_resources(",
|
|
"async fn read_resource(",
|
|
"async fn list_prompts(",
|
|
"async fn get_prompt(",
|
|
"fn get_info(",
|
|
],
|
|
},
|
|
]) {
|
|
const content = fs.readFileSync(
|
|
path.join(repoRoot, bridgeSurface.path),
|
|
"utf8",
|
|
);
|
|
for (const snippet of bridgeSurface.forbidden) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`MCP sampling-step bridge must not own live management surface: ${bridgeSurface.path} contains ${JSON.stringify(snippet)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
const mcpClientHandler = fs.readFileSync(
|
|
path.join(repoRoot, "lime-rs/crates/mcp/src/client.rs"),
|
|
"utf8",
|
|
);
|
|
if (mcpClientHandler.includes("enable_sampling()")) {
|
|
failures.push(
|
|
"MCP client must not advertise sampling without a typed createMessage owner: lime-rs/crates/mcp/src/client.rs contains enable_sampling()",
|
|
);
|
|
}
|
|
|
|
const canonicalToolConsumerFiles = [
|
|
"lime-rs/crates/app-server/src/runtime/provider_history.rs",
|
|
"lime-rs/crates/app-server/src/runtime/context_compaction.rs",
|
|
"lime-rs/crates/app-server/src/runtime/output_refs.rs",
|
|
"lime-rs/crates/app-server/src/runtime/thread_item_projection/media_result.rs",
|
|
"lime-rs/crates/app-server/src/runtime/thread_item_projection/coding_items.rs",
|
|
"lime-rs/crates/app-server/src/runtime/thread_item_projection/control_items.rs",
|
|
"lime-rs/crates/app-server/src/runtime/thread_item_projection/helpers.rs",
|
|
"lime-rs/crates/app-server/src/runtime/thread_item_projection/materializer.rs",
|
|
...collectRustFiles(
|
|
"lime-rs/crates/app-server/src/runtime/thread_item_projection/materializer",
|
|
),
|
|
];
|
|
for (const relativePath of canonicalToolConsumerFiles) {
|
|
const content = fs.readFileSync(path.join(repoRoot, relativePath), "utf8");
|
|
const productionContent = content.split("#[cfg(test)]", 1)[0];
|
|
for (const retiredEventType of [
|
|
'"tool.started"',
|
|
'"tool.result"',
|
|
'"tool.failed"',
|
|
'"tool.completed"',
|
|
]) {
|
|
if (productionContent.includes(retiredEventType)) {
|
|
failures.push(
|
|
`canonical Tool consumer must not parse retired lifecycle: ${relativePath} contains ${retiredEventType}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkOrchestratorHostBoundary() {
|
|
const roots = [
|
|
path.join(repoRoot, "electron"),
|
|
path.join(repoRoot, "src/lib/dev-bridge"),
|
|
];
|
|
const forbiddenSnippets = [
|
|
"orchestrator.skills.enabled",
|
|
"orchestrator.mcp.enabled",
|
|
"discover_orchestrator_skills",
|
|
"OrchestratorSkill",
|
|
"codex_apps",
|
|
];
|
|
for (const root of roots) {
|
|
if (!fs.existsSync(root)) continue;
|
|
for (const relativePath of walkSourceFiles(root)) {
|
|
if (
|
|
!/\.(?:d\.ts|ts|tsx|mjs)$/u.test(relativePath) ||
|
|
relativePath.includes(".test") ||
|
|
relativePath.includes(".spec")
|
|
) {
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(
|
|
path.join(repoRoot, relativePath),
|
|
"utf8",
|
|
);
|
|
for (const snippet of forbiddenSnippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`Orchestrator current owner must remain App Server/runtime/skills/MCP; ${relativePath} must not contain ${JSON.stringify(snippet)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAgentRuntimeClientShells() {
|
|
for (const relativePath of [
|
|
"src/lib/api/agentRuntime.ts",
|
|
"src/lib/api/agentRuntime.d.ts",
|
|
"src/lib/api/agentRuntime/index.ts",
|
|
"src/lib/api/agentRuntime/index.d.ts",
|
|
"src/lib/api/agentRuntime/types.ts",
|
|
"src/lib/api/agentRuntime/types.d.ts",
|
|
"src/lib/api/agentRuntime/mediaClient.ts",
|
|
"src/lib/api/agentRuntime/mediaClient.d.ts",
|
|
"src/lib/api/agentRuntime/subagentClient.ts",
|
|
"src/lib/api/agentRuntime/subagentClient.d.ts",
|
|
]) {
|
|
if (fs.existsSync(path.join(repoRoot, relativePath))) {
|
|
failures.push(
|
|
`retired Agent Runtime client shell or root barrel must stay deleted: ${relativePath}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredPluginRuntimeRendererFacade() {
|
|
const retiredFiles = [
|
|
"electron/pluginRuntimeTaskHost.ts",
|
|
"electron/pluginShellHost.ts",
|
|
"src/lib/api/pluginRuntime.ts",
|
|
"src/lib/api/plugins.ts",
|
|
"src/lib/api/pluginsTypes.ts",
|
|
"src/lib/api/pluginsResultGuards.ts",
|
|
"src/features/plugin/types.ts",
|
|
"src/features/plugin/types.d.ts",
|
|
];
|
|
for (const relativePath of retiredFiles) {
|
|
if (fs.existsSync(path.join(repoRoot, relativePath))) {
|
|
failures.push(
|
|
`retired Plugin runtime/lifecycle facade must stay deleted: ${relativePath}`,
|
|
);
|
|
}
|
|
}
|
|
for (const relativePath of [
|
|
"src/features/plugin/runtime",
|
|
"src/features/plugin/sdk",
|
|
"src/features/plugin/shell",
|
|
"src/features/plugin/publish",
|
|
"src/features/plugin/readiness",
|
|
"src/features/plugin/runtime-profile",
|
|
"src/features/plugin/manifest",
|
|
]) {
|
|
if (fs.existsSync(path.join(repoRoot, relativePath))) {
|
|
failures.push(
|
|
`retired Plugin implementation directory must stay deleted: ${relativePath}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkCanonicalRendererSequenceGate() {
|
|
const relativePath = "src/lib/api/agentRuntime/eventSequenceGate.ts";
|
|
const content = fs.readFileSync(path.join(repoRoot, relativePath), "utf8");
|
|
for (const snippet of ["AgentRuntimeEventPipeline", "processSync("]) {
|
|
if (!content.includes(snippet)) {
|
|
failures.push(
|
|
`canonical renderer sequence gate missing ${JSON.stringify(snippet)} in ${relativePath}`,
|
|
);
|
|
}
|
|
}
|
|
for (const snippet of [
|
|
"AgentRuntimeEventAdapter",
|
|
"withEvent",
|
|
"currentCompatibilityAdapter",
|
|
"currentToolCompletedFanoutAdapter",
|
|
]) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`canonical renderer sequence gate must not restore raw lifecycle adaptation: ${relativePath} contains ${JSON.stringify(snippet)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkAgentRuntimeThinGatewayContracts() {
|
|
const sourceRoot = path.join(repoRoot, "src/lib/api/agentRuntime");
|
|
for (const relativePath of walkSourceFiles(sourceRoot)) {
|
|
if (!isAgentRuntimeGatewaySource(relativePath)) {
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(path.join(repoRoot, relativePath), "utf8");
|
|
for (const {
|
|
snippet,
|
|
reason,
|
|
} of agentRuntimeThinGatewayForbiddenSnippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`agentRuntime thin gateway: ${relativePath} forbidden ${JSON.stringify(
|
|
snippet,
|
|
)}; ${reason}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function walkSourceFiles(root) {
|
|
const entries = fs.readdirSync(root, { withFileTypes: true });
|
|
const files = [];
|
|
for (const entry of entries) {
|
|
const absolutePath = path.join(root, entry.name);
|
|
if (entry.isDirectory()) {
|
|
files.push(...walkSourceFiles(absolutePath));
|
|
continue;
|
|
}
|
|
if (!entry.isFile()) {
|
|
continue;
|
|
}
|
|
files.push(path.relative(repoRoot, absolutePath));
|
|
}
|
|
return files.sort();
|
|
}
|
|
|
|
function checkRendererQueuedTurnWriteSurface() {
|
|
for (const relativeRoot of rendererQueuedTurnWriteSurfaceRoots) {
|
|
const sourceRoot = path.join(repoRoot, relativeRoot);
|
|
for (const relativePath of walkSourceFiles(sourceRoot)) {
|
|
if (
|
|
!/\.(?:d\.ts|ts|tsx)$/u.test(relativePath) ||
|
|
relativePath.includes(".test") ||
|
|
relativePath.includes(".spec") ||
|
|
/(?:^|\/)__tests__(?:\/|$)/u.test(relativePath)
|
|
) {
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(
|
|
path.join(repoRoot, relativePath),
|
|
"utf8",
|
|
);
|
|
for (const snippet of rendererQueuedTurnWriteSurfaceForbiddenSnippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`Renderer queued-turn write surface must stay deleted: ${relativePath} contains ${JSON.stringify(snippet)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredPublicQueuedTurnSurface() {
|
|
for (const file of retiredPublicQueuedTurnSchemaFiles) {
|
|
if (fs.existsSync(path.join(repoRoot, file))) {
|
|
failures.push(
|
|
`retired public queued-turn schema must stay deleted: ${file}`,
|
|
);
|
|
}
|
|
}
|
|
for (const file of [
|
|
...retiredRendererQueuedTurnFiles,
|
|
...retiredPendingSteerFixtureFiles,
|
|
]) {
|
|
if (fs.existsSync(path.join(repoRoot, file))) {
|
|
failures.push(
|
|
`retired public queued-turn file must stay deleted: ${file}`,
|
|
);
|
|
}
|
|
}
|
|
for (const { file, snippets } of retiredPublicQueuedTurnSurfaceSpecs) {
|
|
const absolutePath = path.join(repoRoot, file);
|
|
if (!fs.existsSync(absolutePath)) {
|
|
failures.push(
|
|
`retired public queued-turn guard missing production file: ${file}`,
|
|
);
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(absolutePath, "utf8");
|
|
for (const snippet of snippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired public queued-turn surface: ${file} must not contain ${JSON.stringify(snippet)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
const agentRuntimeScriptsRoot = path.join(repoRoot, "scripts/agent-runtime");
|
|
for (const relativePath of walkScriptFiles(agentRuntimeScriptsRoot)) {
|
|
const content = fs.readFileSync(path.join(repoRoot, relativePath), "utf8");
|
|
for (const snippet of [
|
|
...retiredPendingSteerScenarios,
|
|
"INPUTBAR_PENDING_STEER",
|
|
"inputbarPendingSteer",
|
|
"InputbarPendingSteer",
|
|
]) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired pending-steer fixture surface: ${relativePath} must not contain ${JSON.stringify(snippet)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredExecutionProcessSurface() {
|
|
for (const file of retiredExecutionProcessFiles) {
|
|
if (fs.existsSync(path.join(repoRoot, file))) {
|
|
failures.push(
|
|
`retired executionProcess surface must stay deleted: ${file}`,
|
|
);
|
|
}
|
|
}
|
|
for (const spec of retiredExecutionProcessSurfaceSpecs) {
|
|
const files = spec.files ?? [spec.file];
|
|
for (const file of files) {
|
|
const absolutePath = path.join(repoRoot, file);
|
|
if (!fs.existsSync(absolutePath)) {
|
|
failures.push(
|
|
`retired executionProcess guard missing production file: ${file}`,
|
|
);
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(absolutePath, "utf8");
|
|
for (const snippet of spec.snippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired executionProcess surface: ${file} must not contain ${JSON.stringify(snippet)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredFileSystemSurface() {
|
|
for (const file of retiredFileSystemFiles) {
|
|
if (fs.existsSync(path.join(repoRoot, file))) {
|
|
failures.push(`retired fileSystem surface must stay deleted: ${file}`);
|
|
}
|
|
}
|
|
for (const spec of retiredFileSystemSurfaceSpecs) {
|
|
const files = spec.files ?? [spec.file];
|
|
for (const file of files) {
|
|
const absolutePath = path.join(repoRoot, file);
|
|
if (!fs.existsSync(absolutePath)) {
|
|
failures.push(
|
|
`retired fileSystem guard missing production file: ${file}`,
|
|
);
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(absolutePath, "utf8");
|
|
for (const snippet of spec.snippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired fileSystem surface: ${file} must not contain ${JSON.stringify(snippet)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function isAgentRuntimeGatewaySource(relativePath) {
|
|
return (
|
|
relativePath.endsWith(".ts") &&
|
|
!relativePath.endsWith(".d.ts") &&
|
|
!relativePath.endsWith(".test.ts") &&
|
|
!relativePath.endsWith(".generated.ts")
|
|
);
|
|
}
|
|
|
|
function checkRetiredAgentRuntimeSessionFacadeSurface() {
|
|
for (const file of retiredAgentRuntimeSessionFacadeProductionFiles) {
|
|
const absolutePath = path.join(repoRoot, file);
|
|
if (!fs.existsSync(absolutePath)) {
|
|
failures.push(
|
|
`retired session facade surface guard: missing expected production file ${file}`,
|
|
);
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(absolutePath, "utf8");
|
|
for (const snippet of retiredAgentRuntimeSessionFacadeSnippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired session facade surface: ${file} must not contain ${JSON.stringify(
|
|
snippet,
|
|
)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredSkillExecutionSurfaceFiles() {
|
|
for (const file of retiredSkillExecutionSurfaceFiles) {
|
|
if (fs.existsSync(path.join(repoRoot, file))) {
|
|
failures.push(
|
|
`retired Skill execution surface must stay deleted: ${file}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAgentRuntimeMockFiles() {
|
|
for (const file of retiredAgentRuntimeMockFiles) {
|
|
if (fs.existsSync(path.join(repoRoot, file))) {
|
|
failures.push(
|
|
`retired Agent Runtime mock file must stay deleted: ${file}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAgentRuntimeCommandManifestFiles() {
|
|
for (const file of retiredAgentRuntimeCommandManifestFiles) {
|
|
if (fs.existsSync(path.join(repoRoot, file))) {
|
|
failures.push(
|
|
`retired Agent Runtime command manifest surface must stay deleted: ${file}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAgentRuntimeAdapterFiles() {
|
|
for (const file of retiredAgentRuntimeAdapterFiles) {
|
|
if (fs.existsSync(path.join(repoRoot, file))) {
|
|
failures.push(`retired Agent runtime adapter must stay deleted: ${file}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAgentSessionUpdateSurface() {
|
|
const retiredSchemaFiles = [
|
|
"lime-rs/crates/app-server-protocol/schema/json/v0/AgentSessionUpdateParams.json",
|
|
"lime-rs/crates/app-server-protocol/schema/json/v0/AgentSessionUpdateResponse.json",
|
|
];
|
|
const productionFiles = [
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/method_names.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/session_admin.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/client_request.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/schema_types.rs",
|
|
"lime-rs/crates/app-server-protocol/src/protocol/v0/catalog.rs",
|
|
"lime-rs/crates/app-server-protocol/src/schema_export/registry.rs",
|
|
"lime-rs/crates/app-server-protocol/schema/json/app_server_protocol.schemas.json",
|
|
"lime-rs/crates/app-server-protocol/schema/json/manifest.json",
|
|
"lime-rs/crates/app-server/src/processor/agent_session.rs",
|
|
"lime-rs/crates/app-server/src/processor/dispatch.rs",
|
|
"lime-rs/crates/app-server/src/runtime/session_lifecycle.rs",
|
|
"lime-rs/crates/app-server/src/runtime/projection_store.rs",
|
|
"packages/app-server-client/src/connection-methods.ts",
|
|
"packages/app-server-client/src/generated/protocol-types.ts",
|
|
"packages/app-server-client/src/protocol.ts",
|
|
"packages/app-server-client/src/request-client-methods.ts",
|
|
"packages/app-server-client/src/request-client.ts",
|
|
"src/lib/api/appServer.ts",
|
|
"src/lib/api/agentExecutionRuntime.ts",
|
|
"src/lib/api/agentRuntime/appServerSessionClient.ts",
|
|
"src/lib/api/agentRuntime/requestTypes.ts",
|
|
"src/lib/api/agentRuntime/sessionClient.ts",
|
|
"src/lib/dev-bridge/commandPolicy.ts",
|
|
"src/lib/governance/agentCommandCatalog.json",
|
|
];
|
|
const retiredSnippets = [
|
|
'"agentSession/update"',
|
|
"METHOD_AGENT_SESSION_UPDATE",
|
|
"AgentSessionUpdateParams",
|
|
"AgentSessionUpdateResponse",
|
|
"updateAgentRuntimeSession",
|
|
"appServerClient.updateSession(",
|
|
"update_session_current",
|
|
"update_session_overview",
|
|
];
|
|
|
|
for (const file of retiredSchemaFiles) {
|
|
if (fs.existsSync(path.join(repoRoot, file))) {
|
|
failures.push(
|
|
`retired agentSession/update schema must stay deleted: ${file}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
for (const file of productionFiles) {
|
|
const absolutePath = path.join(repoRoot, file);
|
|
if (!fs.existsSync(absolutePath)) {
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(absolutePath, "utf8");
|
|
for (const snippet of retiredSnippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired agentSession/update surface: ${file} must not contain ${JSON.stringify(
|
|
snippet,
|
|
)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredRendererProjectionFiles() {
|
|
for (const file of retiredRendererProjectionFiles) {
|
|
if (fs.existsSync(path.join(repoRoot, file))) {
|
|
failures.push(`retired Renderer projection must stay deleted: ${file}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAgentStreamToolMessageSynthesisSurface() {
|
|
for (const file of retiredAgentStreamToolMessageSynthesisFiles) {
|
|
if (fs.existsSync(path.join(repoRoot, file))) {
|
|
failures.push(
|
|
`retired Item-to-Message tool synthesis must stay deleted: ${file}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
const agentChatRoot = path.join(repoRoot, "src/components/agent/chat");
|
|
for (const relativePath of walkSourceFiles(agentChatRoot)) {
|
|
if (
|
|
!/\.[cm]?[jt]sx?$/u.test(relativePath) ||
|
|
/\.(?:test|spec)\.[cm]?[jt]sx?$/u.test(relativePath)
|
|
) {
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(path.join(repoRoot, relativePath), "utf8");
|
|
for (const snippet of retiredAgentStreamToolMessageSynthesisSnippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired Item-to-Message tool synthesis: ${relativePath} must not contain ${JSON.stringify(
|
|
snippet,
|
|
)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredRendererQueuedTurnProjectionSurface() {
|
|
for (const file of retiredRendererQueuedTurnProjectionProductionFiles) {
|
|
const absolutePath = path.join(repoRoot, file);
|
|
if (!fs.existsSync(absolutePath)) {
|
|
failures.push(
|
|
`retired Renderer queued-turn projection guard: missing expected production file ${file}`,
|
|
);
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(absolutePath, "utf8");
|
|
for (const snippet of retiredRendererQueuedTurnProjectionSnippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired Renderer queued-turn projection surface: ${file} must not contain ${JSON.stringify(
|
|
snippet,
|
|
)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredRendererQueuedTurnSecondaryProjectionSurface() {
|
|
for (const {
|
|
file,
|
|
snippets,
|
|
} of retiredRendererQueuedTurnSecondaryProjectionSpecs) {
|
|
const absolutePath = path.join(repoRoot, file);
|
|
if (!fs.existsSync(absolutePath)) {
|
|
failures.push(
|
|
`retired Renderer queued-turn secondary projection guard: missing expected production file ${file}`,
|
|
);
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(absolutePath, "utf8");
|
|
for (const snippet of snippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired Renderer queued-turn secondary projection surface: ${file} must not contain ${JSON.stringify(
|
|
snippet,
|
|
)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAgentUiResumeContractFiles() {
|
|
for (const file of retiredAgentUiResumeContractFiles) {
|
|
if (fs.existsSync(path.join(repoRoot, file))) {
|
|
failures.push(
|
|
`retired Agent UI resume contract must stay deleted: ${file}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAgentRuntimeLegacyQueueSurface() {
|
|
for (const file of retiredAgentRuntimeLegacyQueueFiles) {
|
|
if (fs.existsSync(path.join(repoRoot, file))) {
|
|
failures.push(
|
|
`retired Agent Runtime legacy queue file must stay deleted: ${file}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
for (const file of retiredAgentRuntimeLegacyQueueSurfaceFiles) {
|
|
const absolutePath = path.join(repoRoot, file);
|
|
if (!fs.existsSync(absolutePath)) {
|
|
failures.push(
|
|
`retired Agent Runtime legacy queue guard: missing expected file ${file}`,
|
|
);
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(absolutePath, "utf8");
|
|
for (const snippet of retiredAgentRuntimeLegacyQueueSnippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired Agent Runtime legacy queue surface: ${file} must not contain ${JSON.stringify(
|
|
snippet,
|
|
)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAgentRuntimeToolInventoryMockFiles() {
|
|
for (const file of retiredAgentRuntimeToolInventoryMockFiles) {
|
|
if (fs.existsSync(path.join(repoRoot, file))) {
|
|
failures.push(
|
|
`retired Agent Runtime tool inventory mock must stay deleted: ${file}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAgentRuntimeEvidenceExportFacadeSurface() {
|
|
for (const file of retiredAgentRuntimeEvidenceExportFacadeProductionFiles) {
|
|
const absolutePath = path.join(repoRoot, file);
|
|
if (!fs.existsSync(absolutePath)) {
|
|
failures.push(
|
|
`retired evidence export facade surface guard: missing expected production file ${file}`,
|
|
);
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(absolutePath, "utf8");
|
|
for (const snippet of retiredAgentRuntimeEvidenceExportFacadeSnippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired evidence export facade surface: ${file} must not contain ${JSON.stringify(
|
|
snippet,
|
|
)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAgentRuntimeThreadReadFacadeSurface() {
|
|
for (const file of retiredAgentRuntimeThreadReadFacadeProductionFiles) {
|
|
const absolutePath = path.join(repoRoot, file);
|
|
if (!fs.existsSync(absolutePath)) {
|
|
failures.push(
|
|
`retired thread read facade surface guard: missing expected production file ${file}`,
|
|
);
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(absolutePath, "utf8");
|
|
for (const snippet of retiredAgentRuntimeThreadReadFacadeSnippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired thread read facade surface: ${file} must not contain ${JSON.stringify(
|
|
snippet,
|
|
)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAgentRuntimeSubmitTurnFacadeSurface() {
|
|
for (const file of retiredAgentRuntimeSubmitTurnFacadeProductionFiles) {
|
|
const absolutePath = path.join(repoRoot, file);
|
|
if (!fs.existsSync(absolutePath)) {
|
|
failures.push(
|
|
`retired submit turn facade surface guard: missing expected production file ${file}`,
|
|
);
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(absolutePath, "utf8");
|
|
for (const snippet of retiredAgentRuntimeSubmitTurnFacadeSnippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired submit turn facade surface: ${file} must not contain ${JSON.stringify(
|
|
snippet,
|
|
)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAgentRuntimeInterruptTurnFacadeSurface() {
|
|
for (const file of retiredAgentRuntimeInterruptTurnFacadeProductionFiles) {
|
|
const absolutePath = path.join(repoRoot, file);
|
|
if (!fs.existsSync(absolutePath)) {
|
|
failures.push(
|
|
`retired interrupt turn facade surface guard: missing expected production file ${file}`,
|
|
);
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(absolutePath, "utf8");
|
|
for (const snippet of retiredAgentRuntimeInterruptTurnFacadeSnippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired interrupt turn facade surface: ${file} must not contain ${JSON.stringify(
|
|
snippet,
|
|
)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkRetiredAgentRuntimeRespondActionFacadeSurface() {
|
|
for (const file of retiredAgentRuntimeRespondActionFacadeProductionFiles) {
|
|
const absolutePath = path.join(repoRoot, file);
|
|
if (!fs.existsSync(absolutePath)) {
|
|
failures.push(
|
|
`retired respond action facade surface guard: missing expected production file ${file}`,
|
|
);
|
|
continue;
|
|
}
|
|
const content = fs.readFileSync(absolutePath, "utf8");
|
|
for (const snippet of retiredAgentRuntimeRespondActionFacadeSnippets) {
|
|
if (content.includes(snippet)) {
|
|
failures.push(
|
|
`retired respond action facade surface: ${file} must not contain ${JSON.stringify(
|
|
snippet,
|
|
)}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkActiveAipromptsDoNotPromoteRetiredAgentRuntimeCommands() {
|
|
for (const file of activeAgentRuntimeMarkdownFiles) {
|
|
const absolutePath = path.join(repoRoot, file);
|
|
if (!fs.existsSync(absolutePath)) {
|
|
failures.push(
|
|
`active markdown retired agent_runtime guard: missing expected file ${file}`,
|
|
);
|
|
continue;
|
|
}
|
|
|
|
const lines = fs.readFileSync(absolutePath, "utf8").split(/\r?\n/u);
|
|
lines.forEach((line, index) => {
|
|
if (!/agent_runtime_[A-Za-z0-9_*]+/u.test(line)) {
|
|
return;
|
|
}
|
|
if (allowedRetiredAgentRuntimeDocContextPattern.test(line)) {
|
|
return;
|
|
}
|
|
failures.push(
|
|
`active markdown retired agent_runtime guard: ${file}:${index + 1} must mark agent_runtime_* as retired/guard/history/migration-only, got ${JSON.stringify(
|
|
line.trim(),
|
|
)}`,
|
|
);
|
|
});
|
|
|
|
lines.forEach((line, index) => {
|
|
if (!/agent_runtime_[A-Za-z0-9_*]+/u.test(line)) {
|
|
return;
|
|
}
|
|
if (!forbiddenAgentRuntimeCurrentDocContextPattern.test(line)) {
|
|
return;
|
|
}
|
|
if (allowedRetiredAgentRuntimeDocContextPattern.test(line)) {
|
|
return;
|
|
}
|
|
failures.push(
|
|
`active markdown retired agent_runtime current wording: ${file}:${index + 1} must not describe agent_runtime_* as current, got ${JSON.stringify(
|
|
line.trim(),
|
|
)}`,
|
|
);
|
|
});
|
|
}
|
|
}
|
|
|
|
function collectMarkdownFiles(relativeRoot) {
|
|
const root = path.join(repoRoot, relativeRoot);
|
|
if (!fs.existsSync(root)) {
|
|
return [];
|
|
}
|
|
const files = [];
|
|
for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
|
|
const absolutePath = path.join(root, entry.name);
|
|
if (entry.isDirectory()) {
|
|
if (
|
|
entry.name === "node_modules" ||
|
|
entry.name === "dist" ||
|
|
entry.name === "target"
|
|
) {
|
|
continue;
|
|
}
|
|
files.push(
|
|
...collectMarkdownFiles(
|
|
path.relative(repoRoot, absolutePath).replaceAll("\\", "/"),
|
|
),
|
|
);
|
|
continue;
|
|
}
|
|
if (!entry.isFile() || !entry.name.endsWith(".md")) {
|
|
continue;
|
|
}
|
|
files.push(path.relative(repoRoot, absolutePath).replaceAll("\\", "/"));
|
|
}
|
|
return files.sort();
|
|
}
|
|
|
|
function checkScriptsDoNotCallRetiredAgentRuntimeCommands() {
|
|
const scriptsRoot = path.join(repoRoot, "scripts");
|
|
for (const relativePath of walkScriptFiles(scriptsRoot)) {
|
|
const content = fs.readFileSync(path.join(repoRoot, relativePath), "utf8");
|
|
for (const pattern of retiredAgentRuntimeScriptCallPatterns) {
|
|
const match = pattern.exec(content);
|
|
if (match) {
|
|
failures.push(
|
|
`retired agent_runtime script call guard: ${relativePath} must not call retired agent_runtime_* command via ${JSON.stringify(
|
|
match[0],
|
|
)}; keep legacy names only as negative guards or history evidence`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function walkScriptFiles(root) {
|
|
if (!fs.existsSync(root)) {
|
|
return [];
|
|
}
|
|
const files = [];
|
|
for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
|
|
const absolutePath = path.join(root, entry.name);
|
|
if (entry.isDirectory()) {
|
|
if (
|
|
entry.name === "node_modules" ||
|
|
entry.name === "dist" ||
|
|
entry.name === "target"
|
|
) {
|
|
continue;
|
|
}
|
|
files.push(...walkScriptFiles(absolutePath));
|
|
continue;
|
|
}
|
|
if (!entry.isFile()) {
|
|
continue;
|
|
}
|
|
const relativePath = path.relative(repoRoot, absolutePath);
|
|
if (!/\.(?:cjs|js|mjs)$/u.test(relativePath)) {
|
|
continue;
|
|
}
|
|
if (/\.(?:test|spec)\.(?:cjs|js|mjs)$/u.test(relativePath)) {
|
|
continue;
|
|
}
|
|
files.push(relativePath.replaceAll("\\", "/"));
|
|
}
|
|
return files.sort();
|
|
}
|
|
|
|
function descriptorBlock(content, marker) {
|
|
const startIndex = content.indexOf(marker);
|
|
if (startIndex < 0) {
|
|
return null;
|
|
}
|
|
const endIndex = content.indexOf("\n },", startIndex);
|
|
if (endIndex < 0) {
|
|
return null;
|
|
}
|
|
return content.slice(startIndex, endIndex + "\n },".length);
|
|
}
|
|
|
|
function assertBlockIncludes(block, snippet, description) {
|
|
if (!block.includes(snippet)) {
|
|
failures.push(`${description}: missing ${JSON.stringify(snippet)}`);
|
|
}
|
|
}
|
|
|
|
function assertBlockExcludes(block, snippet, description) {
|
|
if (block.includes(snippet)) {
|
|
failures.push(`${description}: forbidden ${JSON.stringify(snippet)}`);
|
|
}
|
|
}
|