@tangle-network/agent-provider-cli-bridge 0.9.4 → 0.9.5
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 +23 -2
- package/dist/index.js +1 -0
- package/dist/retained-environment.d.ts +8 -1
- package/dist/retained-environment.js +16 -9
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -47,6 +47,25 @@ The provider rejects any coordinate or digest mismatch instead of attaching to a
|
|
|
47
47
|
If the caller crashes before saving `controlRef`, call `provider.lookupRun()` with the planned run coordinates.
|
|
48
48
|
The lookup returns the server-issued digest only when all five planned coordinates match the retained run.
|
|
49
49
|
|
|
50
|
+
## Which call adds a turn
|
|
51
|
+
|
|
52
|
+
Continuation has two tiers, and the tier depends on whether the environment object came from `create()` or from `get()`.
|
|
53
|
+
|
|
54
|
+
In the process that created the environment, `environment.dispatch()`, `environment.stream()`, and `session.prompt()` all add a turn.
|
|
55
|
+
Passing the same `sessionId` continues the same CLI conversation.
|
|
56
|
+
|
|
57
|
+
After `provider.get(environmentId)` reconstructs the environment, only `session.continueNative(request, { turn })` can add a turn.
|
|
58
|
+
It requires the `nativeContinuation` capability, which the provider publishes only for the Pi harness today, and only when the running Bridge proves the same contract.
|
|
59
|
+
The reconstructed environment deliberately refuses every other way to start work: `environment.stream()` and `environment.dispatch()` throw "a reconstructed cli-bridge environment can only control an existing run", and `session.prompt()` throws "a reconstructed cli-bridge session cannot start another turn".
|
|
60
|
+
A reconstructed environment for any other harness therefore controls its existing runs (status, cursor replay, result, cancellation, and interaction responses) but adds no turn.
|
|
61
|
+
Restart-safe continuation for those harnesses needs native sessions in the Bridge server itself, which the Bridge does not have yet; it is tracked in the `drewstone/cli-bridge` repository and cannot be reached from this adapter.
|
|
62
|
+
|
|
63
|
+
The capability document keeps `sessions.continue: true` on a reconstructed environment because the Agent Interface couples that flag to `retainedControl`: a document that reports `sessions.continue: false` while keeping retained run control fails `AgentEnvironmentCapabilitiesSchema` with "retained control requires exact run, result, event, cancellation, replay, detach, turn, and session identity together".
|
|
64
|
+
`nativeContinuation` is the flag that states whether a reconstructed environment can add a turn: present means `continueNative` works, absent means no call on that environment starts one.
|
|
65
|
+
|
|
66
|
+
A runtime caller continues a retained run with `RetainedRunHandle.continueNative`, not with `startRetainedRunInEnvironment`.
|
|
67
|
+
`startRetainedRunInEnvironment` requires `provider.list` for its ownership proof, and this provider exposes no `list`; it then calls `environment.dispatch()`, which a reconstructed environment refuses.
|
|
68
|
+
|
|
50
69
|
The bridge model is selected from run data in this order: the turn, the provider default, or the profile's `harness` plus `model.default`.
|
|
51
70
|
Execution fails before network use when none is present.
|
|
52
71
|
|
|
@@ -59,7 +78,7 @@ Retained native sessions currently require `kind: 'host'`.
|
|
|
59
78
|
The provider rejects a sandbox default before it creates the retained session; use one-shot execution for `kind: 'sandbox'`.
|
|
60
79
|
The Bridge currently refuses `netJail` with `kind: 'sandbox'`; use the sandbox's own egress policy.
|
|
61
80
|
|
|
62
|
-
Passing the same `sessionId` on later turns continues the same CLI conversation.
|
|
81
|
+
Passing the same `sessionId` on later turns continues the same CLI conversation while the creating process still holds the environment.
|
|
63
82
|
`executionId` gives a turn stable bridge identity, and `lastEventId` reattaches after a reader failure.
|
|
64
83
|
`dispatch()` starts a bridge-owned durable run and returns after detaching its HTTP reader.
|
|
65
84
|
The returned `AgentSession` exposes status, cursor-based event replay, the terminal result, continuation, and cancellation.
|
|
@@ -79,7 +98,7 @@ Replay and result reads fail loudly after cli-bridge's configured replay retenti
|
|
|
79
98
|
Stopping a `session.events()` reader detaches only that replay observer.
|
|
80
99
|
Stopping a direct `environment.stream()` reader or destroying the environment cancels its active bridge runs and waits for terminal confirmation.
|
|
81
100
|
|
|
82
|
-
Pi retained sessions also expose typed permission interactions.
|
|
101
|
+
Pi retained sessions also expose typed permission interactions and native continuation.
|
|
83
102
|
The provider stores the selected harness, exact model route, and canonical create digest inside its opaque environment identifier.
|
|
84
103
|
This identifier lets `provider.get()` reconstruct profile-selected routes after process death without a cache or repeated configuration.
|
|
85
104
|
The create digest prevents an altered profile or workspace from reusing the previous retained identity.
|
|
@@ -96,6 +115,8 @@ The environment and session then expose `respondToInteraction()` for exact respo
|
|
|
96
115
|
Each command carries its run, session, execution, request digest, and stable operation identifier.
|
|
97
116
|
Native turns require caller-stable `turnId` and `executionId` values so an ambiguous admission cannot create another run.
|
|
98
117
|
The bridge records repeated operations and rejects a different answer for an existing operation.
|
|
118
|
+
Repeating one operation identifier returns its stored acknowledgement; a new operation identifier for an interaction that is already resolved returns `already_resolved_same` when the answer matches and `already_resolved_different` when it does not, and answering an interaction that a run cancellation closed returns `cancelled`.
|
|
119
|
+
The `expired` acknowledgement stays in the contract, but the Bridge never emits it, so only the unit contradiction table covers it.
|
|
99
120
|
The provider reports an unconfirmed network result as retryable and never reports it as accepted.
|
|
100
121
|
Native replay reads `/v1/runs/:runId/events` and validates each canonical envelope through Agent Interface before exposing it.
|
|
101
122
|
When a turn supplies `interactions`, the provider carries its exact map, including an explicit `{}`; an omitted map remains omitted.
|
package/dist/index.js
CHANGED
|
@@ -76,6 +76,7 @@ export function createCliBridgeProvider(options) {
|
|
|
76
76
|
environmentId,
|
|
77
77
|
allowDispatch: true,
|
|
78
78
|
cancelRunsOnDestroy: true,
|
|
79
|
+
creation: "created",
|
|
79
80
|
capabilities: await resolveCapabilities(selectedBackend, model, true, selectedBackend === "pi" ||
|
|
80
81
|
(model !== undefined && remotelyVerifiedRoutes.has(model))),
|
|
81
82
|
selectedBackend,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentEnvironment, AgentEnvironmentCapabilities, CreateAgentEnvironmentInput } from "@tangle-network/agent-interface/environment-provider";
|
|
1
|
+
import type { AgentEnvironment, AgentEnvironmentCapabilities, AgentEnvironmentCreation, CreateAgentEnvironmentInput } from "@tangle-network/agent-interface/environment-provider";
|
|
2
2
|
import type { CliBridgeProviderOptions } from "./provider-options.js";
|
|
3
3
|
export interface CreateCliBridgeEnvironmentArgs {
|
|
4
4
|
readonly options: CliBridgeProviderOptions;
|
|
@@ -7,6 +7,13 @@ export interface CreateCliBridgeEnvironmentArgs {
|
|
|
7
7
|
readonly environmentId: string;
|
|
8
8
|
readonly allowDispatch: boolean;
|
|
9
9
|
readonly cancelRunsOnDestroy: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* The verdict of the create call that builds this environment. The create
|
|
12
|
+
* path states `created` because it provisions the handle that tracks every
|
|
13
|
+
* run it starts; the in-process idempotency helper supplies `replayed`; a
|
|
14
|
+
* reconstruction through `get()` states nothing.
|
|
15
|
+
*/
|
|
16
|
+
readonly creation?: AgentEnvironmentCreation;
|
|
10
17
|
/**
|
|
11
18
|
* The document this provider publishes. The environment offers an optional
|
|
12
19
|
* operation only where the document claims it, so a caller never selects an
|
|
@@ -5,6 +5,18 @@ import { cliBridgeInteractionResponder } from "./interaction-response.js";
|
|
|
5
5
|
import { assertCliBridgeRequestedInteractions, assertCliBridgeTurnModel, continueCliBridgeNative, readCliBridgeNativeContextBoundary, supportsCliBridgeNativeContinuation, supportsCliBridgeNativeInteractions, } from "./retained-native.js";
|
|
6
6
|
import { assertRunMatchesControlRef, exactControlRefForSession, prepareCliBridgeRun, runFromControlRef, } from "./retained-run-state.js";
|
|
7
7
|
import { createCliBridgeTransport } from "./transport.js";
|
|
8
|
+
/**
|
|
9
|
+
* One refusal for every call that would add a turn to a reconstructed
|
|
10
|
+
* environment. `provider.get()` rebuilds control of existing runs from the
|
|
11
|
+
* opaque environment id alone, so it holds no create request that a new native
|
|
12
|
+
* session could reuse. Only `session.continueNative` advances a retained run
|
|
13
|
+
* after reconstruction, and only where the Bridge proves `nativeContinuation`.
|
|
14
|
+
*/
|
|
15
|
+
function assertCliBridgeTurnAllowed(allowed, surface) {
|
|
16
|
+
if (allowed)
|
|
17
|
+
return;
|
|
18
|
+
throw new Error(`a reconstructed cli-bridge environment cannot start a turn through ${surface}; use session.continueNative, which requires the nativeContinuation capability`);
|
|
19
|
+
}
|
|
8
20
|
export function createCliBridgeEnvironment(args) {
|
|
9
21
|
const { options, providerName, environmentInput, environmentId } = args;
|
|
10
22
|
const transport = createCliBridgeTransport(options);
|
|
@@ -27,9 +39,7 @@ export function createCliBridgeEnvironment(args) {
|
|
|
27
39
|
const stream = async function* (turn) {
|
|
28
40
|
if (destroyed)
|
|
29
41
|
throw new Error("cli-bridge environment is destroyed");
|
|
30
|
-
|
|
31
|
-
throw new Error("a reconstructed cli-bridge environment can only control an existing run");
|
|
32
|
-
}
|
|
42
|
+
assertCliBridgeTurnAllowed(args.allowDispatch, "environment.stream()");
|
|
33
43
|
if (args.selectedModel !== undefined &&
|
|
34
44
|
args.capabilities.retainedControl !== undefined) {
|
|
35
45
|
assertCliBridgeTurnModel(options, environmentInput, turn, args.selectedModel);
|
|
@@ -48,6 +58,7 @@ export function createCliBridgeEnvironment(args) {
|
|
|
48
58
|
return {
|
|
49
59
|
id: environmentId,
|
|
50
60
|
provider: providerName,
|
|
61
|
+
...(args.creation === undefined ? {} : { creation: args.creation }),
|
|
51
62
|
capabilities: args.capabilities,
|
|
52
63
|
...(environmentInput.name ? { name: environmentInput.name } : {}),
|
|
53
64
|
status: async (statusOptions) => {
|
|
@@ -58,9 +69,7 @@ export function createCliBridgeEnvironment(args) {
|
|
|
58
69
|
async dispatch(turn) {
|
|
59
70
|
if (destroyed)
|
|
60
71
|
throw new Error("cli-bridge environment is destroyed");
|
|
61
|
-
|
|
62
|
-
throw new Error("a reconstructed cli-bridge environment cannot dispatch new work");
|
|
63
|
-
}
|
|
72
|
+
assertCliBridgeTurnAllowed(args.allowDispatch, "environment.dispatch()");
|
|
64
73
|
if (args.selectedModel !== undefined &&
|
|
65
74
|
args.capabilities.retainedControl !== undefined) {
|
|
66
75
|
assertCliBridgeTurnModel(options, environmentInput, turn, args.selectedModel);
|
|
@@ -229,9 +238,7 @@ function createCliBridgeSession(args) {
|
|
|
229
238
|
return result;
|
|
230
239
|
},
|
|
231
240
|
async prompt(input) {
|
|
232
|
-
|
|
233
|
-
throw new Error("a reconstructed cli-bridge session cannot start another turn");
|
|
234
|
-
}
|
|
241
|
+
assertCliBridgeTurnAllowed(args.allowPrompt, "session.prompt()");
|
|
235
242
|
if (input.sessionId && input.sessionId !== args.id) {
|
|
236
243
|
throw new Error(`cli-bridge session "${args.id}" cannot prompt session "${input.sessionId}"`);
|
|
237
244
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-provider-cli-bridge",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.5",
|
|
4
4
|
"description": "AgentEnvironmentProvider adapter for cli-bridge retained sessions and one-shot turns",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"LICENSE"
|
|
60
60
|
],
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@tangle-network/agent-interface": "^1.
|
|
62
|
+
"@tangle-network/agent-interface": "^1.4.0",
|
|
63
63
|
"undici": "7.29.0"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|