@dudousxd/nestjs-agent-opencode 0.2.0 → 0.3.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 +6 -1
- package/dist/durable/index.cjs +107 -0
- 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 +108 -1
- package/dist/durable/index.js.map +1 -1
- package/dist/{engine-JnBbcRxh.d.cts → engine-Cp5uysaN.d.cts} +46 -1
- package/dist/{engine-JnBbcRxh.d.ts → engine-Cp5uysaN.d.ts} +46 -1
- package/dist/index.cjs +107 -0
- 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 +108 -1
- 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, 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-
|
|
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-Cp5uysaN.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-Cp5uysaN.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, 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-
|
|
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-Cp5uysaN.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-Cp5uysaN.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
|
@@ -150,7 +150,7 @@ import { toJsonSchemaCompat } from "@modelcontextprotocol/sdk/server/zod-json-sc
|
|
|
150
150
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
151
151
|
|
|
152
152
|
// src/turn.ts
|
|
153
|
-
import { encodeStreamEvent, settleElicitation } from "@dudousxd/nestjs-agent-core";
|
|
153
|
+
import { encodeStreamEvent, resolveToolConfirmation, settleElicitation } from "@dudousxd/nestjs-agent-core";
|
|
154
154
|
import { ConflictException } from "@nestjs/common";
|
|
155
155
|
|
|
156
156
|
// src/forms.ts
|
|
@@ -344,6 +344,17 @@ var OpenCodeTurn = class {
|
|
|
344
344
|
reported = emptyUsage();
|
|
345
345
|
priced = false;
|
|
346
346
|
model;
|
|
347
|
+
/** What the session had spent when this turn prompted it; what OpenCode reported since. */
|
|
348
|
+
baseline;
|
|
349
|
+
seen = {
|
|
350
|
+
cost: 0,
|
|
351
|
+
input: 0,
|
|
352
|
+
output: 0,
|
|
353
|
+
reasoning: 0,
|
|
354
|
+
read: 0,
|
|
355
|
+
write: 0
|
|
356
|
+
};
|
|
357
|
+
compacted = false;
|
|
347
358
|
stepOpen = false;
|
|
348
359
|
sawText = false;
|
|
349
360
|
separator = false;
|
|
@@ -355,6 +366,19 @@ var OpenCodeTurn = class {
|
|
|
355
366
|
this.a = a;
|
|
356
367
|
this.model = modelOfLabel(a.input.model);
|
|
357
368
|
}
|
|
369
|
+
/**
|
|
370
|
+
* What the session had spent before this turn prompted it (`session.get`). When the execution
|
|
371
|
+
* ends, what the session spent since that this turn's events did not report — the title OpenCode
|
|
372
|
+
* generates, a compaction: OpenCode records those calls on the session without streaming them — is
|
|
373
|
+
* recorded as a usage row of its own.
|
|
374
|
+
*/
|
|
375
|
+
setBaseline(info) {
|
|
376
|
+
if (info?.tokens === void 0) return;
|
|
377
|
+
this.baseline = {
|
|
378
|
+
cost: Number(info.cost) || 0,
|
|
379
|
+
tokens: info.tokens
|
|
380
|
+
};
|
|
381
|
+
}
|
|
358
382
|
/** What the run spent so far: carried from before this turn object, plus what it saw. */
|
|
359
383
|
totalUsage() {
|
|
360
384
|
return addUsage(this.a.carried, this.spent);
|
|
@@ -611,6 +635,10 @@ var OpenCodeTurn = class {
|
|
|
611
635
|
}
|
|
612
636
|
if (this.ended) return;
|
|
613
637
|
switch (e.type) {
|
|
638
|
+
case "session.compaction.started":
|
|
639
|
+
case "session.compaction.ended":
|
|
640
|
+
this.compacted = true;
|
|
641
|
+
return;
|
|
614
642
|
case "session.step.started":
|
|
615
643
|
case "session.model.selected": {
|
|
616
644
|
const model = d.model;
|
|
@@ -780,6 +808,13 @@ ${delta}` : delta;
|
|
|
780
808
|
async spend(d, purpose) {
|
|
781
809
|
const usage = usageOf(d.tokens);
|
|
782
810
|
const reportedCostUsd = typeof d.cost === "number" && Number.isFinite(d.cost) && d.cost >= 0 ? d.cost : void 0;
|
|
811
|
+
const n = /* @__PURE__ */ __name((v) => typeof v === "number" && Number.isFinite(v) && v > 0 ? v : 0, "n");
|
|
812
|
+
this.seen.cost += reportedCostUsd ?? 0;
|
|
813
|
+
this.seen.input += n(d.tokens?.input);
|
|
814
|
+
this.seen.output += n(d.tokens?.output);
|
|
815
|
+
this.seen.reasoning += n(d.tokens?.reasoning);
|
|
816
|
+
this.seen.read += n(d.tokens?.cache?.read);
|
|
817
|
+
this.seen.write += n(d.tokens?.cache?.write);
|
|
783
818
|
const fallback = reportedCostUsd !== void 0 ? {
|
|
784
819
|
costUsd: reportedCostUsd,
|
|
785
820
|
costSource: "provider"
|
|
@@ -985,6 +1020,8 @@ ${delta}` : delta;
|
|
|
985
1020
|
}
|
|
986
1021
|
const ttlMs = requirement.ttlMs !== void 0 && Number.isFinite(requirement.ttlMs) && requirement.ttlMs > 0 ? Math.floor(requirement.ttlMs) : void 0;
|
|
987
1022
|
const expiresAt = ttlMs !== void 0 ? new Date(Date.now() + ttlMs).toISOString() : void 0;
|
|
1023
|
+
const tool = this.a.approvalPresentation?.(action);
|
|
1024
|
+
const confirmation = tool !== void 0 ? resolveToolConfirmation(tool.name, args, tool.presentation) : void 0;
|
|
988
1025
|
this.segment.calls.push({
|
|
989
1026
|
id: req.id,
|
|
990
1027
|
name: action,
|
|
@@ -999,6 +1036,9 @@ ${delta}` : delta;
|
|
|
999
1036
|
toolType: "action",
|
|
1000
1037
|
input: args,
|
|
1001
1038
|
status: "pending_approval",
|
|
1039
|
+
...confirmation !== void 0 ? {
|
|
1040
|
+
confirmation
|
|
1041
|
+
} : {},
|
|
1002
1042
|
runId: this.a.runId,
|
|
1003
1043
|
approver: requirement.approver,
|
|
1004
1044
|
...expiresAt !== void 0 ? {
|
|
@@ -1016,6 +1056,9 @@ ${delta}` : delta;
|
|
|
1016
1056
|
kind: "approval-requested",
|
|
1017
1057
|
id: req.id,
|
|
1018
1058
|
approver: requirement.approver,
|
|
1059
|
+
...confirmation !== void 0 ? {
|
|
1060
|
+
confirmation
|
|
1061
|
+
} : {},
|
|
1019
1062
|
...expiresAt !== void 0 ? {
|
|
1020
1063
|
expiresAt
|
|
1021
1064
|
} : {}
|
|
@@ -1247,9 +1290,39 @@ ${delta}` : delta;
|
|
|
1247
1290
|
this.messageResults.set(messageId, results);
|
|
1248
1291
|
await this.a.store.setMessageToolResults(messageId, results);
|
|
1249
1292
|
}
|
|
1293
|
+
/** What the session spent since the baseline that no event of this turn reported. */
|
|
1294
|
+
async unreported() {
|
|
1295
|
+
const baseline = this.baseline;
|
|
1296
|
+
if (baseline === void 0) return;
|
|
1297
|
+
this.baseline = void 0;
|
|
1298
|
+
const info = await this.a.client.session.get?.({
|
|
1299
|
+
sessionID: this.a.sessionId
|
|
1300
|
+
}).catch(() => void 0);
|
|
1301
|
+
const after = info?.tokens;
|
|
1302
|
+
if (after === void 0) return;
|
|
1303
|
+
const before = baseline.tokens;
|
|
1304
|
+
const left = /* @__PURE__ */ __name((now, then, seen) => Math.max(0, (Number(now) || 0) - (Number(then) || 0) - seen), "left");
|
|
1305
|
+
const tokens = {
|
|
1306
|
+
input: left(after.input, before.input, this.seen.input),
|
|
1307
|
+
output: left(after.output, before.output, this.seen.output),
|
|
1308
|
+
reasoning: left(after.reasoning, before.reasoning, this.seen.reasoning),
|
|
1309
|
+
cache: {
|
|
1310
|
+
read: left(after.cache?.read, before.cache?.read, this.seen.read),
|
|
1311
|
+
write: left(after.cache?.write, before.cache?.write, this.seen.write)
|
|
1312
|
+
}
|
|
1313
|
+
};
|
|
1314
|
+
const total = tokens.input + tokens.output + tokens.reasoning + tokens.cache.read + tokens.cache.write;
|
|
1315
|
+
if (total === 0) return;
|
|
1316
|
+
const cost = left(info?.cost, baseline.cost, this.seen.cost);
|
|
1317
|
+
await this.spend({
|
|
1318
|
+
tokens,
|
|
1319
|
+
cost: cost < 1e-9 ? 0 : cost
|
|
1320
|
+
}, this.compacted ? "history_summary" : "title");
|
|
1321
|
+
}
|
|
1250
1322
|
async end(outcome) {
|
|
1251
1323
|
if (this.ended) return;
|
|
1252
1324
|
this.ended = true;
|
|
1325
|
+
await this.unreported().catch((error) => this.a.logger.warn(`run ${this.a.runId}: ${errorText(error, "could not read the session usage")}`));
|
|
1253
1326
|
if (outcome.status !== "failed" || this.segment.text || this.segment.calls.length > 0 || this.segment.ui.length > 0) {
|
|
1254
1327
|
await this.flush(true);
|
|
1255
1328
|
}
|
|
@@ -1766,6 +1839,25 @@ var OpenCodeTurns = class {
|
|
|
1766
1839
|
get toolsServer() {
|
|
1767
1840
|
return this.settings.tools?.server ?? "aviary";
|
|
1768
1841
|
}
|
|
1842
|
+
/** The app tool an OpenCode permission `action` names, and its presentation — `undefined` for a built-in. */
|
|
1843
|
+
presentationOf(action) {
|
|
1844
|
+
if (this.settings.tools === void 0) return void 0;
|
|
1845
|
+
const server = this.toolsServer;
|
|
1846
|
+
for (const prefix of [
|
|
1847
|
+
`${server}.`,
|
|
1848
|
+
`${server}_`
|
|
1849
|
+
]) {
|
|
1850
|
+
if (!action.startsWith(prefix)) continue;
|
|
1851
|
+
const spec = this.registry.spec(action.slice(prefix.length));
|
|
1852
|
+
if (spec !== void 0) return {
|
|
1853
|
+
name: spec.name,
|
|
1854
|
+
...spec.presentation !== void 0 ? {
|
|
1855
|
+
presentation: spec.presentation
|
|
1856
|
+
} : {}
|
|
1857
|
+
};
|
|
1858
|
+
}
|
|
1859
|
+
return void 0;
|
|
1860
|
+
}
|
|
1769
1861
|
/** The roles policy a turn's tools are gated by (the agent's own). */
|
|
1770
1862
|
rolesPolicyFor(input) {
|
|
1771
1863
|
return this.deps.forAgent(input.agentName).rolesPolicy;
|
|
@@ -2366,6 +2458,7 @@ ${body}
|
|
|
2366
2458
|
})
|
|
2367
2459
|
} : {}
|
|
2368
2460
|
};
|
|
2461
|
+
live.turn.setBaseline(await this.sessionUsage(live.client, handle.sessionId));
|
|
2369
2462
|
await live.client.session.prompt({
|
|
2370
2463
|
sessionID: handle.sessionId,
|
|
2371
2464
|
text: prompt.text,
|
|
@@ -2445,12 +2538,23 @@ ${body}
|
|
|
2445
2538
|
await live.turn.decide(ask, reply, {
|
|
2446
2539
|
tellOpenCode: false
|
|
2447
2540
|
});
|
|
2541
|
+
live.turn.setBaseline(await this.sessionUsage(live.client, handle.sessionId));
|
|
2448
2542
|
await live.client.session.prompt({
|
|
2449
2543
|
sessionID: handle.sessionId,
|
|
2450
2544
|
text: note
|
|
2451
2545
|
});
|
|
2452
2546
|
return handle;
|
|
2453
2547
|
}
|
|
2548
|
+
/** What a session spent so far (`session.get`), or nothing when OpenCode does not say. */
|
|
2549
|
+
async sessionUsage(client, sessionId) {
|
|
2550
|
+
try {
|
|
2551
|
+
return await client.session.get?.({
|
|
2552
|
+
sessionID: sessionId
|
|
2553
|
+
});
|
|
2554
|
+
} catch {
|
|
2555
|
+
return void 0;
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2454
2558
|
/** Interrupt the thread's session (cancel). */
|
|
2455
2559
|
async interrupt(input) {
|
|
2456
2560
|
const known = await this.sessions.get(input.threadId);
|
|
@@ -2486,6 +2590,9 @@ ${body}
|
|
|
2486
2590
|
agentName: input.agentName
|
|
2487
2591
|
} : {}
|
|
2488
2592
|
}), "approvalFor"),
|
|
2593
|
+
// An app tool reaches OpenCode as `<server>.<name>` / `<server>_<name>`: its own presentation
|
|
2594
|
+
// words the approval card. OpenCode's built-ins (`bash`, `edit`) have none.
|
|
2595
|
+
approvalPresentation: /* @__PURE__ */ __name((action) => this.presentationOf(action), "approvalPresentation"),
|
|
2489
2596
|
modelLabel: input.model ?? "opencode",
|
|
2490
2597
|
priceStep: /* @__PURE__ */ __name((step) => this.priceStep(step), "priceStep"),
|
|
2491
2598
|
...spent !== void 0 ? {
|