pi-harness-runtime 1.1.389 → 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/README.md +242 -0
- package/harness/key-file-audit.ts +535 -0
- package/harness/startup-lines.ts +168 -0
- package/harness/startup-report.ts +277 -0
- package/index.ts +438 -73
- 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 +124 -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 +17 -0
- package/packages/notification/dist/notification-center.d.ts.map +1 -1
- package/packages/notification/dist/notification-center.js +23 -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 +148 -12
- package/packages/notification/src/base-adapter.ts +28 -0
- package/packages/notification/src/notification-center.ts +25 -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/scripts/typecheck-packages.mjs +42 -2
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
|
|
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
|