@pellux/goodvibes-agent 1.9.1 → 1.10.0
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/CHANGELOG.md +10 -0
- package/README.md +12 -1
- package/dist/package/main.js +36712 -28803
- package/dist/package/{web-tree-sitter-jbz042ba.wasm → web-tree-sitter-e011xaqr.wasm} +0 -0
- package/docs/README.md +1 -1
- package/docs/connected-host.md +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/tools-and-commands.md +1 -0
- package/package.json +3 -3
- package/release/live-verification/live-verification.json +11 -11
- package/release/live-verification/live-verification.md +12 -12
- package/src/agent/email/email-service.ts +1 -1
- package/src/agent/email/imap-client.ts +4 -4
- package/src/agent/email/smtp-client.ts +5 -5
- package/src/cli/config-overrides.ts +29 -14
- package/src/cli/entrypoint.ts +12 -4
- package/src/cli/launch-auto-update.ts +218 -0
- package/src/cli/relay-command.ts +4 -4
- package/src/cli/service-posture.ts +2 -2
- package/src/cli/tui-startup.ts +31 -0
- package/src/cli/workspaces-command.ts +5 -1
- package/src/cli-flags.ts +1 -1
- package/src/config/index.ts +1 -1
- package/src/config/update-settings.ts +45 -0
- package/src/config/workspace-registration.ts +214 -15
- package/src/input/commands/runtime-services.ts +0 -5
- package/src/input/commands/update-runtime.ts +313 -0
- package/src/input/commands.ts +2 -0
- package/src/input/feed-context-factory.ts +2 -2
- package/src/input/handler-feed.ts +8 -8
- package/src/input/handler.ts +1 -1
- package/src/input/mcp-workspace.ts +5 -1
- package/src/input/panel-paste-flood-guard.ts +1 -1
- package/src/input/settings-modal-types.ts +11 -5
- package/src/input/settings-modal.ts +56 -61
- package/src/main.ts +19 -20
- package/src/renderer/activity-sidebar.ts +53 -4
- package/src/renderer/settings-modal-helpers.ts +2 -0
- package/src/renderer/settings-modal.ts +37 -25
- package/src/runtime/bootstrap-core.ts +16 -5
- package/src/runtime/bootstrap-external-services.ts +107 -11
- package/src/runtime/bootstrap-hook-bridge.ts +2 -2
- package/src/runtime/bootstrap-shell.ts +4 -4
- package/src/runtime/bootstrap.ts +34 -12
- package/src/runtime/connected-host-autostart.ts +269 -0
- package/src/runtime/daemon-receipts.ts +66 -0
- package/src/runtime/diagnostics/panels/index.ts +0 -2
- package/src/runtime/feature-enablement.ts +176 -0
- package/src/runtime/index.ts +12 -29
- package/src/runtime/memory-spine-adoption.ts +18 -0
- package/src/runtime/onboarding/apply.ts +50 -37
- package/src/runtime/onboarding/types.ts +2 -2
- package/src/runtime/onboarding/verify.ts +22 -4
- package/src/runtime/release-artifacts.ts +113 -0
- package/src/runtime/services.ts +228 -19
- package/src/runtime/session-spine-rest-transport.ts +84 -4
- package/src/runtime/ui-services.ts +1 -1
- package/src/runtime/update-check.ts +64 -0
- package/src/shell/ui-openers.ts +8 -0
- package/src/tools/agent-harness-metadata.ts +8 -0
- package/src/tools/agent-harness-setup-connected-host.ts +1 -1
- package/src/tools/agent-harness-setup-posture.ts +1 -1
- package/src/version.ts +1 -1
- package/src/runtime/diagnostics/panels/ops.ts +0 -156
- package/src/runtime/surface-feature-flags.ts +0 -100
|
Binary file
|
package/docs/README.md
CHANGED
package/docs/connected-host.md
CHANGED
|
@@ -75,7 +75,7 @@ The model can inspect the public operator method catalog with `host action:"meth
|
|
|
75
75
|
|
|
76
76
|
The model can inspect service posture with `host action:"services"`. That report exposes endpoint binding, network-facing posture, issues, and redacted-log diagnostics used by status, doctor, and support bundles. Use `includeParameters:true` when reachability probes and redacted log tail are needed. To inspect one endpoint, use `host action:"service"` with `endpointId`, `target`, or `query`; valid endpoint ids are `controlPlane`, `httpListener`, and `web`. The connected browser cockpit/PWA is the visible UI surface `connected-browser-cockpit`; `computer action:"browser"` inspects readiness and `computer action:"open_browser" confirm:true explicitUserRequest:"..."` opens the configured URL through the existing confirmed surface route. `ui_surface surfaceId:"connected-browser-cockpit"` remains available for detailed compatibility inspection and reports Agent workspace category coverage, mobile/PWA control routes, the Agent onboarding marker, and browser/PWA first-run evidence. Certified SDK/daemon browser/PWA category-route records can make the cockpit `browser-native-ready` only when every Agent workspace category has schema/version/publication/publisher/provenance/freshness-cursor/receipt metadata, exact inspect/open routes, and mobile/touch evidence. Certified browser/PWA first-run records add manifest, service-worker, install, and offline evidence with redacted URLs and summaries. Start/setup readiness can also satisfy the setup checklist from saved durable artifacts or live SDK/daemon setup read models when the connected host publishes them, and reports the gap when no receipt exists. Service lifecycle and listener changes must use setup or confirmed daemon operator methods.
|
|
77
77
|
|
|
78
|
-
For setup or host repair asks, start with `setup action:"repair"`. It is read-only and chooses the next safe route for the current setup blocker or a named target: connected-host status, a `services.status` receipt, confirmed token repair, user-run bootstrap commands, or no lifecycle action when the host is already reachable. It does not start, install, restart, write tokens, import settings, or open UI by itself.
|
|
78
|
+
For setup or host repair asks, start with `setup action:"repair"`. It is read-only and chooses the next safe route for the current setup blocker or a named target: connected-host status, a `services.status` receipt, confirmed token repair, user-run bootstrap commands, or no lifecycle action when the host is already reachable. It does not start, install, restart, write tokens, import settings, or open UI by itself. Separately from these routes, at boot the Agent starts a host that is installed on this machine but stopped: one start through the platform service manager, a bounded wait for it to answer, and an honest receipt. A running host is never restarted, a held port is left alone, and a host that is not installed keeps this guidance.
|
|
79
79
|
|
|
80
80
|
The model can inspect live connected-host readiness with `host action:"status"`. That report uses the same status probe as the CLI: it checks the connected-host status route, verifies host compatibility, checks isolated Agent Knowledge when token and compatibility posture allow it, reports endpoint bindings and token posture without printing token values, returns actionable findings, and includes a compact `modelRoute` for follow-up diagnostics. `includeParameters:true` adds route family and capability detail. Lower-level `connected_host_status` and `daemon_status` remain compatibility routes.
|
|
81
81
|
|
package/docs/getting-started.md
CHANGED
|
@@ -189,7 +189,7 @@ Host diagnostics:
|
|
|
189
189
|
|
|
190
190
|
Model-visible diagnostics prefer `host action:"status|capabilities|capability|services|service|methods|method"`. Lower-level `service_posture`, `service_endpoint`, `connected_host`, `connected_host_status`, `connected_host_capability`, `daemon`, and `daemon_status` harness modes remain available for compatibility and detailed inspection. `agent_operator_method` can run read-only routes directly and write/admin routes only with `confirm:true` plus `explicitUserRequest`.
|
|
191
191
|
|
|
192
|
-
When no connected host is reachable, inspect `setup action:"item" setupItemId:"connected-host-readiness"` for the offline bootstrap plan. It returns user-run commands to verify Bun, install and trust the owning GoodVibes host package, verify host entrypoints, start the GoodVibes service, and reconnect Agent. Agent does not run those host install/start commands implicitly. When the host auth token is missing or malformed on the local machine, use `setup action:"token" setupItemId:"connected-host-auth" confirm:true explicitUserRequest:"..."`; it uses the GoodVibes SDK pairing helper to create or repair `~/.goodvibes/daemon/operator-tokens.json`, preserves valid existing tokens, leaves environment tokens untouched, and returns only path/fingerprint metadata.
|
|
192
|
+
When no connected host is reachable, inspect `setup action:"item" setupItemId:"connected-host-readiness"` for the offline bootstrap plan. It returns user-run commands to verify Bun, install and trust the owning GoodVibes host package, verify host entrypoints, start the GoodVibes service, and reconnect Agent. Agent does not run those host install/start commands implicitly. One bounded exception happens at boot: when the host is already installed on this machine but its service is stopped, Agent starts it once through the platform service manager, waits briefly for it to answer, and reports what it did. When the host auth token is missing or malformed on the local machine, use `setup action:"token" setupItemId:"connected-host-auth" confirm:true explicitUserRequest:"..."`; it uses the GoodVibes SDK pairing helper to create or repair `~/.goodvibes/daemon/operator-tokens.json`, preserves valid existing tokens, leaves environment tokens untouched, and returns only path/fingerprint metadata.
|
|
193
193
|
|
|
194
194
|
## Current Product Notes
|
|
195
195
|
|
|
@@ -332,6 +332,7 @@ Routine promotion is an explicit scheduling route. Local routines stay local unt
|
|
|
332
332
|
| `/tts` | Submit a normal prompt and play the assistant response through live TTS. |
|
|
333
333
|
| `/undo` | Undo the last conversation turn. |
|
|
334
334
|
| `/unpin` | Unpin a model from the favorites list. |
|
|
335
|
+
| `/update` | Check for a newer release; for binary installs, verify and apply it or roll back to the kept previous version. |
|
|
335
336
|
| `/vibe` | Inspect, create, show, or import VIBE.md personality files. |
|
|
336
337
|
| `/voice` | Review voice posture and portable voice metadata. |
|
|
337
338
|
| `/welcome` | Open or print the Agent setup guide. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pellux/goodvibes-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "GoodVibes personal operator assistant TUI with a proactive Agent product brain, isolated Agent Knowledge, local profiles, routines, skills, personas, and explicit build delegation.",
|
|
6
6
|
"type": "module",
|
|
@@ -93,8 +93,8 @@
|
|
|
93
93
|
},
|
|
94
94
|
"dependencies": {},
|
|
95
95
|
"devDependencies": {
|
|
96
|
-
"@pellux/goodvibes-sdk": "1.
|
|
97
|
-
"@pellux/goodvibes-terminal-shell": "1.
|
|
96
|
+
"@pellux/goodvibes-sdk": "1.8.0",
|
|
97
|
+
"@pellux/goodvibes-terminal-shell": "1.8.0",
|
|
98
98
|
"sql.js": "^1.14.1",
|
|
99
99
|
"sqlite-vec": "^0.1.9",
|
|
100
100
|
"zustand": "^5.0.12",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-07-
|
|
2
|
+
"generatedAt": "2026-07-13T23:20:59.518Z",
|
|
3
3
|
"homeDir": "[goodvibes-home]",
|
|
4
4
|
"binaryPath": "[agent-binary]",
|
|
5
5
|
"connectedHostBaseUrl": "http://127.0.0.1:3421",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"id": "verification-ledger",
|
|
10
10
|
"title": "Verification inventory ledger",
|
|
11
11
|
"status": "pass",
|
|
12
|
-
"summary": "99.
|
|
13
|
-
"detail": "
|
|
12
|
+
"summary": "99.6% local verification signal across 978 inventory items.",
|
|
13
|
+
"detail": "73.7% local behavior verified; 223 item(s) require external outcomes."
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"id": "compiled-cli-present",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"title": "Agent CLI version command",
|
|
24
24
|
"status": "pass",
|
|
25
25
|
"summary": "Agent CLI version returned successfully.",
|
|
26
|
-
"detail": "goodvibes-agent 1.
|
|
26
|
+
"detail": "goodvibes-agent 1.9.1"
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
"id": "cli-status-json",
|
|
@@ -37,14 +37,14 @@
|
|
|
37
37
|
"title": "Agent CLI compatibility JSON command",
|
|
38
38
|
"status": "pass",
|
|
39
39
|
"summary": "Agent CLI compatibility returned parseable JSON.",
|
|
40
|
-
"detail": "{\n \"ok\": true,\n \"packageVersion\": \"1.
|
|
40
|
+
"detail": "{\n \"ok\": true,\n \"packageVersion\": \"1.9.1\",\n \"connectedHost\": {\n \"baseUrl\": \"http://127.0.0.1:3421\",\n \"status\": 200,\n \"reachable\": true,\n \"compatible\": true\n },\n \"auth\": {\n \"tokenPresent\": true,\n \"tokenPath\": \"env:GOODVIBES_CONNECTED_HOST_TOKEN\"\n },\n \"agentKnowledge\": {\n \"route\": \"/api/goodvibes-agent/knowledge/status\",\n \"ready\": true,\n \"kind\": \"ok\"\n }\n}"
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"id": "cli-agent-knowledge-status",
|
|
44
44
|
"title": "Agent Knowledge CLI status command",
|
|
45
45
|
"status": "pass",
|
|
46
46
|
"summary": "Agent Knowledge status returned parseable JSON.",
|
|
47
|
-
"detail": "{\n \"ok\": true,\n \"kind\": \"agentKnowledge.status\",\n \"route\": \"/api/goodvibes-agent/knowledge/status\",\n \"data\": {\n \"ready\": true,\n \"storagePath\": \"[goodvibes-home]/tui/knowledge-agent.sqlite\",\n \"sourceCount\": 0,\n \"nodeCount\": 0,\n \"edgeCount\": 0,\n \"issueCount\": 0,\n \"extractionCount\": 0,\n \"jobRunCount\":
|
|
47
|
+
"detail": "{\n \"ok\": true,\n \"kind\": \"agentKnowledge.status\",\n \"route\": \"/api/goodvibes-agent/knowledge/status\",\n \"data\": {\n \"ready\": true,\n \"storagePath\": \"[goodvibes-home]/tui/knowledge-agent.sqlite\",\n \"sourceCount\": 0,\n \"nodeCount\": 0,\n \"edgeCount\": 0,\n \"issueCount\": 0,\n \"extractionCount\": 0,\n \"jobRunCount\": 655,\n \"refinementTaskCount\": 0,\n \"usageCount\": 0,\n \"candidateCount\": 0,\n \"reportCount\": 31,\n \"scheduleCount\": 3,\n \"note\": \"Structured knowledge uses SQL-backed sources, nodes, edges, issues, extractions, and job runs. Markdown is an optional projection, not the source of truth.\"\n }\n}"
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
"id": "cli-providers",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"title": "Authenticated connected-host /status",
|
|
66
66
|
"status": "pass",
|
|
67
67
|
"summary": "/status returned 200 with parseable JSON.",
|
|
68
|
-
"detail": "{\"status\":\"running\",\"version\":\"1.
|
|
68
|
+
"detail": "{\"status\":\"running\",\"version\":\"1.7.1\"}"
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
"id": "connected-host-health",
|
|
@@ -78,15 +78,15 @@
|
|
|
78
78
|
"id": "openai-compatible-models",
|
|
79
79
|
"title": "OpenAI-compatible /v1/models route",
|
|
80
80
|
"status": "pass",
|
|
81
|
-
"summary": "/v1/models returned
|
|
82
|
-
"detail": "/v1/models returned
|
|
81
|
+
"summary": "/v1/models returned 307 model(s).",
|
|
82
|
+
"detail": "/v1/models returned 307 model(s); model identifiers omitted from release artifact."
|
|
83
83
|
},
|
|
84
84
|
{
|
|
85
85
|
"id": "agent-knowledge-status",
|
|
86
86
|
"title": "Agent Knowledge isolated /status",
|
|
87
87
|
"status": "pass",
|
|
88
88
|
"summary": "Agent Knowledge status route returned parseable isolated JSON.",
|
|
89
|
-
"detail": "{\"ready\":true,\"storagePath\":\"[goodvibes-home]/tui/knowledge-agent.sqlite\",\"sourceCount\":0,\"nodeCount\":0,\"edgeCount\":0,\"issueCount\":0,\"extractionCount\":0,\"jobRunCount\":
|
|
89
|
+
"detail": "{\"ready\":true,\"storagePath\":\"[goodvibes-home]/tui/knowledge-agent.sqlite\",\"sourceCount\":0,\"nodeCount\":0,\"edgeCount\":0,\"issueCount\":0,\"extractionCount\":0,\"jobRunCount\":655,\"refinementTaskCount\":0,\"usageCount\":0,\"candidateCount\":0,\"reportCount\":31,\"scheduleCount\":3,\"note\":\"Structured knowledge uses SQL-backed sources, nodes, edges, issues, extractions, and job runs. Markdown is an optional projection, not the source of truth.\"}"
|
|
90
90
|
},
|
|
91
91
|
{
|
|
92
92
|
"id": "agent-knowledge-ask-isolated",
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"title": "Agent Knowledge isolated map",
|
|
129
129
|
"status": "pass",
|
|
130
130
|
"summary": "Agent Knowledge isolated map stayed on the isolated Agent route.",
|
|
131
|
-
"detail": "{\"ok\":true,\"title\":\"Knowledge Map\",\"generatedAt\":
|
|
131
|
+
"detail": "{\"ok\":true,\"title\":\"Knowledge Map\",\"generatedAt\":1783984859516,\"width\":1280,\"height\":920,\"nodeCount\":0,\"edgeCount\":0,\"totalNodeCount\":0,\"totalEdgeCount\":0,\"facets\":{\"recordKinds\":[],\"nodeKinds\":[],\"sourceTypes\":[],\"sourceStatuses\":[],\"nodeStatuses\":[],\"issueCodes\":[],\"issueStatuses\":[],\"issueSeverities\":[],\"edgeRelations\":[],\"tags\":[]},\"nodes\":[],\"edges\":[],\"svg\":\"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"1280\\\" height=\\\"920\\\" viewBox=\\\"0 0 1280 920\\\" role=\\\"img\\\" aria-label=\\\"Knowledge Map\\\">\\n<defs>\\n <radialGradient id=\\\"knowledgeMapBg\\\" cx=\\\"50%\\\" cy=\\\"46%\\\" r=\\\"70%\\\">\\n <stop offset=\\\"0%\\\" stop-color=\\\"#f7f4ec\\\" />\\n <stop offset=\\\"60%\\\" stop-color=\\\"#e9eef0\\\" />\\n <stop offset=\\\"100%\\\" stop-color=\\\"#dde6df\\\" />\\n </radialGradient>\\n <filter id=\\\"softShadow\\\" x=\\\"-20%\\\" y=\\\"-20%\\\" width=\\\"140%\\\" height=\\\"140%\\\">\\n <feDropShadow dx=\\\"0\\\" dy=\\\"6\\... [truncated]"
|
|
132
132
|
},
|
|
133
133
|
{
|
|
134
134
|
"id": "agent-knowledge-connectors-isolated",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# GoodVibes Agent Live Verification
|
|
2
2
|
|
|
3
|
-
Generated: 2026-07-
|
|
3
|
+
Generated: 2026-07-13T23:20:59.518Z
|
|
4
4
|
Home: `[goodvibes-home]`
|
|
5
5
|
Binary: `[agent-binary]`
|
|
6
6
|
Connected host: `http://127.0.0.1:3421`
|
|
@@ -14,7 +14,7 @@ Connected host: `http://127.0.0.1:3421`
|
|
|
14
14
|
|
|
15
15
|
| Check | Status | Summary |
|
|
16
16
|
|---|---|---|
|
|
17
|
-
| Verification inventory ledger | pass | 99.
|
|
17
|
+
| Verification inventory ledger | pass | 99.6% local verification signal across 978 inventory items. |
|
|
18
18
|
| Compiled GoodVibes Agent CLI binary | pass | Found [agent-binary]. |
|
|
19
19
|
| Agent CLI version command | pass | Agent CLI version returned successfully. |
|
|
20
20
|
| Agent CLI status JSON command | pass | Agent CLI status returned parseable JSON. |
|
|
@@ -24,7 +24,7 @@ Connected host: `http://127.0.0.1:3421`
|
|
|
24
24
|
| CLI doctor command | pass | Doctor completed; 1 operator-configuration risk advisory(ies) noted (intentional trust posture, not a release defect). |
|
|
25
25
|
| Authenticated connected-host /status | pass | /status returned 200 with parseable JSON. |
|
|
26
26
|
| Authenticated connected-host /api/health | pass | Health overall=healthy. |
|
|
27
|
-
| OpenAI-compatible /v1/models route | pass | /v1/models returned
|
|
27
|
+
| OpenAI-compatible /v1/models route | pass | /v1/models returned 307 model(s). |
|
|
28
28
|
| Agent Knowledge isolated /status | pass | Agent Knowledge status route returned parseable isolated JSON. |
|
|
29
29
|
| Agent Knowledge isolated ask | pass | Agent Knowledge ask stayed on the isolated Agent route. |
|
|
30
30
|
| Agent Knowledge isolated search | pass | Agent Knowledge search stayed on the isolated Agent route. |
|
|
@@ -39,13 +39,13 @@ Connected host: `http://127.0.0.1:3421`
|
|
|
39
39
|
### Verification inventory ledger
|
|
40
40
|
|
|
41
41
|
```text
|
|
42
|
-
|
|
42
|
+
73.7% local behavior verified; 223 item(s) require external outcomes.
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
### Agent CLI version command
|
|
46
46
|
|
|
47
47
|
```text
|
|
48
|
-
goodvibes-agent 1.
|
|
48
|
+
goodvibes-agent 1.9.1
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
### Agent CLI status JSON command
|
|
@@ -59,7 +59,7 @@ Status JSON command completed; provider/model identifiers omitted from release a
|
|
|
59
59
|
```text
|
|
60
60
|
{
|
|
61
61
|
"ok": true,
|
|
62
|
-
"packageVersion": "1.
|
|
62
|
+
"packageVersion": "1.9.1",
|
|
63
63
|
"connectedHost": {
|
|
64
64
|
"baseUrl": "http://127.0.0.1:3421",
|
|
65
65
|
"status": 200,
|
|
@@ -93,11 +93,11 @@ Status JSON command completed; provider/model identifiers omitted from release a
|
|
|
93
93
|
"edgeCount": 0,
|
|
94
94
|
"issueCount": 0,
|
|
95
95
|
"extractionCount": 0,
|
|
96
|
-
"jobRunCount":
|
|
96
|
+
"jobRunCount": 655,
|
|
97
97
|
"refinementTaskCount": 0,
|
|
98
98
|
"usageCount": 0,
|
|
99
99
|
"candidateCount": 0,
|
|
100
|
-
"reportCount":
|
|
100
|
+
"reportCount": 31,
|
|
101
101
|
"scheduleCount": 3,
|
|
102
102
|
"note": "Structured knowledge uses SQL-backed sources, nodes, edges, issues, extractions, and job runs. Markdown is an optional projection, not the source of truth."
|
|
103
103
|
}
|
|
@@ -119,7 +119,7 @@ Doctor command completed without findings; provider/model identifiers and creden
|
|
|
119
119
|
### Authenticated connected-host /status
|
|
120
120
|
|
|
121
121
|
```text
|
|
122
|
-
{"status":"running","version":"1.
|
|
122
|
+
{"status":"running","version":"1.7.1"}
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
### Authenticated connected-host /api/health
|
|
@@ -131,13 +131,13 @@ Doctor command completed without findings; provider/model identifiers and creden
|
|
|
131
131
|
### OpenAI-compatible /v1/models route
|
|
132
132
|
|
|
133
133
|
```text
|
|
134
|
-
/v1/models returned
|
|
134
|
+
/v1/models returned 307 model(s); model identifiers omitted from release artifact.
|
|
135
135
|
```
|
|
136
136
|
|
|
137
137
|
### Agent Knowledge isolated /status
|
|
138
138
|
|
|
139
139
|
```text
|
|
140
|
-
{"ready":true,"storagePath":"[goodvibes-home]/tui/knowledge-agent.sqlite","sourceCount":0,"nodeCount":0,"edgeCount":0,"issueCount":0,"extractionCount":0,"jobRunCount":
|
|
140
|
+
{"ready":true,"storagePath":"[goodvibes-home]/tui/knowledge-agent.sqlite","sourceCount":0,"nodeCount":0,"edgeCount":0,"issueCount":0,"extractionCount":0,"jobRunCount":655,"refinementTaskCount":0,"usageCount":0,"candidateCount":0,"reportCount":31,"scheduleCount":3,"note":"Structured knowledge uses SQL-backed sources, nodes, edges, issues, extractions, and job runs. Markdown is an optional projection, not the source of truth."}
|
|
141
141
|
```
|
|
142
142
|
|
|
143
143
|
### Agent Knowledge isolated ask
|
|
@@ -173,7 +173,7 @@ Doctor command completed without findings; provider/model identifiers and creden
|
|
|
173
173
|
### Agent Knowledge isolated map
|
|
174
174
|
|
|
175
175
|
```text
|
|
176
|
-
{"ok":true,"title":"Knowledge Map","generatedAt":
|
|
176
|
+
{"ok":true,"title":"Knowledge Map","generatedAt":1783984859516,"width":1280,"height":920,"nodeCount":0,"edgeCount":0,"totalNodeCount":0,"totalEdgeCount":0,"facets":{"recordKinds":[],"nodeKinds":[],"sourceTypes":[],"sourceStatuses":[],"nodeStatuses":[],"issueCodes":[],"issueStatuses":[],"issueSeverities":[],"edgeRelations":[],"tags":[]},"nodes":[],"edges":[],"svg":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1280\" height=\"920\" viewBox=\"0 0 1280 920\" role=\"img\" aria-label=\"Knowledge Map\">\n<defs>\n <radialGradient id=\"knowledgeMapBg\" cx=\"50%\" cy=\"46%\" r=\"70%\">\n <stop offset=\"0%\" stop-color=\"#f7f4ec\" />\n <stop offset=\"60%\" stop-color=\"#e9eef0\" />\n <stop offset=\"100%\" stop-color=\"#dde6df\" />\n </radialGradient>\n <filter id=\"softShadow\" x=\"-20%\" y=\"-20%\" width=\"140%\" height=\"140%\">\n <feDropShadow dx=\"0\" dy=\"6\... [truncated]
|
|
177
177
|
```
|
|
178
178
|
|
|
179
179
|
### Agent Knowledge isolated connectors list
|
|
@@ -363,7 +363,7 @@ export class EmailService {
|
|
|
363
363
|
password,
|
|
364
364
|
});
|
|
365
365
|
|
|
366
|
-
//
|
|
366
|
+
// Validate at the service boundary so injection is blocked regardless of
|
|
367
367
|
// which client implementation is used.
|
|
368
368
|
validateSmtpAddress(config.fromAddress, 'from');
|
|
369
369
|
validateSmtpAddress(opts.to, 'to');
|
|
@@ -80,7 +80,7 @@ function buildXOAuth2Token(username: string, bearerToken: string): string {
|
|
|
80
80
|
* Owns a single shared read cursor; callers must not interleave awaits.
|
|
81
81
|
*/
|
|
82
82
|
// ---------------------------------------------------------------------------
|
|
83
|
-
// IMAP credential quoting
|
|
83
|
+
// IMAP credential quoting: LOGIN injection prevention
|
|
84
84
|
// ---------------------------------------------------------------------------
|
|
85
85
|
|
|
86
86
|
/**
|
|
@@ -248,7 +248,7 @@ class ImapSession {
|
|
|
248
248
|
const literalMatch = /\{(\d+)\}$/.exec(line);
|
|
249
249
|
if (literalMatch) {
|
|
250
250
|
const requested = parseInt(literalMatch[1] ?? '0', 10);
|
|
251
|
-
//
|
|
251
|
+
// Cap server-supplied literal size to prevent memory exhaustion
|
|
252
252
|
if (requested > this.literalCap) {
|
|
253
253
|
cleanup();
|
|
254
254
|
reject(new Error(
|
|
@@ -538,7 +538,7 @@ export class ImapClient {
|
|
|
538
538
|
|
|
539
539
|
private session(): ImapSession {
|
|
540
540
|
const maxBodyBytes = this.options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;
|
|
541
|
-
//
|
|
541
|
+
// Cap literal size at the larger of 1 MB or 4× the configured body preview limit
|
|
542
542
|
const literalCap = Math.max(1_048_576, 4 * maxBodyBytes);
|
|
543
543
|
return new ImapSession(
|
|
544
544
|
this.options.socket,
|
|
@@ -554,7 +554,7 @@ export class ImapClient {
|
|
|
554
554
|
const token = buildXOAuth2Token(username, password.slice(7));
|
|
555
555
|
await session.command(`AUTHENTICATE XOAUTH2 ${token}`);
|
|
556
556
|
} else {
|
|
557
|
-
// LOGIN — credentials are quoted per RFC 3501 to prevent injection
|
|
557
|
+
// LOGIN — credentials are quoted per RFC 3501 to prevent injection.
|
|
558
558
|
// Credentials are not logged anywhere in this module.
|
|
559
559
|
const quotedUser = imapQuoteCredential(username, 'username');
|
|
560
560
|
const quotedPass = imapQuoteCredential(password, 'password');
|
|
@@ -53,15 +53,15 @@ const DEFAULT_TIMEOUT_MS = 15_000;
|
|
|
53
53
|
const CRLF = '\r\n';
|
|
54
54
|
|
|
55
55
|
// ---------------------------------------------------------------------------
|
|
56
|
-
// Input validation
|
|
56
|
+
// Input validation: SMTP header/command injection prevention
|
|
57
57
|
// ---------------------------------------------------------------------------
|
|
58
58
|
|
|
59
|
-
/** Control-character pattern: CR, LF, and other C0
|
|
59
|
+
/** Control-character pattern: CR, LF, and the other C0 and C1 control characters. */
|
|
60
60
|
const CONTROL_CHAR_RE = /[\x00-\x1f\x7f-\x9f]/;
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* Validate a single SMTP envelope address (MAIL FROM / RCPT TO value).
|
|
64
|
-
* Rejects: control characters (\r, \n, any C0
|
|
64
|
+
* Rejects: control characters (\r, \n, any C0 or C1), spaces, angle brackets,
|
|
65
65
|
* comma-separated lists. Only a single bare address is accepted.
|
|
66
66
|
*
|
|
67
67
|
* @throws Error with a plain-language message on invalid input.
|
|
@@ -274,7 +274,7 @@ export class SmtpClient {
|
|
|
274
274
|
// AUTH
|
|
275
275
|
await this.authenticate(session, capabilities, username, password);
|
|
276
276
|
|
|
277
|
-
// Validate envelope fields before writing to the protocol stream (
|
|
277
|
+
// Validate envelope fields before writing to the protocol stream (injection prevention)
|
|
278
278
|
validateSmtpAddress(opts.from, 'from');
|
|
279
279
|
validateSmtpAddress(opts.to, 'to');
|
|
280
280
|
validateSmtpSubject(opts.subject);
|
|
@@ -427,7 +427,7 @@ export function createSmtpStartTlsSocket(
|
|
|
427
427
|
return;
|
|
428
428
|
}
|
|
429
429
|
|
|
430
|
-
//
|
|
430
|
+
// STARTTLS guard: assert no pipelined data arrived after the 220 reply.
|
|
431
431
|
// Any bytes beyond the \n of the 220 line indicate a hostile server
|
|
432
432
|
// injecting data before TLS negotiation begins.
|
|
433
433
|
const newlineIdx = stBuffer.indexOf('\n');
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { ConfigKey, ConfigManager, ConfigSetting
|
|
1
|
+
import type { ConfigKey, ConfigManager, ConfigSetting } from '../config/index.ts';
|
|
2
2
|
import { CONFIG_SCHEMA, ConfigError } from '../config/index.ts';
|
|
3
|
+
import { resolveFeatureEnablementWrite } from '../runtime/feature-enablement.ts';
|
|
3
4
|
import type { GoodVibesCliCommand, GoodVibesCliFlags } from './types.ts';
|
|
4
5
|
import { RUNTIME_ENDPOINT_CONFIG_KEYS, hostModeForHostname } from './endpoints.ts';
|
|
5
6
|
import type { RuntimeEndpointId } from './endpoints.ts';
|
|
@@ -150,24 +151,38 @@ export function applyRuntimeUrlOverride(
|
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
153
|
|
|
153
|
-
|
|
154
|
+
/**
|
|
155
|
+
* Apply --enable-feature/--disable-feature as RUNTIME-ONLY writes to the
|
|
156
|
+
* feature's domain settings key (the dissolved feature model has no separate
|
|
157
|
+
* enablement namespace). Nothing is persisted: the write lands on the
|
|
158
|
+
* in-memory config just like --config overrides, and the settings-derived
|
|
159
|
+
* gate seeding in bootstrap picks it up. Returns honest per-feature errors
|
|
160
|
+
* (unknown ids, always-available features) instead of silently accepting
|
|
161
|
+
* anything, matching applyRuntimeConfigOverrides' contract.
|
|
162
|
+
*/
|
|
163
|
+
export function applyRuntimeFeatureOverrides(
|
|
154
164
|
configManager: ConfigManager,
|
|
155
165
|
options: {
|
|
156
166
|
readonly enableFeatures: readonly string[];
|
|
157
167
|
readonly disableFeatures: readonly string[];
|
|
158
168
|
},
|
|
159
|
-
):
|
|
160
|
-
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
for (const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
): readonly string[] {
|
|
170
|
+
const errors: string[] = [];
|
|
171
|
+
const requests = [
|
|
172
|
+
...options.enableFeatures.map((featureId) => ({ featureId, desired: 'enabled' as const, flag: '--enable-feature' })),
|
|
173
|
+
...options.disableFeatures.map((featureId) => ({ featureId, desired: 'disabled' as const, flag: '--disable-feature' })),
|
|
174
|
+
];
|
|
175
|
+
for (const request of requests) {
|
|
176
|
+
try {
|
|
177
|
+
const write = resolveFeatureEnablementWrite(request.featureId, request.desired);
|
|
178
|
+
setRuntimeOnlyConfigValue(configManager, write.key, write.value);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
errors.push(error instanceof Error
|
|
181
|
+
? `Invalid ${request.flag} ${request.featureId}. ${error.message}`
|
|
182
|
+
: `Invalid ${request.flag} ${request.featureId}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return errors;
|
|
171
186
|
}
|
|
172
187
|
|
|
173
188
|
export function applyRuntimeEndpointFlagOverrides(
|
package/src/cli/entrypoint.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
applyRuntimeCommandEndpointFlagOverrides,
|
|
11
11
|
applyRuntimeConfigOverrides,
|
|
12
12
|
applyRuntimeConfigValue,
|
|
13
|
-
|
|
13
|
+
applyRuntimeFeatureOverrides,
|
|
14
14
|
applyRuntimeUrlOverride,
|
|
15
15
|
buildCliStatusSnapshot,
|
|
16
16
|
handleGoodVibesCliCommand,
|
|
@@ -27,7 +27,7 @@ import { inspectCliExternalRuntime } from './external-runtime.ts';
|
|
|
27
27
|
import { inspectConnectedHostMetrics } from './connected-host-metrics.ts';
|
|
28
28
|
import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
|
|
29
29
|
import { readCheckpointRegistrationSetting } from '../config/checkpoint-settings.ts';
|
|
30
|
-
import { migrateLegacyWorkspaceRegistryIfNeeded,
|
|
30
|
+
import { backfillCheckpointEligibilityIfNeeded, migrateLegacyWorkspaceRegistryIfNeeded, resolveCheckpointEligibilitySync } from '../config/workspace-registration.ts';
|
|
31
31
|
import { resolveAgentRuntimeProfileHome, resolveSelectedAgentRuntimeProfileHome } from '../agent/runtime-profile.ts';
|
|
32
32
|
|
|
33
33
|
type ShellEntrypointOwnership = {
|
|
@@ -147,10 +147,14 @@ export async function prepareShellCliRuntime(
|
|
|
147
147
|
console.error(overrideErrors.join('\n'));
|
|
148
148
|
process.exit(2);
|
|
149
149
|
}
|
|
150
|
-
|
|
150
|
+
const featureOverrideErrors = applyRuntimeFeatureOverrides(configManager, {
|
|
151
151
|
enableFeatures: cli.flags.enableFeatures,
|
|
152
152
|
disableFeatures: cli.flags.disableFeatures,
|
|
153
153
|
});
|
|
154
|
+
if (featureOverrideErrors.length > 0) {
|
|
155
|
+
console.error(featureOverrideErrors.join('\n'));
|
|
156
|
+
process.exit(2);
|
|
157
|
+
}
|
|
154
158
|
|
|
155
159
|
if (cli.flags.provider !== undefined || cli.flags.model !== undefined) {
|
|
156
160
|
const currentModel = configManager.get('provider.model');
|
|
@@ -207,8 +211,12 @@ export async function prepareShellCliRuntime(
|
|
|
207
211
|
if (registrationMigration) {
|
|
208
212
|
logger.info('Migrated the local workspace registry into the shared registration store', { ...registrationMigration });
|
|
209
213
|
}
|
|
214
|
+
backfillCheckpointEligibilityIfNeeded(shellPaths);
|
|
210
215
|
const checkpoints = {
|
|
211
|
-
|
|
216
|
+
// Honest to the checkpoint boundary: a workspace is "registered" for
|
|
217
|
+
// checkpoints only when it is checkpoint-ELIGIBLE (an explicit owner
|
|
218
|
+
// opt-in), not merely present in the shared store as a TUI self-record.
|
|
219
|
+
workspaceRegistered: resolveCheckpointEligibilitySync(shellPaths, bootstrapWorkingDir).status === 'covered',
|
|
212
220
|
unregisteredWorkspaceMode: readCheckpointRegistrationSetting(configManager),
|
|
213
221
|
};
|
|
214
222
|
const statusOptions = {
|