@rexvane/piweb 0.3.16 → 0.3.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +8 -11
- package/.next/build-manifest.json +3 -3
- package/.next/prerender-manifest.json +6 -6
- package/.next/react-loadable-manifest.json +4 -16
- package/.next/required-server-files.js +1 -3
- package/.next/required-server-files.json +1 -3
- package/.next/routes-manifest.json +0 -20
- package/.next/server/app/_global-error/page.js +2 -2
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page.js +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +4 -7
- package/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -5
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
- package/.next/server/app/api/agent/[id]/events/route.js +2 -2
- package/.next/server/app/api/agent/[id]/events/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/[id]/route.js +1 -1
- package/.next/server/app/api/agent/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/[id]/tree/route.js +1 -1
- package/.next/server/app/api/agent/[id]/tree/route.js.nft.json +1 -1
- package/.next/server/app/api/agent/new/route.js +1 -1
- package/.next/server/app/api/agent/new/route.js.nft.json +1 -1
- package/.next/server/app/api/config/route.js +1 -1
- package/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/server/app/api/files/route.js +1 -1
- package/.next/server/app/api/files/route.js.nft.json +1 -1
- package/.next/server/app/api/git/route.js +2 -2
- package/.next/server/app/api/git/route.js.nft.json +1 -1
- package/.next/server/app/api/growth/route.js +1 -1
- package/.next/server/app/api/growth/route.js.nft.json +1 -1
- package/.next/server/app/api/health/route.js +1 -1
- package/.next/server/app/api/models/route.js +1 -1
- package/.next/server/app/api/models/route.js.nft.json +1 -1
- package/.next/server/app/api/pi-settings/route.js +1 -1
- package/.next/server/app/api/pi-settings/route.js.nft.json +1 -1
- package/.next/server/app/api/plugins/route.js +1 -1
- package/.next/server/app/api/plugins/route.js.nft.json +1 -1
- package/.next/server/app/api/prompts/route.js +1 -1
- package/.next/server/app/api/prompts/route.js.nft.json +1 -1
- package/.next/server/app/api/security/route.js +1 -1
- package/.next/server/app/api/security/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/export/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/export/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/[id]/route.js +1 -1
- package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/import/route.js +3 -3
- package/.next/server/app/api/sessions/import/route.js.nft.json +1 -1
- package/.next/server/app/api/sessions/route.js +1 -1
- package/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/.next/server/app/api/skills/route.js +2 -2
- package/.next/server/app/api/skills/route.js.nft.json +1 -1
- package/.next/server/app/api/update/route.js +2 -2
- package/.next/server/app/api/update/route.js.nft.json +1 -1
- package/.next/server/app/api/version/route.js +1 -1
- package/.next/server/app/api/version/route.js.nft.json +1 -1
- package/.next/server/app/api/web-auth/route.js +1 -1
- package/.next/server/app/api/workspaces/route.js +1 -1
- package/.next/server/app/api/workspaces/route.js.nft.json +1 -1
- package/.next/server/app/icon.svg/route.js +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +6 -9
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -7
- package/.next/server/app/index.segments/_full.segment.rsc +6 -9
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -5
- package/.next/server/app/login/page.js +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +1 -1
- package/.next/server/app/login.rsc +5 -8
- package/.next/server/app/login.segments/_full.segment.rsc +5 -8
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -5
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +3 -6
- package/.next/server/app/page.js +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +8 -11
- package/.next/server/chunks/496.js +1 -1
- package/.next/server/chunks/532.js +1 -1
- package/.next/server/chunks/686.js +4 -8
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/2608.ec8ff1f5767c9056.js +1 -0
- package/.next/static/chunks/2716.93be8ad5c970c516.js +1 -0
- package/.next/static/chunks/4632.112d2e893d48d188.js +1 -0
- package/.next/static/chunks/4673.c1fb1580efc6ace7.js +1 -0
- package/.next/static/chunks/4686-f4a037d609cea3f2.js +1 -0
- package/.next/static/chunks/app/_global-error/page-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/events/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/agent/[id]/tree/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/agent/new/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/config/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/files/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/git/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/growth/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/health/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/models/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/pi-settings/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/plugins/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/prompts/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/security/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/export/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/sessions/[id]/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/sessions/import/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/sessions/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/skills/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/update/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/version/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/web-auth/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/api/workspaces/route-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/app/page-b51087831582ee37.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-f77e9ede9808b18e.js +1 -0
- package/.next/static/chunks/webpack-c31263fd83d75ce6.js +1 -0
- package/.next/static/css/850c2fd130ffa2fc.css +1 -0
- package/.next/static/zsynuO_9Kx6nrXgkTUJ04/_buildManifest.js +1 -0
- package/.next/types/routes.d.ts +1 -4
- package/.next/types/validator.ts +0 -27
- package/README.md +17 -29
- package/assets/archive.jpg +0 -0
- package/assets/growth-1.jpg +0 -0
- package/assets/growth-2.jpg +0 -0
- package/assets/import.jpg +0 -0
- package/assets/main.jpg +0 -0
- package/assets/outline.jpg +0 -0
- package/assets/prompts-1.jpg +0 -0
- package/assets/prompts-2.jpg +0 -0
- package/assets/providers-1.jpg +0 -0
- package/assets/providers-2.jpg +0 -0
- package/assets/providers-3.jpg +0 -0
- package/assets/trace-1.jpg +0 -0
- package/assets/trace-2.png +0 -0
- package/assets/trace-3.png +0 -0
- package/assets/trace-4.png +0 -0
- package/assets/viewer-1.jpg +0 -0
- package/assets/viewer-2.jpg +0 -0
- package/bin/pi.js +50 -0
- package/next.config.ts +32 -7
- package/package.json +4 -9
- package/scripts/launcher.mjs +1 -1
- package/scripts/pick-folder.ps1 +2 -11
- package/scripts/release.mjs +31 -11
- package/scripts/verify-package.mjs +0 -53
- package/src/app/api/config/route.ts +1 -4
- package/src/app/api/growth/route.ts +14 -14
- package/src/app/api/models/route.ts +2 -1
- package/src/app/api/security/route.ts +3 -8
- package/src/app/api/update/route.ts +2 -8
- package/src/app/globals.css +90 -777
- package/src/app/layout.tsx +6 -13
- package/src/components/AppShell.tsx +229 -521
- package/src/components/ChatInput.tsx +26 -153
- package/src/components/ChatWindow.tsx +231 -51
- package/src/components/ContextMeter.tsx +17 -11
- package/src/components/FileViewer.tsx +11 -10
- package/src/components/GitPanel.tsx +11 -13
- package/src/components/ModelSelector.tsx +6 -19
- package/src/components/PiMark.tsx +38 -5
- package/src/components/ProjectPanel.tsx +111 -95
- package/src/components/PromptPanel.tsx +51 -132
- package/src/components/SessionImportSection.tsx +37 -53
- package/src/components/SessionSidebar.tsx +57 -159
- package/src/components/SettingsPanel.tsx +193 -330
- package/src/components/icons.tsx +0 -23
- package/src/hooks/useGrowth.ts +123 -156
- package/src/hooks/usePiWeb.ts +15 -122
- package/src/i18n.tsx +42 -98
- package/src/lib/agent-manager.ts +21 -187
- package/src/lib/command-validation.ts +1 -9
- package/src/lib/growth-service.ts +390 -166
- package/src/lib/growth-tracker.ts +64 -264
- package/src/lib/growth-turns.ts +31 -1
- package/src/lib/models/model-scope.ts +15 -0
- package/src/lib/models-service.ts +16 -0
- package/src/lib/pi-settings.ts +7 -0
- package/src/lib/pi.ts +2 -3
- package/src/lib/session-import/claude.ts +2 -13
- package/src/lib/session-import/codex.ts +8 -44
- package/src/lib/session-import/files.ts +0 -14
- package/src/lib/session-import/grok.ts +24 -54
- package/src/lib/session-import/index.ts +0 -5
- package/src/lib/session-import/types.ts +0 -12
- package/src/lib/session-import/writer.ts +3 -8
- package/src/lib/skills-service.ts +9 -16
- package/src/lib/theme.ts +1 -68
- package/src/lib/trajectory.ts +0 -1
- package/src/lib/types.ts +27 -36
- package/tsconfig.json +2 -1
- package/.next/server/app/api/swarm/[id]/route.js +0 -1
- package/.next/server/app/api/swarm/[id]/route.js.nft.json +0 -1
- package/.next/server/app/api/swarm/[id]/route_client-reference-manifest.js +0 -1
- package/.next/server/app/api/swarm/route.js +0 -1
- package/.next/server/app/api/swarm/route.js.nft.json +0 -1
- package/.next/server/app/api/swarm/route_client-reference-manifest.js +0 -1
- package/.next/server/app/api/tests/route.js +0 -2
- package/.next/server/app/api/tests/route.js.nft.json +0 -1
- package/.next/server/app/api/tests/route_client-reference-manifest.js +0 -1
- package/.next/server/chunks/757.js +0 -1
- package/.next/server/chunks/775.js +0 -3
- package/.next/static/0t1jBUAuVaTFTXxRyIo3q/_buildManifest.js +0 -1
- package/.next/static/chunks/2608.43c58236c9cce8e6.js +0 -1
- package/.next/static/chunks/2716.4ec42df1d51354c9.js +0 -1
- package/.next/static/chunks/4632.62139b565b657aac.js +0 -1
- package/.next/static/chunks/4673.7796104395deb8d7.js +0 -1
- package/.next/static/chunks/4686-17f21a006739a596.js +0 -1
- package/.next/static/chunks/7577.10af9bb661652da8.js +0 -1
- package/.next/static/chunks/8866.38ec4ac4ee5a1b74.js +0 -1
- package/.next/static/chunks/app/_global-error/page-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/events/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/agent/[id]/tree/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/agent/new/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/config/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/files/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/git/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/growth/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/health/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/models/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/pi-settings/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/plugins/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/prompts/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/security/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/export/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/sessions/[id]/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/sessions/import/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/sessions/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/skills/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/swarm/[id]/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/swarm/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/tests/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/update/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/version/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/web-auth/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/api/workspaces/route-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/app/page-14379b8060d5cf07.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-5148173b3f55e415.js +0 -1
- package/.next/static/chunks/webpack-d1a69ad9edb38b11.js +0 -1
- package/.next/static/css/d0a0162cb481abe8.css +0 -1
- package/.next/types/app/api/swarm/[id]/route.ts +0 -353
- package/.next/types/app/api/swarm/route.ts +0 -353
- package/.next/types/app/api/tests/route.ts +0 -353
- package/assets/archive.png +0 -0
- package/assets/growth-1.png +0 -0
- package/assets/growth-2.png +0 -0
- package/assets/import.png +0 -0
- package/assets/main.png +0 -0
- package/assets/outline.png +0 -0
- package/assets/prompts-1.png +0 -0
- package/assets/prompts-2.png +0 -0
- package/assets/providers-1.png +0 -0
- package/assets/providers-2.png +0 -0
- package/assets/providers-3.png +0 -0
- package/assets/trace-1.png +0 -0
- package/assets/viewer-1.png +0 -0
- package/assets/viewer-2.png +0 -0
- package/scripts/managed-niubash-assets.mjs +0 -146
- package/scripts/prepare-niubash-packages.mjs +0 -182
- package/scripts/run-test-file.mjs +0 -34
- package/scripts/smoke-managed-niubash.mjs +0 -62
- package/scripts/verify-release-config.mjs +0 -24
- package/src/app/api/swarm/[id]/route.ts +0 -28
- package/src/app/api/swarm/route.ts +0 -24
- package/src/app/api/tests/route.ts +0 -27
- package/src/components/SwarmCoordinatorPod.tsx +0 -1021
- package/src/components/TestInspectorPod.tsx +0 -549
- package/src/lib/delegation.ts +0 -93
- package/src/lib/growth-rounds.ts +0 -84
- package/src/lib/managed-niubash.ts +0 -231
- package/src/lib/runtime-activity.ts +0 -27
- package/src/lib/session-import/lock.ts +0 -25
- package/src/lib/swarm-service.ts +0 -371
- package/src/lib/test-run-service.ts +0 -122
- package/src/lib/workflow.ts +0 -55
- /package/.next/static/{0t1jBUAuVaTFTXxRyIo3q → zsynuO_9Kx6nrXgkTUJ04}/_ssgManifest.js +0 -0
package/src/lib/agent-manager.ts
CHANGED
|
@@ -33,18 +33,14 @@ import { TrajLedger, buildTrajectoryFromEntries, toTrajTokens } from "./trajecto
|
|
|
33
33
|
import { startArchivedSessionRetention } from "./session-retention";
|
|
34
34
|
import { sanitizeToolOutput } from "./text-sanitize";
|
|
35
35
|
import { BoundaryError } from "./path-security";
|
|
36
|
-
import { beginActivity } from "./runtime-activity";
|
|
37
36
|
import { estimateTokensOf } from "./process-format";
|
|
38
37
|
import { getPiSettings } from "./pi-settings";
|
|
39
|
-
import { createManagedNiubashTools } from "./managed-niubash";
|
|
40
|
-
import { createDelegationTool } from "./delegation";
|
|
41
|
-
import { awaitingGoalMessage, isWorkflowMode, planCanRun, readWorkflow, saveWorkflow, workflowInstruction, type WorkflowState } from "./workflow";
|
|
42
38
|
import { clampThinkingLevel, getSupportedThinkingLevels } from "@earendil-works/pi-ai";
|
|
43
39
|
import type {
|
|
44
40
|
AgentCommand,
|
|
45
41
|
ContextBreakdown,
|
|
46
42
|
ContextResource,
|
|
47
|
-
|
|
43
|
+
GrowthRound,
|
|
48
44
|
TrajEntry,
|
|
49
45
|
ToolPreset,
|
|
50
46
|
WebEvent,
|
|
@@ -69,7 +65,6 @@ interface Managed {
|
|
|
69
65
|
ledger: TrajLedger;
|
|
70
66
|
lastActive: number;
|
|
71
67
|
toolPreset: ToolPreset;
|
|
72
|
-
workflow: WorkflowState;
|
|
73
68
|
/** 显式逐项选择优先于 preset;保留失效名称以便资源重新启用后恢复用户选择。 */
|
|
74
69
|
customActiveTools?: string[];
|
|
75
70
|
resourceVersion: number;
|
|
@@ -531,20 +526,6 @@ function translate(m: Managed, evt: AgentSessionEvent): void {
|
|
|
531
526
|
break;
|
|
532
527
|
case "agent_settled":
|
|
533
528
|
m.runActive = false;
|
|
534
|
-
if (m.workflow.mode === "plan") {
|
|
535
|
-
if (m.workflow.planStatus === "planning") {
|
|
536
|
-
const answer = [...(m.session?.messages ?? [])].reverse().find((message) => message.role === "assistant");
|
|
537
|
-
const ready = answer?.role === "assistant" && answer.stopReason === "stop" && answer.content.some((part) => part.type === "text" && part.text.trim());
|
|
538
|
-
const entry = ready ? m.sm.getBranch().slice().reverse().find((item) => item.type === "message" && item.message.role === "assistant" && item.message.stopReason === "stop") : undefined;
|
|
539
|
-
setWorkflow(m, { ...m.workflow, planStatus: entry ? "ready" : "idle", planId: entry?.id });
|
|
540
|
-
} else if (m.workflow.planStatus === "executing") {
|
|
541
|
-
// 执行报错或被中止时方案仍待执行:以当前叶节点为新的批准锚点,可以直接再次执行。
|
|
542
|
-
const answer = [...(m.session?.messages ?? [])].reverse().find((message) => message.role === "assistant");
|
|
543
|
-
const failed = answer?.role === "assistant" && (answer.stopReason === "error" || answer.stopReason === "aborted");
|
|
544
|
-
const anchor = failed ? m.sm.getLeafId() : null;
|
|
545
|
-
setWorkflow(m, anchor ? { ...m.workflow, planStatus: "ready", planId: anchor } : { ...m.workflow, planStatus: "idle", planId: undefined });
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
529
|
publish(m, { type: "status", isStreaming: false, state: "idle", ts: now });
|
|
549
530
|
publishUsage(m);
|
|
550
531
|
if (m.resourceReloadPending) queueMicrotask(() => void reloadManagedResources(m));
|
|
@@ -606,13 +587,18 @@ function growthOf(m: Managed): GrowthTracker {
|
|
|
606
587
|
m.growth.dispose();
|
|
607
588
|
m.growth = null;
|
|
608
589
|
}
|
|
609
|
-
return (m.growth ??= createGrowthTracker({
|
|
590
|
+
return (m.growth ??= createGrowthTracker({
|
|
591
|
+
cwd: m.cwd,
|
|
592
|
+
sessionPath: m.sessionPath,
|
|
593
|
+
publish: (evt) => publish(m, evt),
|
|
594
|
+
entries: () => m.sm.getEntries() as never,
|
|
595
|
+
}));
|
|
610
596
|
}
|
|
611
597
|
|
|
612
|
-
/**
|
|
613
|
-
export async function
|
|
598
|
+
/** 立即记录(项目栏按钮):把当前改动提交为「你的修改」,同时广播给本会话的订阅者 */
|
|
599
|
+
export async function growthRecord(m: Managed): Promise<GrowthRound | null> {
|
|
614
600
|
touch(m);
|
|
615
|
-
return growthOf(m).
|
|
601
|
+
return growthOf(m).recordNow();
|
|
616
602
|
}
|
|
617
603
|
|
|
618
604
|
// ---------- 会话生命周期 ----------
|
|
@@ -654,7 +640,6 @@ function registerManaged(sessionPath: string, cwd: string, sm: SessionManager):
|
|
|
654
640
|
ledger: new TrajLedger(initialTrajectory),
|
|
655
641
|
lastActive: Date.now(),
|
|
656
642
|
toolPreset: "readonly",
|
|
657
|
-
workflow: readWorkflow(sm),
|
|
658
643
|
resourceVersion: 0,
|
|
659
644
|
resourceReloadPending: false,
|
|
660
645
|
resourceReloading: false,
|
|
@@ -803,33 +788,12 @@ function publishEnvironmentTrajectory(m: Managed, session: AgentSession): void {
|
|
|
803
788
|
}
|
|
804
789
|
|
|
805
790
|
export async function ensureSession(m: Managed): Promise<AgentSession> {
|
|
806
|
-
const release = beginActivity("session");
|
|
807
|
-
try { return await ensureSessionActive(m); }
|
|
808
|
-
finally { release(); }
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
async function ensureSessionActive(m: Managed): Promise<AgentSession> {
|
|
812
791
|
if (m.disposed) throw new Error("session is disposed");
|
|
813
792
|
if (m.creating) return m.creating;
|
|
814
793
|
if (m.session) return m.session;
|
|
815
794
|
m.creating = (async () => {
|
|
816
795
|
await resourceLoaderReady(m.cwd);
|
|
817
|
-
const loader = await createSessionResourceLoader(m.cwd
|
|
818
|
-
name: "piweb-workflow",
|
|
819
|
-
hidden: true,
|
|
820
|
-
factory: (pi) => {
|
|
821
|
-
pi.on("before_agent_start", (event) => {
|
|
822
|
-
const instruction = workflowInstruction(m.workflow);
|
|
823
|
-
if (instruction) {
|
|
824
|
-
if (event.systemPromptOptions.forceSystemPrompt !== undefined) event.systemPromptOptions.forceSystemPrompt += `\n\n${instruction}`;
|
|
825
|
-
else event.systemPromptOptions.sections.piweb_workflow = instruction;
|
|
826
|
-
} else delete event.systemPromptOptions.sections.piweb_workflow;
|
|
827
|
-
if (m.workflow.mode === "plan" && m.workflow.planStatus !== "executing") {
|
|
828
|
-
event.systemPromptOptions.selectedTools = event.systemPromptOptions.selectedTools.filter((name) => [...TOOL_PRESETS.readonly, "piweb_delegate"].includes(name));
|
|
829
|
-
}
|
|
830
|
-
});
|
|
831
|
-
},
|
|
832
|
-
}]);
|
|
796
|
+
const loader = await createSessionResourceLoader(m.cwd);
|
|
833
797
|
let created: AgentSession | undefined;
|
|
834
798
|
try {
|
|
835
799
|
if (m.disposed) throw new Error("session is disposed");
|
|
@@ -840,8 +804,6 @@ async function ensureSessionActive(m: Managed): Promise<AgentSession> {
|
|
|
840
804
|
modelRuntime: await getModelRuntime(),
|
|
841
805
|
resourceLoader: loader,
|
|
842
806
|
settingsManager: getSettingsManager(m.cwd),
|
|
843
|
-
// Windows: 同名 bash 覆盖 SDK 内置工具,指向托管 niubash;其它平台返回 [],走 Pi 默认。
|
|
844
|
-
customTools: [...createManagedNiubashTools(m.cwd), createDelegationTool(m.cwd, () => m.session)],
|
|
845
807
|
});
|
|
846
808
|
created = session;
|
|
847
809
|
if (m.disposed) throw new Error("session is disposed");
|
|
@@ -888,9 +850,7 @@ function isManagedBusy(m: Managed): boolean {
|
|
|
888
850
|
|
|
889
851
|
function allowedToolNames(m: Managed, session: AgentSession): string[] {
|
|
890
852
|
const allowed = m.customActiveTools ?? (m.toolPreset === "full" ? undefined : TOOL_PRESETS[m.toolPreset]);
|
|
891
|
-
|
|
892
|
-
const planning = m.workflow.mode === "plan" && m.workflow.planStatus !== "executing";
|
|
893
|
-
return listAllToolNames(session).filter((name) => (!effective || effective.includes(name)) && (!planning || [...TOOL_PRESETS.readonly, "piweb_delegate"].includes(name)));
|
|
853
|
+
return listAllToolNames(session).filter((name) => !allowed || allowed.includes(name));
|
|
894
854
|
}
|
|
895
855
|
|
|
896
856
|
function applyToolPolicy(m: Managed, session: AgentSession): void {
|
|
@@ -901,20 +861,6 @@ function publishTools(m: Managed, session: AgentSession): void {
|
|
|
901
861
|
publish(m, { type: "tools", active: listActiveTools(session), all: listAllToolNames(session), toolPreset: m.toolPreset, customActiveTools: m.customActiveTools ?? null, ts: Date.now() });
|
|
902
862
|
}
|
|
903
863
|
|
|
904
|
-
function setWorkflow(m: Managed, next: WorkflowState): void {
|
|
905
|
-
saveWorkflow(m.sm, next);
|
|
906
|
-
m.workflow = next;
|
|
907
|
-
publishWorkflow(m);
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
function publishWorkflow(m: Managed): void {
|
|
911
|
-
if (m.session && !m.disposed) {
|
|
912
|
-
applyToolPolicy(m, m.session);
|
|
913
|
-
publishTools(m, m.session);
|
|
914
|
-
}
|
|
915
|
-
publish(m, { type: "workflow", workflow: m.workflow, ts: Date.now() });
|
|
916
|
-
}
|
|
917
|
-
|
|
918
864
|
/** SDK reload 自动启用扩展工具,注册新工具也会刷新全集;统一在激活边界收敛到服务端选择。 */
|
|
919
865
|
function installSessionPolicy(m: Managed, session: AgentSession): void {
|
|
920
866
|
const setActive = session.setActiveToolsByName.bind(session);
|
|
@@ -1230,12 +1176,12 @@ export async function buildSnapshot(m: Managed): Promise<WebSnapshot> {
|
|
|
1230
1176
|
}
|
|
1231
1177
|
for (let i = messages.length - 1; i >= 0 && !compactedSinceLastAssistant; i--) {
|
|
1232
1178
|
const msg = messages[i];
|
|
1233
|
-
if (msg.role === "assistant" && msg.usage
|
|
1234
|
-
lastTurnTokens =
|
|
1179
|
+
if (msg.role === "assistant" && msg.usage) {
|
|
1180
|
+
lastTurnTokens =
|
|
1235
1181
|
Number(msg.usage.input ?? 0) +
|
|
1236
1182
|
Number(msg.usage.cacheRead ?? 0) +
|
|
1237
1183
|
Number(msg.usage.cacheWrite ?? 0) +
|
|
1238
|
-
Number(msg.usage.output ?? 0)
|
|
1184
|
+
Number(msg.usage.output ?? 0);
|
|
1239
1185
|
break;
|
|
1240
1186
|
}
|
|
1241
1187
|
}
|
|
@@ -1300,7 +1246,6 @@ export async function buildSnapshot(m: Managed): Promise<WebSnapshot> {
|
|
|
1300
1246
|
thinkingLevel,
|
|
1301
1247
|
thinkingLevels,
|
|
1302
1248
|
toolPreset: m.toolPreset,
|
|
1303
|
-
workflow: m.workflow,
|
|
1304
1249
|
customActiveTools: m.customActiveTools ?? null,
|
|
1305
1250
|
extensionUiRequests: m.ui?.getPendingRequests() ?? [],
|
|
1306
1251
|
tools,
|
|
@@ -1354,52 +1299,12 @@ export interface CommandResult {
|
|
|
1354
1299
|
}
|
|
1355
1300
|
|
|
1356
1301
|
export async function execute(m: Managed, cmd: AgentCommand): Promise<CommandResult> {
|
|
1357
|
-
let release: (() => void) | undefined;
|
|
1358
|
-
try {
|
|
1359
|
-
if (!["abort", "clearQueue", "extensionUiResponse"].includes(cmd.cmd)) release = beginActivity("session");
|
|
1360
|
-
return await executeCommand(m, cmd);
|
|
1361
|
-
} catch (error) {
|
|
1362
|
-
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
1363
|
-
} finally {
|
|
1364
|
-
release?.();
|
|
1365
|
-
}
|
|
1366
|
-
}
|
|
1367
|
-
|
|
1368
|
-
function trackedPrompt(session: AgentSession, ...args: Parameters<AgentSession["prompt"]>): ReturnType<AgentSession["prompt"]> {
|
|
1369
|
-
const release = beginActivity("session");
|
|
1370
|
-
try { return session.prompt(...args).finally(release); }
|
|
1371
|
-
catch (error) { release(); throw error; }
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
async function executeCommand(m: Managed, cmd: AgentCommand): Promise<CommandResult> {
|
|
1375
1302
|
touch(m);
|
|
1376
1303
|
try {
|
|
1377
1304
|
switch (cmd.cmd) {
|
|
1378
1305
|
case "prepare":
|
|
1379
1306
|
await ensureSession(m);
|
|
1380
1307
|
return { ok: true };
|
|
1381
|
-
case "setWorkflowMode": {
|
|
1382
|
-
if (!isWorkflowMode(cmd.mode)) return { ok: false, error: "invalid workflow mode" };
|
|
1383
|
-
if (isManagedBusy(m)) return { ok: false, error: "cannot change workflow while the agent is running" };
|
|
1384
|
-
// 重选当前模式不重置:否则会清掉 Goal 目标或待执行的方案,并多写一条记录。
|
|
1385
|
-
if (cmd.mode === m.workflow.mode) return { ok: true };
|
|
1386
|
-
setWorkflow(m, { mode: cmd.mode, planStatus: "idle", goal: "" });
|
|
1387
|
-
return { ok: true };
|
|
1388
|
-
}
|
|
1389
|
-
case "approvePlan": {
|
|
1390
|
-
if (!planCanRun(m.workflow)) return { ok: false, error: "there is no plan awaiting approval" };
|
|
1391
|
-
if (isManagedBusy(m)) return { ok: false, error: "session is busy" };
|
|
1392
|
-
const branch = m.sm.getBranch();
|
|
1393
|
-
const planIndex = branch.findIndex((entry) => entry.id === m.workflow.planId);
|
|
1394
|
-
if (planIndex < 0 || branch.slice(planIndex + 1).some((entry) => entry.type === "message")) {
|
|
1395
|
-
return { ok: false, error: "the plan is no longer the latest conversation; request a new plan" };
|
|
1396
|
-
}
|
|
1397
|
-
const ready = m.workflow;
|
|
1398
|
-
setWorkflow(m, { ...ready, planStatus: "executing" });
|
|
1399
|
-
const result = await execute(m, { cmd: "prompt", text: "Execute the plan you just proposed. Verify the changes and report any unfinished work." });
|
|
1400
|
-
if (!result.ok) setWorkflow(m, ready);
|
|
1401
|
-
return result;
|
|
1402
|
-
}
|
|
1403
1308
|
case "prompt": {
|
|
1404
1309
|
const text = (cmd.text ?? "").trim();
|
|
1405
1310
|
if (!text && !cmd.images?.length) return { ok: false, error: "empty prompt" };
|
|
@@ -1411,7 +1316,6 @@ async function executeCommand(m: Managed, cmd: AgentCommand): Promise<CommandRes
|
|
|
1411
1316
|
if (m.disposed) throw new Error("session is disposed");
|
|
1412
1317
|
// 只有用户显式选择 steer/followUp 才排队;旧的普通提交不能悄悄成为 steering。
|
|
1413
1318
|
if ((session.isStreaming || m.runActive) && !cmd.behavior) return { ok: false, error: "session is busy; choose steer or followUp" };
|
|
1414
|
-
if (m.workflow.mode === "plan" && (session.isStreaming || m.runActive)) return { ok: false, error: "wait for the current plan or execution to finish" };
|
|
1415
1319
|
if (!session.isStreaming) {
|
|
1416
1320
|
// 基线快照不能无限阻塞首条 prompt(git 不可用时每次探测至多 30s 超时):
|
|
1417
1321
|
// 5s 内没完成就放行 prompt,快照后台补拍(工具结束后照常记步,外部修改兜底)。
|
|
@@ -1421,18 +1325,11 @@ async function executeCommand(m: Managed, cmd: AgentCommand): Promise<CommandRes
|
|
|
1421
1325
|
]);
|
|
1422
1326
|
}
|
|
1423
1327
|
if (m.disposed) throw new Error("session is disposed");
|
|
1424
|
-
|
|
1425
|
-
if (m.workflow.mode === "plan" && m.workflow.planStatus !== "executing") {
|
|
1426
|
-
setWorkflow(m, { ...m.workflow, planStatus: "planning", planId: undefined });
|
|
1427
|
-
} else if (m.workflow.mode === "goal" && !m.workflow.goal && text) {
|
|
1428
|
-
setWorkflow(m, { ...m.workflow, goal: text.slice(0, 8_000) });
|
|
1429
|
-
}
|
|
1430
|
-
const result = await new Promise<CommandResult>((resolve) => {
|
|
1328
|
+
return await new Promise<CommandResult>((resolve) => {
|
|
1431
1329
|
let accepted = false;
|
|
1432
|
-
const run =
|
|
1330
|
+
const run = session.prompt(text, {
|
|
1433
1331
|
images: cmd.images,
|
|
1434
1332
|
streamingBehavior: cmd.behavior,
|
|
1435
|
-
expandPromptTemplates: m.workflow.mode !== "plan" || m.workflow.planStatus === "executing",
|
|
1436
1333
|
source: "rpc",
|
|
1437
1334
|
preflightResult: (success) => {
|
|
1438
1335
|
if (success) {
|
|
@@ -1449,9 +1346,7 @@ async function executeCommand(m: Managed, cmd: AgentCommand): Promise<CommandRes
|
|
|
1449
1346
|
if (accepted) publish(m, { type: "error", message, ts: Date.now() });
|
|
1450
1347
|
else resolve({ ok: false, error: message });
|
|
1451
1348
|
});
|
|
1452
|
-
|
|
1453
|
-
if (!result.ok && m.workflow !== previousWorkflow) setWorkflow(m, previousWorkflow);
|
|
1454
|
-
return result;
|
|
1349
|
+
});
|
|
1455
1350
|
} finally {
|
|
1456
1351
|
m.promptSubmitting = false;
|
|
1457
1352
|
if (!m.disposed) publish(m, { type: "status", isStreaming: isManagedBusy(m), state: isManagedBusy(m) ? "running" : "idle", ts: Date.now() });
|
|
@@ -1460,7 +1355,6 @@ async function executeCommand(m: Managed, cmd: AgentCommand): Promise<CommandRes
|
|
|
1460
1355
|
}
|
|
1461
1356
|
case "steer":
|
|
1462
1357
|
case "followUp": {
|
|
1463
|
-
if (m.workflow.mode === "plan") return { ok: false, error: "Plan mode does not queue prompts" };
|
|
1464
1358
|
if (m.promptSubmitting || m.resourceReloading) return { ok: false, error: "session is busy accepting another command" };
|
|
1465
1359
|
const session = await ensureSession(m);
|
|
1466
1360
|
if (m.promptSubmitting || m.resourceReloading || !session.isStreaming) return { ok: false, error: "session is not accepting queued messages" };
|
|
@@ -1549,10 +1443,6 @@ async function executeCommand(m: Managed, cmd: AgentCommand): Promise<CommandRes
|
|
|
1549
1443
|
const entryId = String((cmd as any).entryId ?? "");
|
|
1550
1444
|
if (!entryId) return { ok: false, error: "missing entryId" };
|
|
1551
1445
|
const r = await session.navigateTree(entryId);
|
|
1552
|
-
if (!r?.cancelled) {
|
|
1553
|
-
m.workflow = readWorkflow(m.sm);
|
|
1554
|
-
publishWorkflow(m);
|
|
1555
|
-
}
|
|
1556
1446
|
return { ok: !r?.cancelled, data: { cancelled: r?.cancelled === true, editorText: r?.editorText } };
|
|
1557
1447
|
}
|
|
1558
1448
|
case "editAndResend": {
|
|
@@ -1562,9 +1452,6 @@ async function executeCommand(m: Managed, cmd: AgentCommand): Promise<CommandRes
|
|
|
1562
1452
|
const text = (cmd.text ?? "").trim();
|
|
1563
1453
|
if (!entryId) return { ok: false, error: "missing entryId" };
|
|
1564
1454
|
if (!text) return { ok: false, error: "empty prompt" };
|
|
1565
|
-
const target = m.sm.getEntry(entryId);
|
|
1566
|
-
if (target?.type !== "message" || target.message.role !== "user") return { ok: false, error: "message is not editable" };
|
|
1567
|
-
const images = Array.isArray(target.message.content) ? target.message.content.filter((part) => part.type === "image") : [];
|
|
1568
1455
|
if (m.promptSubmitting || m.resourceReloading) return { ok: false, error: "session is busy accepting another command" };
|
|
1569
1456
|
m.promptSubmitting = true;
|
|
1570
1457
|
try {
|
|
@@ -1578,64 +1465,11 @@ async function executeCommand(m: Managed, cmd: AgentCommand): Promise<CommandRes
|
|
|
1578
1465
|
}
|
|
1579
1466
|
}
|
|
1580
1467
|
if (m.disposed) throw new Error("session is disposed");
|
|
1581
|
-
|
|
1582
|
-
const originalLeafId = m.sm.getLeafId();
|
|
1583
|
-
const leafWasTarget = originalLeafId === entryId;
|
|
1584
|
-
if (leafWasTarget) {
|
|
1585
|
-
if (target.parentId) m.sm.branch(target.parentId);
|
|
1586
|
-
else m.sm.resetLeaf();
|
|
1587
|
-
}
|
|
1588
|
-
let moved;
|
|
1589
|
-
try {
|
|
1590
|
-
moved = await session.navigateTree(entryId);
|
|
1591
|
-
} catch (error) {
|
|
1592
|
-
if (leafWasTarget) m.sm.branch(entryId);
|
|
1593
|
-
throw error;
|
|
1594
|
-
}
|
|
1595
|
-
if (moved?.cancelled && leafWasTarget) m.sm.branch(entryId);
|
|
1468
|
+
const moved = await session.navigateTree(entryId);
|
|
1596
1469
|
if (moved?.cancelled) return { ok: false, error: "edit cancelled" };
|
|
1597
|
-
m.workflow = readWorkflow(m.sm);
|
|
1598
|
-
publishWorkflow(m);
|
|
1599
1470
|
await growthOf(m).prepare().catch(() => undefined);
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
// 编辑的正是定下目标的那条消息时,目标跟着改;旧目标记录是它的祖先,回退分支不会带走它。
|
|
1603
|
-
else if (m.workflow.mode === "goal" && awaitingGoalMessage(m.sm) && m.workflow.goal !== text.slice(0, 8_000)) {
|
|
1604
|
-
setWorkflow(m, { ...m.workflow, goal: text.slice(0, 8_000) });
|
|
1605
|
-
}
|
|
1606
|
-
const options = { images, expandPromptTemplates: m.workflow.mode !== "plan" };
|
|
1607
|
-
return await new Promise<CommandResult>((resolve) => {
|
|
1608
|
-
let accepted = false;
|
|
1609
|
-
const run = trackedPrompt(session, text, {
|
|
1610
|
-
...options,
|
|
1611
|
-
preflightResult: (success) => {
|
|
1612
|
-
if (success) {
|
|
1613
|
-
accepted = true;
|
|
1614
|
-
resolve({ ok: true, data: { accepted: true } });
|
|
1615
|
-
}
|
|
1616
|
-
},
|
|
1617
|
-
});
|
|
1618
|
-
void run.then(() => {
|
|
1619
|
-
if (!accepted) resolve({ ok: true });
|
|
1620
|
-
}, (error) => {
|
|
1621
|
-
const message = String(error?.message ?? error);
|
|
1622
|
-
if (accepted) {
|
|
1623
|
-
publish(m, { type: "error", message, ts: Date.now() });
|
|
1624
|
-
return;
|
|
1625
|
-
}
|
|
1626
|
-
// Rejected preflight never wrote the edited turn; restore the old branch before the client resyncs.
|
|
1627
|
-
try {
|
|
1628
|
-
if (originalLeafId) m.sm.branch(originalLeafId);
|
|
1629
|
-
else m.sm.resetLeaf();
|
|
1630
|
-
session.refreshContext();
|
|
1631
|
-
m.workflow = readWorkflow(m.sm);
|
|
1632
|
-
publishWorkflow(m);
|
|
1633
|
-
} catch {
|
|
1634
|
-
if (m.workflow !== previousWorkflow) setWorkflow(m, previousWorkflow);
|
|
1635
|
-
}
|
|
1636
|
-
resolve({ ok: false, error: message });
|
|
1637
|
-
});
|
|
1638
|
-
});
|
|
1471
|
+
await session.prompt(text);
|
|
1472
|
+
return { ok: true };
|
|
1639
1473
|
} finally {
|
|
1640
1474
|
m.promptSubmitting = false;
|
|
1641
1475
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentCommand, ImageAttachment, ToolPreset
|
|
1
|
+
import type { AgentCommand, ImageAttachment, ToolPreset } from "./types";
|
|
2
2
|
|
|
3
3
|
const COMMANDS = new Set<AgentCommand["cmd"]>([
|
|
4
4
|
"prepare",
|
|
@@ -10,8 +10,6 @@ const COMMANDS = new Set<AgentCommand["cmd"]>([
|
|
|
10
10
|
"setModel",
|
|
11
11
|
"setThinkingLevel",
|
|
12
12
|
"setToolPreset",
|
|
13
|
-
"setWorkflowMode",
|
|
14
|
-
"approvePlan",
|
|
15
13
|
"setActiveTools",
|
|
16
14
|
"rename",
|
|
17
15
|
"fork",
|
|
@@ -23,7 +21,6 @@ const COMMANDS = new Set<AgentCommand["cmd"]>([
|
|
|
23
21
|
"reload",
|
|
24
22
|
]);
|
|
25
23
|
const TOOL_PRESETS = new Set<ToolPreset>(["readonly", "standard", "full"]);
|
|
26
|
-
const WORKFLOW_MODES = new Set<WorkflowMode>(["agent", "plan", "goal"]);
|
|
27
24
|
const STREAMING_BEHAVIORS = new Set(["steer", "followUp"]);
|
|
28
25
|
const IMAGE_TYPES = new Set(["image/jpeg", "image/png", "image/webp", "image/gif"]);
|
|
29
26
|
const MAX_TEXT = 1_000_000;
|
|
@@ -81,10 +78,6 @@ export function parseAgentCommand(value: unknown): CommandParseResult {
|
|
|
81
78
|
if (typeof raw.preset !== "string" || !TOOL_PRESETS.has(raw.preset as ToolPreset)) throw new Error("invalid tool preset");
|
|
82
79
|
command.preset = raw.preset as ToolPreset;
|
|
83
80
|
}
|
|
84
|
-
if (raw.mode !== undefined) {
|
|
85
|
-
if (typeof raw.mode !== "string" || !WORKFLOW_MODES.has(raw.mode as WorkflowMode)) throw new Error("invalid workflow mode");
|
|
86
|
-
command.mode = raw.mode as WorkflowMode;
|
|
87
|
-
}
|
|
88
81
|
if (raw.behavior !== undefined) {
|
|
89
82
|
if (typeof raw.behavior !== "string" || !STREAMING_BEHAVIORS.has(raw.behavior)) throw new Error("invalid streaming behavior");
|
|
90
83
|
command.behavior = raw.behavior as "steer" | "followUp";
|
|
@@ -115,7 +108,6 @@ export function parseAgentCommand(value: unknown): CommandParseResult {
|
|
|
115
108
|
if (command.cmd === "setModel" && (!command.provider || !command.modelId)) throw new Error("provider and modelId are required");
|
|
116
109
|
if (command.cmd === "setThinkingLevel" && !command.level) throw new Error("level is required");
|
|
117
110
|
if (command.cmd === "setToolPreset" && !command.preset) throw new Error("preset is required");
|
|
118
|
-
if (command.cmd === "setWorkflowMode" && !command.mode) throw new Error("mode is required");
|
|
119
111
|
if (command.cmd === "setActiveTools" && !command.names) throw new Error("names are required");
|
|
120
112
|
if (command.cmd === "navigate" && !command.entryId) throw new Error("entryId is required");
|
|
121
113
|
return { ok: true, command };
|