mac: bundle web chat assets
This commit is contained in:
62
apps/macos/Sources/Clawdis/Resources/WebChat/agent/agent.d.ts
vendored
Normal file
62
apps/macos/Sources/Clawdis/Resources/WebChat/agent/agent.d.ts
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
import { type AgentTool, type Message, type Model } from "@mariozechner/pi-ai";
|
||||
import type { AppMessage } from "../components/Messages.js";
|
||||
import type { Attachment } from "../utils/attachment-utils.js";
|
||||
import type { AgentTransport } from "./transports/types.js";
|
||||
import type { DebugLogEntry } from "./types.js";
|
||||
export type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high";
|
||||
export interface AgentState {
|
||||
systemPrompt: string;
|
||||
model: Model<any>;
|
||||
thinkingLevel: ThinkingLevel;
|
||||
tools: AgentTool<any>[];
|
||||
messages: AppMessage[];
|
||||
isStreaming: boolean;
|
||||
streamMessage: Message | null;
|
||||
pendingToolCalls: Set<string>;
|
||||
error?: string;
|
||||
}
|
||||
export type AgentEvent = {
|
||||
type: "state-update";
|
||||
state: AgentState;
|
||||
} | {
|
||||
type: "error-no-model";
|
||||
} | {
|
||||
type: "error-no-api-key";
|
||||
provider: string;
|
||||
} | {
|
||||
type: "started";
|
||||
} | {
|
||||
type: "completed";
|
||||
};
|
||||
export interface AgentOptions {
|
||||
initialState?: Partial<AgentState>;
|
||||
debugListener?: (entry: DebugLogEntry) => void;
|
||||
transport: AgentTransport;
|
||||
messageTransformer?: (messages: AppMessage[]) => Message[] | Promise<Message[]>;
|
||||
}
|
||||
export declare class Agent {
|
||||
private _state;
|
||||
private listeners;
|
||||
private abortController?;
|
||||
private transport;
|
||||
private debugListener?;
|
||||
private messageTransformer;
|
||||
private messageQueue;
|
||||
constructor(opts: AgentOptions);
|
||||
get state(): AgentState;
|
||||
subscribe(fn: (e: AgentEvent) => void): () => void;
|
||||
setSystemPrompt(v: string): void;
|
||||
setModel(m: Model<any>): void;
|
||||
setThinkingLevel(l: ThinkingLevel): void;
|
||||
setTools(t: AgentTool<any>[]): void;
|
||||
replaceMessages(ms: AppMessage[]): void;
|
||||
appendMessage(m: AppMessage): void;
|
||||
queueMessage(m: AppMessage): Promise<void>;
|
||||
clearMessages(): void;
|
||||
abort(): void;
|
||||
private logState;
|
||||
prompt(input: string, attachments?: Attachment[]): Promise<void>;
|
||||
private patch;
|
||||
private emit;
|
||||
}
|
||||
//# sourceMappingURL=agent.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent/agent.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,SAAS,EAId,KAAK,OAAO,EACZ,KAAK,KAAK,EAEV,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAkB,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAmBhD,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE1E,MAAM,WAAW,UAAU;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;IACxB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,UAAU,GACnB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,GAC1B;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC;AAEzB,MAAM,WAAW,YAAY;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACnC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,SAAS,EAAE,cAAc,CAAC;IAE1B,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;CAChF;AAED,qBAAa,KAAK;IACjB,OAAO,CAAC,MAAM,CAUZ;IACF,OAAO,CAAC,SAAS,CAAsC;IACvD,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,aAAa,CAAC,CAAiC;IACvD,OAAO,CAAC,kBAAkB,CAA6D;IACvF,OAAO,CAAC,YAAY,CAAwC;gBAEhD,IAAI,EAAE,YAAY;IAO9B,IAAI,KAAK,IAAI,UAAU,CAEtB;IAED,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI;IAOlD,eAAe,CAAC,CAAC,EAAE,MAAM;IAGzB,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC;IAGtB,gBAAgB,CAAC,CAAC,EAAE,aAAa;IAGjC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE;IAG5B,eAAe,CAAC,EAAE,EAAE,UAAU,EAAE;IAGhC,aAAa,CAAC,CAAC,EAAE,UAAU;IAGrB,YAAY,CAAC,CAAC,EAAE,UAAU;IAQhC,aAAa;IAIb,KAAK;IAIL,OAAO,CAAC,QAAQ;IAKV,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE;IA8LtD,OAAO,CAAC,KAAK;IAKb,OAAO,CAAC,IAAI;CAKZ"}
|
||||
272
apps/macos/Sources/Clawdis/Resources/WebChat/agent/agent.js
Normal file
272
apps/macos/Sources/Clawdis/Resources/WebChat/agent/agent.js
Normal file
@@ -0,0 +1,272 @@
|
||||
import { getModel, } from "@mariozechner/pi-ai";
|
||||
// Default transformer: Keep only LLM-compatible messages, strip app-specific fields
|
||||
function defaultMessageTransformer(messages) {
|
||||
return messages
|
||||
.filter((m) => {
|
||||
// Only keep standard LLM message roles
|
||||
return m.role === "user" || m.role === "assistant" || m.role === "toolResult";
|
||||
})
|
||||
.map((m) => {
|
||||
if (m.role === "user") {
|
||||
// Strip attachments field (app-specific)
|
||||
const { attachments, ...rest } = m;
|
||||
return rest;
|
||||
}
|
||||
return m;
|
||||
});
|
||||
}
|
||||
export class Agent {
|
||||
constructor(opts) {
|
||||
this._state = {
|
||||
systemPrompt: "",
|
||||
model: getModel("google", "gemini-2.5-flash-lite-preview-06-17"),
|
||||
thinkingLevel: "off",
|
||||
tools: [],
|
||||
messages: [],
|
||||
isStreaming: false,
|
||||
streamMessage: null,
|
||||
pendingToolCalls: new Set(),
|
||||
error: undefined,
|
||||
};
|
||||
this.listeners = new Set();
|
||||
this.messageQueue = [];
|
||||
this._state = { ...this._state, ...opts.initialState };
|
||||
this.debugListener = opts.debugListener;
|
||||
this.transport = opts.transport;
|
||||
this.messageTransformer = opts.messageTransformer || defaultMessageTransformer;
|
||||
}
|
||||
get state() {
|
||||
return this._state;
|
||||
}
|
||||
subscribe(fn) {
|
||||
this.listeners.add(fn);
|
||||
fn({ type: "state-update", state: this._state });
|
||||
return () => this.listeners.delete(fn);
|
||||
}
|
||||
// Mutators
|
||||
setSystemPrompt(v) {
|
||||
this.patch({ systemPrompt: v });
|
||||
}
|
||||
setModel(m) {
|
||||
this.patch({ model: m });
|
||||
}
|
||||
setThinkingLevel(l) {
|
||||
this.patch({ thinkingLevel: l });
|
||||
}
|
||||
setTools(t) {
|
||||
this.patch({ tools: t });
|
||||
}
|
||||
replaceMessages(ms) {
|
||||
this.patch({ messages: ms.slice() });
|
||||
}
|
||||
appendMessage(m) {
|
||||
this.patch({ messages: [...this._state.messages, m] });
|
||||
}
|
||||
async queueMessage(m) {
|
||||
// Transform message and queue it for injection at next turn
|
||||
const transformed = await this.messageTransformer([m]);
|
||||
this.messageQueue.push({
|
||||
original: m,
|
||||
llm: transformed[0], // undefined if filtered out
|
||||
});
|
||||
}
|
||||
clearMessages() {
|
||||
this.patch({ messages: [] });
|
||||
}
|
||||
abort() {
|
||||
this.abortController?.abort();
|
||||
}
|
||||
logState(message) {
|
||||
const { systemPrompt, model, messages } = this._state;
|
||||
console.log(message, { systemPrompt, model, messages });
|
||||
}
|
||||
async prompt(input, attachments) {
|
||||
const model = this._state.model;
|
||||
if (!model) {
|
||||
this.emit({ type: "error-no-model" });
|
||||
return;
|
||||
}
|
||||
// Build user message with attachments
|
||||
const content = [{ type: "text", text: input }];
|
||||
if (attachments?.length) {
|
||||
for (const a of attachments) {
|
||||
if (a.type === "image") {
|
||||
content.push({ type: "image", data: a.content, mimeType: a.mimeType });
|
||||
}
|
||||
else if (a.type === "document" && a.extractedText) {
|
||||
content.push({
|
||||
type: "text",
|
||||
text: `\n\n[Document: ${a.fileName}]\n${a.extractedText}`,
|
||||
isDocument: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
const userMessage = {
|
||||
role: "user",
|
||||
content,
|
||||
attachments: attachments?.length ? attachments : undefined,
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
this.abortController = new AbortController();
|
||||
this.patch({ isStreaming: true, streamMessage: null, error: undefined });
|
||||
this.emit({ type: "started" });
|
||||
const reasoning = this._state.thinkingLevel === "off"
|
||||
? undefined
|
||||
: this._state.thinkingLevel === "minimal"
|
||||
? "low"
|
||||
: this._state.thinkingLevel;
|
||||
const cfg = {
|
||||
systemPrompt: this._state.systemPrompt,
|
||||
tools: this._state.tools,
|
||||
model,
|
||||
reasoning,
|
||||
getQueuedMessages: async () => {
|
||||
// Return queued messages (they'll be added to state via message_end event)
|
||||
const queued = this.messageQueue.slice();
|
||||
this.messageQueue = [];
|
||||
return queued;
|
||||
},
|
||||
};
|
||||
try {
|
||||
let partial = null;
|
||||
let turnDebug = null;
|
||||
let turnStart = 0;
|
||||
this.logState("prompt started, current state:");
|
||||
// Transform app messages to LLM-compatible messages (initial set)
|
||||
const llmMessages = await this.messageTransformer(this._state.messages);
|
||||
console.log("transformed messages:", llmMessages);
|
||||
for await (const ev of this.transport.run(llmMessages, userMessage, cfg, this.abortController.signal)) {
|
||||
switch (ev.type) {
|
||||
case "turn_start": {
|
||||
turnStart = performance.now();
|
||||
// Build request context snapshot (use transformed messages)
|
||||
const ctx = {
|
||||
systemPrompt: this._state.systemPrompt,
|
||||
messages: [...llmMessages],
|
||||
tools: this._state.tools,
|
||||
};
|
||||
turnDebug = {
|
||||
timestamp: new Date().toISOString(),
|
||||
request: {
|
||||
provider: cfg.model.provider,
|
||||
model: cfg.model.id,
|
||||
context: { ...ctx },
|
||||
},
|
||||
sseEvents: [],
|
||||
};
|
||||
break;
|
||||
}
|
||||
case "message_start":
|
||||
case "message_update": {
|
||||
partial = ev.message;
|
||||
// Collect SSE-like events for debug (drop heavy partial)
|
||||
if (ev.type === "message_update" && ev.assistantMessageEvent && turnDebug) {
|
||||
const copy = { ...ev.assistantMessageEvent };
|
||||
if (copy && "partial" in copy)
|
||||
delete copy.partial;
|
||||
turnDebug.sseEvents.push(JSON.stringify(copy));
|
||||
if (!turnDebug.ttft)
|
||||
turnDebug.ttft = performance.now() - turnStart;
|
||||
}
|
||||
this.patch({ streamMessage: ev.message });
|
||||
break;
|
||||
}
|
||||
case "message_end": {
|
||||
partial = null;
|
||||
this.appendMessage(ev.message);
|
||||
this.patch({ streamMessage: null });
|
||||
if (turnDebug) {
|
||||
if (ev.message.role !== "assistant" && ev.message.role !== "toolResult") {
|
||||
turnDebug.request.context.messages.push(ev.message);
|
||||
}
|
||||
if (ev.message.role === "assistant")
|
||||
turnDebug.response = ev.message;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "tool_execution_start": {
|
||||
const s = new Set(this._state.pendingToolCalls);
|
||||
s.add(ev.toolCallId);
|
||||
this.patch({ pendingToolCalls: s });
|
||||
break;
|
||||
}
|
||||
case "tool_execution_end": {
|
||||
const s = new Set(this._state.pendingToolCalls);
|
||||
s.delete(ev.toolCallId);
|
||||
this.patch({ pendingToolCalls: s });
|
||||
break;
|
||||
}
|
||||
case "turn_end": {
|
||||
// finalize current turn
|
||||
if (turnDebug) {
|
||||
turnDebug.totalTime = performance.now() - turnStart;
|
||||
this.debugListener?.(turnDebug);
|
||||
turnDebug = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "agent_end": {
|
||||
this.patch({ streamMessage: null });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (partial && partial.role === "assistant" && partial.content.length > 0) {
|
||||
const onlyEmpty = !partial.content.some((c) => (c.type === "thinking" && c.thinking.trim().length > 0) ||
|
||||
(c.type === "text" && c.text.trim().length > 0) ||
|
||||
(c.type === "toolCall" && c.name.trim().length > 0));
|
||||
if (!onlyEmpty) {
|
||||
this.appendMessage(partial);
|
||||
}
|
||||
else {
|
||||
if (this.abortController?.signal.aborted) {
|
||||
throw new Error("Request was aborted");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
if (String(err?.message || err) === "no-api-key") {
|
||||
this.emit({ type: "error-no-api-key", provider: model.provider });
|
||||
}
|
||||
else {
|
||||
const msg = {
|
||||
role: "assistant",
|
||||
content: [{ type: "text", text: "" }],
|
||||
api: model.api,
|
||||
provider: model.provider,
|
||||
model: model.id,
|
||||
usage: {
|
||||
input: 0,
|
||||
output: 0,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
||||
},
|
||||
stopReason: this.abortController?.signal.aborted ? "aborted" : "error",
|
||||
errorMessage: err?.message || String(err),
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
this.appendMessage(msg);
|
||||
this.patch({ error: err?.message || String(err) });
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.patch({ isStreaming: false, streamMessage: null, pendingToolCalls: new Set() });
|
||||
this.abortController = undefined;
|
||||
this.emit({ type: "completed" });
|
||||
}
|
||||
this.logState("final state:");
|
||||
}
|
||||
patch(p) {
|
||||
this._state = { ...this._state, ...p };
|
||||
this.emit({ type: "state-update", state: this._state });
|
||||
}
|
||||
emit(e) {
|
||||
for (const listener of this.listeners) {
|
||||
listener(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=agent.js.map
|
||||
File diff suppressed because one or more lines are too long
11
apps/macos/Sources/Clawdis/Resources/WebChat/agent/transports/AppTransport.d.ts
vendored
Normal file
11
apps/macos/Sources/Clawdis/Resources/WebChat/agent/transports/AppTransport.d.ts
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import type { Message } from "@mariozechner/pi-ai";
|
||||
import type { AgentRunConfig, AgentTransport } from "./types.js";
|
||||
/**
|
||||
* Transport that uses an app server with user authentication tokens.
|
||||
* The server manages user accounts and proxies requests to LLM providers.
|
||||
*/
|
||||
export declare class AppTransport implements AgentTransport {
|
||||
private readonly proxyUrl;
|
||||
run(messages: Message[], userMessage: Message, cfg: AgentRunConfig, signal?: AbortSignal): AsyncGenerator<import("@mariozechner/pi-ai").AgentEvent, void, unknown>;
|
||||
}
|
||||
//# sourceMappingURL=AppTransport.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"AppTransport.d.ts","sourceRoot":"","sources":["../../../src/agent/transports/AppTransport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAOX,OAAO,EAKP,MAAM,qBAAqB,CAAC;AAO7B,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AA0SjE;;;GAGG;AACH,qBAAa,YAAa,YAAW,cAAc;IAElD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmC;IAErD,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,WAAW;CAsC/F"}
|
||||
@@ -0,0 +1,318 @@
|
||||
import { agentLoop } from "@mariozechner/pi-ai";
|
||||
import { AssistantMessageEventStream } from "@mariozechner/pi-ai/dist/utils/event-stream.js";
|
||||
import { parseStreamingJson } from "@mariozechner/pi-ai/dist/utils/json-parse.js";
|
||||
import { clearAuthToken, getAuthToken } from "../../utils/auth-token.js";
|
||||
import { i18n } from "../../utils/i18n.js";
|
||||
/**
|
||||
* Stream function that proxies through a server instead of calling providers directly.
|
||||
* The server strips the partial field from delta events to reduce bandwidth.
|
||||
* We reconstruct the partial message client-side.
|
||||
*/
|
||||
function streamSimpleProxy(model, context, options, proxyUrl) {
|
||||
const stream = new AssistantMessageEventStream();
|
||||
(async () => {
|
||||
// Initialize the partial message that we'll build up from events
|
||||
const partial = {
|
||||
role: "assistant",
|
||||
stopReason: "stop",
|
||||
content: [],
|
||||
api: model.api,
|
||||
provider: model.provider,
|
||||
model: model.id,
|
||||
usage: {
|
||||
input: 0,
|
||||
output: 0,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
||||
},
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
let reader;
|
||||
// Set up abort handler to cancel the reader
|
||||
const abortHandler = () => {
|
||||
if (reader) {
|
||||
reader.cancel("Request aborted by user").catch(() => { });
|
||||
}
|
||||
};
|
||||
if (options.signal) {
|
||||
options.signal.addEventListener("abort", abortHandler);
|
||||
}
|
||||
try {
|
||||
const response = await fetch(`${proxyUrl}/api/stream`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${options.authToken}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model,
|
||||
context,
|
||||
options: {
|
||||
temperature: options.temperature,
|
||||
maxTokens: options.maxTokens,
|
||||
reasoning: options.reasoning,
|
||||
// Don't send apiKey or signal - those are added server-side
|
||||
},
|
||||
}),
|
||||
signal: options.signal,
|
||||
});
|
||||
if (!response.ok) {
|
||||
let errorMessage = `Proxy error: ${response.status} ${response.statusText}`;
|
||||
try {
|
||||
const errorData = await response.json();
|
||||
if (errorData.error) {
|
||||
errorMessage = `Proxy error: ${errorData.error}`;
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// Couldn't parse error response, use default message
|
||||
}
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
// Parse SSE stream
|
||||
reader = response.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = "";
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done)
|
||||
break;
|
||||
// Check if aborted after reading
|
||||
if (options.signal?.aborted) {
|
||||
throw new Error("Request aborted by user");
|
||||
}
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const lines = buffer.split("\n");
|
||||
buffer = lines.pop() || "";
|
||||
for (const line of lines) {
|
||||
if (line.startsWith("data: ")) {
|
||||
const data = line.slice(6).trim();
|
||||
if (data) {
|
||||
const proxyEvent = JSON.parse(data);
|
||||
let event;
|
||||
// Handle different event types
|
||||
// Server sends events with partial for non-delta events,
|
||||
// and without partial for delta events
|
||||
switch (proxyEvent.type) {
|
||||
case "start":
|
||||
event = { type: "start", partial };
|
||||
break;
|
||||
case "text_start":
|
||||
partial.content[proxyEvent.contentIndex] = {
|
||||
type: "text",
|
||||
text: "",
|
||||
};
|
||||
event = { type: "text_start", contentIndex: proxyEvent.contentIndex, partial };
|
||||
break;
|
||||
case "text_delta": {
|
||||
const content = partial.content[proxyEvent.contentIndex];
|
||||
if (content?.type === "text") {
|
||||
content.text += proxyEvent.delta;
|
||||
event = {
|
||||
type: "text_delta",
|
||||
contentIndex: proxyEvent.contentIndex,
|
||||
delta: proxyEvent.delta,
|
||||
partial,
|
||||
};
|
||||
}
|
||||
else {
|
||||
throw new Error("Received text_delta for non-text content");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "text_end": {
|
||||
const content = partial.content[proxyEvent.contentIndex];
|
||||
if (content?.type === "text") {
|
||||
content.textSignature = proxyEvent.contentSignature;
|
||||
event = {
|
||||
type: "text_end",
|
||||
contentIndex: proxyEvent.contentIndex,
|
||||
content: content.text,
|
||||
partial,
|
||||
};
|
||||
}
|
||||
else {
|
||||
throw new Error("Received text_end for non-text content");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "thinking_start":
|
||||
partial.content[proxyEvent.contentIndex] = {
|
||||
type: "thinking",
|
||||
thinking: "",
|
||||
};
|
||||
event = { type: "thinking_start", contentIndex: proxyEvent.contentIndex, partial };
|
||||
break;
|
||||
case "thinking_delta": {
|
||||
const content = partial.content[proxyEvent.contentIndex];
|
||||
if (content?.type === "thinking") {
|
||||
content.thinking += proxyEvent.delta;
|
||||
event = {
|
||||
type: "thinking_delta",
|
||||
contentIndex: proxyEvent.contentIndex,
|
||||
delta: proxyEvent.delta,
|
||||
partial,
|
||||
};
|
||||
}
|
||||
else {
|
||||
throw new Error("Received thinking_delta for non-thinking content");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "thinking_end": {
|
||||
const content = partial.content[proxyEvent.contentIndex];
|
||||
if (content?.type === "thinking") {
|
||||
content.thinkingSignature = proxyEvent.contentSignature;
|
||||
event = {
|
||||
type: "thinking_end",
|
||||
contentIndex: proxyEvent.contentIndex,
|
||||
content: content.thinking,
|
||||
partial,
|
||||
};
|
||||
}
|
||||
else {
|
||||
throw new Error("Received thinking_end for non-thinking content");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "toolcall_start":
|
||||
partial.content[proxyEvent.contentIndex] = {
|
||||
type: "toolCall",
|
||||
id: proxyEvent.id,
|
||||
name: proxyEvent.toolName,
|
||||
arguments: {},
|
||||
partialJson: "",
|
||||
};
|
||||
event = { type: "toolcall_start", contentIndex: proxyEvent.contentIndex, partial };
|
||||
break;
|
||||
case "toolcall_delta": {
|
||||
const content = partial.content[proxyEvent.contentIndex];
|
||||
if (content?.type === "toolCall") {
|
||||
content.partialJson += proxyEvent.delta;
|
||||
content.arguments = parseStreamingJson(content.partialJson) || {};
|
||||
event = {
|
||||
type: "toolcall_delta",
|
||||
contentIndex: proxyEvent.contentIndex,
|
||||
delta: proxyEvent.delta,
|
||||
partial,
|
||||
};
|
||||
partial.content[proxyEvent.contentIndex] = { ...content }; // Trigger reactivity
|
||||
}
|
||||
else {
|
||||
throw new Error("Received toolcall_delta for non-toolCall content");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "toolcall_end": {
|
||||
const content = partial.content[proxyEvent.contentIndex];
|
||||
if (content?.type === "toolCall") {
|
||||
delete content.partialJson;
|
||||
event = {
|
||||
type: "toolcall_end",
|
||||
contentIndex: proxyEvent.contentIndex,
|
||||
toolCall: content,
|
||||
partial,
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "done":
|
||||
partial.stopReason = proxyEvent.reason;
|
||||
partial.usage = proxyEvent.usage;
|
||||
event = { type: "done", reason: proxyEvent.reason, message: partial };
|
||||
break;
|
||||
case "error":
|
||||
partial.stopReason = proxyEvent.reason;
|
||||
partial.errorMessage = proxyEvent.errorMessage;
|
||||
partial.usage = proxyEvent.usage;
|
||||
event = { type: "error", reason: proxyEvent.reason, error: partial };
|
||||
break;
|
||||
default: {
|
||||
// Exhaustive check
|
||||
const _exhaustiveCheck = proxyEvent;
|
||||
console.warn(`Unhandled event type: ${proxyEvent.type}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Push the event to stream
|
||||
if (event) {
|
||||
stream.push(event);
|
||||
}
|
||||
else {
|
||||
throw new Error("Failed to create event from proxy event");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if aborted after reading
|
||||
if (options.signal?.aborted) {
|
||||
throw new Error("Request aborted by user");
|
||||
}
|
||||
stream.end();
|
||||
}
|
||||
catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
if (errorMessage.toLowerCase().includes("proxy") && errorMessage.includes("Unauthorized")) {
|
||||
clearAuthToken();
|
||||
}
|
||||
partial.stopReason = options.signal?.aborted ? "aborted" : "error";
|
||||
partial.errorMessage = errorMessage;
|
||||
stream.push({
|
||||
type: "error",
|
||||
reason: partial.stopReason,
|
||||
error: partial,
|
||||
});
|
||||
stream.end();
|
||||
}
|
||||
finally {
|
||||
// Clean up abort handler
|
||||
if (options.signal) {
|
||||
options.signal.removeEventListener("abort", abortHandler);
|
||||
}
|
||||
}
|
||||
})();
|
||||
return stream;
|
||||
}
|
||||
// Proxy transport executes the turn using a remote proxy server
|
||||
/**
|
||||
* Transport that uses an app server with user authentication tokens.
|
||||
* The server manages user accounts and proxies requests to LLM providers.
|
||||
*/
|
||||
export class AppTransport {
|
||||
constructor() {
|
||||
// Hardcoded proxy URL for now - will be made configurable later
|
||||
this.proxyUrl = "https://genai.mariozechner.at";
|
||||
}
|
||||
async *run(messages, userMessage, cfg, signal) {
|
||||
const authToken = await getAuthToken();
|
||||
if (!authToken) {
|
||||
throw new Error(i18n("Auth token is required for proxy transport"));
|
||||
}
|
||||
// Use proxy - no local API key needed
|
||||
const streamFn = (model, context, options) => {
|
||||
return streamSimpleProxy(model, context, {
|
||||
...options,
|
||||
authToken,
|
||||
}, this.proxyUrl);
|
||||
};
|
||||
// Messages are already LLM-compatible (filtered by Agent)
|
||||
const context = {
|
||||
systemPrompt: cfg.systemPrompt,
|
||||
messages,
|
||||
tools: cfg.tools,
|
||||
};
|
||||
const pc = {
|
||||
model: cfg.model,
|
||||
reasoning: cfg.reasoning,
|
||||
getQueuedMessages: cfg.getQueuedMessages,
|
||||
};
|
||||
// Yield events from the upstream agentLoop iterator
|
||||
// Pass streamFn as the 5th parameter to use proxy
|
||||
for await (const ev of agentLoop(userMessage, context, pc, signal, streamFn)) {
|
||||
yield ev;
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=AppTransport.js.map
|
||||
File diff suppressed because one or more lines are too long
10
apps/macos/Sources/Clawdis/Resources/WebChat/agent/transports/ProviderTransport.d.ts
vendored
Normal file
10
apps/macos/Sources/Clawdis/Resources/WebChat/agent/transports/ProviderTransport.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import { type Message } from "@mariozechner/pi-ai";
|
||||
import type { AgentRunConfig, AgentTransport } from "./types.js";
|
||||
/**
|
||||
* Transport that calls LLM providers directly.
|
||||
* Uses CORS proxy only for providers that require it (Anthropic OAuth, Z-AI).
|
||||
*/
|
||||
export declare class ProviderTransport implements AgentTransport {
|
||||
run(messages: Message[], userMessage: Message, cfg: AgentRunConfig, signal?: AbortSignal): AsyncGenerator<import("@mariozechner/pi-ai").AgentEvent, void, unknown>;
|
||||
}
|
||||
//# sourceMappingURL=ProviderTransport.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"ProviderTransport.d.ts","sourceRoot":"","sources":["../../../src/agent/transports/ProviderTransport.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,OAAO,EAEZ,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjE;;;GAGG;AACH,qBAAa,iBAAkB,YAAW,cAAc;IAChD,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,WAAW;CAiC/F"}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { agentLoop, } from "@mariozechner/pi-ai";
|
||||
import { getAppStorage } from "../../storage/app-storage.js";
|
||||
import { applyProxyIfNeeded } from "../../utils/proxy-utils.js";
|
||||
/**
|
||||
* Transport that calls LLM providers directly.
|
||||
* Uses CORS proxy only for providers that require it (Anthropic OAuth, Z-AI).
|
||||
*/
|
||||
export class ProviderTransport {
|
||||
async *run(messages, userMessage, cfg, signal) {
|
||||
// Get API key from storage
|
||||
const apiKey = await getAppStorage().providerKeys.get(cfg.model.provider);
|
||||
if (!apiKey) {
|
||||
throw new Error("no-api-key");
|
||||
}
|
||||
// Get proxy URL from settings (if available)
|
||||
const proxyEnabled = await getAppStorage().settings.get("proxy.enabled");
|
||||
const proxyUrl = await getAppStorage().settings.get("proxy.url");
|
||||
// Apply proxy only if this provider/key combination requires it
|
||||
const model = applyProxyIfNeeded(cfg.model, apiKey, proxyEnabled ? proxyUrl || undefined : undefined);
|
||||
// Messages are already LLM-compatible (filtered by Agent)
|
||||
const context = {
|
||||
systemPrompt: cfg.systemPrompt,
|
||||
messages,
|
||||
tools: cfg.tools,
|
||||
};
|
||||
const pc = {
|
||||
model,
|
||||
reasoning: cfg.reasoning,
|
||||
apiKey,
|
||||
getQueuedMessages: cfg.getQueuedMessages,
|
||||
};
|
||||
// Yield events from agentLoop
|
||||
for await (const ev of agentLoop(userMessage, context, pc, signal)) {
|
||||
yield ev;
|
||||
}
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=ProviderTransport.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"ProviderTransport.js","sourceRoot":"","sources":["../../../src/agent/transports/ProviderTransport.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,SAAS,GAGT,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGhE;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IAC7B,KAAK,CAAC,CAAC,GAAG,CAAC,QAAmB,EAAE,WAAoB,EAAE,GAAmB,EAAE,MAAoB;QAC9F,2BAA2B;QAC3B,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC1E,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;QAC/B,CAAC;QAED,6CAA6C;QAC7C,MAAM,YAAY,GAAG,MAAM,aAAa,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAU,eAAe,CAAC,CAAC;QAClF,MAAM,QAAQ,GAAG,MAAM,aAAa,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAS,WAAW,CAAC,CAAC;QAEzE,gEAAgE;QAChE,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,QAAQ,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAEtG,0DAA0D;QAC1D,MAAM,OAAO,GAAiB;YAC7B,YAAY,EAAE,GAAG,CAAC,YAAY;YAC9B,QAAQ;YACR,KAAK,EAAE,GAAG,CAAC,KAAK;SAChB,CAAC;QAEF,MAAM,EAAE,GAAoB;YAC3B,KAAK;YACL,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,MAAM;YACN,iBAAiB,EAAE,GAAG,CAAC,iBAAiB;SACxC,CAAC;QAEF,8BAA8B;QAC9B,IAAI,KAAK,EAAE,MAAM,EAAE,IAAI,SAAS,CAAC,WAAqC,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC;YAC9F,MAAM,EAAE,CAAC;QACV,CAAC;IACF,CAAC;CACD"}
|
||||
4
apps/macos/Sources/Clawdis/Resources/WebChat/agent/transports/index.d.ts
vendored
Normal file
4
apps/macos/Sources/Clawdis/Resources/WebChat/agent/transports/index.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from "./AppTransport.js";
|
||||
export * from "./ProviderTransport.js";
|
||||
export * from "./types.js";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/transports/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,YAAY,CAAC"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from "./AppTransport.js";
|
||||
export * from "./ProviderTransport.js";
|
||||
export * from "./types.js";
|
||||
//# sourceMappingURL=index.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/agent/transports/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,YAAY,CAAC"}
|
||||
48
apps/macos/Sources/Clawdis/Resources/WebChat/agent/transports/proxy-types.d.ts
vendored
Normal file
48
apps/macos/Sources/Clawdis/Resources/WebChat/agent/transports/proxy-types.d.ts
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
import type { StopReason, Usage } from "@mariozechner/pi-ai";
|
||||
export type ProxyAssistantMessageEvent = {
|
||||
type: "start";
|
||||
} | {
|
||||
type: "text_start";
|
||||
contentIndex: number;
|
||||
} | {
|
||||
type: "text_delta";
|
||||
contentIndex: number;
|
||||
delta: string;
|
||||
} | {
|
||||
type: "text_end";
|
||||
contentIndex: number;
|
||||
contentSignature?: string;
|
||||
} | {
|
||||
type: "thinking_start";
|
||||
contentIndex: number;
|
||||
} | {
|
||||
type: "thinking_delta";
|
||||
contentIndex: number;
|
||||
delta: string;
|
||||
} | {
|
||||
type: "thinking_end";
|
||||
contentIndex: number;
|
||||
contentSignature?: string;
|
||||
} | {
|
||||
type: "toolcall_start";
|
||||
contentIndex: number;
|
||||
id: string;
|
||||
toolName: string;
|
||||
} | {
|
||||
type: "toolcall_delta";
|
||||
contentIndex: number;
|
||||
delta: string;
|
||||
} | {
|
||||
type: "toolcall_end";
|
||||
contentIndex: number;
|
||||
} | {
|
||||
type: "done";
|
||||
reason: Extract<StopReason, "stop" | "length" | "toolUse">;
|
||||
usage: Usage;
|
||||
} | {
|
||||
type: "error";
|
||||
reason: Extract<StopReason, "aborted" | "error">;
|
||||
errorMessage: string;
|
||||
usage: Usage;
|
||||
};
|
||||
//# sourceMappingURL=proxy-types.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"proxy-types.d.ts","sourceRoot":"","sources":["../../../src/agent/transports/proxy-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE7D,MAAM,MAAM,0BAA0B,GACnC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,GACzE;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC9E;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAC1F;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC"}
|
||||
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=proxy-types.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"proxy-types.js","sourceRoot":"","sources":["../../../src/agent/transports/proxy-types.ts"],"names":[],"mappings":""}
|
||||
12
apps/macos/Sources/Clawdis/Resources/WebChat/agent/transports/types.d.ts
vendored
Normal file
12
apps/macos/Sources/Clawdis/Resources/WebChat/agent/transports/types.d.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import type { AgentEvent, AgentTool, Message, Model, QueuedMessage } from "@mariozechner/pi-ai";
|
||||
export interface AgentRunConfig {
|
||||
systemPrompt: string;
|
||||
tools: AgentTool<any>[];
|
||||
model: Model<any>;
|
||||
reasoning?: "low" | "medium" | "high";
|
||||
getQueuedMessages?: <T>() => Promise<QueuedMessage<T>[]>;
|
||||
}
|
||||
export interface AgentTransport {
|
||||
run(messages: Message[], userMessage: Message, config: AgentRunConfig, signal?: AbortSignal): AsyncIterable<AgentEvent>;
|
||||
}
|
||||
//# sourceMappingURL=types.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/agent/transports/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGhG,MAAM,WAAW,cAAc;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;IACxB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACtC,iBAAiB,CAAC,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;CACzD;AAKD,MAAM,WAAW,cAAc;IAC9B,GAAG,CACF,QAAQ,EAAE,OAAO,EAAE,EACnB,WAAW,EAAE,OAAO,EACpB,MAAM,EAAE,cAAc,EACtB,MAAM,CAAC,EAAE,WAAW,GAClB,aAAa,CAAC,UAAU,CAAC,CAAC;CAC7B"}
|
||||
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=types.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/agent/transports/types.ts"],"names":[],"mappings":""}
|
||||
15
apps/macos/Sources/Clawdis/Resources/WebChat/agent/types.d.ts
vendored
Normal file
15
apps/macos/Sources/Clawdis/Resources/WebChat/agent/types.d.ts
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { AssistantMessage, Context } from "@mariozechner/pi-ai";
|
||||
export interface DebugLogEntry {
|
||||
timestamp: string;
|
||||
request: {
|
||||
provider: string;
|
||||
model: string;
|
||||
context: Context;
|
||||
};
|
||||
response?: AssistantMessage;
|
||||
error?: unknown;
|
||||
sseEvents: string[];
|
||||
ttft?: number;
|
||||
totalTime?: number;
|
||||
}
|
||||
//# sourceMappingURL=types.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agent/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAErE,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/D,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB"}
|
||||
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=types.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/agent/types.ts"],"names":[],"mappings":""}
|
||||
Reference in New Issue
Block a user