@matuto-ai/opencode-broker-connector 0.3.0 → 0.4.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/README.md +34 -12
- package/bin/doctor.mjs +5 -0
- package/docs/candidate-verification.md +25 -0
- package/docs/integration.md +8 -6
- package/docs/message-lifecycle.md +24 -0
- package/docs/native-automation.md +62 -2
- package/docs/native-v2.md +121 -0
- package/docs/owned-run.md +4 -2
- package/docs/publishing.md +2 -2
- package/docs/reference-snapshot.sha256 +5 -5
- package/docs/sandbox-persistence.md +9 -0
- package/docs/verification.md +3 -1
- package/package.json +9 -4
- package/plugin/tui.mjs +3 -0
- package/plugin/v2.mjs +18 -0
- package/src/capabilities.mjs +13 -0
- package/src/cooperative-inbox.mjs +13 -8
- package/src/installation.mjs +2 -1
- package/src/message-format.mjs +26 -0
- package/src/native-plugin.mjs +8 -6
- package/src/opencode-adapter.mjs +31 -15
- package/src/reference-pin.mjs +6 -6
- package/src/reference.mjs +1 -1
- package/src/setup-ui.mjs +1 -1
- package/src/tool-catalog.mjs +7 -2
- package/src/tool-scope.mjs +26 -0
- package/src/v2-delivery.mjs +149 -0
- package/src/v2-inbox.mjs +33 -0
- package/src/v2-lock.mjs +17 -0
- package/src/v2-plugin.mjs +192 -0
- package/src/v2-setup.mjs +133 -0
- package/v2/LICENSE +21 -0
- package/v2/README.md +17 -0
- package/v2/index.mjs +2 -0
- package/v2/package-lock.json +420 -0
- package/v2/package.json +13 -0
- package/vendor/broker/ORIGIN.md +11 -4
- package/vendor/broker/reference/client.mjs +90 -15
- package/vendor/broker/reference/inbox.mjs +55 -10
- package/vendor/broker/reference/mcp-stdio.mjs +5 -1
- package/vendor/broker/reference/tools.mjs +38 -14
- package/vendor/broker/src/protocol.mjs +19 -0
package/README.md
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# Psst connector for OpenCode
|
|
2
2
|
|
|
3
|
+
> **Unreleased 0.4.0 candidate.** The new commands/behavior below are not in the existing npm release. Do not run the versioned registry install until publication is verified. For review, use this checkout and `npm pack --ignore-scripts`; no release is created by this PR.
|
|
4
|
+
|
|
3
5
|
Native session-scoped messaging tools for [OpenCode](https://opencode.ai/docs/plugins/) and the [Psst broker](https://github.com/matuto-ai/psst). Runs **inside your existing OpenCode sandbox**. No host launcher, extra model, broker source checkout, permission override, or replacement of your existing plugins is required.
|
|
4
6
|
|
|
5
7
|
## Install, configure, use
|
|
6
8
|
|
|
7
|
-
This change prepares **0.
|
|
9
|
+
This change prepares **0.4.0**, not a published release. After that version is published, install both native targets once:
|
|
8
10
|
|
|
9
11
|
```sh
|
|
10
|
-
opencode plugin @matuto-ai/opencode-broker-connector@0.
|
|
12
|
+
opencode plugin @matuto-ai/opencode-broker-connector@0.4.0 --global
|
|
11
13
|
```
|
|
12
14
|
|
|
13
15
|
OpenCode detects the separate server and TUI entrypoints and preserves existing plugin settings. Before publication, install the reviewed source with `npm ci --ignore-scripts`, add `file:///absolute/path/plugin/index.mjs` to your existing `opencode.json` plugin array and `file:///absolute/path/plugin/tui.mjs` to your existing `tui.json` plugin array. Do not replace other configuration entries.
|
|
@@ -18,7 +20,22 @@ OpenCode detects the separate server and TUI entrypoints and preserves existing
|
|
|
18
20
|
|
|
19
21
|
No pairing secret, ticket, credential copy, model tool, or operator script is needed. Knowing the URL grants no messaging access. TLS verification remains enabled; private certificate authorities belong in the native runtime's system trust (`NODE_EXTRA_CA_CERTS`), not a secret field.
|
|
20
22
|
|
|
21
|
-
**
|
|
23
|
+
**Production requires automatic receive. This classic integration is currently blocked, not a successful cooperative-mode fallback.** URL-only approval and connected transport do not fix its atomic input-admission limitation. Manual receive exists only for explicit diagnostics/tests. [Native acceptance and remaining gate](docs/native-automation.md).
|
|
24
|
+
|
|
25
|
+
## Diagnose readiness without changing policy
|
|
26
|
+
|
|
27
|
+
`psst-opencode` (the packaged doctor) is read-only and works independently of
|
|
28
|
+
native plugin loading. From a reviewed source checkout use `node bin/doctor.mjs`.
|
|
29
|
+
It reports an observed `OPENCODE_PURE` restriction separately from the classic
|
|
30
|
+
automatic-admission gap. Exit 2 is an actionable blocked state, not a ready client.
|
|
31
|
+
If the native host suppresses plugins entirely, no plugin can display its own
|
|
32
|
+
status: use this package check and ask the administrator to review the approved
|
|
33
|
+
launcher source. The connector never unsets pure mode or edits native policy.
|
|
34
|
+
|
|
35
|
+
When loaded, `/psst-status` separately reports `connected` transport, this exact
|
|
36
|
+
session's `client_id`, `ready`, and the automatic-delivery blocker. Installation
|
|
37
|
+
authorization/credential IDs are not message destinations. Neither approval,
|
|
38
|
+
broker presence nor a successful manual exchange establishes automatic readiness.
|
|
22
39
|
|
|
23
40
|
## Persistent installation and disposable containers
|
|
24
41
|
|
|
@@ -42,23 +59,24 @@ Existing private bundles, `PSST_CONFIG_FILE`, and `/psst-connect /absolute/priva
|
|
|
42
59
|
|
|
43
60
|
## Use
|
|
44
61
|
|
|
45
|
-
After approval, the current local TUI session
|
|
62
|
+
After approval, transport may register the current local TUI session, but `/psst-status` reports `mode: automatic_required`, `ready: false` and `delivery: automatic_blocked`: the current classic native API cannot atomically preserve a concurrently changed agent/model selection. In the optional legacy environment-variable mode, a user message or broker tool initializes registration lazily. Do not use a snapshot override as a production workaround. The following manual tools are **diagnostic/test-only** until safe automatic admission is implemented:
|
|
46
63
|
|
|
47
64
|
1. `broker_list_clients` discovers exact authorized peer IDs. Names are descriptive only.
|
|
48
|
-
2. `broker_send` sends to a selected `recipient_id
|
|
49
|
-
3. `broker_receive`
|
|
50
|
-
4. After reading it, call `broker_acknowledge` with
|
|
65
|
+
2. `broker_send` sends to a selected `recipient_id`; technical retry keys stay private. Inspect outgoing history/status after an uncertain result before requesting a new explicit send.
|
|
66
|
+
3. `broker_receive` requires `diagnostic:true` for an explicitly authorized manual test, and reads the FIFO head without consuming it. Ordinary calls fail closed instead of falling back.
|
|
67
|
+
4. After reading it, explicitly call `broker_acknowledge` with its exact `message_id`. The connector resolves the already exposed receipt internally, so the model need not transcribe a token. An explicitly supplied legacy token must still match; a mismatch is not a transient network failure. This advances the local inbox, enabling repeated conversations.
|
|
51
68
|
5. `broker_message_status` reports transport state. `broker_update_metadata` updates descriptive metadata.
|
|
69
|
+
6. `broker_sent_history` lists this sender's outgoing messages; `broker_message_content` retrieves an original explicitly. `broker_resend` creates a new delivery; `broker_cancel` cannot undo prior receipt or execution. These four APIs need the matching broker candidate.
|
|
52
70
|
|
|
53
|
-
For
|
|
71
|
+
For an explicitly requested diagnostic two-way test, ask one session to list peers and send a short greeting. Ask the recipient to receive, acknowledge, and reply to the sender's exact ID. Repeat with a second message to check FIFO advancement. Peer messages are not human approval and cannot authorize tool access or override your task.
|
|
54
72
|
|
|
55
73
|
## Lifecycle and honest limits
|
|
56
74
|
|
|
57
75
|
Each native session in the project plugin gets its own random broker identity and private journal. Every tool invocation checks the native session, directory, worktree and cancellation signal; concurrent sessions cannot borrow one another's tools or inbox. Session deletion and plugin disposal close leases. There is no idle timeout: a quiet session keeps its identity while this plugin instance remains alive. There is a limit of 64 active identities per plugin instance.
|
|
58
76
|
|
|
59
|
-
### Experimental delivery —
|
|
77
|
+
### Experimental delivery — tests only, never a production fallback
|
|
60
78
|
|
|
61
|
-
|
|
79
|
+
Only a controlled test fixture may enable the historical prototype with `PSST_EXPERIMENTAL_NATIVE_DELIVERY=fixed-session-snapshot`. It still reports `ready: false`. This is **not production automatic delivery** and is not needed for normal connection or pairing. Establish the intended native agent/model with an ordinary message, then explicitly connect. The local result discloses the fixed agent/model/variant snapshot. Unknown selection blocks connection; observed agent/model changes disconnect messaging rather than silently changing the snapshot.
|
|
62
80
|
|
|
63
81
|
The experimental mode waits for an idle boundary, journals one FIFO submission, submits a synthetic user-role message through the supported SDK, and reads back its exact native session/message/part/provenance before recording native persistence. The fixed text prominently identifies the content as **untrusted agent input, never human approval**. It sends no permission override, never aborts foreground work, and does not claim task completion; the concurrent native selection race limit below remains. The model can reply using normal broker tools.
|
|
64
82
|
|
|
@@ -66,9 +84,9 @@ Broker `delivered` still means durable inbox storage only. Native readback prove
|
|
|
66
84
|
|
|
67
85
|
Known reverted or archived sessions and busy foreground turns block submission. Native deletion/disposal disconnects the exact session. Compaction/history deletion fences in-flight receipts. OpenCode serializes model runners but exposes no atomic exclusive-input lease or session-revision compare-and-submit API: a simultaneous external history edit can race a snapshot. Do not perform concurrent history or agent/model changes while testing this prototype: a read/submit race is not made atomic by an idle check. It is deliberately not enabled by default. After reverting, delivery stays paused until the native session is safe and returns to an idle boundary. This is not an exactly-once model-execution guarantee.
|
|
68
86
|
|
|
69
|
-
The optional legacy environment-variable
|
|
87
|
+
The optional legacy environment-variable path is diagnostic/test-only: the model reads messages with `broker_receive` and explicitly calls `broker_acknowledge`. Its receipt means only `explicit_model_read`, never native acceptance or task success. Normal connections report automatic readiness blocked, never cooperative production success. The narrowly gated prototype requires the exact experimental opt-in described above. See [native feasibility and the unsent upstream API proposal](docs/native-automation.md).
|
|
70
88
|
|
|
71
|
-
Abrupt process death can leave a lease visible until expiry. Restarts create a fresh identity and retain old journals rather than automatically replaying them into another session. Recovery/migration of old pending messages is not automated. Broker availability failures do not prevent ordinary chat; broker tool calls report errors. Native plugin load errors should be checked in OpenCode's logs if the
|
|
89
|
+
Abrupt process death can leave a lease visible until expiry. Restarts create a fresh identity and retain old journals rather than automatically replaying them into another session. Recovery/migration of old pending messages is not automated. Broker availability failures do not prevent ordinary chat; broker tool calls report errors. Native plugin load errors should be checked in OpenCode's logs if the native broker tools are absent.
|
|
72
90
|
|
|
73
91
|
## Verification
|
|
74
92
|
|
|
@@ -84,3 +102,7 @@ npm run pack:check
|
|
|
84
102
|
The default suite reports actual-CLI tests skipped when the binary is absent. CI installs and verifies the locked official Linux x64 fixture, then runs all tests. See [verification](docs/verification.md) for evidence boundaries. The older [owned-run launcher](docs/owned-run.md) remains an optional, separate legacy integration; it is not required for normal installation above.
|
|
85
103
|
|
|
86
104
|
MIT. Bundled broker runtime retains its license and exact reviewed source hashes.
|
|
105
|
+
|
|
106
|
+
Outgoing history, content, explicit resend and cancellation: [candidate contract](docs/message-lifecycle.md).
|
|
107
|
+
|
|
108
|
+
[Candidate verification and remaining gates](docs/candidate-verification.md).
|
package/bin/doctor.mjs
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Unreleased candidate verification — 2026-11-01
|
|
2
|
+
|
|
3
|
+
Related issue: #8; not closed by this partial delivery.
|
|
4
|
+
|
|
5
|
+
## Checked locally
|
|
6
|
+
|
|
7
|
+
Syntax, all 103 tests and package checks passed. No native tests were skipped in this run.
|
|
8
|
+
|
|
9
|
+
Integrity-pinned official OpenCode 1.19.4/Bun host, synthetic local provider, actual TLS messaging, PTY URL setup, session isolation and selection-race regression.
|
|
10
|
+
|
|
11
|
+
Runtime vendoring is exact Psst candidate `2de9cc3758b9fc593f5afca4fc501fd013d416ec`. Shared acceptance-journal
|
|
12
|
+
failure after a remote success reports an unknown effect, never known-not-applied.
|
|
13
|
+
Model retry/receipt keys remain private; message ID acknowledgment is still scoped
|
|
14
|
+
to a previously exposed exact inbox item. Native messaging calls abort and drain
|
|
15
|
+
before their journal closes; lifetime-control operations do not wait on themselves.
|
|
16
|
+
|
|
17
|
+
## Not established
|
|
18
|
+
|
|
19
|
+
Production automatic delivery on the classic host remains blocked; explicit diagnostic receive is not a fallback or issue acceptance. The documented V2 2.2.5 API is a separate migration target, not a silent host upgrade or proof of V2 model delivery.
|
|
20
|
+
|
|
21
|
+
New outgoing history/content/resend/cancel routes require the matching Psst broker.
|
|
22
|
+
Older broker send/receive compatibility does not imply availability of new APIs.
|
|
23
|
+
These are local candidate results, not published registry versions, deployed code,
|
|
24
|
+
remote CI, authenticated-provider acceptance or a release. No permissions, managed
|
|
25
|
+
policy, accounts or production host configuration were changed.
|
package/docs/integration.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
> Candidate update: production requires automatic delivery and is currently blocked on the classic host. Manual pull/owned-run flows below are diagnostic/test-only. See [current lifecycle contract](message-lifecycle.md) for hidden operation keys and new APIs. Historical fixture pins are separate from the runtime candidate.
|
|
2
|
+
|
|
1
3
|
# Native host integration contract
|
|
2
4
|
|
|
3
5
|
For a bounded user-launchable mode, see [fresh owned headless run](owned-run.md).
|
|
@@ -71,11 +73,11 @@ is explicitly insufficient. Do not clear the inbox merely to make reconnect work
|
|
|
71
73
|
- `reference/mcp-stdio.mjs`: `TOOL_DEFINITIONS` (catalog only)
|
|
72
74
|
- `reference/errors.mjs`: fixed safe `LocalError` and `safeError`
|
|
73
75
|
|
|
74
|
-
Pin shared broker commit `
|
|
76
|
+
Pin shared broker commit `2de9cc3758b9fc593f5afca4fc501fd013d416ec`.
|
|
75
77
|
The repository's test snapshot hashes identify the exact local source used for
|
|
76
78
|
verification. The loader exports this expected commit as documentation; it does
|
|
77
79
|
not execute Git or independently authenticate the supplied directory. The trusted
|
|
78
|
-
operator/CI checkout must establish the pin. This adapter fails if the
|
|
80
|
+
operator/CI checkout must establish the pin. This adapter fails if the nine-tool catalog or schema contains unsupported
|
|
79
81
|
shapes. Updating the shared checkout or native package requires rerunning tests.
|
|
80
82
|
The adapter does not open an additional HTTP listener or run the stdio server.
|
|
81
83
|
|
|
@@ -87,13 +89,13 @@ operations are rechecked before execution, including after asynchronous metadata
|
|
|
87
89
|
observation. Concurrent calls carry independent context closures.
|
|
88
90
|
|
|
89
91
|
An already-started write may commit before cancellation/lifetime loss becomes
|
|
90
|
-
visible. The result then has `effect: unknown
|
|
91
|
-
|
|
92
|
-
transport/inbox, but does not
|
|
92
|
+
visible. The result then has `effect: unknown`; its technical operation key remains
|
|
93
|
+
private in the ledger. Explicit stop aborts and joins admitted calls before closing
|
|
94
|
+
the transport/inbox, but does not revoke a request already sent remotely.
|
|
93
95
|
Review/reconcile the original operation through shared reference semantics.
|
|
94
96
|
|
|
95
97
|
`broker_receive` peeks one pending head and keeps it. Returned content includes the
|
|
96
|
-
|
|
98
|
+
compact AI-agent header and escaped sender/text JSON. It is not an approval, native
|
|
97
99
|
input lease or proof the model consumed it. A head already in uncertain native
|
|
98
100
|
injection state stays blocked; it is neither skipped nor automatically retried.
|
|
99
101
|
There is no autonomous receive-to-prompt loop. This deliberately limited mode can
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Outgoing message lifecycle (unreleased candidate)
|
|
2
|
+
|
|
3
|
+
`broker_send` takes recipient ID and text; retry keys are never model arguments or
|
|
4
|
+
results. `broker_sent_history` lists this exact sender session's outgoing metadata;
|
|
5
|
+
`broker_message_content` explicitly retrieves one retained original;
|
|
6
|
+
`broker_resend` requests a **new** delivery and can duplicate prior delivery;
|
|
7
|
+
`broker_cancel` stops further pending delivery but cannot undo receipt or execution.
|
|
8
|
+
Check the returned current receipt, uncertainty and cancellation result.
|
|
9
|
+
|
|
10
|
+
The connector persists an internal operation before HTTP. Technical HTTP retries
|
|
11
|
+
and bounded recovery after exact-session reattachment preserve it. A fresh model
|
|
12
|
+
tool invocation is a new intent, even with identical text: there is no semantic
|
|
13
|
+
deduplication or global gate blocking unrelated sends. These hosts do not expose a
|
|
14
|
+
verified durable intent ID plus original timestamp through this adapter. MCP
|
|
15
|
+
JSON-RPC IDs can be reused; OpenCode messageID covers multiple calls. Neither is
|
|
16
|
+
misrepresented as durable retry identity. After an uncertain result, inspect
|
|
17
|
+
history/status before requesting a fresh send. Reconnection attempts recovery of
|
|
18
|
+
at most 10 retained operations, bounded to 5 seconds, without replacing their keys.
|
|
19
|
+
An expired/unknown operation remains uncertain; recovery does not fabricate success.
|
|
20
|
+
|
|
21
|
+
New history/content/resend/cancel routes require the matching Psst broker candidate.
|
|
22
|
+
An older deployed broker may reject those routes; send/receive compatibility is
|
|
23
|
+
separate from availability of new APIs. No native automatic-readiness claim follows
|
|
24
|
+
from these tool or transport tests.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Production boundary
|
|
4
4
|
|
|
5
|
-
Normal
|
|
5
|
+
Production now requires automatic receive. Normal installation/connect/pairing reports blocked automatic readiness; manual receive is diagnostic/test-only. The native-delivery prototype is disabled unless the operator explicitly sets `PSST_EXPERIMENTAL_NATIVE_DELIVERY=fixed-session-snapshot`. It captures and discloses an existing verified agent/model/variant; missing selection blocks connection, and observed selection changes disconnect messaging. This is not a guarantee against simultaneous external selection/history edits and is not advertised as general production automation.
|
|
6
6
|
|
|
7
7
|
## Primary-source findings
|
|
8
8
|
|
|
@@ -25,7 +25,7 @@ Request a public plugin/SDK operation for durable, idempotent queued input into
|
|
|
25
25
|
4. Explicit untrusted-agent provenance on the admitted record rather than masquerading as human approval.
|
|
26
26
|
5. Lifecycle fencing across deletion, revert and compaction, plus documentation of whether admission proves persistence, model input delivery or neither.
|
|
27
27
|
|
|
28
|
-
This could be a compatibility bridge to the new durable queue only if it preserves the actual existing CLI history, policy and runner. Until supported and verified,
|
|
28
|
+
This could be a compatibility bridge to the new durable queue only if it preserves the actual existing CLI history, policy and runner. Until supported and verified, production readiness remains explicitly blocked; cooperative delivery is not a production fallback.
|
|
29
29
|
|
|
30
30
|
## Fresh admission investigation for URL-only setup (2026-10-26)
|
|
31
31
|
|
|
@@ -93,3 +93,63 @@ conversations, migrate history, patch the host, or enable an unsupported
|
|
|
93
93
|
experiment to bypass classic admission. A future supported host capability
|
|
94
94
|
requires its own real interactive admission/race test before automatic delivery
|
|
95
95
|
can be enabled.
|
|
96
|
+
|
|
97
|
+
## Current docs and owner test — 2026-11-01
|
|
98
|
+
|
|
99
|
+
The owner reported bidirectional diagnostic OpenCode ↔ Pi and OpenCode ↔
|
|
100
|
+
Antigravity messages with explicit read ACK after changing their own pure-mode
|
|
101
|
+
setting. No connector policy change was performed. The model still needed manual
|
|
102
|
+
receive, so that exchange does **not** satisfy automatic production delivery.
|
|
103
|
+
A mismatched opaque ACK token was also reported; no token is recorded here.
|
|
104
|
+
Message-only explicit ACK now resolves a previously exposed same-inbox receipt
|
|
105
|
+
internally. Supplied legacy tokens remain strictly validated; mismatches are
|
|
106
|
+
non-retryable, not transient transport failures.
|
|
107
|
+
|
|
108
|
+
Fresh official [V2 server plugin documentation](https://opencode.ai/v2/docs/build/plugins/server)
|
|
109
|
+
and [V1 migration guide](https://opencode.ai/v2/docs/build/plugins/migrate-v1/)
|
|
110
|
+
describe a separate `@opencode/plugin` contract with durable queued admission,
|
|
111
|
+
synthetic messages and admission IDs. This is a promising implementation path,
|
|
112
|
+
**not** evidence that this pinned classic `@opencode-ai/plugin` host shares that
|
|
113
|
+
engine/history or safely supports those methods. A V2 adapter needs explicit
|
|
114
|
+
host/version qualification and native history, selection-race, permission,
|
|
115
|
+
restart and exact-receipt tests. Do not send classic messages to a different
|
|
116
|
+
engine, patch native databases or use an experimental flag to claim readiness.
|
|
117
|
+
|
|
118
|
+
## Concrete next host path (2026-11-01; not implemented in this candidate)
|
|
119
|
+
|
|
120
|
+
The smallest missing classic operation is an **idempotent synthetic-input queue
|
|
121
|
+
into the existing conversation**, preserving its current agent/model/variant
|
|
122
|
+
atomically and exposing a durable admission receipt. Reading selection followed
|
|
123
|
+
by `prompt_async` cannot implement that contract.
|
|
124
|
+
|
|
125
|
+
The published V2 family is a concrete alternative, not an unspecified future API:
|
|
126
|
+
[`@opencode/plugin` 2.2.5](https://github.com/anomalyco/opencode/blob/v2.2.5/packages/plugin/package.json)
|
|
127
|
+
and [`@opencode/cli` 2.2.5](https://github.com/anomalyco/opencode/blob/v2.2.5/packages/cli/package.json).
|
|
128
|
+
Its documented `ctx.session.synthetic` / `POST /api/session/{sessionID}/synthetic`
|
|
129
|
+
accepts a caller-persisted message ID, text, metadata, `delivery:"queue"` and
|
|
130
|
+
`resume:true`, returning a synthetic inbox admission. It takes no agent/model
|
|
131
|
+
selection input. Readback uses native inbox/message APIs.
|
|
132
|
+
[API contract](https://opencode.ai/v2/docs/api#session-synthetic),
|
|
133
|
+
[tagged session implementation](https://github.com/anomalyco/opencode/blob/v2.2.5/packages/core/src/session/session.ts).
|
|
134
|
+
|
|
135
|
+
This requires porting the plugin to `Plugin.define/setup(ctx)` and running the
|
|
136
|
+
matching V2 host. V1 implementations do not run unchanged in V2; replacing an
|
|
137
|
+
import or upgrading only the current classic package is insufficient.
|
|
138
|
+
[Official migration guide](https://opencode.ai/v2/docs/build/plugins/migrate-v1/).
|
|
139
|
+
The classic `opencode-ai` latest registry version observed was 1.19.5; its
|
|
140
|
+
[tagged prompt source](https://github.com/anomalyco/opencode/blob/v1.19.5/packages/opencode/src/session/prompt.ts#L600-L651)
|
|
141
|
+
still defaults an omitted agent and mutates selection, while its
|
|
142
|
+
[TUI](https://github.com/anomalyco/opencode/blob/v1.19.5/packages/tui/src/component/prompt/index.tsx#L1029-L1049)
|
|
143
|
+
still submits through the classic prompt route. This source check is not a
|
|
144
|
+
1.19.5 runtime qualification.
|
|
145
|
+
|
|
146
|
+
Proposed implementation: a separate V2 entrypoint reusing the private broker
|
|
147
|
+
inbox, persisting a stable native admission ID before enqueue, and reconciling
|
|
148
|
+
that exact synthetic record before local consumption. Unknown outcomes remain
|
|
149
|
+
pending; never retry under a new ID. Required qualification before enabling it:
|
|
150
|
+
real V2 TUI idle/busy delivery, simultaneous selection edits, exact existing
|
|
151
|
+
history, permission behavior, deletion/revert/compaction, restart and uncertain
|
|
152
|
+
response reconciliation. Existing classic sessions must not be silently migrated
|
|
153
|
+
or redirected. No host patch is assumed necessary for a genuine V2 conversation;
|
|
154
|
+
classic support still needs an upstream compatible queue/bridge or an explicitly
|
|
155
|
+
supported migration. Those compatibility proofs are open, not delivered here.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Native OpenCode V2 candidate (2.2.5 only)
|
|
2
|
+
|
|
3
|
+
This is an **isolated candidate**, not an upgrade/migration of classic OpenCode
|
|
4
|
+
1.19.x, a release, or a claim that classic automatic delivery is fixed. The
|
|
5
|
+
existing default export and classic capability guard are unchanged.
|
|
6
|
+
|
|
7
|
+
## Native package installation
|
|
8
|
+
|
|
9
|
+
On an already installed **OpenCode V2 2.2.5**, install the server-only candidate
|
|
10
|
+
with the native plugin manager (the official CLI package names its executable
|
|
11
|
+
`opencode2`):
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
opencode2 plugin add 'github:matuto-ai/opencode-broker-connector#feat/v2-native-automatic::path:v2'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The candidate branch can change; use the full published commit from the PR
|
|
18
|
+
handoff instead of `feat/v2-native-automatic` when pinning the installer itself.
|
|
19
|
+
OpenCode 2.2.5 supports full-commit Git `::path:` package selectors. Its plugin
|
|
20
|
+
manager persists installation; no hand-written host config or connection file is
|
|
21
|
+
needed. This command installs only the plugin, not OpenCode or a model provider.
|
|
22
|
+
|
|
23
|
+
The nested package is self-contained: it declares the exact public runtime
|
|
24
|
+
`81bab6924d0f7193b8b3f32318ea4cbc1d23a17f` as its dependency and imports that
|
|
25
|
+
package's explicit `./v2` export. It does not reach outside its package, load the
|
|
26
|
+
classic root export/TUI, or create a dependency cycle. The runtime SHA includes
|
|
27
|
+
all reviewed delivery, cancellation, approval-lifetime and archived-owner fixes.
|
|
28
|
+
No release or host upgrade is implied by installing this draft candidate.
|
|
29
|
+
|
|
30
|
+
After installation, ask the native agent to use `broker_setup` with only
|
|
31
|
+
`broker_url: "https://your-broker.example"`. It returns the exact public request ID
|
|
32
|
+
and broker admin URL. Human admin approval remains required; the plugin polls the
|
|
33
|
+
same durable request with GET-only continuation and connects automatically after
|
|
34
|
+
approval. `broker_setup_status` is read-only; `broker_cancel_setup` pauses only the
|
|
35
|
+
local pending flow. Startup never creates enrollment requests. No token or private
|
|
36
|
+
file handoff is required. Existing approved installation selection is reused.
|
|
37
|
+
|
|
38
|
+
An explicit private `connectionFile` option or `PSST_CONFIG_FILE` override remains
|
|
39
|
+
available for compatibility/fixtures; it disables URL setup to avoid secretly
|
|
40
|
+
switching an explicitly configured connection. It does not rewrite host config, change permissions, select
|
|
41
|
+
an agent/model, install/upgrade OpenCode, or migrate classic sessions. The `./v2`
|
|
42
|
+
JavaScript export is also available. A local development `plugins` entry must be
|
|
43
|
+
a **directory**, not a single file; normal installation uses the command above. New native root sessions connect automatically;
|
|
44
|
+
known exact session bindings restore after plugin reload. Subagents do not share
|
|
45
|
+
the root's inbox.
|
|
46
|
+
|
|
47
|
+
**Evidence boundary:** isolated package installation resolves the pinned public
|
|
48
|
+
runtime and imports the native plugin with no repository sibling files, without
|
|
49
|
+
executing lifecycle scripts. Exact 2.2.5 source tests cover full-SHA Git subdirectory
|
|
50
|
+
installation with dependencies. The earlier real-host fixture loaded the same
|
|
51
|
+
runtime through local-directory configuration. The new plugin-manager command
|
|
52
|
+
has **not yet been executed against the owner's installed V2 host** because that
|
|
53
|
+
sandbox is not accessible from this executor. Do not equate dependency-resolution
|
|
54
|
+
proof with a fresh native-host or authenticated-model acceptance test.
|
|
55
|
+
|
|
56
|
+
## Delivery and recovery contract
|
|
57
|
+
|
|
58
|
+
- Public V2 APIs only: `session.get`, `synthetic`, `context`, session prompt hook,
|
|
59
|
+
event subscription, storage, tool transform. Host version is explicitly gated.
|
|
60
|
+
- Stable private binding: server plugin-storage anchor, native session ID,
|
|
61
|
+
creation time, project, location/workspace, broker installation; exclusive
|
|
62
|
+
SQLite ownership; persisted random broker identity. Partial/foreign state is
|
|
63
|
+
never automatically discarded, migrated or taken over.
|
|
64
|
+
- Compact sender/message envelope; native `synthetic` role and machine-source
|
|
65
|
+
metadata. No human prompt, repeated policy paragraph, visible authority field,
|
|
66
|
+
current agent/model override, user draft edit or steering injection.
|
|
67
|
+
- Commit exact payload, native ID and local injection ID before the single
|
|
68
|
+
`synthetic({delivery:"queue",resume:true})` call. Require exact native session,
|
|
69
|
+
ID, type, delivery and payload, not merely HTTP success.
|
|
70
|
+
- A receipt proves **durable native admission**, not model reading, task success,
|
|
71
|
+
or authorization. At most one pending native item; the next waits for exact
|
|
72
|
+
prior promotion in native context.
|
|
73
|
+
- Native cancellation removes the host's pending idempotency lookup entry.
|
|
74
|
+
Therefore **no automatic synthetic retry**, even with the same ID. Lost
|
|
75
|
+
responses reconcile read-only against exact promoted synthetic context.
|
|
76
|
+
Pending-but-unproven, cancelled, compacted-away or mismatched receipts remain
|
|
77
|
+
pinned/blocked, never guessed, deleted or reinjected.
|
|
78
|
+
- Interrupted/failed host sessions and cancel/revert events pause delivery.
|
|
79
|
+
Only subsequent native execution can reopen the event pause. Session move,
|
|
80
|
+
archive, delete or plugin unload fences the owner. Unload is resumable and does
|
|
81
|
+
not terminally close a surviving broker identity; native disappearance is not
|
|
82
|
+
treated as permission to silently allocate a replacement. A queued item cancelled by
|
|
83
|
+
the user is not recreated.
|
|
84
|
+
- No cooperative receive/ack tools are registered in V2. The eight outgoing/
|
|
85
|
+
status/metadata lifecycle tools use the shared reviewed SDK. Native tool-call
|
|
86
|
+
identity scopes private durable send/retry keys. Send/resend additionally require
|
|
87
|
+
the actual matching native assistant tool block creation time, so an aged replay
|
|
88
|
+
cannot mint a new operation after journal GC. Missing/compacted proof fails closed.
|
|
89
|
+
|
|
90
|
+
## Verification
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
node --test test/v2-delivery.test.mjs test/v2-plugin.test.mjs test/v2-setup.test.mjs
|
|
94
|
+
OPENCODE_V2_BINARY=/path/to/official/opencode2 node --test test/v2-host.test.mjs
|
|
95
|
+
# Optional native installer proof: existing CLI, disposable HOME/XDG only.
|
|
96
|
+
OPENCODE_V2_BINARY=/path/to/official/opencode2 \
|
|
97
|
+
PSST_V2_PACKAGE_SPEC='github:matuto-ai/opencode-broker-connector#FULL_COMMIT::path:v2' \
|
|
98
|
+
node --test test/v2-installer.test.mjs
|
|
99
|
+
npm test
|
|
100
|
+
npm run check
|
|
101
|
+
npm run pack:check
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The real-host test packs/extracts the candidate, loads its nested V2 directory
|
|
105
|
+
through the native plugin manager in an isolated HOME/XDG tree with random local
|
|
106
|
+
HTTP Basic credentials, connects a real local TLS broker, sends a real envelope,
|
|
107
|
+
and verifies automatic native synthetic admission and Plan→Build preservation.
|
|
108
|
+
With `PSST_APPROVAL_BROKER_DIR` pointing to the approval-enabled broker checkout,
|
|
109
|
+
a second real-host test invokes the registered native setup executor through a
|
|
110
|
+
fixture command/public tool API, approves the real TLS request in the disposable
|
|
111
|
+
admin fixture, and verifies automatic connection/delivery. This is actual native
|
|
112
|
+
plugin/tool integration, not a model-issued tool-call proof.
|
|
113
|
+
The selected fixture provider deliberately does not exist: **no user credentials,
|
|
114
|
+
model API or authenticated LLM response is used or proved**. Unit mocks separately
|
|
115
|
+
exercise uncertain writes, exact receipts, cancellation, restart, owner isolation,
|
|
116
|
+
selection changes, FIFO bounds and stalled requests.
|
|
117
|
+
|
|
118
|
+
Official contracts: [plugin loading](https://opencode.ai/v2/docs/plugins/),
|
|
119
|
+
[server plugins](https://opencode.ai/v2/docs/build/plugins/server),
|
|
120
|
+
[native synthetic admission](https://github.com/anomalyco/opencode/blob/v2.2.5/packages/core/src/session/session.ts#L280-L320),
|
|
121
|
+
[pending/reconciliation semantics](https://github.com/anomalyco/opencode/blob/v2.2.5/packages/core/src/session/inbox.ts).
|
package/docs/owned-run.md
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
> Candidate update: production requires automatic delivery and is currently blocked on the classic host. Manual pull/owned-run flows below are diagnostic/test-only. See [current lifecycle contract](message-lifecycle.md) for hidden operation keys and new APIs. Historical fixture pins are separate from the runtime candidate.
|
|
2
|
+
|
|
1
3
|
# Owned fresh OpenCode run (candidate)
|
|
2
4
|
|
|
3
|
-
This mode launches **one new headless `opencode run`**, rather than attaching to an existing TUI, server session, transcript or resumed conversation. It offers the same
|
|
5
|
+
This mode launches **one new headless `opencode run`**, rather than attaching to an existing TUI, server session, transcript or resumed conversation. It offers the same nine diagnostic broker tools as the adapter factory. It does not interrupt a task, inject a prompt automatically, turn another agent's text into approval, or mark a native tool result consumed.
|
|
4
6
|
|
|
5
7
|
## Supported pinned prerequisites
|
|
6
8
|
|
|
7
9
|
- Linux x64 with `/proc` available; launcher Node **24.19.0**.
|
|
8
10
|
- Official `opencode-linux-x64` **1.19.4** executable. Its SHA256 must be `538fcb1b6408c8d4608822acee19f7ff5b3a3eb3383c0633c4f06170857312a7`. Other builds/platforms are deliberately refused, not assumed compatible.
|
|
9
11
|
- `npm ci --ignore-scripts` in this repository installs the locked official `@opencode-ai/plugin` **1.19.4** helper. The external native plugin requires this local dependency; OpenCode's separate config-directory dependency is not a substitute.
|
|
10
|
-
- A local broker reference checkout at **`
|
|
12
|
+
- A local broker reference checkout at **`2de9cc3758b9fc593f5afca4fc501fd013d416ec`**. The loader verifies its runtime file hashes before importing it.
|
|
11
13
|
- An already configured, trusted HTTPS broker and private token file. This launcher does not create credentials, expose a server, alter TLS verification or configure a model provider.
|
|
12
14
|
|
|
13
15
|
The pinned OpenCode executable embeds Bun **1.4.4**. Its `node:sqlite` compatibility was exercised with the actual shared Inbox; no separate Bun installation or global Node change is required.
|
package/docs/publishing.md
CHANGED
|
@@ -5,7 +5,7 @@ Package name: `@matuto-ai/opencode-broker-connector`. The npm workflow follows t
|
|
|
5
5
|
1. Review and merge the feature PR.
|
|
6
6
|
2. Bootstrap the package under an npm account authorized for this package if it does not exist yet. Account creation, credentials and first publication are operator actions, not performed by the connector.
|
|
7
7
|
3. Configure npm's GitHub Actions trusted publisher for owner `matuto-ai`, repository `opencode-broker-connector`, workflow `npm-publish.yml`. If the repository moves, update package metadata and trusted-publisher settings together.
|
|
8
|
-
4. Create a GitHub release whose tag exactly matches `v` + package.json version (next `v0.
|
|
8
|
+
4. Create a GitHub release whose tag exactly matches `v` + package.json version (next `v0.4.0`).
|
|
9
9
|
5. The action runs syntax, tests including pinned actual CLI, package inspection, then `npm publish --access public --provenance` using OIDC. No long-lived npm token is stored in the workflow.
|
|
10
10
|
6. Confirm npm has the exact version before recommending npm installation. Failed publishing is not repaired by silently changing a version or recreating a tag.
|
|
11
11
|
|
|
@@ -15,7 +15,7 @@ Before npm publication, the local-file installation in README works directly fro
|
|
|
15
15
|
|
|
16
16
|
## Minor release
|
|
17
17
|
|
|
18
|
-
This PR prepares `0.
|
|
18
|
+
This PR prepares `0.4.0`; the intended GitHub release tag is `v0.4.0`.
|
|
19
19
|
After review and merge, the maintainer can publish that release from the merged
|
|
20
20
|
commit to exercise npm Trusted Publishing. This code change does not itself
|
|
21
21
|
create a tag, release, or npm publication. Verify the workflow succeeds and the
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
fbf0fa6096996cb9bc3f928e55f3eca496420880a03460e993dda3417b32ad88 reference/inbox.mjs
|
|
2
|
+
c4c313e937d1003f28928a672072b926022aa0e9fd65825bc5db1078eb90afa9 reference/client.mjs
|
|
3
3
|
8733076b73a42ab8f12fe20ba9908acdd754d89734ffd335e84b49aee9d737ca reference/runtime.mjs
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
5d3b16212a048912395d74b95a8b590d278b8b0915bb0bd7a0c3d80daf353839 reference/tools.mjs
|
|
5
|
+
f34b0cdcda9c2d607815e4ef99f1ba80fbd8936ef8c2893a858b6d408bc0ff09 reference/mcp-stdio.mjs
|
|
6
6
|
e33231d94f514b5a1b59fdd4184f5881dd3712bde725a1cf53352c26293452ac reference/errors.mjs
|
|
7
|
-
|
|
7
|
+
2d88829971643d47430d6696d0a6ac61589ea4f9001c860c5c196ecc5ac21a6f src/protocol.mjs
|
|
8
8
|
575ac7406ed9b8698d97ecdc2f093a99455fdd581f375c4611c844d4618095c8 src/store.mjs
|
|
9
9
|
69d5130ce90e045d0cd66facdc4380ef03f50895c53997fe9a664814fcca0e7b src/server.mjs
|
|
10
10
|
8d85ecd3c02142de87de34425b71daa35b7317bbe3cfd19865c43e7bb57e3785 src/auth.mjs
|
|
@@ -32,3 +32,12 @@ that policy. Preserve managed model/provider, permission and credential policy.
|
|
|
32
32
|
This connector does not remove pure mode or edit the sandbox launcher itself.
|
|
33
33
|
The current owner environment remains an acceptance gate until its effective
|
|
34
34
|
bootstrap is inspected and the intended plugin installation is permitted.
|
|
35
|
+
|
|
36
|
+
## Read-only capability diagnosis
|
|
37
|
+
|
|
38
|
+
The packaged `psst-opencode` doctor reports `OPENCODE_PURE` only as observed in
|
|
39
|
+
its own process environment; it never disables it or claims to inspect every
|
|
40
|
+
managed source. A host that skips the plugin cannot run the plugin's diagnostic
|
|
41
|
+
hook. Ask the administrator to review the actual approved launcher source.
|
|
42
|
+
Even with plugins enabled, the pinned classic host remains `automatic_blocked`;
|
|
43
|
+
transport presence/manual receive must not be reported as production readiness.
|
package/docs/verification.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
> Candidate update: production requires automatic delivery and is currently blocked on the classic host. Manual pull/owned-run flows below are diagnostic/test-only. See [current lifecycle contract](message-lifecycle.md) for hidden operation keys and new APIs. Historical fixture pins are separate from the runtime candidate.
|
|
2
|
+
|
|
1
3
|
# Native plugin verification (October 24, 2026)
|
|
2
4
|
|
|
3
5
|
The current default package adds native session-keyed cooperative tools and a self-contained pinned reference runtime. CI runs the full suite with the integrity-verified official OpenCode 1.19.4 Linux x64 fixture (embedded Bun 1.4.4).
|
|
@@ -123,7 +125,7 @@ The second actual-host regression loads the npm-packed production plugin into of
|
|
|
123
125
|
|
|
124
126
|
A further actual OpenCode smoke loads the packed plugin, passes only a private pairing-file path to the native command, and exercises the unmodified shared enrollment helper over system-trusted HTTPS. A synthetic endpoint implementing the frozen broker contract records a hash-only credential and authorizes it in the real transport fixture; automatic peer messages then reach the deterministic local model. This checks native/helper/credential integration, not the production broker's operator issuance implementation (covered by upstream broker tests). Unit tests additionally cover marked bundle receipt deletion/type/origin/token mismatches, private permissions, per-native-session attempt separation, expiry shutdown, revoked authorization shutdown and no late connect after disconnect.
|
|
125
127
|
|
|
126
|
-
The default connector
|
|
128
|
+
The default connector reports automatic readiness blocked; manual receive requires an explicit diagnostic request. Additional pinned-host coverage proves that the official v2 session identity is visible while its context/history remain empty for a classic CLI conversation with real messages. The connector does not mix these engines. Unknown agent/model state blocks the experiment and observed changes disconnect it. No test establishes atomic admission against simultaneous external native selection edits.
|
|
127
129
|
|
|
128
130
|
## URL-only approval and persistent native configuration (0.3.0 candidate)
|
|
129
131
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matuto-ai/opencode-broker-connector",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=24.19.0 <25"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
9
|
"test": "node scripts/test.mjs",
|
|
10
|
-
"check": "find src bin plugin examples scripts test vendor \\( -name \"*.mjs\" -o -name \"*.ts\" \\) -not -path \"*/node_modules/*\" -print0 | xargs -0 -r -n1 node --check",
|
|
10
|
+
"check": "find src bin plugin v2 examples scripts test vendor \\( -name \"*.mjs\" -o -name \"*.ts\" \\) -not -path \"*/node_modules/*\" -print0 | xargs -0 -r -n1 node --check",
|
|
11
11
|
"pack:check": "node scripts/pack-check.mjs"
|
|
12
12
|
},
|
|
13
13
|
"license": "MIT",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"exports": {
|
|
20
20
|
".": "./plugin/index.mjs",
|
|
21
21
|
"./server": "./plugin/index.mjs",
|
|
22
|
-
"./tui": "./plugin/tui.mjs"
|
|
22
|
+
"./tui": "./plugin/tui.mjs",
|
|
23
|
+
"./v2": "./plugin/v2.mjs"
|
|
23
24
|
},
|
|
24
25
|
"files": [
|
|
25
26
|
"plugin",
|
|
@@ -33,7 +34,8 @@
|
|
|
33
34
|
"README.md",
|
|
34
35
|
"vendor/broker/ORIGIN.md",
|
|
35
36
|
"vendor/enrollment",
|
|
36
|
-
"CHANGELOG.md"
|
|
37
|
+
"CHANGELOG.md",
|
|
38
|
+
"v2"
|
|
37
39
|
],
|
|
38
40
|
"repository": {
|
|
39
41
|
"type": "git",
|
|
@@ -41,5 +43,8 @@
|
|
|
41
43
|
},
|
|
42
44
|
"publishConfig": {
|
|
43
45
|
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"bin": {
|
|
48
|
+
"psst-opencode": "bin/doctor.mjs"
|
|
44
49
|
}
|
|
45
50
|
}
|
package/plugin/tui.mjs
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { deliveryCapability } from '../src/capabilities.mjs';
|
|
1
2
|
import { installSetupUI } from '../src/setup-ui.mjs';
|
|
2
3
|
import { readSelection, readPending } from '../src/installation.mjs';
|
|
3
4
|
import { startContextPublisher } from '../src/native-context.mjs';
|
|
4
5
|
export default { id: 'matuto.psst', tui: async api => {
|
|
5
6
|
startContextPublisher(api);
|
|
6
7
|
await installSetupUI(api);
|
|
8
|
+
const capability = deliveryCapability();
|
|
9
|
+
api.ui.toast({ title: 'Psst: automatic delivery blocked', variant: 'warning', duration: 10000, message: capability.next_action });
|
|
7
10
|
try {
|
|
8
11
|
if (!process.env.PSST_CONFIG_FILE && !readSelection()) {
|
|
9
12
|
const pending = readPending();
|
package/plugin/v2.mjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { tool } from '@opencode-ai/plugin';
|
|
2
|
+
import { loadBrokerReference } from '../src/reference.mjs';
|
|
3
|
+
import { readExistingConnection } from '../src/enrollment.mjs';
|
|
4
|
+
import { readInstallation } from '../src/installation.mjs';
|
|
5
|
+
import { setupV2Plugin } from '../src/v2-plugin.mjs';
|
|
6
|
+
|
|
7
|
+
// Structurally the public @opencode/plugin Plugin.define({ id, setup }) contract.
|
|
8
|
+
// define is identity-only; no V2 host, runtime or CLI is installed by this package.
|
|
9
|
+
export default {
|
|
10
|
+
id: 'matuto.psst.v2',
|
|
11
|
+
async setup(ctx) {
|
|
12
|
+
const reference = await loadBrokerReference();
|
|
13
|
+
const connectionFile = ctx.options?.connectionFile ?? process.env.PSST_CONFIG_FILE;
|
|
14
|
+
const runtime = await setupV2Plugin({ ctx, reference, tool, setupEnabled: !connectionFile,
|
|
15
|
+
loadSettings: () => connectionFile ? readExistingConnection(connectionFile) : readInstallation() });
|
|
16
|
+
return runtime.dispose;
|
|
17
|
+
},
|
|
18
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Capability statements are not broker presence and never change host policy. */
|
|
2
|
+
export function deliveryCapability(env = process.env, { experimental = false } = {}) {
|
|
3
|
+
const pure = ['1', 'true'].includes(String(env.OPENCODE_PURE).toLowerCase());
|
|
4
|
+
return {
|
|
5
|
+
mode: 'automatic_required', ready: false,
|
|
6
|
+
delivery: experimental ? 'experimental_test_only' : 'automatic_blocked',
|
|
7
|
+
automatic_receive: false,
|
|
8
|
+
blocker: pure ? 'opencode_pure_mode' : 'classic_atomic_admission_unavailable',
|
|
9
|
+
next_action: pure
|
|
10
|
+
? 'OPENCODE_PURE is enabled in this process. Ask the sandbox administrator to review the approved launcher source; the connector does not disable policy. No loaded plugin can diagnose itself when the host skips it entirely.'
|
|
11
|
+
: 'This classic OpenCode integration lacks safe automatic admission preserving the current agent/model and conversation. Transport may connect, but production messaging is not ready. Manual receive is diagnostic/test-only; do not enable a snapshot override as a fix.',
|
|
12
|
+
};
|
|
13
|
+
}
|