pi-harness-runtime 1.1.390 → 1.1.391
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/AGENTS.md +12 -6
- package/harness/startup-report.ts +36 -6
- package/index.ts +22 -2
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/agent-policy/package.json +1 -1
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard-plugin/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/codex-watcher/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/connection-runtime/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/contracts/dist/workspace-env-format.d.ts +56 -3
- package/packages/contracts/dist/workspace-env-format.js +119 -22
- package/packages/contracts/dist/workspace-env.d.ts +4 -4
- package/packages/contracts/dist/workspace-env.js +426 -23
- package/packages/contracts/package.json +1 -1
- package/packages/contracts/src/workspace-env-format.ts +147 -17
- package/packages/contracts/src/workspace-env.ts +443 -24
- package/packages/contracts/test/workspace-env.test.ts +95 -7
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/durable-review/package.json +1 -1
- package/packages/e2e-tester/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-sink/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/package.json +1 -1
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/milestone-manager/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/dist/adapters/line-adapter.d.ts +39 -0
- package/packages/notification/dist/adapters/line-adapter.d.ts.map +1 -1
- package/packages/notification/dist/adapters/line-adapter.js +119 -8
- package/packages/notification/dist/adapters/line-adapter.js.map +1 -1
- package/packages/notification/dist/base-adapter.d.ts +20 -0
- package/packages/notification/dist/base-adapter.d.ts.map +1 -1
- package/packages/notification/dist/base-adapter.js +17 -0
- package/packages/notification/dist/base-adapter.js.map +1 -1
- package/packages/notification/dist/notification-center.d.ts +8 -0
- package/packages/notification/dist/notification-center.d.ts.map +1 -1
- package/packages/notification/dist/notification-center.js +11 -0
- package/packages/notification/dist/notification-center.js.map +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/notification/src/adapters/line-adapter.ts +145 -13
- package/packages/notification/src/base-adapter.ts +28 -0
- package/packages/notification/src/notification-center.ts +12 -0
- package/packages/observability/package.json +1 -1
- package/packages/okf-indexer/package.json +1 -1
- package/packages/paperclip-integration/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/permission-mode/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/qdrant-skills/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/relay/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skills/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/telegram/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/dist/harness-footer.d.ts +23 -8
- package/packages/tui/dist/harness-footer.d.ts.map +1 -1
- package/packages/tui/dist/harness-footer.js +144 -2
- package/packages/tui/dist/harness-footer.js.map +1 -1
- package/packages/tui/dist/index.d.ts +1 -1
- package/packages/tui/dist/index.d.ts.map +1 -1
- package/packages/tui/dist/index.js +1 -1
- package/packages/tui/dist/index.js.map +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/tui/src/harness-footer.ts +149 -2
- package/packages/tui/src/index.ts +1 -0
- package/packages/tui/test/harness-footer.test.ts +134 -15
- package/packages/types/package.json +1 -1
- package/packages/voice-api/package.json +1 -1
- package/packages/webmcp-tester/package.json +1 -1
- package/packages/wiki/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -502,21 +502,27 @@ bun run build && bun run start # Server deployment
|
|
|
502
502
|
|
|
503
503
|
**This info is shown in UI and delivered to agent context:**
|
|
504
504
|
```
|
|
505
|
-
Workspace: DEVELOPMENT | dev server: running |
|
|
505
|
+
Workspace: ~/pi-harness-runtime | OS: Linux | mode: DEVELOPMENT | dev server: running | dev script: available | build script: available | RAM: 10/16
|
|
506
506
|
```
|
|
507
507
|
|
|
508
508
|
The mode words are exactly what the detector emits: `DEVELOPMENT`, `PRODUCTION`,
|
|
509
509
|
`TEST` or `UNKNOWN` (with its reason, e.g. `UNKNOWN (no explicit NODE_ENV)`).
|
|
510
|
-
A dev/build script is a CAPABILITY, not a state: `
|
|
511
|
-
|
|
510
|
+
A dev/build script is a CAPABILITY, not a state: `dev script: available` means
|
|
511
|
+
the script exists, not that a server runs. The server state is separate and
|
|
512
|
+
never claims more than it knows: `running`, `not detected` (a check ran and
|
|
513
|
+
found nothing) or `not checked` (no check was possible, e.g. no `pgrep`).
|
|
514
|
+
|
|
515
|
+
The OS is part of the line because it decides which command prints the
|
|
516
|
+
working directory: `pwd` on Linux/macOS, `cd` or `echo %cd%` on Windows.
|
|
517
|
+
The agent context names the command to use.
|
|
512
518
|
|
|
513
519
|
**IMPORTANT Rules:**
|
|
514
520
|
|
|
515
521
|
| State | Action |
|
|
516
522
|
|-------|--------|
|
|
517
|
-
| `
|
|
518
|
-
| `
|
|
519
|
-
| `
|
|
523
|
+
| `mode: UNKNOWN (…)` | Explicitly ask user before build |
|
|
524
|
+
| `mode: DEVELOPMENT` | Use `dev` mode, don't auto-build |
|
|
525
|
+
| `mode: PRODUCTION` | Build allowed, but confirm with user |
|
|
520
526
|
| `Low RAM` | Never run parallel build + dev |
|
|
521
527
|
| `Dev server running` | Reuse it, don't restart |
|
|
522
528
|
|
|
@@ -59,7 +59,10 @@ export function oneLineError(error: unknown, maxLength = 160): string {
|
|
|
59
59
|
"$1<redacted>",
|
|
60
60
|
)
|
|
61
61
|
// A url path: "/bot123456:ABC-DEF/", "/token/abc12345".
|
|
62
|
-
|
|
62
|
+
// The boundary is "not a digit" and not a word boundary, so a
|
|
63
|
+
// token that is glued to a word ("xbot123:ABC-DEF") is redacted
|
|
64
|
+
// as well.
|
|
65
|
+
.replace(/(^|[^0-9])\d{6,}:[A-Za-z0-9_\-]{4,}/g, "$1<redacted>")
|
|
63
66
|
.replace(
|
|
64
67
|
/(\/((?:access_token|api[-_]?key|token|secret)[=/]))[A-Za-z0-9_\-:]{4,}/gi,
|
|
65
68
|
"$1<redacted>",
|
|
@@ -177,6 +180,21 @@ export function lineConfigurationReport(options: {
|
|
|
177
180
|
telegramConfigured?: boolean;
|
|
178
181
|
/** The fix commands for the missing LINE credentials. */
|
|
179
182
|
fixes: string[];
|
|
183
|
+
/**
|
|
184
|
+
* The fix commands for the channel access token only.
|
|
185
|
+
*
|
|
186
|
+
* The startup check validates the ACCESS TOKEN. The user id is only the
|
|
187
|
+
* recipient of the messages, so a failed check must not point at
|
|
188
|
+
* line-user-id.txt.
|
|
189
|
+
*/
|
|
190
|
+
accessTokenFixes?: string[];
|
|
191
|
+
/**
|
|
192
|
+
* Why the channel did not start (from the adapter).
|
|
193
|
+
*
|
|
194
|
+
* It says WHICH problem it is - an invalid or revoked token, a LINE API
|
|
195
|
+
* failure or a network failure - and it never contains a credential.
|
|
196
|
+
*/
|
|
197
|
+
channelDiagnostic?: string | null;
|
|
180
198
|
}): StartupReport | null {
|
|
181
199
|
if (!options.clientKeyFilePresent) return null;
|
|
182
200
|
const channelState = options.channelState ?? "not-started";
|
|
@@ -204,15 +222,27 @@ export function lineConfigurationReport(options: {
|
|
|
204
222
|
}
|
|
205
223
|
if (channelState === "failed") {
|
|
206
224
|
// The credentials are there but the channel did not start - the
|
|
207
|
-
//
|
|
225
|
+
// channel access token is what the startup check validates, so
|
|
226
|
+
// the user id must not be named as the cause.
|
|
227
|
+
const details = [
|
|
228
|
+
...(options.accessTokenFixes && options.accessTokenFixes.length > 0
|
|
229
|
+
? options.accessTokenFixes
|
|
230
|
+
: options.fixes),
|
|
231
|
+
];
|
|
232
|
+
if (options.channelDiagnostic) {
|
|
233
|
+
details.push(options.channelDiagnostic);
|
|
234
|
+
}
|
|
235
|
+
details.push(
|
|
236
|
+
"The startup check validates the channel access token - the user id is only the recipient of the messages.",
|
|
237
|
+
);
|
|
238
|
+
details.push(
|
|
239
|
+
"Fix the file, then reload Pi so the channel is checked again.",
|
|
240
|
+
);
|
|
208
241
|
return {
|
|
209
242
|
label: "LINE",
|
|
210
243
|
text: "configured but the LINE channel did not start",
|
|
211
244
|
status: "warn",
|
|
212
|
-
details
|
|
213
|
-
...options.fixes,
|
|
214
|
-
"Check the LINE credentials in ~/.pi-harness-runtime/keys/, then reload Pi.",
|
|
215
|
-
],
|
|
245
|
+
details,
|
|
216
246
|
};
|
|
217
247
|
}
|
|
218
248
|
// The credentials are there but the channel was never started in this
|
package/index.ts
CHANGED
|
@@ -163,6 +163,15 @@ let keyFileAuditDone = false;
|
|
|
163
163
|
* startup line must not claim a green "configured".
|
|
164
164
|
*/
|
|
165
165
|
let lineChannelState: "started" | "failed" | "not-started" = "not-started";
|
|
166
|
+
/**
|
|
167
|
+
* Why the LINE channel did not start (from the adapter).
|
|
168
|
+
*
|
|
169
|
+
* The adapter knows the difference between an invalid or revoked token
|
|
170
|
+
* (401/403), a LINE API failure and a network failure - the startup
|
|
171
|
+
* summary shows it so the user knows what to fix. It never contains a
|
|
172
|
+
* credential.
|
|
173
|
+
*/
|
|
174
|
+
let lineChannelDiagnostic: string | null = null;
|
|
166
175
|
let telegramChannelState: "started" | "failed" | "not-started" = "not-started";
|
|
167
176
|
/** Did the relay client connect at least once in this extension load? */
|
|
168
177
|
let relayStreamConnected = false;
|
|
@@ -1398,9 +1407,13 @@ async function initTelegram(pi: ExtensionAPI): Promise<void> {
|
|
|
1398
1407
|
if (lineChannelConfigured) {
|
|
1399
1408
|
if (center.isChannelHealthy("line")) {
|
|
1400
1409
|
lineChannelState = "started";
|
|
1410
|
+
lineChannelDiagnostic = null;
|
|
1401
1411
|
addHarnessMessage("LINE", "configured and enabled (tap Toggle LINE to disable)", "ok");
|
|
1402
1412
|
} else {
|
|
1403
1413
|
lineChannelState = "failed";
|
|
1414
|
+
// Keep the reason: "the token is wrong" and "LINE is down"
|
|
1415
|
+
// need different actions.
|
|
1416
|
+
lineChannelDiagnostic = center.getChannelDiagnostic("line");
|
|
1404
1417
|
}
|
|
1405
1418
|
}
|
|
1406
1419
|
if (telegramChannelState !== "started") {
|
|
@@ -1795,8 +1808,15 @@ function reportLineConfiguration(): void {
|
|
|
1795
1808
|
channelState: lineChannelState,
|
|
1796
1809
|
telegramConfigured: telegramIsConfigured(),
|
|
1797
1810
|
// The fallback makes sure that a warning always carries a command,
|
|
1798
|
-
// even when the audit could not answer.
|
|
1799
|
-
|
|
1811
|
+
// even when the audit could not answer. It names the ACCESS TOKEN
|
|
1812
|
+
// only - the user id is the recipient of the messages, not the cause
|
|
1813
|
+
// of a failed startup check.
|
|
1814
|
+
fixes: keyFileFixesOrFallback("LINE", ["channel access token"]),
|
|
1815
|
+
// The startup check validates the access token - the user id is only
|
|
1816
|
+
// the recipient, so it must not be named as the cause.
|
|
1817
|
+
accessTokenFixes: keyFileFixesOrFallback("LINE", ["channel access token"]),
|
|
1818
|
+
// The reason the channel did not start (invalid token, LINE down, ...).
|
|
1819
|
+
channelDiagnostic: lineChannelDiagnostic,
|
|
1800
1820
|
// Without Telegram the LINE channel cannot start - the user needs
|
|
1801
1821
|
// the Telegram commands, not only an explanation.
|
|
1802
1822
|
telegramFixes: keyFileFixesOrFallback("Telegram", ["bot token", "chat id"]),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-harness/capability-registry",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.391",
|
|
4
4
|
"description": "Capability Registry for pi-harness-runtime — tracks model capabilities and enables capability-based routing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -37,6 +37,16 @@ export interface WorkspaceEnvResult {
|
|
|
37
37
|
packageManager: string | null;
|
|
38
38
|
devServerRunning: boolean;
|
|
39
39
|
buildServerRunning: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* The tri-state state of the dev server.
|
|
42
|
+
*
|
|
43
|
+
* "not detected" means a check ran and found nothing; "not checked"
|
|
44
|
+
* means no check was possible (an unsupported platform or a failed
|
|
45
|
+
* check). Neither of them is evidence that a server is not running.
|
|
46
|
+
*/
|
|
47
|
+
devServerState?: ServerState;
|
|
48
|
+
/** The tri-state state of the build server. */
|
|
49
|
+
buildServerState?: ServerState;
|
|
40
50
|
ramTotalGb: number | null;
|
|
41
51
|
ramAvailableGb: number | null;
|
|
42
52
|
ramEffectiveLimitGb: number | null;
|
|
@@ -44,6 +54,47 @@ export interface WorkspaceEnvResult {
|
|
|
44
54
|
buildAllowed: boolean;
|
|
45
55
|
detectedAt: number;
|
|
46
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* The state of a dev/build server.
|
|
59
|
+
*/
|
|
60
|
+
/**
|
|
61
|
+
* Is this command line a package-manager launcher?
|
|
62
|
+
*
|
|
63
|
+
* A launcher ("npm run dev", "bun run start") only STARTS a server - the
|
|
64
|
+
* server is its child. Counting the launcher would report a running
|
|
65
|
+
* server for a script that does not start one at all ("sleep 300").
|
|
66
|
+
*
|
|
67
|
+
* The rule is pure, so it lives in the pure module and can be tested
|
|
68
|
+
* without the SQLite cache.
|
|
69
|
+
*/
|
|
70
|
+
export declare function isLauncherCommand(cmdline: string): boolean;
|
|
71
|
+
export type ServerState = "running" | "not-detected" | "not-checked";
|
|
72
|
+
/**
|
|
73
|
+
* The name of the operating system the harness runs on.
|
|
74
|
+
*
|
|
75
|
+
* The OS decides which command shows the working directory (pwd on
|
|
76
|
+
* POSIX, cd / echo %cd% on Windows), so the summary names it.
|
|
77
|
+
*/
|
|
78
|
+
export declare function describeOs(platformName?: string): string;
|
|
79
|
+
/**
|
|
80
|
+
* The command that prints the working directory on this OS.
|
|
81
|
+
*/
|
|
82
|
+
export declare function describeCwdCommand(platformName?: string): string;
|
|
83
|
+
/**
|
|
84
|
+
* Remove the pids of our own processes from a pgrep result.
|
|
85
|
+
*
|
|
86
|
+
* The shell that runs pgrep carries the search pattern in its own command
|
|
87
|
+
* line, so pgrep always reports it - a server would be claimed where none
|
|
88
|
+
* runs. The pids of our own processes are therefore dropped.
|
|
89
|
+
*/
|
|
90
|
+
export declare function filterOwnPids(pids: string[], ownPids: string[]): string[];
|
|
91
|
+
/**
|
|
92
|
+
* Shorten the home directory to "~".
|
|
93
|
+
*
|
|
94
|
+
* The check is on a path boundary: "/home/frappe" is the home of
|
|
95
|
+
* "/home/frappe/app", but not of "/home/frappeX".
|
|
96
|
+
*/
|
|
97
|
+
export declare function formatWorkspacePath(workspacePath: string, home?: string): string;
|
|
47
98
|
/**
|
|
48
99
|
* Human readable mode label.
|
|
49
100
|
*
|
|
@@ -56,10 +107,12 @@ export declare function describeWorkspaceMode(env: WorkspaceEnvResult): string;
|
|
|
56
107
|
/**
|
|
57
108
|
* Describe a dev/build server as a state.
|
|
58
109
|
*
|
|
59
|
-
* "not
|
|
60
|
-
*
|
|
61
|
-
*
|
|
110
|
+
* "not detected" is what a check that found nothing says - it is NOT the
|
|
111
|
+
* same as "not running": on a platform where no check is possible the
|
|
112
|
+
* state is "not checked". Neither of them says anything about the
|
|
113
|
+
* workspace mode.
|
|
62
114
|
*/
|
|
115
|
+
export declare function describeServerState(state: ServerState): string;
|
|
63
116
|
export declare function describeServerState(running: boolean, hasScript: boolean): string;
|
|
64
117
|
/**
|
|
65
118
|
* One line status for the footer / status bar.
|
|
@@ -12,6 +12,88 @@
|
|
|
12
12
|
* "not running (script available)" so it cannot be mistaken for a running
|
|
13
13
|
* server or for evidence about the workspace mode.
|
|
14
14
|
*/
|
|
15
|
+
/**
|
|
16
|
+
* The state of a dev/build server.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Is this command line a package-manager launcher?
|
|
20
|
+
*
|
|
21
|
+
* A launcher ("npm run dev", "bun run start") only STARTS a server - the
|
|
22
|
+
* server is its child. Counting the launcher would report a running
|
|
23
|
+
* server for a script that does not start one at all ("sleep 300").
|
|
24
|
+
*
|
|
25
|
+
* The rule is pure, so it lives in the pure module and can be tested
|
|
26
|
+
* without the SQLite cache.
|
|
27
|
+
*/
|
|
28
|
+
export function isLauncherCommand(cmdline) {
|
|
29
|
+
return /^(npm|bun|yarn|pnpm)\b.*\b(run\s+)?(dev|start)\b/.test(cmdline.trim());
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The name of the operating system the harness runs on.
|
|
33
|
+
*
|
|
34
|
+
* The OS decides which command shows the working directory (pwd on
|
|
35
|
+
* POSIX, cd / echo %cd% on Windows), so the summary names it.
|
|
36
|
+
*/
|
|
37
|
+
export function describeOs(platformName) {
|
|
38
|
+
const name = platformName ?? process.platform;
|
|
39
|
+
switch (name) {
|
|
40
|
+
case "linux":
|
|
41
|
+
return "Linux";
|
|
42
|
+
case "darwin":
|
|
43
|
+
return "macOS";
|
|
44
|
+
case "win32":
|
|
45
|
+
return "Windows";
|
|
46
|
+
default:
|
|
47
|
+
return name;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The command that prints the working directory on this OS.
|
|
52
|
+
*/
|
|
53
|
+
export function describeCwdCommand(platformName) {
|
|
54
|
+
switch (platformName ?? process.platform) {
|
|
55
|
+
case "win32":
|
|
56
|
+
return "cd or echo %cd% (CMD), or (Get-Location).Path (PowerShell)";
|
|
57
|
+
case "linux":
|
|
58
|
+
case "darwin":
|
|
59
|
+
return "pwd";
|
|
60
|
+
default:
|
|
61
|
+
return "pwd (POSIX shells)";
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Remove the pids of our own processes from a pgrep result.
|
|
66
|
+
*
|
|
67
|
+
* The shell that runs pgrep carries the search pattern in its own command
|
|
68
|
+
* line, so pgrep always reports it - a server would be claimed where none
|
|
69
|
+
* runs. The pids of our own processes are therefore dropped.
|
|
70
|
+
*/
|
|
71
|
+
export function filterOwnPids(pids, ownPids) {
|
|
72
|
+
const own = new Set(ownPids.map((pid) => pid.trim()));
|
|
73
|
+
return pids.map((pid) => pid.trim()).filter((pid) => pid.length > 0 && !own.has(pid));
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Shorten the home directory to "~".
|
|
77
|
+
*
|
|
78
|
+
* The check is on a path boundary: "/home/frappe" is the home of
|
|
79
|
+
* "/home/frappe/app", but not of "/home/frappeX".
|
|
80
|
+
*/
|
|
81
|
+
export function formatWorkspacePath(workspacePath, home) {
|
|
82
|
+
if (!workspacePath)
|
|
83
|
+
return "";
|
|
84
|
+
// A trailing separator is not part of the path.
|
|
85
|
+
const path = workspacePath.replace(/[\\/]+$/, "") || workspacePath;
|
|
86
|
+
const homeDir = (home ?? process.env["HOME"] ?? process.env["USERPROFILE"] ?? "").replace(/[\\/]+$/, "");
|
|
87
|
+
// A root home ("/") shortens nothing - every path would look like "~".
|
|
88
|
+
if (homeDir && homeDir !== "/" && path.startsWith(homeDir)) {
|
|
89
|
+
const rest = path.slice(homeDir.length);
|
|
90
|
+
if (rest === "")
|
|
91
|
+
return "~";
|
|
92
|
+
if (rest.startsWith("/") || rest.startsWith("\\"))
|
|
93
|
+
return `~${rest}`;
|
|
94
|
+
}
|
|
95
|
+
return path;
|
|
96
|
+
}
|
|
15
97
|
/**
|
|
16
98
|
* Human readable mode label.
|
|
17
99
|
*
|
|
@@ -30,28 +112,42 @@ export function describeWorkspaceMode(env) {
|
|
|
30
112
|
}
|
|
31
113
|
return "UNKNOWN (no explicit NODE_ENV)";
|
|
32
114
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
115
|
+
export function describeServerState(stateOrRunning, hasScript) {
|
|
116
|
+
// The legacy signature (a boolean plus the script flag) is kept so that
|
|
117
|
+
// published consumers keep working.
|
|
118
|
+
if (typeof stateOrRunning === "boolean") {
|
|
119
|
+
if (stateOrRunning)
|
|
120
|
+
return "running";
|
|
121
|
+
return hasScript ? "not running (script available)" : "no script";
|
|
122
|
+
}
|
|
123
|
+
switch (stateOrRunning) {
|
|
124
|
+
case "running":
|
|
125
|
+
return "running";
|
|
126
|
+
case "not-detected":
|
|
127
|
+
return "not detected";
|
|
128
|
+
case "not-checked":
|
|
129
|
+
return "not checked";
|
|
130
|
+
default:
|
|
131
|
+
// An unknown state is never reported as "not running".
|
|
132
|
+
return "not checked";
|
|
133
|
+
}
|
|
46
134
|
}
|
|
47
135
|
/**
|
|
48
136
|
* One line status for the footer / status bar.
|
|
49
137
|
*/
|
|
50
138
|
export function formatEnvStatusLine(env) {
|
|
51
139
|
const mode = describeWorkspaceMode(env);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
140
|
+
// Without a stored state the honest answer is "not checked" - a legacy
|
|
141
|
+
// row that says "false" cannot tell a missing server from a platform
|
|
142
|
+
// where no check was possible.
|
|
143
|
+
const devState = env.devServerState ?? (env.devServerRunning ? "running" : "not-checked");
|
|
144
|
+
const buildState = env.buildServerState ?? (env.buildServerRunning ? "running" : "not-checked");
|
|
145
|
+
const path = formatWorkspacePath(env.workspacePath);
|
|
146
|
+
let status = `Workspace: ${path} | OS: ${describeOs()} | mode: ${mode}` +
|
|
147
|
+
` | dev server: ${describeServerState(devState)}` +
|
|
148
|
+
` | dev script: ${env.hasDevScript ? "available" : "unavailable"}` +
|
|
149
|
+
` | build server: ${describeServerState(buildState)}` +
|
|
150
|
+
` | build script: ${env.hasBuildScript ? "available" : "unavailable"}`;
|
|
55
151
|
const ramStr = formatRam(env);
|
|
56
152
|
if (ramStr) {
|
|
57
153
|
status += ` | RAM: ${ramStr}`;
|
|
@@ -93,18 +189,19 @@ function formatRamForAgent(env) {
|
|
|
93
189
|
export function formatEnvForAgentResult(env) {
|
|
94
190
|
let message = `[Workspace Environment]\n`;
|
|
95
191
|
message += `Mode: ${describeWorkspaceMode(env)}\n`;
|
|
192
|
+
message += `OS: ${describeOs()}\n`;
|
|
193
|
+
message += `Workspace path: ${formatWorkspacePath(env.workspacePath)}\n`;
|
|
194
|
+
message += `The workspace path was captured from the process working directory - to verify it in a shell: ${describeCwdCommand()}\n`;
|
|
96
195
|
if (env.evidence.length > 0) {
|
|
97
196
|
const sources = env.evidence.map((e) => `${e.source}:${e.value}`).join(", ");
|
|
98
197
|
message += `Evidence: ${sources}\n`;
|
|
99
198
|
}
|
|
100
199
|
message += `Dev script: ${env.hasDevScript ? "yes" : "no"}\n`;
|
|
101
200
|
message += `Build script: ${env.hasBuildScript ? "yes" : "no"}\n`;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
message += `Build server: running\n`;
|
|
107
|
-
}
|
|
201
|
+
const devState = env.devServerState ?? (env.devServerRunning ? "running" : "not-checked");
|
|
202
|
+
const buildState = env.buildServerState ?? (env.buildServerRunning ? "running" : "not-checked");
|
|
203
|
+
message += `Dev server: ${describeServerState(devState)}\n`;
|
|
204
|
+
message += `Build server: ${describeServerState(buildState)}\n`;
|
|
108
205
|
if (env.ramTotalGb !== null || env.ramAvailableGb !== null) {
|
|
109
206
|
message += `RAM: ${formatRamForAgent(env)}\n`;
|
|
110
207
|
if (env.lowRamWarning) {
|
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
* Stores detected environment in SQLite for agent reference.
|
|
10
10
|
* Uses synchronous directory creation and exception-safe operations.
|
|
11
11
|
*/
|
|
12
|
-
import { describeServerState, describeWorkspaceMode, formatEnvForAgentResult } from "./workspace-env-format.js";
|
|
13
|
-
import type { EnvEvidence, WorkspaceEnvResult, WorkspaceMode } from "./workspace-env-format.js";
|
|
12
|
+
import { describeCwdCommand, describeOs, describeServerState, describeWorkspaceMode, formatEnvForAgentResult, formatWorkspacePath } from "./workspace-env-format.js";
|
|
13
|
+
import type { EnvEvidence, ServerState, WorkspaceEnvResult, WorkspaceMode } from "./workspace-env-format.js";
|
|
14
14
|
/**
|
|
15
15
|
* The mode/evidence types and every human readable rendering of the workspace
|
|
16
16
|
* environment live in workspace-env-format.ts. They are re-exported here so
|
|
17
17
|
* the existing import paths keep working.
|
|
18
18
|
*/
|
|
19
|
-
export { describeServerState, describeWorkspaceMode, formatEnvForAgentResult, };
|
|
20
|
-
export type { EnvEvidence, WorkspaceEnvResult, WorkspaceMode };
|
|
19
|
+
export { describeCwdCommand, describeOs, describeServerState, describeWorkspaceMode, formatEnvForAgentResult, formatWorkspacePath, };
|
|
20
|
+
export type { EnvEvidence, ServerState, WorkspaceEnvResult, WorkspaceMode };
|
|
21
21
|
/**
|
|
22
22
|
* Detect and store workspace environment
|
|
23
23
|
*/
|