@roll-agent/runtime 0.1.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/approval/approval-gate.d.ts +11 -0
- package/dist/approval/approval-gate.js +1 -0
- package/dist/engine/agent-session.d.ts +34 -0
- package/dist/engine/agent-session.js +1 -0
- package/dist/engine/conversation-engine.d.ts +48 -0
- package/dist/engine/conversation-engine.js +1 -0
- package/dist/engine/event-queue.d.ts +8 -0
- package/dist/engine/event-queue.js +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +1 -0
- package/dist/policy/configurable-policy.d.ts +17 -0
- package/dist/policy/configurable-policy.js +1 -0
- package/dist/policy/default-policy.d.ts +4 -0
- package/dist/policy/default-policy.js +1 -0
- package/dist/server/protocol.d.ts +105 -0
- package/dist/server/protocol.js +1 -0
- package/dist/server/runtime-server.d.ts +12 -0
- package/dist/server/runtime-server.js +1 -0
- package/dist/server/transport/stdio.d.ts +3 -0
- package/dist/server/transport/stdio.js +1 -0
- package/dist/store/thread-store.d.ts +30 -0
- package/dist/store/thread-store.js +1 -0
- package/dist/tool-bridge/build-tools.d.ts +30 -0
- package/dist/tool-bridge/build-tools.js +1 -0
- package/dist/tool-bridge/naming.d.ts +10 -0
- package/dist/tool-bridge/naming.js +1 -0
- package/dist/tool-bridge/normalize-result.d.ts +6 -0
- package/dist/tool-bridge/normalize-result.js +1 -0
- package/dist/types/events.d.ts +45 -0
- package/dist/types/events.js +1 -0
- package/dist/types/policy.d.ts +18 -0
- package/dist/types/policy.js +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ApprovalDecision {
|
|
2
|
+
readonly approved: boolean;
|
|
3
|
+
readonly reason?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class ApprovalGate {
|
|
6
|
+
private readonly pending;
|
|
7
|
+
request(approvalId: string): Promise<ApprovalDecision>;
|
|
8
|
+
resolve(approvalId: string, decision: ApprovalDecision): boolean;
|
|
9
|
+
abortAll(reason?: string): void;
|
|
10
|
+
get pendingCount(): number;
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class ApprovalGate{pending=new Map;request(e){return new Promise(n=>{this.pending.set(e,n)})}resolve(e,n){const t=this.pending.get(e);return!!t&&(this.pending.delete(e),t(n),!0)}abortAll(e="aborted"){for(const n of this.pending.values())n({approved:!1,reason:e});this.pending.clear()}get pendingCount(){return this.pending.size}}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type ModelMessage } from "ai";
|
|
2
|
+
import type { LanguageModelV3 } from "@ai-sdk/provider";
|
|
3
|
+
import type { SessionEvent } from "../types/events.ts";
|
|
4
|
+
import type { ToolPolicy } from "../types/policy.ts";
|
|
5
|
+
import { type AgentToolSource } from "../tool-bridge/build-tools.ts";
|
|
6
|
+
export interface AgentSessionOptions {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly model: LanguageModelV3;
|
|
9
|
+
readonly sources: readonly AgentToolSource[];
|
|
10
|
+
readonly maxSteps: number;
|
|
11
|
+
readonly policy?: ToolPolicy;
|
|
12
|
+
readonly initialMessages?: readonly ModelMessage[];
|
|
13
|
+
readonly onPersist?: (messages: readonly ModelMessage[]) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare class AgentSession {
|
|
16
|
+
readonly id: string;
|
|
17
|
+
private readonly model;
|
|
18
|
+
private readonly maxSteps;
|
|
19
|
+
private readonly messages;
|
|
20
|
+
private readonly onPersist;
|
|
21
|
+
private readonly gate;
|
|
22
|
+
private readonly tools;
|
|
23
|
+
private readonly registry;
|
|
24
|
+
private emit;
|
|
25
|
+
private activeTurn;
|
|
26
|
+
constructor(options: AgentSessionOptions);
|
|
27
|
+
send(input: string): AsyncIterable<SessionEvent>;
|
|
28
|
+
private runTurn;
|
|
29
|
+
private requestApproval;
|
|
30
|
+
approve(approvalId: string): boolean;
|
|
31
|
+
reject(approvalId: string, reason?: string): boolean;
|
|
32
|
+
getMessages(): readonly ModelMessage[];
|
|
33
|
+
abort(): void;
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{randomUUID as e}from"node:crypto";import{stepCountIs as t,streamText as s}from"ai";import{buildAgentToolset as o}from"../tool-bridge/build-tools.js";import{readIsError as r}from"../tool-bridge/normalize-result.js";import{ApprovalGate as a}from"../approval/approval-gate.js";import{AsyncEventQueue as i}from"./event-queue.js";function l(e){return e instanceof Error?e.message:String(e)}function n(e){return{...void 0!==e.inputTokens?{inputTokens:e.inputTokens}:{},...void 0!==e.outputTokens?{outputTokens:e.outputTokens}:{},...void 0!==e.totalTokens?{totalTokens:e.totalTokens}:{}}}export class AgentSession{id;model;maxSteps;messages;onPersist;gate=new a;tools;registry;emit;activeTurn;constructor(e){this.id=e.id,this.model=e.model,this.maxSteps=e.maxSteps,this.messages=e.initialMessages?[...e.initialMessages]:[],this.onPersist=e.onPersist;const t=o(e.sources,{...e.policy?{policy:e.policy}:{},requestApproval:e=>this.requestApproval(e)});this.tools=t.tools,this.registry=t.registry}async*send(e){if(this.activeTurn)throw new Error("session already has an active turn");const t=new i;this.emit=e=>t.push(e);const s=this.messages.length;this.messages.push({role:"user",content:e});const o={abortController:new AbortController,aborted:!1};this.activeTurn=o,this.runTurn(t,o,s).catch(e=>{t.push({type:"error",stage:"execute",message:l(e)}),t.close()});try{for await(const e of t)yield e}finally{this.activeTurn===o&&this.abort(),void 0!==this.emit&&(this.emit=void 0)}}async runTurn(o,a,i){try{o.push({type:"message-start",messageId:e()});const p=s({model:this.model,messages:this.messages,tools:this.tools,stopWhen:t(this.maxSteps),abortSignal:a.abortController.signal});let u,m,h="";for await(const e of p.fullStream)switch(e.type){case"text-delta":h+=e.text,o.push({type:"text-delta",delta:e.text});break;case"tool-call":{const t=this.registry.resolve(e.toolName);o.push({type:"tool-call",toolCallId:e.toolCallId,agentName:t?.agentName??e.toolName,toolName:t?.toolName??e.toolName,input:e.input});break}case"tool-result":{const t=this.registry.resolve(e.toolName);o.push({type:"tool-result",toolCallId:e.toolCallId,agentName:t?.agentName??e.toolName,toolName:t?.toolName??e.toolName,output:e.output,isError:r(e.output)});break}case"tool-error":{const t=this.registry.resolve(e.toolName);o.push({type:"tool-result",toolCallId:e.toolCallId,agentName:t?.agentName??e.toolName,toolName:t?.toolName??e.toolName,output:l(e.error),isError:!0});break}case"finish-step":o.push({type:"step-finish",finishReason:e.finishReason,usage:n(e.usage)});break;case"finish":u=n(e.totalUsage);break;case"error":o.push({type:"error",stage:"execute",message:l(e.error)});break;case"abort":a.aborted=!0}if(a.aborted||a.abortController.signal.aborted)return this.messages.splice(i),void o.push({type:"error",stage:"execute",message:"aborted"});try{m=(await p.response).messages}catch(e){return this.messages.splice(i),void o.push({type:"error",stage:"execute",message:l(e)})}this.messages.push(...m),this.onPersist?.(this.messages.slice(i)),o.push({type:"message-finish",text:h,...u?{totalUsage:u}:{}})}catch(e){this.messages.splice(i),o.push({type:"error",stage:"execute",message:l(e)})}finally{this.activeTurn===a&&(this.activeTurn=void 0),o.close()}}requestApproval(t){const s=e(),o=this.gate.request(s);return void 0===this.emit?(this.gate.resolve(s,{approved:!1,reason:"approval event could not be delivered"}),o):(this.emit({type:"confirmation-required",approvalId:s,agentName:t.agentName,toolName:t.toolName,input:t.input,...t.reason?{reason:t.reason}:{}}),o)}approve(e){return this.gate.resolve(e,{approved:!0})}reject(e,t){return this.gate.resolve(e,{approved:!1,...t?{reason:t}:{}})}getMessages(){return this.messages}abort(){this.activeTurn&&(this.activeTurn.aborted=!0),this.gate.abortAll(),this.activeTurn?.abortController.abort()}}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { LanguageModelV3 } from "@ai-sdk/provider";
|
|
2
|
+
import { McpClientManager } from "@roll-agent/core/mcp/client-manager";
|
|
3
|
+
import type { RollConfig } from "@roll-agent/core/config/schema";
|
|
4
|
+
import type { RegisteredAgent } from "@roll-agent/core/types/agent";
|
|
5
|
+
import type { AgentToolSource } from "../tool-bridge/build-tools.ts";
|
|
6
|
+
import type { ToolPolicy } from "../types/policy.ts";
|
|
7
|
+
import type { ThreadStore } from "../store/thread-store.ts";
|
|
8
|
+
import { AgentSession } from "./agent-session.ts";
|
|
9
|
+
export interface ConversationEngineOptions {
|
|
10
|
+
readonly config: RollConfig;
|
|
11
|
+
readonly agents?: readonly RegisteredAgent[];
|
|
12
|
+
readonly model?: LanguageModelV3;
|
|
13
|
+
readonly sources?: readonly AgentToolSource[];
|
|
14
|
+
readonly clientManager?: McpClientManager;
|
|
15
|
+
readonly store?: ThreadStore;
|
|
16
|
+
readonly policy?: ToolPolicy;
|
|
17
|
+
readonly maxSteps?: number;
|
|
18
|
+
readonly onAgentBootstrapIssue?: (issue: AgentBootstrapIssue) => void;
|
|
19
|
+
}
|
|
20
|
+
export interface CreateSessionInput {
|
|
21
|
+
readonly title?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface AgentBootstrapIssue {
|
|
24
|
+
readonly agentName: string;
|
|
25
|
+
readonly message: string;
|
|
26
|
+
}
|
|
27
|
+
export declare class ConversationEngine {
|
|
28
|
+
private readonly config;
|
|
29
|
+
private readonly clientManager;
|
|
30
|
+
private readonly store;
|
|
31
|
+
private readonly policy;
|
|
32
|
+
private readonly maxSteps;
|
|
33
|
+
private readonly explicitAgents;
|
|
34
|
+
private readonly explicitModel;
|
|
35
|
+
private readonly explicitSources;
|
|
36
|
+
private readonly onAgentBootstrapIssue;
|
|
37
|
+
private ready;
|
|
38
|
+
constructor(options: ConversationEngineOptions);
|
|
39
|
+
createSession(input?: CreateSessionInput): Promise<AgentSession>;
|
|
40
|
+
resumeSession(threadId: string): Promise<AgentSession>;
|
|
41
|
+
private buildSession;
|
|
42
|
+
private ensureReady;
|
|
43
|
+
private bootstrap;
|
|
44
|
+
private resolveModel;
|
|
45
|
+
private resolveProviderName;
|
|
46
|
+
private resolveModelName;
|
|
47
|
+
dispose(): Promise<void>;
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{randomUUID as e}from"node:crypto";import{McpClientManager as t}from"@roll-agent/core/mcp/client-manager";import{createProviderModel as s}from"@roll-agent/core/llm/providers";import{AgentStore as o}from"@roll-agent/core/registry/store";import{resolveTransportWithDevSpawnSpec as i}from"@roll-agent/core/registry/dev-spawn";import{normalizeListedTools as r}from"@roll-agent/core/cli/utils/agent-tools";import{getAgentEnv as n}from"@roll-agent/core/config/helpers";import{AgentSession as l}from"./agent-session.js";const a=16;function c(e){if("object"!=typeof e||null===e||!("annotations"in e))return;const t=e.annotations;if("object"!=typeof t||null===t)return;const s={};return"readOnlyHint"in t&&"boolean"==typeof t.readOnlyHint&&(s.readOnlyHint=t.readOnlyHint),"destructiveHint"in t&&"boolean"==typeof t.destructiveHint&&(s.destructiveHint=t.destructiveHint),void 0===s.readOnlyHint&&void 0===s.destructiveHint?void 0:s}export class ConversationEngine{config;clientManager;store;policy;maxSteps;explicitAgents;explicitModel;explicitSources;onAgentBootstrapIssue;ready;constructor(e){this.config=e.config,this.clientManager=e.clientManager??new t,this.store=e.store,this.policy=e.policy,this.maxSteps=e.maxSteps??a,this.explicitAgents=e.agents,this.explicitModel=e.model,this.explicitSources=e.sources,this.onAgentBootstrapIssue=e.onAgentBootstrapIssue}async createSession(t={}){const s=await this.ensureReady(),o=this.store?this.store.createThread({...t.title?{title:t.title}:{},model:this.resolveModelName()}):e();return this.buildSession(s,o,[])}async resumeSession(e){if(!this.store)throw new Error("resumeSession requires a ThreadStore");if(!this.store.hasThread(e))throw new Error(`Thread "${e}" 不存在`);const t=await this.ensureReady();return this.buildSession(t,e,this.store.getMessages(e))}buildSession(e,t,s){const o=this.store;return new l({id:t,model:e.model,sources:e.sources,maxSteps:this.maxSteps,...this.policy?{policy:this.policy}:{},initialMessages:s,...o?{onPersist:e=>o.appendMessages(t,e)}:{}})}ensureReady(){return this.ready||(this.ready=this.bootstrap()),this.ready}async bootstrap(){const e=this.explicitModel??this.resolveModel();if(this.explicitSources)return{model:e,sources:this.explicitSources};const t=this.explicitAgents??new o(this.config.agents.dataDir).list(),s=[];for(const o of t)try{const t=i(o),l=n(this.config,o.skill.name),a=await this.clientManager.connect(o.skill.name,t,o.installPath,{samplingModel:e,...l?{env:l}:{}}),d=(await a.listTools()).tools,h=r(d).map((e,t)=>({tool:e,annotations:c(d[t])}));s.push({agentName:o.skill.name,client:a,tools:h})}catch(e){this.onAgentBootstrapIssue?.({agentName:o.skill.name,message:e instanceof Error?e.message:String(e)})}return{model:e,sources:s}}resolveModel(){const e=this.resolveProviderName(),t=this.resolveModelName(),o=this.config.llm.providers[e];if(!o)throw new Error(`LLM provider "${e}" 未配置`);return s(e,t,o.apiKey,o.baseUrl)}resolveProviderName(){return this.config.runtime.provider??this.config.llm.defaultProvider}resolveModelName(){return this.config.runtime.model??this.config.llm.defaultModel}async dispose(){await this.clientManager.disconnectAll()}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class AsyncEventQueue{buffer=[];resolver;closed=!1;push(e){if(!this.closed)if(this.resolver){const s=this.resolver;this.resolver=void 0,s({value:e,done:!1})}else this.buffer.push(e)}close(){if(!this.closed&&(this.closed=!0,this.resolver)){const e=this.resolver;this.resolver=void 0,e({value:void 0,done:!0})}}async*[Symbol.asyncIterator](){for(;;){if(this.buffer.length>0){yield this.buffer.shift();continue}if(this.closed)return;const e=await new Promise(e=>{this.resolver=e});if(e.done)return;yield e.value}}}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export { ConversationEngine } from "./engine/conversation-engine.ts";
|
|
2
|
+
export type { AgentBootstrapIssue, ConversationEngineOptions, CreateSessionInput, } from "./engine/conversation-engine.ts";
|
|
3
|
+
export { AgentSession } from "./engine/agent-session.ts";
|
|
4
|
+
export type { AgentSessionOptions } from "./engine/agent-session.ts";
|
|
5
|
+
export { buildAgentToolset } from "./tool-bridge/build-tools.ts";
|
|
6
|
+
export type { AgentToolSource, SourceTool, ApprovalRequest, ToolBridgeContext, BuiltToolset, } from "./tool-bridge/build-tools.ts";
|
|
7
|
+
export { ToolRegistry } from "./tool-bridge/naming.ts";
|
|
8
|
+
export type { ToolRoute } from "./tool-bridge/naming.ts";
|
|
9
|
+
export { normalizeToolResult } from "./tool-bridge/normalize-result.ts";
|
|
10
|
+
export type { NormalizedToolResult } from "./tool-bridge/normalize-result.ts";
|
|
11
|
+
export { ThreadStore, defaultThreadsDir, expandTilde } from "./store/thread-store.ts";
|
|
12
|
+
export type { ThreadRecord, CreateThreadInput } from "./store/thread-store.ts";
|
|
13
|
+
export { DefaultToolPolicy } from "./policy/default-policy.ts";
|
|
14
|
+
export { ConfigurableToolPolicy } from "./policy/configurable-policy.ts";
|
|
15
|
+
export type { ConfigurableToolPolicyOptions, ToolApprovalDefault, ToolApprovalOverrideAction, } from "./policy/configurable-policy.ts";
|
|
16
|
+
export type { ToolPolicy, ToolPolicyContext, PolicyDecision, PolicyAction, ToolAnnotations, } from "./types/policy.ts";
|
|
17
|
+
export { ApprovalGate } from "./approval/approval-gate.ts";
|
|
18
|
+
export type { ApprovalDecision } from "./approval/approval-gate.ts";
|
|
19
|
+
export { RuntimeServer } from "./server/runtime-server.ts";
|
|
20
|
+
export { createStdioConnection } from "./server/transport/stdio.ts";
|
|
21
|
+
export { RpcMethod, EVENT_NOTIFICATION, isRequest } from "./server/protocol.ts";
|
|
22
|
+
export type { JsonRpcConnection, JsonRpcMessage, JsonRpcRequest, JsonRpcNotification, JsonRpcId, } from "./server/protocol.ts";
|
|
23
|
+
export type { SessionEvent, SessionEventStage, SessionTokenUsage } from "./types/events.ts";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{ConversationEngine}from"./engine/conversation-engine.js";export{AgentSession}from"./engine/agent-session.js";export{buildAgentToolset}from"./tool-bridge/build-tools.js";export{ToolRegistry}from"./tool-bridge/naming.js";export{normalizeToolResult}from"./tool-bridge/normalize-result.js";export{ThreadStore,defaultThreadsDir,expandTilde}from"./store/thread-store.js";export{DefaultToolPolicy}from"./policy/default-policy.js";export{ConfigurableToolPolicy}from"./policy/configurable-policy.js";export{ApprovalGate}from"./approval/approval-gate.js";export{RuntimeServer}from"./server/runtime-server.js";export{createStdioConnection}from"./server/transport/stdio.js";export{RpcMethod,EVENT_NOTIFICATION,isRequest}from"./server/protocol.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { PolicyDecision, ToolPolicy, ToolPolicyContext } from "../types/policy.ts";
|
|
2
|
+
export declare const TOOL_APPROVAL_DEFAULTS: readonly ["guarded", "auto", "deny"];
|
|
3
|
+
export type ToolApprovalDefault = (typeof TOOL_APPROVAL_DEFAULTS)[number];
|
|
4
|
+
export declare const TOOL_APPROVAL_OVERRIDE_ACTIONS: readonly ["auto", "confirm", "deny"];
|
|
5
|
+
export type ToolApprovalOverrideAction = (typeof TOOL_APPROVAL_OVERRIDE_ACTIONS)[number];
|
|
6
|
+
export interface ConfigurableToolPolicyOptions {
|
|
7
|
+
readonly defaultMode?: ToolApprovalDefault;
|
|
8
|
+
readonly overrides?: Readonly<Record<string, ToolApprovalOverrideAction>>;
|
|
9
|
+
readonly fallback?: ToolPolicy;
|
|
10
|
+
}
|
|
11
|
+
export declare class ConfigurableToolPolicy implements ToolPolicy {
|
|
12
|
+
private readonly defaultMode;
|
|
13
|
+
private readonly overrides;
|
|
14
|
+
private readonly fallback;
|
|
15
|
+
constructor(options?: ConfigurableToolPolicyOptions);
|
|
16
|
+
check(context: ToolPolicyContext): PolicyDecision;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DefaultToolPolicy as o}from"./default-policy.js";export const TOOL_APPROVAL_DEFAULTS=["guarded","auto","deny"];export const TOOL_APPROVAL_OVERRIDE_ACTIONS=["auto","confirm","deny"];function e(o){return`${o.agentName}.${o.toolName}`}function t(o){return"auto"===o?{action:"allow"}:"confirm"===o?{action:"confirm",reason:"配置要求确认"}:{action:"deny",reason:"配置拒绝执行"}}export class ConfigurableToolPolicy{defaultMode;overrides;fallback;constructor(e={}){this.defaultMode=e.defaultMode??"guarded",this.overrides=e.overrides??{},this.fallback=e.fallback??new o}check(o){const a=this.overrides[e(o)];return void 0!==a?t(a):"auto"===this.defaultMode?!0===o.annotations?.destructiveHint?{action:"confirm",reason:"破坏性操作"}:{action:"allow"}:"deny"===this.defaultMode?{action:"deny",reason:"默认策略拒绝执行"}:this.fallback.check(o)}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=["send","write","delete","remove","update","create","post","submit","reply","pay","insert","drop","set","put","patch","add","edit","open","select","filter","exchange","cancel","approve","click","navigate","fill","type","press","upload","scroll"],t=["get","list","read","search","fetch","query","find","show","describe","inspect","status","check","count","view","load","scan","resolve","validate","format","preview","diagnostic","snapshot"],n=new Set(e),o=new Set(t);function a(e){return e.toLowerCase().split(/[_\-\s]+/).map(e=>e.trim()).filter(e=>e.length>0)}function r(e,t){return e.some(e=>t.has(e))}export class DefaultToolPolicy{check(e){const{annotations:t}=e,s=a(e.toolName);return!0===t?.destructiveHint?{action:"confirm",reason:"破坏性操作"}:r(s,n)?{action:"confirm",reason:"写/发送类操作"}:!0===t?.readOnlyHint||r(s,o)?{action:"allow"}:{action:"confirm",reason:"未知操作,默认需确认"}}}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export type JsonRpcId = number | string;
|
|
3
|
+
export interface JsonRpcRequest {
|
|
4
|
+
readonly jsonrpc: "2.0";
|
|
5
|
+
readonly id: JsonRpcId;
|
|
6
|
+
readonly method: string;
|
|
7
|
+
readonly params?: unknown;
|
|
8
|
+
}
|
|
9
|
+
export interface JsonRpcNotification {
|
|
10
|
+
readonly jsonrpc: "2.0";
|
|
11
|
+
readonly method: string;
|
|
12
|
+
readonly params?: unknown;
|
|
13
|
+
}
|
|
14
|
+
export interface JsonRpcSuccessResponse {
|
|
15
|
+
readonly jsonrpc: "2.0";
|
|
16
|
+
readonly id: JsonRpcId;
|
|
17
|
+
readonly result: unknown;
|
|
18
|
+
}
|
|
19
|
+
export interface JsonRpcErrorResponse {
|
|
20
|
+
readonly jsonrpc: "2.0";
|
|
21
|
+
readonly id: JsonRpcId | null;
|
|
22
|
+
readonly error: {
|
|
23
|
+
readonly code: number;
|
|
24
|
+
readonly message: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export type JsonRpcMessage = JsonRpcRequest | JsonRpcNotification | JsonRpcSuccessResponse | JsonRpcErrorResponse;
|
|
28
|
+
export interface JsonRpcConnection {
|
|
29
|
+
send(message: JsonRpcMessage): void;
|
|
30
|
+
onMessage(handler: (message: JsonRpcMessage) => void): void;
|
|
31
|
+
onClose(handler: () => void): void;
|
|
32
|
+
close(): void;
|
|
33
|
+
}
|
|
34
|
+
export declare const RpcMethod: {
|
|
35
|
+
readonly Create: "session.create";
|
|
36
|
+
readonly Resume: "session.resume";
|
|
37
|
+
readonly Send: "session.send";
|
|
38
|
+
readonly Approve: "session.approve";
|
|
39
|
+
readonly Reject: "session.reject";
|
|
40
|
+
readonly Abort: "session.abort";
|
|
41
|
+
readonly Messages: "session.messages";
|
|
42
|
+
};
|
|
43
|
+
export declare const EVENT_NOTIFICATION = "session.event";
|
|
44
|
+
export declare const createParamsSchema: z.ZodObject<{
|
|
45
|
+
title: z.ZodOptional<z.ZodString>;
|
|
46
|
+
}, "strip", z.ZodTypeAny, {
|
|
47
|
+
title?: string | undefined;
|
|
48
|
+
}, {
|
|
49
|
+
title?: string | undefined;
|
|
50
|
+
}>;
|
|
51
|
+
export declare const resumeParamsSchema: z.ZodObject<{
|
|
52
|
+
threadId: z.ZodString;
|
|
53
|
+
}, "strip", z.ZodTypeAny, {
|
|
54
|
+
threadId: string;
|
|
55
|
+
}, {
|
|
56
|
+
threadId: string;
|
|
57
|
+
}>;
|
|
58
|
+
export declare const sendParamsSchema: z.ZodObject<{
|
|
59
|
+
sessionId: z.ZodString;
|
|
60
|
+
input: z.ZodString;
|
|
61
|
+
}, "strip", z.ZodTypeAny, {
|
|
62
|
+
input: string;
|
|
63
|
+
sessionId: string;
|
|
64
|
+
}, {
|
|
65
|
+
input: string;
|
|
66
|
+
sessionId: string;
|
|
67
|
+
}>;
|
|
68
|
+
export declare const approveParamsSchema: z.ZodObject<{
|
|
69
|
+
sessionId: z.ZodString;
|
|
70
|
+
approvalId: z.ZodString;
|
|
71
|
+
}, "strip", z.ZodTypeAny, {
|
|
72
|
+
approvalId: string;
|
|
73
|
+
sessionId: string;
|
|
74
|
+
}, {
|
|
75
|
+
approvalId: string;
|
|
76
|
+
sessionId: string;
|
|
77
|
+
}>;
|
|
78
|
+
export declare const rejectParamsSchema: z.ZodObject<{
|
|
79
|
+
sessionId: z.ZodString;
|
|
80
|
+
approvalId: z.ZodString;
|
|
81
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
82
|
+
}, "strip", z.ZodTypeAny, {
|
|
83
|
+
approvalId: string;
|
|
84
|
+
sessionId: string;
|
|
85
|
+
reason?: string | undefined;
|
|
86
|
+
}, {
|
|
87
|
+
approvalId: string;
|
|
88
|
+
sessionId: string;
|
|
89
|
+
reason?: string | undefined;
|
|
90
|
+
}>;
|
|
91
|
+
export declare const abortParamsSchema: z.ZodObject<{
|
|
92
|
+
sessionId: z.ZodString;
|
|
93
|
+
}, "strip", z.ZodTypeAny, {
|
|
94
|
+
sessionId: string;
|
|
95
|
+
}, {
|
|
96
|
+
sessionId: string;
|
|
97
|
+
}>;
|
|
98
|
+
export declare const messagesParamsSchema: z.ZodObject<{
|
|
99
|
+
sessionId: z.ZodString;
|
|
100
|
+
}, "strip", z.ZodTypeAny, {
|
|
101
|
+
sessionId: string;
|
|
102
|
+
}, {
|
|
103
|
+
sessionId: string;
|
|
104
|
+
}>;
|
|
105
|
+
export declare function isRequest(message: JsonRpcMessage): message is JsonRpcRequest;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{z as s}from"zod";export const RpcMethod={Create:"session.create",Resume:"session.resume",Send:"session.send",Approve:"session.approve",Reject:"session.reject",Abort:"session.abort",Messages:"session.messages"};export const EVENT_NOTIFICATION="session.event";export const createParamsSchema=s.object({title:s.string().optional()});export const resumeParamsSchema=s.object({threadId:s.string()});export const sendParamsSchema=s.object({sessionId:s.string(),input:s.string()});export const approveParamsSchema=s.object({sessionId:s.string(),approvalId:s.string()});export const rejectParamsSchema=s.object({sessionId:s.string(),approvalId:s.string(),reason:s.string().optional()});export const abortParamsSchema=s.object({sessionId:s.string()});export const messagesParamsSchema=s.object({sessionId:s.string()});export function isRequest(s){return"method"in s&&"id"in s}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ConversationEngine } from "../engine/conversation-engine.ts";
|
|
2
|
+
import { type JsonRpcConnection } from "./protocol.ts";
|
|
3
|
+
export declare class RuntimeServer {
|
|
4
|
+
private readonly engine;
|
|
5
|
+
private readonly connection;
|
|
6
|
+
private readonly sessions;
|
|
7
|
+
constructor(engine: ConversationEngine, connection: JsonRpcConnection);
|
|
8
|
+
abortAll(): void;
|
|
9
|
+
private handleMessage;
|
|
10
|
+
private requireSession;
|
|
11
|
+
private dispatch;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{EVENT_NOTIFICATION as s,RpcMethod as e,abortParamsSchema as n,approveParamsSchema as t,createParamsSchema as r,isRequest as o,messagesParamsSchema as i,rejectParamsSchema as a,resumeParamsSchema as c,sendParamsSchema as d}from"./protocol.js";function h(s){return s instanceof Error?s.message:String(s)}export class RuntimeServer{engine;connection;sessions=new Map;constructor(s,e){this.engine=s,this.connection=e,this.connection.onMessage(s=>this.handleMessage(s))}abortAll(){for(const s of this.sessions.values())s.abort();this.sessions.clear()}handleMessage(s){o(s)&&this.dispatch(s).then(e=>{this.connection.send({jsonrpc:"2.0",id:s.id,result:e})}).catch(e=>{this.connection.send({jsonrpc:"2.0",id:s.id,error:{code:-32e3,message:h(e)}})})}requireSession(s){const e=this.sessions.get(s);if(!e)throw new Error(`Session "${s}" 不存在`);return e}async dispatch(o){switch(o.method){case e.Create:{const s=r.parse(o.params),e=await this.engine.createSession(s.title?{title:s.title}:{});return this.sessions.set(e.id,e),{sessionId:e.id}}case e.Resume:{const s=c.parse(o.params),e=await this.engine.resumeSession(s.threadId);return this.sessions.set(e.id,e),{sessionId:e.id}}case e.Send:{const e=d.parse(o.params),n=this.requireSession(e.sessionId);for await(const t of n.send(e.input))this.connection.send({jsonrpc:"2.0",method:s,params:{sessionId:e.sessionId,event:t}});return{status:"completed"}}case e.Approve:{const s=t.parse(o.params);return{resolved:this.requireSession(s.sessionId).approve(s.approvalId)}}case e.Reject:{const s=a.parse(o.params);return{resolved:this.requireSession(s.sessionId).reject(s.approvalId,s.reason)}}case e.Abort:{const s=n.parse(o.params);return this.requireSession(s.sessionId).abort(),{ok:!0}}case e.Messages:{const s=i.parse(o.params);return{messages:this.requireSession(s.sessionId).getMessages()}}default:throw new Error(`Unknown method: ${o.method}`)}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createInterface as n}from"node:readline";function o(n){return"object"==typeof n&&null!==n&&"jsonrpc"in n&&"2.0"===n.jsonrpc}export function createStdioConnection(e,t){const r=[],s=[],c=n({input:e});return c.on("line",n=>{const e=n.trim();if(0===e.length)return;let t;try{t=JSON.parse(e)}catch{return}if(o(t))for(const n of r)n(t)}),c.on("close",()=>{for(const n of s)n()}),{send(n){t.write(`${JSON.stringify(n)}\n`)},onMessage(n){r.push(n)},onClose(n){s.push(n)},close(){c.close()}}}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type ModelMessage } from "ai";
|
|
2
|
+
export interface ThreadRecord {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly title: string | undefined;
|
|
5
|
+
readonly model: string | undefined;
|
|
6
|
+
readonly createdAt: string;
|
|
7
|
+
readonly updatedAt: string;
|
|
8
|
+
}
|
|
9
|
+
export interface CreateThreadInput {
|
|
10
|
+
readonly id?: string;
|
|
11
|
+
readonly title?: string;
|
|
12
|
+
readonly model?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function expandTilde(path: string): string;
|
|
15
|
+
export declare function defaultThreadsDir(): string;
|
|
16
|
+
export declare class ThreadStore {
|
|
17
|
+
private readonly db;
|
|
18
|
+
constructor(dir?: string);
|
|
19
|
+
private init;
|
|
20
|
+
createThread(input?: CreateThreadInput): string;
|
|
21
|
+
hasThread(id: string): boolean;
|
|
22
|
+
getThread(id: string): ThreadRecord | undefined;
|
|
23
|
+
listThreads(): ThreadRecord[];
|
|
24
|
+
countMessages(threadId: string): number;
|
|
25
|
+
updateTitle(threadId: string, title: string): void;
|
|
26
|
+
deleteThread(threadId: string): void;
|
|
27
|
+
appendMessages(threadId: string, messages: readonly ModelMessage[]): void;
|
|
28
|
+
getMessages(threadId: string): ModelMessage[];
|
|
29
|
+
close(): void;
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{existsSync as e,mkdirSync as t}from"node:fs";import{homedir as r}from"node:os";import{resolve as d}from"node:path";import{randomUUID as a}from"node:crypto";import{DatabaseSync as s}from"node:sqlite";import{modelMessageSchema as i}from"ai";const n=1;export function expandTilde(e){return e.startsWith("~/")?d(r(),e.slice(2)):e}export function defaultThreadsDir(){return d(r(),".roll-agent","threads")}function E(e){return{id:e.id,title:e.title??void 0,model:e.model??void 0,createdAt:e.created_at,updatedAt:e.updated_at}}export class ThreadStore{db;constructor(r=defaultThreadsDir()){const a=expandTilde(r);e(a)||t(a,{recursive:!0}),this.db=new s(d(a,"threads.db")),this.init()}init(){this.db.exec("PRAGMA foreign_keys = ON;"),this.db.exec(`CREATE TABLE IF NOT EXISTS threads (\n id TEXT PRIMARY KEY,\n title TEXT,\n model TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n );\n CREATE TABLE IF NOT EXISTS messages (\n thread_id TEXT NOT NULL,\n idx INTEGER NOT NULL,\n role TEXT NOT NULL,\n content_json TEXT NOT NULL,\n created_at TEXT NOT NULL,\n PRIMARY KEY (thread_id, idx),\n FOREIGN KEY (thread_id) REFERENCES threads(id) ON DELETE CASCADE\n );\n PRAGMA user_version = ${String(1)};`)}createThread(e={}){const t=e.id??a(),r=(new Date).toISOString();return this.db.prepare("INSERT INTO threads (id, title, model, created_at, updated_at) VALUES (?, ?, ?, ?, ?)").run(t,e.title??null,e.model??null,r,r),t}hasThread(e){return void 0!==this.db.prepare("SELECT 1 FROM threads WHERE id = ?").get(e)}getThread(e){const t=this.db.prepare("SELECT * FROM threads WHERE id = ?").get(e);return t?E(t):void 0}listThreads(){return this.db.prepare("SELECT * FROM threads ORDER BY updated_at DESC, rowid DESC").all().map(E)}countMessages(e){return this.db.prepare("SELECT COUNT(*) AS n FROM messages WHERE thread_id = ?").get(e).n}updateTitle(e,t){this.db.prepare("UPDATE threads SET title = ? WHERE id = ?").run(t,e)}deleteThread(e){this.db.prepare("DELETE FROM threads WHERE id = ?").run(e)}appendMessages(e,t){if(0===t.length)return;if(!this.hasThread(e))throw new Error(`Thread "${e}" 不存在`);let r=this.db.prepare("SELECT COALESCE(MAX(idx), -1) AS maxIdx FROM messages WHERE thread_id = ?").get(e).maxIdx+1;const d=(new Date).toISOString(),a=this.db.prepare("INSERT INTO messages (thread_id, idx, role, content_json, created_at) VALUES (?, ?, ?, ?, ?)");this.db.exec("BEGIN");try{for(const s of t)a.run(e,r,s.role,JSON.stringify(s),d),r+=1;this.db.prepare("UPDATE threads SET updated_at = ? WHERE id = ?").run(d,e),this.db.exec("COMMIT")}catch(e){throw this.db.exec("ROLLBACK"),e}}getMessages(e){return this.db.prepare("SELECT content_json FROM messages WHERE thread_id = ? ORDER BY idx ASC").all(e).map(e=>i.parse(JSON.parse(e.content_json)))}close(){this.db.close()}}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type ToolSet } from "ai";
|
|
2
|
+
import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
3
|
+
import type { AgentTool } from "@roll-agent/core/types/agent";
|
|
4
|
+
import type { ApprovalDecision } from "../approval/approval-gate.ts";
|
|
5
|
+
import type { ToolAnnotations, ToolPolicy } from "../types/policy.ts";
|
|
6
|
+
import { ToolRegistry } from "./naming.ts";
|
|
7
|
+
export interface SourceTool {
|
|
8
|
+
readonly tool: AgentTool;
|
|
9
|
+
readonly annotations: ToolAnnotations | undefined;
|
|
10
|
+
}
|
|
11
|
+
export interface AgentToolSource {
|
|
12
|
+
readonly agentName: string;
|
|
13
|
+
readonly client: Client;
|
|
14
|
+
readonly tools: readonly SourceTool[];
|
|
15
|
+
}
|
|
16
|
+
export interface ApprovalRequest {
|
|
17
|
+
readonly agentName: string;
|
|
18
|
+
readonly toolName: string;
|
|
19
|
+
readonly input: Record<string, unknown>;
|
|
20
|
+
readonly reason: string | undefined;
|
|
21
|
+
}
|
|
22
|
+
export interface ToolBridgeContext {
|
|
23
|
+
readonly policy?: ToolPolicy;
|
|
24
|
+
readonly requestApproval: (request: ApprovalRequest) => Promise<ApprovalDecision>;
|
|
25
|
+
}
|
|
26
|
+
export interface BuiltToolset {
|
|
27
|
+
readonly tools: ToolSet;
|
|
28
|
+
readonly registry: ToolRegistry;
|
|
29
|
+
}
|
|
30
|
+
export declare function buildAgentToolset(sources: readonly AgentToolSource[], ctx: ToolBridgeContext): BuiltToolset;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsonSchema as o,tool as t}from"ai";import{preflightToolCall as n}from"@roll-agent/core/tool-runtime/preflight";import{ToolRegistry as r}from"./naming.js";import{normalizeToolResult as e}from"./normalize-result.js";function a(o){return"object"!=typeof o||null===o||Array.isArray(o)?{}:o}function i(o){return`参数校验失败: ${o.map(o=>o.message).join("; ")}`}async function s(o,t,n,r,e){if(!o.policy)return;const a=o.policy.check({agentName:t,toolName:n,input:r,...e?{annotations:e}:{}});if("deny"===a.action)return{output:"策略拒绝执行"+(a.reason?`: ${a.reason}`:""),isError:!0};if("confirm"===a.action){const e=await o.requestApproval({agentName:t,toolName:n,input:r,reason:a.reason});if(!e.approved)return{output:"已取消执行"+(e.reason?`: ${e.reason}`:""),isError:!0}}}export function buildAgentToolset(c,u){const m=new r,l={};for(const r of c){const{client:c,agentName:p}=r;for(const{tool:f,annotations:g}of r.tools){l[m.register(p,f.name)]=t({description:f.description??`${f.name} (via ${p})`,inputSchema:o(f.inputSchema),execute:async(o,t)=>{const r=a(o),m=n(f,r);if(!m.ok)return{output:i(m.issues),isError:!0};const l=await s(u,p,f.name,r,g);if(l)return l;const y=t.abortSignal?{signal:t.abortSignal}:void 0,d=await c.callTool({name:f.name,arguments:r},void 0,y);return e(d)}})}}return{tools:l,registry:m}}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ToolRoute {
|
|
2
|
+
readonly agentName: string;
|
|
3
|
+
readonly toolName: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class ToolRegistry {
|
|
6
|
+
private readonly routes;
|
|
7
|
+
register(agentName: string, toolName: string): string;
|
|
8
|
+
resolve(id: string): ToolRoute | undefined;
|
|
9
|
+
size(): number;
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=/[^a-zA-Z0-9_-]/g;function t(t){return t.replace(e,"_")}export class ToolRegistry{routes=new Map;register(e,r){const s=`${t(e)}__${t(r)}`;let o=s,n=1;for(;this.routes.has(o);)o=`${s}_${String(n)}`,n+=1;return this.routes.set(o,{agentName:e,toolName:r}),o}resolve(e){return this.routes.get(e)}size(){return this.routes.size}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{extractTextContent as o,isToolErrorResult as r}from"@roll-agent/core/cli/utils/tool-results";function t(o){return"object"==typeof o&&null!==o&&"content"in o?o.content:void 0}export function normalizeToolResult(n){const e=r(n),i=o(t(n));return{output:i.length>0?i.join("\n"):n,isError:e}}export function readIsError(o){return"object"==typeof o&&null!==o&&"isError"in o&&!0===o.isError}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export interface SessionTokenUsage {
|
|
2
|
+
readonly inputTokens?: number;
|
|
3
|
+
readonly outputTokens?: number;
|
|
4
|
+
readonly totalTokens?: number;
|
|
5
|
+
}
|
|
6
|
+
export type SessionEventStage = "bootstrap" | "plan" | "execute";
|
|
7
|
+
export type SessionEvent = {
|
|
8
|
+
readonly type: "message-start";
|
|
9
|
+
readonly messageId: string;
|
|
10
|
+
} | {
|
|
11
|
+
readonly type: "text-delta";
|
|
12
|
+
readonly delta: string;
|
|
13
|
+
} | {
|
|
14
|
+
readonly type: "tool-call";
|
|
15
|
+
readonly toolCallId: string;
|
|
16
|
+
readonly agentName: string;
|
|
17
|
+
readonly toolName: string;
|
|
18
|
+
readonly input: unknown;
|
|
19
|
+
} | {
|
|
20
|
+
readonly type: "tool-result";
|
|
21
|
+
readonly toolCallId: string;
|
|
22
|
+
readonly agentName: string;
|
|
23
|
+
readonly toolName: string;
|
|
24
|
+
readonly output: unknown;
|
|
25
|
+
readonly isError: boolean;
|
|
26
|
+
} | {
|
|
27
|
+
readonly type: "confirmation-required";
|
|
28
|
+
readonly approvalId: string;
|
|
29
|
+
readonly agentName: string;
|
|
30
|
+
readonly toolName: string;
|
|
31
|
+
readonly input: unknown;
|
|
32
|
+
readonly reason?: string;
|
|
33
|
+
} | {
|
|
34
|
+
readonly type: "step-finish";
|
|
35
|
+
readonly finishReason: string;
|
|
36
|
+
readonly usage?: SessionTokenUsage;
|
|
37
|
+
} | {
|
|
38
|
+
readonly type: "message-finish";
|
|
39
|
+
readonly text: string;
|
|
40
|
+
readonly totalUsage?: SessionTokenUsage;
|
|
41
|
+
} | {
|
|
42
|
+
readonly type: "error";
|
|
43
|
+
readonly stage: SessionEventStage;
|
|
44
|
+
readonly message: string;
|
|
45
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ToolAnnotations {
|
|
2
|
+
readonly readOnlyHint?: boolean;
|
|
3
|
+
readonly destructiveHint?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export type PolicyAction = "allow" | "confirm" | "deny";
|
|
6
|
+
export interface PolicyDecision {
|
|
7
|
+
readonly action: PolicyAction;
|
|
8
|
+
readonly reason?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ToolPolicyContext {
|
|
11
|
+
readonly agentName: string;
|
|
12
|
+
readonly toolName: string;
|
|
13
|
+
readonly input: Record<string, unknown>;
|
|
14
|
+
readonly annotations?: ToolAnnotations;
|
|
15
|
+
}
|
|
16
|
+
export interface ToolPolicy {
|
|
17
|
+
check(context: ToolPolicyContext): PolicyDecision;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{};
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@roll-agent/runtime",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/steveoon/roll-agent"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/steveoon/roll-agent",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/steveoon/roll-agent/issues"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=22.6.0"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@ai-sdk/provider": "^3.0.8",
|
|
30
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
31
|
+
"ai": "^6.0.154",
|
|
32
|
+
"zod": "^3.25.76"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^22.0.0",
|
|
36
|
+
"@roll-agent/core": "0.11.0"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && node ../../scripts/obfuscate.mjs",
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"test": "node --experimental-strip-types --experimental-sqlite --test \"src/**/*.test.ts\"",
|
|
42
|
+
"clean": "rm -rf dist"
|
|
43
|
+
}
|
|
44
|
+
}
|