@dudousxd/nestjs-agent-opencode 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -1
- package/dist/durable/index.cjs +268 -75
- 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 +269 -76
- package/dist/durable/index.js.map +1 -1
- package/dist/{engine-Bij6AdoF.d.cts → engine-JnBbcRxh.d.cts} +123 -19
- package/dist/{engine-Bij6AdoF.d.ts → engine-JnBbcRxh.d.ts} +123 -19
- package/dist/index.cjs +267 -72
- 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 +264 -72
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as OpenCodeClient, e as OpenCodeEvent, f as OpenCodeForm, g as OpenCodeFormValue, h as OpenCodeFormField, i as OpenCodeMcpEndpoint, O as OpenCodeTurns, a as OpenCodeEngineSettings } from './engine-
|
|
2
|
-
export { I as InMemoryOpenCodeSessionStore, M as Milestone, j as OpenCodeAmendment, k as OpenCodeCallContext, c as OpenCodeEngineOptions, b as OpenCodeHost, l as OpenCodeKeyValue, m as OpenCodeModelRef, n as OpenCodePermissionRequest, o as OpenCodePermissionRule, p as OpenCodeReplyMismatchError, q as OpenCodeRunResult, r as OpenCodeServer, s as OpenCodeSessionCreate, t as OpenCodeSessionRef, u as OpenCodeSessionStore, v as OpenCodeToolCall, w as OpenCodeToolRefusedError, x as OpenCodeToolsClaims, y as OpenCodeToolsOptions, z as OpenCodeToolsTokens, A as OpenCodeTurn, B as OpenCodeTurnContext, P as PendingAsk, S as SessionHandle, T as TurnOutcome,
|
|
1
|
+
import { d as OpenCodeClient, e as OpenCodeEvent, f as OpenCodeForm, g as OpenCodeFormValue, h as OpenCodeFormField, i as OpenCodeMcpEndpoint, O as OpenCodeTurns, a as OpenCodeEngineSettings } from './engine-JnBbcRxh.cjs';
|
|
2
|
+
export { I as InMemoryOpenCodeSessionStore, M as Milestone, j as OpenCodeAmendment, k as OpenCodeCallContext, c as OpenCodeEngineOptions, b as OpenCodeHost, l as OpenCodeKeyValue, m as OpenCodeModelRef, n as OpenCodePermissionRequest, o as OpenCodePermissionRule, p as OpenCodeReplyMismatchError, q as OpenCodeRunResult, r as OpenCodeServer, s as OpenCodeSessionCreate, t as OpenCodeSessionRef, u as OpenCodeSessionStore, v as OpenCodeToolCall, w as OpenCodeToolRefusedError, x as OpenCodeToolsClaims, y as OpenCodeToolsOptions, z as OpenCodeToolsTokens, A as OpenCodeTurn, B as OpenCodeTurnContext, C as OpenCodeUsage, P as PendingAsk, S as SessionHandle, D as StepCost, E as StepModel, T as TurnOutcome, F as addUsage, G as emptyUsage, H as keyValueOpenCodeSessionStore, J as openCode, K as openCodeControllers, L as openCodeProviders, N as usageOf } from './engine-JnBbcRxh.cjs';
|
|
3
3
|
import { ElicitationRequest, ElicitationQuestion, AgentRunner, AgentRunInput, AgentRunStartOptions, HumanReply } from '@dudousxd/nestjs-agent-core';
|
|
4
4
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
5
5
|
import '@dudousxd/nestjs-agent';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as OpenCodeClient, e as OpenCodeEvent, f as OpenCodeForm, g as OpenCodeFormValue, h as OpenCodeFormField, i as OpenCodeMcpEndpoint, O as OpenCodeTurns, a as OpenCodeEngineSettings } from './engine-
|
|
2
|
-
export { I as InMemoryOpenCodeSessionStore, M as Milestone, j as OpenCodeAmendment, k as OpenCodeCallContext, c as OpenCodeEngineOptions, b as OpenCodeHost, l as OpenCodeKeyValue, m as OpenCodeModelRef, n as OpenCodePermissionRequest, o as OpenCodePermissionRule, p as OpenCodeReplyMismatchError, q as OpenCodeRunResult, r as OpenCodeServer, s as OpenCodeSessionCreate, t as OpenCodeSessionRef, u as OpenCodeSessionStore, v as OpenCodeToolCall, w as OpenCodeToolRefusedError, x as OpenCodeToolsClaims, y as OpenCodeToolsOptions, z as OpenCodeToolsTokens, A as OpenCodeTurn, B as OpenCodeTurnContext, P as PendingAsk, S as SessionHandle, T as TurnOutcome,
|
|
1
|
+
import { d as OpenCodeClient, e as OpenCodeEvent, f as OpenCodeForm, g as OpenCodeFormValue, h as OpenCodeFormField, i as OpenCodeMcpEndpoint, O as OpenCodeTurns, a as OpenCodeEngineSettings } from './engine-JnBbcRxh.js';
|
|
2
|
+
export { I as InMemoryOpenCodeSessionStore, M as Milestone, j as OpenCodeAmendment, k as OpenCodeCallContext, c as OpenCodeEngineOptions, b as OpenCodeHost, l as OpenCodeKeyValue, m as OpenCodeModelRef, n as OpenCodePermissionRequest, o as OpenCodePermissionRule, p as OpenCodeReplyMismatchError, q as OpenCodeRunResult, r as OpenCodeServer, s as OpenCodeSessionCreate, t as OpenCodeSessionRef, u as OpenCodeSessionStore, v as OpenCodeToolCall, w as OpenCodeToolRefusedError, x as OpenCodeToolsClaims, y as OpenCodeToolsOptions, z as OpenCodeToolsTokens, A as OpenCodeTurn, B as OpenCodeTurnContext, C as OpenCodeUsage, P as PendingAsk, S as SessionHandle, D as StepCost, E as StepModel, T as TurnOutcome, F as addUsage, G as emptyUsage, H as keyValueOpenCodeSessionStore, J as openCode, K as openCodeControllers, L as openCodeProviders, N as usageOf } from './engine-JnBbcRxh.js';
|
|
3
3
|
import { ElicitationRequest, ElicitationQuestion, AgentRunner, AgentRunInput, AgentRunStartOptions, HumanReply } from '@dudousxd/nestjs-agent-core';
|
|
4
4
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
5
5
|
import '@dudousxd/nestjs-agent';
|
package/dist/index.js
CHANGED
|
@@ -239,6 +239,41 @@ function toFormAnswer(form, answers = {}) {
|
|
|
239
239
|
__name(toFormAnswer, "toFormAnswer");
|
|
240
240
|
|
|
241
241
|
// src/turn.ts
|
|
242
|
+
function emptyUsage() {
|
|
243
|
+
return {
|
|
244
|
+
inputTokens: 0,
|
|
245
|
+
outputTokens: 0,
|
|
246
|
+
cacheReadTokens: 0,
|
|
247
|
+
cacheWriteTokens: 0,
|
|
248
|
+
reasoningTokens: 0,
|
|
249
|
+
costUsd: 0
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
__name(emptyUsage, "emptyUsage");
|
|
253
|
+
function addUsage(a, b) {
|
|
254
|
+
const x = a ?? emptyUsage();
|
|
255
|
+
const y = b ?? emptyUsage();
|
|
256
|
+
return {
|
|
257
|
+
inputTokens: x.inputTokens + (y.inputTokens ?? 0),
|
|
258
|
+
outputTokens: x.outputTokens + (y.outputTokens ?? 0),
|
|
259
|
+
cacheReadTokens: (x.cacheReadTokens ?? 0) + (y.cacheReadTokens ?? 0),
|
|
260
|
+
cacheWriteTokens: (x.cacheWriteTokens ?? 0) + (y.cacheWriteTokens ?? 0),
|
|
261
|
+
reasoningTokens: (x.reasoningTokens ?? 0) + (y.reasoningTokens ?? 0),
|
|
262
|
+
costUsd: x.costUsd + (y.costUsd ?? 0)
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
__name(addUsage, "addUsage");
|
|
266
|
+
function subUsage(a, b) {
|
|
267
|
+
return {
|
|
268
|
+
inputTokens: a.inputTokens - b.inputTokens,
|
|
269
|
+
outputTokens: a.outputTokens - b.outputTokens,
|
|
270
|
+
cacheReadTokens: a.cacheReadTokens - b.cacheReadTokens,
|
|
271
|
+
cacheWriteTokens: a.cacheWriteTokens - b.cacheWriteTokens,
|
|
272
|
+
reasoningTokens: a.reasoningTokens - b.reasoningTokens,
|
|
273
|
+
costUsd: a.costUsd - b.costUsd
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
__name(subUsage, "subUsage");
|
|
242
277
|
var ASK_TOOL_NAME = "ask";
|
|
243
278
|
var FAILED_STATUSES = /* @__PURE__ */ new Set([
|
|
244
279
|
"error",
|
|
@@ -304,11 +339,11 @@ var OpenCodeTurn = class {
|
|
|
304
339
|
hidden = /* @__PURE__ */ new Set();
|
|
305
340
|
milestones = [];
|
|
306
341
|
waiting;
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
342
|
+
/** What this turn object saw spent, and how much of it a milestone already reported. */
|
|
343
|
+
spent = emptyUsage();
|
|
344
|
+
reported = emptyUsage();
|
|
345
|
+
priced = false;
|
|
346
|
+
model;
|
|
312
347
|
stepOpen = false;
|
|
313
348
|
sawText = false;
|
|
314
349
|
separator = false;
|
|
@@ -318,6 +353,11 @@ var OpenCodeTurn = class {
|
|
|
318
353
|
stepError;
|
|
319
354
|
constructor(a) {
|
|
320
355
|
this.a = a;
|
|
356
|
+
this.model = modelOfLabel(a.input.model);
|
|
357
|
+
}
|
|
358
|
+
/** What the run spent so far: carried from before this turn object, plus what it saw. */
|
|
359
|
+
totalUsage() {
|
|
360
|
+
return addUsage(this.a.carried, this.spent);
|
|
321
361
|
}
|
|
322
362
|
get sessionId() {
|
|
323
363
|
return this.a.sessionId;
|
|
@@ -400,7 +440,15 @@ var OpenCodeTurn = class {
|
|
|
400
440
|
this.chain = this.chain.then(() => ask.kind === "approval" ? this.decided(ask, reply, tell) : this.answered(ask, reply, tell)).then(resolve, reject);
|
|
401
441
|
});
|
|
402
442
|
}
|
|
403
|
-
reach(
|
|
443
|
+
reach(reached) {
|
|
444
|
+
const usage = subUsage(this.spent, this.reported);
|
|
445
|
+
this.reported = {
|
|
446
|
+
...this.spent
|
|
447
|
+
};
|
|
448
|
+
const milestone = {
|
|
449
|
+
...reached,
|
|
450
|
+
usage
|
|
451
|
+
};
|
|
404
452
|
const waiting = this.waiting;
|
|
405
453
|
if (waiting !== void 0) {
|
|
406
454
|
this.waiting = void 0;
|
|
@@ -556,9 +604,22 @@ var OpenCodeTurn = class {
|
|
|
556
604
|
}
|
|
557
605
|
}
|
|
558
606
|
async onEvent(e) {
|
|
559
|
-
if (this.ended) return;
|
|
560
607
|
const d = e.data ?? {};
|
|
608
|
+
if (e.type === "session.usage.recorded") {
|
|
609
|
+
await this.usageRecorded(d);
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
if (this.ended) return;
|
|
561
613
|
switch (e.type) {
|
|
614
|
+
case "session.step.started":
|
|
615
|
+
case "session.model.selected": {
|
|
616
|
+
const model = d.model;
|
|
617
|
+
if (typeof model?.id === "string" && typeof model.providerID === "string") this.model = {
|
|
618
|
+
providerID: model.providerID,
|
|
619
|
+
id: model.id
|
|
620
|
+
};
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
562
623
|
case "session.text.delta": {
|
|
563
624
|
const delta = typeof d.delta === "string" ? d.delta : "";
|
|
564
625
|
if (!delta) return;
|
|
@@ -712,42 +773,63 @@ ${delta}` : delta;
|
|
|
712
773
|
});
|
|
713
774
|
}
|
|
714
775
|
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
};
|
|
726
|
-
|
|
727
|
-
this.
|
|
728
|
-
|
|
729
|
-
|
|
776
|
+
modelId() {
|
|
777
|
+
return this.model !== void 0 ? `${this.model.providerID}/${this.model.id}` : this.a.modelLabel;
|
|
778
|
+
}
|
|
779
|
+
/** One model call's usage and cost, into the ledger and the run's total. */
|
|
780
|
+
async spend(d, purpose) {
|
|
781
|
+
const usage = usageOf(d.tokens);
|
|
782
|
+
const reportedCostUsd = typeof d.cost === "number" && Number.isFinite(d.cost) && d.cost >= 0 ? d.cost : void 0;
|
|
783
|
+
const fallback = reportedCostUsd !== void 0 ? {
|
|
784
|
+
costUsd: reportedCostUsd,
|
|
785
|
+
costSource: "provider"
|
|
786
|
+
} : {};
|
|
787
|
+
let cost = fallback;
|
|
788
|
+
if (this.a.priceStep !== void 0) {
|
|
789
|
+
cost = await this.a.priceStep({
|
|
790
|
+
model: this.model,
|
|
791
|
+
usage,
|
|
792
|
+
reportedCostUsd
|
|
793
|
+
}).catch(() => fallback);
|
|
794
|
+
}
|
|
795
|
+
this.spent = addUsage(this.spent, {
|
|
796
|
+
inputTokens: usage.inputTokens,
|
|
797
|
+
outputTokens: usage.outputTokens,
|
|
798
|
+
cacheReadTokens: usage.cacheReadTokens ?? 0,
|
|
799
|
+
cacheWriteTokens: usage.cacheWriteTokens ?? 0,
|
|
800
|
+
reasoningTokens: usage.reasoningTokens ?? 0,
|
|
801
|
+
costUsd: cost.costUsd ?? 0
|
|
802
|
+
});
|
|
803
|
+
if (cost.costUsd !== void 0) this.priced = true;
|
|
730
804
|
await this.a.store.recordUsage({
|
|
731
805
|
threadId: this.a.input.threadId,
|
|
732
806
|
actorRef: this.a.input.actor.id,
|
|
733
|
-
modelId: this.
|
|
734
|
-
purpose
|
|
807
|
+
modelId: this.modelId(),
|
|
808
|
+
purpose,
|
|
735
809
|
usage,
|
|
736
|
-
...
|
|
737
|
-
costUsd,
|
|
738
|
-
costSource: "provider"
|
|
739
|
-
} : {}
|
|
810
|
+
...cost
|
|
740
811
|
});
|
|
812
|
+
return {
|
|
813
|
+
usage,
|
|
814
|
+
cost
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
/** `session.usage.recorded`: a call OpenCode made besides the steps (the title, a compaction). */
|
|
818
|
+
async usageRecorded(d) {
|
|
819
|
+
await this.spend(d, d.source === "title" ? "title" : "history_summary");
|
|
820
|
+
}
|
|
821
|
+
async stepEnded(d) {
|
|
822
|
+
const { usage, cost } = await this.spend(d, "chat");
|
|
741
823
|
if (!this.stepOpen) return;
|
|
742
824
|
this.stepOpen = false;
|
|
743
825
|
await this.write({
|
|
744
826
|
kind: "step-finish",
|
|
745
827
|
usage,
|
|
746
|
-
costUsd: costUsd ?? null,
|
|
828
|
+
costUsd: cost.costUsd ?? null,
|
|
747
829
|
...this.segment.reasoningMs > 0 ? {
|
|
748
830
|
reasoningMs: this.segment.reasoningMs
|
|
749
831
|
} : {},
|
|
750
|
-
model: this.
|
|
832
|
+
model: this.modelId()
|
|
751
833
|
});
|
|
752
834
|
}
|
|
753
835
|
/**
|
|
@@ -766,12 +848,7 @@ ${delta}` : delta;
|
|
|
766
848
|
content: s.text,
|
|
767
849
|
runId: this.a.runId,
|
|
768
850
|
...final ? {
|
|
769
|
-
usage:
|
|
770
|
-
...this.usage,
|
|
771
|
-
...this.costUsd !== void 0 ? {
|
|
772
|
-
costUsd: this.costUsd
|
|
773
|
-
} : {}
|
|
774
|
-
}
|
|
851
|
+
usage: this.messageUsage()
|
|
775
852
|
} : {},
|
|
776
853
|
...this.a.input.agentName !== void 0 ? {
|
|
777
854
|
agentName: this.a.input.agentName
|
|
@@ -799,6 +876,26 @@ ${delta}` : delta;
|
|
|
799
876
|
]);
|
|
800
877
|
return message.id;
|
|
801
878
|
}
|
|
879
|
+
/** The run's usage as its last message carries it: the whole run, cache tokens included. */
|
|
880
|
+
messageUsage() {
|
|
881
|
+
const total = this.totalUsage();
|
|
882
|
+
return {
|
|
883
|
+
inputTokens: total.inputTokens,
|
|
884
|
+
outputTokens: total.outputTokens,
|
|
885
|
+
...total.cacheReadTokens > 0 ? {
|
|
886
|
+
cacheReadTokens: total.cacheReadTokens
|
|
887
|
+
} : {},
|
|
888
|
+
...total.cacheWriteTokens > 0 ? {
|
|
889
|
+
cacheWriteTokens: total.cacheWriteTokens
|
|
890
|
+
} : {},
|
|
891
|
+
...total.reasoningTokens > 0 ? {
|
|
892
|
+
reasoningTokens: total.reasoningTokens
|
|
893
|
+
} : {},
|
|
894
|
+
...this.priced || (this.a.carried?.costUsd ?? 0) > 0 ? {
|
|
895
|
+
costUsd: total.costUsd
|
|
896
|
+
} : {}
|
|
897
|
+
};
|
|
898
|
+
}
|
|
802
899
|
/** A request recorded by an earlier process (a turn resumed after a restart). */
|
|
803
900
|
async alreadyRecorded(id) {
|
|
804
901
|
return (await this.a.store.toolCallApproval?.(id) ?? null) !== null;
|
|
@@ -1168,6 +1265,35 @@ ${delta}` : delta;
|
|
|
1168
1265
|
});
|
|
1169
1266
|
}
|
|
1170
1267
|
};
|
|
1268
|
+
function modelOfLabel(label) {
|
|
1269
|
+
const slash = label?.indexOf("/") ?? -1;
|
|
1270
|
+
if (label === void 0 || slash <= 0 || slash === label.length - 1) return void 0;
|
|
1271
|
+
return {
|
|
1272
|
+
providerID: label.slice(0, slash),
|
|
1273
|
+
id: label.slice(slash + 1)
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
__name(modelOfLabel, "modelOfLabel");
|
|
1277
|
+
function usageOf(tokens) {
|
|
1278
|
+
const n = /* @__PURE__ */ __name((v) => typeof v === "number" && Number.isFinite(v) && v > 0 ? v : 0, "n");
|
|
1279
|
+
const read = n(tokens?.cache?.read);
|
|
1280
|
+
const write = n(tokens?.cache?.write);
|
|
1281
|
+
const reasoning = n(tokens?.reasoning);
|
|
1282
|
+
return {
|
|
1283
|
+
inputTokens: n(tokens?.input) + read + write,
|
|
1284
|
+
outputTokens: n(tokens?.output),
|
|
1285
|
+
...read > 0 ? {
|
|
1286
|
+
cacheReadTokens: read
|
|
1287
|
+
} : {},
|
|
1288
|
+
...write > 0 ? {
|
|
1289
|
+
cacheWriteTokens: write
|
|
1290
|
+
} : {},
|
|
1291
|
+
...reasoning > 0 ? {
|
|
1292
|
+
reasoningTokens: reasoning
|
|
1293
|
+
} : {}
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
__name(usageOf, "usageOf");
|
|
1171
1297
|
|
|
1172
1298
|
// src/mcp.ts
|
|
1173
1299
|
var LOOP_SERVED_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -1432,7 +1558,7 @@ import { Inject as Inject3, Injectable as Injectable2 } from "@nestjs/common";
|
|
|
1432
1558
|
// src/turns.ts
|
|
1433
1559
|
import { randomUUID } from "crypto";
|
|
1434
1560
|
import { AGENT_CHAT_QUEUE } from "@dudousxd/nestjs-agent";
|
|
1435
|
-
import { AGENT_DEPS_FACTORY, AGENT_MEMORY, AGENT_SINK, AGENT_SKILLS, AGENT_STORE, AGENT_TOOL_REGISTRY, DEFAULT_MAX_FACT_CHARS, DefaultApprovalPolicy, RUN_ENDED_BEFORE_TOOL_CALL, actorScope, buildMemoryBlock, defaultScopeResolver, encodeStreamEvent as encodeStreamEvent2, memoryWriteVerdict, publishAgentRunFailed, releaseThreadRun, resolveMemoryDigest, resolveSkillCatalog, streamFailure } from "@dudousxd/nestjs-agent-core";
|
|
1561
|
+
import { AGENT_DEPS_FACTORY, AGENT_MEMORY, AGENT_OPTIONS, AGENT_PRICING_STORE, AGENT_SINK, AGENT_SKILLS, AGENT_STORE, AGENT_TOOL_REGISTRY, DEFAULT_MAX_FACT_CHARS, DefaultApprovalPolicy, ModelPriceResolver, RUN_ENDED_BEFORE_TOOL_CALL, actorScope, buildMemoryBlock, defaultScopeResolver, encodeStreamEvent as encodeStreamEvent2, memoryWriteVerdict, parseBedrockModelId, publishAgentRunFailed, releaseThreadRun, resolveMemoryDigest, resolveSkillCatalog, resolveUsageCost, streamFailure } from "@dudousxd/nestjs-agent-core";
|
|
1436
1562
|
import { Inject as Inject2, Injectable, Logger as Logger2, Optional } from "@nestjs/common";
|
|
1437
1563
|
|
|
1438
1564
|
// src/event-hub.ts
|
|
@@ -1599,7 +1725,7 @@ var OpenCodeTurns = class {
|
|
|
1599
1725
|
spent = /* @__PURE__ */ new Set();
|
|
1600
1726
|
/** When the tools endpoint was last registered for a location (`server|boot|directory|actor`). */
|
|
1601
1727
|
toolsIssued = /* @__PURE__ */ new Map();
|
|
1602
|
-
constructor(host, sessions, settings, store, sink, deps, registry, skills, memory, queue, toolsTokens2) {
|
|
1728
|
+
constructor(host, sessions, settings, store, sink, deps, registry, skills, memory, queue, toolsTokens2, pricingStore, agentOptions) {
|
|
1603
1729
|
this.host = host;
|
|
1604
1730
|
this.sessions = sessions;
|
|
1605
1731
|
this.settings = settings;
|
|
@@ -1611,6 +1737,30 @@ var OpenCodeTurns = class {
|
|
|
1611
1737
|
this.memory = memory;
|
|
1612
1738
|
this.queue = queue;
|
|
1613
1739
|
this.toolsTokens = toolsTokens2;
|
|
1740
|
+
this.prices = new ModelPriceResolver({
|
|
1741
|
+
pricingStore,
|
|
1742
|
+
catalog: agentOptions?.priceCatalog,
|
|
1743
|
+
log: {
|
|
1744
|
+
info: /* @__PURE__ */ __name((message) => this.logger.log(message), "info"),
|
|
1745
|
+
warn: /* @__PURE__ */ __name((message) => this.logger.warn(message), "warn")
|
|
1746
|
+
}
|
|
1747
|
+
});
|
|
1748
|
+
}
|
|
1749
|
+
prices;
|
|
1750
|
+
/**
|
|
1751
|
+
* What a model call OpenCode made cost, by the same rule the library's loop records its own steps
|
|
1752
|
+
* at: a reported figure wins, else an estimate off the model's price — see
|
|
1753
|
+
* {@link OpenCodeEngineSettings.cost}.
|
|
1754
|
+
*/
|
|
1755
|
+
async priceStep(step) {
|
|
1756
|
+
const { model, usage, reportedCostUsd } = step;
|
|
1757
|
+
const tokens = usage.inputTokens + usage.outputTokens;
|
|
1758
|
+
const reported = reportedCostUsd !== void 0 && (reportedCostUsd > 0 || tokens === 0);
|
|
1759
|
+
if (reported && this.settings.cost !== "estimate") {
|
|
1760
|
+
return resolveUsageCost(usage, reportedCostUsd, void 0);
|
|
1761
|
+
}
|
|
1762
|
+
const price = model !== void 0 && tokens > 0 ? await this.prices.priceFor(priceRef(model)) : void 0;
|
|
1763
|
+
return resolveUsageCost(usage, price === void 0 ? reportedCostUsd : void 0, price);
|
|
1614
1764
|
}
|
|
1615
1765
|
/** The tools server's name in OpenCode. */
|
|
1616
1766
|
get toolsServer() {
|
|
@@ -2200,8 +2350,8 @@ ${body}
|
|
|
2200
2350
|
}
|
|
2201
2351
|
// ---- prompt / observe / reply --------------------------------------------------------------
|
|
2202
2352
|
/** Start listening to the session (so nothing it says is missed), then send the user message. */
|
|
2203
|
-
async prompt(runId, input, handle) {
|
|
2204
|
-
const live = await this.ensureLive(runId, input, handle, false);
|
|
2353
|
+
async prompt(runId, input, handle, spent) {
|
|
2354
|
+
const live = await this.ensureLive(runId, input, handle, false, spent);
|
|
2205
2355
|
try {
|
|
2206
2356
|
const prompt = await this.host.promptFor?.({
|
|
2207
2357
|
input,
|
|
@@ -2231,9 +2381,12 @@ ${body}
|
|
|
2231
2381
|
* Wait for the turn's next milestone. In a process that was not following the turn (a resumed
|
|
2232
2382
|
* durable run), the turn is rebuilt and first catches up on requests OpenCode raised meanwhile;
|
|
2233
2383
|
* `session.wait` is the safety net for a terminal event that was missed.
|
|
2384
|
+
*
|
|
2385
|
+
* `spent` is what the run spent before (the sum of the `usage` of its earlier milestones): a turn
|
|
2386
|
+
* rebuilt here starts from it, so the answer it persists carries the whole run's usage.
|
|
2234
2387
|
*/
|
|
2235
|
-
async observe(runId, input, handle) {
|
|
2236
|
-
const live = await this.ensureLive(runId, input, handle, true);
|
|
2388
|
+
async observe(runId, input, handle, spent) {
|
|
2389
|
+
const live = await this.ensureLive(runId, input, handle, true, spent);
|
|
2237
2390
|
const { turn, client } = live;
|
|
2238
2391
|
if (turn.hasMilestone()) return this.reached(runId, input, handle, await turn.next());
|
|
2239
2392
|
let done = false;
|
|
@@ -2272,23 +2425,23 @@ ${body}
|
|
|
2272
2425
|
* request is gone with it: a new session is opened, told what the person decided, and prompted
|
|
2273
2426
|
* to go on.
|
|
2274
2427
|
*/
|
|
2275
|
-
async reply(runId, input, handle, ask, reply) {
|
|
2428
|
+
async reply(runId, input, handle, ask, reply, spent) {
|
|
2276
2429
|
const server = await this.host.server(input.actor);
|
|
2277
2430
|
if (server.key !== handle.serverKey || server.bootId !== handle.bootId) {
|
|
2278
|
-
return this.continueAfterRestart(runId, input, server, ask, reply);
|
|
2431
|
+
return this.continueAfterRestart(runId, input, server, ask, reply, spent);
|
|
2279
2432
|
}
|
|
2280
|
-
const live = await this.ensureLive(runId, input, handle, false);
|
|
2433
|
+
const live = await this.ensureLive(runId, input, handle, false, spent);
|
|
2281
2434
|
await live.turn.decide(ask, reply);
|
|
2282
2435
|
return handle;
|
|
2283
2436
|
}
|
|
2284
|
-
async continueAfterRestart(runId, input, server, ask, reply) {
|
|
2437
|
+
async continueAfterRestart(runId, input, server, ask, reply, spent) {
|
|
2285
2438
|
const approved = "approved" in reply && reply.approved === true;
|
|
2286
2439
|
const note = ask.kind === "approval" ? approved ? `The user approved the action ${ask.action} you asked permission for. Continue the task.` : `The user did not approve the action ${ask.action}. Continue without it and explain.` : `The user answered your question: ${JSON.stringify("answers" in reply ? reply.answers : {})}. Continue.`;
|
|
2287
2440
|
const thread = await this.store.getThread(input.threadId);
|
|
2288
2441
|
const handle = await this.createSession(runId, input, server, thread?.messages ?? [], note);
|
|
2289
2442
|
await this.refreshInstructions(runId, input, server.client, handle.sessionId);
|
|
2290
2443
|
this.drop(runId);
|
|
2291
|
-
const live = await this.ensureLive(runId, input, handle, false);
|
|
2444
|
+
const live = await this.ensureLive(runId, input, handle, false, spent);
|
|
2292
2445
|
await live.turn.decide(ask, reply, {
|
|
2293
2446
|
tellOpenCode: false
|
|
2294
2447
|
});
|
|
@@ -2308,7 +2461,7 @@ ${body}
|
|
|
2308
2461
|
sessionID: known.sessionId
|
|
2309
2462
|
});
|
|
2310
2463
|
}
|
|
2311
|
-
async ensureLive(runId, input, handle, catchUp) {
|
|
2464
|
+
async ensureLive(runId, input, handle, catchUp, spent) {
|
|
2312
2465
|
const current = this.live.get(runId);
|
|
2313
2466
|
if (current !== void 0 && current.handle.sessionId === handle.sessionId) return current;
|
|
2314
2467
|
current?.stop();
|
|
@@ -2334,6 +2487,10 @@ ${body}
|
|
|
2334
2487
|
} : {}
|
|
2335
2488
|
}), "approvalFor"),
|
|
2336
2489
|
modelLabel: input.model ?? "opencode",
|
|
2490
|
+
priceStep: /* @__PURE__ */ __name((step) => this.priceStep(step), "priceStep"),
|
|
2491
|
+
...spent !== void 0 ? {
|
|
2492
|
+
carried: spent
|
|
2493
|
+
} : {},
|
|
2337
2494
|
logger: this.logger,
|
|
2338
2495
|
onGranted: /* @__PURE__ */ __name((action, id) => {
|
|
2339
2496
|
const grants = this.grants.get(runId) ?? [];
|
|
@@ -2380,20 +2537,14 @@ ${body}
|
|
|
2380
2537
|
}
|
|
2381
2538
|
return milestone;
|
|
2382
2539
|
}
|
|
2383
|
-
/**
|
|
2384
|
-
|
|
2540
|
+
/**
|
|
2541
|
+
* What the run produced, as the host's settle hooks see it. `usage` is what the run spent — the
|
|
2542
|
+
* runner's sum of its milestones' usage, which a resumed run reads back from its journal — else
|
|
2543
|
+
* what the turn this process follows saw.
|
|
2544
|
+
*/
|
|
2545
|
+
async runResult(runId, input, outcome, durationMs, usage) {
|
|
2385
2546
|
const thread = await this.store.getThread(input.threadId);
|
|
2386
2547
|
const messages = (thread?.messages ?? []).filter((m) => m.role === "assistant" && m.runId === runId);
|
|
2387
|
-
const usage = {
|
|
2388
|
-
inputTokens: 0,
|
|
2389
|
-
outputTokens: 0,
|
|
2390
|
-
costUsd: 0
|
|
2391
|
-
};
|
|
2392
|
-
for (const m of messages) {
|
|
2393
|
-
usage.inputTokens += m.usage?.inputTokens ?? 0;
|
|
2394
|
-
usage.outputTokens += m.usage?.outputTokens ?? 0;
|
|
2395
|
-
usage.costUsd += m.usage?.costUsd ?? 0;
|
|
2396
|
-
}
|
|
2397
2548
|
return {
|
|
2398
2549
|
runId,
|
|
2399
2550
|
input,
|
|
@@ -2438,15 +2589,31 @@ ${body}
|
|
|
2438
2589
|
this.logger.warn(`onSettled failed: ${errorText(error, "error")}`);
|
|
2439
2590
|
}
|
|
2440
2591
|
}
|
|
2441
|
-
/**
|
|
2442
|
-
|
|
2592
|
+
/**
|
|
2593
|
+
* What the run spent: the runner's sum of its milestones, or what the turn this process follows
|
|
2594
|
+
* saw (which starts from that sum) when it saw more — a run that failed or was cancelled between
|
|
2595
|
+
* two milestones.
|
|
2596
|
+
*/
|
|
2597
|
+
spentBy(runId, spent) {
|
|
2598
|
+
const seen = this.live.get(runId)?.turn.totalUsage();
|
|
2599
|
+
if (spent === void 0) return seen ?? emptyUsage();
|
|
2600
|
+
if (seen === void 0) return spent;
|
|
2601
|
+
const tokens = /* @__PURE__ */ __name((u) => u.inputTokens + u.outputTokens, "tokens");
|
|
2602
|
+
return tokens(seen) > tokens(spent) ? seen : spent;
|
|
2603
|
+
}
|
|
2604
|
+
/**
|
|
2605
|
+
* End the run's stream and bookkeeping for how its execution ended. `spent` is what the run spent
|
|
2606
|
+
* (the sum of its milestones' `usage`); omit → what the turn this process follows saw.
|
|
2607
|
+
*/
|
|
2608
|
+
async settle(runId, input, outcome, durationMs, spent) {
|
|
2443
2609
|
if (outcome.status === "failed") {
|
|
2444
|
-
await this.settleFailed(runId, input, outcome.error, durationMs);
|
|
2610
|
+
await this.settleFailed(runId, input, outcome.error, durationMs, spent);
|
|
2445
2611
|
return;
|
|
2446
2612
|
}
|
|
2613
|
+
const usage = this.spentBy(runId, spent);
|
|
2447
2614
|
this.forget(runId);
|
|
2448
2615
|
const writer = await this.sink.open(runId);
|
|
2449
|
-
const result = await this.runResult(runId, input, outcome, durationMs);
|
|
2616
|
+
const result = await this.runResult(runId, input, outcome, durationMs, usage);
|
|
2450
2617
|
await this.amend(writer, result);
|
|
2451
2618
|
if (outcome.status === "interrupted") {
|
|
2452
2619
|
this.logger.log(`agent run ${runId} cancelled`);
|
|
@@ -2474,13 +2641,14 @@ ${body}
|
|
|
2474
2641
|
}
|
|
2475
2642
|
await this.settled(result);
|
|
2476
2643
|
}
|
|
2477
|
-
async settleFailed(runId, input, error, durationMs = 0) {
|
|
2644
|
+
async settleFailed(runId, input, error, durationMs = 0, spent) {
|
|
2645
|
+
const usage = this.spentBy(runId, spent);
|
|
2478
2646
|
this.forget(runId);
|
|
2479
2647
|
const writer = await this.sink.open(runId);
|
|
2480
2648
|
const result = await this.runResult(runId, input, {
|
|
2481
2649
|
status: "failed",
|
|
2482
2650
|
error
|
|
2483
|
-
}, durationMs);
|
|
2651
|
+
}, durationMs, usage);
|
|
2484
2652
|
const worded = (await this.amend(writer, result)).error;
|
|
2485
2653
|
const message = worded ?? streamFailure(new Error(error)).message;
|
|
2486
2654
|
this.logger.error(`agent run ${runId} failed: ${error}`);
|
|
@@ -2550,6 +2718,10 @@ OpenCodeTurns = _ts_decorate2([
|
|
|
2550
2718
|
_ts_param2(9, Inject2(AGENT_CHAT_QUEUE)),
|
|
2551
2719
|
_ts_param2(10, Optional()),
|
|
2552
2720
|
_ts_param2(10, Inject2(OPENCODE_TOOLS_TOKENS)),
|
|
2721
|
+
_ts_param2(11, Optional()),
|
|
2722
|
+
_ts_param2(11, Inject2(AGENT_PRICING_STORE)),
|
|
2723
|
+
_ts_param2(12, Optional()),
|
|
2724
|
+
_ts_param2(12, Inject2(AGENT_OPTIONS)),
|
|
2553
2725
|
_ts_metadata2("design:type", Function),
|
|
2554
2726
|
_ts_metadata2("design:paramtypes", [
|
|
2555
2727
|
typeof OpenCodeHost === "undefined" ? Object : OpenCodeHost,
|
|
@@ -2562,6 +2734,8 @@ OpenCodeTurns = _ts_decorate2([
|
|
|
2562
2734
|
typeof SkillsConfig === "undefined" ? Object : SkillsConfig,
|
|
2563
2735
|
typeof MemoryConfig === "undefined" ? Object : MemoryConfig,
|
|
2564
2736
|
typeof ChatQueueService === "undefined" ? Object : ChatQueueService,
|
|
2737
|
+
Object,
|
|
2738
|
+
typeof AgentPricingStore === "undefined" ? Object : AgentPricingStore,
|
|
2565
2739
|
Object
|
|
2566
2740
|
])
|
|
2567
2741
|
], OpenCodeTurns);
|
|
@@ -2604,6 +2778,19 @@ function uiEmitter(scope, push) {
|
|
|
2604
2778
|
};
|
|
2605
2779
|
}
|
|
2606
2780
|
__name(uiEmitter, "uiEmitter");
|
|
2781
|
+
function priceRef(model) {
|
|
2782
|
+
const aliases = [
|
|
2783
|
+
model.id
|
|
2784
|
+
];
|
|
2785
|
+
const tail = model.id.slice(model.id.lastIndexOf("/") + 1);
|
|
2786
|
+
if (tail !== model.id && parseBedrockModelId(tail) !== void 0) aliases.push(tail);
|
|
2787
|
+
return {
|
|
2788
|
+
modelId: `${model.providerID}/${model.id}`,
|
|
2789
|
+
provider: model.providerID,
|
|
2790
|
+
aliases
|
|
2791
|
+
};
|
|
2792
|
+
}
|
|
2793
|
+
__name(priceRef, "priceRef");
|
|
2607
2794
|
|
|
2608
2795
|
// src/runner.ts
|
|
2609
2796
|
function _ts_decorate3(decorators, target, key, desc) {
|
|
@@ -2705,18 +2892,20 @@ var OpenCodeAgentRunner = class {
|
|
|
2705
2892
|
async run(runId, input) {
|
|
2706
2893
|
const started = Date.now();
|
|
2707
2894
|
this.inputs.set(runId, input);
|
|
2895
|
+
let spent = emptyUsage();
|
|
2708
2896
|
try {
|
|
2709
2897
|
let handle = await this.turns.begin(runId, input);
|
|
2710
2898
|
if (this.cancelled.has(runId)) throw new RunCancelledError();
|
|
2711
|
-
await this.turns.prompt(runId, input, handle);
|
|
2899
|
+
await this.turns.prompt(runId, input, handle, spent);
|
|
2712
2900
|
for (; ; ) {
|
|
2713
|
-
const milestone = await this.turns.observe(runId, input, handle);
|
|
2901
|
+
const milestone = await this.turns.observe(runId, input, handle, spent);
|
|
2902
|
+
spent = addUsage(spent, milestone.usage);
|
|
2714
2903
|
if (milestone.kind === "finished") {
|
|
2715
|
-
await this.turns.settle(runId, input, milestone.outcome, Date.now() - started);
|
|
2904
|
+
await this.turns.settle(runId, input, milestone.outcome, Date.now() - started, spent);
|
|
2716
2905
|
return;
|
|
2717
2906
|
}
|
|
2718
2907
|
const reply = await this.park(runId, milestone.ask.id, milestone.ask.kind === "approval" ? "approval" : "answers", milestone.timeoutMs);
|
|
2719
|
-
handle = await this.turns.reply(runId, input, handle, milestone.ask, reply);
|
|
2908
|
+
handle = await this.turns.reply(runId, input, handle, milestone.ask, reply, spent);
|
|
2720
2909
|
}
|
|
2721
2910
|
} catch (error) {
|
|
2722
2911
|
if (error instanceof RunCancelledError) {
|
|
@@ -2726,7 +2915,7 @@ var OpenCodeAgentRunner = class {
|
|
|
2726
2915
|
}, Date.now() - started);
|
|
2727
2916
|
return;
|
|
2728
2917
|
}
|
|
2729
|
-
await this.turns.settleFailed(runId, input, errorText(error, "the turn failed"));
|
|
2918
|
+
await this.turns.settleFailed(runId, input, errorText(error, "the turn failed"), Date.now() - started);
|
|
2730
2919
|
} finally {
|
|
2731
2920
|
this.inputs.delete(runId);
|
|
2732
2921
|
}
|
|
@@ -2878,6 +3067,8 @@ export {
|
|
|
2878
3067
|
OpenCodeToolsTokens,
|
|
2879
3068
|
OpenCodeTurn,
|
|
2880
3069
|
OpenCodeTurns,
|
|
3070
|
+
addUsage,
|
|
3071
|
+
emptyUsage,
|
|
2881
3072
|
keyValueOpenCodeSessionStore,
|
|
2882
3073
|
openCode,
|
|
2883
3074
|
openCodeControllers,
|
|
@@ -2885,6 +3076,7 @@ export {
|
|
|
2885
3076
|
sessionOf,
|
|
2886
3077
|
toElicitation,
|
|
2887
3078
|
toFormAnswer,
|
|
2888
|
-
toQuestion
|
|
3079
|
+
toQuestion,
|
|
3080
|
+
usageOf
|
|
2889
3081
|
};
|
|
2890
3082
|
//# sourceMappingURL=index.js.map
|