@dudousxd/nestjs-agent-opencode 0.1.2 → 0.2.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 +34 -1
- package/dist/durable/index.cjs +344 -74
- package/dist/durable/index.cjs.map +1 -1
- package/dist/durable/index.d.cts +1 -1
- package/dist/durable/index.d.ts +1 -1
- package/dist/durable/index.js +345 -75
- package/dist/durable/index.js.map +1 -1
- package/dist/{engine-Bij6AdoF.d.cts → engine-0YkBLWZR.d.cts} +154 -19
- package/dist/{engine-Bij6AdoF.d.ts → engine-0YkBLWZR.d.ts} +154 -19
- package/dist/index.cjs +343 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +340 -71
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AgentDepsFactory, ChatQueueService, AgentEngine } from '@dudousxd/nestjs-agent';
|
|
2
2
|
import { ConflictException, Logger, OnApplicationShutdown, Type, InjectionToken, Provider } from '@nestjs/common';
|
|
3
|
-
import { ElicitationRequest, AgentRunInput, SinkWriter, AgentStore, ApprovalRequirement, AgentUiComponent, HumanReply, Actor, StoredMessage, ToolRegistry, TokenStreamSink, SkillsConfig, MemoryConfig, RolesPolicy, RememberToolInput, AiToolCtx } from '@dudousxd/nestjs-agent-core';
|
|
3
|
+
import { ElicitationRequest, CostSource, AgentRunInput, SinkWriter, AgentStore, ApprovalRequirement, MessageUsage, AgentUiComponent, HumanReply, Actor, StoredMessage, ToolRegistry, TokenStreamSink, SkillsConfig, MemoryConfig, AgentPricingStore, PriceCatalogOptions, RolesPolicy, RememberToolInput, AiToolCtx } from '@dudousxd/nestjs-agent-core';
|
|
4
4
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
5
5
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
6
6
|
|
|
@@ -40,6 +40,9 @@ interface OpenCodeClient {
|
|
|
40
40
|
metadata?: {
|
|
41
41
|
readonly [key: string]: OpenCodeJson;
|
|
42
42
|
};
|
|
43
|
+
/** What the session spent so far, every model call OpenCode made for it (the title too). */
|
|
44
|
+
cost?: number;
|
|
45
|
+
tokens?: OpenCodeTokens;
|
|
43
46
|
}>;
|
|
44
47
|
/** Resolves when the session goes idle. Optional: a safety net for a missed terminal event. */
|
|
45
48
|
wait?(args: {
|
|
@@ -204,6 +207,16 @@ interface OpenCodeFormField {
|
|
|
204
207
|
/** The user may type their own answer instead of picking one of `options`. */
|
|
205
208
|
custom?: boolean;
|
|
206
209
|
}
|
|
210
|
+
/** A token count as OpenCode reports it: `input` is the uncached input, the cache beside it. */
|
|
211
|
+
interface OpenCodeTokens {
|
|
212
|
+
input: number;
|
|
213
|
+
output: number;
|
|
214
|
+
reasoning?: number;
|
|
215
|
+
cache?: {
|
|
216
|
+
read: number;
|
|
217
|
+
write: number;
|
|
218
|
+
};
|
|
219
|
+
}
|
|
207
220
|
|
|
208
221
|
/** How an OpenCode execution ended. */
|
|
209
222
|
type TurnOutcome = {
|
|
@@ -234,14 +247,46 @@ type PendingAsk = {
|
|
|
234
247
|
request: ElicitationRequest;
|
|
235
248
|
messageId?: string;
|
|
236
249
|
};
|
|
237
|
-
/**
|
|
250
|
+
/**
|
|
251
|
+
* What a turn spent. `inputTokens` is the whole input side, cached input included (as the library's
|
|
252
|
+
* `MessageUsage` counts it — OpenCode's own `tokens.input` leaves the cache out); `cacheReadTokens`,
|
|
253
|
+
* `cacheWriteTokens` and `reasoningTokens` are subsets. `costUsd` sums every priced call.
|
|
254
|
+
*/
|
|
255
|
+
interface OpenCodeUsage {
|
|
256
|
+
inputTokens: number;
|
|
257
|
+
outputTokens: number;
|
|
258
|
+
cacheReadTokens: number;
|
|
259
|
+
cacheWriteTokens: number;
|
|
260
|
+
reasoningTokens: number;
|
|
261
|
+
costUsd: number;
|
|
262
|
+
}
|
|
263
|
+
declare function emptyUsage(): OpenCodeUsage;
|
|
264
|
+
/** `a + b`; a missing side (a milestone journaled before usage travelled) counts as nothing. */
|
|
265
|
+
declare function addUsage(a: OpenCodeUsage | undefined, b: OpenCodeUsage | undefined): OpenCodeUsage;
|
|
266
|
+
/** The model a step ran on, as OpenCode names it (`session.step.started`). */
|
|
267
|
+
interface StepModel {
|
|
268
|
+
providerID: string;
|
|
269
|
+
id: string;
|
|
270
|
+
}
|
|
271
|
+
/** What a model call cost, and where the figure came from. */
|
|
272
|
+
interface StepCost {
|
|
273
|
+
costUsd?: number;
|
|
274
|
+
costSource?: CostSource;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Where a turn stands: it needs a person, or it is over. `usage` is what the turn spent since its
|
|
278
|
+
* previous milestone — journaled with the milestone, so a run resumed in another process still adds
|
|
279
|
+
* up what every process saw.
|
|
280
|
+
*/
|
|
238
281
|
type Milestone = {
|
|
239
282
|
kind: 'ask';
|
|
240
283
|
ask: PendingAsk;
|
|
241
284
|
timeoutMs?: number;
|
|
285
|
+
usage?: OpenCodeUsage;
|
|
242
286
|
} | {
|
|
243
287
|
kind: 'finished';
|
|
244
288
|
outcome: TurnOutcome;
|
|
289
|
+
usage?: OpenCodeUsage;
|
|
245
290
|
};
|
|
246
291
|
interface OpenCodeTurnArgs {
|
|
247
292
|
runId: string;
|
|
@@ -252,8 +297,19 @@ interface OpenCodeTurnArgs {
|
|
|
252
297
|
store: AgentStore;
|
|
253
298
|
/** What an action needs before it runs (the module's `ApprovalPolicy`). */
|
|
254
299
|
approvalFor: (action: string) => Promise<ApprovalRequirement>;
|
|
255
|
-
/** The model label usage is recorded under. */
|
|
300
|
+
/** The model label usage is recorded under until OpenCode names the step's model. */
|
|
256
301
|
modelLabel: string;
|
|
302
|
+
/**
|
|
303
|
+
* What a model call cost: OpenCode's reported figure, or the library's estimate. Omit → OpenCode's
|
|
304
|
+
* figure as reported.
|
|
305
|
+
*/
|
|
306
|
+
priceStep?: (step: {
|
|
307
|
+
model: StepModel | undefined;
|
|
308
|
+
usage: MessageUsage;
|
|
309
|
+
reportedCostUsd: number | undefined;
|
|
310
|
+
}) => Promise<StepCost>;
|
|
311
|
+
/** What the run spent before this turn object existed (an earlier process, an earlier session). */
|
|
312
|
+
carried?: OpenCodeUsage;
|
|
257
313
|
logger: Logger;
|
|
258
314
|
/**
|
|
259
315
|
* An action OpenCode was allowed to run (a person approved it, or the policy did): the approval
|
|
@@ -296,8 +352,15 @@ declare class OpenCodeTurn {
|
|
|
296
352
|
private readonly hidden;
|
|
297
353
|
private readonly milestones;
|
|
298
354
|
private waiting;
|
|
299
|
-
|
|
300
|
-
private
|
|
355
|
+
/** What this turn object saw spent, and how much of it a milestone already reported. */
|
|
356
|
+
private spent;
|
|
357
|
+
private reported;
|
|
358
|
+
private priced;
|
|
359
|
+
private model;
|
|
360
|
+
/** What the session had spent when this turn prompted it; what OpenCode reported since. */
|
|
361
|
+
private baseline;
|
|
362
|
+
private readonly seen;
|
|
363
|
+
private compacted;
|
|
301
364
|
private stepOpen;
|
|
302
365
|
private sawText;
|
|
303
366
|
private separator;
|
|
@@ -306,6 +369,18 @@ declare class OpenCodeTurn {
|
|
|
306
369
|
private ended;
|
|
307
370
|
private stepError;
|
|
308
371
|
constructor(a: OpenCodeTurnArgs);
|
|
372
|
+
/**
|
|
373
|
+
* What the session had spent before this turn prompted it (`session.get`). When the execution
|
|
374
|
+
* ends, what the session spent since that this turn's events did not report — the title OpenCode
|
|
375
|
+
* generates, a compaction: OpenCode records those calls on the session without streaming them — is
|
|
376
|
+
* recorded as a usage row of its own.
|
|
377
|
+
*/
|
|
378
|
+
setBaseline(info: {
|
|
379
|
+
cost?: number;
|
|
380
|
+
tokens?: OpenCodeTokens;
|
|
381
|
+
} | undefined): void;
|
|
382
|
+
/** What the run spent so far: carried from before this turn object, plus what it saw. */
|
|
383
|
+
totalUsage(): OpenCodeUsage;
|
|
309
384
|
get sessionId(): string;
|
|
310
385
|
get finished(): boolean;
|
|
311
386
|
/** Feed one of the session's events. */
|
|
@@ -348,12 +423,19 @@ declare class OpenCodeTurn {
|
|
|
348
423
|
private innerCalls;
|
|
349
424
|
private onEvent;
|
|
350
425
|
private settleTool;
|
|
426
|
+
private modelId;
|
|
427
|
+
/** One model call's usage and cost, into the ledger and the run's total. */
|
|
428
|
+
private spend;
|
|
429
|
+
/** `session.usage.recorded`: a call OpenCode made besides the steps (the title, a compaction). */
|
|
430
|
+
private usageRecorded;
|
|
351
431
|
private stepEnded;
|
|
352
432
|
/**
|
|
353
433
|
* Persist what the turn produced since the last flush as one assistant message — the message a
|
|
354
434
|
* call put to a person hangs on, or the turn's last one. Returns its id.
|
|
355
435
|
*/
|
|
356
436
|
private flush;
|
|
437
|
+
/** The run's usage as its last message carries it: the whole run, cache tokens included. */
|
|
438
|
+
private messageUsage;
|
|
357
439
|
/** A request recorded by an earlier process (a turn resumed after a restart). */
|
|
358
440
|
private alreadyRecorded;
|
|
359
441
|
/** The persisted assistant message carrying call `id`, so its result lands on the same message. */
|
|
@@ -363,8 +445,16 @@ declare class OpenCodeTurn {
|
|
|
363
445
|
private onForm;
|
|
364
446
|
private answered;
|
|
365
447
|
private addResult;
|
|
448
|
+
/** What the session spent since the baseline that no event of this turn reported. */
|
|
449
|
+
private unreported;
|
|
366
450
|
private end;
|
|
367
451
|
}
|
|
452
|
+
/**
|
|
453
|
+
* OpenCode's token counts as the library's `MessageUsage`. OpenCode reports the uncached input in
|
|
454
|
+
* `input` and the cache reads and writes beside it; the library counts the whole input side in
|
|
455
|
+
* `inputTokens`, the cache counts being subsets of it.
|
|
456
|
+
*/
|
|
457
|
+
declare function usageOf(tokens: any): MessageUsage;
|
|
368
458
|
|
|
369
459
|
/**
|
|
370
460
|
* Where a turn runs and how its OpenCode session is set up — the part only the host knows. The
|
|
@@ -471,11 +561,12 @@ interface OpenCodeRunResult {
|
|
|
471
561
|
text: string;
|
|
472
562
|
/** The run's assistant messages, as stored. */
|
|
473
563
|
messages: StoredMessage[];
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
564
|
+
/**
|
|
565
|
+
* What the run spent, over every model call OpenCode made for it (its steps, the title, a
|
|
566
|
+
* compaction) and every process that ran a part of it. `inputTokens` counts cached input too;
|
|
567
|
+
* `cacheReadTokens`/`cacheWriteTokens` are subsets of it.
|
|
568
|
+
*/
|
|
569
|
+
usage: OpenCodeUsage;
|
|
479
570
|
durationMs: number;
|
|
480
571
|
}
|
|
481
572
|
/** See {@link OpenCodeHost.beforeSettle}. */
|
|
@@ -648,6 +739,19 @@ interface OpenCodeEngineSettings {
|
|
|
648
739
|
* parked on a person is not observing: this bounds one stretch of OpenCode working on its own.
|
|
649
740
|
*/
|
|
650
741
|
turnTimeoutMs?: number;
|
|
742
|
+
/**
|
|
743
|
+
* Whose figure a model call is recorded at. OpenCode prices each call itself, off its model
|
|
744
|
+
* catalog (the `cost` its config declares, else models.dev's list price):
|
|
745
|
+
*
|
|
746
|
+
* - `'reported'` (default) — OpenCode's figure when it has one (`cost_source` `'provider'`); a call
|
|
747
|
+
* OpenCode priced at 0 (no price for the model) is estimated from the library's price instead
|
|
748
|
+
* (`priceCatalog`, the pricing store, the built-in GovCloud Bedrock table, models.dev;
|
|
749
|
+
* `cost_source` `'estimate'`).
|
|
750
|
+
* - `'estimate'` — the library's price whenever it has one, OpenCode's figure otherwise. For
|
|
751
|
+
* models OpenCode prices at a list price that is not yours (Bedrock in GovCloud, a negotiated
|
|
752
|
+
* rate) when you would rather not declare `cost` in OpenCode's config.
|
|
753
|
+
*/
|
|
754
|
+
cost?: 'reported' | 'estimate';
|
|
651
755
|
}
|
|
652
756
|
/** A thread's session, as the steps of a turn pass it along (and a durable run journals it). */
|
|
653
757
|
interface SessionHandle {
|
|
@@ -699,7 +803,20 @@ declare class OpenCodeTurns implements OnApplicationShutdown {
|
|
|
699
803
|
private readonly spent;
|
|
700
804
|
/** When the tools endpoint was last registered for a location (`server|boot|directory|actor`). */
|
|
701
805
|
private readonly toolsIssued;
|
|
702
|
-
constructor(host: OpenCodeHost, sessions: OpenCodeSessionStore, settings: OpenCodeEngineSettings, store: AgentStore, sink: TokenStreamSink, deps: AgentDepsFactory, registry: ToolRegistry, skills?: SkillsConfig | undefined, memory?: MemoryConfig | undefined, queue?: ChatQueueService | undefined, toolsTokens?: (OpenCodeToolsTokens | null) | undefined
|
|
806
|
+
constructor(host: OpenCodeHost, sessions: OpenCodeSessionStore, settings: OpenCodeEngineSettings, store: AgentStore, sink: TokenStreamSink, deps: AgentDepsFactory, registry: ToolRegistry, skills?: SkillsConfig | undefined, memory?: MemoryConfig | undefined, queue?: ChatQueueService | undefined, toolsTokens?: (OpenCodeToolsTokens | null) | undefined, pricingStore?: AgentPricingStore, agentOptions?: {
|
|
807
|
+
priceCatalog?: PriceCatalogOptions | false;
|
|
808
|
+
});
|
|
809
|
+
private readonly prices;
|
|
810
|
+
/**
|
|
811
|
+
* What a model call OpenCode made cost, by the same rule the library's loop records its own steps
|
|
812
|
+
* at: a reported figure wins, else an estimate off the model's price — see
|
|
813
|
+
* {@link OpenCodeEngineSettings.cost}.
|
|
814
|
+
*/
|
|
815
|
+
priceStep(step: {
|
|
816
|
+
model: StepModel | undefined;
|
|
817
|
+
usage: MessageUsage;
|
|
818
|
+
reportedCostUsd: number | undefined;
|
|
819
|
+
}): Promise<StepCost>;
|
|
703
820
|
/** The tools server's name in OpenCode. */
|
|
704
821
|
get toolsServer(): string;
|
|
705
822
|
/** The roles policy a turn's tools are gated by (the agent's own). */
|
|
@@ -784,20 +901,25 @@ declare class OpenCodeTurns implements OnApplicationShutdown {
|
|
|
784
901
|
*/
|
|
785
902
|
private addTools;
|
|
786
903
|
/** Start listening to the session (so nothing it says is missed), then send the user message. */
|
|
787
|
-
prompt(runId: string, input: AgentRunInput, handle: SessionHandle): Promise<void>;
|
|
904
|
+
prompt(runId: string, input: AgentRunInput, handle: SessionHandle, spent?: OpenCodeUsage): Promise<void>;
|
|
788
905
|
/**
|
|
789
906
|
* Wait for the turn's next milestone. In a process that was not following the turn (a resumed
|
|
790
907
|
* durable run), the turn is rebuilt and first catches up on requests OpenCode raised meanwhile;
|
|
791
908
|
* `session.wait` is the safety net for a terminal event that was missed.
|
|
909
|
+
*
|
|
910
|
+
* `spent` is what the run spent before (the sum of the `usage` of its earlier milestones): a turn
|
|
911
|
+
* rebuilt here starts from it, so the answer it persists carries the whole run's usage.
|
|
792
912
|
*/
|
|
793
|
-
observe(runId: string, input: AgentRunInput, handle: SessionHandle): Promise<Milestone>;
|
|
913
|
+
observe(runId: string, input: AgentRunInput, handle: SessionHandle, spent?: OpenCodeUsage): Promise<Milestone>;
|
|
794
914
|
/**
|
|
795
915
|
* Hand a person's answer back to OpenCode. When the server restarted while the turn waited, the
|
|
796
916
|
* request is gone with it: a new session is opened, told what the person decided, and prompted
|
|
797
917
|
* to go on.
|
|
798
918
|
*/
|
|
799
|
-
reply(runId: string, input: AgentRunInput, handle: SessionHandle, ask: PendingAsk, reply: HumanReply): Promise<SessionHandle>;
|
|
919
|
+
reply(runId: string, input: AgentRunInput, handle: SessionHandle, ask: PendingAsk, reply: HumanReply, spent?: OpenCodeUsage): Promise<SessionHandle>;
|
|
800
920
|
private continueAfterRestart;
|
|
921
|
+
/** What a session spent so far (`session.get`), or nothing when OpenCode does not say. */
|
|
922
|
+
private sessionUsage;
|
|
801
923
|
/** Interrupt the thread's session (cancel). */
|
|
802
924
|
interrupt(input: AgentRunInput): Promise<void>;
|
|
803
925
|
private ensureLive;
|
|
@@ -807,7 +929,11 @@ declare class OpenCodeTurns implements OnApplicationShutdown {
|
|
|
807
929
|
private forget;
|
|
808
930
|
/** A person was asked something: tell the host (cards in other channels, wake-ups). */
|
|
809
931
|
private reached;
|
|
810
|
-
/**
|
|
932
|
+
/**
|
|
933
|
+
* What the run produced, as the host's settle hooks see it. `usage` is what the run spent — the
|
|
934
|
+
* runner's sum of its milestones' usage, which a resumed run reads back from its journal — else
|
|
935
|
+
* what the turn this process follows saw.
|
|
936
|
+
*/
|
|
811
937
|
private runResult;
|
|
812
938
|
/**
|
|
813
939
|
* The host's last word on the answer before the stream ends: components to append (a guardrail
|
|
@@ -816,9 +942,18 @@ declare class OpenCodeTurns implements OnApplicationShutdown {
|
|
|
816
942
|
private amend;
|
|
817
943
|
/** Delivery, telemetry, spend: after the run settled. Errors are the host's, never the run's. */
|
|
818
944
|
private settled;
|
|
819
|
-
/**
|
|
820
|
-
|
|
821
|
-
|
|
945
|
+
/**
|
|
946
|
+
* What the run spent: the runner's sum of its milestones, or what the turn this process follows
|
|
947
|
+
* saw (which starts from that sum) when it saw more — a run that failed or was cancelled between
|
|
948
|
+
* two milestones.
|
|
949
|
+
*/
|
|
950
|
+
private spentBy;
|
|
951
|
+
/**
|
|
952
|
+
* End the run's stream and bookkeeping for how its execution ended. `spent` is what the run spent
|
|
953
|
+
* (the sum of its milestones' `usage`); omit → what the turn this process follows saw.
|
|
954
|
+
*/
|
|
955
|
+
settle(runId: string, input: AgentRunInput, outcome: TurnOutcome, durationMs: number, spent?: OpenCodeUsage): Promise<void>;
|
|
956
|
+
settleFailed(runId: string, input: AgentRunInput, error: string, durationMs?: number, spent?: OpenCodeUsage): Promise<void>;
|
|
822
957
|
/** Starts the next queued message of the thread; set by the runner (it owns `start`). */
|
|
823
958
|
startNext: ((next: AgentRunInput, runId: string) => Promise<unknown>) | undefined;
|
|
824
959
|
/** As `InlineAgentRunner`: hand the thread to its next queued message, and say so on the stream. */
|
|
@@ -846,4 +981,4 @@ declare function openCodeControllers(options: OpenCodeEngineSettings): Type<obje
|
|
|
846
981
|
/** The providers every OpenCode engine needs: host, session store, settings and the turn steps. */
|
|
847
982
|
declare function openCodeProviders(options: OpenCodeEngineOptions): Provider[];
|
|
848
983
|
|
|
849
|
-
export { OpenCodeTurn as A, type OpenCodeTurnContext as B,
|
|
984
|
+
export { OpenCodeTurn as A, type OpenCodeTurnContext as B, type OpenCodeUsage as C, type StepCost as D, type StepModel as E, addUsage as F, emptyUsage as G, keyValueOpenCodeSessionStore as H, InMemoryOpenCodeSessionStore as I, openCode as J, openCodeControllers as K, openCodeProviders as L, type Milestone as M, usageOf as N, OpenCodeTurns as O, type PendingAsk as P, type SessionHandle as S, type TurnOutcome as T, type OpenCodeEngineSettings as a, type OpenCodeHost as b, type OpenCodeEngineOptions as c, type OpenCodeClient as d, type OpenCodeEvent as e, type OpenCodeForm as f, type OpenCodeFormValue as g, type OpenCodeFormField as h, OpenCodeMcpEndpoint as i, type OpenCodeAmendment as j, type OpenCodeCallContext as k, type OpenCodeKeyValue as l, type OpenCodeModelRef as m, type OpenCodePermissionRequest as n, type OpenCodePermissionRule as o, OpenCodeReplyMismatchError as p, type OpenCodeRunResult as q, type OpenCodeServer as r, type OpenCodeSessionCreate as s, type OpenCodeSessionRef as t, type OpenCodeSessionStore as u, type OpenCodeToolCall as v, OpenCodeToolRefusedError as w, type OpenCodeToolsClaims as x, type OpenCodeToolsOptions as y, OpenCodeToolsTokens as z };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AgentDepsFactory, ChatQueueService, AgentEngine } from '@dudousxd/nestjs-agent';
|
|
2
2
|
import { ConflictException, Logger, OnApplicationShutdown, Type, InjectionToken, Provider } from '@nestjs/common';
|
|
3
|
-
import { ElicitationRequest, AgentRunInput, SinkWriter, AgentStore, ApprovalRequirement, AgentUiComponent, HumanReply, Actor, StoredMessage, ToolRegistry, TokenStreamSink, SkillsConfig, MemoryConfig, RolesPolicy, RememberToolInput, AiToolCtx } from '@dudousxd/nestjs-agent-core';
|
|
3
|
+
import { ElicitationRequest, CostSource, AgentRunInput, SinkWriter, AgentStore, ApprovalRequirement, MessageUsage, AgentUiComponent, HumanReply, Actor, StoredMessage, ToolRegistry, TokenStreamSink, SkillsConfig, MemoryConfig, AgentPricingStore, PriceCatalogOptions, RolesPolicy, RememberToolInput, AiToolCtx } from '@dudousxd/nestjs-agent-core';
|
|
4
4
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
5
5
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
6
6
|
|
|
@@ -40,6 +40,9 @@ interface OpenCodeClient {
|
|
|
40
40
|
metadata?: {
|
|
41
41
|
readonly [key: string]: OpenCodeJson;
|
|
42
42
|
};
|
|
43
|
+
/** What the session spent so far, every model call OpenCode made for it (the title too). */
|
|
44
|
+
cost?: number;
|
|
45
|
+
tokens?: OpenCodeTokens;
|
|
43
46
|
}>;
|
|
44
47
|
/** Resolves when the session goes idle. Optional: a safety net for a missed terminal event. */
|
|
45
48
|
wait?(args: {
|
|
@@ -204,6 +207,16 @@ interface OpenCodeFormField {
|
|
|
204
207
|
/** The user may type their own answer instead of picking one of `options`. */
|
|
205
208
|
custom?: boolean;
|
|
206
209
|
}
|
|
210
|
+
/** A token count as OpenCode reports it: `input` is the uncached input, the cache beside it. */
|
|
211
|
+
interface OpenCodeTokens {
|
|
212
|
+
input: number;
|
|
213
|
+
output: number;
|
|
214
|
+
reasoning?: number;
|
|
215
|
+
cache?: {
|
|
216
|
+
read: number;
|
|
217
|
+
write: number;
|
|
218
|
+
};
|
|
219
|
+
}
|
|
207
220
|
|
|
208
221
|
/** How an OpenCode execution ended. */
|
|
209
222
|
type TurnOutcome = {
|
|
@@ -234,14 +247,46 @@ type PendingAsk = {
|
|
|
234
247
|
request: ElicitationRequest;
|
|
235
248
|
messageId?: string;
|
|
236
249
|
};
|
|
237
|
-
/**
|
|
250
|
+
/**
|
|
251
|
+
* What a turn spent. `inputTokens` is the whole input side, cached input included (as the library's
|
|
252
|
+
* `MessageUsage` counts it — OpenCode's own `tokens.input` leaves the cache out); `cacheReadTokens`,
|
|
253
|
+
* `cacheWriteTokens` and `reasoningTokens` are subsets. `costUsd` sums every priced call.
|
|
254
|
+
*/
|
|
255
|
+
interface OpenCodeUsage {
|
|
256
|
+
inputTokens: number;
|
|
257
|
+
outputTokens: number;
|
|
258
|
+
cacheReadTokens: number;
|
|
259
|
+
cacheWriteTokens: number;
|
|
260
|
+
reasoningTokens: number;
|
|
261
|
+
costUsd: number;
|
|
262
|
+
}
|
|
263
|
+
declare function emptyUsage(): OpenCodeUsage;
|
|
264
|
+
/** `a + b`; a missing side (a milestone journaled before usage travelled) counts as nothing. */
|
|
265
|
+
declare function addUsage(a: OpenCodeUsage | undefined, b: OpenCodeUsage | undefined): OpenCodeUsage;
|
|
266
|
+
/** The model a step ran on, as OpenCode names it (`session.step.started`). */
|
|
267
|
+
interface StepModel {
|
|
268
|
+
providerID: string;
|
|
269
|
+
id: string;
|
|
270
|
+
}
|
|
271
|
+
/** What a model call cost, and where the figure came from. */
|
|
272
|
+
interface StepCost {
|
|
273
|
+
costUsd?: number;
|
|
274
|
+
costSource?: CostSource;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Where a turn stands: it needs a person, or it is over. `usage` is what the turn spent since its
|
|
278
|
+
* previous milestone — journaled with the milestone, so a run resumed in another process still adds
|
|
279
|
+
* up what every process saw.
|
|
280
|
+
*/
|
|
238
281
|
type Milestone = {
|
|
239
282
|
kind: 'ask';
|
|
240
283
|
ask: PendingAsk;
|
|
241
284
|
timeoutMs?: number;
|
|
285
|
+
usage?: OpenCodeUsage;
|
|
242
286
|
} | {
|
|
243
287
|
kind: 'finished';
|
|
244
288
|
outcome: TurnOutcome;
|
|
289
|
+
usage?: OpenCodeUsage;
|
|
245
290
|
};
|
|
246
291
|
interface OpenCodeTurnArgs {
|
|
247
292
|
runId: string;
|
|
@@ -252,8 +297,19 @@ interface OpenCodeTurnArgs {
|
|
|
252
297
|
store: AgentStore;
|
|
253
298
|
/** What an action needs before it runs (the module's `ApprovalPolicy`). */
|
|
254
299
|
approvalFor: (action: string) => Promise<ApprovalRequirement>;
|
|
255
|
-
/** The model label usage is recorded under. */
|
|
300
|
+
/** The model label usage is recorded under until OpenCode names the step's model. */
|
|
256
301
|
modelLabel: string;
|
|
302
|
+
/**
|
|
303
|
+
* What a model call cost: OpenCode's reported figure, or the library's estimate. Omit → OpenCode's
|
|
304
|
+
* figure as reported.
|
|
305
|
+
*/
|
|
306
|
+
priceStep?: (step: {
|
|
307
|
+
model: StepModel | undefined;
|
|
308
|
+
usage: MessageUsage;
|
|
309
|
+
reportedCostUsd: number | undefined;
|
|
310
|
+
}) => Promise<StepCost>;
|
|
311
|
+
/** What the run spent before this turn object existed (an earlier process, an earlier session). */
|
|
312
|
+
carried?: OpenCodeUsage;
|
|
257
313
|
logger: Logger;
|
|
258
314
|
/**
|
|
259
315
|
* An action OpenCode was allowed to run (a person approved it, or the policy did): the approval
|
|
@@ -296,8 +352,15 @@ declare class OpenCodeTurn {
|
|
|
296
352
|
private readonly hidden;
|
|
297
353
|
private readonly milestones;
|
|
298
354
|
private waiting;
|
|
299
|
-
|
|
300
|
-
private
|
|
355
|
+
/** What this turn object saw spent, and how much of it a milestone already reported. */
|
|
356
|
+
private spent;
|
|
357
|
+
private reported;
|
|
358
|
+
private priced;
|
|
359
|
+
private model;
|
|
360
|
+
/** What the session had spent when this turn prompted it; what OpenCode reported since. */
|
|
361
|
+
private baseline;
|
|
362
|
+
private readonly seen;
|
|
363
|
+
private compacted;
|
|
301
364
|
private stepOpen;
|
|
302
365
|
private sawText;
|
|
303
366
|
private separator;
|
|
@@ -306,6 +369,18 @@ declare class OpenCodeTurn {
|
|
|
306
369
|
private ended;
|
|
307
370
|
private stepError;
|
|
308
371
|
constructor(a: OpenCodeTurnArgs);
|
|
372
|
+
/**
|
|
373
|
+
* What the session had spent before this turn prompted it (`session.get`). When the execution
|
|
374
|
+
* ends, what the session spent since that this turn's events did not report — the title OpenCode
|
|
375
|
+
* generates, a compaction: OpenCode records those calls on the session without streaming them — is
|
|
376
|
+
* recorded as a usage row of its own.
|
|
377
|
+
*/
|
|
378
|
+
setBaseline(info: {
|
|
379
|
+
cost?: number;
|
|
380
|
+
tokens?: OpenCodeTokens;
|
|
381
|
+
} | undefined): void;
|
|
382
|
+
/** What the run spent so far: carried from before this turn object, plus what it saw. */
|
|
383
|
+
totalUsage(): OpenCodeUsage;
|
|
309
384
|
get sessionId(): string;
|
|
310
385
|
get finished(): boolean;
|
|
311
386
|
/** Feed one of the session's events. */
|
|
@@ -348,12 +423,19 @@ declare class OpenCodeTurn {
|
|
|
348
423
|
private innerCalls;
|
|
349
424
|
private onEvent;
|
|
350
425
|
private settleTool;
|
|
426
|
+
private modelId;
|
|
427
|
+
/** One model call's usage and cost, into the ledger and the run's total. */
|
|
428
|
+
private spend;
|
|
429
|
+
/** `session.usage.recorded`: a call OpenCode made besides the steps (the title, a compaction). */
|
|
430
|
+
private usageRecorded;
|
|
351
431
|
private stepEnded;
|
|
352
432
|
/**
|
|
353
433
|
* Persist what the turn produced since the last flush as one assistant message — the message a
|
|
354
434
|
* call put to a person hangs on, or the turn's last one. Returns its id.
|
|
355
435
|
*/
|
|
356
436
|
private flush;
|
|
437
|
+
/** The run's usage as its last message carries it: the whole run, cache tokens included. */
|
|
438
|
+
private messageUsage;
|
|
357
439
|
/** A request recorded by an earlier process (a turn resumed after a restart). */
|
|
358
440
|
private alreadyRecorded;
|
|
359
441
|
/** The persisted assistant message carrying call `id`, so its result lands on the same message. */
|
|
@@ -363,8 +445,16 @@ declare class OpenCodeTurn {
|
|
|
363
445
|
private onForm;
|
|
364
446
|
private answered;
|
|
365
447
|
private addResult;
|
|
448
|
+
/** What the session spent since the baseline that no event of this turn reported. */
|
|
449
|
+
private unreported;
|
|
366
450
|
private end;
|
|
367
451
|
}
|
|
452
|
+
/**
|
|
453
|
+
* OpenCode's token counts as the library's `MessageUsage`. OpenCode reports the uncached input in
|
|
454
|
+
* `input` and the cache reads and writes beside it; the library counts the whole input side in
|
|
455
|
+
* `inputTokens`, the cache counts being subsets of it.
|
|
456
|
+
*/
|
|
457
|
+
declare function usageOf(tokens: any): MessageUsage;
|
|
368
458
|
|
|
369
459
|
/**
|
|
370
460
|
* Where a turn runs and how its OpenCode session is set up — the part only the host knows. The
|
|
@@ -471,11 +561,12 @@ interface OpenCodeRunResult {
|
|
|
471
561
|
text: string;
|
|
472
562
|
/** The run's assistant messages, as stored. */
|
|
473
563
|
messages: StoredMessage[];
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
564
|
+
/**
|
|
565
|
+
* What the run spent, over every model call OpenCode made for it (its steps, the title, a
|
|
566
|
+
* compaction) and every process that ran a part of it. `inputTokens` counts cached input too;
|
|
567
|
+
* `cacheReadTokens`/`cacheWriteTokens` are subsets of it.
|
|
568
|
+
*/
|
|
569
|
+
usage: OpenCodeUsage;
|
|
479
570
|
durationMs: number;
|
|
480
571
|
}
|
|
481
572
|
/** See {@link OpenCodeHost.beforeSettle}. */
|
|
@@ -648,6 +739,19 @@ interface OpenCodeEngineSettings {
|
|
|
648
739
|
* parked on a person is not observing: this bounds one stretch of OpenCode working on its own.
|
|
649
740
|
*/
|
|
650
741
|
turnTimeoutMs?: number;
|
|
742
|
+
/**
|
|
743
|
+
* Whose figure a model call is recorded at. OpenCode prices each call itself, off its model
|
|
744
|
+
* catalog (the `cost` its config declares, else models.dev's list price):
|
|
745
|
+
*
|
|
746
|
+
* - `'reported'` (default) — OpenCode's figure when it has one (`cost_source` `'provider'`); a call
|
|
747
|
+
* OpenCode priced at 0 (no price for the model) is estimated from the library's price instead
|
|
748
|
+
* (`priceCatalog`, the pricing store, the built-in GovCloud Bedrock table, models.dev;
|
|
749
|
+
* `cost_source` `'estimate'`).
|
|
750
|
+
* - `'estimate'` — the library's price whenever it has one, OpenCode's figure otherwise. For
|
|
751
|
+
* models OpenCode prices at a list price that is not yours (Bedrock in GovCloud, a negotiated
|
|
752
|
+
* rate) when you would rather not declare `cost` in OpenCode's config.
|
|
753
|
+
*/
|
|
754
|
+
cost?: 'reported' | 'estimate';
|
|
651
755
|
}
|
|
652
756
|
/** A thread's session, as the steps of a turn pass it along (and a durable run journals it). */
|
|
653
757
|
interface SessionHandle {
|
|
@@ -699,7 +803,20 @@ declare class OpenCodeTurns implements OnApplicationShutdown {
|
|
|
699
803
|
private readonly spent;
|
|
700
804
|
/** When the tools endpoint was last registered for a location (`server|boot|directory|actor`). */
|
|
701
805
|
private readonly toolsIssued;
|
|
702
|
-
constructor(host: OpenCodeHost, sessions: OpenCodeSessionStore, settings: OpenCodeEngineSettings, store: AgentStore, sink: TokenStreamSink, deps: AgentDepsFactory, registry: ToolRegistry, skills?: SkillsConfig | undefined, memory?: MemoryConfig | undefined, queue?: ChatQueueService | undefined, toolsTokens?: (OpenCodeToolsTokens | null) | undefined
|
|
806
|
+
constructor(host: OpenCodeHost, sessions: OpenCodeSessionStore, settings: OpenCodeEngineSettings, store: AgentStore, sink: TokenStreamSink, deps: AgentDepsFactory, registry: ToolRegistry, skills?: SkillsConfig | undefined, memory?: MemoryConfig | undefined, queue?: ChatQueueService | undefined, toolsTokens?: (OpenCodeToolsTokens | null) | undefined, pricingStore?: AgentPricingStore, agentOptions?: {
|
|
807
|
+
priceCatalog?: PriceCatalogOptions | false;
|
|
808
|
+
});
|
|
809
|
+
private readonly prices;
|
|
810
|
+
/**
|
|
811
|
+
* What a model call OpenCode made cost, by the same rule the library's loop records its own steps
|
|
812
|
+
* at: a reported figure wins, else an estimate off the model's price — see
|
|
813
|
+
* {@link OpenCodeEngineSettings.cost}.
|
|
814
|
+
*/
|
|
815
|
+
priceStep(step: {
|
|
816
|
+
model: StepModel | undefined;
|
|
817
|
+
usage: MessageUsage;
|
|
818
|
+
reportedCostUsd: number | undefined;
|
|
819
|
+
}): Promise<StepCost>;
|
|
703
820
|
/** The tools server's name in OpenCode. */
|
|
704
821
|
get toolsServer(): string;
|
|
705
822
|
/** The roles policy a turn's tools are gated by (the agent's own). */
|
|
@@ -784,20 +901,25 @@ declare class OpenCodeTurns implements OnApplicationShutdown {
|
|
|
784
901
|
*/
|
|
785
902
|
private addTools;
|
|
786
903
|
/** Start listening to the session (so nothing it says is missed), then send the user message. */
|
|
787
|
-
prompt(runId: string, input: AgentRunInput, handle: SessionHandle): Promise<void>;
|
|
904
|
+
prompt(runId: string, input: AgentRunInput, handle: SessionHandle, spent?: OpenCodeUsage): Promise<void>;
|
|
788
905
|
/**
|
|
789
906
|
* Wait for the turn's next milestone. In a process that was not following the turn (a resumed
|
|
790
907
|
* durable run), the turn is rebuilt and first catches up on requests OpenCode raised meanwhile;
|
|
791
908
|
* `session.wait` is the safety net for a terminal event that was missed.
|
|
909
|
+
*
|
|
910
|
+
* `spent` is what the run spent before (the sum of the `usage` of its earlier milestones): a turn
|
|
911
|
+
* rebuilt here starts from it, so the answer it persists carries the whole run's usage.
|
|
792
912
|
*/
|
|
793
|
-
observe(runId: string, input: AgentRunInput, handle: SessionHandle): Promise<Milestone>;
|
|
913
|
+
observe(runId: string, input: AgentRunInput, handle: SessionHandle, spent?: OpenCodeUsage): Promise<Milestone>;
|
|
794
914
|
/**
|
|
795
915
|
* Hand a person's answer back to OpenCode. When the server restarted while the turn waited, the
|
|
796
916
|
* request is gone with it: a new session is opened, told what the person decided, and prompted
|
|
797
917
|
* to go on.
|
|
798
918
|
*/
|
|
799
|
-
reply(runId: string, input: AgentRunInput, handle: SessionHandle, ask: PendingAsk, reply: HumanReply): Promise<SessionHandle>;
|
|
919
|
+
reply(runId: string, input: AgentRunInput, handle: SessionHandle, ask: PendingAsk, reply: HumanReply, spent?: OpenCodeUsage): Promise<SessionHandle>;
|
|
800
920
|
private continueAfterRestart;
|
|
921
|
+
/** What a session spent so far (`session.get`), or nothing when OpenCode does not say. */
|
|
922
|
+
private sessionUsage;
|
|
801
923
|
/** Interrupt the thread's session (cancel). */
|
|
802
924
|
interrupt(input: AgentRunInput): Promise<void>;
|
|
803
925
|
private ensureLive;
|
|
@@ -807,7 +929,11 @@ declare class OpenCodeTurns implements OnApplicationShutdown {
|
|
|
807
929
|
private forget;
|
|
808
930
|
/** A person was asked something: tell the host (cards in other channels, wake-ups). */
|
|
809
931
|
private reached;
|
|
810
|
-
/**
|
|
932
|
+
/**
|
|
933
|
+
* What the run produced, as the host's settle hooks see it. `usage` is what the run spent — the
|
|
934
|
+
* runner's sum of its milestones' usage, which a resumed run reads back from its journal — else
|
|
935
|
+
* what the turn this process follows saw.
|
|
936
|
+
*/
|
|
811
937
|
private runResult;
|
|
812
938
|
/**
|
|
813
939
|
* The host's last word on the answer before the stream ends: components to append (a guardrail
|
|
@@ -816,9 +942,18 @@ declare class OpenCodeTurns implements OnApplicationShutdown {
|
|
|
816
942
|
private amend;
|
|
817
943
|
/** Delivery, telemetry, spend: after the run settled. Errors are the host's, never the run's. */
|
|
818
944
|
private settled;
|
|
819
|
-
/**
|
|
820
|
-
|
|
821
|
-
|
|
945
|
+
/**
|
|
946
|
+
* What the run spent: the runner's sum of its milestones, or what the turn this process follows
|
|
947
|
+
* saw (which starts from that sum) when it saw more — a run that failed or was cancelled between
|
|
948
|
+
* two milestones.
|
|
949
|
+
*/
|
|
950
|
+
private spentBy;
|
|
951
|
+
/**
|
|
952
|
+
* End the run's stream and bookkeeping for how its execution ended. `spent` is what the run spent
|
|
953
|
+
* (the sum of its milestones' `usage`); omit → what the turn this process follows saw.
|
|
954
|
+
*/
|
|
955
|
+
settle(runId: string, input: AgentRunInput, outcome: TurnOutcome, durationMs: number, spent?: OpenCodeUsage): Promise<void>;
|
|
956
|
+
settleFailed(runId: string, input: AgentRunInput, error: string, durationMs?: number, spent?: OpenCodeUsage): Promise<void>;
|
|
822
957
|
/** Starts the next queued message of the thread; set by the runner (it owns `start`). */
|
|
823
958
|
startNext: ((next: AgentRunInput, runId: string) => Promise<unknown>) | undefined;
|
|
824
959
|
/** As `InlineAgentRunner`: hand the thread to its next queued message, and say so on the stream. */
|
|
@@ -846,4 +981,4 @@ declare function openCodeControllers(options: OpenCodeEngineSettings): Type<obje
|
|
|
846
981
|
/** The providers every OpenCode engine needs: host, session store, settings and the turn steps. */
|
|
847
982
|
declare function openCodeProviders(options: OpenCodeEngineOptions): Provider[];
|
|
848
983
|
|
|
849
|
-
export { OpenCodeTurn as A, type OpenCodeTurnContext as B,
|
|
984
|
+
export { OpenCodeTurn as A, type OpenCodeTurnContext as B, type OpenCodeUsage as C, type StepCost as D, type StepModel as E, addUsage as F, emptyUsage as G, keyValueOpenCodeSessionStore as H, InMemoryOpenCodeSessionStore as I, openCode as J, openCodeControllers as K, openCodeProviders as L, type Milestone as M, usageOf as N, OpenCodeTurns as O, type PendingAsk as P, type SessionHandle as S, type TurnOutcome as T, type OpenCodeEngineSettings as a, type OpenCodeHost as b, type OpenCodeEngineOptions as c, type OpenCodeClient as d, type OpenCodeEvent as e, type OpenCodeForm as f, type OpenCodeFormValue as g, type OpenCodeFormField as h, OpenCodeMcpEndpoint as i, type OpenCodeAmendment as j, type OpenCodeCallContext as k, type OpenCodeKeyValue as l, type OpenCodeModelRef as m, type OpenCodePermissionRequest as n, type OpenCodePermissionRule as o, OpenCodeReplyMismatchError as p, type OpenCodeRunResult as q, type OpenCodeServer as r, type OpenCodeSessionCreate as s, type OpenCodeSessionRef as t, type OpenCodeSessionStore as u, type OpenCodeToolCall as v, OpenCodeToolRefusedError as w, type OpenCodeToolsClaims as x, type OpenCodeToolsOptions as y, OpenCodeToolsTokens as z };
|