pi-harness-runtime 1.1.388 → 1.1.390

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.
Files changed (123) hide show
  1. package/README.md +242 -0
  2. package/harness/key-file-audit.ts +535 -0
  3. package/harness/startup-lines.ts +168 -0
  4. package/harness/startup-report.ts +247 -0
  5. package/index.ts +418 -73
  6. package/package.json +1 -1
  7. package/packages/a2a-adapter/package.json +1 -1
  8. package/packages/agent-policy/package.json +1 -1
  9. package/packages/architecture-generator/package.json +1 -1
  10. package/packages/auth/package.json +1 -1
  11. package/packages/autonomous-refactor/package.json +1 -1
  12. package/packages/autonomous-runtime/package.json +1 -1
  13. package/packages/cache-strategy/package.json +1 -1
  14. package/packages/capability-registry/package.json +1 -1
  15. package/packages/checkpoint/package.json +1 -1
  16. package/packages/cli-plugin-sdk/package.json +1 -1
  17. package/packages/clipboard/package.json +1 -1
  18. package/packages/clipboard-plugin/package.json +1 -1
  19. package/packages/code-generation/package.json +1 -1
  20. package/packages/code-review/package.json +1 -1
  21. package/packages/codex-adapter/package.json +1 -1
  22. package/packages/codex-watcher/package.json +1 -1
  23. package/packages/config-capture/package.json +1 -1
  24. package/packages/connection-runtime/package.json +1 -1
  25. package/packages/context-compiler/package.json +1 -1
  26. package/packages/context-discovery/package.json +1 -1
  27. package/packages/context-manager/package.json +1 -1
  28. package/packages/contracts/package.json +1 -1
  29. package/packages/cookie-sanitizer/package.json +1 -1
  30. package/packages/cost-optimizer/package.json +1 -1
  31. package/packages/dependency-analyzer/package.json +1 -1
  32. package/packages/django-plugin/package.json +1 -1
  33. package/packages/doc-generator/package.json +1 -1
  34. package/packages/durable-review/package.json +1 -1
  35. package/packages/e2e-tester/package.json +1 -1
  36. package/packages/evaluation-engine/package.json +1 -1
  37. package/packages/evaluation-runner/package.json +1 -1
  38. package/packages/event-bus/package.json +1 -1
  39. package/packages/event-sink/package.json +1 -1
  40. package/packages/event-store/package.json +1 -1
  41. package/packages/experience-replay/package.json +1 -1
  42. package/packages/feedback-collector/package.json +1 -1
  43. package/packages/file-copy-helper/package.json +1 -1
  44. package/packages/framework-detector/package.json +1 -1
  45. package/packages/framework-plugin-sdk/package.json +1 -1
  46. package/packages/frappe-plugin/package.json +1 -1
  47. package/packages/generic-web-plugin/package.json +1 -1
  48. package/packages/health-monitor/package.json +1 -1
  49. package/packages/intent-analyzer/package.json +1 -1
  50. package/packages/jev-judge/package.json +1 -1
  51. package/packages/knowledge-graph/package.json +1 -1
  52. package/packages/knowledge-retrieval/package.json +1 -1
  53. package/packages/laravel-plugin/package.json +1 -1
  54. package/packages/learning-engine/package.json +1 -1
  55. package/packages/mcp-adapter/package.json +1 -1
  56. package/packages/memory-engine/package.json +1 -1
  57. package/packages/milestone-manager/package.json +1 -1
  58. package/packages/model-registry/package.json +1 -1
  59. package/packages/nextjs-plugin/package.json +1 -1
  60. package/packages/notification/dist/adapters/line-adapter.d.ts.map +1 -1
  61. package/packages/notification/dist/adapters/line-adapter.js +6 -1
  62. package/packages/notification/dist/adapters/line-adapter.js.map +1 -1
  63. package/packages/notification/dist/notification-center.d.ts +9 -0
  64. package/packages/notification/dist/notification-center.d.ts.map +1 -1
  65. package/packages/notification/dist/notification-center.js +12 -0
  66. package/packages/notification/dist/notification-center.js.map +1 -1
  67. package/packages/notification/package.json +1 -1
  68. package/packages/notification/src/adapters/line-adapter.ts +5 -1
  69. package/packages/notification/src/notification-center.ts +13 -0
  70. package/packages/observability/package.json +1 -1
  71. package/packages/okf-indexer/package.json +1 -1
  72. package/packages/paperclip-integration/package.json +1 -1
  73. package/packages/performance-optimizer/package.json +1 -1
  74. package/packages/permission-mode/package.json +1 -1
  75. package/packages/privilege-broker/package.json +1 -1
  76. package/packages/project-analyzer/package.json +1 -1
  77. package/packages/project-bootstrap/package.json +1 -1
  78. package/packages/projection-engine/package.json +1 -1
  79. package/packages/prompt-compiler/package.json +1 -1
  80. package/packages/prompt-versioning/package.json +1 -1
  81. package/packages/provider-adapter-sdk/package.json +1 -1
  82. package/packages/provider-router/package.json +1 -1
  83. package/packages/provider-selector/package.json +1 -1
  84. package/packages/providers/package.json +1 -1
  85. package/packages/qdrant-skills/package.json +1 -1
  86. package/packages/quota-manager/package.json +1 -1
  87. package/packages/rate-limiter/package.json +1 -1
  88. package/packages/react-vite-plugin/package.json +1 -1
  89. package/packages/relay/package.json +1 -1
  90. package/packages/release-manager/package.json +1 -1
  91. package/packages/requirement-compiler/package.json +1 -1
  92. package/packages/runtime/package.json +1 -1
  93. package/packages/scheduler/package.json +1 -1
  94. package/packages/scheduler-adapter/package.json +1 -1
  95. package/packages/session/package.json +1 -1
  96. package/packages/session-api/package.json +1 -1
  97. package/packages/session-export/package.json +1 -1
  98. package/packages/shared-context/package.json +1 -1
  99. package/packages/skill-mcp-client/package.json +1 -1
  100. package/packages/skill-registry/package.json +1 -1
  101. package/packages/skills/package.json +1 -1
  102. package/packages/sprint-planner/package.json +1 -1
  103. package/packages/subscription-engine/package.json +1 -1
  104. package/packages/task-compiler/package.json +1 -1
  105. package/packages/telegram/package.json +1 -1
  106. package/packages/tencentdb-memory/package.json +1 -1
  107. package/packages/tencentdb-sync/package.json +1 -1
  108. package/packages/test-data-generator/package.json +1 -1
  109. package/packages/test-generator/package.json +1 -1
  110. package/packages/todo-bd-sync/package.json +1 -1
  111. package/packages/token-estimation/package.json +1 -1
  112. package/packages/token-optimizer/package.json +1 -1
  113. package/packages/trajectory/package.json +1 -1
  114. package/packages/tui/package.json +1 -1
  115. package/packages/types/package.json +1 -1
  116. package/packages/voice-api/package.json +1 -1
  117. package/packages/webmcp-tester/package.json +1 -1
  118. package/packages/wiki/package.json +1 -1
  119. package/packages/workflow-events/package.json +1 -1
  120. package/packages/workspace-scanner/package.json +1 -1
  121. package/packages/worktree/package.json +1 -1
  122. package/packages/write-review/package.json +1 -1
  123. package/scripts/typecheck-packages.mjs +42 -2
package/README.md CHANGED
@@ -371,6 +371,44 @@ All data stored locally in `~/.pi/`:
371
371
  +-- okf/ # (optional) Your custom OKF knowledge
372
372
  ```
373
373
 
374
+ Credentials live in their own directory, `~/.pi-harness-runtime/keys/` — one file
375
+ per secret, never in the repository. Common key files:
376
+
377
+ ```
378
+ ~/.pi-harness-runtime/keys/
379
+ +-- telegram-bot-token.txt # Telegram bot token
380
+ +-- telegram-webhook-url.txt # Public HTTPS URL of the Telegram webhook
381
+ +-- telegram-webhook-secret.txt # Webhook secret (x-telegram-bot-api-secret-token)
382
+ +-- telegram-allowed-users.txt # Allowed Telegram user ids (comma-separated)
383
+ +-- telegram-chat-id.txt # Legacy single allowed user id
384
+ +-- relay-auth-token.txt # Relay WebSocket auth token
385
+ +-- relay-ws-url.txt # Relay WebSocket URL (optional)
386
+ +-- line-access-token.txt # LINE channel access token (LINE only)
387
+ +-- line-user-id.txt # LINE user id (the extension only)
388
+ +-- line-channel-secret.txt # LINE channel secret (webhook server only)
389
+ +-- typesafe-api-key.txt # Jev / TypeSafe API key
390
+ +-- openrouter-api-key.txt # Jev / OpenRouter API key (fallback provider)
391
+ +-- jev-api-key.txt # Legacy Jev key (OpenRouter `sk-or-…` or TypeSafe)
392
+ ```
393
+
394
+ This is a subset. The complete map is spread over the places the harness reads
395
+ the credentials from: `harness/key-loader.ts` (KEY_FILE_MAP — the model and
396
+ storage keys the langchain runner loads into the environment),
397
+ `harness/telegram-auth.ts`, `index.ts` and `scripts/unified-webhook-server.ts`
398
+ (the Telegram and LINE credentials the extension and the webhook server read
399
+ from disk) and `packages/relay/src/relay-endpoint.ts` (RELAY_URL_SOURCES /
400
+ RELAY_TOKEN_SOURCES — the relay endpoint and token).
401
+
402
+ Two places can name the same credential with different files: the key-loader
403
+ map is what the **langchain runner** loads into the environment, while the
404
+ extension reads its own files (`qdrant-cluster-url.txt`, not
405
+ `qdrant-cluster-endpoint.txt`; `telegram-bot-token.txt`, not a mapped
406
+ variable). The startup fix commands always name the file the running code
407
+ actually reads.
408
+
409
+ See [Relay Setup](#relay-setup-two-way-telegram-stream) for the `echo` commands that
410
+ create the relay and Telegram key files.
411
+
374
412
  ## Custom OKF Knowledge (Optional)
375
413
 
376
414
  Create `~/.pi/okf/` to add your custom knowledge that the runtime reads during context compilation:
@@ -547,6 +585,106 @@ echo "{coder-api-key}" > ~/.pi-harness-runtime/keys/coder-api-key.txt
547
585
  echo "{langsmith-key}" > ~/.pi-harness-runtime/keys/langsmith-api-key.txt
548
586
  ```
549
587
 
588
+ The startup summary scans `~/.pi-harness-runtime/keys/` and lists the missing
589
+ credentials of every feature that has a startup line (Telegram, Relay, LINE,
590
+ Jev, Qdrant, Honcho) together with the exact command that creates them — each
591
+ command line is prefixed with `Fix:`:
592
+
593
+ ```text
594
+ ├─ [WARN] Relay: two-way streaming off; no relay endpoint configured
595
+ │ Fix: echo "<TOKEN>" > ~/.pi-harness-runtime/keys/relay-auth-token.txt
596
+ │ Fix: echo "<SECRET>" > ~/.pi-harness-runtime/keys/telegram-webhook-secret.txt
597
+ │ Fix: echo "<WS_URL>" > ~/.pi-harness-runtime/keys/relay-ws-url.txt
598
+ │ Fix: echo "<WEBHOOK_URL>" > ~/.pi-harness-runtime/keys/telegram-webhook-url.txt
599
+ │ Then reload Pi.
600
+ ```
601
+
602
+ A credential counts as present when its key file exists and is **not** empty,
603
+ or when the environment variable it is read from is set (a credential the
604
+ extension reads from a file only — the Telegram bot token and chat id — is
605
+ not satisfied by an exported variable). A file that exists but is empty is
606
+ reported with the same command plus an `# the file exists but is empty - the
607
+ command replaces it` note (only the primary file carries that note — an
608
+ alternative file that does not exist yet is simply missing). A value the
609
+ reader would reject counts as
610
+ missing as well: a key file with five characters or less is ignored by the
611
+ skills loader, a Jev key with ten characters or less by the judge, and an
612
+ allowed-user list without a single usable id is not a user list. Such a file
613
+ is reported with an `# the file exists but the value is not accepted - the
614
+ command replaces it` note.
615
+
616
+ **Scope of the summary.** The audit covers the credentials of the features
617
+ that have a startup line — Telegram, Relay, LINE, Jev, Qdrant and Honcho.
618
+ The LINE channel secret (`line-channel-secret.txt`) is **not** part of it: it
619
+ is only needed on the machine that runs the webhook server and no startup
620
+ line owns it, so it is never reported as missing. Optional integrations
621
+ without a startup line (for example Paperclip) are not part of the summary
622
+ either; they write their own hint to the log file.
623
+
624
+ **Narrow terminals.** A fix command that is too long for the terminal is
625
+ split — the directory to create and the command itself — so that nothing
626
+ is cut off in the middle of a path. The split form creates the key
627
+ directory first (`mkdir -p`) and keeps the full path in the redirect, so it
628
+ works whether or not the directory exists and it does not change the working
629
+ directory of your shell. When even that does not fit, the redirect moves
630
+ onto a line of its own (with a backslash continuation, so the shell still
631
+ runs it as one command):
632
+
633
+ ```text
634
+ ├─ [WARN] Relay: two-way streaming off; no relay endpoint configured
635
+ │ Fix: mkdir -p ~/.pi-harness-runtime/keys
636
+ │ echo "<TOKEN>" > ~/.pi-harness-runtime/keys/relay-auth-token.txt
637
+ │ Then reload Pi.
638
+ ```
639
+
640
+ A command is never cut off: a broken path is worse than a long line.
641
+
642
+ **A file that is already there is never overwritten silently.** When the
643
+ summary shows a command for a file that exists, the command says that it
644
+ replaces the file. When the audit cannot tell whether the value in the file
645
+ is usable, the summary points at the file instead of offering an `echo`
646
+ that would replace a working secret with a placeholder.
647
+
648
+ The fix commands of each feature:
649
+
650
+ | Feature | Key files the fix commands create | Environment variable |
651
+ | --- | --- | --- |
652
+ | Telegram | `telegram-bot-token.txt`, `telegram-chat-id.txt`, `telegram-allowed-users.txt` | — (bot token and chat id: files only; the allowlist also accepts `TELEGRAM_ALLOWED_USERS`) |
653
+ | Relay | `relay-auth-token.txt` (or `telegram-webhook-secret.txt`), `relay-ws-url.txt` (or `telegram-webhook-url.txt`) | `RELAY_AUTH_TOKEN`, `RELAY_WS_URL` |
654
+ | LINE | `line-access-token.txt`, `line-user-id.txt` | — (files only) |
655
+ | Jev | `typesafe-api-key.txt` (or `openrouter-api-key.txt`, or the legacy `jev-api-key.txt`) | `TYPESAFE_API_KEY`, `OPENROUTER_API_KEY` |
656
+ | Qdrant | `qdrant-cluster-url.txt`, `qdrant-api-key.txt`, `openai-api-key.txt` | `QDRANT_CLUSTER_ENDPOINT`, `QDRANT_API_KEY`, `OPENAI_API_KEY` |
657
+ | Honcho | `honcho-api-key.txt` | — (file only) |
658
+
659
+ Only the missing part is listed: a relay that has a URL but no token shows
660
+ the token command alone. The Relay and the LINE line are optional features:
661
+ they only appear when the user is actually using them — a relay key file
662
+ (or the webhook url the relay url is derived from) exists, or the Telegram
663
+ channel works. A user who never touches them sees no warning on every
664
+ start. The LINE warning only appears once a
665
+ `line-access-token.txt` or a `line-user-id.txt` file exists: a user who never
666
+ touches LINE does not see a warning on every start. The LINE line only turns
667
+ green when the channel was really started in that run — after you create the
668
+ LINE key files, reload Pi once, otherwise the line says
669
+ `configured; reload Pi to enable the channel` (or
670
+ `configured; Telegram must be configured first` when the LINE channel cannot
671
+ start because Telegram is not configured yet).
672
+
673
+ The audit never prints a credential value — only the placeholder. Secrets
674
+ managed by [Infisical](#3-infisical-secrets-optional--centralized-key-management)
675
+ are not covered: the audit looks at the key files and the environment only.
676
+
677
+ **When the summary refreshes.** The Relay and LINE lines are re-checked when
678
+ a session starts, so they follow the key files immediately. The LINE
679
+ *channel* is only started once per load — after you create the LINE key
680
+ files, reload Pi once, otherwise the line says `configured; reload Pi to
681
+ enable the channel` (or `configured; Telegram must be configured first` when
682
+ a reload cannot help because Telegram is missing). The other lines
683
+ (Telegram, Jev, Qdrant, Honcho) describe the state at load time — the
684
+ features are initialised once per load, so a new key file needs a reload
685
+ before the line changes. That is why every fix command ends with
686
+ "Then reload Pi."
687
+
550
688
  ### 3. Infisical Secrets (Optional — Centralized Key Management)
551
689
 
552
690
  For centralized secret management via Infisical Cloud:
@@ -937,6 +1075,9 @@ Single server handles both Telegram and LINE webhooks on one domain.
937
1075
 
938
1076
  ### Setup
939
1077
 
1078
+ > For the two-way WebSocket stream (relay server + relay client) see
1079
+ > [Relay Setup](#relay-setup-two-way-telegram-stream).
1080
+
940
1081
  1. **Create Telegram Bot**
941
1082
  ```bash
942
1083
  # DM @BotFather → /newbot → get token
@@ -1002,6 +1143,15 @@ server {
1002
1143
  proxy_set_header Host $host;
1003
1144
  proxy_set_header X-Real-IP $remote_addr;
1004
1145
  }
1146
+
1147
+ # The relay WebSocket (two-way Telegram stream) - see "Relay Setup" below
1148
+ location /ws {
1149
+ proxy_pass http://127.0.0.1:8444/ws;
1150
+ proxy_http_version 1.1;
1151
+ proxy_set_header Upgrade $http_upgrade;
1152
+ proxy_set_header Connection "upgrade";
1153
+ proxy_set_header Host $host;
1154
+ }
1005
1155
  }
1006
1156
  ```
1007
1157
 
@@ -1026,6 +1176,98 @@ echo "123456789" > ~/.pi-harness-runtime/keys/telegram-chat-id.txt
1026
1176
 
1027
1177
  Unauthorized callback queries are rejected before processing.
1028
1178
 
1179
+ ## Relay Setup (Two-Way Telegram Stream)
1180
+
1181
+ The two-way Telegram stream has two halves:
1182
+
1183
+ - **Server** — `scripts/unified-webhook-server.ts` receives the Telegram webhook and
1184
+ broadcasts every callback to the connected WebSocket clients (relay on `WS_PORT`,
1185
+ default `8444`).
1186
+ - **Client** — `scripts/relay-client.ts` connects to that relay and forwards the
1187
+ callbacks into pi (job pipe, Telegram replies).
1188
+
1189
+ Both halves resolve the credential from the same key chain
1190
+ (`packages/relay/src/relay-endpoint.ts`), so — with `RELAY_AUTH_TOKEN` exported in
1191
+ both shells — the client and the server use the same secret. Only the client
1192
+ resolves the URL:
1193
+
1194
+ | Setting | Resolution order (first match wins) |
1195
+ | --- | --- |
1196
+ | WebSocket URL | `RELAY_WS_URL` env → `keys/relay-ws-url.txt` → derived from `keys/telegram-webhook-url.txt` (same host and port, path `/ws`, `https` → `wss`) |
1197
+ | Auth token | `RELAY_AUTH_TOKEN` env → `keys/relay-auth-token.txt` → `keys/telegram-webhook-secret.txt` |
1198
+
1199
+ ### 1. Create the key files
1200
+
1201
+ Replace the placeholders with your own values — never commit real ones.
1202
+
1203
+ ```bash
1204
+ mkdir -p ~/.pi-harness-runtime/keys
1205
+
1206
+ # Telegram bot token (from @BotFather)
1207
+ echo "YOUR_TELEGRAM_BOT_TOKEN" > ~/.pi-harness-runtime/keys/telegram-bot-token.txt
1208
+
1209
+ # Public HTTPS URL of your webhook (the reverse proxy in front of the relay)
1210
+ echo "https://webhook.your-domain.com/telegram" > ~/.pi-harness-runtime/keys/telegram-webhook-url.txt
1211
+
1212
+ # The secret the webhook expects in the x-telegram-bot-api-secret-token header
1213
+ echo "YOUR_TELEGRAM_WEBHOOK_SECRET" > ~/.pi-harness-runtime/keys/telegram-webhook-secret.txt
1214
+
1215
+ # Dedicated relay auth token (recommended - keeps it separate from the
1216
+ # Telegram webhook secret, so one leaked secret does not unlock both)
1217
+ echo "YOUR_RELAY_AUTH_TOKEN" > ~/.pi-harness-runtime/keys/relay-auth-token.txt
1218
+
1219
+ # Allowed Telegram user ids (comma-separated)
1220
+ echo "123456789,987654321" > ~/.pi-harness-runtime/keys/telegram-allowed-users.txt
1221
+
1222
+ # Optional: the relay WebSocket URL. Only needed when it cannot be derived
1223
+ # from the webhook URL (the relay runs on another host/port or a custom path).
1224
+ # It must be a plain ws:// or wss:// URL - no credentials, no query string.
1225
+ echo "wss://relay.your-domain.com:8444/ws" > ~/.pi-harness-runtime/keys/relay-ws-url.txt
1226
+ ```
1227
+
1228
+ ### 2. Or use environment variables
1229
+
1230
+ ```bash
1231
+ # The CLIENT reads RELAY_WS_URL; the SERVER only needs RELAY_AUTH_TOKEN.
1232
+ # Both processes resolve the environment at startup, so export the token in
1233
+ # BOTH shells (the server and the client) - otherwise they disagree.
1234
+ export RELAY_WS_URL="wss://webhook.your-domain.com/ws" # client only
1235
+ export RELAY_AUTH_TOKEN="YOUR_RELAY_AUTH_TOKEN" # server AND client
1236
+ ```
1237
+
1238
+ `RELAY_WS_URL` / `keys/relay-ws-url.txt` must be a plain `ws://` or `wss://` URL —
1239
+ a URL with credentials (`wss://user:pass@host/ws`) or a query string is skipped
1240
+ with a warning instead of being used.
1241
+
1242
+ ### 3. Expose the relay through the reverse proxy
1243
+
1244
+ The derived URL (`…/ws`) only works when the proxy maps `/ws` to the relay port.
1245
+ The `location /ws` block is already part of the NGINX `server` block shown in
1246
+ [NGINX Configuration](#nginx-configuration) — do **not** add it a second time
1247
+ (nginx rejects a duplicate location). If your NGINX config predates the relay,
1248
+ copy that block from the NGINX section into your `server` block exactly once.
1249
+
1250
+ When the webhook URL addresses the application directly (no proxy in front), the
1251
+ resolver *warns* about a derived loopback URL (it still returns it) — the relay
1252
+ listens on `WS_PORT` (default `8444`), not on the HTTP port. Set `RELAY_WS_URL`
1253
+ or `keys/relay-ws-url.txt` for that setup.
1254
+
1255
+ ### 4. Start both halves
1256
+
1257
+ ```bash
1258
+ # Server: HTTP webhook + WebSocket relay (WS_PORT, default 8444)
1259
+ bun run scripts/unified-webhook-server.ts
1260
+
1261
+ # Client: connects to the relay and forwards the callbacks into pi
1262
+ bun run scripts/relay-client.ts
1263
+ ```
1264
+
1265
+ Without a relay auth token the server does **not** start the WebSocket relay —
1266
+ callbacks are queued on disk instead.
1267
+
1268
+ > **Note:** the token value is never logged, only the name of the source it came
1269
+ > from (`env RELAY_AUTH_TOKEN`, `keys/relay-auth-token.txt`, …).
1270
+
1029
1271
  ## License
1030
1272
 
1031
1273
  MIT © 2026 MooCoding