@tangle-network/agent-provider-cli-bridge 0.6.4 → 0.7.1
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 +24 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +31 -1
- package/dist/observation.d.ts +49 -0
- package/dist/observation.js +141 -0
- package/dist/retained-environment.d.ts +7 -1
- package/dist/retained-environment.js +30 -3
- package/dist/retained-execution.d.ts +3 -0
- package/dist/retained-execution.js +4 -3
- package/dist/retained-stream.d.ts +2 -1
- package/dist/retained-stream.js +207 -57
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -49,6 +49,9 @@ Passing the same `sessionId` on later turns continues the same CLI conversation.
|
|
|
49
49
|
`dispatch()` starts a bridge-owned durable run and returns after detaching its HTTP reader.
|
|
50
50
|
The returned `AgentSession` exposes status, cursor-based event replay, the terminal result, continuation, and cancellation.
|
|
51
51
|
Cancellation returns only after cli-bridge confirms the run is terminal.
|
|
52
|
+
A direct stream treats a finish frame as provisional until cli-bridge returns the same run's aggregate result.
|
|
53
|
+
A retained replay confirms its terminal state from the retained run endpoint.
|
|
54
|
+
The provider rejects a terminal response when its run id or request digest does not match the accepted stream.
|
|
52
55
|
Usage events and terminal result metadata include `modelRequests` only when the bridge measured an exact non-negative integer count.
|
|
53
56
|
Missing, malformed, partial, or estimated request counts remain unknown.
|
|
54
57
|
When `dispatch()` receives no `sessionId`, it creates one from that turn's stable run id and returns it.
|
|
@@ -58,3 +61,24 @@ Stopping a direct `environment.stream()` reader or destroying the environment ca
|
|
|
58
61
|
|
|
59
62
|
Response headers and streamed bodies have no transport timeout by default.
|
|
60
63
|
For unattended runs, set `headersTimeoutMs`, `bodyTimeoutMs`, or an `AbortSignal` so an unresponsive bridge cannot wait forever.
|
|
64
|
+
|
|
65
|
+
## Environment observation
|
|
66
|
+
|
|
67
|
+
`environment.observe()` returns the normalized `AgentEnvironmentObservation` when the provider document carries an `observation` block.
|
|
68
|
+
Every surface keeps a freshness discriminator, so a value this bridge cannot report is visibly absent instead of arriving as a measured zero.
|
|
69
|
+
|
|
70
|
+
| Surface | cli-bridge source | State when the source is missing |
|
|
71
|
+
| --- | --- | --- |
|
|
72
|
+
| `identity` | provider name and environment id | always known |
|
|
73
|
+
| `lifecycle.status` | `running` until the environment is destroyed | always known |
|
|
74
|
+
| `endpoint` | scheme, host, and explicit port of `baseUrl` | `unavailable` |
|
|
75
|
+
| `placement.verified` | `defaultExecution.kind` as `sandbox` or `local` | always known |
|
|
76
|
+
| `modelUsage` | the token usage and cost the newest execution measured | `unavailable` |
|
|
77
|
+
|
|
78
|
+
cli-bridge forwards a turn and provisions no compute, so it states no requested or effective compute shape, no resource use, and no compute cost.
|
|
79
|
+
It holds no account, so it states no plan, credit balance, quota, or billing period.
|
|
80
|
+
Those five surfaces are never claimed in the capability document and always carry `unavailable` with the reason.
|
|
81
|
+
|
|
82
|
+
The usage of one run is summed across its events and attributed to that run's execution id, which the observation carries as the provenance source.
|
|
83
|
+
An environment rebuilt with `provider.get(id)` has measured nothing yet, so it reports the usage surface as unavailable until a turn completes through it.
|
|
84
|
+
The endpoint holds only a scheme, a host, and an explicit port; userinfo, path, and query are dropped, and the bearer beside the base URL is never read.
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { AgentEnvironmentCapabilities, AgentEnvironmentProvider } from "@ta
|
|
|
2
2
|
import { type HarnessType } from "@tangle-network/agent-interface";
|
|
3
3
|
import { type CliBridgeProviderOptions } from "./provider-options.js";
|
|
4
4
|
export type { CliBridgeProviderOptions } from "./provider-options.js";
|
|
5
|
+
export { safeEndpointFromBaseUrl } from "./observation.js";
|
|
5
6
|
export declare function createCliBridgeProvider(options: CliBridgeProviderOptions): AgentEnvironmentProvider;
|
|
6
7
|
/**
|
|
7
8
|
* Describe the bridge backend, not this adapter.
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
import { harnessSystemPromptIntents, snapshotAgentProfile, } from "@tangle-network/agent-interface";
|
|
2
2
|
import { createCliBridgeEnvironment } from "./retained-environment.js";
|
|
3
3
|
import { assertCliBridgeProviderOptions, } from "./provider-options.js";
|
|
4
|
+
import { narrowedCliBridgeObservation } from "./observation.js";
|
|
5
|
+
export { safeEndpointFromBaseUrl } from "./observation.js";
|
|
4
6
|
export function createCliBridgeProvider(options) {
|
|
5
7
|
assertCliBridgeProviderOptions(options);
|
|
6
8
|
const name = options.name ?? "cli-bridge";
|
|
9
|
+
// The observation surfaces are declared as intent and narrowed to the
|
|
10
|
+
// sources this bridge can put a value on, so the environment offers the
|
|
11
|
+
// operation exactly where the document claims it.
|
|
12
|
+
const resolveCapabilities = () => {
|
|
13
|
+
const declared = options.capabilities ?? defaultCliBridgeCapabilities();
|
|
14
|
+
return declared.observation === undefined
|
|
15
|
+
? declared
|
|
16
|
+
: {
|
|
17
|
+
...declared,
|
|
18
|
+
observation: narrowedCliBridgeObservation(declared.observation, options),
|
|
19
|
+
};
|
|
20
|
+
};
|
|
7
21
|
return {
|
|
8
22
|
name,
|
|
9
|
-
capabilities:
|
|
23
|
+
capabilities: resolveCapabilities,
|
|
10
24
|
async create(input) {
|
|
11
25
|
if (typeof input.profile === "string") {
|
|
12
26
|
throw new Error(`createCliBridgeProvider requires an inline AgentProfile; named profile "${input.profile}" is unsupported`);
|
|
@@ -23,6 +37,7 @@ export function createCliBridgeProvider(options) {
|
|
|
23
37
|
environmentId,
|
|
24
38
|
allowDispatch: true,
|
|
25
39
|
cancelRunsOnDestroy: true,
|
|
40
|
+
capabilities: resolveCapabilities(),
|
|
26
41
|
});
|
|
27
42
|
},
|
|
28
43
|
async get(id) {
|
|
@@ -36,6 +51,7 @@ export function createCliBridgeProvider(options) {
|
|
|
36
51
|
environmentId: id,
|
|
37
52
|
allowDispatch: false,
|
|
38
53
|
cancelRunsOnDestroy: false,
|
|
54
|
+
capabilities: resolveCapabilities(),
|
|
39
55
|
});
|
|
40
56
|
},
|
|
41
57
|
};
|
|
@@ -88,5 +104,19 @@ export function defaultCliBridgeCapabilities(harness) {
|
|
|
88
104
|
placement: true,
|
|
89
105
|
usage: true,
|
|
90
106
|
confidential: false,
|
|
107
|
+
// cli-bridge measures what a turn cost and where it forwarded that turn.
|
|
108
|
+
// It provisions no compute and holds no account, so the surfaces that
|
|
109
|
+
// describe provisioned resources and billing are never claimed.
|
|
110
|
+
observation: {
|
|
111
|
+
identity: true,
|
|
112
|
+
lifecycle: true,
|
|
113
|
+
endpoint: true,
|
|
114
|
+
placement: true,
|
|
115
|
+
resources: false,
|
|
116
|
+
resourceUse: false,
|
|
117
|
+
modelUsage: true,
|
|
118
|
+
computeBilling: false,
|
|
119
|
+
accountUsage: false,
|
|
120
|
+
},
|
|
91
121
|
};
|
|
92
122
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { AgentEnvironmentCapabilities, AgentEnvironmentObservation, SafeEndpoint, TokenUsage } from "@tangle-network/agent-interface";
|
|
2
|
+
import type { CliBridgeProviderOptions } from "./provider-options.js";
|
|
3
|
+
/** One execution's accumulated token usage and cost. */
|
|
4
|
+
interface ExecutionUsageRecord {
|
|
5
|
+
executionId: string;
|
|
6
|
+
usage: TokenUsage;
|
|
7
|
+
observedAt: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The newest per-execution usage this environment handle measured.
|
|
11
|
+
*
|
|
12
|
+
* cli-bridge reports usage on the events of one run, so the totals are summed
|
|
13
|
+
* per execution and the newest execution answers the environment-scoped
|
|
14
|
+
* observation. The record lives with the handle: an environment rebuilt by id
|
|
15
|
+
* starts with none, and the observation then reports the usage surface as
|
|
16
|
+
* unavailable rather than as a measured zero.
|
|
17
|
+
*/
|
|
18
|
+
export interface ExecutionUsageLog {
|
|
19
|
+
record(executionId: string | undefined, usage: TokenUsage | undefined): void;
|
|
20
|
+
latest(): ExecutionUsageRecord | undefined;
|
|
21
|
+
}
|
|
22
|
+
export declare function createExecutionUsageLog(): ExecutionUsageLog;
|
|
23
|
+
/**
|
|
24
|
+
* Read the credential-free network location of the cli-bridge endpoint.
|
|
25
|
+
*
|
|
26
|
+
* Only the scheme, host, and explicit port are carried. Userinfo, path, and
|
|
27
|
+
* query are dropped, and the bearer beside the base URL is never read, so an
|
|
28
|
+
* endpoint payload cannot transport a credential.
|
|
29
|
+
*/
|
|
30
|
+
export declare function safeEndpointFromBaseUrl(baseUrl: string | undefined): SafeEndpoint | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Clear every observation surface no source backs.
|
|
33
|
+
*
|
|
34
|
+
* cli-bridge forwards a turn to a remote bridge and reports what that turn
|
|
35
|
+
* cost. It never provisions compute, so it states no compute shape, no
|
|
36
|
+
* resource use, no compute cost, and no account plan. The endpoint rests on a
|
|
37
|
+
* base URL that parses.
|
|
38
|
+
*/
|
|
39
|
+
export declare function narrowedCliBridgeObservation(declared: NonNullable<AgentEnvironmentCapabilities["observation"]>, options: CliBridgeProviderOptions): NonNullable<AgentEnvironmentCapabilities["observation"]>;
|
|
40
|
+
export interface CliBridgeObservationSources {
|
|
41
|
+
options: CliBridgeProviderOptions;
|
|
42
|
+
provider: string;
|
|
43
|
+
environmentId: string;
|
|
44
|
+
destroyed: boolean;
|
|
45
|
+
usageLog: ExecutionUsageLog;
|
|
46
|
+
}
|
|
47
|
+
/** Build the normalized, freshness-tagged observation of one environment. */
|
|
48
|
+
export declare function observeCliBridgeEnvironment(sources: CliBridgeObservationSources): AgentEnvironmentObservation;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { AgentEnvironmentObservationSchema } from "@tangle-network/agent-interface";
|
|
2
|
+
export function createExecutionUsageLog() {
|
|
3
|
+
let latest;
|
|
4
|
+
return {
|
|
5
|
+
record(executionId, usage) {
|
|
6
|
+
// Usage without the execution it belongs to cannot be attributed, and an
|
|
7
|
+
// execution without usage measured nothing. Neither is recorded.
|
|
8
|
+
if (executionId === undefined || executionId.length === 0)
|
|
9
|
+
return;
|
|
10
|
+
if (usage === undefined)
|
|
11
|
+
return;
|
|
12
|
+
latest = {
|
|
13
|
+
executionId,
|
|
14
|
+
usage,
|
|
15
|
+
observedAt: new Date().toISOString(),
|
|
16
|
+
};
|
|
17
|
+
},
|
|
18
|
+
latest() {
|
|
19
|
+
return latest === undefined
|
|
20
|
+
? undefined
|
|
21
|
+
: { ...latest, usage: { ...latest.usage } };
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Read the credential-free network location of the cli-bridge endpoint.
|
|
27
|
+
*
|
|
28
|
+
* Only the scheme, host, and explicit port are carried. Userinfo, path, and
|
|
29
|
+
* query are dropped, and the bearer beside the base URL is never read, so an
|
|
30
|
+
* endpoint payload cannot transport a credential.
|
|
31
|
+
*/
|
|
32
|
+
export function safeEndpointFromBaseUrl(baseUrl) {
|
|
33
|
+
if (typeof baseUrl !== "string" || baseUrl.length === 0)
|
|
34
|
+
return undefined;
|
|
35
|
+
let parsed;
|
|
36
|
+
try {
|
|
37
|
+
parsed = new URL(baseUrl);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
const scheme = parsed.protocol.replace(/:$/, "");
|
|
43
|
+
const host = parsed.hostname;
|
|
44
|
+
if (scheme.length === 0 || host.length === 0)
|
|
45
|
+
return undefined;
|
|
46
|
+
const port = parsed.port === "" ? undefined : Number.parseInt(parsed.port, 10);
|
|
47
|
+
if (port !== undefined && (!Number.isInteger(port) || port < 1 || port > 65_535)) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
return { scheme, host, ...(port === undefined ? {} : { port }) };
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Clear every observation surface no source backs.
|
|
54
|
+
*
|
|
55
|
+
* cli-bridge forwards a turn to a remote bridge and reports what that turn
|
|
56
|
+
* cost. It never provisions compute, so it states no compute shape, no
|
|
57
|
+
* resource use, no compute cost, and no account plan. The endpoint rests on a
|
|
58
|
+
* base URL that parses.
|
|
59
|
+
*/
|
|
60
|
+
export function narrowedCliBridgeObservation(declared, options) {
|
|
61
|
+
const endpoint = safeEndpointFromBaseUrl(options.baseUrl) !== undefined;
|
|
62
|
+
return {
|
|
63
|
+
identity: declared.identity,
|
|
64
|
+
lifecycle: declared.lifecycle,
|
|
65
|
+
endpoint: endpoint ? declared.endpoint : false,
|
|
66
|
+
placement: declared.placement,
|
|
67
|
+
resources: false,
|
|
68
|
+
resourceUse: false,
|
|
69
|
+
modelUsage: declared.modelUsage,
|
|
70
|
+
computeBilling: false,
|
|
71
|
+
accountUsage: false,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** Build the normalized, freshness-tagged observation of one environment. */
|
|
75
|
+
export function observeCliBridgeEnvironment(sources) {
|
|
76
|
+
const capturedAt = new Date().toISOString();
|
|
77
|
+
const provenance = {
|
|
78
|
+
origin: "reported",
|
|
79
|
+
observedAt: capturedAt,
|
|
80
|
+
source: "cli-bridge",
|
|
81
|
+
};
|
|
82
|
+
const subject = {
|
|
83
|
+
provider: sources.provider,
|
|
84
|
+
environmentId: sources.environmentId,
|
|
85
|
+
};
|
|
86
|
+
const endpoint = safeEndpointFromBaseUrl(sources.options.baseUrl);
|
|
87
|
+
const latest = sources.usageLog.latest();
|
|
88
|
+
const absent = (reason) => ({
|
|
89
|
+
state: "unavailable",
|
|
90
|
+
reason,
|
|
91
|
+
});
|
|
92
|
+
const noCompute = "cli-bridge forwards a turn and provisions no compute";
|
|
93
|
+
const noAccount = "cli-bridge reports no account plan, credit, or quota";
|
|
94
|
+
const noProbe = "cli-bridge never probes the bridge, so its runtime state is unproven";
|
|
95
|
+
return AgentEnvironmentObservationSchema.parse({
|
|
96
|
+
subject,
|
|
97
|
+
capturedAt,
|
|
98
|
+
identity: { state: "known", value: subject, provenance },
|
|
99
|
+
// A destroyed handle stopped because this adapter stopped it, which is the
|
|
100
|
+
// only lifecycle fact cli-bridge establishes. A live handle holds a base
|
|
101
|
+
// URL and nothing else, and configuration is not a running runtime.
|
|
102
|
+
lifecycle: sources.destroyed
|
|
103
|
+
? { state: "known", value: { status: "stopped" }, provenance }
|
|
104
|
+
: absent(noProbe),
|
|
105
|
+
endpoint: endpoint === undefined
|
|
106
|
+
? absent("the cli-bridge base URL states no reachable host")
|
|
107
|
+
: { state: "known", value: endpoint, provenance },
|
|
108
|
+
// The configured execution kind is where the caller asked the turn to run,
|
|
109
|
+
// so it is carried as the request. cli-bridge runs no placement check, so
|
|
110
|
+
// nothing verifies it.
|
|
111
|
+
placement: {
|
|
112
|
+
requested: {
|
|
113
|
+
kind: sources.options.defaultExecution?.kind === "sandbox" ? "sandbox" : "local",
|
|
114
|
+
},
|
|
115
|
+
verified: absent(noProbe),
|
|
116
|
+
},
|
|
117
|
+
resources: { effective: absent(noCompute) },
|
|
118
|
+
resourceUse: { current: absent(noCompute), peak: absent(noCompute) },
|
|
119
|
+
modelUsage: latest === undefined
|
|
120
|
+
? absent("no execution measured token usage through this environment handle")
|
|
121
|
+
: {
|
|
122
|
+
state: "known",
|
|
123
|
+
value: latest.usage,
|
|
124
|
+
// The provenance source names the execution the usage belongs to,
|
|
125
|
+
// because cli-bridge measures usage per run and never for the
|
|
126
|
+
// environment.
|
|
127
|
+
provenance: {
|
|
128
|
+
origin: "reported",
|
|
129
|
+
observedAt: latest.observedAt,
|
|
130
|
+
source: latest.executionId,
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
computeBilling: absent(noCompute),
|
|
134
|
+
accountUsage: {
|
|
135
|
+
plan: absent(noAccount),
|
|
136
|
+
credits: absent(noAccount),
|
|
137
|
+
quota: absent(noAccount),
|
|
138
|
+
period: absent(noAccount),
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentEnvironment, CreateAgentEnvironmentInput } from "@tangle-network/agent-interface/environment-provider";
|
|
1
|
+
import type { AgentEnvironment, AgentEnvironmentCapabilities, 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,5 +7,11 @@ export interface CreateCliBridgeEnvironmentArgs {
|
|
|
7
7
|
readonly environmentId: string;
|
|
8
8
|
readonly allowDispatch: boolean;
|
|
9
9
|
readonly cancelRunsOnDestroy: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* The document this provider publishes. The environment offers an optional
|
|
12
|
+
* operation only where the document claims it, so a caller never selects an
|
|
13
|
+
* action the document did not carry.
|
|
14
|
+
*/
|
|
15
|
+
readonly capabilities: AgentEnvironmentCapabilities;
|
|
10
16
|
}
|
|
11
17
|
export declare function createCliBridgeEnvironment(args: CreateCliBridgeEnvironmentArgs): AgentEnvironment;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { agentSessionStatusFromRun, cancelCliBridgeRun, cancelExactCliBridgeRun, getCliBridgeRun, } from "./retained-control.js";
|
|
2
|
-
import { collectCliBridgeTurnResult, dispatchCliBridgeTurn, streamCliBridgeSessionEvents, streamTrackedCliBridgeTurn, } from "./retained-execution.js";
|
|
2
|
+
import { addTokenUsage, collectCliBridgeTurnResult, dispatchCliBridgeTurn, streamCliBridgeSessionEvents, streamTrackedCliBridgeTurn, } from "./retained-execution.js";
|
|
3
|
+
import { createExecutionUsageLog, observeCliBridgeEnvironment, } from "./observation.js";
|
|
3
4
|
import { assertRunMatchesControlRef, exactControlRefForSession, prepareCliBridgeRun, runFromControlRef, } from "./retained-run-state.js";
|
|
4
5
|
import { createCliBridgeTransport } from "./transport.js";
|
|
5
6
|
export function createCliBridgeEnvironment(args) {
|
|
@@ -8,6 +9,7 @@ export function createCliBridgeEnvironment(args) {
|
|
|
8
9
|
const runs = new Map();
|
|
9
10
|
const sessions = new Map();
|
|
10
11
|
const readers = new Set();
|
|
12
|
+
const usageLog = createExecutionUsageLog();
|
|
11
13
|
let destroyed = false;
|
|
12
14
|
let closePromise;
|
|
13
15
|
const stream = async function* (turn) {
|
|
@@ -17,7 +19,14 @@ export function createCliBridgeEnvironment(args) {
|
|
|
17
19
|
throw new Error("a reconstructed cli-bridge environment can only control an existing run");
|
|
18
20
|
}
|
|
19
21
|
const prepared = prepareCliBridgeRun(options, environmentInput, turn, environmentId, false);
|
|
20
|
-
|
|
22
|
+
// A streamed run reports usage across its events, so the totals are summed
|
|
23
|
+
// here and recorded as one execution's measurement.
|
|
24
|
+
let streamedUsage;
|
|
25
|
+
for await (const event of streamTrackedCliBridgeTurn(options, environmentInput, prepared, transport, runs, sessions, readers)) {
|
|
26
|
+
streamedUsage = addTokenUsage(streamedUsage, event.usage);
|
|
27
|
+
usageLog.record(prepared.run.executionId, streamedUsage);
|
|
28
|
+
yield event;
|
|
29
|
+
}
|
|
21
30
|
};
|
|
22
31
|
return {
|
|
23
32
|
id: environmentId,
|
|
@@ -52,8 +61,23 @@ export function createCliBridgeEnvironment(args) {
|
|
|
52
61
|
allowPrompt: args.allowDispatch,
|
|
53
62
|
requestedControlRef: sessionOptions?.controlRef,
|
|
54
63
|
isDestroyed: () => destroyed,
|
|
64
|
+
usageLog,
|
|
55
65
|
});
|
|
56
66
|
},
|
|
67
|
+
...(args.capabilities.observation
|
|
68
|
+
? {
|
|
69
|
+
async observe(observeOptions) {
|
|
70
|
+
observeOptions?.signal?.throwIfAborted();
|
|
71
|
+
return observeCliBridgeEnvironment({
|
|
72
|
+
options,
|
|
73
|
+
provider: providerName,
|
|
74
|
+
environmentId,
|
|
75
|
+
destroyed,
|
|
76
|
+
usageLog,
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
: {}),
|
|
57
81
|
placement: async (placementOptions) => {
|
|
58
82
|
placementOptions?.signal?.throwIfAborted();
|
|
59
83
|
return {
|
|
@@ -161,7 +185,9 @@ function createCliBridgeSession(args) {
|
|
|
161
185
|
},
|
|
162
186
|
async result(resultOptions) {
|
|
163
187
|
const run = requireCurrentRun();
|
|
164
|
-
|
|
188
|
+
const result = await collectCliBridgeTurnResult(streamCliBridgeSessionEvents(args.options, args.environmentInput, run, args.transport, args.runs, args.readers, { since: "0", signal: resultOptions?.signal }), run, args.options, args.transport, resultOptions?.signal);
|
|
189
|
+
args.usageLog.record(run.executionId, result.usage);
|
|
190
|
+
return result;
|
|
165
191
|
},
|
|
166
192
|
async prompt(input) {
|
|
167
193
|
if (!args.allowPrompt) {
|
|
@@ -175,6 +201,7 @@ function createCliBridgeSession(args) {
|
|
|
175
201
|
sessionId: args.id,
|
|
176
202
|
}, args.environmentId, false);
|
|
177
203
|
const result = await collectCliBridgeTurnResult(streamTrackedCliBridgeTurn(args.options, args.environmentInput, prepared, args.transport, args.runs, args.sessions, args.readers), prepared.run, args.options, args.transport, input.signal);
|
|
204
|
+
args.usageLog.record(prepared.run.executionId, result.usage);
|
|
178
205
|
return { ...result, sessionId: args.id };
|
|
179
206
|
},
|
|
180
207
|
async cancel(cancelOptions) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TokenUsage } from "@tangle-network/agent-interface";
|
|
1
2
|
import type { AgentEnvironmentEvent, AgentSessionRef, AgentTurnResult, CreateAgentEnvironmentInput } from "@tangle-network/agent-interface/environment-provider";
|
|
2
3
|
import type { CliBridgeProviderOptions } from "./provider-options.js";
|
|
3
4
|
import { type CliBridgeRun, type CliBridgeSessionState, type PreparedCliBridgeRun } from "./retained-run-state.js";
|
|
@@ -10,3 +11,5 @@ export declare function streamCliBridgeSessionEvents(options: CliBridgeProviderO
|
|
|
10
11
|
signal?: AbortSignal;
|
|
11
12
|
}): AsyncIterable<AgentEnvironmentEvent>;
|
|
12
13
|
export declare function collectCliBridgeTurnResult(source: AsyncIterable<AgentEnvironmentEvent>, run: CliBridgeRun, options: CliBridgeProviderOptions, transport: CliBridgeTransport, signal?: AbortSignal): Promise<AgentTurnResult>;
|
|
14
|
+
/** Sum the usage a run reported across its events into one total. */
|
|
15
|
+
export declare function addTokenUsage(current: TokenUsage | undefined, next: TokenUsage | undefined): TokenUsage | undefined;
|
|
@@ -27,7 +27,7 @@ export async function* streamTrackedCliBridgeTurn(options, environmentInput, pre
|
|
|
27
27
|
let drained = false;
|
|
28
28
|
let threw = false;
|
|
29
29
|
try {
|
|
30
|
-
for await (const event of streamCliBridgeTurn(options, turn, run.requestBody, transport, run.id, originalTurn.lastEventId, signal, (response) => captureCliBridgeRunIdentity(response, run,
|
|
30
|
+
for await (const event of streamCliBridgeTurn(options, turn, run.requestBody, transport, run.id, originalTurn.lastEventId, signal, (response) => captureCliBridgeRunIdentity(response, run, true), () => getCliBridgeRun(options, transport, run, 30_000, signal))) {
|
|
31
31
|
yield event;
|
|
32
32
|
}
|
|
33
33
|
drained = true;
|
|
@@ -171,7 +171,7 @@ export async function* streamCliBridgeSessionEvents(options, environmentInput, r
|
|
|
171
171
|
...(run.sessionId ? { sessionId: run.sessionId } : {}),
|
|
172
172
|
executionId: run.executionId,
|
|
173
173
|
turnId: run.turnId,
|
|
174
|
-
}, undefined, transport, run.id, eventOptions?.since ?? "0", signal, (response) => captureCliBridgeRunIdentity(response, run, false));
|
|
174
|
+
}, undefined, transport, run.id, eventOptions?.since ?? "0", signal, (response) => captureCliBridgeRunIdentity(response, run, false), () => getCliBridgeRun(options, transport, run, 30_000, signal));
|
|
175
175
|
drained = true;
|
|
176
176
|
if (runs.get(run.id) === run)
|
|
177
177
|
runs.delete(run.id);
|
|
@@ -267,7 +267,8 @@ export async function collectCliBridgeTurnResult(source, run, options, transport
|
|
|
267
267
|
events,
|
|
268
268
|
};
|
|
269
269
|
}
|
|
270
|
-
|
|
270
|
+
/** Sum the usage a run reported across its events into one total. */
|
|
271
|
+
export function addTokenUsage(current, next) {
|
|
271
272
|
if (!next)
|
|
272
273
|
return current;
|
|
273
274
|
if (!current)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { AgentEnvironmentEvent, AgentTurnInput } from "@tangle-network/agent-interface/environment-provider";
|
|
2
2
|
import type { CliBridgeProviderOptions } from "./provider-options.js";
|
|
3
|
+
import type { CliBridgeRunSnapshot } from "./retained-run-state.js";
|
|
3
4
|
import type { CliBridgeResponse, CliBridgeTransport } from "./transport.js";
|
|
4
5
|
export declare class CliBridgeRequestRejectedError extends Error {
|
|
5
6
|
readonly status: number;
|
|
6
7
|
constructor(status: number, detail: string);
|
|
7
8
|
}
|
|
8
|
-
export declare function streamCliBridgeTurn(options: CliBridgeProviderOptions, turn: AgentTurnInput, requestBody: string | undefined, transport: CliBridgeTransport, runId: string, lastEventId?: string, signal?: AbortSignal,
|
|
9
|
+
export declare function streamCliBridgeTurn(options: CliBridgeProviderOptions, turn: AgentTurnInput, requestBody: string | undefined, transport: CliBridgeTransport, runId: string, lastEventId?: string, signal?: AbortSignal, onResponse?: (response: CliBridgeResponse) => void, readAuthoritativeRun?: () => Promise<CliBridgeRunSnapshot | null>): AsyncIterable<AgentEnvironmentEvent>;
|
package/dist/retained-stream.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { retainedEventsWithIdentity, retainedReplayRequest, } from "./retained-event-cursor.js";
|
|
2
|
+
import { detachCliBridgeReader } from "./retained-control.js";
|
|
2
3
|
import { requestHeaders, trimSlash } from "./transport.js";
|
|
3
4
|
import { modelRequestsFromOpenAi, parseSse, responseIdentityFromOpenAi, safeJson, toolCallsFromDelta, usageFromOpenAi, } from "./wire.js";
|
|
4
5
|
export class CliBridgeRequestRejectedError extends Error {
|
|
@@ -9,7 +10,15 @@ export class CliBridgeRequestRejectedError extends Error {
|
|
|
9
10
|
this.name = "CliBridgeRequestRejectedError";
|
|
10
11
|
}
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
+
class CliBridgeRunCancelledError extends Error {
|
|
14
|
+
detail;
|
|
15
|
+
constructor(detail) {
|
|
16
|
+
super(`cli-bridge run cancelled: ${detail}`);
|
|
17
|
+
this.detail = detail;
|
|
18
|
+
this.name = "CliBridgeRunCancelledError";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export async function* streamCliBridgeTurn(options, turn, requestBody, transport, runId, lastEventId, signal, onResponse, readAuthoritativeRun) {
|
|
13
22
|
const reconnect = requestBody === undefined;
|
|
14
23
|
const replay = retainedReplayRequest(lastEventId);
|
|
15
24
|
const response = await transport.fetch(reconnect
|
|
@@ -37,9 +46,20 @@ export async function* streamCliBridgeTurn(options, turn, requestBody, transport
|
|
|
37
46
|
}
|
|
38
47
|
throw new CliBridgeRequestRejectedError(response.status, detail);
|
|
39
48
|
}
|
|
40
|
-
onAccepted?.(response);
|
|
41
49
|
if (!response.body)
|
|
42
50
|
throw new Error("cli-bridge response body is empty");
|
|
51
|
+
try {
|
|
52
|
+
onResponse?.(response);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
try {
|
|
56
|
+
await detachCliBridgeReader(response.body);
|
|
57
|
+
}
|
|
58
|
+
catch (detachError) {
|
|
59
|
+
throw new AggregateError([error, detachError], `cli-bridge rejected response identity for run "${runId}" and could not detach its reader`);
|
|
60
|
+
}
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
43
63
|
let text = "";
|
|
44
64
|
const sessionId = turn.sessionId ?? runId;
|
|
45
65
|
const messageId = turn.turnId ?? `${sessionId}:assistant`;
|
|
@@ -51,25 +71,39 @@ export async function* streamCliBridgeTurn(options, turn, requestBody, transport
|
|
|
51
71
|
let servedModel;
|
|
52
72
|
let systemFingerprint;
|
|
53
73
|
let textBoundaryPending = false;
|
|
54
|
-
let terminalCursor;
|
|
55
74
|
let sawProtocolEnd = false;
|
|
75
|
+
let terminalFrameSeen = false;
|
|
76
|
+
let cancelledTerminalSeen = false;
|
|
77
|
+
let terminalFrame;
|
|
56
78
|
for await (const frame of parseSse(response.body)) {
|
|
57
79
|
if (frame.data === "[DONE]") {
|
|
58
80
|
sawProtocolEnd = true;
|
|
59
81
|
continue;
|
|
60
82
|
}
|
|
83
|
+
if (terminalFrameSeen)
|
|
84
|
+
continue;
|
|
61
85
|
const parsed = safeJson(frame.data);
|
|
62
86
|
if (!parsed)
|
|
63
87
|
continue;
|
|
64
88
|
if (parsed.error && typeof parsed.error === "object") {
|
|
65
89
|
const error = parsed.error;
|
|
66
90
|
const message = typeof error.message === "string" ? error.message : "cli-bridge error";
|
|
91
|
+
const cancelled = error.type === "run_cancelled";
|
|
67
92
|
yield* retainedEventsWithIdentity([{
|
|
68
93
|
type: "status",
|
|
69
|
-
data: { status: "failed", error: message },
|
|
70
|
-
normalized: {
|
|
94
|
+
data: { status: cancelled ? "cancelled" : "failed", error: message },
|
|
95
|
+
normalized: {
|
|
96
|
+
type: "status",
|
|
97
|
+
status: cancelled ? "cancelled" : "failed",
|
|
98
|
+
detail: message,
|
|
99
|
+
},
|
|
71
100
|
}], frame.id, runId, sessionId, turn.executionId, replay.anchor);
|
|
72
|
-
|
|
101
|
+
terminalFrameSeen = true;
|
|
102
|
+
completed = cancelled;
|
|
103
|
+
cancelledTerminalSeen = cancelled;
|
|
104
|
+
if (!cancelled)
|
|
105
|
+
throw new Error(`cli-bridge: ${message}`);
|
|
106
|
+
continue;
|
|
73
107
|
}
|
|
74
108
|
const choice = Array.isArray(parsed.choices) ? parsed.choices[0] : undefined;
|
|
75
109
|
const delta = choice?.delta;
|
|
@@ -161,6 +195,7 @@ export async function* streamCliBridgeTurn(options, turn, requestBody, transport
|
|
|
161
195
|
if (toolCallDeltas.length > 0)
|
|
162
196
|
textBoundaryPending = true;
|
|
163
197
|
if (choice?.finish_reason) {
|
|
198
|
+
terminalFrameSeen = true;
|
|
164
199
|
if (choice.finish_reason === "error") {
|
|
165
200
|
frameEvents.push({
|
|
166
201
|
type: "status",
|
|
@@ -175,61 +210,160 @@ export async function* streamCliBridgeTurn(options, turn, requestBody, transport
|
|
|
175
210
|
throw new Error("cli-bridge returned finish_reason=error");
|
|
176
211
|
}
|
|
177
212
|
completed = true;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
frameEvents.push({
|
|
185
|
-
type: "result",
|
|
186
|
-
data: {
|
|
187
|
-
finalText: text,
|
|
188
|
-
finishReason: choice.finish_reason,
|
|
189
|
-
status: "completed",
|
|
190
|
-
...identityData,
|
|
191
|
-
...(modelRequestsKnown ? { modelRequests: observedModelRequests } : {}),
|
|
192
|
-
},
|
|
193
|
-
});
|
|
194
|
-
}
|
|
213
|
+
terminalFrame = {
|
|
214
|
+
...(frame.id === undefined ? {} : { id: frame.id }),
|
|
215
|
+
events: frameEvents,
|
|
216
|
+
finishReason: choice.finish_reason,
|
|
217
|
+
};
|
|
218
|
+
continue;
|
|
195
219
|
}
|
|
196
220
|
yield* retainedEventsWithIdentity(frameEvents, frame.id, runId, sessionId, turn.executionId, replay.anchor);
|
|
197
221
|
}
|
|
198
222
|
if (!sawProtocolEnd) {
|
|
199
223
|
throw new Error("cli-bridge stream ended without the [DONE] protocol marker");
|
|
200
224
|
}
|
|
225
|
+
if (cancelledTerminalSeen)
|
|
226
|
+
return;
|
|
201
227
|
if (!completed && lastEventId === undefined) {
|
|
228
|
+
let snapshot;
|
|
229
|
+
try {
|
|
230
|
+
snapshot = await terminalRunSnapshot(runId, readAuthoritativeRun);
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
throw new Error("cli-bridge stream ended without a terminal result", {
|
|
234
|
+
cause: error,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
if (snapshot.status === "cancelled") {
|
|
238
|
+
const event = cancelledEvent(`cli-bridge run "${runId}" was cancelled`);
|
|
239
|
+
yield {
|
|
240
|
+
...event,
|
|
241
|
+
data: {
|
|
242
|
+
...event.data,
|
|
243
|
+
runId,
|
|
244
|
+
sessionId,
|
|
245
|
+
...(turn.executionId === undefined
|
|
246
|
+
? {}
|
|
247
|
+
: { executionId: turn.executionId }),
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
202
252
|
throw new Error("cli-bridge stream ended without a terminal result");
|
|
203
253
|
}
|
|
204
|
-
if (
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
runId,
|
|
220
|
-
sessionId,
|
|
221
|
-
...(turn.executionId === undefined ? {} : { executionId: turn.executionId }),
|
|
222
|
-
...(finalCursor === undefined ? {} : { cursor: finalCursor }),
|
|
223
|
-
...(finalModelRequests === undefined
|
|
224
|
-
? {}
|
|
225
|
-
: { modelRequests: finalModelRequests }),
|
|
226
|
-
},
|
|
227
|
-
...(result.usage && !sawUsage ? { usage: result.usage } : {}),
|
|
228
|
-
...(finalCursor === undefined ? {} : { id: finalCursor }),
|
|
229
|
-
};
|
|
254
|
+
if (!terminalFrame) {
|
|
255
|
+
if (requestBody !== undefined && lastEventId !== undefined) {
|
|
256
|
+
try {
|
|
257
|
+
await readFullCliBridgeResult(options, requestBody, transport, signal, onResponse);
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
if (error instanceof CliBridgeRunCancelledError)
|
|
261
|
+
return;
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
else if (requestBody === undefined) {
|
|
266
|
+
await terminalRunSnapshot(runId, readAuthoritativeRun);
|
|
267
|
+
}
|
|
268
|
+
return;
|
|
230
269
|
}
|
|
270
|
+
let terminalEvent;
|
|
271
|
+
let terminalFailure;
|
|
272
|
+
if (requestBody !== undefined) {
|
|
273
|
+
let result;
|
|
274
|
+
try {
|
|
275
|
+
result = await readFullCliBridgeResult(options, requestBody, transport, signal, onResponse);
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
if (error instanceof CliBridgeRunCancelledError) {
|
|
279
|
+
terminalEvent = cancelledEvent(error.detail);
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
throw error;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (result !== undefined) {
|
|
286
|
+
const finalModelRequests = result.modelRequests ??
|
|
287
|
+
(modelRequestsKnown ? observedModelRequests : undefined);
|
|
288
|
+
terminalEvent = {
|
|
289
|
+
type: "result",
|
|
290
|
+
data: {
|
|
291
|
+
finalText: lastEventId === undefined ? text : result.text,
|
|
292
|
+
finishReason: lastEventId === undefined ? terminalFrame.finishReason : result.finishReason,
|
|
293
|
+
status: "completed",
|
|
294
|
+
...(result.model === undefined ? {} : { model: result.model }),
|
|
295
|
+
...(result.system_fingerprint === undefined
|
|
296
|
+
? {}
|
|
297
|
+
: { system_fingerprint: result.system_fingerprint }),
|
|
298
|
+
...(finalModelRequests === undefined
|
|
299
|
+
? {}
|
|
300
|
+
: { modelRequests: finalModelRequests }),
|
|
301
|
+
},
|
|
302
|
+
...(result.usage && !sawUsage ? { usage: result.usage } : {}),
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
const snapshot = await terminalRunSnapshot(runId, readAuthoritativeRun);
|
|
308
|
+
if (snapshot.status === "cancelled") {
|
|
309
|
+
terminalEvent = cancelledEvent(`cli-bridge run "${runId}" was cancelled`);
|
|
310
|
+
}
|
|
311
|
+
else if (snapshot.status === "error") {
|
|
312
|
+
const detail = `cli-bridge run "${runId}" ended with an error`;
|
|
313
|
+
terminalEvent = failedEvent(detail);
|
|
314
|
+
terminalFailure = new Error(detail);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
terminalEvent = {
|
|
318
|
+
type: "result",
|
|
319
|
+
data: {
|
|
320
|
+
finalText: text,
|
|
321
|
+
finishReason: terminalFrame.finishReason,
|
|
322
|
+
status: "completed",
|
|
323
|
+
...(servedModel === undefined ? {} : { model: servedModel }),
|
|
324
|
+
...(systemFingerprint === undefined
|
|
325
|
+
? {}
|
|
326
|
+
: { system_fingerprint: systemFingerprint }),
|
|
327
|
+
...(modelRequestsKnown ? { modelRequests: observedModelRequests } : {}),
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (!terminalEvent) {
|
|
333
|
+
throw new Error("cli-bridge terminal state did not produce a terminal event");
|
|
334
|
+
}
|
|
335
|
+
terminalFrame.events.push(terminalEvent);
|
|
336
|
+
yield* retainedEventsWithIdentity(terminalFrame.events, terminalFrame.id, runId, sessionId, turn.executionId, replay.anchor);
|
|
337
|
+
if (terminalFailure)
|
|
338
|
+
throw terminalFailure;
|
|
339
|
+
}
|
|
340
|
+
async function terminalRunSnapshot(runId, readAuthoritativeRun) {
|
|
341
|
+
if (!readAuthoritativeRun) {
|
|
342
|
+
throw new Error("cli-bridge retained stream omitted authoritative run status");
|
|
343
|
+
}
|
|
344
|
+
const snapshot = await readAuthoritativeRun();
|
|
345
|
+
if (!snapshot)
|
|
346
|
+
throw new Error(`cli-bridge lost run "${runId}" before terminal replay`);
|
|
347
|
+
if (!snapshot.terminal || snapshot.status === "running") {
|
|
348
|
+
throw new Error(`cli-bridge run "${runId}" remained active after its stream ended`);
|
|
349
|
+
}
|
|
350
|
+
return snapshot;
|
|
351
|
+
}
|
|
352
|
+
function cancelledEvent(detail) {
|
|
353
|
+
return {
|
|
354
|
+
type: "status",
|
|
355
|
+
data: { status: "cancelled", error: detail },
|
|
356
|
+
normalized: { type: "status", status: "cancelled", detail },
|
|
357
|
+
};
|
|
231
358
|
}
|
|
232
|
-
|
|
359
|
+
function failedEvent(detail) {
|
|
360
|
+
return {
|
|
361
|
+
type: "status",
|
|
362
|
+
data: { status: "failed", error: detail },
|
|
363
|
+
normalized: { type: "status", status: "failed", detail },
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
async function readFullCliBridgeResult(options, requestBody, transport, signal, onResponse) {
|
|
233
367
|
const body = safeJson(requestBody);
|
|
234
368
|
if (!body)
|
|
235
369
|
throw new Error("cli-bridge replay request is not valid JSON");
|
|
@@ -239,15 +373,22 @@ async function readFullCliBridgeResult(options, requestBody, transport, signal,
|
|
|
239
373
|
body: JSON.stringify({ ...body, stream: false }),
|
|
240
374
|
...(signal ? { signal } : {}),
|
|
241
375
|
});
|
|
376
|
+
const responseText = await response.text();
|
|
377
|
+
onResponse?.(response);
|
|
242
378
|
if (!response.ok) {
|
|
243
|
-
|
|
379
|
+
const error = cliBridgeError(safeJson(responseText));
|
|
380
|
+
if (error?.type === "run_cancelled") {
|
|
381
|
+
throw new CliBridgeRunCancelledError(cliBridgeErrorMessage(error));
|
|
382
|
+
}
|
|
383
|
+
throw new Error(`cli-bridge replay result ${response.status}: ${responseText}`);
|
|
244
384
|
}
|
|
245
|
-
|
|
246
|
-
const
|
|
247
|
-
if (
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
385
|
+
const parsed = safeJson(responseText);
|
|
386
|
+
const error = cliBridgeError(parsed);
|
|
387
|
+
if (error) {
|
|
388
|
+
if (error.type === "run_cancelled") {
|
|
389
|
+
throw new CliBridgeRunCancelledError(cliBridgeErrorMessage(error));
|
|
390
|
+
}
|
|
391
|
+
throw new Error(`cli-bridge replay result failed: ${cliBridgeErrorMessage(error)}`);
|
|
251
392
|
}
|
|
252
393
|
const choice = Array.isArray(parsed?.choices) ? parsed.choices[0] : undefined;
|
|
253
394
|
const message = choice?.message && typeof choice.message === "object"
|
|
@@ -274,3 +415,12 @@ async function readFullCliBridgeResult(options, requestBody, transport, signal,
|
|
|
274
415
|
: { system_fingerprint: responseIdentity.system_fingerprint }),
|
|
275
416
|
};
|
|
276
417
|
}
|
|
418
|
+
function cliBridgeError(parsed) {
|
|
419
|
+
const error = parsed?.error;
|
|
420
|
+
return error && typeof error === "object" && !Array.isArray(error)
|
|
421
|
+
? error
|
|
422
|
+
: undefined;
|
|
423
|
+
}
|
|
424
|
+
function cliBridgeErrorMessage(error) {
|
|
425
|
+
return typeof error.message === "string" ? error.message : "cli-bridge replay failed";
|
|
426
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-provider-cli-bridge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "AgentEnvironmentProvider adapter for cli-bridge /v1/chat/completions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
"dist/index.d.ts",
|
|
27
27
|
"dist/index.js",
|
|
28
|
+
"dist/observation.d.ts",
|
|
29
|
+
"dist/observation.js",
|
|
28
30
|
"dist/provider-options.d.ts",
|
|
29
31
|
"dist/provider-options.js",
|
|
30
32
|
"dist/retained-control.d.ts",
|
|
@@ -47,7 +49,7 @@
|
|
|
47
49
|
"LICENSE"
|
|
48
50
|
],
|
|
49
51
|
"dependencies": {
|
|
50
|
-
"@tangle-network/agent-interface": "0.
|
|
52
|
+
"@tangle-network/agent-interface": "0.52.0",
|
|
51
53
|
"undici": "7.29.0"
|
|
52
54
|
},
|
|
53
55
|
"devDependencies": {
|