@demicodes/agent 0.1.0 → 0.2.1
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/client-entry.d.mts +2 -2
- package/dist/client-entry.mjs +1 -1
- package/dist/index.d.mts +59 -30
- package/dist/index.mjs +148 -70
- package/dist/stdio-transport.d.mts +1 -2
- package/dist/stdio-transport.mjs +3 -3
- package/dist/{transport-BkAbPvRc.d.mts → transport-DVa_82EW.d.mts} +2 -3
- package/dist/{websocket-transport-o6r-jV5p.mjs → websocket-transport-Bod0puog.mjs} +3 -3
- package/dist/{websocket-transport-D6zJ4PLC.d.mts → websocket-transport-Cn_rhIIX.d.mts} +1 -2
- package/package.json +5 -5
- package/dist/json-codec-BFLXlg3K.mjs +0 -70
package/dist/client-entry.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as TranscriptPatch, l as ServerFrame, n as AgentServerTransport, o as ClientFrame, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandSnapshotLike } from "./transport-
|
|
2
|
-
import { a as AgentClientListener, i as AgentClient, n as createWebSocketClientTransport, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-
|
|
1
|
+
import { d as TranscriptPatch, l as ServerFrame, n as AgentServerTransport, o as ClientFrame, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandSnapshotLike } from "./transport-DVa_82EW.mjs";
|
|
2
|
+
import { a as AgentClientListener, i as AgentClient, n as createWebSocketClientTransport, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-Cn_rhIIX.mjs";
|
|
3
3
|
import { ProviderSelection } from "@demicodes/provider";
|
|
4
4
|
export { AgentClient, type AgentClientListener, type AgentClientTransport, type AgentServerTransport, type AgentTransport, type ClientFrame, type ClientSessionEvent, type JsonWebSocket, type ProviderSelection, type ServerFrame, type ShellCommandSnapshotLike, type TranscriptPatch, createWebSocketClientTransport, createWebSocketServerTransport };
|
package/dist/client-entry.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as createWebSocketServerTransport, r as AgentClient, t as createWebSocketClientTransport } from "./websocket-transport-
|
|
1
|
+
import { n as createWebSocketServerTransport, r as AgentClient, t as createWebSocketClientTransport } from "./websocket-transport-Bod0puog.mjs";
|
|
2
2
|
export { AgentClient, createWebSocketClientTransport, createWebSocketServerTransport };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { A as AgentToolInvokeResult, B as DEFAULT_TURN_RETRY_POLICY, C as AgentSessionRestoreParams, D as AgentTool, E as AgentSystemPromptContext, F as CompactionWindow, H as isRetryableCode, I as DrainedTranscriptPatches, L as Transcript, M as SessionEvent, N as SessionEventListener, O as AgentToolContext, P as ToolContinuation, R as TranscriptOptions, S as AgentSessionParams, T as AgentSessionStore, U as resolveRetryPolicy, V as TurnRetryPolicy, W as retryDelayMs, _ as AgentHarnessRuntime, a as createInProcessTransportPair, b as AgentReferenceResolveContext, c as ConversationSummary, d as TranscriptPatch, f as AbortResult, g as AgentHarnessContext, h as AgentHarness, i as InProcessTransportPair, j as ExternalMutationReservation, k as AgentToolInvokeContext, l as ServerFrame, m as AgentDisposeContext, n as AgentServerTransport, o as ClientFrame, p as AbortTarget, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandSnapshotLike, v as AgentLifecycleEvent, w as AgentSessionSnapshot, x as AgentSessionOptions, y as AgentPromptContext, z as estimateTranscriptBlockTokens } from "./transport-
|
|
2
|
-
import { a as AgentClientListener, i as AgentClient, n as createWebSocketClientTransport, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-
|
|
3
|
-
import { BashEnvironment, BashEnvironmentOptions, ShellCommandSnapshot } from "@demicodes/shell";
|
|
1
|
+
import { A as AgentToolInvokeResult, B as DEFAULT_TURN_RETRY_POLICY, C as AgentSessionRestoreParams, D as AgentTool, E as AgentSystemPromptContext, F as CompactionWindow, H as isRetryableCode, I as DrainedTranscriptPatches, L as Transcript, M as SessionEvent, N as SessionEventListener, O as AgentToolContext, P as ToolContinuation, R as TranscriptOptions, S as AgentSessionParams, T as AgentSessionStore, U as resolveRetryPolicy, V as TurnRetryPolicy, W as retryDelayMs, _ as AgentHarnessRuntime, a as createInProcessTransportPair, b as AgentReferenceResolveContext, c as ConversationSummary, d as TranscriptPatch, f as AbortResult, g as AgentHarnessContext, h as AgentHarness, i as InProcessTransportPair, j as ExternalMutationReservation, k as AgentToolInvokeContext, l as ServerFrame, m as AgentDisposeContext, n as AgentServerTransport, o as ClientFrame, p as AbortTarget, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandSnapshotLike, v as AgentLifecycleEvent, w as AgentSessionSnapshot, x as AgentSessionOptions, y as AgentPromptContext, z as estimateTranscriptBlockTokens } from "./transport-DVa_82EW.mjs";
|
|
2
|
+
import { a as AgentClientListener, i as AgentClient, n as createWebSocketClientTransport, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-Cn_rhIIX.mjs";
|
|
3
|
+
import { BashEnvironment, BashEnvironmentOptions, Host, ShellCommandSnapshot } from "@demicodes/shell";
|
|
4
4
|
import { AgentProvider, Provider } from "@demicodes/provider";
|
|
5
|
-
import { Block, ModelSelection, QueuedMessage, SessionPhase, UserContentBlock } from "@demicodes/core";
|
|
6
|
-
|
|
5
|
+
import { Block, Model, ModelSelection, QueuedMessage, SessionPhase, UserContentBlock } from "@demicodes/core";
|
|
7
6
|
//#region src/session.d.ts
|
|
8
7
|
type ActiveTurnPhase = 'provider_streaming' | 'tool_executing' | 'compacting' | 'finalizing';
|
|
9
8
|
declare class AgentSession<State> {
|
|
@@ -20,6 +19,7 @@ declare class AgentSession<State> {
|
|
|
20
19
|
private readonly listeners;
|
|
21
20
|
private readonly pendingActions;
|
|
22
21
|
private readonly queued;
|
|
22
|
+
get modelSelection(): ModelSelection;
|
|
23
23
|
private readonly transcriptLog;
|
|
24
24
|
private readonly agentState;
|
|
25
25
|
private currentPhase;
|
|
@@ -144,10 +144,6 @@ declare class AgentSession<State> {
|
|
|
144
144
|
private resolveIdleWaiters;
|
|
145
145
|
}
|
|
146
146
|
//#endregion
|
|
147
|
-
//#region src/json-codec.d.ts
|
|
148
|
-
declare function stringifyAgentJson(value: unknown): string;
|
|
149
|
-
declare function parseAgentJson<T>(text: string): T;
|
|
150
|
-
//#endregion
|
|
151
147
|
//#region src/patch.d.ts
|
|
152
148
|
/**
|
|
153
149
|
* Applies journal-produced transcript patches to a block list, returning a new
|
|
@@ -157,21 +153,6 @@ declare function parseAgentJson<T>(text: string): T;
|
|
|
157
153
|
declare function applyTranscriptPatches(blocks: Block[], patches: TranscriptPatch[]): Block[];
|
|
158
154
|
declare function cloneBlocks(blocks: Block[]): Block[];
|
|
159
155
|
//#endregion
|
|
160
|
-
//#region src/command-tools.d.ts
|
|
161
|
-
interface CommandToolProjectionOptions {
|
|
162
|
-
/** Leaf paths to project (e.g. 'editor create'). Empty/absent = all leaves. */
|
|
163
|
-
include?: string[];
|
|
164
|
-
exclude?: string[];
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Projects registered command leaves onto the native tool surface: one
|
|
168
|
-
* AgentTool per leaf, named by its path (editor create -> editor_create).
|
|
169
|
-
* The tool renders the same shell invocation the model could type and runs it
|
|
170
|
-
* through BashEnvironment.exec, so both projections share one implementation,
|
|
171
|
-
* one audit trail, and one artifact store.
|
|
172
|
-
*/
|
|
173
|
-
declare function createCommandProjectionTools<State = unknown>(environment: BashEnvironment, options?: CommandToolProjectionOptions, reservedNames?: ReadonlySet<string>): AgentTool<State>[];
|
|
174
|
-
//#endregion
|
|
175
156
|
//#region src/server.d.ts
|
|
176
157
|
/** Session tuning forwarded to every AgentSession this server creates. */
|
|
177
158
|
interface AgentServerSessionOptions {
|
|
@@ -182,33 +163,79 @@ interface AgentServerSessionOptions {
|
|
|
182
163
|
};
|
|
183
164
|
persistIntervalMs?: number;
|
|
184
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Host-agnostic hook invoked once per `open()` before BashEnvironment is built.
|
|
168
|
+
* LocalHost uses this to inject PATH / env for the command bridge; AgentServer
|
|
169
|
+
* itself does not know about UDS, shims, or bin directories.
|
|
170
|
+
*/
|
|
171
|
+
interface PrepareSessionShellContext {
|
|
172
|
+
agentSessionId: string;
|
|
173
|
+
host: Host;
|
|
174
|
+
commandNames: readonly string[];
|
|
175
|
+
/** Shell options from AgentServer construction (before this hook). */
|
|
176
|
+
shell: Omit<BashEnvironmentOptions, 'host' | 'commands'>;
|
|
177
|
+
}
|
|
178
|
+
type PrepareSessionShell = (ctx: PrepareSessionShellContext) => Omit<BashEnvironmentOptions, 'host' | 'commands'> | Promise<Omit<BashEnvironmentOptions, 'host' | 'commands'>>;
|
|
185
179
|
interface AgentServerOptions {
|
|
186
180
|
agent: AgentHarness<unknown>;
|
|
187
181
|
providers: Provider[];
|
|
188
182
|
shell?: Omit<BashEnvironmentOptions, 'host' | 'commands'>;
|
|
189
183
|
session?: AgentServerSessionOptions;
|
|
190
184
|
/**
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
* the shell form alone keeps the smallest tool surface.
|
|
185
|
+
* Optional host-side shell prep (env, PATH, etc.). Implementation-agnostic —
|
|
186
|
+
* command bridge wiring lives in `@demicodes/host-local`, not here.
|
|
194
187
|
*/
|
|
195
|
-
|
|
188
|
+
prepareSessionShell?: PrepareSessionShell;
|
|
196
189
|
}
|
|
197
190
|
interface AgentTransportBinding {
|
|
198
191
|
close(): Promise<void>;
|
|
199
192
|
}
|
|
193
|
+
/** Options for {@link AgentServer.runCommandLine}. */
|
|
194
|
+
interface RunCommandLineOptions {
|
|
195
|
+
cwd: string;
|
|
196
|
+
stdin: string;
|
|
197
|
+
signal?: AbortSignal;
|
|
198
|
+
}
|
|
199
|
+
/** Result of {@link AgentServer.runCommandLine}. */
|
|
200
|
+
interface RunCommandLineResult {
|
|
201
|
+
exitCode: number;
|
|
202
|
+
/** UTF-8 text, or base64 when `stdoutEncoding` is 'base64'. */
|
|
203
|
+
stdout: string;
|
|
204
|
+
stdoutEncoding?: 'base64';
|
|
205
|
+
stderr: string;
|
|
206
|
+
}
|
|
207
|
+
declare class RunCommandLineSessionNotFoundError extends Error {
|
|
208
|
+
readonly agentSessionId: string;
|
|
209
|
+
constructor(agentSessionId: string);
|
|
210
|
+
}
|
|
211
|
+
declare class RunCommandLineCommandNotRegisteredError extends Error {
|
|
212
|
+
readonly commandName: string;
|
|
213
|
+
constructor(commandName: string);
|
|
214
|
+
}
|
|
215
|
+
declare class RunCommandLineTimeoutError extends Error {
|
|
216
|
+
readonly commandId: string;
|
|
217
|
+
readonly partialStdout: string;
|
|
218
|
+
readonly partialStderr: string;
|
|
219
|
+
constructor(commandId: string, partialStdout: string, partialStderr: string);
|
|
220
|
+
}
|
|
200
221
|
declare class AgentServer {
|
|
201
222
|
private readonly agent;
|
|
202
223
|
private readonly providers;
|
|
203
224
|
private readonly shellOptions;
|
|
204
225
|
private readonly sessionOptions;
|
|
205
|
-
private readonly
|
|
226
|
+
private readonly prepareSessionShell;
|
|
206
227
|
private readonly bindings;
|
|
207
228
|
private readonly sessionOwnership;
|
|
208
229
|
constructor(options: AgentServerOptions);
|
|
209
230
|
client(): AgentClient;
|
|
210
231
|
attachTransport(transport: AgentServerTransport): AgentTransportBinding;
|
|
211
232
|
close(): Promise<void>;
|
|
233
|
+
/**
|
|
234
|
+
* Runs one registered-command invocation to completion for a live session.
|
|
235
|
+
* Transport-agnostic: callers (e.g. LocalHost command bridge) supply their
|
|
236
|
+
* own IPC; AgentServer only knows how to exec against the open session shell.
|
|
237
|
+
*/
|
|
238
|
+
runCommandLine(agentSessionId: string, name: string, args: string[], opts: RunCommandLineOptions): Promise<RunCommandLineResult>;
|
|
212
239
|
}
|
|
213
240
|
//#endregion
|
|
214
241
|
//#region src/tools.d.ts
|
|
@@ -221,10 +248,12 @@ interface ShellToolResultOptions {
|
|
|
221
248
|
includePreview?: boolean;
|
|
222
249
|
previewBudgetTokens?: number;
|
|
223
250
|
exposeCommandHandle?: boolean;
|
|
251
|
+
/** Model receiving this result; gates binary-stream media attachment. */
|
|
252
|
+
model?: Model;
|
|
224
253
|
}
|
|
225
254
|
declare function shellPreviewBudgetTokens(contextWindow: number): number;
|
|
226
255
|
declare function toShellToolResult(result: ShellCommandSnapshot, toolCallId?: string, options?: ShellToolResultOptions): AgentToolInvokeResult;
|
|
227
256
|
declare function finishShellToolResult<State>(environment: BashEnvironment, result: ShellCommandSnapshot, ctx: AgentToolInvokeContext<State>): Promise<AgentToolInvokeResult>;
|
|
228
257
|
declare function shellCommandHandleRequired(result: ShellCommandSnapshot, budgetTokens: number): boolean;
|
|
229
258
|
//#endregion
|
|
230
|
-
export { AbortResult, AbortTarget, ActiveTurnPhase, AgentClient, AgentClientListener, AgentClientTransport, AgentDisposeContext, AgentHarness, AgentHarnessContext, AgentHarnessRuntime, AgentLifecycleEvent, AgentPromptContext, AgentReferenceResolveContext, AgentServer, AgentServerOptions, AgentServerSessionOptions, AgentServerTransport, AgentSession, AgentSessionOptions, AgentSessionParams, AgentSessionRestoreParams, AgentSessionSnapshot, AgentSessionStore, AgentSystemPromptContext, AgentTool, AgentToolContext, AgentToolInvokeContext, AgentToolInvokeResult, AgentTransport, AgentTransportBinding, ClientFrame, ClientSessionEvent,
|
|
259
|
+
export { AbortResult, AbortTarget, ActiveTurnPhase, AgentClient, AgentClientListener, AgentClientTransport, AgentDisposeContext, AgentHarness, AgentHarnessContext, AgentHarnessRuntime, AgentLifecycleEvent, AgentPromptContext, AgentReferenceResolveContext, AgentServer, AgentServerOptions, AgentServerSessionOptions, AgentServerTransport, AgentSession, AgentSessionOptions, AgentSessionParams, AgentSessionRestoreParams, AgentSessionSnapshot, AgentSessionStore, AgentSystemPromptContext, AgentTool, AgentToolContext, AgentToolInvokeContext, AgentToolInvokeResult, AgentTransport, AgentTransportBinding, ClientFrame, ClientSessionEvent, CompactionWindow, ConversationSummary, DEFAULT_TURN_RETRY_POLICY, DrainedTranscriptPatches, ExternalMutationReservation, InProcessTransportPair, JsonWebSocket, PrepareSessionShell, PrepareSessionShellContext, RunCommandLineCommandNotRegisteredError, RunCommandLineOptions, RunCommandLineResult, RunCommandLineSessionNotFoundError, RunCommandLineTimeoutError, ServerFrame, SessionEvent, SessionEventListener, ShellCommandSnapshotLike, ShellToolResultOptions, StandardAgentToolOptions, ToolContinuation, Transcript, TranscriptOptions, TranscriptPatch, TurnRetryPolicy, applyTranscriptPatches, cloneBlocks, createInProcessTransportPair, createStandardAgentTools, createWebSocketClientTransport, createWebSocketServerTransport, estimateTranscriptBlockTokens, finishShellToolResult, isRetryableCode, resolveRetryPolicy, retryDelayMs, shellCommandHandleRequired, shellPreviewBudgetTokens, toShellToolResult };
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as cloneBlocks, i as applyTranscriptPatches, n as createWebSocketServerTransport, r as AgentClient, t as createWebSocketClientTransport } from "./websocket-transport-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { BashEnvironment, CommandRegistry, listRegisteredCommandOperations } from "@demicodes/shell";
|
|
1
|
+
import { a as cloneBlocks, i as applyTranscriptPatches, n as createWebSocketServerTransport, r as AgentClient, t as createWebSocketClientTransport } from "./websocket-transport-Bod0puog.mjs";
|
|
2
|
+
import { AbortError, abortable, asError, asRecord, asString, bytesToBase64, createId, delay, isAbortError, isRecord, noop, parseJsonOrString, safeJsonStringify, throwIfAborted, truncate } from "@demicodes/utils";
|
|
3
|
+
import { BashEnvironment, CommandRegistry, MAX_TIMEOUT_MS, heredocDelimiter, shellQuote } from "@demicodes/shell";
|
|
5
4
|
import { providerRuntime } from "@demicodes/provider";
|
|
5
|
+
import { modelAcceptsMediaType, sniffModelMediaType } from "@demicodes/core";
|
|
6
6
|
//#region src/transcript.ts
|
|
7
7
|
const DEFAULT_MODEL_TEXT_HEAD_CHARS = 8e3;
|
|
8
8
|
const DEFAULT_MODEL_TEXT_TAIL_CHARS = 8e3;
|
|
@@ -532,6 +532,7 @@ function stringifyUserContent(content) {
|
|
|
532
532
|
switch (content.type) {
|
|
533
533
|
case "text": return content.text;
|
|
534
534
|
case "image": return content.source.type === "url" ? content.source.url : content.source.mediaType;
|
|
535
|
+
case "video": return content.source.type === "url" ? content.source.url : content.source.mediaType;
|
|
535
536
|
case "document": return `${content.source.fileName} ${content.source.mediaType}`;
|
|
536
537
|
case "reference": return content.reference;
|
|
537
538
|
}
|
|
@@ -540,6 +541,7 @@ function stringifyToolResult(content) {
|
|
|
540
541
|
switch (content.type) {
|
|
541
542
|
case "text": return content.text;
|
|
542
543
|
case "image": return content.source.mediaType;
|
|
544
|
+
case "video": return content.source.mediaType;
|
|
543
545
|
}
|
|
544
546
|
}
|
|
545
547
|
function boundUserContent(content, headChars, tailChars) {
|
|
@@ -1139,6 +1141,9 @@ var AgentSession = class AgentSession {
|
|
|
1139
1141
|
listeners = /* @__PURE__ */ new Set();
|
|
1140
1142
|
pendingActions = [];
|
|
1141
1143
|
queued = [];
|
|
1144
|
+
get modelSelection() {
|
|
1145
|
+
return this.model;
|
|
1146
|
+
}
|
|
1142
1147
|
transcriptLog;
|
|
1143
1148
|
agentState;
|
|
1144
1149
|
currentPhase = "idle";
|
|
@@ -2212,13 +2217,14 @@ function toShellToolResult(result, toolCallId = "", options = {}) {
|
|
|
2212
2217
|
type: "text",
|
|
2213
2218
|
text: formatShellToolResult(result, options)
|
|
2214
2219
|
}];
|
|
2215
|
-
if (result.status === "exited" && result.
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2220
|
+
if (result.status === "exited" && result.binaryStdout) {
|
|
2221
|
+
const verdict = binaryStreamVerdict(result.binaryStdout, result.commandId, options.model);
|
|
2222
|
+
if (verdict.block) output.push(verdict.block);
|
|
2223
|
+
if (verdict.note) output.push({
|
|
2224
|
+
type: "text",
|
|
2225
|
+
text: verdict.note
|
|
2226
|
+
});
|
|
2227
|
+
}
|
|
2222
2228
|
return {
|
|
2223
2229
|
output,
|
|
2224
2230
|
isError: false,
|
|
@@ -2231,6 +2237,32 @@ function toShellToolResult(result, toolCallId = "", options = {}) {
|
|
|
2231
2237
|
} : void 0
|
|
2232
2238
|
};
|
|
2233
2239
|
}
|
|
2240
|
+
/**
|
|
2241
|
+
* Boundary decision for a binary final stream: attach as native media when the
|
|
2242
|
+
* magic matches the closed model-media set, the model accepts the type, and
|
|
2243
|
+
* the stream was not truncated; otherwise explain why nothing was attached.
|
|
2244
|
+
*/
|
|
2245
|
+
function binaryStreamVerdict(binary, commandId, model) {
|
|
2246
|
+
const media = sniffModelMediaType(binary.data);
|
|
2247
|
+
const binPath = `/@/commands/${commandId}/stdout.bin`;
|
|
2248
|
+
if (binary.truncated) return { note: `Binary stdout was truncated at the output limit (${binary.data.length} of ${binary.totalBytes} bytes)${media ? ` and looks like ${media.mediaType}` : ""}; it was not attached. Redirect to a file or raise the output limit and re-run.` };
|
|
2249
|
+
if (!media) return { note: `Binary stdout does not match any model-viewable media type; the raw bytes remain readable at ${binPath}.` };
|
|
2250
|
+
if (!model || !modelAcceptsMediaType(model, media.mediaType)) return { note: `Binary stdout is ${media.mediaType}, which this model does not accept natively; the raw bytes remain readable at ${binPath}.` };
|
|
2251
|
+
const source = {
|
|
2252
|
+
mediaType: media.mediaType,
|
|
2253
|
+
data: bytesToBase64(binary.data)
|
|
2254
|
+
};
|
|
2255
|
+
return {
|
|
2256
|
+
block: media.kind === "video" ? {
|
|
2257
|
+
type: "video",
|
|
2258
|
+
source
|
|
2259
|
+
} : {
|
|
2260
|
+
type: "image",
|
|
2261
|
+
source
|
|
2262
|
+
},
|
|
2263
|
+
note: `Attached stdout as ${media.mediaType} (${binary.totalBytes} bytes).`
|
|
2264
|
+
};
|
|
2265
|
+
}
|
|
2234
2266
|
function parseShellExecInput(input) {
|
|
2235
2267
|
const record = asRecord(input, "agent tool input must be an object");
|
|
2236
2268
|
if (typeof record.script !== "string") throw new Error("shell_exec requires string field \"script\"");
|
|
@@ -2352,7 +2384,8 @@ async function finishShellToolResult(environment, result, ctx) {
|
|
|
2352
2384
|
const toolResult = toShellToolResult(result, ctx.toolCallId, {
|
|
2353
2385
|
includePreview: true,
|
|
2354
2386
|
previewBudgetTokens,
|
|
2355
|
-
exposeCommandHandle
|
|
2387
|
+
exposeCommandHandle,
|
|
2388
|
+
model: ctx.model.model
|
|
2356
2389
|
});
|
|
2357
2390
|
if (!exposeCommandHandle) await environment.releaseCommand(result.commandId);
|
|
2358
2391
|
return toolResult;
|
|
@@ -2364,56 +2397,41 @@ function shellCommandHandleRequired(result, budgetTokens) {
|
|
|
2364
2397
|
return preview.truncated || result.output.truncated || result.output.bytes > maxChars || result.stdout.truncated || result.stderr.truncated;
|
|
2365
2398
|
}
|
|
2366
2399
|
//#endregion
|
|
2367
|
-
//#region src/command-tools.ts
|
|
2368
|
-
/** Observation window for projected command invocations. Registered commands
|
|
2369
|
-
* execute in-process and complete quickly; long work belongs to shell_exec. */
|
|
2370
|
-
const COMMAND_TOOL_TIMEOUT_MS = 6e4;
|
|
2371
|
-
/**
|
|
2372
|
-
* Projects registered command leaves onto the native tool surface: one
|
|
2373
|
-
* AgentTool per leaf, named by its path (editor create -> editor_create).
|
|
2374
|
-
* The tool renders the same shell invocation the model could type and runs it
|
|
2375
|
-
* through BashEnvironment.exec, so both projections share one implementation,
|
|
2376
|
-
* one audit trail, and one artifact store.
|
|
2377
|
-
*/
|
|
2378
|
-
function createCommandProjectionTools(environment, options = {}, reservedNames = /* @__PURE__ */ new Set()) {
|
|
2379
|
-
const operations = listRegisteredCommandOperations(environment.registeredCommands()).filter((operation) => operationSelected(operation, options));
|
|
2380
|
-
const seen = new Set(reservedNames);
|
|
2381
|
-
return operations.map((operation) => {
|
|
2382
|
-
const name = operation.path.join("_");
|
|
2383
|
-
if (seen.has(name)) throw new Error(`Command tool projection: tool name "${name}" conflicts with an existing tool`);
|
|
2384
|
-
seen.add(name);
|
|
2385
|
-
return {
|
|
2386
|
-
name,
|
|
2387
|
-
description: operation.description,
|
|
2388
|
-
inputSchema: operation.inputSchema,
|
|
2389
|
-
invoke: async (ctx, input) => {
|
|
2390
|
-
const values = asRecord(input, `${name} input must be an object`);
|
|
2391
|
-
const result = await environment.exec({
|
|
2392
|
-
script: operation.renderScript(values),
|
|
2393
|
-
agentSessionId: ctx.agentSessionId,
|
|
2394
|
-
timeoutMs: COMMAND_TOOL_TIMEOUT_MS,
|
|
2395
|
-
signal: ctx.signal
|
|
2396
|
-
});
|
|
2397
|
-
ctx.emitProgress(result);
|
|
2398
|
-
return finishShellToolResult(environment, result, ctx);
|
|
2399
|
-
}
|
|
2400
|
-
};
|
|
2401
|
-
});
|
|
2402
|
-
}
|
|
2403
|
-
function operationSelected(operation, options) {
|
|
2404
|
-
const path = operation.path.join(" ");
|
|
2405
|
-
if (options.exclude?.includes(path)) return false;
|
|
2406
|
-
if (options.include && options.include.length > 0) return options.include.includes(path);
|
|
2407
|
-
return true;
|
|
2408
|
-
}
|
|
2409
|
-
//#endregion
|
|
2410
2400
|
//#region src/server.ts
|
|
2401
|
+
var RunCommandLineSessionNotFoundError = class extends Error {
|
|
2402
|
+
agentSessionId;
|
|
2403
|
+
constructor(agentSessionId) {
|
|
2404
|
+
super(`runCommandLine: no session "${agentSessionId}" is open in this process`);
|
|
2405
|
+
this.agentSessionId = agentSessionId;
|
|
2406
|
+
this.name = "RunCommandLineSessionNotFoundError";
|
|
2407
|
+
}
|
|
2408
|
+
};
|
|
2409
|
+
var RunCommandLineCommandNotRegisteredError = class extends Error {
|
|
2410
|
+
commandName;
|
|
2411
|
+
constructor(commandName) {
|
|
2412
|
+
super(`runCommandLine: command "${commandName}" is not registered for this session`);
|
|
2413
|
+
this.commandName = commandName;
|
|
2414
|
+
this.name = "RunCommandLineCommandNotRegisteredError";
|
|
2415
|
+
}
|
|
2416
|
+
};
|
|
2417
|
+
var RunCommandLineTimeoutError = class extends Error {
|
|
2418
|
+
commandId;
|
|
2419
|
+
partialStdout;
|
|
2420
|
+
partialStderr;
|
|
2421
|
+
constructor(commandId, partialStdout, partialStderr) {
|
|
2422
|
+
super(`runCommandLine: command "${commandId}" exceeded the ${MAX_TIMEOUT_MS}ms ceiling and was aborted`);
|
|
2423
|
+
this.commandId = commandId;
|
|
2424
|
+
this.partialStdout = partialStdout;
|
|
2425
|
+
this.partialStderr = partialStderr;
|
|
2426
|
+
this.name = "RunCommandLineTimeoutError";
|
|
2427
|
+
}
|
|
2428
|
+
};
|
|
2411
2429
|
var AgentServer = class {
|
|
2412
2430
|
agent;
|
|
2413
2431
|
providers;
|
|
2414
2432
|
shellOptions;
|
|
2415
2433
|
sessionOptions;
|
|
2416
|
-
|
|
2434
|
+
prepareSessionShell;
|
|
2417
2435
|
bindings = /* @__PURE__ */ new Set();
|
|
2418
2436
|
sessionOwnership = new SessionOwnershipRegistry();
|
|
2419
2437
|
constructor(options) {
|
|
@@ -2421,7 +2439,7 @@ var AgentServer = class {
|
|
|
2421
2439
|
this.providers = createProviderMap(options.providers);
|
|
2422
2440
|
this.shellOptions = options.shell ?? {};
|
|
2423
2441
|
this.sessionOptions = options.session ?? {};
|
|
2424
|
-
this.
|
|
2442
|
+
this.prepareSessionShell = options.prepareSessionShell ?? null;
|
|
2425
2443
|
}
|
|
2426
2444
|
client() {
|
|
2427
2445
|
const transports = createInProcessTransportPair();
|
|
@@ -2435,7 +2453,7 @@ var AgentServer = class {
|
|
|
2435
2453
|
providers: this.providers,
|
|
2436
2454
|
shell: this.shellOptions,
|
|
2437
2455
|
session: this.sessionOptions,
|
|
2438
|
-
|
|
2456
|
+
prepareSessionShell: this.prepareSessionShell,
|
|
2439
2457
|
sessions: this.sessionOwnership
|
|
2440
2458
|
});
|
|
2441
2459
|
this.bindings.add(binding);
|
|
@@ -2446,6 +2464,16 @@ var AgentServer = class {
|
|
|
2446
2464
|
this.bindings.clear();
|
|
2447
2465
|
await Promise.all(bindings.map((binding) => binding.close()));
|
|
2448
2466
|
}
|
|
2467
|
+
/**
|
|
2468
|
+
* Runs one registered-command invocation to completion for a live session.
|
|
2469
|
+
* Transport-agnostic: callers (e.g. LocalHost command bridge) supply their
|
|
2470
|
+
* own IPC; AgentServer only knows how to exec against the open session shell.
|
|
2471
|
+
*/
|
|
2472
|
+
async runCommandLine(agentSessionId, name, args, opts) {
|
|
2473
|
+
const binding = this.sessionOwnership.get(agentSessionId);
|
|
2474
|
+
if (!binding) throw new RunCommandLineSessionNotFoundError(agentSessionId);
|
|
2475
|
+
return binding.runCommandLine(name, args, opts);
|
|
2476
|
+
}
|
|
2449
2477
|
};
|
|
2450
2478
|
/**
|
|
2451
2479
|
* Tracks which transport binding currently owns each client-provided session
|
|
@@ -2463,6 +2491,9 @@ var SessionOwnershipRegistry = class {
|
|
|
2463
2491
|
release(sessionId, binding) {
|
|
2464
2492
|
if (this.holders.get(sessionId) === binding) this.holders.delete(sessionId);
|
|
2465
2493
|
}
|
|
2494
|
+
get(sessionId) {
|
|
2495
|
+
return this.holders.get(sessionId);
|
|
2496
|
+
}
|
|
2466
2497
|
};
|
|
2467
2498
|
var AgentTransportBindingImpl = class {
|
|
2468
2499
|
transport;
|
|
@@ -2470,7 +2501,7 @@ var AgentTransportBindingImpl = class {
|
|
|
2470
2501
|
providers;
|
|
2471
2502
|
shellOptions;
|
|
2472
2503
|
sessionOptions;
|
|
2473
|
-
|
|
2504
|
+
prepareSessionShell;
|
|
2474
2505
|
sessions;
|
|
2475
2506
|
session = null;
|
|
2476
2507
|
currentAgent = null;
|
|
@@ -2478,6 +2509,7 @@ var AgentTransportBindingImpl = class {
|
|
|
2478
2509
|
currentCwd = null;
|
|
2479
2510
|
currentProviderId = null;
|
|
2480
2511
|
currentSessionId = null;
|
|
2512
|
+
currentCommandNames = /* @__PURE__ */ new Set();
|
|
2481
2513
|
unsubscribeSession = null;
|
|
2482
2514
|
unsubscribeTransport = null;
|
|
2483
2515
|
closed = false;
|
|
@@ -2487,7 +2519,7 @@ var AgentTransportBindingImpl = class {
|
|
|
2487
2519
|
this.providers = options.providers;
|
|
2488
2520
|
this.shellOptions = options.shell ?? {};
|
|
2489
2521
|
this.sessionOptions = options.session ?? {};
|
|
2490
|
-
this.
|
|
2522
|
+
this.prepareSessionShell = options.prepareSessionShell;
|
|
2491
2523
|
this.sessions = options.sessions;
|
|
2492
2524
|
this.unsubscribeTransport = this.transport.onFrame((frame) => {
|
|
2493
2525
|
this.handleFrame(frame);
|
|
@@ -2694,26 +2726,26 @@ var AgentTransportBindingImpl = class {
|
|
|
2694
2726
|
const commands = agent.commands?.(harnessContext) ?? [];
|
|
2695
2727
|
const commandRegistry = new CommandRegistry();
|
|
2696
2728
|
for (const command of commands) commandRegistry.register(command);
|
|
2729
|
+
const commandNames = commandRegistry.list().map((command) => command.name);
|
|
2697
2730
|
const environment = new BashEnvironment({
|
|
2698
|
-
...this.
|
|
2731
|
+
...this.prepareSessionShell ? await this.prepareSessionShell({
|
|
2732
|
+
agentSessionId,
|
|
2733
|
+
host,
|
|
2734
|
+
commandNames,
|
|
2735
|
+
shell: this.shellOptions
|
|
2736
|
+
}) : this.shellOptions,
|
|
2699
2737
|
host,
|
|
2700
2738
|
commands: commandRegistry
|
|
2701
2739
|
});
|
|
2702
2740
|
let sessionRef = null;
|
|
2703
|
-
const
|
|
2741
|
+
const tools = createStandardAgentTools({
|
|
2704
2742
|
environment,
|
|
2705
2743
|
scheduleYield: (_ctx, durationMs) => {
|
|
2706
2744
|
if (!sessionRef) throw new Error("AgentServer: session is not ready for yield scheduling");
|
|
2707
2745
|
return sessionRef.scheduleYieldWakeup(durationMs);
|
|
2708
2746
|
}
|
|
2709
2747
|
});
|
|
2710
|
-
const
|
|
2711
|
-
const tools = [...standardTools, ...projectedTools];
|
|
2712
|
-
let commandsPrompt = commandRegistry.renderPrompt();
|
|
2713
|
-
if (projectedTools.length > 0) {
|
|
2714
|
-
const names = projectedTools.map((tool) => tool.name).join(", ");
|
|
2715
|
-
commandsPrompt += `\n\nNative tool forms: ${names} — identical behavior, audit, and artifacts to the shell commands above.`;
|
|
2716
|
-
}
|
|
2748
|
+
const commandsPrompt = commandRegistry.renderHelp();
|
|
2717
2749
|
const runtime = {
|
|
2718
2750
|
harnessName: agent.name,
|
|
2719
2751
|
initialState: () => agent.initialState(),
|
|
@@ -2754,6 +2786,7 @@ var AgentTransportBindingImpl = class {
|
|
|
2754
2786
|
this.currentEnvironment = environment;
|
|
2755
2787
|
this.currentCwd = frame.cwd;
|
|
2756
2788
|
this.currentProviderId = frame.provider.providerId;
|
|
2789
|
+
this.currentCommandNames = new Set(commandNames);
|
|
2757
2790
|
if (restoring) session.updateModel(null, frame.provider.model);
|
|
2758
2791
|
this.unsubscribeSession = this.session.subscribe((event) => this.handleSessionEvent(event));
|
|
2759
2792
|
this.send({ type: "opened" });
|
|
@@ -2858,6 +2891,7 @@ var AgentTransportBindingImpl = class {
|
|
|
2858
2891
|
this.currentEnvironment = null;
|
|
2859
2892
|
this.currentCwd = null;
|
|
2860
2893
|
this.currentProviderId = null;
|
|
2894
|
+
this.currentCommandNames = /* @__PURE__ */ new Set();
|
|
2861
2895
|
if (this.currentSessionId) {
|
|
2862
2896
|
this.sessions.release(this.currentSessionId, this);
|
|
2863
2897
|
this.currentSessionId = null;
|
|
@@ -2891,6 +2925,50 @@ var AgentTransportBindingImpl = class {
|
|
|
2891
2925
|
});
|
|
2892
2926
|
this.sendShellWriteResult(frame.commandId, result);
|
|
2893
2927
|
}
|
|
2928
|
+
/** Backs `AgentServer.runCommandLine` — see its doc comment for the contract. */
|
|
2929
|
+
async runCommandLine(name, args, opts) {
|
|
2930
|
+
const environment = this.currentEnvironment;
|
|
2931
|
+
const agentSessionId = this.currentSessionId;
|
|
2932
|
+
if (!environment || !agentSessionId) throw new Error("runCommandLine: session has no active shell environment");
|
|
2933
|
+
if (!this.currentCommandNames.has(name)) throw new RunCommandLineCommandNotRegisteredError(name);
|
|
2934
|
+
const words = [name, ...args].map(shellQuote).join(" ");
|
|
2935
|
+
let script = words;
|
|
2936
|
+
if (opts.stdin.length > 0) {
|
|
2937
|
+
const delimiter = heredocDelimiter(opts.stdin);
|
|
2938
|
+
script = `${words} <<'${delimiter}'\n${opts.stdin.endsWith("\n") ? opts.stdin : `${opts.stdin}\n`}${delimiter}`;
|
|
2939
|
+
}
|
|
2940
|
+
const result = await environment.exec({
|
|
2941
|
+
agentSessionId,
|
|
2942
|
+
script,
|
|
2943
|
+
timeoutMs: MAX_TIMEOUT_MS,
|
|
2944
|
+
signal: opts.signal,
|
|
2945
|
+
ephemeral: true,
|
|
2946
|
+
cwd: opts.cwd
|
|
2947
|
+
});
|
|
2948
|
+
try {
|
|
2949
|
+
if (result.status === "exited") {
|
|
2950
|
+
if (result.binaryStdout) {
|
|
2951
|
+
const truncationNote = result.binaryStdout.truncated ? `command bridge: binary stdout truncated at the output limit (${result.binaryStdout.data.length} of ${result.binaryStdout.totalBytes} bytes)\n` : "";
|
|
2952
|
+
return {
|
|
2953
|
+
exitCode: result.exitCode,
|
|
2954
|
+
stdout: bytesToBase64(result.binaryStdout.data),
|
|
2955
|
+
stdoutEncoding: "base64",
|
|
2956
|
+
stderr: `${result.stderr.delta}${truncationNote}`
|
|
2957
|
+
};
|
|
2958
|
+
}
|
|
2959
|
+
return {
|
|
2960
|
+
exitCode: result.exitCode,
|
|
2961
|
+
stdout: result.stdout.delta,
|
|
2962
|
+
stderr: result.stderr.delta
|
|
2963
|
+
};
|
|
2964
|
+
}
|
|
2965
|
+
if (result.status === "aborted") throw new Error(`runCommandLine: call for "${name}" was cancelled before it completed`);
|
|
2966
|
+
const aborted = await environment.abort({ commandId: result.commandId });
|
|
2967
|
+
throw new RunCommandLineTimeoutError(result.commandId, aborted.status === "aborted" ? aborted.stdout.delta : "", aborted.status === "aborted" ? aborted.stderr.delta : "");
|
|
2968
|
+
} finally {
|
|
2969
|
+
await environment.disposeShell(result.shellId).catch(() => {});
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2894
2972
|
sessionFor(command) {
|
|
2895
2973
|
if (!this.session) {
|
|
2896
2974
|
this.send({
|
|
@@ -3056,4 +3134,4 @@ function createProviderMap(providers) {
|
|
|
3056
3134
|
return map;
|
|
3057
3135
|
}
|
|
3058
3136
|
//#endregion
|
|
3059
|
-
export { AgentClient, AgentServer, AgentSession, DEFAULT_TURN_RETRY_POLICY, Transcript, applyTranscriptPatches, cloneBlocks,
|
|
3137
|
+
export { AgentClient, AgentServer, AgentSession, DEFAULT_TURN_RETRY_POLICY, RunCommandLineCommandNotRegisteredError, RunCommandLineSessionNotFoundError, RunCommandLineTimeoutError, Transcript, applyTranscriptPatches, cloneBlocks, createInProcessTransportPair, createStandardAgentTools, createWebSocketClientTransport, createWebSocketServerTransport, estimateTranscriptBlockTokens, finishShellToolResult, isRetryableCode, resolveRetryPolicy, retryDelayMs, shellCommandHandleRequired, shellPreviewBudgetTokens, toShellToolResult };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { n as AgentServerTransport, t as AgentClientTransport } from "./transport-
|
|
1
|
+
import { n as AgentServerTransport, t as AgentClientTransport } from "./transport-DVa_82EW.mjs";
|
|
2
2
|
import { Readable, Writable } from "node:stream";
|
|
3
|
-
|
|
4
3
|
//#region src/stdio-transport.d.ts
|
|
5
4
|
declare function createStdioClientTransport(readable: Readable, writable: Writable): AgentClientTransport;
|
|
6
5
|
declare function createStdioServerTransport(readable: Readable, writable: Writable): AgentServerTransport;
|
package/dist/stdio-transport.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parsePortableJson, stringifyPortableJson } from "@demicodes/utils";
|
|
2
2
|
import { createInterface } from "node:readline";
|
|
3
3
|
//#region src/stdio-transport.ts
|
|
4
4
|
function createStdioClientTransport(readable, writable) {
|
|
@@ -19,13 +19,13 @@ var JsonLineTransport = class {
|
|
|
19
19
|
this.readline = createInterface({ input: readable });
|
|
20
20
|
this.readline.on("line", (line) => {
|
|
21
21
|
if (this.closed || line.trim() === "") return;
|
|
22
|
-
const frame =
|
|
22
|
+
const frame = parsePortableJson(line);
|
|
23
23
|
for (const handler of this.handlers) handler(frame);
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
send(frame) {
|
|
27
27
|
if (this.closed) throw new Error("Agent transport is closed");
|
|
28
|
-
this.writable.write(`${
|
|
28
|
+
this.writable.write(`${stringifyPortableJson(frame)}\n`);
|
|
29
29
|
}
|
|
30
30
|
onFrame(handler) {
|
|
31
31
|
this.handlers.add(handler);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { BashAuditEvent,
|
|
1
|
+
import { BashAuditEvent, Command, Host, ShellCommandSnapshot } from "@demicodes/shell";
|
|
2
2
|
import { AgentProvider, InferenceItem, ProviderEvent, ProviderSelection, ToolDefinition } from "@demicodes/provider";
|
|
3
3
|
import { Block, ModelSelection, QueuedMessage, SessionPhase, ToolResultContentBlock, Transcript, UserContentBlock } from "@demicodes/core";
|
|
4
|
-
|
|
5
4
|
//#region src/retry-policy.d.ts
|
|
6
5
|
/**
|
|
7
6
|
* Retry policy for provider requests, applied by the agent runtime (turn loop
|
|
@@ -164,7 +163,7 @@ interface AgentHarness<State = unknown> {
|
|
|
164
163
|
name: string;
|
|
165
164
|
initialState(): State;
|
|
166
165
|
host(ctx: AgentHarnessContext<State>): Host;
|
|
167
|
-
commands?(ctx: AgentHarnessContext<State>):
|
|
166
|
+
commands?(ctx: AgentHarnessContext<State>): Command[];
|
|
168
167
|
systemPrompt(ctx: AgentSystemPromptContext<State>): string;
|
|
169
168
|
preamble?(ctx: AgentPromptContext<State>): string | null;
|
|
170
169
|
resolveReferences?(ctx: AgentReferenceResolveContext<State>, content: UserContentBlock[]): Promise<UserContentBlock[]> | UserContentBlock[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parsePortableJson, stringifyPortableJson } from "@demicodes/utils";
|
|
2
2
|
//#region src/patch.ts
|
|
3
3
|
/**
|
|
4
4
|
* Applies journal-produced transcript patches to a block list, returning a new
|
|
@@ -447,7 +447,7 @@ var WebSocketJsonTransport = class {
|
|
|
447
447
|
socket;
|
|
448
448
|
handlers = /* @__PURE__ */ new Set();
|
|
449
449
|
onMessage = (event) => {
|
|
450
|
-
const frame =
|
|
450
|
+
const frame = parsePortableJson(typeof event.data === "string" ? event.data : String(event.data));
|
|
451
451
|
for (const handler of this.handlers) handler(frame);
|
|
452
452
|
};
|
|
453
453
|
constructor(socket) {
|
|
@@ -455,7 +455,7 @@ var WebSocketJsonTransport = class {
|
|
|
455
455
|
this.socket.addEventListener("message", this.onMessage);
|
|
456
456
|
}
|
|
457
457
|
send(frame) {
|
|
458
|
-
this.socket.send(
|
|
458
|
+
this.socket.send(stringifyPortableJson(frame));
|
|
459
459
|
}
|
|
460
460
|
onFrame(handler) {
|
|
461
461
|
this.handlers.add(handler);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { c as ConversationSummary, f as AbortResult, n as AgentServerTransport, s as ClientSessionEvent, t as AgentClientTransport } from "./transport-
|
|
1
|
+
import { c as ConversationSummary, f as AbortResult, n as AgentServerTransport, s as ClientSessionEvent, t as AgentClientTransport } from "./transport-DVa_82EW.mjs";
|
|
2
2
|
import { ProviderSelection } from "@demicodes/provider";
|
|
3
3
|
import { Block, UserContentBlock } from "@demicodes/core";
|
|
4
|
-
|
|
5
4
|
//#region src/client.d.ts
|
|
6
5
|
type AgentClientListener = (event: ClientSessionEvent) => void;
|
|
7
6
|
declare class AgentClient {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@demicodes/agent",
|
|
3
3
|
"description": "Session runtime and transport-neutral client and server protocol for Demi.",
|
|
4
|
-
"version": "0.1
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@demicodes/core": "
|
|
26
|
-
"@demicodes/provider": "
|
|
27
|
-
"@demicodes/shell": "
|
|
28
|
-
"@demicodes/utils": "
|
|
25
|
+
"@demicodes/core": "^0.2.1",
|
|
26
|
+
"@demicodes/provider": "^0.2.1",
|
|
27
|
+
"@demicodes/shell": "^0.2.1",
|
|
28
|
+
"@demicodes/utils": "^0.2.1"
|
|
29
29
|
},
|
|
30
30
|
"license": "Apache-2.0",
|
|
31
31
|
"main": "./dist/index.mjs",
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
//#region src/json-codec.ts
|
|
2
|
-
const BINARY_MARKER = "__demiUint8Array";
|
|
3
|
-
const BIGINT_MARKER = "__demiBigInt";
|
|
4
|
-
const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
5
|
-
function stringifyAgentJson(value) {
|
|
6
|
-
return JSON.stringify(value, (_key, nested) => {
|
|
7
|
-
if (nested instanceof Uint8Array) return {
|
|
8
|
-
[BINARY_MARKER]: true,
|
|
9
|
-
base64: bytesToBase64(nested)
|
|
10
|
-
};
|
|
11
|
-
if (typeof nested === "bigint") return {
|
|
12
|
-
[BIGINT_MARKER]: true,
|
|
13
|
-
value: nested.toString()
|
|
14
|
-
};
|
|
15
|
-
return nested;
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
function parseAgentJson(text) {
|
|
19
|
-
return JSON.parse(text, (_key, nested) => {
|
|
20
|
-
if (isEncodedUint8Array(nested)) return base64ToBytes(nested.base64);
|
|
21
|
-
if (isEncodedBigInt(nested)) return BigInt(nested.value);
|
|
22
|
-
return nested;
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
function isEncodedUint8Array(value) {
|
|
26
|
-
return value !== null && typeof value === "object" && !Array.isArray(value) && value[BINARY_MARKER] === true && typeof value.base64 === "string";
|
|
27
|
-
}
|
|
28
|
-
function isEncodedBigInt(value) {
|
|
29
|
-
return value !== null && typeof value === "object" && !Array.isArray(value) && value[BIGINT_MARKER] === true && typeof value.value === "string";
|
|
30
|
-
}
|
|
31
|
-
function bytesToBase64(bytes) {
|
|
32
|
-
let output = "";
|
|
33
|
-
for (let index = 0; index < bytes.byteLength; index += 3) {
|
|
34
|
-
const first = bytes[index];
|
|
35
|
-
const second = bytes[index + 1];
|
|
36
|
-
const third = bytes[index + 2];
|
|
37
|
-
output += BASE64_ALPHABET[first >> 2];
|
|
38
|
-
output += BASE64_ALPHABET[(first & 3) << 4 | (second ?? 0) >> 4];
|
|
39
|
-
output += second === void 0 ? "=" : BASE64_ALPHABET[(second & 15) << 2 | (third ?? 0) >> 6];
|
|
40
|
-
output += third === void 0 ? "=" : BASE64_ALPHABET[third & 63];
|
|
41
|
-
}
|
|
42
|
-
return output;
|
|
43
|
-
}
|
|
44
|
-
function base64ToBytes(base64) {
|
|
45
|
-
const clean = base64.replace(/\s+/g, "");
|
|
46
|
-
if (clean.length === 0) return /* @__PURE__ */ new Uint8Array();
|
|
47
|
-
if (clean.length % 4 !== 0) throw new Error("Invalid base64 payload length");
|
|
48
|
-
const padding = clean.endsWith("==") ? 2 : clean.endsWith("=") ? 1 : 0;
|
|
49
|
-
const bytes = new Uint8Array(clean.length / 4 * 3 - padding);
|
|
50
|
-
let offset = 0;
|
|
51
|
-
for (let index = 0; index < clean.length; index += 4) {
|
|
52
|
-
const first = base64Value(clean[index]);
|
|
53
|
-
const second = base64Value(clean[index + 1]);
|
|
54
|
-
const third = clean[index + 2] === "=" ? 0 : base64Value(clean[index + 2]);
|
|
55
|
-
const fourth = clean[index + 3] === "=" ? 0 : base64Value(clean[index + 3]);
|
|
56
|
-
const triple = first << 18 | second << 12 | third << 6 | fourth;
|
|
57
|
-
if (offset < bytes.byteLength) bytes[offset++] = triple >> 16 & 255;
|
|
58
|
-
if (offset < bytes.byteLength) bytes[offset++] = triple >> 8 & 255;
|
|
59
|
-
if (offset < bytes.byteLength) bytes[offset++] = triple & 255;
|
|
60
|
-
}
|
|
61
|
-
return bytes;
|
|
62
|
-
}
|
|
63
|
-
function base64Value(char) {
|
|
64
|
-
if (!char || char === "=") throw new Error("Invalid base64 payload");
|
|
65
|
-
const value = BASE64_ALPHABET.indexOf(char);
|
|
66
|
-
if (value === -1) throw new Error("Invalid base64 payload");
|
|
67
|
-
return value;
|
|
68
|
-
}
|
|
69
|
-
//#endregion
|
|
70
|
-
export { stringifyAgentJson as n, parseAgentJson as t };
|