@prismshadow/penguin-server 0.2.9 → 0.2.10
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 +1 -0
- package/dist/api/types.d.ts +426 -87
- package/dist/auth-token.js +4 -2
- package/dist/auth-token.js.map +1 -1
- package/dist/{chunk-WL5FUO3A.js → chunk-ADZJYDNC.js} +201 -140
- package/dist/chunk-ADZJYDNC.js.map +1 -0
- package/dist/{chunk-OMBFPEGQ.js → chunk-GOO5VUAB.js} +10 -8
- package/dist/chunk-GOO5VUAB.js.map +1 -0
- package/dist/chunk-HMTT2PX4.js +93 -0
- package/dist/chunk-HMTT2PX4.js.map +1 -0
- package/dist/chunk-HOS3W3UP.js +127 -0
- package/dist/chunk-HOS3W3UP.js.map +1 -0
- package/dist/{chunk-OTYHSDV7.js → chunk-Q65VPAQS.js} +2 -2
- package/dist/chunk-Q65VPAQS.js.map +1 -0
- package/dist/index.js +5587 -2922
- package/dist/index.js.map +1 -1
- package/dist/lock.d.ts +9 -1
- package/dist/lock.js +3 -1
- package/dist/machine-status.d.ts +18 -0
- package/dist/machine-status.js +37 -0
- package/dist/machine-status.js.map +1 -0
- package/dist/reset-admin-password.js +6 -4
- package/dist/reset-admin-password.js.map +1 -1
- package/package.json +6 -3
- package/web-dist/assets/addon-clipboard-1cARCaK9.js +1 -0
- package/web-dist/assets/{addon-fit-BjXzaLkS.js → addon-fit-BWdzl8Er.js} +1 -1
- package/web-dist/assets/{addon-web-links-D4HvCIde.js → addon-web-links-DjXuvn4Z.js} +1 -1
- package/web-dist/assets/{highlighter-Di8euoN5.js → highlighter-Cu43iYr8.js} +1 -1
- package/web-dist/assets/index-Bm9n7ZV-.js +457 -0
- package/web-dist/assets/index-DR4PrRzS.css +1 -0
- package/web-dist/assets/{xterm-XhYBaOEK.js → xterm-DKcY6q-I.js} +1 -1
- package/web-dist/index.html +2 -2
- package/dist/chunk-OMBFPEGQ.js.map +0 -1
- package/dist/chunk-OTYHSDV7.js.map +0 -1
- package/dist/chunk-WL5FUO3A.js.map +0 -1
- package/web-dist/assets/index-C6i84Esu.js +0 -451
- package/web-dist/assets/index-DW00p4Ny.css +0 -1
package/dist/api/types.d.ts
CHANGED
|
@@ -370,7 +370,7 @@ interface ModelInfo {
|
|
|
370
370
|
interface ModelsResponse {
|
|
371
371
|
/** Paired reference to the default Model. */
|
|
372
372
|
defaultModel?: ModelRefDto;
|
|
373
|
-
/** Vision model used as a proxy reader for
|
|
373
|
+
/** Vision model used as a proxy reader for read_file (describes images when the session model has vision=false). */
|
|
374
374
|
visionModel?: ModelRefDto;
|
|
375
375
|
/**
|
|
376
376
|
* When the Project's model/credential config last changed (ISO; the config file's mtime,
|
|
@@ -416,7 +416,7 @@ interface ModelUpdateEntry {
|
|
|
416
416
|
interface ModelsUpdateRequest {
|
|
417
417
|
/** Must be included in models (matched by paired reference). */
|
|
418
418
|
defaultModel?: ModelRefDto;
|
|
419
|
-
/** Vision model used as a proxy reader for
|
|
419
|
+
/** Vision model used as a proxy reader for read_file: must be included in models and not annotated vision=false; omitted keeps the existing value. */
|
|
420
420
|
visionModel?: ModelRefDto;
|
|
421
421
|
models: ModelUpdateEntry[];
|
|
422
422
|
}
|
|
@@ -708,12 +708,12 @@ interface VaultEntryUpdate {
|
|
|
708
708
|
interface VaultUpdateRequest {
|
|
709
709
|
entries: VaultEntryUpdate[];
|
|
710
710
|
}
|
|
711
|
-
/** One installed
|
|
712
|
-
interface
|
|
713
|
-
/**
|
|
711
|
+
/** One installed plugin (a skill or a hook package) the library carries a higher version of (see {@link AgentSummary.pluginUpdates}). */
|
|
712
|
+
interface PluginUpdateRef {
|
|
713
|
+
/** Plugin name — what `POST …/plugins` reinstalls to bring the Agent up to date. */
|
|
714
714
|
name: string;
|
|
715
|
-
/** The LIBRARY's version, i.e. what installing again would bring, not what is on disk. */
|
|
716
|
-
version:
|
|
715
|
+
/** The LIBRARY's version (`YYYY.MM.DD.N`), i.e. what installing again would bring, not what is on disk. */
|
|
716
|
+
version: string;
|
|
717
717
|
}
|
|
718
718
|
interface AgentSummary {
|
|
719
719
|
agentId: string;
|
|
@@ -740,14 +740,17 @@ interface AgentSummary {
|
|
|
740
740
|
scheduleCount: number;
|
|
741
741
|
/** Installed Skill count (number of agent_state/skills/<name>/ directories with a SKILL.md). */
|
|
742
742
|
skillCount: number;
|
|
743
|
-
/**
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
*
|
|
747
|
-
*
|
|
743
|
+
/** Installed hook-package count (number of agent_state/hooks/<name>/ directories with a hooks.json). */
|
|
744
|
+
hookCount: number;
|
|
745
|
+
/**
|
|
746
|
+
* Installed plugins the built-in library has moved past — a skill or a hook package whose
|
|
747
|
+
* on-disk version is behind the library plugin that ships it — each with the library version
|
|
748
|
+
* on offer: the plugin-library update gate, riding along on the Agent list so a badge over
|
|
749
|
+
* that page costs no request of its own. Empty when nothing is behind. Skills the library
|
|
750
|
+
* does not carry (installed from a zip or a picked directory) are never listed: there is no
|
|
748
751
|
* library version for them to be behind.
|
|
749
752
|
*/
|
|
750
|
-
|
|
753
|
+
pluginUpdates: PluginUpdateRef[];
|
|
751
754
|
/** Memory count (topic files summed over the scope directories under agent_state/memory/, independent of the memory switch). */
|
|
752
755
|
memoryCount: number;
|
|
753
756
|
}
|
|
@@ -761,11 +764,12 @@ interface AgentCreateRequest {
|
|
|
761
764
|
name?: string;
|
|
762
765
|
description?: string;
|
|
763
766
|
/**
|
|
764
|
-
* Library
|
|
765
|
-
* exist in the library (404 `
|
|
766
|
-
*
|
|
767
|
+
* Library plugin names installed into the new Agent, seeding it at creation — each plugin's
|
|
768
|
+
* skills and hook package. Every name must exist in the library (404 `unknown_plugin`
|
|
769
|
+
* otherwise, before anything is created); omitted or empty leaves the Agent with nothing
|
|
770
|
+
* installed, which is what a plain Agent gets by default.
|
|
767
771
|
*/
|
|
768
|
-
|
|
772
|
+
plugins?: string[];
|
|
769
773
|
/**
|
|
770
774
|
* Skills imported from a directory on disk instead of the library. `skillsDirectory` is the
|
|
771
775
|
* absolute path the user picked and `directorySkills` are the names to install from it, read
|
|
@@ -778,7 +782,7 @@ interface AgentCreateRequest {
|
|
|
778
782
|
/**
|
|
779
783
|
* Base64 of an exported Agent State snapshot package (`.tar.gz`): the new Agent is
|
|
780
784
|
* initialized from the package instead of the default template. Mutually exclusive with
|
|
781
|
-
*
|
|
785
|
+
* seeding (`plugins` / `skillsDirectory`) — the package carries its own skills and hooks.
|
|
782
786
|
* Explicit `name` / `description` override the package's values; absent ones keep them.
|
|
783
787
|
*/
|
|
784
788
|
dataBase64?: string;
|
|
@@ -840,6 +844,16 @@ interface AgentSchedulesConfigDto {
|
|
|
840
844
|
/** Whether the stored template carries `{{SCHEDULES}}`; POST …/schedules/template-placeholder inserts it explicitly. */
|
|
841
845
|
templateHasPlaceholder: boolean;
|
|
842
846
|
}
|
|
847
|
+
/**
|
|
848
|
+
* Hook config, edited on the Hooks tab. One Agent-level switch and no prompt: hook packages
|
|
849
|
+
* are scripts run at the loop's hook points, not text injected into the context. `enabled`
|
|
850
|
+
* reports the effective value (a config with no `hooks` section reads as enabled, matching
|
|
851
|
+
* core).
|
|
852
|
+
*/
|
|
853
|
+
interface AgentHooksConfigDto {
|
|
854
|
+
/** Whether a Session created from now on runs the installed hook packages (they stay installed either way). */
|
|
855
|
+
enabled: boolean;
|
|
856
|
+
}
|
|
843
857
|
/** Structured view of system_config.yaml (for the edit form). */
|
|
844
858
|
interface AgentConfigDto {
|
|
845
859
|
name?: string;
|
|
@@ -860,6 +874,7 @@ interface AgentConfigDto {
|
|
|
860
874
|
vault: AgentVaultConfigDto;
|
|
861
875
|
skills: AgentSkillsConfigDto;
|
|
862
876
|
schedules: AgentSchedulesConfigDto;
|
|
877
|
+
hooks: AgentHooksConfigDto;
|
|
863
878
|
toolsBuiltin: ToolDefinitionConfig[];
|
|
864
879
|
mcpServers: MCPServerConfig[];
|
|
865
880
|
}
|
|
@@ -919,6 +934,10 @@ interface AgentConfigUpdateRequest {
|
|
|
919
934
|
enabled?: boolean;
|
|
920
935
|
prompt?: string;
|
|
921
936
|
};
|
|
937
|
+
/** The Agent-level hook switch; it has no prompt half. */
|
|
938
|
+
hooks?: {
|
|
939
|
+
enabled?: boolean;
|
|
940
|
+
};
|
|
922
941
|
toolsBuiltin?: ToolDefinitionConfig[];
|
|
923
942
|
mcpServers?: MCPServerConfig[];
|
|
924
943
|
};
|
|
@@ -1044,10 +1063,12 @@ interface SessionInfo {
|
|
|
1044
1063
|
approvalMode: ApprovalMode;
|
|
1045
1064
|
/**
|
|
1046
1065
|
* Thinking level pinned for this Session (set via PATCH; the Web App's in-chat picker).
|
|
1047
|
-
* Unset = never pinned:
|
|
1048
|
-
*
|
|
1049
|
-
*
|
|
1050
|
-
*
|
|
1066
|
+
* Unset = never pinned: each model context the Session opens reads the Agent config's
|
|
1067
|
+
* `model.thinking_level`, so config edits keep taking effect. Once pinned it survives
|
|
1068
|
+
* reloads and applies from the Session's very next LLM request — the thinking level is
|
|
1069
|
+
* the soft-limited runtime parameter, changeable mid-context at the cost of the
|
|
1070
|
+
* provider's cached context (the picker advises compacting first) — and every later
|
|
1071
|
+
* context opens at it; an Agent-config change no longer moves it.
|
|
1051
1072
|
*/
|
|
1052
1073
|
thinkingLevel?: ThinkingLevelName;
|
|
1053
1074
|
/** Short title auto-generated by the model after the first turn; unset until generated (frontend shows "New Chat"). */
|
|
@@ -1090,6 +1111,23 @@ interface SessionInfo {
|
|
|
1090
1111
|
tracePath?: string;
|
|
1091
1112
|
/** Present when the Session has an ENABLED messaging binding: its channel (the sidebar row's per-channel indicator). */
|
|
1092
1113
|
messagingChannel?: MessagingChannel;
|
|
1114
|
+
/**
|
|
1115
|
+
* Background work the Session's loaded runtime still owns: command sessions running past
|
|
1116
|
+
* their yield window (`exec_command` promotions and `run_in_background` launches) and
|
|
1117
|
+
* background subagent sessions mid-round. Read from the runtime's in-memory registries —
|
|
1118
|
+
* no Trace is consulted — and present only while at least one count is non-zero, so a
|
|
1119
|
+
* Session that is not loaded (a resumed entry starts with empty registries) and one with
|
|
1120
|
+
* nothing running both omit it. Changes are pushed as `session_background` on the user
|
|
1121
|
+
* channel; list rows and the single-session GET carry the same field.
|
|
1122
|
+
*/
|
|
1123
|
+
backgroundTasks?: SessionBackgroundTasks;
|
|
1124
|
+
}
|
|
1125
|
+
/** The background-task counts of one Session (see SessionInfo.backgroundTasks). */
|
|
1126
|
+
interface SessionBackgroundTasks {
|
|
1127
|
+
/** Background command sessions whose process is still running. */
|
|
1128
|
+
processes: number;
|
|
1129
|
+
/** Background subagent sessions (promoted to a `subagent_id`) currently mid-round. */
|
|
1130
|
+
subagents: number;
|
|
1093
1131
|
}
|
|
1094
1132
|
/**
|
|
1095
1133
|
* Session list category, the sidebar's four-way split applied server-side: archived wins
|
|
@@ -1110,6 +1148,13 @@ interface SessionsResponse {
|
|
|
1110
1148
|
* content that lives in other Workspaces.
|
|
1111
1149
|
*/
|
|
1112
1150
|
workspaceCounts?: Record<string, SessionCategoryCounts>;
|
|
1151
|
+
/**
|
|
1152
|
+
* Present with `counts`: each Workspace path's newest Session (any category), as its
|
|
1153
|
+
* `createdAt`. With `workspaceCounts` this is what lets the sidebar list every Workspace
|
|
1154
|
+
* that holds Sessions and place the groups by recency before — or without — loading any
|
|
1155
|
+
* of their rows.
|
|
1156
|
+
*/
|
|
1157
|
+
workspaceLatest?: Record<string, string>;
|
|
1113
1158
|
}
|
|
1114
1159
|
/** Server directory browsing (advanced new-Workspace picker): starts from the home directory by default, can navigate up to the root. */
|
|
1115
1160
|
interface DirEntryInfo {
|
|
@@ -1184,9 +1229,10 @@ interface SessionPatchRequest {
|
|
|
1184
1229
|
approvalMode?: ApprovalMode;
|
|
1185
1230
|
/**
|
|
1186
1231
|
* Pin this Session's thinking level (`none | low | medium | high | xhigh | max`, anything else
|
|
1187
|
-
* is a 400). It
|
|
1188
|
-
*
|
|
1189
|
-
* the picker
|
|
1232
|
+
* is a 400). It replaces the Agent-config fallback for this Session and applies from the
|
|
1233
|
+
* very next LLM request — soft-limited: a mid-context change is allowed, at the cost of
|
|
1234
|
+
* the provider's cached context, which is why the picker advises compacting first. There
|
|
1235
|
+
* is no unpin: the picker only offers concrete levels.
|
|
1190
1236
|
*/
|
|
1191
1237
|
thinkingLevel?: ThinkingLevelName;
|
|
1192
1238
|
/** Archive / unarchive (default list hides archived). */
|
|
@@ -1250,6 +1296,14 @@ interface MessagesPageInfo {
|
|
|
1250
1296
|
prior: {
|
|
1251
1297
|
subagentTokens: number;
|
|
1252
1298
|
elapsedMs: number;
|
|
1299
|
+
/**
|
|
1300
|
+
* Model-API time and tool wall time accrued before this window, the breakdown of
|
|
1301
|
+
* `elapsedMs` the chat header shows under it. Seeded together with their total: seeding
|
|
1302
|
+
* one alone would put a full elapsed time beside components covering only the window.
|
|
1303
|
+
* The two may overlap and do not partition `elapsedMs` (see `TraceTaskStats.toolMs`).
|
|
1304
|
+
*/
|
|
1305
|
+
apiMs: number;
|
|
1306
|
+
toolMs: number;
|
|
1253
1307
|
sessionTokens: number;
|
|
1254
1308
|
contextTokens: number;
|
|
1255
1309
|
};
|
|
@@ -1307,14 +1361,6 @@ type TaskInputPart = {
|
|
|
1307
1361
|
};
|
|
1308
1362
|
interface TaskCreateRequest {
|
|
1309
1363
|
input: TaskInputPart[];
|
|
1310
|
-
/**
|
|
1311
|
-
* Thinking level for this Task's LLM requests (a per-turn parameter; one of
|
|
1312
|
-
* `none | low | medium | high | xhigh | max`, anything else is a 400). Omitted = falls back to
|
|
1313
|
-
* the Session's pinned level (`SessionInfo.thinkingLevel`) and, when that is unset too,
|
|
1314
|
-
* to the Agent config's `model.thinking_level`. A queued follow-up (`queueIfBusy`) keeps
|
|
1315
|
-
* its level and applies it when it auto-starts.
|
|
1316
|
-
*/
|
|
1317
|
-
thinkingLevel?: ThinkingLevelName;
|
|
1318
1364
|
/**
|
|
1319
1365
|
* Queue instead of 409 when a Task/compaction is already in progress: the input is held
|
|
1320
1366
|
* server-side and auto-starts as an ordinary next task once the session returns to idle
|
|
@@ -1324,14 +1370,16 @@ interface TaskCreateRequest {
|
|
|
1324
1370
|
/**
|
|
1325
1371
|
* Present = goal mode: the input's text becomes the objective (leading `[use_skills]`
|
|
1326
1372
|
* blocks and the like are stripped from the recorded objective; the round-1 message keeps
|
|
1327
|
-
* them) and the
|
|
1328
|
-
* `budget` is the token budget (uncached input + output);
|
|
1373
|
+
* them) and the Session's installed `goal` hook package drives round after round until the
|
|
1374
|
+
* goal reaches a terminal state. `budget` is the token budget (uncached input + output);
|
|
1375
|
+
* omitted or -1 = unlimited. Requires the goal plugin installed on the Agent — 409
|
|
1376
|
+
* `goal_plugin_not_installed` otherwise.
|
|
1329
1377
|
*/
|
|
1330
1378
|
goal?: {
|
|
1331
1379
|
budget?: number;
|
|
1332
1380
|
};
|
|
1333
1381
|
}
|
|
1334
|
-
/** Goal-mode run state
|
|
1382
|
+
/** Goal-mode run state, read from the Session's GOAL.json — the goal plugin's file (the chat page's banner restores from it; a live status on an idle Session reads as `aborted`). */
|
|
1335
1383
|
interface GoalStateView {
|
|
1336
1384
|
objective: string;
|
|
1337
1385
|
status: "active" | "complete" | "blocked" | "budget_limited" | "aborted";
|
|
@@ -1339,7 +1387,6 @@ interface GoalStateView {
|
|
|
1339
1387
|
budget: number;
|
|
1340
1388
|
used: number;
|
|
1341
1389
|
rounds: number;
|
|
1342
|
-
updatedAt: string;
|
|
1343
1390
|
}
|
|
1344
1391
|
interface GoalResponse {
|
|
1345
1392
|
/** The Session's most recent goal run; null if it never ran one. */
|
|
@@ -1455,8 +1502,6 @@ interface RecalledMessageResponse {
|
|
|
1455
1502
|
fileName: string;
|
|
1456
1503
|
dataUrl: string;
|
|
1457
1504
|
}[];
|
|
1458
|
-
/** Follow-up recall only: the per-turn thinking level the entry was queued with, when one was. */
|
|
1459
|
-
thinkingLevel?: ThinkingLevelName;
|
|
1460
1505
|
}
|
|
1461
1506
|
interface ApprovalDecisionRequest {
|
|
1462
1507
|
decision: "allow" | "deny";
|
|
@@ -2002,6 +2047,13 @@ type ServerEvent =
|
|
|
2002
2047
|
queued?: number;
|
|
2003
2048
|
/** Steering messages queued but not yet delivered (absent = none): lets the composer's hint and its content survive reloads. */
|
|
2004
2049
|
pendingSteering?: PendingSteeringInfo[];
|
|
2050
|
+
/**
|
|
2051
|
+
* Steering the run ended without delivering (absent = none) — an interrupt while a tool
|
|
2052
|
+
* was running is the ordinary way to produce one. Handed back rather than discarded: the
|
|
2053
|
+
* composer recalls each by the same handle and restores it into the draft, so the typed
|
|
2054
|
+
* message returns to the input box instead of being lost.
|
|
2055
|
+
*/
|
|
2056
|
+
returnedSteering?: PendingSteeringInfo[];
|
|
2005
2057
|
/** Queued follow-up tasks awaiting auto-start (absent = none): per-entry content + recall handle, alongside the `queued` count. */
|
|
2006
2058
|
pendingFollowUps?: PendingFollowUpInfo[];
|
|
2007
2059
|
/**
|
|
@@ -2043,6 +2095,19 @@ type ServerEvent =
|
|
|
2043
2095
|
lastActiveAt: string;
|
|
2044
2096
|
hasTrace: boolean;
|
|
2045
2097
|
}
|
|
2098
|
+
/**
|
|
2099
|
+
* A Session's background-task counts changed: a command promoted to the background, a
|
|
2100
|
+
* process that exited or was stopped, a background subagent starting or settling a round,
|
|
2101
|
+
* a released session. The counts are the row's `backgroundTasks` as they stand after the
|
|
2102
|
+
* change — zeros included, so a list can clear its mark without refetching. Published to
|
|
2103
|
+
* the user channels of the Project's owner and members, like `session_state`.
|
|
2104
|
+
*/
|
|
2105
|
+
| {
|
|
2106
|
+
type: "session_background";
|
|
2107
|
+
sessionId: string;
|
|
2108
|
+
processes: number;
|
|
2109
|
+
subagents: number;
|
|
2110
|
+
}
|
|
2046
2111
|
/** Last-Event-ID has been evicted from the buffer: the frontend should re-fetch the history endpoint before continuing to consume this connection. */
|
|
2047
2112
|
| {
|
|
2048
2113
|
type: "resync_required";
|
|
@@ -2133,6 +2198,24 @@ interface ContextToolShare {
|
|
|
2133
2198
|
name: string;
|
|
2134
2199
|
tokens: number;
|
|
2135
2200
|
}
|
|
2201
|
+
/**
|
|
2202
|
+
* One file's share of the context: its `read_file` / `edit_file` / `write_file` calls plus their
|
|
2203
|
+
* results, keyed by the file each call named.
|
|
2204
|
+
*/
|
|
2205
|
+
interface ContextFileShare {
|
|
2206
|
+
/**
|
|
2207
|
+
* Workspace-relative when the file is inside the Session's Workspace; otherwise absolute, with
|
|
2208
|
+
* the home directory shortened to `~`. Spellings that resolve to the same file are one row.
|
|
2209
|
+
*/
|
|
2210
|
+
path: string;
|
|
2211
|
+
tokens: number;
|
|
2212
|
+
/** How many calls of each file tool named the file in this context. */
|
|
2213
|
+
ops: {
|
|
2214
|
+
read: number;
|
|
2215
|
+
edit: number;
|
|
2216
|
+
write: number;
|
|
2217
|
+
};
|
|
2218
|
+
}
|
|
2136
2219
|
/**
|
|
2137
2220
|
* What the Session's current model context is made of — the part derived from its messages.
|
|
2138
2221
|
*
|
|
@@ -2143,7 +2226,8 @@ interface ContextToolShare {
|
|
|
2143
2226
|
*
|
|
2144
2227
|
* The six parts partition the context and sum to `total`; `topTools` is a ranking inside
|
|
2145
2228
|
* `toolRequests + toolResults` and can sum to less than those two (a result whose call was not
|
|
2146
|
-
* recorded in the same Trace shard has no tool to be attributed to).
|
|
2229
|
+
* recorded in the same Trace shard has no tool to be attributed to). `topFiles` is the same
|
|
2230
|
+
* ranking narrowed to the three file tools and keyed by the file each call named.
|
|
2147
2231
|
*/
|
|
2148
2232
|
interface SessionContextParts {
|
|
2149
2233
|
systemPrompt: number;
|
|
@@ -2156,6 +2240,8 @@ interface SessionContextParts {
|
|
|
2156
2240
|
total: number;
|
|
2157
2241
|
/** Tools ranked by the context their traffic occupies, descending; at most five. */
|
|
2158
2242
|
topTools: ContextToolShare[];
|
|
2243
|
+
/** Files ranked by the context their file-tool traffic occupies, descending; at most five. */
|
|
2244
|
+
topFiles: ContextFileShare[];
|
|
2159
2245
|
/**
|
|
2160
2246
|
* A completed compaction closed the context these figures describe, and the next one has not
|
|
2161
2247
|
* been written yet: the composition is of what was compacted away, not of what the model now
|
|
@@ -2275,6 +2361,16 @@ interface TraceTaskStats {
|
|
|
2275
2361
|
cacheWrite: number;
|
|
2276
2362
|
output: number;
|
|
2277
2363
|
};
|
|
2364
|
+
/**
|
|
2365
|
+
* This turn's cost in USD: each Request's three buckets at the Project's current rates for
|
|
2366
|
+
* the file's model, at the tier that Request's own timestamp fell in — the rule and the
|
|
2367
|
+
* price lookup the cost center applies to the usage row the same `token_usage` produced,
|
|
2368
|
+
* so this figure, the toolbar's and the cost center's agree on what a request cost. Present
|
|
2369
|
+
* on every turn of a priced file (a turn with no Request reads 0); absent when the model has
|
|
2370
|
+
* no pricing or the file's head names no provider, and then absent from the response's
|
|
2371
|
+
* total as well.
|
|
2372
|
+
*/
|
|
2373
|
+
cost?: number;
|
|
2278
2374
|
/**
|
|
2279
2375
|
* Total LLM generation duration for this turn (the denominator for output TPS; human
|
|
2280
2376
|
* approval wait already deducted). The numerator is simply `tokens.output`: since
|
|
@@ -2282,6 +2378,21 @@ interface TraceTaskStats {
|
|
|
2282
2378
|
* output — there's no second figure to reconcile.
|
|
2283
2379
|
*/
|
|
2284
2380
|
llmMs: number;
|
|
2381
|
+
/**
|
|
2382
|
+
* Wall-clock time this turn spent executing tools: the **union** of its tool spans'
|
|
2383
|
+
* execution intervals (`approvalTs ?? callTs` to `outputTs`), so tools running in parallel
|
|
2384
|
+
* are counted once instead of summed. Two exclusions, both deliberate: the human approval
|
|
2385
|
+
* wait (`callTs` to `approvalTs`) is not tool work, and the argument-generation segment is
|
|
2386
|
+
* the model streaming arguments, already counted in `llmMs`. A span with no `outputTs` —
|
|
2387
|
+
* still running when the file ended, or interrupted — contributes nothing rather than being
|
|
2388
|
+
* extrapolated to now.
|
|
2389
|
+
*
|
|
2390
|
+
* This and `llmMs` may **overlap**: a tool started in the background keeps running while the
|
|
2391
|
+
* model decodes. They are two measured components of the turn's duration, not a partition of
|
|
2392
|
+
* it, and they need not add up to the turn's span (approval waits and harness overhead belong
|
|
2393
|
+
* to neither). Never derive one by subtracting the other from the duration.
|
|
2394
|
+
*/
|
|
2395
|
+
toolMs: number;
|
|
2285
2396
|
}
|
|
2286
2397
|
/** Duration span of a single tool call (complete tool_call message → paired tool_call_output). */
|
|
2287
2398
|
interface ToolCallSpan {
|
|
@@ -2304,6 +2415,21 @@ interface WorkspaceFilesResponse {
|
|
|
2304
2415
|
path: string;
|
|
2305
2416
|
entries: WorkspaceFileEntry[];
|
|
2306
2417
|
}
|
|
2418
|
+
/** Write one Workspace file whole (the Upload button, a drop, and the Files panel's editor). */
|
|
2419
|
+
interface FilesWriteRequest {
|
|
2420
|
+
/** The entire file, base64-encoded (≤14MB decoded). */
|
|
2421
|
+
dataBase64: string;
|
|
2422
|
+
/**
|
|
2423
|
+
* Write precondition: the version marker the caller read off this file's `ETag` on
|
|
2424
|
+
* `GET files/content`. The server compares it against the file's state immediately
|
|
2425
|
+
* before writing and answers 409 `file_changed` — having written nothing — when they
|
|
2426
|
+
* differ, which is what stops the editor's save from quietly dropping what the Agent
|
|
2427
|
+
* wrote during the turn. Omitted by a caller that read no version (an upload creates or
|
|
2428
|
+
* replaces unconditionally); that absence, not a sentinel value, is what says there was
|
|
2429
|
+
* no prior version to match.
|
|
2430
|
+
*/
|
|
2431
|
+
ifVersion?: string;
|
|
2432
|
+
}
|
|
2307
2433
|
/** Batch file existence check (message file cards only list files that actually exist). */
|
|
2308
2434
|
interface FilesStatRequest {
|
|
2309
2435
|
/** Paths relative to the Workspace root (≤100 items, each ≤512 characters). */
|
|
@@ -2375,6 +2501,23 @@ interface TraceAnalysisResponse {
|
|
|
2375
2501
|
* frontend's events are paginated, so self-aggregation would undercount.
|
|
2376
2502
|
*/
|
|
2377
2503
|
elapsedMs: number;
|
|
2504
|
+
/**
|
|
2505
|
+
* The file's model-API time: the sum of the turns' `llmMs` (human approval wait deducted,
|
|
2506
|
+
* compaction requests included, so the scope matches `elapsedMs`).
|
|
2507
|
+
*/
|
|
2508
|
+
apiMs: number;
|
|
2509
|
+
/**
|
|
2510
|
+
* The file's tool wall time: the sum of the turns' `toolMs` (parallel tools counted once
|
|
2511
|
+
* within a turn). Summed per turn rather than unioned across the file, so the global figure
|
|
2512
|
+
* stays the sum of the per-turn figures, exactly as `elapsedMs` is. May overlap `apiMs` —
|
|
2513
|
+
* see `TraceTaskStats.toolMs`.
|
|
2514
|
+
*/
|
|
2515
|
+
toolMs: number;
|
|
2516
|
+
/**
|
|
2517
|
+
* The file's cost in USD: the sum of the turns' `cost` (compaction turns included, the
|
|
2518
|
+
* scope every total here shares). Absent exactly when the turns carry no `cost`.
|
|
2519
|
+
*/
|
|
2520
|
+
cost?: number;
|
|
2378
2521
|
requests: RequestSpan[];
|
|
2379
2522
|
/** Token / duration aggregated per Task (used directly by the Trace page's context ring and per-turn TPS). */
|
|
2380
2523
|
tasks: TraceTaskStats[];
|
|
@@ -2577,16 +2720,8 @@ interface UsageErrorItem {
|
|
|
2577
2720
|
* items.
|
|
2578
2721
|
*/
|
|
2579
2722
|
interface UsageErrors {
|
|
2723
|
+
/** Filtered row count — also what a clear of the same filter takes (see {@link UsageErrorsClearResponse}). */
|
|
2580
2724
|
total: number;
|
|
2581
|
-
/**
|
|
2582
|
-
* How many of {@link total} a clear would actually take (see {@link UsageErrorsClearResponse}).
|
|
2583
|
-
*
|
|
2584
|
-
* The same as `total` for an ordinary member, and smaller for an admin, whose reads include
|
|
2585
|
-
* unattributed rows that no Project-scoped clear removes. The confirmation is the only place
|
|
2586
|
-
* this matters, and it is the place it matters most: an irreversible delete has to name the
|
|
2587
|
-
* number that will really go, not the number on screen.
|
|
2588
|
-
*/
|
|
2589
|
-
clearable: number;
|
|
2590
2725
|
/** Count of unexpected ones (500 / runtime exceptions) among them — the part the frontend highlights. */
|
|
2591
2726
|
unexpected: number;
|
|
2592
2727
|
/** The most frequent source · code (null when there are no errors). */
|
|
@@ -2598,8 +2733,9 @@ interface UsageErrors {
|
|
|
2598
2733
|
* GET /api/projects/:projectId/usage/errors — one page of the error detail table, newest
|
|
2599
2734
|
* first. The dashboard response above already carries the first page; this exists so
|
|
2600
2735
|
* "show me earlier ones" does not have to refetch the whole aggregate. It takes the same
|
|
2601
|
-
* date/agent filter as the dashboard
|
|
2602
|
-
*
|
|
2736
|
+
* date/agent filter as the dashboard (`fromTs`/`toTs` narrow it to a trailing window, both
|
|
2737
|
+
* or neither), so a page never widens what the summary counted, plus an optional `kind`
|
|
2738
|
+
* ({@link UsageErrorKind}) narrowing to one of the two categories — which
|
|
2603
2739
|
* is how the cost-center badge asks "are there unexpected errors, and how new is the newest"
|
|
2604
2740
|
* with `limit=1` instead of pulling the whole dashboard aggregate.
|
|
2605
2741
|
*/
|
|
@@ -2610,11 +2746,15 @@ interface UsageErrorsPage {
|
|
|
2610
2746
|
}
|
|
2611
2747
|
/**
|
|
2612
2748
|
* DELETE /api/projects/:projectId/usage/errors — empties the error table for the filter the
|
|
2613
|
-
* panel is showing (its date range and Agent), Project
|
|
2749
|
+
* panel is showing (its date range, the trailing window when one is on, and Agent), Project
|
|
2750
|
+
* owner only.
|
|
2614
2751
|
*
|
|
2615
2752
|
* Scoped to the filter rather than the Project's whole history, so a clear takes exactly the
|
|
2616
|
-
* rows on screen
|
|
2617
|
-
*
|
|
2753
|
+
* rows on screen — for an admin, the unattributed rows an admin's panel shows included; a
|
|
2754
|
+
* member's panel never shows them and a member's clear never takes them.
|
|
2755
|
+
*
|
|
2756
|
+
* `from` and `to` are both required (400 otherwise), where the reads treat them as optional:
|
|
2757
|
+
* an absent bound is unbounded on that side, which is the whole history rather than a filter.
|
|
2618
2758
|
*/
|
|
2619
2759
|
interface UsageErrorsClearResponse {
|
|
2620
2760
|
/** How many rows were deleted, so the caller can say what went instead of guessing. */
|
|
@@ -2795,31 +2935,99 @@ interface SkillMetadataItem {
|
|
|
2795
2935
|
/** Short description for frontend display (frontmatter short_description, optional; falls back to description if missing). */
|
|
2796
2936
|
shortDescription?: string;
|
|
2797
2937
|
shortDescriptionZh?: string;
|
|
2798
|
-
/**
|
|
2938
|
+
/**
|
|
2939
|
+
* Raw icon.svg text from the installed skill directory: the plugin's icon for a library
|
|
2940
|
+
* install (written beside SKILL.md at install time), a custom one for a user-authored skill.
|
|
2941
|
+
* Only installed lists carry it — the library listing's skills share their plugin's icon,
|
|
2942
|
+
* which the plugin item carries once. Absent, the frontend draws the book glyph.
|
|
2943
|
+
*/
|
|
2799
2944
|
icon?: string;
|
|
2800
|
-
/** Version
|
|
2801
|
-
version:
|
|
2802
|
-
/** Update timestamp (frontmatter updated, ISO 8601 UTC by convention; defaults to an empty string). */
|
|
2803
|
-
updated: string;
|
|
2945
|
+
/** Version (`YYYY.MM.DD.N`, frontmatter version; a copy installed before that spelling still carries `YYYY-MM-DD.N`); an empty string when the frontmatter carries none or a malformed one. */
|
|
2946
|
+
version: string;
|
|
2804
2947
|
}
|
|
2805
|
-
|
|
2948
|
+
/** One installed hook package (`agent_state/hooks/<name>/`): its manifest, without the scripts. */
|
|
2949
|
+
interface HookItem {
|
|
2950
|
+
/** Hook package name — the plugin that shipped it (the identity uninstall addresses it by). */
|
|
2951
|
+
name: string;
|
|
2952
|
+
description: string;
|
|
2953
|
+
descriptionZh?: string;
|
|
2954
|
+
/** Version (`YYYY.MM.DD.N`; a copy installed before that spelling still carries `YYYY-MM-DD.N`); an empty string when the manifest carries none. */
|
|
2955
|
+
version: string;
|
|
2956
|
+
/** The hook points the package answers at, e.g. `["stop"]`. */
|
|
2957
|
+
events: string[];
|
|
2958
|
+
/** The plugin's raw icon.svg, written beside the manifest at install time; absent when the plugin ships none (the frontend draws the hook glyph). */
|
|
2959
|
+
icon?: string;
|
|
2960
|
+
}
|
|
2961
|
+
/** One library plugin as the listing describes it: the manifest fields plus what it ships (skill bodies and scripts are never sent). */
|
|
2962
|
+
interface PluginItem {
|
|
2963
|
+
name: string;
|
|
2964
|
+
description: string;
|
|
2965
|
+
descriptionZh?: string;
|
|
2966
|
+
shortDescription?: string;
|
|
2967
|
+
shortDescriptionZh?: string;
|
|
2968
|
+
/** `YYYY.MM.DD.N`. */
|
|
2969
|
+
version: string;
|
|
2970
|
+
/** The plugin's skills (metadata only). */
|
|
2971
|
+
skills: SkillMetadataItem[];
|
|
2972
|
+
/** The hook points the plugin's hook package answers at (`[]` without one). */
|
|
2973
|
+
hooks: string[];
|
|
2974
|
+
/** The plugin's raw icon.svg (beside plugin.json — every built-in plugin ships one), the icon of everything it ships; the frontend draws the puzzle-piece plugin glyph without it. */
|
|
2975
|
+
icon?: string;
|
|
2976
|
+
}
|
|
2977
|
+
interface PluginGroupItem {
|
|
2806
2978
|
id: string;
|
|
2807
2979
|
title: string;
|
|
2808
|
-
/** Chinese
|
|
2980
|
+
/** Chinese category title (optional; the UI displays it per language). */
|
|
2809
2981
|
titleZh?: string;
|
|
2810
|
-
|
|
2982
|
+
plugins: PluginItem[];
|
|
2983
|
+
}
|
|
2984
|
+
/** GET /api/plugins: the library by category (any logged-in user). */
|
|
2985
|
+
interface PluginLibraryResponse {
|
|
2986
|
+
groups: PluginGroupItem[];
|
|
2811
2987
|
}
|
|
2812
|
-
/**
|
|
2813
|
-
|
|
2814
|
-
|
|
2988
|
+
/**
|
|
2989
|
+
* GET /api/plugins/:plugin/files: everything a library plugin ships, for the detail view's file
|
|
2990
|
+
* browser — each skill's installable SKILL.md and auxiliary files under `skills/<name>/`, the
|
|
2991
|
+
* hook package's scripts under `hooks/` — keyed by path relative to the plugin directory. The
|
|
2992
|
+
* manifest and the icon are not among them: the listing already carries both.
|
|
2993
|
+
*/
|
|
2994
|
+
interface PluginFilesResponse {
|
|
2995
|
+
files: Record<string, string>;
|
|
2815
2996
|
}
|
|
2816
|
-
/**
|
|
2997
|
+
/**
|
|
2998
|
+
* POST /api/projects/:p/agents/:a/plugins: install library plugins by name — each one's skills
|
|
2999
|
+
* and hook package; already-installed ones are overwritten with library content (i.e. updated).
|
|
3000
|
+
* Every name must be in the library (404 `unknown_plugin`, nothing written). 201 returns the
|
|
3001
|
+
* refreshed installed lists.
|
|
3002
|
+
*/
|
|
3003
|
+
interface PluginInstallRequest {
|
|
3004
|
+
names: string[];
|
|
3005
|
+
}
|
|
3006
|
+
interface AgentPluginsInstallResponse {
|
|
3007
|
+
skills: SkillMetadataItem[];
|
|
3008
|
+
hooks: HookItem[];
|
|
3009
|
+
}
|
|
3010
|
+
/** GET /api/projects/:p/agents/:a/skills: Skills installed on this Agent. */
|
|
2817
3011
|
interface AgentSkillsResponse {
|
|
2818
3012
|
skills: SkillMetadataItem[];
|
|
2819
3013
|
}
|
|
2820
|
-
/**
|
|
2821
|
-
interface
|
|
2822
|
-
|
|
3014
|
+
/** GET /api/projects/:p/agents/:a/hooks: hook packages installed on this Agent; DELETE …/hooks/:name uninstalls one (204). */
|
|
3015
|
+
interface AgentHooksResponse {
|
|
3016
|
+
hooks: HookItem[];
|
|
3017
|
+
}
|
|
3018
|
+
/**
|
|
3019
|
+
* POST /api/projects/:p/agents/:a/hooks/archive: install one hook package from an uploaded zip.
|
|
3020
|
+
* Layout: hooks.json and its scripts at the zip root, or exactly one top-level directory
|
|
3021
|
+
* containing them (the directory name is then the package name). 201 returns the refreshed
|
|
3022
|
+
* installed list (AgentHooksResponse); an already-installed name without `overwrite` is 409
|
|
3023
|
+
* `hook_exists`. GET …/hooks/:name/archive is the matching export: the installed directory as
|
|
3024
|
+
* a zip attachment, which round-trips through this POST.
|
|
3025
|
+
*/
|
|
3026
|
+
interface HookArchiveInstallRequest {
|
|
3027
|
+
/** Base64-encoded zip archive (decoded size capped at 14MB, like the skill archive). */
|
|
3028
|
+
dataBase64: string;
|
|
3029
|
+
/** Replace an installed package of the same name instead of answering 409. */
|
|
3030
|
+
overwrite?: boolean;
|
|
2823
3031
|
}
|
|
2824
3032
|
/**
|
|
2825
3033
|
* POST /api/projects/:p/agents/:a/skills/archive: install one Skill from an uploaded zip.
|
|
@@ -2870,7 +3078,9 @@ interface UpdateCheckResponse {
|
|
|
2870
3078
|
* utilityProcess message channel and served at GET /api/desktop/update. `state` is the
|
|
2871
3079
|
* discriminator; the optional fields belong to the states named on them.
|
|
2872
3080
|
*
|
|
2873
|
-
*
|
|
3081
|
+
* The shell never downloads on its own: a check ends in `available`, and the download
|
|
3082
|
+
* starts only on the page's (or the native dialog's) say-so — the `download` command. A
|
|
3083
|
+
* `downloaded` build stays the reported state until it is installed: a later periodic
|
|
2874
3084
|
* check (or its failure) must not hide the actionable "restart to install" step.
|
|
2875
3085
|
*/
|
|
2876
3086
|
interface DesktopUpdateStatus {
|
|
@@ -2883,8 +3093,8 @@ interface DesktopUpdateStatus {
|
|
|
2883
3093
|
* carry that signal (a check that ends where it started is byte-identical).
|
|
2884
3094
|
*/
|
|
2885
3095
|
seq?: number;
|
|
2886
|
-
state: "idle" | "checking" | "up-to-date" | "downloading" | "downloaded" | "error" | "unsupported";
|
|
2887
|
-
/**
|
|
3096
|
+
state: "idle" | "checking" | "up-to-date" | "available" | "downloading" | "downloaded" | "error" | "unsupported";
|
|
3097
|
+
/** The newer release: offered (`available`), being fetched (`downloading`) or ready to install (`downloaded`). */
|
|
2888
3098
|
version?: string;
|
|
2889
3099
|
/** Download progress 0–100 (`downloading`). */
|
|
2890
3100
|
percent?: number;
|
|
@@ -2905,15 +3115,19 @@ interface DesktopUpdaterStatusMessage {
|
|
|
2905
3115
|
type: "desktop-updater-status";
|
|
2906
3116
|
status: DesktopUpdateStatus;
|
|
2907
3117
|
}
|
|
2908
|
-
/**
|
|
3118
|
+
/**
|
|
3119
|
+
* Server → shell command over the utilityProcess message channel (relayed from
|
|
3120
|
+
* POST /api/desktop/update/check|download|install): look for a release, fetch the one
|
|
3121
|
+
* offered, or restart into the one downloaded.
|
|
3122
|
+
*/
|
|
2909
3123
|
interface DesktopUpdaterCommandMessage {
|
|
2910
3124
|
type: "desktop-updater-command";
|
|
2911
|
-
action: "check" | "install";
|
|
3125
|
+
action: "check" | "download" | "install";
|
|
2912
3126
|
}
|
|
2913
3127
|
/**
|
|
2914
|
-
*
|
|
2915
|
-
*
|
|
2916
|
-
* CLI's own refusals (source checkout, unrecognized install layout, Windows).
|
|
3128
|
+
* The outcome of one self-update run (`penguin update --yes` on the server host), carried
|
|
3129
|
+
* by {@link UpdateJobStatus.result}. `unsupported` covers both a server not launched via
|
|
3130
|
+
* the CLI and the CLI's own refusals (source checkout, unrecognized install layout, Windows).
|
|
2917
3131
|
*/
|
|
2918
3132
|
interface UpdateRunResponse {
|
|
2919
3133
|
status: "updated" | "failed" | "unsupported";
|
|
@@ -2924,6 +3138,44 @@ interface UpdateRunResponse {
|
|
|
2924
3138
|
/** True when the install changed (or was already current): restart the service to run the new version. */
|
|
2925
3139
|
needsRestart: boolean;
|
|
2926
3140
|
}
|
|
3141
|
+
/**
|
|
3142
|
+
* Where a running self-update is: resolving the release and fetching the installer,
|
|
3143
|
+
* downloading the bundle (the one phase with a percentage), or verifying and installing it.
|
|
3144
|
+
*/
|
|
3145
|
+
type UpdateJobPhase = "resolving" | "downloading" | "installing";
|
|
3146
|
+
/**
|
|
3147
|
+
* GET / POST /api/version/update (admin only): the self-update job. POST starts a run when
|
|
3148
|
+
* none is in flight — a finished run may be started again, which is how a failed one is
|
|
3149
|
+
* retried — and answers with the status exactly as GET does; the page polls GET while
|
|
3150
|
+
* `state` is `running`. One job per process: two admins clicking at once share the one run,
|
|
3151
|
+
* and the finished status stays readable until the next start.
|
|
3152
|
+
*/
|
|
3153
|
+
interface UpdateJobStatus {
|
|
3154
|
+
state: "idle" | "running" | "done";
|
|
3155
|
+
/** The release the run targets — the update check's newest version when the run started; null when none was known. */
|
|
3156
|
+
targetVersion: string | null;
|
|
3157
|
+
/** Running only. */
|
|
3158
|
+
phase?: UpdateJobPhase;
|
|
3159
|
+
/** Running, `downloading` only: 0–100 read off the installer's progress bar; null until its first tick. */
|
|
3160
|
+
percent?: number | null;
|
|
3161
|
+
/** Tail of the update command's combined stdout+stderr so far (capped; empty when nothing ran). */
|
|
3162
|
+
output: string;
|
|
3163
|
+
/** Done only. */
|
|
3164
|
+
result?: UpdateRunResponse;
|
|
3165
|
+
startedAt?: string;
|
|
3166
|
+
finishedAt?: string;
|
|
3167
|
+
}
|
|
3168
|
+
/**
|
|
3169
|
+
* POST /api/version/restart (admin only): asks the process to exit with the supervisor's
|
|
3170
|
+
* restart code after a graceful shutdown, so `penguin server|web` relaunches it on the
|
|
3171
|
+
* installed release. `restarting: false` when nothing supervises this process — it was
|
|
3172
|
+
* started some other way than through the CLI, or it is a dev run — and the page shows the
|
|
3173
|
+
* manual restart hint instead.
|
|
3174
|
+
*/
|
|
3175
|
+
interface RestartResponse {
|
|
3176
|
+
restarting: boolean;
|
|
3177
|
+
reason?: "no_supervisor";
|
|
3178
|
+
}
|
|
2927
3179
|
/** One `Host` entry of the server's `~/.ssh/config`, as the Machines page lists it. */
|
|
2928
3180
|
interface MachineInfo {
|
|
2929
3181
|
/** `ssh:<alias>` — the id the install route is asked for. */
|
|
@@ -2935,9 +3187,9 @@ interface MachineInfo {
|
|
|
2935
3187
|
*/
|
|
2936
3188
|
alias: string;
|
|
2937
3189
|
/**
|
|
2938
|
-
* The last install THIS server carried out there, remembered
|
|
2939
|
-
* restart, a hot push, and installing on some other machine. Null when this
|
|
2940
|
-
* never installed there.
|
|
3190
|
+
* The last install THIS server carried out there FOR THIS PROJECT, remembered in web.db so
|
|
3191
|
+
* it survives a restart, a hot push, and installing on some other machine. Null when this
|
|
3192
|
+
* Project has never installed there — a host another Project did is `elsewhere` below.
|
|
2941
3193
|
*
|
|
2942
3194
|
* A record of what was done, not a survey of the far side: a machine wiped by hand still
|
|
2943
3195
|
* reads as installed until the next install probes it and corrects the record. Asking the
|
|
@@ -2948,25 +3200,112 @@ interface MachineInfo {
|
|
|
2948
3200
|
version: string;
|
|
2949
3201
|
at: string;
|
|
2950
3202
|
} | null;
|
|
3203
|
+
/**
|
|
3204
|
+
* Installed by this server, but not this Project's machine — another Project's, or nobody's
|
|
3205
|
+
* since it was released — and so not a host nobody has touched either. Absent in every
|
|
3206
|
+
* other case, including when it IS this Project's (where `installed` carries the same record).
|
|
3207
|
+
*
|
|
3208
|
+
* Reported rather than folded into `installed` because the two lead to different actions:
|
|
3209
|
+
* one is a machine to use, the other is a machine to adopt, which costs a row and no ssh.
|
|
3210
|
+
* Reported rather than hidden because a row that silently looked uninstalled would send
|
|
3211
|
+
* someone to spend a 30 MB transfer re-doing what is already done.
|
|
3212
|
+
*/
|
|
3213
|
+
elsewhere?: {
|
|
3214
|
+
version: string;
|
|
3215
|
+
at: string;
|
|
3216
|
+
};
|
|
3217
|
+
/**
|
|
3218
|
+
* The machine's OWN id — 16 base64url characters minted by the server that runs there,
|
|
3219
|
+
* stable across renames, re-aliasing and reinstalls. Null until a server has started on
|
|
3220
|
+
* that machine, since nothing has minted one yet.
|
|
3221
|
+
*
|
|
3222
|
+
* This is what anything stored should point at; `id` above is an ADDRESS (`ssh:<alias>`),
|
|
3223
|
+
* and `alias` is what people read. Two aliases for one host share a `machineId`, and an
|
|
3224
|
+
* alias repointed at a different host answers a different one — an id never changes for a
|
|
3225
|
+
* machine, so a change of id is a change of machine.
|
|
3226
|
+
*/
|
|
3227
|
+
machineId: string | null;
|
|
3228
|
+
/** The host this server itself runs on. Always present, always installed, never a target. */
|
|
3229
|
+
local: boolean;
|
|
3230
|
+
/**
|
|
3231
|
+
* The connection this server holds to it — the one ssh session everything to the machine
|
|
3232
|
+
* rides (machines/transport/ssh-session.ts): a fact about a process on THIS side, which
|
|
3233
|
+
* outlives the far server. Present means `/server/<id>/api/…` has somewhere to go; whether
|
|
3234
|
+
* a server ANSWERS over there is `status`'s word, from the last probe — and the two must not
|
|
3235
|
+
* be read for each other: taking the connection for the machine's liveness is the mistake
|
|
3236
|
+
* behind the connect loop (#561). Always null for `local`, which needs no connection.
|
|
3237
|
+
*/
|
|
3238
|
+
connection: {
|
|
3239
|
+
pid: number;
|
|
3240
|
+
} | null;
|
|
3241
|
+
/**
|
|
3242
|
+
* The machine's API as last seen by this server's proxy — stamped by traffic passing
|
|
3243
|
+
* through, never by a probe of its own. `answeredAt` when the last forwarded request got
|
|
3244
|
+
* an HTTP answer (any status: a server that refuses is still answering); `failedAt` and
|
|
3245
|
+
* the transport's own words when the connection had nowhere to deliver. Null until a first
|
|
3246
|
+
* request flows, and only as fresh as the last one — no traffic, no measurement, which is
|
|
3247
|
+
* honest: nothing burns ssh for a page nobody is looking at. Always null for `local`;
|
|
3248
|
+
* this server answering the request that fetched this list is that measurement.
|
|
3249
|
+
*/
|
|
3250
|
+
api: {
|
|
3251
|
+
answeredAt: string;
|
|
3252
|
+
} | {
|
|
3253
|
+
failedAt: string;
|
|
3254
|
+
detail: string;
|
|
3255
|
+
} | null;
|
|
3256
|
+
/**
|
|
3257
|
+
* What the last probe found over there, or null when none has been taken. Never filled in
|
|
3258
|
+
* at list time: a probe costs an ssh round trip per machine, so the list reports the last
|
|
3259
|
+
* answer and the page asks for a fresh one when it wants one — on a widening schedule,
|
|
3260
|
+
* since each probe is an ssh round trip while the list is only the config's text.
|
|
3261
|
+
*/
|
|
3262
|
+
status: MachineServerStatus | null;
|
|
2951
3263
|
}
|
|
2952
3264
|
/**
|
|
2953
|
-
*
|
|
2954
|
-
*
|
|
2955
|
-
*
|
|
3265
|
+
* One machine's server state. There is deliberately no separate "ssh" status: ssh is the
|
|
3266
|
+
* transport, so a machine it cannot reach reads as `unreachable` with OpenSSH's own
|
|
3267
|
+
* diagnostic in `detail` rather than as two statuses a reader has to combine.
|
|
2956
3268
|
*/
|
|
2957
|
-
interface
|
|
3269
|
+
interface MachineServerStatus {
|
|
3270
|
+
state: "running" | "stopped" | "unreachable";
|
|
3271
|
+
/** ISO timestamp of the probe this answer came from. */
|
|
3272
|
+
checkedAt: string;
|
|
3273
|
+
/** The port it is serving on (`running`). */
|
|
3274
|
+
port?: number;
|
|
3275
|
+
/** Why the machine could not be reached (`unreachable`) — ssh's own words. */
|
|
3276
|
+
detail?: string;
|
|
3277
|
+
}
|
|
3278
|
+
/**
|
|
3279
|
+
* The running or last job on a machine — an install, or a connect — polled by GET
|
|
3280
|
+
* /api/machines while one runs. One at a time. `log` carries the far side's own words where
|
|
3281
|
+
* there are any: ssh's diagnostics and the remote installer's output say more about a
|
|
3282
|
+
* refused key or an unusable Node than a paraphrase would.
|
|
3283
|
+
*/
|
|
3284
|
+
interface MachineJob {
|
|
3285
|
+
kind: "install" | "connect" | "restart";
|
|
2958
3286
|
machineId: string;
|
|
2959
3287
|
alias: string;
|
|
2960
3288
|
running: boolean;
|
|
2961
3289
|
log: string[];
|
|
2962
3290
|
result: null | {
|
|
2963
3291
|
ok: true;
|
|
2964
|
-
|
|
3292
|
+
installed: "installed" | "already-installed";
|
|
2965
3293
|
version: string | null;
|
|
3294
|
+
} | {
|
|
3295
|
+
ok: true;
|
|
3296
|
+
connected: true;
|
|
2966
3297
|
} | {
|
|
2967
3298
|
ok: false;
|
|
2968
3299
|
step: string;
|
|
2969
3300
|
message: string;
|
|
3301
|
+
/**
|
|
3302
|
+
* The failure has a next step this side can take, and it needs saying yes to:
|
|
3303
|
+
* installing the PROGRAM over there and restarting it. Set when a hot update could
|
|
3304
|
+
* not be handed over — the machine's store holds no CLI this server can talk to, and
|
|
3305
|
+
* installing is what replicates one. Offered rather than done, because it restarts a
|
|
3306
|
+
* server this Project does not own alone.
|
|
3307
|
+
*/
|
|
3308
|
+
canReplaceProgram?: true;
|
|
2970
3309
|
};
|
|
2971
3310
|
}
|
|
2972
3311
|
/** GET /api/machines, and the 202 body of POST /api/machines/:machineId/install. */
|
|
@@ -2978,7 +3317,7 @@ interface MachinesResponse {
|
|
|
2978
3317
|
* checkout, which stands on no release the remote could download.
|
|
2979
3318
|
*/
|
|
2980
3319
|
imageVersion: string | null;
|
|
2981
|
-
job:
|
|
3320
|
+
job: MachineJob | null;
|
|
2982
3321
|
}
|
|
2983
3322
|
|
|
2984
|
-
export type { AdminPasswordResetRequest, AdminUserCreateRequest, AdminUserCreateResponse, AdminUsersResponse, AgentCompactionConfigDto, AgentConfigDto, AgentConfigResponse, AgentConfigUpdateRequest, AgentCreateRequest, AgentCreateResponse, AgentImportRequest, AgentImportResponse, AgentKernelUpdateResponse, AgentMemoryConfigDto, AgentModelConfigDto, AgentSchedulesConfigDto, AgentSkillsConfigDto, AgentSkillsResponse, AgentSummary, AgentTraceDateGroup, AgentTraceFileRef, AgentTraceSessionEntry, AgentTraceSessionFile, AgentTraceSessionGroup, AgentTracesResponse, AgentVaultConfigDto, AgentsResponse, ApprovalDecisionRequest, ApprovalMode, AuthLoginRequest, AuthResponse, BenchmarkCaseScore, BenchmarkCaseSummary, BenchmarkCasesResponse, BenchmarkEvaluation, BenchmarkRunScore, BenchmarkSummary, BenchmarksResponse, CaseMaterial, ChatDefaultsDto, CommandPolicyDto, CommandPolicyRuleDto, ContextToolShare, CredentialInfo, DefaultModelResponse, DefaultModelUpdateRequest, DesktopUpdateStatus, DesktopUpdateStatusResponse, DesktopUpdaterCommandMessage, DesktopUpdaterStatusMessage, DirEntryInfo, DirListResponse, DirectorySkillItem, DirectorySkillsResponse, DraftShortcut, EndpointModelListRequest, EndpointModelListResponse, ErrorBody, FeishuBindingInfo, FeishuBindingPutRequest, FeishuBindingResponse, FeishuTestRequest, FeishuTestResponse, FilesStatRequest, FilesStatResponse, GoalResponse, GoalServerEvent, GoalStateView, HistoryMessage, InstallResponse, MachineInfo,
|
|
3323
|
+
export type { AdminPasswordResetRequest, AdminUserCreateRequest, AdminUserCreateResponse, AdminUsersResponse, AgentCompactionConfigDto, AgentConfigDto, AgentConfigResponse, AgentConfigUpdateRequest, AgentCreateRequest, AgentCreateResponse, AgentHooksConfigDto, AgentHooksResponse, AgentImportRequest, AgentImportResponse, AgentKernelUpdateResponse, AgentMemoryConfigDto, AgentModelConfigDto, AgentPluginsInstallResponse, AgentSchedulesConfigDto, AgentSkillsConfigDto, AgentSkillsResponse, AgentSummary, AgentTraceDateGroup, AgentTraceFileRef, AgentTraceSessionEntry, AgentTraceSessionFile, AgentTraceSessionGroup, AgentTracesResponse, AgentVaultConfigDto, AgentsResponse, ApprovalDecisionRequest, ApprovalMode, AuthLoginRequest, AuthResponse, BenchmarkCaseScore, BenchmarkCaseSummary, BenchmarkCasesResponse, BenchmarkEvaluation, BenchmarkRunScore, BenchmarkSummary, BenchmarksResponse, CaseMaterial, ChatDefaultsDto, CommandPolicyDto, CommandPolicyRuleDto, ContextFileShare, ContextToolShare, CredentialInfo, DefaultModelResponse, DefaultModelUpdateRequest, DesktopUpdateStatus, DesktopUpdateStatusResponse, DesktopUpdaterCommandMessage, DesktopUpdaterStatusMessage, DirEntryInfo, DirListResponse, DirectorySkillItem, DirectorySkillsResponse, DraftShortcut, EndpointModelListRequest, EndpointModelListResponse, ErrorBody, FeishuBindingInfo, FeishuBindingPutRequest, FeishuBindingResponse, FeishuTestRequest, FeishuTestResponse, FilesStatRequest, FilesStatResponse, FilesWriteRequest, GoalResponse, GoalServerEvent, GoalStateView, HistoryMessage, HookArchiveInstallRequest, HookItem, InstallResponse, MachineInfo, MachineJob, MachineServerStatus, MachinesResponse, McpServerTestResponse, MeResponse, MemberAddRequest, MemberAddResponse, MemberInfo, MembersResponse, MemoryFileInfo, MemoryFileResponse, MemoryFilesResponse, MemoryImportMode, MemoryImportRequest, MemoryImportResponse, MemoryOverviewResponse, MemoryScopeExport, MemoryScopeInfo, MemoryTransferFile, MessagesLiveTail, MessagesPageInfo, MessagesResponse, MessagingBindingCommon, MessagingBindingInfo, MessagingBindingStateRequest, MessagingBindingsResponse, MessagingChannel, MessagingChannelState, MessagingDeliveryError, MessagingDeliveryPatch, MessagingRuntimeState, MessagingRuntimeStatus, MessagingTestMessageResponse, ModelInfo, ModelOAuthCodeRequest, ModelOAuthCodeResponse, ModelOAuthErrorCode, ModelOAuthMode, ModelOAuthStartRequest, ModelOAuthStartResponse, ModelOAuthStatusResponse, ModelPricingDto, ModelProtocolDetectRequest, ModelProtocolDetectResponse, ModelProtocolProbeDto, ModelRefDto, ModelTestRequest, ModelTestResponse, ModelUpdateEntry, ModelVisionDetectRequest, ModelVisionDetectResponse, ModelVisionOutcome, ModelsResponse, ModelsUpdateRequest, PasswordChangeRequest, PendingFollowUpInfo, PendingSteeringInfo, PluginFilesResponse, PluginGroupItem, PluginInstallRequest, PluginItem, PluginLibraryResponse, PluginUpdateRef, PrefsResponse, ProjectCreateRequest, ProjectCreateResponse, ProjectRole, ProjectSummary, ProjectUpdateRequest, ProjectUpdateResponse, ProjectsResponse, ProtocolProbeOutcome, QQBindingInfo, QQBindingPutRequest, QQBindingResponse, QQScanPollResponse, QQScanStartResponse, QQTestRequest, QQTestResponse, RecalledMessageResponse, RequestSpan, RestartResponse, RetryNowResponse, ScheduleItem, ScheduleServerEvent, ScheduleStatus, ScheduleUpsertRequest, SchedulesResponse, ServerEvent, ServerSettings, ServerSettingsResponse, ServerSettingsUpdateRequest, SessionBackgroundTasks, SessionCategory, SessionCategoryCounts, SessionContextParts, SessionContextResponse, SessionCreateRequest, SessionCreateResponse, SessionForkRequest, SessionForkResponse, SessionInfo, SessionPatchRequest, SessionProcessInfo, SessionProcessesResponse, SessionResponse, SessionSource, SessionStatus, SessionTracesResponse, SessionsResponse, SkillArchiveInstallRequest, SkillMetadataItem, SteerRequest, SubagentMessageResponse, SubagentRuntimeInfo, TaskCreateRequest, TaskCreateResponse, TaskInputPart, TelegramBindingInfo, TelegramBindingPutRequest, TelegramBindingResponse, TelegramTestRequest, TelegramTestResponse, ToolCallSpan, TraceAnalysisResponse, TraceEventsResponse, TraceFileInfo, TraceImportRequest, TraceImportResponse, TraceModelSegment, TraceOtherSpan, TracePosition, TraceTaskStats, TraceToolSpan, UiPrefs, UpdateCheckResponse, UpdateJobPhase, UpdateJobStatus, UpdateRunResponse, UploadLimits, UsageAgentSeries, UsageBucket, UsageEntitySeriesCounts, UsageErrorCount, UsageErrorItem, UsageErrorKind, UsageErrors, UsageErrorsClearResponse, UsageErrorsPage, UsageGranularity, UsageGroupBy, UsageGroupRow, UsageModelSeries, UsageModelTotal, UsageModelTotals, UsageResponse, UsageSeriesPoint, UsageTrendPointInTrace, UserInfo, VaultEntryInfo, VaultEntryUpdate, VaultResponse, VaultUpdateRequest, VersionResponse, WeChatBindingInfo, WeChatBindingPutRequest, WeChatBindingResponse, WeChatScanPollResponse, WeChatScanStartResponse, WeChatScanStatus, WeChatScanVerifyRequest, WeChatTestResponse, WorkspaceFileEntry, WorkspaceFilesResponse };
|