@roll-agent/client-node 0.0.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 ADDED
@@ -0,0 +1,52 @@
1
+ # `@roll-agent/client-node`
2
+
3
+ 面向 Node.js、Electron 主进程和本地 Companion 的 Roll Runtime Protocol v1 客户端。
4
+
5
+ 它负责启动或连接 Runtime、初始化协商、JSON-RPC 请求、流式事件、协议校验、未知 Turn
6
+ 结果跟踪,以及可等待的有界子进程关闭。Renderer 不应直接持有该客户端或子进程句柄。
7
+
8
+ ## 安装
9
+
10
+ ```bash
11
+ pnpm add @roll-agent/client-node
12
+ ```
13
+
14
+ ## 最小示例
15
+
16
+ ```ts
17
+ import { randomUUID } from "node:crypto";
18
+ import { RollNodeClient } from "@roll-agent/client-node";
19
+
20
+ const client = await RollNodeClient.start({
21
+ cwd: "/absolute/path/to/workspace",
22
+ onTurnOutcomeUnknown: (turnId) => {
23
+ console.error(`Turn ${turnId} 的结果未知;不要自动重放`);
24
+ },
25
+ });
26
+
27
+ try {
28
+ const { thread } = await client.request("thread.create", {
29
+ requestId: randomUUID(),
30
+ title: "My UI",
31
+ });
32
+ await client.request("turn.start", {
33
+ requestId: randomUUID(),
34
+ threadId: thread.id,
35
+ turnId: randomUUID(),
36
+ input: { text: "检查这个项目" },
37
+ });
38
+ } finally {
39
+ await client.shutdown();
40
+ }
41
+ ```
42
+
43
+ `turn.start` 只确认接收。应用必须持续消费 `onEvent()`,并把
44
+ `onTurnOutcomeUnknown()` 作为本地活动状态的收敛信号:停止 Working 状态、结束本地 waiter、
45
+ 保留部分输出,随后在健康连接上或重连后读取 Snapshot。未知副作用不能自动重放。
46
+
47
+ ## 文档
48
+
49
+ - [Node 客户端 API 参考](https://github.com/steveoon/roll-agent/blob/main/docs/client-node-reference.md)
50
+ - [Runtime Protocol v1 参考](https://github.com/steveoon/roll-agent/blob/main/docs/runtime-protocol-v1-reference.md)
51
+ - [创建第一个 Runtime UI 客户端](https://github.com/steveoon/roll-agent/blob/main/docs/tutorial-runtime-ui-quickstart.md)
52
+ - [Electron 参考适配器](https://github.com/steveoon/roll-agent/tree/main/examples/electron-runtime-client)
@@ -0,0 +1,144 @@
1
+ import type { Readable, Writable } from "node:stream";
2
+ import { type InitializeResult, type RuntimeEventEnvelope, type RuntimeMethod, type RuntimeMethodInput, type RuntimeMethodResult, type RuntimeProtocolErrorData, type TurnId } from "@roll-agent/protocol";
3
+ export interface RuntimeClientTransport {
4
+ readonly stdin: Writable;
5
+ readonly stdout: Readable;
6
+ readonly stderr?: Readable;
7
+ onExit(listener: (code: number | null, signal: NodeJS.Signals | null) => void): void;
8
+ close(): void;
9
+ terminate?(): void;
10
+ forceClose?(): void;
11
+ }
12
+ export interface RuntimeShutdownOptions {
13
+ readonly gracefulTimeoutMs?: number;
14
+ readonly terminateTimeoutMs?: number;
15
+ readonly forceKillTimeoutMs?: number;
16
+ }
17
+ export interface RollNodeClientOptions {
18
+ readonly cwd: string;
19
+ readonly command?: string;
20
+ readonly args?: readonly string[];
21
+ readonly env?: NodeJS.ProcessEnv;
22
+ readonly clientName?: string;
23
+ readonly clientVersion?: string;
24
+ readonly onStderr?: (line: string) => void;
25
+ readonly onTurnOutcomeUnknown?: (turnId: TurnId) => void;
26
+ readonly maxFrameBytes?: number;
27
+ readonly requestTimeoutMs?: number;
28
+ readonly maxReadRetries?: number;
29
+ readonly readRetryDelayMs?: number;
30
+ readonly shutdownOptions?: RuntimeShutdownOptions;
31
+ }
32
+ export interface ConnectRuntimeClientOptions {
33
+ readonly transport: RuntimeClientTransport;
34
+ readonly clientName?: string;
35
+ readonly clientVersion?: string;
36
+ readonly onStderr?: (line: string) => void;
37
+ readonly onTurnOutcomeUnknown?: (turnId: TurnId) => void;
38
+ readonly maxFrameBytes?: number;
39
+ readonly requestTimeoutMs?: number;
40
+ readonly maxReadRetries?: number;
41
+ readonly readRetryDelayMs?: number;
42
+ readonly shutdownOptions?: RuntimeShutdownOptions;
43
+ }
44
+ export interface RuntimeClientExit {
45
+ readonly code: number | null;
46
+ readonly signal: NodeJS.Signals | null;
47
+ readonly error: Error;
48
+ }
49
+ export declare class RollRpcError extends Error {
50
+ readonly code: number;
51
+ readonly data: RuntimeProtocolErrorData | undefined;
52
+ constructor(error: {
53
+ readonly code: number;
54
+ readonly message: string;
55
+ readonly data?: RuntimeProtocolErrorData;
56
+ });
57
+ }
58
+ export declare class RollRuntimeExitedError extends Error {
59
+ readonly code: number | null;
60
+ readonly signal: NodeJS.Signals | null;
61
+ constructor(code: number | null, signal: NodeJS.Signals | null);
62
+ }
63
+ export declare class RollRequestTimeoutError extends Error {
64
+ readonly method: RuntimeMethod;
65
+ readonly timeoutMs: number;
66
+ constructor(method: RuntimeMethod, timeoutMs: number);
67
+ }
68
+ export declare class RollRequestFrameTooLargeError extends Error {
69
+ readonly frameBytes: number;
70
+ readonly maxFrameBytes: number;
71
+ constructor(frameBytes: number, maxFrameBytes: number);
72
+ }
73
+ export declare class RollRuntimeClosingError extends Error {
74
+ constructor();
75
+ }
76
+ export declare class RollRuntimeShutdownTimeoutError extends Error {
77
+ readonly gracefulTimeoutMs: number;
78
+ readonly terminateTimeoutMs: number;
79
+ readonly forceKillTimeoutMs: number;
80
+ constructor(gracefulTimeoutMs: number, terminateTimeoutMs: number, forceKillTimeoutMs: number);
81
+ }
82
+ export declare class RollProtocolViolationError extends Error {
83
+ constructor(message: string, cause?: unknown);
84
+ }
85
+ export declare class RollUncorrelatedRpcError extends RollRpcError {
86
+ constructor(error: {
87
+ readonly code: number;
88
+ readonly message: string;
89
+ readonly data?: RuntimeProtocolErrorData;
90
+ });
91
+ }
92
+ export declare class RollNodeClient {
93
+ private readonly transport;
94
+ private readonly maxFrameBytes;
95
+ private outboundMaxFrameBytes;
96
+ private readonly pending;
97
+ private readonly listeners;
98
+ private readonly exitListeners;
99
+ private readonly activeTurns;
100
+ private readonly unknownTurns;
101
+ private readonly onTurnOutcomeUnknown;
102
+ private readonly requestTimeoutMs;
103
+ private readonly maxReadRetries;
104
+ private readonly readRetryDelayMs;
105
+ private readonly defaultShutdownOptions;
106
+ private readonly outputReader;
107
+ private readonly stderrReader;
108
+ private requestId;
109
+ private writeQueue;
110
+ private readonly exitPromise;
111
+ private resolveExit;
112
+ private exited;
113
+ private closing;
114
+ private outputReaderClosed;
115
+ private stderrReaderClosed;
116
+ private initializationResult;
117
+ private connectionFailure;
118
+ private exitResult;
119
+ private shutdownPromise;
120
+ private constructor();
121
+ static start(options: RollNodeClientOptions): Promise<RollNodeClient>;
122
+ static connect(options: ConnectRuntimeClientOptions): Promise<RollNodeClient>;
123
+ onEvent(listener: (event: RuntimeEventEnvelope) => void): () => void;
124
+ onExit(listener: (exit: RuntimeClientExit) => void): () => void;
125
+ getInitializationResult(): InitializeResult;
126
+ request<TMethod extends RuntimeMethod>(method: TMethod, input: RuntimeMethodInput<TMethod>): Promise<RuntimeMethodResult<TMethod>>;
127
+ private requestOnce;
128
+ getOutcomeUnknownTurnIds(): readonly TurnId[];
129
+ close(): void;
130
+ shutdown(options?: RuntimeShutdownOptions): Promise<RuntimeClientExit>;
131
+ private performShutdown;
132
+ private write;
133
+ private handleLine;
134
+ private handleEvent;
135
+ private handleExit;
136
+ private failProtocol;
137
+ private failConnection;
138
+ private closeOutputReader;
139
+ private closeReaders;
140
+ private finishExit;
141
+ private rejectPending;
142
+ private markActiveTurnsOutcomeUnknown;
143
+ private markTurnOutcomeUnknown;
144
+ }
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{spawn as e}from"node:child_process";import{once as t}from"node:events";import{createInterface as r}from"node:readline";import{RUNTIME_EVENT_NOTIFICATION as o,RUNTIME_METHODS as i,RUNTIME_PROTOCOL_VERSION as n,parseRuntimeMethodParams as s,parseRuntimeMethodResult as l,runtimeEventEnvelopeSchema as a,runtimeProtocolErrorDataSchema as u}from"@roll-agent/protocol";const d=4194304,c=1,h=100,m=3e4,R=3e4,w=1e4,f=5e3,p=new Set([i.threadList,i.threadSnapshot,i.threadCapabilities,i.operationGet]);export class RollRpcError extends Error{code;data;constructor(e){super(e.message),this.name="RollRpcError",this.code=e.code,this.data=e.data}}export class RollRuntimeExitedError extends Error{code;signal;constructor(e,t){super(`Roll Runtime exited before the request completed (code=${String(e)}, signal=${String(t)})`),this.name="RollRuntimeExitedError",this.code=e,this.signal=t}}export class RollRequestTimeoutError extends Error{method;timeoutMs;constructor(e,t){super(`Roll Runtime request "${e}" timed out after ${String(t)} ms`),this.name="RollRequestTimeoutError",this.method=e,this.timeoutMs=t}}export class RollRequestFrameTooLargeError extends Error{frameBytes;maxFrameBytes;constructor(e,t){super(`Roll Runtime request frame is ${String(e)} bytes, exceeding the ${String(t)} byte limit`),this.name="RollRequestFrameTooLargeError",this.frameBytes=e,this.maxFrameBytes=t}}export class RollRuntimeClosingError extends Error{constructor(){super("Roll Runtime client is shutting down"),this.name="RollRuntimeClosingError"}}export class RollRuntimeShutdownTimeoutError extends Error{gracefulTimeoutMs;terminateTimeoutMs;forceKillTimeoutMs;constructor(e,t,r){super(`Roll Runtime did not exit within ${String(e+t+r)} ms`),this.name="RollRuntimeShutdownTimeoutError",this.gracefulTimeoutMs=e,this.terminateTimeoutMs=t,this.forceKillTimeoutMs=r}}export class RollProtocolViolationError extends Error{constructor(e,t){super(e,void 0===t?void 0:{cause:t}),this.name="RollProtocolViolationError"}}export class RollUncorrelatedRpcError extends RollRpcError{constructor(e){super(e),this.name="RollUncorrelatedRpcError"}}function x(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function v(e){return"string"==typeof e||"number"==typeof e&&Number.isFinite(e)}function E(e,t){if(!Number.isInteger(e)||e<=0)throw new Error(`${t} must be a positive integer`);return e}function y(e={}){return{gracefulTimeoutMs:E(e.gracefulTimeoutMs??R,"gracefulTimeoutMs"),terminateTimeoutMs:E(e.terminateTimeoutMs??w,"terminateTimeoutMs"),forceKillTimeoutMs:E(e.forceKillTimeoutMs??f,"forceKillTimeoutMs")}}function g(e,t){if(!x(e)||"number"!=typeof e.code||!Number.isInteger(e.code)||"string"!=typeof e.message)throw new RollProtocolViolationError(`Roll Runtime returned an invalid error for ${t}`);const r=void 0===e.data?void 0:u.safeParse(e.data);if(void 0!==r&&!r.success)throw new RollProtocolViolationError(`Roll Runtime returned invalid error data for ${t}`,r.error);return{code:e.code,message:e.message,...!0===r?.success?{data:r.data}:{}}}function T(e,t){return new Promise((r,o)=>{const i=setTimeout(()=>r(void 0),t);e.then(e=>{clearTimeout(i),r(e)},e=>{clearTimeout(i),o(e instanceof Error?e:new Error(String(e)))})})}function M(e){return{stdin:e.stdin,stdout:e.stdout,stderr:e.stderr,onExit(t){let r=!1;const o=(e,o)=>{r||(r=!0,t(e,o))};e.once("close",o),e.once("error",()=>o(null,null))},close(){e.stdin.end()},terminate(){null===e.exitCode&&null===e.signalCode&&e.kill("SIGTERM")},forceClose(){null===e.exitCode&&null===e.signalCode&&e.kill("SIGKILL")}}}export class RollNodeClient{transport;maxFrameBytes;outboundMaxFrameBytes;pending=new Map;listeners=new Set;exitListeners=new Set;activeTurns=new Set;unknownTurns=new Set;onTurnOutcomeUnknown;requestTimeoutMs;maxReadRetries;readRetryDelayMs;defaultShutdownOptions;outputReader;stderrReader;requestId=0;writeQueue=Promise.resolve();exitPromise;resolveExit;exited=!1;closing=!1;outputReaderClosed=!1;stderrReaderClosed=!1;initializationResult;connectionFailure;exitResult;shutdownPromise;constructor(e){if(this.transport=e.transport,this.maxFrameBytes=e.maxFrameBytes??d,this.outboundMaxFrameBytes=this.maxFrameBytes,this.onTurnOutcomeUnknown=e.onTurnOutcomeUnknown,this.requestTimeoutMs=e.requestTimeoutMs??m,this.maxReadRetries=e.maxReadRetries??1,this.readRetryDelayMs=e.readRetryDelayMs??h,this.defaultShutdownOptions=y(e.shutdownOptions),!Number.isInteger(this.maxFrameBytes)||this.maxFrameBytes<=0)throw new Error("maxFrameBytes must be a positive integer");if(!Number.isInteger(this.requestTimeoutMs)||this.requestTimeoutMs<=0)throw new Error("requestTimeoutMs must be a positive integer");if(!Number.isInteger(this.maxReadRetries)||this.maxReadRetries<0)throw new Error("maxReadRetries must be a non-negative integer");if(!Number.isInteger(this.readRetryDelayMs)||this.readRetryDelayMs<0)throw new Error("readRetryDelayMs must be a non-negative integer");this.exitPromise=new Promise(e=>{this.resolveExit=e}),this.outputReader=r({input:e.transport.stdout}),this.outputReader.on("line",e=>this.handleLine(e)),this.stderrReader=void 0===e.transport.stderr?void 0:r({input:e.transport.stderr}),this.stderrReader?.on("line",t=>e.onStderr?.(t)),this.transport.onExit((e,t)=>this.handleExit(e,t))}static async start(t){if(0===t.cwd.trim().length)throw new Error("RollNodeClient requires an explicit non-empty cwd");const r=e(t.command??"roll",[...t.args??["runtime","serve","--stdio"]],{cwd:t.cwd,env:t.env??process.env,shell:!1,stdio:"pipe"});return await RollNodeClient.connect({transport:M(r),...void 0!==t.clientName?{clientName:t.clientName}:{},...void 0!==t.clientVersion?{clientVersion:t.clientVersion}:{},...void 0!==t.onStderr?{onStderr:t.onStderr}:{},...void 0!==t.onTurnOutcomeUnknown?{onTurnOutcomeUnknown:t.onTurnOutcomeUnknown}:{},...void 0!==t.maxFrameBytes?{maxFrameBytes:t.maxFrameBytes}:{},...void 0!==t.requestTimeoutMs?{requestTimeoutMs:t.requestTimeoutMs}:{},...void 0!==t.maxReadRetries?{maxReadRetries:t.maxReadRetries}:{},...void 0!==t.readRetryDelayMs?{readRetryDelayMs:t.readRetryDelayMs}:{},...void 0!==t.shutdownOptions?{shutdownOptions:t.shutdownOptions}:{}})}static async connect(e){let t;try{return t=new RollNodeClient(e),t.initializationResult=await t.request(i.initialize,{protocolVersions:[n],client:{name:e.clientName??"@roll-agent/client-node",version:e.clientVersion??"0.1.0"}}),t.outboundMaxFrameBytes=Math.min(t.maxFrameBytes,t.initializationResult.limits.maxFrameBytes),t}catch(r){throw void 0===t?e.transport.close():await t.shutdown().catch(()=>{}),r}}onEvent(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}onExit(e){const t=this.exitResult;return void 0!==t?(queueMicrotask(()=>e(t)),()=>{}):(this.exitListeners.add(e),()=>{this.exitListeners.delete(e)})}getInitializationResult(){if(void 0===this.initializationResult)throw new Error("Roll Runtime client has not completed initialization");return this.initializationResult}async request(e,t){if(void 0!==this.connectionFailure)throw this.connectionFailure;if(this.exited)throw this.exitResult?.error??new RollRuntimeExitedError(null,null);if(this.closing)throw new RollRuntimeClosingError;const r=s(e,t),o=e===i.turnStart?s(i.turnStart,r).turnId:void 0;void 0!==o&&this.activeTurns.add(o);let n=0;for(;;)try{return await this.requestOnce(e,r)}catch(t){if(!p.has(e)||!(t instanceof RollRpcError)||!0!==t.data?.retryable||n>=this.maxReadRetries)throw void 0!==o&&(t instanceof RollRpcError&&!(t instanceof RollUncorrelatedRpcError)||t instanceof RollRequestFrameTooLargeError?this.activeTurns.delete(o):this.markTurnOutcomeUnknown(o)),t;n+=1,await new Promise(e=>{setTimeout(e,this.readRetryDelayMs)})}}async requestOnce(e,t){const r=this.requestId;this.requestId+=1;const o=new Promise((t,o)=>{const i=setTimeout(()=>{this.pending.delete(r)&&o(new RollRequestTimeoutError(e,this.requestTimeoutMs))},this.requestTimeoutMs);this.pending.set(r,{method:e,resolve:t,reject:o,timer:i})});try{await this.write({jsonrpc:"2.0",id:r,method:e,params:t});const i=await o;try{return l(e,i)}catch(t){const r=new RollProtocolViolationError(`Roll Runtime returned an invalid result for "${e}"`,t);throw this.failProtocol(r),r}}catch(e){const t=this.pending.get(r);throw void 0!==t&&(clearTimeout(t.timer),this.pending.delete(r)),e}}getOutcomeUnknownTurnIds(){return[...this.unknownTurns]}close(){this.shutdown().catch(()=>{})}shutdown(e){const t=this.exitResult;return void 0!==t?Promise.resolve(t):(this.shutdownPromise??=this.performShutdown(void 0===e?this.defaultShutdownOptions:y(e)),this.shutdownPromise)}async performShutdown(e){const{gracefulTimeoutMs:t,terminateTimeoutMs:r,forceKillTimeoutMs:o}=e;this.closing=!0,this.transport.close();const i=await T(this.exitPromise,t);if(void 0!==i)return i;if(void 0!==this.transport.terminate){this.transport.terminate();const e=await T(this.exitPromise,r);if(void 0!==e)return e}if(void 0===this.transport.forceClose){const e=new RollRuntimeShutdownTimeoutError(t,r,o);throw this.finishExit(e,null,null),this.closeReaders(),e}this.transport.forceClose();const n=await T(this.exitPromise,o);if(void 0!==n)return n;const s=new RollRuntimeShutdownTimeoutError(t,r,o);throw this.finishExit(s,null,null),this.closeReaders(),s}async write(e){const r=JSON.stringify(e),o=Buffer.byteLength(r,"utf8");if(o>this.outboundMaxFrameBytes)throw new RollRequestFrameTooLargeError(o,this.outboundMaxFrameBytes);const i=`${r}\n`;this.writeQueue=this.writeQueue.then(async()=>{this.transport.stdin.write(i)||await t(this.transport.stdin,"drain")});try{await this.writeQueue}catch(e){const t=new RollProtocolViolationError("Failed to write to the Roll Runtime transport",e);throw this.failProtocol(t),t}}handleLine(e){if(Buffer.byteLength(e,"utf8")>this.maxFrameBytes)return void this.failProtocol(new RollProtocolViolationError(`Roll Runtime frame exceeds ${String(this.maxFrameBytes)} bytes`));let t;try{t=JSON.parse(e)}catch(e){return void this.failProtocol(new RollProtocolViolationError("Roll Runtime emitted invalid JSON",e))}if(!x(t)||"2.0"!==t.jsonrpc)return void this.failProtocol(new RollProtocolViolationError("Roll Runtime emitted an invalid JSON-RPC frame"));if(t.method===o){const e=a.safeParse(t.params);return e.success?void this.handleEvent(e.data):void this.failProtocol(new RollProtocolViolationError("Roll Runtime emitted an invalid runtime.event",e.error))}if(null===t.id){if(!Object.hasOwn(t,"error")||Object.hasOwn(t,"result"))return void this.failProtocol(new RollProtocolViolationError("Roll Runtime response with a null id must contain exactly one error"));try{this.failConnection(new RollUncorrelatedRpcError(g(t.error,"an uncorrelated request")))}catch(e){this.failProtocol(e instanceof RollProtocolViolationError?e:new RollProtocolViolationError("Roll Runtime returned an invalid uncorrelated error",e))}return}if(!v(t.id))return void this.failProtocol(new RollProtocolViolationError("Roll Runtime response has an invalid id"));const r=this.pending.get(t.id);if(void 0===r)return;const i=void 0!==t.error;if(i!==Object.hasOwn(t,"result")){if(i){let e;try{e=new RollRpcError(g(t.error,`"${r.method}"`))}catch(e){return void this.failProtocol(e instanceof RollProtocolViolationError?e:new RollProtocolViolationError(`Roll Runtime returned an invalid error for "${r.method}"`,e))}return this.pending.delete(t.id),clearTimeout(r.timer),void r.reject(e)}this.pending.delete(t.id),clearTimeout(r.timer),r.resolve(t.result)}else this.failProtocol(new RollProtocolViolationError(`Roll Runtime response for "${r.method}" must contain exactly one result or error`))}handleEvent(e){void 0===e.turnId||"turn.completed"!==e.event.type&&"turn.cancelled"!==e.event.type&&"turn.failed"!==e.event.type||this.activeTurns.delete(e.turnId);for(const t of this.listeners)t(e)}handleExit(e,t){this.finishExit(this.connectionFailure??new RollRuntimeExitedError(e,t),e,t),this.closeReaders()}failProtocol(e){this.failConnection(e)}failConnection(e){void 0!==this.connectionFailure||this.exited||(this.connectionFailure=e,this.closing=!0,this.rejectPending(e),this.markActiveTurnsOutcomeUnknown(),this.closeOutputReader(),this.shutdown().catch(()=>{}))}closeOutputReader(){this.outputReaderClosed||(this.outputReaderClosed=!0,this.outputReader.close())}closeReaders(){this.closeOutputReader(),void 0===this.stderrReader||this.stderrReaderClosed||(this.stderrReaderClosed=!0,this.stderrReader.close())}finishExit(e,t,r){if(!this.exited){this.exited=!0,this.closing=!0,this.rejectPending(e),this.markActiveTurnsOutcomeUnknown(),this.exitResult={code:t,signal:r,error:e},this.resolveExit(this.exitResult);for(const e of this.exitListeners)e(this.exitResult);this.exitListeners.clear()}}rejectPending(e){for(const t of this.pending.values())clearTimeout(t.timer),t.reject(e);this.pending.clear()}markActiveTurnsOutcomeUnknown(){for(const e of this.activeTurns)this.markTurnOutcomeUnknown(e);this.activeTurns.clear()}markTurnOutcomeUnknown(e){this.activeTurns.delete(e),this.unknownTurns.has(e)||(this.unknownTurns.add(e),this.onTurnOutcomeUnknown?.(e))}}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@roll-agent/client-node",
3
+ "version": "0.0.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
+ "@roll-agent/protocol": "0.0.0"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^22.0.0"
33
+ },
34
+ "scripts": {
35
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && node ../../scripts/obfuscate.mjs",
36
+ "typecheck": "tsc --noEmit",
37
+ "test": "node --experimental-strip-types --test \"src/**/*.test.ts\"",
38
+ "clean": "rm -rf dist"
39
+ }
40
+ }