@gang-of-beads/pi-web-plugin-api 0.1.0-alpha.2 → 0.1.0-alpha.4
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/plugin-api.d.ts +74 -3
- package/dist/server-plugin-api.d.ts +8 -0
- package/dist/shared/apiTypes.d.ts +33 -1
- package/dist/shared/apiTypes.js +2 -0
- package/dist/shared/pluginApiTypes.d.ts +65 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Lightweight browser and server plugin contracts for [PI WEB](https://github.com/
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
npm install --save-dev @gang-of-beads/pi-web-plugin-api
|
|
8
|
+
npm install --save-dev @gang-of-beads/pi-web-plugin-api
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
Browser plugins also install `lit@^3`: the browser declarations use Lit's template and style types, including when rendering through the host's `context.html`. Server-only plugins do not need Lit; their declaration dependencies are included.
|
|
@@ -28,7 +28,7 @@ Bundle runtime imports into each plugin half: PI WEB loads plugin modules as the
|
|
|
28
28
|
|
|
29
29
|
## Compatibility
|
|
30
30
|
|
|
31
|
-
`0.1.0-alpha.
|
|
31
|
+
`0.1.0-alpha.4` contains the declarations shipped by PI WEB `2.202610.13`: a server plugin receives its private settings as `context.serverSettings`, and the config types carry `serverSettings`; a composer contribution's context carries a `signal` that aborts when the composer leaves its session; and a browser plugin can list and add project folders on the selected machine through `projectFolders`. Browser plugins declare `apiVersion: 2`; server plugins declare `apiVersion: 1`. The existing `@gang-of-beads/pi-web/plugin-api` and `@gang-of-beads/pi-web/server-plugin-api` entry points remain available.
|
|
32
32
|
|
|
33
33
|
This is an alpha release. Host-internal members marked unstable are not a supported third-party contract.
|
|
34
34
|
|
package/dist/plugin-api.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CSSResultGroup, TemplateResult } from "lit";
|
|
2
|
-
import type { FileSuggestion, ForegroundToken, PluginListModel, PluginReadFailure, LegacyThemeToken, SemanticSurfaceToken, ShapeTypographyToken, TerminalCommandRun, TerminalInfo, DeleteWorkspaceFileResponse, FileContentResponse, FileTreeResponse, JsonValue, MachineKind, MoveWorkspaceFileOptions, MoveWorkspaceFileResponse, PiWebStatusResponse, TerminalCommandRunHandle, WorkspaceProviderMetadata, WorkspaceRemovalPresentation, WorkspaceUploadBatchProgress, WorkspaceUploadCancelHandle, WriteWorkspaceFileOptions, WriteWorkspaceFileResponse, MachineConnection } from "./shared/pluginApiTypes.js";
|
|
2
|
+
import type { FileSuggestion, ProjectFolderListing, ProjectFolderListingRequest, ForegroundToken, MessageRoleToken, PluginListModel, PluginReadFailure, LegacyThemeToken, SemanticSurfaceToken, ShapeTypographyToken, TerminalCommandRun, TerminalInfo, DeleteWorkspaceFileResponse, FileContentResponse, FileTreeResponse, JsonValue, MachineKind, MoveWorkspaceFileOptions, MoveWorkspaceFileResponse, PiWebStatusResponse, TerminalCommandRunHandle, WorkspaceProviderMetadata, WorkspaceRemovalPresentation, WorkspaceUploadBatchProgress, WorkspaceUploadCancelHandle, WriteWorkspaceFileOptions, WriteWorkspaceFileResponse, MachineConnection } from "./shared/pluginApiTypes.js";
|
|
3
3
|
export type { ThemeToken } from "./shared/pluginApiTypes.js";
|
|
4
|
-
export type { FileSuggestion, LegacyThemeToken, SemanticSurfaceToken, TerminalInfo, FileContentMediaType, FileContentResponse, FileTreeEntry, FileTreeResponse, JsonObject, JsonPrimitive, JsonValue, MachineConnection, MachineKind, PiWebComponentStatus, PiWebDockerMode, PluginListAction, PluginListGroup, PluginListModel, PluginListRead, PluginListRow, PluginListStatus, PluginListTone, PluginListWords, PluginReadFailure, PiWebInstallationInfo, PiWebInstallationKind, PiWebPackageManager, PiWebReleaseStatus, PiWebServiceComponent, PiWebStatusMessage, PiWebStatusResponse, PiWebStatusSeverity, PiWebVersionResponse, TerminalCommandRun, TerminalCommandRunHandle, TerminalCommandRunStatus, WorkspaceProviderCapabilities, WorkspaceProviderMetadata, WorkspaceRemovalPresentation, WorkspaceFileUploadProgress, WorkspaceUploadBatchFileProgress, WorkspaceUploadBatchProgress, WorkspaceUploadCancelHandle, WriteWorkspaceFileOptions, WriteWorkspaceFileResponse, DeleteWorkspaceFileResponse, MoveWorkspaceFileOptions, MoveWorkspaceFileResponse, } from "./shared/pluginApiTypes.js";
|
|
4
|
+
export type { FileSuggestion, ProjectFolderContents, ProjectFolderCrumb, ProjectFolderEntry, ProjectFolderListing, ProjectFolderListingRequest, ProjectFolderUnreadableCause, LegacyThemeToken, SemanticSurfaceToken, TerminalInfo, FileContentMediaType, FileContentResponse, FileTreeEntry, FileTreeResponse, JsonObject, JsonPrimitive, JsonValue, MachineConnection, MachineKind, PiWebComponentStatus, PiWebDockerMode, PluginListAction, PluginListGroup, PluginListModel, PluginListRead, PluginListRow, PluginListStatus, PluginListTone, PluginListWords, PluginReadFailure, PiWebInstallationInfo, PiWebInstallationKind, PiWebPackageManager, PiWebReleaseStatus, PiWebServiceComponent, PiWebStatusMessage, PiWebStatusResponse, PiWebStatusSeverity, PiWebVersionResponse, TerminalCommandRun, TerminalCommandRunHandle, TerminalCommandRunStatus, WorkspaceProviderCapabilities, WorkspaceProviderMetadata, WorkspaceRemovalPresentation, WorkspaceFileUploadProgress, WorkspaceUploadBatchFileProgress, WorkspaceUploadBatchProgress, WorkspaceUploadCancelHandle, WriteWorkspaceFileOptions, WriteWorkspaceFileResponse, DeleteWorkspaceFileResponse, MoveWorkspaceFileOptions, MoveWorkspaceFileResponse, } from "./shared/pluginApiTypes.js";
|
|
5
5
|
export { CORE_STATUS_FLAGS } from "./shared/machineStatus.js";
|
|
6
6
|
export { workspaceFileRefusalOf, type WorkspaceFileRefusal } from "./shared/apiTypes.js";
|
|
7
7
|
export type PluginId = string;
|
|
@@ -492,12 +492,44 @@ export interface CodeFenceRendererContribution {
|
|
|
492
492
|
render: (source: string) => Node | Promise<Node>;
|
|
493
493
|
}
|
|
494
494
|
export type ComposerSlot = "leading" | "trailing";
|
|
495
|
+
/**
|
|
496
|
+
* What a composer control sees, bound to the machine and session the composer
|
|
497
|
+
* showed when the context was made. The composer is reused across sessions and
|
|
498
|
+
* machines, so work that outlives the click (a dictation still streaming) stays
|
|
499
|
+
* with the session it started in.
|
|
500
|
+
*/
|
|
495
501
|
export interface ComposerRuntimeContext {
|
|
502
|
+
/**
|
|
503
|
+
* The session the context is bound to. A context made while a new session
|
|
504
|
+
* was still starting reports the session's real id once it has one: the
|
|
505
|
+
* same session under its lasting id, so read it when you need it rather
|
|
506
|
+
* than keeping a copy. It changes at most that once, and only then.
|
|
507
|
+
*/
|
|
496
508
|
sessionId: string | undefined;
|
|
497
509
|
machineId: string | undefined;
|
|
498
510
|
draft: string;
|
|
499
511
|
busy: boolean;
|
|
512
|
+
/**
|
|
513
|
+
* Aborted when the composer leaves this context's session: the reader
|
|
514
|
+
* switches session or machine, or the composer unmounts. A new session
|
|
515
|
+
* getting its real id is not leaving it. Already aborted if that happened
|
|
516
|
+
* before the context reached the plugin. Stop work bound to the session when
|
|
517
|
+
* it fires. Absent on hosts older than this member: there, nothing tells the
|
|
518
|
+
* plugin the composer left.
|
|
519
|
+
*/
|
|
520
|
+
signal?: AbortSignal;
|
|
521
|
+
/**
|
|
522
|
+
* Append text to this session's draft. Once the composer has left the
|
|
523
|
+
* session, the text joins that session's stored draft instead of the one on
|
|
524
|
+
* screen. A context made before the composer had a session has no stored
|
|
525
|
+
* draft, so its writes after the composer left are discarded.
|
|
526
|
+
*/
|
|
500
527
|
insertText: (text: string) => void;
|
|
528
|
+
/**
|
|
529
|
+
* Replace this session's draft. Once the composer has left the session,
|
|
530
|
+
* the stored draft is replaced instead of the one on screen, or the write is
|
|
531
|
+
* discarded if the context was made before the composer had a session.
|
|
532
|
+
*/
|
|
501
533
|
replaceDraft: (text: string) => void;
|
|
502
534
|
notify: (message: string, severity: "info" | "warning" | "error") => void;
|
|
503
535
|
/** Ask the composer to redraw after state only the plugin can see changed. */
|
|
@@ -581,6 +613,41 @@ export interface PluginProjectTrustRead {
|
|
|
581
613
|
readonly decision: boolean | null;
|
|
582
614
|
readonly trusted: boolean;
|
|
583
615
|
}
|
|
616
|
+
/**
|
|
617
|
+
* The add-project dialog's access to one machine's folders, captured when the dialog opens: every
|
|
618
|
+
* folder listing, suggestion, trust read and the final add made through it go to `machine`,
|
|
619
|
+
* whatever is selected afterwards.
|
|
620
|
+
*/
|
|
621
|
+
export interface PluginProjectFolders {
|
|
622
|
+
readonly machine: {
|
|
623
|
+
readonly id: string;
|
|
624
|
+
readonly name: string | undefined;
|
|
625
|
+
};
|
|
626
|
+
listFolder: (request: ProjectFolderListingRequest, signal: AbortSignal) => Promise<PluginProjectFolderReply>;
|
|
627
|
+
directories: (query: string, signal: AbortSignal) => Promise<FileSuggestion[]>;
|
|
628
|
+
trust: (path: string) => Promise<PluginProjectTrustRead>;
|
|
629
|
+
create: (input: PluginProjectCreateInput) => Promise<string | undefined>;
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* How one folder listing came back, naming the machine that was asked: the listing; a new folder
|
|
633
|
+
* name that machine refuses, with its reason; a machine too old to list folders; or no answer.
|
|
634
|
+
*/
|
|
635
|
+
export type PluginProjectFolderReply = {
|
|
636
|
+
readonly kind: "listed";
|
|
637
|
+
readonly machineId: string;
|
|
638
|
+
readonly listing: ProjectFolderListing;
|
|
639
|
+
} | {
|
|
640
|
+
readonly kind: "name-refused";
|
|
641
|
+
readonly machineId: string;
|
|
642
|
+
readonly reason: string;
|
|
643
|
+
} | {
|
|
644
|
+
readonly kind: "unsupported";
|
|
645
|
+
readonly machineId: string;
|
|
646
|
+
} | {
|
|
647
|
+
readonly kind: "unanswered";
|
|
648
|
+
readonly machineId: string;
|
|
649
|
+
readonly reason: string;
|
|
650
|
+
};
|
|
584
651
|
export interface PluginPromptEditor {
|
|
585
652
|
/** Insert text at the current cursor position. Replaces any selection.
|
|
586
653
|
* If the editor is not focused, focuses it first.
|
|
@@ -627,6 +694,8 @@ export interface PluginRuntimeContext {
|
|
|
627
694
|
projectDirectories: (query: string, signal: AbortSignal) => Promise<FileSuggestion[]>;
|
|
628
695
|
/** Server-resolved existing trust for a raw path, on the selected machine. */
|
|
629
696
|
projectTrust: (path: string) => Promise<PluginProjectTrustRead>;
|
|
697
|
+
/** Folder access bound to the machine selected now, for the add-project dialog. Absent on hosts without the folder browser. */
|
|
698
|
+
projectFolders?: () => PluginProjectFolders;
|
|
630
699
|
configureAuth: () => void | Promise<void>;
|
|
631
700
|
logoutAuth: () => void | Promise<void>;
|
|
632
701
|
openThemePicker: () => void;
|
|
@@ -903,9 +972,11 @@ export interface WorkspaceLabelContribution {
|
|
|
903
972
|
items: (context: WorkspaceLabelContext) => WorkspaceLabelItem[];
|
|
904
973
|
}
|
|
905
974
|
export type ThemeColorScheme = "dark" | "light";
|
|
906
|
-
export type ThemeTokens = Record<LegacyThemeToken, string> & Partial<Record<SemanticSurfaceToken | ForegroundToken | ShapeTypographyToken, string>>;
|
|
975
|
+
export type ThemeTokens = Record<LegacyThemeToken, string> & Partial<Record<SemanticSurfaceToken | ForegroundToken | ShapeTypographyToken | MessageRoleToken, string>>;
|
|
907
976
|
export interface ThemeContribution {
|
|
908
977
|
id: LocalContributionId;
|
|
978
|
+
/** Prefer this available concrete theme; tokens remain the fallback for other hosts. */
|
|
979
|
+
replacedBy?: QualifiedContributionId;
|
|
909
980
|
name: string;
|
|
910
981
|
description?: string;
|
|
911
982
|
order?: number;
|
|
@@ -20,6 +20,14 @@ export interface ServerPluginActivationContext {
|
|
|
20
20
|
readonly packageRoot: string;
|
|
21
21
|
readonly logger: ServerPluginLogger;
|
|
22
22
|
readonly settings: JsonObject;
|
|
23
|
+
/**
|
|
24
|
+
* A JSON copy of this plugin's own private `plugins.<id>.serverSettings` block, taken at
|
|
25
|
+
* activation; `{}` when none is configured. No browser receives it, and no other plugin's block
|
|
26
|
+
* is ever here. Undefined means the host is older and does not supply private settings at all,
|
|
27
|
+
* which is not the same as none configured: a plugin that needs a key should report that host
|
|
28
|
+
* as unable to provide it rather than as unconfigured.
|
|
29
|
+
*/
|
|
30
|
+
readonly serverSettings?: JsonObject;
|
|
23
31
|
/**
|
|
24
32
|
* Durable per-plugin storage. Missing is not empty: `read` answers
|
|
25
33
|
* undefined for a key that was never written, and a corrupt document reads
|
|
@@ -61,8 +61,17 @@ export type PiWebPluginConfigMap = Record<string, PiWebPluginConfig>;
|
|
|
61
61
|
export interface PiWebPluginConfig {
|
|
62
62
|
enabled?: boolean;
|
|
63
63
|
settings?: PiWebPluginSettings;
|
|
64
|
+
/** Raw file/server configuration only; public responses omit this block. */
|
|
65
|
+
serverSettings?: PiWebPluginSettings;
|
|
64
66
|
[key: string]: unknown;
|
|
65
67
|
}
|
|
68
|
+
/** Explicit private-settings operations by plugin id; a plugin the map omits keeps its stored block. */
|
|
69
|
+
export type PiWebServerSettingsUpdates = Record<string, {
|
|
70
|
+
operation: "replace";
|
|
71
|
+
value: PiWebPluginSettings;
|
|
72
|
+
} | {
|
|
73
|
+
operation: "clear";
|
|
74
|
+
}>;
|
|
66
75
|
export interface PiWebPathAccessConfig {
|
|
67
76
|
allowedPaths?: string[];
|
|
68
77
|
}
|
|
@@ -100,6 +109,11 @@ export interface PiWebListTilesConfig {
|
|
|
100
109
|
phone?: ListTilesPerRow;
|
|
101
110
|
desktop?: ListTilesPerRow;
|
|
102
111
|
}
|
|
112
|
+
/** One theme choice, as a browser keeps it locally: a qualified theme id and whether it follows the system. */
|
|
113
|
+
export interface PiWebSharedThemeConfig {
|
|
114
|
+
themeId: `${string}:${string}`;
|
|
115
|
+
auto: boolean;
|
|
116
|
+
}
|
|
103
117
|
export interface PiWebConfigValues {
|
|
104
118
|
host?: string;
|
|
105
119
|
port?: number;
|
|
@@ -122,6 +136,11 @@ export interface PiWebConfigValues {
|
|
|
122
136
|
updateCommand?: string;
|
|
123
137
|
/** Tiles per row in the Navigate lists, per layout; see PiWebListTilesConfig. */
|
|
124
138
|
listTiles?: PiWebListTilesConfig;
|
|
139
|
+
/**
|
|
140
|
+
* The theme every browser of this PI WEB shares (owner, 2026-10-16); absent, each browser keeps
|
|
141
|
+
* its own. Written only through `PUT /api/config/theme`, so a general config save keeps it.
|
|
142
|
+
*/
|
|
143
|
+
theme?: PiWebSharedThemeConfig;
|
|
125
144
|
/**
|
|
126
145
|
* When true, PI WEB appends environment facts to session system prompts:
|
|
127
146
|
* the pi-web session nesting every session runs in, plus container facts in
|
|
@@ -259,6 +278,10 @@ export interface PiWebConfigResponse {
|
|
|
259
278
|
config: PiWebConfigValues;
|
|
260
279
|
effectiveConfig: PiWebConfigValues;
|
|
261
280
|
envOverrides: PiWebConfigEnvOverrides;
|
|
281
|
+
/** Advertised only by the target that implements private settings preservation and explicit updates. */
|
|
282
|
+
serverSettingsProtocol?: 1;
|
|
283
|
+
/** Which plugins hold a `serverSettings` block (an empty block counts); presence only, never validity or a value. */
|
|
284
|
+
serverSettingsConfigured?: Record<string, boolean>;
|
|
262
285
|
}
|
|
263
286
|
export interface Project {
|
|
264
287
|
id: string;
|
|
@@ -343,6 +366,8 @@ export declare const SESSION_UNREAD_COMPLETED_AT_MAX_LENGTH = 64;
|
|
|
343
366
|
export declare const SESSION_NOT_FOUND_CODE = "session-not-found";
|
|
344
367
|
/** The code the web and the daemon answer with for a route they do not have: the machine is older than the page (B16). */
|
|
345
368
|
export declare const ROUTE_MISSING_CODE = "route-missing";
|
|
369
|
+
/** The code the project-folder listing answers with for a new folder name the machine cannot use. */
|
|
370
|
+
export declare const PROJECT_FOLDER_NAME_REFUSED_CODE = "folder-name-refused";
|
|
346
371
|
/**
|
|
347
372
|
* What a failed answer says about the link (B16), in the `transport` field of its error body: the
|
|
348
373
|
* web process found nothing listening where its session daemon should be (the daemon is restarting,
|
|
@@ -686,6 +711,13 @@ export interface QueuedSessionMessage {
|
|
|
686
711
|
* existed, by another client, or by a non-browser caller.
|
|
687
712
|
*/
|
|
688
713
|
clientMessageId?: string;
|
|
714
|
+
/**
|
|
715
|
+
* How many images the message carries. A device handed the message back (Stop, Clear queue,
|
|
716
|
+
* Take back) without its own copy of them can say so instead of returning the words as if
|
|
717
|
+
* that were all. Absent when the daemon does not know: one from before this field existed, or
|
|
718
|
+
* an entry an extension put in pi's queue directly.
|
|
719
|
+
*/
|
|
720
|
+
imageCount?: number;
|
|
689
721
|
}
|
|
690
722
|
/** Length bound for extension-dialog ids. */
|
|
691
723
|
export declare const EXTENSION_DIALOG_ID_MAX_LENGTH = 128;
|
|
@@ -1272,7 +1304,7 @@ export interface SlashCommand {
|
|
|
1272
1304
|
description?: string;
|
|
1273
1305
|
source: "extension" | "prompt" | "skill" | "builtin";
|
|
1274
1306
|
}
|
|
1275
|
-
export type { FileSuggestion } from "./pluginApiTypes.js";
|
|
1307
|
+
export type { FileSuggestion, ProjectFolderContents, ProjectFolderCrumb, ProjectFolderEntry, ProjectFolderListing, ProjectFolderListingRequest, ProjectFolderUnreadableCause } from "./pluginApiTypes.js";
|
|
1276
1308
|
export interface TerminalInfo {
|
|
1277
1309
|
id: string;
|
|
1278
1310
|
cwd: string;
|
package/dist/shared/apiTypes.js
CHANGED
|
@@ -18,6 +18,8 @@ export const SESSION_UNREAD_COMPLETED_AT_MAX_LENGTH = 64;
|
|
|
18
18
|
export const SESSION_NOT_FOUND_CODE = "session-not-found";
|
|
19
19
|
/** The code the web and the daemon answer with for a route they do not have: the machine is older than the page (B16). */
|
|
20
20
|
export const ROUTE_MISSING_CODE = "route-missing";
|
|
21
|
+
/** The code the project-folder listing answers with for a new folder name the machine cannot use. */
|
|
22
|
+
export const PROJECT_FOLDER_NAME_REFUSED_CODE = "folder-name-refused";
|
|
21
23
|
/**
|
|
22
24
|
* What a failed answer says about the link (B16), in the `transport` field of its error body: the
|
|
23
25
|
* web process found nothing listening where its session daemon should be (the daemon is restarting,
|
|
@@ -50,6 +50,60 @@ export interface FileSuggestion {
|
|
|
50
50
|
path: string;
|
|
51
51
|
kind: "tracked" | "untracked" | "other";
|
|
52
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* One folder to list for the add-project folder browser: a path as the reader entered or chose it
|
|
55
|
+
* (empty means the machine's home folder), or, with `child`, a new folder's name under that path.
|
|
56
|
+
* The machine resolves and joins it with its own path rules; the page never splits or joins paths.
|
|
57
|
+
*/
|
|
58
|
+
export interface ProjectFolderListingRequest {
|
|
59
|
+
readonly path: string;
|
|
60
|
+
readonly child?: string;
|
|
61
|
+
}
|
|
62
|
+
/** One step of an absolute path, root first, spelled the way the machine spells it. */
|
|
63
|
+
export interface ProjectFolderCrumb {
|
|
64
|
+
readonly name: string;
|
|
65
|
+
readonly path: string;
|
|
66
|
+
}
|
|
67
|
+
/** A subfolder the folder browser can enter. */
|
|
68
|
+
export interface ProjectFolderEntry {
|
|
69
|
+
readonly name: string;
|
|
70
|
+
readonly path: string;
|
|
71
|
+
}
|
|
72
|
+
/** Why a folder that exists, or might, could not be listed. None of these means the folder is empty. */
|
|
73
|
+
export type ProjectFolderUnreadableCause = "not-a-folder" | "denied" | "timed-out" | "failed";
|
|
74
|
+
/**
|
|
75
|
+
* What one listing found. `complete` is every subfolder; `truncated` is the first `folders` of
|
|
76
|
+
* `total`; `incomplete` stopped before every linked folder was checked; `missing` is a folder that
|
|
77
|
+
* does not exist yet, which adding the project creates; `unreadable` names why it could not be read.
|
|
78
|
+
*/
|
|
79
|
+
export type ProjectFolderContents = {
|
|
80
|
+
readonly kind: "complete";
|
|
81
|
+
readonly folders: readonly ProjectFolderEntry[];
|
|
82
|
+
} | {
|
|
83
|
+
readonly kind: "truncated";
|
|
84
|
+
readonly folders: readonly ProjectFolderEntry[];
|
|
85
|
+
readonly total: number;
|
|
86
|
+
} | {
|
|
87
|
+
readonly kind: "incomplete";
|
|
88
|
+
readonly folders: readonly ProjectFolderEntry[];
|
|
89
|
+
} | {
|
|
90
|
+
readonly kind: "missing";
|
|
91
|
+
} | {
|
|
92
|
+
readonly kind: "unreadable";
|
|
93
|
+
readonly cause: ProjectFolderUnreadableCause;
|
|
94
|
+
readonly detail?: string;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* The machine's answer for one folder: its absolute path, its parent (null at a filesystem root),
|
|
98
|
+
* the path's steps root first, the machine's path separator, and what is inside.
|
|
99
|
+
*/
|
|
100
|
+
export interface ProjectFolderListing {
|
|
101
|
+
readonly path: string;
|
|
102
|
+
readonly parent: string | null;
|
|
103
|
+
readonly crumbs: readonly ProjectFolderCrumb[];
|
|
104
|
+
readonly separator: string;
|
|
105
|
+
readonly contents: ProjectFolderContents;
|
|
106
|
+
}
|
|
53
107
|
export interface FileContentResponse {
|
|
54
108
|
path: string;
|
|
55
109
|
language?: string;
|
|
@@ -214,13 +268,20 @@ export interface PiWebStatusResponse extends PiWebVersionResponse {
|
|
|
214
268
|
*/
|
|
215
269
|
/**
|
|
216
270
|
* Shape and typography stops a theme may pin. Optional by design: a theme
|
|
217
|
-
* that omits them inherits the core's current shape -
|
|
218
|
-
*
|
|
219
|
-
* its rounded sans rendering. Radii follow the published scale; there is no
|
|
271
|
+
* that omits them inherits the core's current shape - the rounded sans
|
|
272
|
+
* Material scale - so a flat or mono theme MUST set these to keep its look. Radii follow the published scale; there is no
|
|
220
273
|
* density or border-width token yet.
|
|
221
274
|
*/
|
|
222
275
|
export type ShapeTypographyToken = "--pi-font-ui" | "--pi-font-display" | "--pi-font-mono" | "--pi-radius-xs" | "--pi-radius-sm" | "--pi-radius-md" | "--pi-radius-lg" | "--pi-radius-xl";
|
|
223
|
-
export type ThemeToken = LegacyThemeToken | SemanticSurfaceToken | ForegroundToken | ShapeTypographyToken;
|
|
276
|
+
export type ThemeToken = LegacyThemeToken | SemanticSurfaceToken | ForegroundToken | ShapeTypographyToken | MessageRoleToken;
|
|
277
|
+
/**
|
|
278
|
+
* Conversation message colours by who wrote the message. Optional: a theme that omits one gets it
|
|
279
|
+
* derived from its own tokens when it is applied (user from the selection colour and accent border,
|
|
280
|
+
* assistant from the surface, system from the purple family), so packs written before these tokens
|
|
281
|
+
* keep their user and assistant look and still get a system message that reads apart from the
|
|
282
|
+
* assistant's (owner, 2026-10-16).
|
|
283
|
+
*/
|
|
284
|
+
export type MessageRoleToken = "--pi-msg-user-bg" | "--pi-msg-user-border" | "--pi-msg-user-header-bg" | "--pi-msg-assistant-bg" | "--pi-msg-assistant-border" | "--pi-msg-assistant-header-bg" | "--pi-msg-system-bg" | "--pi-msg-system-border" | "--pi-msg-system-header-bg";
|
|
224
285
|
/**
|
|
225
286
|
* Foregrounds a theme may name for a filled surface it owns. Optional by
|
|
226
287
|
* design: a theme that omits one keeps the previous fallback, which is why
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gang-of-beads/pi-web-plugin-api",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.4",
|
|
4
4
|
"description": "Lightweight PI WEB browser and server plugin contracts, with TypeScript declarations and public runtime helpers.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Gang of Beads",
|