@jmfederico/pi-web 1.202610.1 → 1.202610.3
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 +23 -134
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/index-BAl5IbYx.js +4429 -0
- package/dist/client/assets/vendor-editor-core-C2PJX3uW.js +10 -0
- package/dist/client/assets/{vendor-editor-languages-DOCw3vc9.js → vendor-editor-languages-CS6n1J8n.js} +1 -1
- package/dist/client/index.html +4 -48
- package/dist/config.js +8 -0
- package/dist/config.js.map +1 -1
- package/dist/pi-packages/captains-log/dist/browser/index.js +30 -32
- package/dist/pi-packages/captains-log/dist/companion.js +1 -1
- package/dist/pi-packages/captains-log/package.json +4 -4
- package/dist/pi-packages/relays/extensions/index.js +60 -0
- package/dist/pi-packages/relays/package.json +10 -1
- package/dist/pi-packages/relays/pi-web-plugin.js +31 -1
- package/dist/pi-packages/relays/prompts/relay-worktree.md +6 -16
- package/dist/pi-packages/relays/prompts/relay.md +6 -33
- package/dist/pi-packages/relays/relayDispatch.js +67 -0
- package/dist/pi-packages/relays/relayIdentity.js +37 -0
- package/dist/pi-packages/relays/relaysPanelElement.js +37 -12
- package/dist/pi-packages/relays/skills/relay/SKILL.md +24 -68
- package/dist/pi-packages/relays/skills/relay-runner/SKILL.md +40 -219
- package/dist/pi-packages/workflows/browser/pi-web-plugin.js +33 -0
- package/dist/pi-packages/workflows/package.json +22 -0
- package/dist/pi-packages/workflows/prompts/worktree.md +12 -0
- package/dist/pi-web-plugins/files/browser/pi-web-plugin.js +49 -51
- package/dist/pi-web-plugins/git/browser/git-panel.js +0 -1
- package/dist/pi-web-plugins/git/server-plugin.js +13 -2
- package/dist/pi-web-plugins/git/workspace-discovery-notify.cjs +14 -0
- package/dist/pi-web-plugins/git/workspaceDiscoveryHooks.js +186 -0
- package/dist/pi-web-plugins/info/infoInternals.js +3 -3
- package/dist/pi-web-plugins/info/pi-web-plugin.js +1 -1
- package/dist/pi-web-plugins/mermaid/browser/mermaid-engine.js +1087 -422
- package/dist/pi-web-plugins/terminal/browser/pi-web-plugin.js +30 -30
- package/dist/pi-web-plugins/updates/pi-web-plugin.js +1 -1
- package/dist/piWebUpdate.js +2 -2
- package/dist/piWebUpdate.js.map +1 -1
- package/dist/plugin-api.d.ts +229 -8
- package/dist/server/activity/workspaceActivityService.js +4 -1
- package/dist/server/activity/workspaceActivityService.js.map +1 -1
- package/dist/server/app.js +5 -0
- package/dist/server/app.js.map +1 -1
- package/dist/server/configRoutes.js +6 -0
- package/dist/server/configRoutes.js.map +1 -1
- package/dist/server/knownAutoInstallPiPackages.js +6 -0
- package/dist/server/knownAutoInstallPiPackages.js.map +1 -1
- package/dist/server/navigationPreferenceRoutes.js +39 -0
- package/dist/server/navigationPreferenceRoutes.js.map +1 -0
- package/dist/server/plugins/projectPluginSettings.js +95 -0
- package/dist/server/plugins/projectPluginSettings.js.map +1 -0
- package/dist/server/plugins/serverPluginRuntime.js +26 -3
- package/dist/server/plugins/serverPluginRuntime.js.map +1 -1
- package/dist/server/sessiond/autoInstallPiPackages.js +3 -3
- package/dist/server/sessiond/workspaceCatalogRoutes.js +3 -1
- package/dist/server/sessiond/workspaceCatalogRoutes.js.map +1 -1
- package/dist/server/sessiond/workspaceNotificationRoutes.js +41 -0
- package/dist/server/sessiond/workspaceNotificationRoutes.js.map +1 -0
- package/dist/server/sessiond.js +40 -7
- package/dist/server/sessiond.js.map +1 -1
- package/dist/server/sessions/askUserDomain.js +232 -0
- package/dist/server/sessions/askUserDomain.js.map +1 -0
- package/dist/server/sessions/askUserTool.js +15 -17
- package/dist/server/sessions/askUserTool.js.map +1 -1
- package/dist/server/sessions/dockerEnvironmentFacts.js +8 -0
- package/dist/server/sessions/dockerEnvironmentFacts.js.map +1 -1
- package/dist/server/sessions/extensionSessionDispatch.js +76 -0
- package/dist/server/sessions/extensionSessionDispatch.js.map +1 -0
- package/dist/server/sessions/globalProviderPolicy.js +71 -16
- package/dist/server/sessions/globalProviderPolicy.js.map +1 -1
- package/dist/server/sessions/messageHistoryTarget.js +61 -0
- package/dist/server/sessions/messageHistoryTarget.js.map +1 -0
- package/dist/server/sessions/piSessionManagerGateway.js +23 -24
- package/dist/server/sessions/piSessionManagerGateway.js.map +1 -1
- package/dist/server/sessions/piSessionService.js +759 -276
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/queuedMessageMutation.js +168 -0
- package/dist/server/sessions/queuedMessageMutation.js.map +1 -0
- package/dist/server/sessions/sessionArchiveStore.js +5 -1
- package/dist/server/sessions/sessionArchiveStore.js.map +1 -1
- package/dist/server/sessions/sessionArchiveTree.js +2 -2
- package/dist/server/sessions/sessionArchiveTree.js.map +1 -1
- package/dist/server/sessions/sessionCommandService.js +9 -3
- package/dist/server/sessions/sessionCommandService.js.map +1 -1
- package/dist/server/sessions/sessionImageDimensions.js +31 -0
- package/dist/server/sessions/sessionImageDimensions.js.map +1 -0
- package/dist/server/sessions/sessionMediaIndex.js +7 -1
- package/dist/server/sessions/sessionMediaIndex.js.map +1 -1
- package/dist/server/sessions/sessionMetadata.js +51 -0
- package/dist/server/sessions/sessionMetadata.js.map +1 -0
- package/dist/server/sessions/sessionNameGenerator.js +8 -28
- package/dist/server/sessions/sessionNameGenerator.js.map +1 -1
- package/dist/server/sessions/sessionRoutes.js +20 -2
- package/dist/server/sessions/sessionRoutes.js.map +1 -1
- package/dist/server/sessions/sessionSummaryScanner.js +62 -5
- package/dist/server/sessions/sessionSummaryScanner.js.map +1 -1
- package/dist/server/sessions/spawnSessionTool.js +3 -1
- package/dist/server/sessions/spawnSessionTool.js.map +1 -1
- package/dist/server/sessions/spawnSubsessionTool.js +25 -17
- package/dist/server/sessions/spawnSubsessionTool.js.map +1 -1
- package/dist/server/sessions/subsessionCompletionDelivery.js +15 -0
- package/dist/server/sessions/subsessionCompletionDelivery.js.map +1 -0
- package/dist/server/sessions/subsessionCompletionInbox.js +134 -0
- package/dist/server/sessions/subsessionCompletionInbox.js.map +1 -0
- package/dist/server/sessions/subsessionProvenance.js +27 -0
- package/dist/server/sessions/subsessionProvenance.js.map +1 -0
- package/dist/server/status/machineStatusService.js +17 -5
- package/dist/server/status/machineStatusService.js.map +1 -1
- package/dist/server/storage/navigationPreferenceStore.js +137 -0
- package/dist/server/storage/navigationPreferenceStore.js.map +1 -0
- package/dist/server/workspaces/projectPiWebConfig.js +88 -6
- package/dist/server/workspaces/projectPiWebConfig.js.map +1 -1
- package/dist/server/workspaces/workspaceChangeNotifier.js +12 -0
- package/dist/server/workspaces/workspaceChangeNotifier.js.map +1 -0
- package/dist/server/workspaces/workspaceNotificationCommand.js +64 -0
- package/dist/server/workspaces/workspaceNotificationCommand.js.map +1 -0
- package/dist/server/workspaces/workspaceProviderRegistry.js +55 -0
- package/dist/server/workspaces/workspaceProviderRegistry.js.map +1 -1
- package/dist/server-plugin-api.d.ts +18 -0
- package/dist/server-plugin-api.js.map +1 -1
- package/dist/sessiond/sessionDaemonClient.js +3 -3
- package/dist/sessiond/sessionDaemonClient.js.map +1 -1
- package/dist/shared/apiTypes.js +2 -2
- package/dist/shared/apiTypes.js.map +1 -1
- package/dist/shared/federatedRoutes.js +6 -0
- package/dist/shared/federatedRoutes.js.map +1 -1
- package/dist/shared/machineStatus.js +11 -2
- package/dist/shared/machineStatus.js.map +1 -1
- package/dist/shared/navigationPreferences.js +6 -0
- package/dist/shared/navigationPreferences.js.map +1 -0
- package/dist/shared/pluginApiTypes.d.ts +2 -0
- package/dist/shared/sessionMedia.js +6 -0
- package/dist/shared/sessionMedia.js.map +1 -1
- package/dist/shared/streamingBehavior.js +7 -0
- package/dist/shared/streamingBehavior.js.map +1 -0
- package/dist/shared/themePreference.js +23 -0
- package/dist/shared/themePreference.js.map +1 -0
- package/dist/workspaceNotificationCli.js +95 -0
- package/dist/workspaceNotificationCli.js.map +1 -0
- package/docs/config.md +111 -86
- package/docs/plugins.md +105 -30
- package/examples/session-bridge-plugin/package.json +2 -2
- package/examples/session-bridge-plugin/src/companion.ts +1 -1
- package/examples/workspace-provider-plugin/package.json +1 -1
- package/package.json +33 -33
- package/dist/client/assets/index-CBjDnBIN.js +0 -4178
- package/dist/client/assets/vendor-editor-core-YWog6mAR.js +0 -10
- package/dist/server/sessions/pendingAskStore.js +0 -275
- package/dist/server/sessions/pendingAskStore.js.map +0 -1
|
@@ -4,6 +4,8 @@ export type JsonValue = JsonPrimitive | JsonObject | readonly JsonValue[];
|
|
|
4
4
|
export interface JsonObject {
|
|
5
5
|
readonly [key: string]: JsonValue;
|
|
6
6
|
}
|
|
7
|
+
/** Explicitly browser-public session data, keyed by owning package/plugin namespace. */
|
|
8
|
+
export type SessionUiMetadata = Readonly<Record<string, JsonObject>>;
|
|
7
9
|
/**
|
|
8
10
|
* Typed token for one exact host/plugin capability version. The provider id
|
|
9
11
|
* and package-local id together with the version form the stable capability
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/** Only a complete, positive pixel pair can establish image geometry. */
|
|
2
|
+
export function validImageDimensions(width, height) {
|
|
3
|
+
return typeof width === "number" && Number.isSafeInteger(width) && width > 0
|
|
4
|
+
&& typeof height === "number" && Number.isSafeInteger(height) && height > 0
|
|
5
|
+
? { width, height } : undefined;
|
|
6
|
+
}
|
|
1
7
|
/** Explicit opt-in keeps older browser clients and remote machines compatible. */
|
|
2
8
|
export const SESSION_MEDIA_MODE = "reference";
|
|
3
9
|
export function isSessionMediaId(value) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionMedia.js","sourceRoot":"","sources":["../../src/shared/sessionMedia.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sessionMedia.js","sourceRoot":"","sources":["../../src/shared/sessionMedia.ts"],"names":[],"mappings":"AAgBA,yEAAyE;AACzE,MAAM,UAAU,oBAAoB,CAAC,KAAc,EAAE,MAAe;IAClE,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;WACvE,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC;QAC3E,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACpC,CAAC;AAED,kFAAkF;AAClF,MAAM,CAAC,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAE9C,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACpE,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function requireDefaultStreamingBehavior(value, source) {
|
|
2
|
+
if (value !== "steer" && value !== "followUp") {
|
|
3
|
+
throw new Error(`PI WEB config defaultStreamingBehavior must be steer or followUp: ${source}`);
|
|
4
|
+
}
|
|
5
|
+
return value;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=streamingBehavior.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamingBehavior.js","sourceRoot":"","sources":["../../src/shared/streamingBehavior.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,+BAA+B,CAAC,KAAc,EAAE,MAAc;IAC5E,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,qEAAqE,MAAM,EAAE,CAAC,CAAC;IACjG,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const qualifiedThemeIdPattern = /^[a-z][a-z0-9.-]*:[a-z][a-z0-9.-]*$/u;
|
|
2
|
+
/** Parse data only: theme availability is resolved after browser plugins load. */
|
|
3
|
+
export function parseThemePreference(value) {
|
|
4
|
+
if (!isRecord(value))
|
|
5
|
+
return undefined;
|
|
6
|
+
const record = value;
|
|
7
|
+
const themeId = record["themeId"];
|
|
8
|
+
const auto = record["auto"];
|
|
9
|
+
if (typeof themeId !== "string" || !qualifiedThemeIdPattern.test(themeId) || typeof auto !== "boolean")
|
|
10
|
+
return undefined;
|
|
11
|
+
return { themeId, auto };
|
|
12
|
+
}
|
|
13
|
+
function isRecord(value) {
|
|
14
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
export function requireDefaultThemePreference(value, source) {
|
|
17
|
+
const preference = parseThemePreference(value);
|
|
18
|
+
if (preference === undefined) {
|
|
19
|
+
throw new Error(`PI WEB config defaultTheme must contain a qualified themeId and a boolean auto: ${source}`);
|
|
20
|
+
}
|
|
21
|
+
return preference;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=themePreference.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themePreference.js","sourceRoot":"","sources":["../../src/shared/themePreference.ts"],"names":[],"mappings":"AAEA,MAAM,uBAAuB,GAAG,sCAAsC,CAAC;AAEvE,kFAAkF;AAClF,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACvC,MAAM,MAAM,GAAG,KAAK,CAAC;IACrB,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5B,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACzH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,KAAc,EAAE,MAAc;IAC1E,MAAM,UAAU,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,mFAAmF,MAAM,EAAE,CAAC,CAAC;IAC/G,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { isPiWebPluginId } from "./shared/pluginIds.js";
|
|
4
|
+
import { SessionDaemonClient } from "./sessiond/sessionDaemonClient.js";
|
|
5
|
+
const usage = "Usage: pi-web workspaces notify --project <projectId> --plugin <pluginId>";
|
|
6
|
+
const idMaxLength = 512;
|
|
7
|
+
/** These identifiers are opaque; preserve the original value rather than trimming it. */
|
|
8
|
+
export function requireWorkspaceNotificationProjectId(value) {
|
|
9
|
+
if (typeof value !== "string" || value.trim() === "" || value.length > idMaxLength) {
|
|
10
|
+
throw new Error("Workspace notification project id must be non-empty and at most 512 characters");
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
export function requireWorkspaceNotificationPluginId(value) {
|
|
15
|
+
if (typeof value !== "string" || value.length > idMaxLength || !isPiWebPluginId(value)) {
|
|
16
|
+
throw new Error("Workspace notification plugin id must match a PI WEB plugin id and be at most 512 characters");
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
/** Failures propagate to the CLI's nonzero exit boundary; integrations own best-effort policy. */
|
|
21
|
+
export async function runWorkspaceNotificationCli(args, dependencies = {}) {
|
|
22
|
+
const target = parseCommand(args);
|
|
23
|
+
if (target === undefined) {
|
|
24
|
+
(dependencies.writeLine ?? console.log)(usage);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const client = dependencies.client ?? dependencies.createClient?.(target.daemonOptions) ?? new SessionDaemonClient(target.daemonOptions);
|
|
28
|
+
const response = await client.request("POST", `/workspace-notifications/projects/${encodeURIComponent(target.projectId)}`, { pluginId: target.pluginId }, { signal: AbortSignal.timeout(2_000) });
|
|
29
|
+
if (response.statusCode < 200 || response.statusCode >= 300) {
|
|
30
|
+
const detail = response.body.trim().slice(0, 1024);
|
|
31
|
+
throw new Error(`Workspace notification failed (HTTP ${String(response.statusCode)})${detail === "" ? "" : `: ${detail}`}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function parseCommand(args) {
|
|
35
|
+
if (args.length === 0
|
|
36
|
+
|| (args.length === 1 && (args[0] === "help" || isHelp(args[0])))
|
|
37
|
+
|| (args.length === 2 && args[0] === "notify" && isHelp(args[1]))) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
if (args[0] !== "notify")
|
|
41
|
+
throw new Error(usage);
|
|
42
|
+
const values = new Map();
|
|
43
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
44
|
+
const arg = args[index];
|
|
45
|
+
if (arg === undefined)
|
|
46
|
+
continue;
|
|
47
|
+
const equals = arg.indexOf("=");
|
|
48
|
+
const option = equals === -1 ? arg : arg.slice(0, equals);
|
|
49
|
+
if (option !== "--project" && option !== "--plugin" && option !== "--daemon-url" && option !== "--daemon-socket") {
|
|
50
|
+
throw new Error(`Unknown workspaces notify option: ${arg}`);
|
|
51
|
+
}
|
|
52
|
+
if (values.has(option))
|
|
53
|
+
throw new Error(`Duplicate workspaces notify option: ${option}`);
|
|
54
|
+
const value = equals === -1 ? args[index + 1] : arg.slice(equals + 1);
|
|
55
|
+
if (value === undefined || value === "" || (equals === -1 && value.startsWith("-"))) {
|
|
56
|
+
throw new Error(`${option} requires a value`);
|
|
57
|
+
}
|
|
58
|
+
values.set(option, value);
|
|
59
|
+
if (equals === -1)
|
|
60
|
+
index += 1;
|
|
61
|
+
}
|
|
62
|
+
if (!values.has("--project") || !values.has("--plugin"))
|
|
63
|
+
throw new Error(usage);
|
|
64
|
+
if (values.has("--daemon-url") && values.has("--daemon-socket")) {
|
|
65
|
+
throw new Error("Specify only one of --daemon-url and --daemon-socket");
|
|
66
|
+
}
|
|
67
|
+
const daemonOptions = {};
|
|
68
|
+
const url = values.get("--daemon-url");
|
|
69
|
+
if (url !== undefined) {
|
|
70
|
+
const parsed = new URL(url);
|
|
71
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:")
|
|
72
|
+
throw new Error("--daemon-url requires an HTTP(S) URL");
|
|
73
|
+
daemonOptions.baseUrl = parsed.href;
|
|
74
|
+
}
|
|
75
|
+
const socket = values.get("--daemon-socket");
|
|
76
|
+
if (socket !== undefined)
|
|
77
|
+
daemonOptions.socketPath = socket;
|
|
78
|
+
return {
|
|
79
|
+
projectId: requireWorkspaceNotificationProjectId(values.get("--project")),
|
|
80
|
+
pluginId: requireWorkspaceNotificationPluginId(values.get("--plugin")),
|
|
81
|
+
daemonOptions,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function isHelp(value) {
|
|
85
|
+
return value === "--help" || value === "-h";
|
|
86
|
+
}
|
|
87
|
+
// Hook invocations use this lightweight entry instead of loading the service
|
|
88
|
+
// installation CLI. Both entrypoints share the same bounded request runner.
|
|
89
|
+
if (process.argv[1] !== undefined && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
90
|
+
runWorkspaceNotificationCli(process.argv.slice(2)).catch((error) => {
|
|
91
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
92
|
+
process.exitCode = 1;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=workspaceNotificationCli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaceNotificationCli.js","sourceRoot":"","sources":["../src/workspaceNotificationCli.ts"],"names":[],"mappings":"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"}
|
package/docs/config.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
PI WEB configuration covers the machine-local and project-local settings you usually need: the web/API bind address, trusted development-host settings, UI preferences, desired plugin enablement/settings, server-plugin recovery, file-explorer path access, manual upload defaults, upload limits, the Pi agent state directory, and session-daemon tools.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Settings below describe available choices, scope, limitations, and restart requirements. An HTML version is available at <https://pi-web.dev/config>.
|
|
6
6
|
|
|
7
7
|
## Config files
|
|
8
8
|
|
|
@@ -11,7 +11,7 @@ PI WEB uses two config files:
|
|
|
11
11
|
- **Global PI WEB config:** `$PI_WEB_CONFIG`, or `$XDG_CONFIG_HOME/pi-web/config.json`, or `~/.config/pi-web/config.json`.
|
|
12
12
|
- **Project-local PI WEB config:** `<project>/.pi-web/config.json` for commit-able project settings.
|
|
13
13
|
|
|
14
|
-
Each PI WEB machine has its own config. When using Fleet/machine federation, Settings uses the selected machine for config that affects work running there: session daemon tools, desired PI WEB plugin enablement/settings, external path access, and upload defaults. Gateway/browser-only settings stay local to the gateway: keyboard shortcuts, remote machine registry/tokens, and gateway host/port/allowed-hosts.
|
|
14
|
+
Each PI WEB machine has its own config. When using Fleet/machine federation, Settings uses the selected machine for config that affects work running there: session daemon tools, desired PI WEB plugin enablement/settings, external path access, and upload defaults. Gateway/browser-only settings stay local to the gateway: the default theme, keyboard shortcuts, remote machine registry/tokens, and gateway host/port/allowed-hosts.
|
|
15
15
|
|
|
16
16
|
Pi package settings are separate from PI WEB config. They live in Pi's package-manager settings on the target machine and are managed by Pi (`pi install`, `pi remove`, `pi update`) or **Settings → Pi packages**. In a federated setup, **Settings → Pi packages** targets the currently selected machine. The PI WEB `plugins` config key controls desired enablement/settings for discovered browser-only, server-only, and dual-entry PI WEB plugins on that machine; it does not install, remove, or update Pi packages.
|
|
17
17
|
|
|
@@ -25,8 +25,8 @@ Pi package settings are separate from PI WEB config. They live in Pi's package-m
|
|
|
25
25
|
| Override the path for one command | Supply a nonempty `PI_WEB_CONFIG` when invoking that command. This does not rewrite service definitions. |
|
|
26
26
|
| Change the managed service config path | Run `pi-web install --config /path/to/config.json` to regenerate both web/API and sessiond service definitions. |
|
|
27
27
|
| Upgrade from an installation that set the path only for the web service | Rerun that same install command so both services use the same config. |
|
|
28
|
-
| systemd cannot verify the loaded service
|
|
29
|
-
| systemd uses `EnvironmentFile=` | Accepted with a
|
|
28
|
+
| systemd cannot verify the loaded service config | The command stops. Reinstall services with the intended config path and reload the service manager before retrying. |
|
|
29
|
+
| systemd uses `EnvironmentFile=` | Accepted with a warning; config-path overrides in that file cannot be verified. |
|
|
30
30
|
| launchd has an old config path or a label loaded from another plist | `start` and `doctor` fail. `restart` reloads installed plists and can repair stale loaded state. |
|
|
31
31
|
|
|
32
32
|
## Startup model and thinking defaults
|
|
@@ -61,10 +61,17 @@ Process restarts depend on the key:
|
|
|
61
61
|
- `pathAccess`: applies on the next request; existing file views may need a browser refresh.
|
|
62
62
|
- `uploads.defaultFolder`: applies to newly opened Files upload dialogs and new direct drag/drop batches after config/workspace refresh.
|
|
63
63
|
- `attachments.defaultFolder`: applies to new prompt-attachment saves after config/workspace refresh.
|
|
64
|
-
- `plugins`: browser-only changes
|
|
64
|
+
- `plugins`: browser-only changes need a tab reload. Server-backed enablement, settings, or package changes require a manual session-daemon restart, then a tab reload. See [Project plugin settings](#project-plugin-settings).
|
|
65
65
|
- `serverPlugins.safeStart`: persistent offline recovery state applied before server-plugin discovery/import on the next sessiond start; use the `pi-web plugins safe-start ...` CLI rather than hand-editing it.
|
|
66
|
-
- Pi package
|
|
67
|
-
- `shortcuts`: saved settings apply in the browser after config refresh/save.
|
|
66
|
+
- Pi package changes: use `/reload` in each idle session for ordinary extensions, skills, templates, and themes. Packages containing server plugins require a manual session-daemon restart and browser reload. Global provider registration or connection changes also require a daemon restart; model-list-only updates do not. See [Pi extension provider baseline](#pi-extension-provider-baseline).
|
|
67
|
+
- `shortcuts` / `defaultStreamingBehavior`: saved settings apply in the browser after config refresh/save; no service restart.
|
|
68
|
+
- `defaultTheme`: applies after settings save or browser config refresh when the browser has no local theme override; no service restart.
|
|
69
|
+
|
|
70
|
+
### Streaming send default
|
|
71
|
+
|
|
72
|
+
In **Settings → Keyboard shortcuts → Send while agent is running**, choose **Steer** (the default) to deliver input before the next model call, or **Follow-up** to queue it until the current response finishes. This changes only the keyboard shortcut, not the chat buttons. During compaction, messages queue as follow-ups.
|
|
73
|
+
|
|
74
|
+
The global gateway key is `defaultStreamingBehavior`: `steer` or `followUp`. It is not project-local and needs no service restart.
|
|
68
75
|
|
|
69
76
|
## Global config example
|
|
70
77
|
|
|
@@ -72,6 +79,8 @@ Process restarts depend on the key:
|
|
|
72
79
|
{
|
|
73
80
|
"host": "127.0.0.1",
|
|
74
81
|
"port": 8504,
|
|
82
|
+
"defaultTheme": { "themeId": "themes:pi-web-dark", "auto": true },
|
|
83
|
+
"defaultStreamingBehavior": "steer",
|
|
75
84
|
"pathAccess": {
|
|
76
85
|
"allowedPaths": ["~/SDKs", "/opt/reference"]
|
|
77
86
|
},
|
|
@@ -121,50 +130,23 @@ Project-local `pathAccess.allowedPaths` entries are merged after the global list
|
|
|
121
130
|
|
|
122
131
|
Project-local `uploads.defaultFolder` overrides the global upload destination for workspaces in that project, and project-local `attachments.defaultFolder` overrides the global prompt-attachment destination the same way. These defaults also apply when accessing the project through Fleet.
|
|
123
132
|
|
|
124
|
-
|
|
133
|
+
Project-local `plugins.<id>.settings` supplies overrides for server plugins that support project settings, including Git. Only settings are allowed here: `plugins.<id>.enabled` is not supported; plugin enablement stays global. See [Project plugin settings](#project-plugin-settings) for merge and restart rules.
|
|
134
|
+
|
|
135
|
+
Plugins may also own separate project files, such as `.pi-web/tasks.json` for the built-in Workspace Tasks plugin.
|
|
125
136
|
|
|
126
137
|
PI WEB also honors one optional project hook; see [Worktree pre-remove hook](#worktree-pre-remove-hook).
|
|
127
138
|
|
|
128
139
|
## Worktree pre-remove hook
|
|
129
140
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
```text
|
|
133
|
-
.pi-web/hooks/worktree-pre-remove
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
relative to the workspace where the deletion command runs. PI WEB runs the deletion command from the project's main workspace when it exists, so commit the hook there and it follows the repository.
|
|
137
|
-
|
|
138
|
-
When the hook is present and executable, PI WEB dispatches the hook and the removal as one composed terminal command:
|
|
139
|
-
|
|
140
|
-
```sh
|
|
141
|
-
'<hook path>' '<workspace path>' && <workspace removal command>
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
For Git projects the removal command is `git worktree remove '<worktree path>'`.
|
|
145
|
-
|
|
146
|
-
Contract:
|
|
147
|
-
|
|
148
|
-
- **Arguments:** exactly one — the absolute path of the workspace being removed.
|
|
149
|
-
- **Working directory:** the workspace the removal command runs in, not the workspace being removed.
|
|
150
|
-
- **Exit codes:** `0` lets the removal proceed; any non-zero exit blocks it. The `&&` chain is the fail-closed guarantee — a failing hook keeps the worktree on disk.
|
|
151
|
-
- **Absent hook:** a missing file, or a file without the executable bit (for example after a checkout that lost it), is treated as no hook; PI WEB then runs the removal command on its own.
|
|
141
|
+
Use an executable `.pi-web/hooks/worktree-pre-remove` script to stop containers or release workspace resources before removal. Place it relative to the workspace where the removal command runs—normally the project's main workspace.
|
|
152
142
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
set -eu
|
|
161
|
-
|
|
162
|
-
worktree_path="$1"
|
|
163
|
-
|
|
164
|
-
# Stop/remove local dev containers bind-mounting "$worktree_path",
|
|
165
|
-
# release other per-worktree resources, etc.
|
|
166
|
-
# Exit non-zero to block the worktree removal.
|
|
167
|
-
```
|
|
143
|
+
| Item | Behavior |
|
|
144
|
+
| --- | --- |
|
|
145
|
+
| Argument | One absolute path: the workspace being removed. |
|
|
146
|
+
| Success (`0`) | Continue with workspace removal. |
|
|
147
|
+
| Failure (nonzero) | Block removal; keep the workspace on disk. |
|
|
148
|
+
| Missing / not executable | Skip the hook and run removal normally. |
|
|
149
|
+
| Output | Visible in the workspace deletion terminal run. |
|
|
168
150
|
|
|
169
151
|
## Configuration matrix
|
|
170
152
|
|
|
@@ -185,13 +167,18 @@ Rows with JSON key `—` are runtime-only environment variables, not config-file
|
|
|
185
167
|
| Agent can post question forms | `askUser` | `PI_WEB_ASK_USER` | Global/session daemon | Not supported locally | Restart session daemon on that machine |
|
|
186
168
|
| Extension dialog auto-cancel timeout | `extensionDialogsTimeoutMs` | — | Global/session daemon | Not supported locally | Restart session daemon on that machine |
|
|
187
169
|
| Session environment facts | `environmentFacts` | `PI_WEB_ENVIRONMENT_FACTS` | Global/session daemon | Not supported locally | Restart session daemon on that machine |
|
|
188
|
-
| PI WEB plugin desired enablement
|
|
170
|
+
| PI WEB plugin desired enablement | `plugins.<id>.enabled` | — | Global | Not supported locally | Browser-only: reload tab. Server-backed: manually restart sessiond, then reload tab |
|
|
171
|
+
| PI WEB plugin settings | `plugins.<id>.settings` | — | Global + project for server plugins supporting project settings | **Merges top-level setting keys** over global settings; no project enablement | Browser-only global settings: reload tab. Server-backed global/project settings: manually restart sessiond, then reload tab |
|
|
172
|
+
| Git worktree discovery hooks | `plugins.git.settings.workspaceDiscoveryHooks` | — | Global + project | Project boolean overrides global; default `true` | Manually restart session daemon; browser reload alone does not apply changes |
|
|
189
173
|
| Server-plugin safe start | `serverPlugins.safeStart` | — | Global/offline recovery | Not supported locally; manage with `pi-web plugins safe-start ...` | Applied before discovery/import on next sessiond start |
|
|
174
|
+
| Default browser theme | `defaultTheme.themeId`, `defaultTheme.auto` | — | Gateway global | Not supported locally; device choices take precedence | Settings save / browser config refresh; no restart |
|
|
175
|
+
| Streaming send default | `defaultStreamingBehavior` | — | Global gateway | Not supported locally | Applies after settings save/config refresh; defaults to `steer` |
|
|
190
176
|
| Keyboard shortcuts | `shortcuts.<actionId>` | — | Global | Not supported locally | Applies after settings save/config refresh |
|
|
191
177
|
| Project config version | `version` | — | Project | Project-local only; must be `1` when present | Next project-config read |
|
|
192
178
|
| **Runtime-only environment variables** | | | | | |
|
|
193
179
|
| Global config file path | — | `PI_WEB_CONFIG` (`XDG_CONFIG_HOME` affects the default path) | Process/env | Selects the global config file; not a project config | Restart services/processes after changing env |
|
|
194
180
|
| Managed data directory | — | `PI_WEB_DATA_DIR` | Process/env | Not supported locally | Restart web/API and session daemon |
|
|
181
|
+
| Git hook instance namespace | — | `PI_WEB_INSTANCE_NAMESPACE` | Session daemon env | Not supported locally | Restart session daemon; see [running multiple instances](#git-instance-namespace) |
|
|
195
182
|
| Session daemon socket | — | `PI_WEB_SESSIOND_SOCKET` | Web/API + session daemon env | Not supported locally | Restart daemon and web/API; both must match |
|
|
196
183
|
| Session daemon TCP port | — | `PI_WEB_SESSIOND_PORT` | Session daemon env | Not supported locally | Restart session daemon; set `PI_WEB_SESSIOND_URL` for web/API too |
|
|
197
184
|
| Session daemon TCP host | — | `PI_WEB_SESSIOND_HOST` | Session daemon env | Not supported locally | Restart session daemon |
|
|
@@ -217,11 +204,11 @@ This setting does not change the PI WEB config file selected by `PI_WEB_CONFIG`
|
|
|
217
204
|
|
|
218
205
|
### Agent process environment
|
|
219
206
|
|
|
220
|
-
Agent shells, terminals, and
|
|
207
|
+
Agent shells, terminals, and child sessions inherit the daemon environment, including its Pi state paths. `NODE_ENV` and `PORT` are removed so they do not interfere with development commands.
|
|
221
208
|
|
|
222
|
-
|
|
209
|
+
`PI_WEB_SESSION=1` marks nested processes. Inherited `PI_WEB_*` values still point to the hosting instance. Use a separate data directory, daemon endpoint, and web port for a second instance. Do not restart the hosting session daemon from inside an active session you need to preserve.
|
|
223
210
|
|
|
224
|
-
|
|
211
|
+
`environmentFacts` includes nesting and deployment guidance in session system prompts by default. Set it to `false`, or use `PI_WEB_ENVIRONMENT_FACTS=false`, to omit that guidance. Restart sessiond after changing it.
|
|
225
212
|
|
|
226
213
|
### External path access
|
|
227
214
|
|
|
@@ -235,7 +222,7 @@ Accepted root forms:
|
|
|
235
222
|
- Home-relative paths: `~/SDKs`
|
|
236
223
|
- Windows absolute paths on Windows hosts: `C:\Users\dev\SDKs`
|
|
237
224
|
|
|
238
|
-
|
|
225
|
+
Roots must be existing directories. Symlink escapes outside allowed roots are rejected.
|
|
239
226
|
|
|
240
227
|
In **Settings → General**, external filesystem roots are saved on the selected machine. Gateway host, port, and allowed-hosts fields stay on the gateway config.
|
|
241
228
|
|
|
@@ -258,7 +245,7 @@ The Files panel can upload one or more files in two ways:
|
|
|
258
245
|
}
|
|
259
246
|
```
|
|
260
247
|
|
|
261
|
-
The value must be a non-empty workspace-relative folder
|
|
248
|
+
The value must be a non-empty workspace-relative folder, without absolute paths or `..` traversal. In the upload dialog only, clearing the destination uploads that batch to the workspace root.
|
|
262
249
|
|
|
263
250
|
Uploads stay inside the workspace, create parent folders by default, and do not overwrite existing files unless you enable overwrite in the review dialog. Direct drag/drop never overwrites. Check the upload progress UI for completion, conflicts, and errors.
|
|
264
251
|
|
|
@@ -280,7 +267,7 @@ When the chat composer has pending attachments, its delivery selector offers **S
|
|
|
280
267
|
}
|
|
281
268
|
```
|
|
282
269
|
|
|
283
|
-
The value must be a non-empty workspace-relative folder
|
|
270
|
+
The value must be a non-empty workspace-relative folder, without absolute paths or `..` traversal. Saved attachments stay inside the workspace. An explicit per-request folder overrides the configured default.
|
|
284
271
|
|
|
285
272
|
In Fleet, Settings saves the global attachment default on the selected machine; the composer uses that project's effective destination.
|
|
286
273
|
|
|
@@ -298,9 +285,7 @@ PI_CODING_AGENT_SESSION_DIR=/opt/pi-profiles/lab-sessions
|
|
|
298
285
|
|
|
299
286
|
The directory must use the data layout supported by the bundled Pi SDK; PI WEB does not load or convert incompatible formats, migrate profile data, or repartition PI WEB-managed archives when the directory changes.
|
|
300
287
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
If the session daemon cannot report a valid active directory, profile-dependent Pi package and PI WEB plugin operations report unavailable instead of falling back to independently resolved values. A package-managed update command is shown only when the daemon reports a valid active directory and the `pi` command is on `PATH`, and the command pins that directory for the update. Restart the session daemon on the selected machine to establish the next active directory.
|
|
288
|
+
Changing either path requires a session-daemon restart on the target machine; restarting only web/API does not apply it. Sessions, terminals, and package operations use the daemon's active paths. If those paths are unavailable, profile-dependent operations are unavailable too.
|
|
304
289
|
|
|
305
290
|
### Pi extension provider baseline
|
|
306
291
|
|
|
@@ -308,17 +293,17 @@ Model providers are shared across all sessions on a machine. PI WEB loads them w
|
|
|
308
293
|
|
|
309
294
|
Provider connection settings stay fixed until the daemon restarts. Project extensions and `/reload` cannot add, replace, or remove providers. Other Pi extension features continue to load and reload normally.
|
|
310
295
|
|
|
311
|
-
Pi virtual models are unsupported
|
|
296
|
+
Pi virtual models are unsupported, including from global extensions. Disable the extension's virtual-model feature and select a physical model instead; restarting the daemon does not enable virtual models.
|
|
312
297
|
|
|
313
298
|
#### Model list refresh for a known provider
|
|
314
299
|
|
|
315
300
|
An extension may refresh an existing provider's **model list** without a restart, provided all other provider settings remain unchanged. Changes to credentials, connection settings, or provider implementation require a daemon restart. Accepted model-list updates are available to sessions immediately.
|
|
316
301
|
|
|
317
|
-
Model lists are shared
|
|
302
|
+
Model lists are shared across the machine, not isolated per project. If two workspaces update the same provider's list, the last update wins. Pi extensions remain trusted code, and model entries can override provider connection details.
|
|
318
303
|
|
|
319
304
|
#### Provider decisions in the daemon log
|
|
320
305
|
|
|
321
|
-
|
|
306
|
+
Provider decisions are recorded in daemon logs, not browser notifications. Entries omit provider configuration and credentials. See [provider extension troubleshooting](https://pi-web.dev/faq#provider-extension-no-effect) for ignored changes.
|
|
322
307
|
|
|
323
308
|
This prevents accidental provider, configuration, or credential contamination between projects; it is not a security boundary because Pi extensions remain trusted daemon code.
|
|
324
309
|
|
|
@@ -326,20 +311,11 @@ Configure providers before the daemon starts: use the active agent directory's `
|
|
|
326
311
|
|
|
327
312
|
### Background model catalog refresh
|
|
328
313
|
|
|
329
|
-
PI WEB
|
|
330
|
-
|
|
331
|
-
A refresh that is *already* in flight can still briefly delay starting or opening a session, because the shared runtime is read while that refresh is running. PI WEB says so while you wait: the session's activity line names the startup step it is on and adds `provider model lists are refreshing` when a background refresh is running at the same time. That note reports what is happening concurrently, not a proven cause.
|
|
332
|
-
|
|
333
|
-
The session daemon runs the refresh:
|
|
334
|
-
|
|
335
|
-
- **15 seconds after the daemon starts**, then **hourly**. Pi treats stored catalogs as fresh for four hours, so most hourly ticks make no network request at all; the shorter tick only makes sure a due refresh is not delayed to the next tick.
|
|
336
|
-
- **Immediately after a provider login or logout**, bypassing that freshness window, because the cached catalog is known to be wrong.
|
|
314
|
+
PI WEB refreshes provider model catalogs automatically in the background and after login or logout. Reopen the model selector to see new models. Failed refreshes keep the last successful catalog and report problems in daemon logs. A refresh can briefly delay session startup; the activity line reports when model lists are refreshing.
|
|
337
315
|
|
|
338
|
-
|
|
316
|
+
Set `PI_WEB_OFFLINE` or `PI_OFFLINE` in the web/API and session-daemon environment and restart both to disable release checks and catalog network refresh. Sessions then use stored catalogs. `PI_WEB_SKIP_VERSION_CHECK` and `PI_SKIP_VERSION_CHECK` disable only release checks.
|
|
339
317
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
To turn the background refresh off entirely, set `PI_WEB_OFFLINE` or `PI_OFFLINE` in the session daemon's environment and restart it. In offline mode PI WEB performs no provider catalog network requests, including after logins, and sessions use the catalogs already stored in the agent directory. The `PI_WEB_SKIP_VERSION_CHECK` and `PI_SKIP_VERSION_CHECK` keys do **not** affect this refresh; they only suppress PI WEB release checks.
|
|
318
|
+
Unset or clear these flags to turn them off: any nonempty value, including `false` or `0`, enables them.
|
|
343
319
|
|
|
344
320
|
### Project trust for project-local resources
|
|
345
321
|
|
|
@@ -362,13 +338,11 @@ This mirrors the Pi CLI: with `defaultProjectTrust: "never"`, an opened workspac
|
|
|
362
338
|
|
|
363
339
|
`subsessions` controls whether agents receive the tracked-subsession tools: `spawn_subsession`, `list_subsessions`, `check_subsession`, `read_subsession`, and `yield_to_subsessions`. It defaults to `true` and also requires `spawnSessions` to be enabled.
|
|
364
340
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
A tracked subsession always runs in the spawning session's working directory, so it stays in that workspace's session tree next to its parent. `spawn_subsession` takes no `cwd`. To get work done elsewhere, instruct the child to work there from this workspace, or use `spawn_session`, which still targets any workspace of the project, for an independent session there.
|
|
341
|
+
Independent sessions run in a workspace of the same project without returning output to their parent. Tracked subsessions run in the parent's working directory and return results automatically; the parent can keep working or wait for them. Delivered results are not automatically repeated, but remain available for review.
|
|
368
342
|
|
|
369
|
-
|
|
343
|
+
Agent-created tracked subsessions are collapsed under their parent. Use **Agent subsessions** to expand them. User-created forks and clones, unknown-origin sessions, children without an available parent, and independent sessions remain visible.
|
|
370
344
|
|
|
371
|
-
|
|
345
|
+
New sessions inherit the parent's model and thinking level unless another model is requested, for example with a `#provider/model-id` prompt reference. Thinking levels are limited to what the chosen model supports.
|
|
372
346
|
|
|
373
347
|
In **Settings → Session daemon**, these keys are saved on the selected machine. Restart the session daemon on that machine after changing them.
|
|
374
348
|
|
|
@@ -378,13 +352,9 @@ In **Settings → Session daemon**, these keys are saved on the selected machine
|
|
|
378
352
|
|
|
379
353
|
Use **Settings → Session daemon → Allow agents to ask questions** to change `askUser` on the selected machine. An environment override makes the toggle read-only.
|
|
380
354
|
|
|
381
|
-
Agents can
|
|
382
|
-
|
|
383
|
-
Calling `ask_user` posts the whole set as one browser form and ends the current agent run instead of waiting for the user. The open form is owned by the session daemon, so it survives a browser disconnect, browser reload, or web/API restart while that daemon keeps running. When the user submits, the answers arrive as a follow-up that wakes the session; each question is reported with its selected option values or free text, or explicitly as unanswered.
|
|
355
|
+
Agents can ask questions with choices or free-text answers. You may leave questions unanswered; partial submissions are confirmed before sending. Answering or skipping resumes the agent.
|
|
384
356
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
Sending an ordinary chat message while a form is open voids the form: the card closes as cancelled and the model is told its questions went unanswered as part of the turn the message itself starts.
|
|
357
|
+
Forms are saved in the conversation and survive restarts. Only a form at the end of the active conversation is open; answering, skipping, or sending another message closes it. Earlier forms remain expandable for read-only review. Returning the conversation to a question reopens it; archived conversations remain read-only.
|
|
388
358
|
|
|
389
359
|
Restart the session daemon after changing `askUser` or after upgrading PI WEB to a version that introduces this tool. For the systemd user service, run `systemctl --user restart pi-web-sessiond`.
|
|
390
360
|
|
|
@@ -392,7 +362,7 @@ Restart the session daemon after changing `askUser` or after upgrading PI WEB to
|
|
|
392
362
|
|
|
393
363
|
Pi extensions can show confirmation, selection, and text-input dialogs inline in the session transcript, including while a session starts or a tool runs. Dialog support is always on; there is no enable flag. See [Pi extension dialogs in PI WEB](https://pi-web.dev/plugins#pi-extension-dialogs) for details.
|
|
394
364
|
|
|
395
|
-
`extensionDialogsTimeoutMs`
|
|
365
|
+
`extensionDialogsTimeoutMs` cancels unanswered extension dialogs after the configured interval. It defaults to `300000` (5 minutes); set it to `0` to wait forever. If the extension sets its own timeout, the sooner deadline applies.
|
|
396
366
|
|
|
397
367
|
The key is edited directly in the global config file. Restart the session daemon after changing it — for the systemd user service, run `systemctl --user restart pi-web-sessiond`.
|
|
398
368
|
|
|
@@ -410,7 +380,44 @@ The `plugins` key controls desired enablement and JSON settings for PI WEB brows
|
|
|
410
380
|
}
|
|
411
381
|
```
|
|
412
382
|
|
|
413
|
-
Plugins are enabled by default unless their package metadata declares `defaultEnabled: false`, as Captain's Log does. Explicit `plugins.<id>.enabled` config overrides the package default. `plugins.<id>.enabled: false` hides a browser-only entry on the next page load. For a server-backed entry, desired disablement takes effect on the next sessiond start; its paired browser entry continues to follow the still-active server entry until that restart. The bundled `pi-web.terminal` plugin is required during normal startup: ordinary config cannot disable it, and Settings renders it non-editable.
|
|
383
|
+
Plugins are enabled by default unless their package metadata declares `defaultEnabled: false`, as Captain's Log does. Explicit `plugins.<id>.enabled` config overrides the package default. `plugins.<id>.enabled: false` hides a browser-only entry on the next page load. For a server-backed entry, desired disablement takes effect on the next sessiond start; its paired browser entry continues to follow the still-active server entry until that restart. The bundled `pi-web.terminal` plugin is required during normal startup: ordinary config cannot disable it, and Settings renders it non-editable. Global server settings are captured at daemon startup; diagnostics do not expose their values.
|
|
384
|
+
|
|
385
|
+
#### Project plugin settings
|
|
386
|
+
|
|
387
|
+
Supporting server plugins, including Git, accept `plugins.<id>.settings` in `<project>/.pi-web/config.json` at the registered project's path, not in individual worktrees. Project top-level keys override global settings; nested objects are replaced rather than deep-merged. Plugin enablement stays global.
|
|
388
|
+
|
|
389
|
+
After changing global or project server-plugin settings, manually restart the target session daemon, then reload the browser. A browser reload, web/API restart, or Pi's `/reload` is insufficient. The daemon restart can interrupt sessions and terminals; finish important work and restart from outside its hosted sessions.
|
|
390
|
+
|
|
391
|
+
#### Git worktree discovery hooks
|
|
392
|
+
|
|
393
|
+
`plugins.git.settings.workspaceDiscoveryHooks` enables automatic worktree discovery on supported Git builds (Git 2.54+). It defaults to `true` and preserves existing hooks. See [Automatic Git worktree discovery](https://pi-web.dev/plugins#automatic-git-worktree-discovery).
|
|
394
|
+
|
|
395
|
+
To opt out, merge this into machine config or the registered project's `.pi-web/config.json`:
|
|
396
|
+
|
|
397
|
+
```json
|
|
398
|
+
{
|
|
399
|
+
"plugins": {
|
|
400
|
+
"git": {
|
|
401
|
+
"settings": {
|
|
402
|
+
"workspaceDiscoveryHooks": false
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Project values override the machine default. Changes require a manual session-daemon restart. Disabling hooks leaves the Git plugin and ordinary workspace discovery available.
|
|
410
|
+
|
|
411
|
+
<a id="git-instance-namespace"></a>
|
|
412
|
+
#### Git worktree discovery when running multiple instances
|
|
413
|
+
|
|
414
|
+
Most installations need no changes. Docker dev automatically uses `dev` to keep its worktree notifications separate from production; production keeps its existing behavior.
|
|
415
|
+
|
|
416
|
+
For a custom setup where instances share a PI WEB data directory, set `PI_WEB_INSTANCE_NAMESPACE=dev` in the dev session daemon's environment and leave it unset in production. Use a different name for each additional instance: 1–32 letters, digits, underscores or hyphens, starting with a letter or digit.
|
|
417
|
+
|
|
418
|
+
Restart the affected daemon to apply the change; for Docker, recreate the affected containers. This interrupts active sessions and terminals, so finish important work first. This setting separates Git notifications only; separate data directories are still recommended for independent instances.
|
|
419
|
+
|
|
420
|
+
Keep the name stable. If you need to retire a name, disable [discovery hooks](#git-worktree-discovery-hooks) while still using that name before switching, so the old notifications are removed.
|
|
414
421
|
|
|
415
422
|
#### Desired versus active plugin state
|
|
416
423
|
|
|
@@ -449,6 +456,24 @@ pi-web plugins safe-start clear --restart
|
|
|
449
456
|
|
|
450
457
|
Ordinary import/activation/start/health failures are quarantined when possible, but server plugins are trusted in-process code, share sessiond's event loop, and are not crash-isolated. `bundled-only` bypasses external plugin failures; `none` is the emergency level that also bypasses bundled server plugins. Setting, clearing, or disabling takes effect for server code only after sessiond restarts, and that restart may interrupt active sessions/runtime ownership.
|
|
451
458
|
|
|
459
|
+
### Theme default and device choices
|
|
460
|
+
|
|
461
|
+
In **Settings → General → Theme**, choose a theme and **Auto** mode, then:
|
|
462
|
+
|
|
463
|
+
- **Use on this device** saves a choice for this browser only.
|
|
464
|
+
- **Set as default** shares a default without replacing existing device choices.
|
|
465
|
+
- **Use the default** clears this browser's override.
|
|
466
|
+
|
|
467
|
+
Device choices take precedence over the configured default, then the built-in default (PI WEB Dark with Auto on). Auto follows the device's light/dark preference for paired themes; unpaired themes stay selected. Unavailable themes temporarily fall back to Classic without erasing the choice.
|
|
468
|
+
|
|
469
|
+
The default belongs to the gateway, not a project or remote machine. Changes apply after settings save or browser config refresh, with no service restart.
|
|
470
|
+
|
|
471
|
+
```json
|
|
472
|
+
{ "defaultTheme": { "themeId": "themes:pi-web-dark", "auto": true } }
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
Use a theme contribution ID rather than a display name. Built-in IDs are `themes:pi-web-dark`, `themes:pi-web-light`, and `themes:classic`.
|
|
476
|
+
|
|
452
477
|
### Shortcut config
|
|
453
478
|
|
|
454
479
|
Shortcut values are keyed by action id. Values are shortcut strings such as `mod+k`, `g p`, or `shift+enter`; `null` disables that action's shortcut.
|
|
@@ -467,11 +492,11 @@ Shortcut values are keyed by action id. Values are shortcut strings such as `mod
|
|
|
467
492
|
|
|
468
493
|
Prefer Settings → Keyboard for editing, recording, disabling, or resetting shortcuts. `mod` accepts Ctrl or ⌘. Browsers and operating systems may reserve some combinations.
|
|
469
494
|
|
|
470
|
-
App shortcuts
|
|
495
|
+
App shortcuts support single keys or sequences. Avoid conflicting bindings and browser-reserved combinations. Unmodified and Shift-only shortcuts do not start while editing text.
|
|
471
496
|
|
|
472
|
-
|
|
497
|
+
Composer send bindings accept one key combination, not sequences. Desktop defaults to Enter; touch or narrow screens default to Shift+Enter. The touch binding (`composer.send.mobile`) applies with a coarse primary pointer or a viewport at most 760px wide. Unassigned Enter/Shift+Enter insert newlines; Enter accepts a selected completion first. `null` disables keyboard submission, not the send button.
|
|
473
498
|
|
|
474
|
-
Existing browser-local Enter preferences remain the fallback until
|
|
499
|
+
Existing browser-local Enter preferences remain the fallback until a composer binding is configured. Reset restores that fallback. New bindings are saved in gateway config.
|
|
475
500
|
|
|
476
501
|
## Prompt completions
|
|
477
502
|
|