@chainingintention/pi-web-cn 1.202606.12 → 1.202606.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/client/assets/{CodeViewer-BKljKDuK.js → CodeViewer-D5OA_6r4.js} +1 -1
- package/dist/client/assets/{TerminalPanel-DeDTQWls.js → TerminalPanel-kfPHfhUe.js} +9 -9
- package/dist/client/assets/{index-BuVYTYo8.js → index-MmspRbMF.js} +358 -270
- package/dist/client/index.html +1 -1
- package/dist/config.js +26 -0
- package/dist/config.js.map +1 -1
- package/dist/pi-web-plugins/updates/pi-web-plugin.js +58 -1
- package/dist/pi-web-plugins/updates/updatesLogic.js +13 -13
- package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +1 -5
- package/dist/server/configRoutes.js +10 -0
- package/dist/server/configRoutes.js.map +1 -1
- package/dist/server/managementEmbed.js +6 -1
- package/dist/server/managementEmbed.js.map +1 -1
- package/dist/server/sessiond.js +15 -2
- package/dist/server/sessiond.js.map +1 -1
- package/dist/server/sessions/attachmentService.js +2 -2
- package/dist/server/sessions/attachmentService.js.map +1 -1
- package/dist/server/sessions/builtinCommands.js +21 -21
- package/dist/server/sessions/builtinCommands.js.map +1 -1
- package/dist/server/sessions/oauthLoginFlowService.js +15 -15
- package/dist/server/sessions/oauthLoginFlowService.js.map +1 -1
- package/dist/server/sessions/piSessionService.js +71 -33
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/sessionCommandService.js +32 -28
- package/dist/server/sessions/sessionCommandService.js.map +1 -1
- package/dist/server/sessions/sessionRoutes.js +2 -2
- package/dist/server/sessions/sessionRoutes.js.map +1 -1
- package/dist/server/sessions/spawnSessionTool.js +36 -0
- package/dist/server/sessions/spawnSessionTool.js.map +1 -0
- package/dist/server/sessions/spawnTargetResolver.js +36 -0
- package/dist/server/sessions/spawnTargetResolver.js.map +1 -0
- package/dist/shared/apiTypes.d.ts +7 -1
- package/docs/plugins.md +3 -3
- package/package.json +2 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
const SpawnSessionParams = Type.Object({
|
|
4
|
+
prompt: Type.String({
|
|
5
|
+
description: "发送给新建会话的第一条指令。新会话会独立运行;你不会收到它的输出。",
|
|
6
|
+
}),
|
|
7
|
+
cwd: Type.Optional(Type.String({
|
|
8
|
+
description: "新会话的工作目录。必须是与当前会话同一项目下的工作区(worktree 或根目录)。默认使用当前会话的工作目录。",
|
|
9
|
+
})),
|
|
10
|
+
});
|
|
11
|
+
/**
|
|
12
|
+
* Custom tool that lets the LLM start a new, independent pi-web session and
|
|
13
|
+
* deliver an initial prompt to it. The spawned session is a normal pi-web session
|
|
14
|
+
* a human can open and interact with. The tool is constructed per-session, so it
|
|
15
|
+
* carries the spawning session's cwd for project-scope validation.
|
|
16
|
+
*/
|
|
17
|
+
export function createSpawnSessionToolDefinition(spawningCwd, deps) {
|
|
18
|
+
return defineTool({
|
|
19
|
+
name: "spawn_session",
|
|
20
|
+
label: "派生会话",
|
|
21
|
+
description: "启动一个新的独立 pi-web 会话,并发送初始提示。可用于派遣新的代理继续工作或执行计划。新会话会自行运行,人类可以打开并交互;你不会收到它的输出。",
|
|
22
|
+
promptSnippet: "spawn_session:使用第一条提示启动新的独立会话",
|
|
23
|
+
parameters: SpawnSessionParams,
|
|
24
|
+
async execute(_toolCallId, params) {
|
|
25
|
+
// Failures throw: the agent loop turns the thrown message into an error
|
|
26
|
+
// tool result the model sees, so the spawning agent can adapt (e.g. pick a
|
|
27
|
+
// valid workspace) rather than crash.
|
|
28
|
+
const result = await deps.spawn({ spawningCwd, prompt: params.prompt, cwd: params.cwd });
|
|
29
|
+
return {
|
|
30
|
+
content: [{ type: "text", text: `已在 ${result.cwd} 启动会话 ${result.sessionId}。` }],
|
|
31
|
+
details: result,
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=spawnSessionTool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawnSessionTool.js","sourceRoot":"","sources":["../../../src/server/sessions/spawnSessionTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAmB7D,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC;IACrC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;QAClB,WAAW,EAAE,mCAAmC;KACjD,CAAC;IACF,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAC7B,WAAW,EAAE,0DAA0D;KACxE,CAAC,CAAC;CACJ,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,UAAU,gCAAgC,CAAC,WAAmB,EAAE,IAA0B;IAC9F,OAAO,UAAU,CAAqD;QACpE,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,MAAM;QACb,WAAW,EAAE,6EAA6E;QAC1F,aAAa,EAAE,+BAA+B;QAC9C,UAAU,EAAE,kBAAkB;QAC9B,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM;YAC/B,wEAAwE;YACxE,2EAA2E;YAC3E,sCAAsC;YACtC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;YACzF,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC,GAAG,SAAS,MAAM,CAAC,SAAS,GAAG,EAAE,CAAC;gBAC/E,OAAO,EAAE,MAAM;aAChB,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { cwdPathsEqual } from "../workingDirectory.js";
|
|
2
|
+
/**
|
|
3
|
+
* Default resolver composing the project registry and live worktree discovery.
|
|
4
|
+
* It finds the registered project whose current workspace set contains the
|
|
5
|
+
* spawning session's cwd, then validates the requested target against that set.
|
|
6
|
+
*/
|
|
7
|
+
export class ProjectScopedSpawnTargetResolver {
|
|
8
|
+
constructor(deps) {
|
|
9
|
+
this.deps = deps;
|
|
10
|
+
}
|
|
11
|
+
async resolveSpawnTarget(spawningCwd, requestedCwd) {
|
|
12
|
+
const allowedCwds = await this.allowedSpawnTargets(spawningCwd);
|
|
13
|
+
if (allowedCwds === undefined)
|
|
14
|
+
return { allowed: false, reason: "not-registered" };
|
|
15
|
+
const target = requestedCwd === undefined || requestedCwd === "" ? spawningCwd : requestedCwd;
|
|
16
|
+
const match = allowedCwds.find((path) => cwdPathsEqual(path, target));
|
|
17
|
+
if (match === undefined)
|
|
18
|
+
return { allowed: false, reason: "out-of-project", allowedCwds };
|
|
19
|
+
return { allowed: true, cwd: match };
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Workspace paths of the registered project that owns `spawningCwd`, or
|
|
23
|
+
* `undefined` when no registered project contains it.
|
|
24
|
+
*/
|
|
25
|
+
async allowedSpawnTargets(spawningCwd) {
|
|
26
|
+
const projects = await this.deps.projects.list();
|
|
27
|
+
for (const project of projects) {
|
|
28
|
+
const workspaces = await this.deps.workspaces.list(project);
|
|
29
|
+
const paths = workspaces.map((workspace) => workspace.path);
|
|
30
|
+
if (paths.some((path) => cwdPathsEqual(path, spawningCwd)))
|
|
31
|
+
return paths;
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=spawnTargetResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawnTargetResolver.js","sourceRoot":"","sources":["../../../src/server/sessions/spawnTargetResolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AA+CvD;;;;GAIG;AACH,MAAM,OAAO,gCAAgC;IAC3C,YAA6B,IAA0C;QAA1C,SAAI,GAAJ,IAAI,CAAsC;IAAG,CAAC;IAE3E,KAAK,CAAC,kBAAkB,CAAC,WAAmB,EAAE,YAAgC;QAC5E,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAChE,IAAI,WAAW,KAAK,SAAS;YAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QACnF,MAAM,MAAM,GAAG,YAAY,KAAK,SAAS,IAAI,YAAY,KAAK,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC;QAC9F,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QACtE,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC;QAC1F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IACvC,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,mBAAmB,CAAC,WAAmB;QACnD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACjD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5D,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC5D,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;gBAAE,OAAO,KAAK,CAAC;QAC3E,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF"}
|
|
@@ -52,6 +52,8 @@ export interface PiWebConfigValues {
|
|
|
52
52
|
managementEmbed?: PiWebManagementEmbedConfig;
|
|
53
53
|
/** Maximum accepted HTTP request body size in bytes (uploads/attachments). */
|
|
54
54
|
maxUploadBytes?: number;
|
|
55
|
+
/** When true, LLMs can start new sessions via the spawn_session tool. */
|
|
56
|
+
spawnSessions?: boolean;
|
|
55
57
|
}
|
|
56
58
|
export interface PiWebManagementEmbedConfig {
|
|
57
59
|
enabled?: boolean;
|
|
@@ -87,6 +89,7 @@ export interface PiWebConfigEnvOverrides {
|
|
|
87
89
|
host: boolean;
|
|
88
90
|
port: boolean;
|
|
89
91
|
allowedHosts: boolean;
|
|
92
|
+
spawnSessions: boolean;
|
|
90
93
|
}
|
|
91
94
|
export interface PiWebConfigResponse {
|
|
92
95
|
path: string;
|
|
@@ -562,11 +565,14 @@ export type SessionUiEvent = {
|
|
|
562
565
|
type: "session.name";
|
|
563
566
|
sessionId: string;
|
|
564
567
|
name?: string;
|
|
568
|
+
} | {
|
|
569
|
+
type: "session.created";
|
|
570
|
+
session: SessionInfo;
|
|
565
571
|
} | {
|
|
566
572
|
type: "pi.event";
|
|
567
573
|
eventType: string;
|
|
568
574
|
};
|
|
569
575
|
export type GlobalSessionEvent = Extract<SessionUiEvent, {
|
|
570
|
-
type: "status.update" | "activity.update" | "session.name";
|
|
576
|
+
type: "status.update" | "activity.update" | "session.name" | "session.created";
|
|
571
577
|
}>;
|
|
572
578
|
export type RealtimeEvent = GlobalSessionEvent | TerminalUiEvent | WorkspaceActivityUiEvent;
|
package/docs/plugins.md
CHANGED
|
@@ -42,7 +42,7 @@ Copy-paste prompt for creating a plugin:
|
|
|
42
42
|
Build a PI WEB plugin for this project.
|
|
43
43
|
Goal: <describe the UI behavior>.
|
|
44
44
|
Before coding, read the PI WEB plugin docs:
|
|
45
|
-
https://pi-web.dev/plugins
|
|
45
|
+
https://pi-web.dev/plugins
|
|
46
46
|
Full API reference:
|
|
47
47
|
https://pi-web.dev/plugins.md
|
|
48
48
|
Create it as a local plugin under ~/.pi-web/plugins/<plugin-id>.
|
|
@@ -56,7 +56,7 @@ Copy-paste prompt for modifying a plugin:
|
|
|
56
56
|
```text
|
|
57
57
|
Improve the PI WEB plugin at <path>.
|
|
58
58
|
Before coding, read the PI WEB plugin docs:
|
|
59
|
-
https://pi-web.dev/plugins
|
|
59
|
+
https://pi-web.dev/plugins
|
|
60
60
|
Full API reference:
|
|
61
61
|
https://pi-web.dev/plugins.md
|
|
62
62
|
Keep the plugin compatible with the documented v1 API.
|
|
@@ -131,7 +131,7 @@ Reload the PI WEB browser tab. PI WEB serves plugin modules with an mtime-based
|
|
|
131
131
|
|
|
132
132
|
## Remote machine plugins
|
|
133
133
|
|
|
134
|
-
When [machine federation](https://pi-web.dev/machines
|
|
134
|
+
When [machine federation](https://pi-web.dev/machines) is enabled, PI WEB also loads discovered plugins from the selected remote machine. Remote plugins are trusted browser-side code like local plugins, but their contributions are machine-scoped:
|
|
135
135
|
|
|
136
136
|
- actions, workspace panels, and workspace labels only appear while that machine is selected;
|
|
137
137
|
- plugin file and terminal helpers run against that machine;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chainingintention/pi-web-cn",
|
|
3
|
-
"version": "1.202606.
|
|
3
|
+
"version": "1.202606.14",
|
|
4
4
|
"description": "Remote web UI and browser control plane for persistent Pi Coding Agent sessions.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Federico Jaramillo Martinez",
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
"lit": "^3.3.1",
|
|
73
73
|
"marked": "^18.0.3",
|
|
74
74
|
"node-pty": "^1.1.0",
|
|
75
|
+
"typebox": "1.1.38",
|
|
75
76
|
"ws": "^8.20.1"
|
|
76
77
|
},
|
|
77
78
|
"devDependencies": {
|