@dudousxd/nestjs-agent-opencode 0.2.1 → 0.4.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/dist/durable/index.cjs +52 -2
- 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 +54 -4
- package/dist/durable/index.js.map +1 -1
- package/dist/{engine-0YkBLWZR.d.cts → engine-BNNxQAFV.d.cts} +22 -3
- package/dist/{engine-0YkBLWZR.d.ts → engine-BNNxQAFV.d.ts} +22 -3
- package/dist/index.cjs +52 -2
- 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 +54 -4
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
|
@@ -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, CostSource, AgentRunInput, SinkWriter, AgentStore, ApprovalRequirement, MessageUsage, AgentUiComponent, HumanReply, Actor, StoredMessage, ToolRegistry, TokenStreamSink, SkillsConfig, MemoryConfig, AgentPricingStore, PriceCatalogOptions, RolesPolicy, RememberToolInput, AiToolCtx } from '@dudousxd/nestjs-agent-core';
|
|
3
|
+
import { ElicitationRequest, CostSource, AgentRunInput, SinkWriter, AgentStore, ApprovalRequirement, ToolPresentation, 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
|
|
|
@@ -297,6 +297,15 @@ interface OpenCodeTurnArgs {
|
|
|
297
297
|
store: AgentStore;
|
|
298
298
|
/** What an action needs before it runs (the module's `ApprovalPolicy`). */
|
|
299
299
|
approvalFor: (action: string) => Promise<ApprovalRequirement>;
|
|
300
|
+
/**
|
|
301
|
+
* The app tool a permission `action` names, with its presentation: its `confirm` templates (filled
|
|
302
|
+
* from the call's arguments) word the approval card. `undefined` (or omitted) → an OpenCode
|
|
303
|
+
* built-in, worded from its name.
|
|
304
|
+
*/
|
|
305
|
+
approvalPresentation?: (action: string) => {
|
|
306
|
+
name: string;
|
|
307
|
+
presentation?: ToolPresentation;
|
|
308
|
+
} | undefined;
|
|
300
309
|
/** The model label usage is recorded under until OpenCode names the step's model. */
|
|
301
310
|
modelLabel: string;
|
|
302
311
|
/**
|
|
@@ -676,6 +685,8 @@ declare class OpenCodeToolRefusedError extends Error {
|
|
|
676
685
|
declare class OpenCodeMcpEndpoint {
|
|
677
686
|
private readonly turns;
|
|
678
687
|
private readonly tokens;
|
|
688
|
+
/** Genui telemetry of the UI calls OpenCode makes (its code mode calls tools here, not in the loop). */
|
|
689
|
+
private readonly genui;
|
|
679
690
|
constructor(turns: OpenCodeTurns, tokens: OpenCodeToolsTokens);
|
|
680
691
|
/** The claims of a request's bearer token, or `null`. */
|
|
681
692
|
authenticate(authorization: string | string[] | undefined): OpenCodeToolsClaims | null;
|
|
@@ -787,7 +798,8 @@ declare class OpenCodeTurns implements OnApplicationShutdown {
|
|
|
787
798
|
private readonly host;
|
|
788
799
|
private readonly sessions;
|
|
789
800
|
private readonly settings;
|
|
790
|
-
|
|
801
|
+
/** Read by the MCP endpoint too (genui telemetry of the calls OpenCode makes). */
|
|
802
|
+
readonly store: AgentStore;
|
|
791
803
|
private readonly sink;
|
|
792
804
|
private readonly deps;
|
|
793
805
|
readonly registry: ToolRegistry;
|
|
@@ -803,7 +815,9 @@ declare class OpenCodeTurns implements OnApplicationShutdown {
|
|
|
803
815
|
private readonly spent;
|
|
804
816
|
/** When the tools endpoint was last registered for a location (`server|boot|directory|actor`). */
|
|
805
817
|
private readonly toolsIssued;
|
|
806
|
-
constructor(host: OpenCodeHost, sessions: OpenCodeSessionStore, settings: OpenCodeEngineSettings,
|
|
818
|
+
constructor(host: OpenCodeHost, sessions: OpenCodeSessionStore, settings: OpenCodeEngineSettings,
|
|
819
|
+
/** Read by the MCP endpoint too (genui telemetry of the calls OpenCode makes). */
|
|
820
|
+
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
821
|
priceCatalog?: PriceCatalogOptions | false;
|
|
808
822
|
});
|
|
809
823
|
private readonly prices;
|
|
@@ -819,6 +833,11 @@ declare class OpenCodeTurns implements OnApplicationShutdown {
|
|
|
819
833
|
}): Promise<StepCost>;
|
|
820
834
|
/** The tools server's name in OpenCode. */
|
|
821
835
|
get toolsServer(): string;
|
|
836
|
+
/** The app tool an OpenCode permission `action` names, and its presentation — `undefined` for a built-in. */
|
|
837
|
+
presentationOf(action: string): {
|
|
838
|
+
name: string;
|
|
839
|
+
presentation?: ToolPresentation;
|
|
840
|
+
} | undefined;
|
|
822
841
|
/** The roles policy a turn's tools are gated by (the agent's own). */
|
|
823
842
|
rolesPolicyFor(input: Pick<AgentRunInput, 'agentName'>): RolesPolicy;
|
|
824
843
|
/** The tools a turn may reach: the agent's allow-list, narrowed by its persona's. */
|
|
@@ -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, CostSource, AgentRunInput, SinkWriter, AgentStore, ApprovalRequirement, MessageUsage, AgentUiComponent, HumanReply, Actor, StoredMessage, ToolRegistry, TokenStreamSink, SkillsConfig, MemoryConfig, AgentPricingStore, PriceCatalogOptions, RolesPolicy, RememberToolInput, AiToolCtx } from '@dudousxd/nestjs-agent-core';
|
|
3
|
+
import { ElicitationRequest, CostSource, AgentRunInput, SinkWriter, AgentStore, ApprovalRequirement, ToolPresentation, 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
|
|
|
@@ -297,6 +297,15 @@ interface OpenCodeTurnArgs {
|
|
|
297
297
|
store: AgentStore;
|
|
298
298
|
/** What an action needs before it runs (the module's `ApprovalPolicy`). */
|
|
299
299
|
approvalFor: (action: string) => Promise<ApprovalRequirement>;
|
|
300
|
+
/**
|
|
301
|
+
* The app tool a permission `action` names, with its presentation: its `confirm` templates (filled
|
|
302
|
+
* from the call's arguments) word the approval card. `undefined` (or omitted) → an OpenCode
|
|
303
|
+
* built-in, worded from its name.
|
|
304
|
+
*/
|
|
305
|
+
approvalPresentation?: (action: string) => {
|
|
306
|
+
name: string;
|
|
307
|
+
presentation?: ToolPresentation;
|
|
308
|
+
} | undefined;
|
|
300
309
|
/** The model label usage is recorded under until OpenCode names the step's model. */
|
|
301
310
|
modelLabel: string;
|
|
302
311
|
/**
|
|
@@ -676,6 +685,8 @@ declare class OpenCodeToolRefusedError extends Error {
|
|
|
676
685
|
declare class OpenCodeMcpEndpoint {
|
|
677
686
|
private readonly turns;
|
|
678
687
|
private readonly tokens;
|
|
688
|
+
/** Genui telemetry of the UI calls OpenCode makes (its code mode calls tools here, not in the loop). */
|
|
689
|
+
private readonly genui;
|
|
679
690
|
constructor(turns: OpenCodeTurns, tokens: OpenCodeToolsTokens);
|
|
680
691
|
/** The claims of a request's bearer token, or `null`. */
|
|
681
692
|
authenticate(authorization: string | string[] | undefined): OpenCodeToolsClaims | null;
|
|
@@ -787,7 +798,8 @@ declare class OpenCodeTurns implements OnApplicationShutdown {
|
|
|
787
798
|
private readonly host;
|
|
788
799
|
private readonly sessions;
|
|
789
800
|
private readonly settings;
|
|
790
|
-
|
|
801
|
+
/** Read by the MCP endpoint too (genui telemetry of the calls OpenCode makes). */
|
|
802
|
+
readonly store: AgentStore;
|
|
791
803
|
private readonly sink;
|
|
792
804
|
private readonly deps;
|
|
793
805
|
readonly registry: ToolRegistry;
|
|
@@ -803,7 +815,9 @@ declare class OpenCodeTurns implements OnApplicationShutdown {
|
|
|
803
815
|
private readonly spent;
|
|
804
816
|
/** When the tools endpoint was last registered for a location (`server|boot|directory|actor`). */
|
|
805
817
|
private readonly toolsIssued;
|
|
806
|
-
constructor(host: OpenCodeHost, sessions: OpenCodeSessionStore, settings: OpenCodeEngineSettings,
|
|
818
|
+
constructor(host: OpenCodeHost, sessions: OpenCodeSessionStore, settings: OpenCodeEngineSettings,
|
|
819
|
+
/** Read by the MCP endpoint too (genui telemetry of the calls OpenCode makes). */
|
|
820
|
+
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
821
|
priceCatalog?: PriceCatalogOptions | false;
|
|
808
822
|
});
|
|
809
823
|
private readonly prices;
|
|
@@ -819,6 +833,11 @@ declare class OpenCodeTurns implements OnApplicationShutdown {
|
|
|
819
833
|
}): Promise<StepCost>;
|
|
820
834
|
/** The tools server's name in OpenCode. */
|
|
821
835
|
get toolsServer(): string;
|
|
836
|
+
/** The app tool an OpenCode permission `action` names, and its presentation — `undefined` for a built-in. */
|
|
837
|
+
presentationOf(action: string): {
|
|
838
|
+
name: string;
|
|
839
|
+
presentation?: ToolPresentation;
|
|
840
|
+
} | undefined;
|
|
822
841
|
/** The roles policy a turn's tools are gated by (the agent's own). */
|
|
823
842
|
rolesPolicyFor(input: Pick<AgentRunInput, 'agentName'>): RolesPolicy;
|
|
824
843
|
/** The tools a turn may reach: the agent's allow-list, narrowed by its persona's. */
|
package/dist/index.cjs
CHANGED
|
@@ -195,6 +195,7 @@ OpenCodeMcpController = _ts_decorate([
|
|
|
195
195
|
// src/mcp.ts
|
|
196
196
|
var import_node_crypto = require("crypto");
|
|
197
197
|
var import_nestjs_agent_core3 = require("@dudousxd/nestjs-agent-core");
|
|
198
|
+
var import_genui = require("@dudousxd/nestjs-agent-core/genui");
|
|
198
199
|
var import_server = require("@modelcontextprotocol/sdk/server/index.js");
|
|
199
200
|
var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
200
201
|
var import_zod_json_schema_compat = require("@modelcontextprotocol/sdk/server/zod-json-schema-compat.js");
|
|
@@ -1071,6 +1072,8 @@ ${delta}` : delta;
|
|
|
1071
1072
|
}
|
|
1072
1073
|
const ttlMs = requirement.ttlMs !== void 0 && Number.isFinite(requirement.ttlMs) && requirement.ttlMs > 0 ? Math.floor(requirement.ttlMs) : void 0;
|
|
1073
1074
|
const expiresAt = ttlMs !== void 0 ? new Date(Date.now() + ttlMs).toISOString() : void 0;
|
|
1075
|
+
const tool = this.a.approvalPresentation?.(action);
|
|
1076
|
+
const confirmation = tool !== void 0 ? (0, import_nestjs_agent_core2.resolveToolConfirmation)(tool.name, args, tool.presentation) : void 0;
|
|
1074
1077
|
this.segment.calls.push({
|
|
1075
1078
|
id: req.id,
|
|
1076
1079
|
name: action,
|
|
@@ -1085,6 +1088,9 @@ ${delta}` : delta;
|
|
|
1085
1088
|
toolType: "action",
|
|
1086
1089
|
input: args,
|
|
1087
1090
|
status: "pending_approval",
|
|
1091
|
+
...confirmation !== void 0 ? {
|
|
1092
|
+
confirmation
|
|
1093
|
+
} : {},
|
|
1088
1094
|
runId: this.a.runId,
|
|
1089
1095
|
approver: requirement.approver,
|
|
1090
1096
|
...expiresAt !== void 0 ? {
|
|
@@ -1102,6 +1108,9 @@ ${delta}` : delta;
|
|
|
1102
1108
|
kind: "approval-requested",
|
|
1103
1109
|
id: req.id,
|
|
1104
1110
|
approver: requirement.approver,
|
|
1111
|
+
...confirmation !== void 0 ? {
|
|
1112
|
+
confirmation
|
|
1113
|
+
} : {},
|
|
1105
1114
|
...expiresAt !== void 0 ? {
|
|
1106
1115
|
expiresAt
|
|
1107
1116
|
} : {}
|
|
@@ -1507,6 +1516,8 @@ var OpenCodeMcpEndpoint2 = class {
|
|
|
1507
1516
|
}
|
|
1508
1517
|
turns;
|
|
1509
1518
|
tokens;
|
|
1519
|
+
/** Genui telemetry of the UI calls OpenCode makes (its code mode calls tools here, not in the loop). */
|
|
1520
|
+
genui = new import_nestjs_agent_core3.GenuiRunRecorder();
|
|
1510
1521
|
constructor(turns, tokens) {
|
|
1511
1522
|
this.turns = turns;
|
|
1512
1523
|
this.tokens = tokens;
|
|
@@ -1638,7 +1649,7 @@ var OpenCodeMcpEndpoint2 = class {
|
|
|
1638
1649
|
if (spec.kind === "action" && !await this.turns.spendApproval(turn.runId, name, turn.input)) {
|
|
1639
1650
|
throw new OpenCodeToolRefusedError(`"${name}" is an action and nobody approved this call; ask for the permission first.`);
|
|
1640
1651
|
}
|
|
1641
|
-
|
|
1652
|
+
const invoke = /* @__PURE__ */ __name(() => registry.invoke(name, args ?? {}, {
|
|
1642
1653
|
actor,
|
|
1643
1654
|
threadId: turn.ctx.threadId,
|
|
1644
1655
|
runId: turn.runId,
|
|
@@ -1655,7 +1666,24 @@ var OpenCodeMcpEndpoint2 = class {
|
|
|
1655
1666
|
} : {}
|
|
1656
1667
|
}, this.turns.rolesPolicyFor(turn.input), allowed !== void 0 ? {
|
|
1657
1668
|
allowedTools: allowed
|
|
1658
|
-
} : {});
|
|
1669
|
+
} : {}), "invoke");
|
|
1670
|
+
return this.genui.track({
|
|
1671
|
+
store: this.turns.store,
|
|
1672
|
+
marker: spec.genui,
|
|
1673
|
+
runId: turn.runId,
|
|
1674
|
+
threadId: turn.ctx.threadId,
|
|
1675
|
+
actorRef: actor.id,
|
|
1676
|
+
...turn.input.agentName !== void 0 ? {
|
|
1677
|
+
agentName: turn.input.agentName
|
|
1678
|
+
} : {},
|
|
1679
|
+
channel: (0, import_genui.turnChannel)(turn.input.pageContext),
|
|
1680
|
+
modelId: turn.input.model ?? "opencode",
|
|
1681
|
+
call: {
|
|
1682
|
+
id: `mcp:${turn.runId}:${requestId}`,
|
|
1683
|
+
name,
|
|
1684
|
+
input: args ?? {}
|
|
1685
|
+
}
|
|
1686
|
+
}, invoke);
|
|
1659
1687
|
}
|
|
1660
1688
|
/** `remember`: one fact, at the actor's own scope only — as the loop serves it. */
|
|
1661
1689
|
async remember(turn, args) {
|
|
@@ -1882,6 +1910,25 @@ var OpenCodeTurns = class {
|
|
|
1882
1910
|
get toolsServer() {
|
|
1883
1911
|
return this.settings.tools?.server ?? "aviary";
|
|
1884
1912
|
}
|
|
1913
|
+
/** The app tool an OpenCode permission `action` names, and its presentation — `undefined` for a built-in. */
|
|
1914
|
+
presentationOf(action) {
|
|
1915
|
+
if (this.settings.tools === void 0) return void 0;
|
|
1916
|
+
const server = this.toolsServer;
|
|
1917
|
+
for (const prefix of [
|
|
1918
|
+
`${server}.`,
|
|
1919
|
+
`${server}_`
|
|
1920
|
+
]) {
|
|
1921
|
+
if (!action.startsWith(prefix)) continue;
|
|
1922
|
+
const spec = this.registry.spec(action.slice(prefix.length));
|
|
1923
|
+
if (spec !== void 0) return {
|
|
1924
|
+
name: spec.name,
|
|
1925
|
+
...spec.presentation !== void 0 ? {
|
|
1926
|
+
presentation: spec.presentation
|
|
1927
|
+
} : {}
|
|
1928
|
+
};
|
|
1929
|
+
}
|
|
1930
|
+
return void 0;
|
|
1931
|
+
}
|
|
1885
1932
|
/** The roles policy a turn's tools are gated by (the agent's own). */
|
|
1886
1933
|
rolesPolicyFor(input) {
|
|
1887
1934
|
return this.deps.forAgent(input.agentName).rolesPolicy;
|
|
@@ -2614,6 +2661,9 @@ ${body}
|
|
|
2614
2661
|
agentName: input.agentName
|
|
2615
2662
|
} : {}
|
|
2616
2663
|
}), "approvalFor"),
|
|
2664
|
+
// An app tool reaches OpenCode as `<server>.<name>` / `<server>_<name>`: its own presentation
|
|
2665
|
+
// words the approval card. OpenCode's built-ins (`bash`, `edit`) have none.
|
|
2666
|
+
approvalPresentation: /* @__PURE__ */ __name((action) => this.presentationOf(action), "approvalPresentation"),
|
|
2617
2667
|
modelLabel: input.model ?? "opencode",
|
|
2618
2668
|
priceStep: /* @__PURE__ */ __name((step) => this.priceStep(step), "priceStep"),
|
|
2619
2669
|
...spent !== void 0 ? {
|