@hachej/boring-agent 0.1.63 → 0.1.65
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/{agentPluginEvents-Ddn5DQ5E.d.ts → agentPluginEvents-ChUzG2Lh.d.ts} +3 -134
- package/dist/chatSubmitPayload-DwOHyiqR.d.ts +22 -0
- package/dist/chunk-4LXA7OOV.js +290 -0
- package/dist/chunk-AJZHR626.js +85 -0
- package/dist/chunk-AQBXNPMD.js +17 -0
- package/dist/chunk-HHW2UNBK.js +1812 -0
- package/dist/chunk-NKP5AR4C.js +2755 -0
- package/dist/chunk-WSQ5QNIY.js +18 -0
- package/dist/chunk-XZKU7FBV.js +96 -0
- package/dist/{chunk-HDOSWEXG.js → chunk-ZD7MM2LQ.js} +0 -15
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.js +15 -0
- package/dist/createHarness-LA2OO2DL.js +17 -0
- package/dist/front/index.d.ts +32 -27
- package/dist/front/index.js +84 -30
- package/dist/front/styles.css +67 -70
- package/dist/harness-DN9KdrT7.d.ts +265 -0
- package/dist/piChatCommand-C5ZM-AMG.d.ts +40 -0
- package/dist/{piChatEvent-B6GDifo2.d.ts → piChatEvent-B6Lg9ft-.d.ts} +88 -98
- package/dist/server/index.d.ts +238 -6
- package/dist/server/index.js +3294 -6225
- package/dist/shared/index.d.ts +212 -208
- package/dist/shared/index.js +21 -9
- package/docs/ERROR_CODES.md +3 -0
- package/docs/plans/archive/harness-followup-capabilities.md +1 -1
- package/docs/plans/archive/pi-tools-migration.md +1 -1
- package/docs/plans/archive/vercel-persistent-sandbox-adapter.md +1 -1
- package/docs/runtime.md +22 -9
- package/package.json +39 -34
- package/dist/chatSubmitPayload-DHqQL2wD.d.ts +0 -48
- package/dist/chunk-G6YPXDHR.js +0 -376
|
@@ -1,134 +1,3 @@
|
|
|
1
|
-
import { d as SessionStore } from './chatSubmitPayload-DHqQL2wD.js';
|
|
2
|
-
|
|
3
|
-
interface TelemetrySink {
|
|
4
|
-
capture(event: TelemetryEvent): void | Promise<void>;
|
|
5
|
-
flush?(): void | Promise<void>;
|
|
6
|
-
}
|
|
7
|
-
interface TelemetryEvent {
|
|
8
|
-
name: string;
|
|
9
|
-
distinctId?: string;
|
|
10
|
-
properties?: Record<string, unknown>;
|
|
11
|
-
}
|
|
12
|
-
declare const noopTelemetry: TelemetrySink;
|
|
13
|
-
declare function safeCapture(telemetry: TelemetrySink, event: TelemetryEvent): void;
|
|
14
|
-
|
|
15
|
-
type JSONSchema = Record<string, unknown>;
|
|
16
|
-
type ToolReadinessRequirement = 'workspace-fs' | 'sandbox-exec' | 'ui-bridge' | 'runtime-dependencies' | `runtime:${string}`;
|
|
17
|
-
interface AgentTool {
|
|
18
|
-
name: string;
|
|
19
|
-
description: string;
|
|
20
|
-
/** Optional one-line prompt entry. Pi-built tools should preserve pi's snippet verbatim. */
|
|
21
|
-
promptSnippet?: string;
|
|
22
|
-
readinessRequirements?: ToolReadinessRequirement[];
|
|
23
|
-
parameters: JSONSchema;
|
|
24
|
-
execute(params: Record<string, unknown>, ctx: ToolExecContext): Promise<ToolResult>;
|
|
25
|
-
}
|
|
26
|
-
interface ToolExecContext {
|
|
27
|
-
abortSignal: AbortSignal;
|
|
28
|
-
toolCallId: string;
|
|
29
|
-
onUpdate?: (partial: string) => void;
|
|
30
|
-
/** Agent chat/session id executing this tool, when known. */
|
|
31
|
-
sessionId?: string;
|
|
32
|
-
}
|
|
33
|
-
interface ToolResult {
|
|
34
|
-
content: Array<{
|
|
35
|
-
type: 'text';
|
|
36
|
-
text: string;
|
|
37
|
-
}>;
|
|
38
|
-
isError?: boolean;
|
|
39
|
-
details?: unknown;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
interface AgentHarnessFactoryInput {
|
|
43
|
-
tools: AgentTool[];
|
|
44
|
-
/** Host/storage cwd used for harness-owned filesystem resources. */
|
|
45
|
-
cwd: string;
|
|
46
|
-
/** Agent-visible cwd used by Pi/system prompt/session metadata. */
|
|
47
|
-
runtimeCwd?: string;
|
|
48
|
-
systemPromptAppend?: string;
|
|
49
|
-
sessionNamespace?: string;
|
|
50
|
-
sessionRoot?: string;
|
|
51
|
-
sessionDir?: string;
|
|
52
|
-
/**
|
|
53
|
-
* Optional dynamic system-prompt source. Harness calls it whenever it
|
|
54
|
-
* builds or rebuilds a session prompt and appends the returned string.
|
|
55
|
-
* Workspace plugin layer wires this so live-reloaded plugins can contribute
|
|
56
|
-
* prompt context without a workspace-injected harness extension.
|
|
57
|
-
*/
|
|
58
|
-
systemPromptDynamic?: () => string | undefined | Promise<string | undefined>;
|
|
59
|
-
/** Host-provided telemetry sink. Optional and best-effort; harnesses may ignore it. */
|
|
60
|
-
telemetry?: TelemetrySink;
|
|
61
|
-
}
|
|
62
|
-
type AgentHarnessFactory = (input: AgentHarnessFactoryInput) => AgentHarness | Promise<AgentHarness>;
|
|
63
|
-
interface AgentHarness {
|
|
64
|
-
readonly id: string;
|
|
65
|
-
readonly placement: 'server' | 'browser';
|
|
66
|
-
/** Session lifecycle; may delegate to an underlying runtime (e.g. pi's JSONL). */
|
|
67
|
-
sessions: SessionStore;
|
|
68
|
-
/**
|
|
69
|
-
* Resolved system prompt currently in effect for `sessionId`. Returns
|
|
70
|
-
* `undefined` when the underlying runtime hasn't yet instantiated a
|
|
71
|
-
* session (typical pre-first-turn state — pi creates lazily on the first
|
|
72
|
-
* prompt). Optional so non-pi harnesses can opt out cleanly.
|
|
73
|
-
*/
|
|
74
|
-
getSystemPrompt?: (sessionId: string) => string | undefined;
|
|
75
|
-
/** Reload native agent resources/extensions for an existing session. */
|
|
76
|
-
reloadSession?: (sessionId: string) => Promise<boolean>;
|
|
77
|
-
/**
|
|
78
|
-
* Resource (skill/extension) load diagnostics for an existing session.
|
|
79
|
-
* Returns `[]` when the session has no live agent session yet. Lets the
|
|
80
|
-
* /reload route and the `plugin_diagnostics` tool surface silent
|
|
81
|
-
* skill/extension load failures back to the UI and the agent.
|
|
82
|
-
*/
|
|
83
|
-
getResourceDiagnostics?: (sessionId: string) => Array<{
|
|
84
|
-
source: string;
|
|
85
|
-
message: string;
|
|
86
|
-
path?: string;
|
|
87
|
-
}>;
|
|
88
|
-
/** List slash commands registered in the agent runtime for a given session. */
|
|
89
|
-
getSlashCommands?: (sessionId: string, ctx: RunContext) => ReadonlyArray<AgentSlashCommandSummary> | Promise<ReadonlyArray<AgentSlashCommandSummary>>;
|
|
90
|
-
/**
|
|
91
|
-
* Execute a named slash command registered via `pi.registerCommand` in a
|
|
92
|
-
* plugin extension. Calls the handler in-process; the handler may dispatch
|
|
93
|
-
* UI commands (openPanel, notify) through the workspace bridge. Throws if
|
|
94
|
-
* the command is not found or the handler throws.
|
|
95
|
-
*/
|
|
96
|
-
executeSlashCommand?: (sessionId: string, name: string, args: string, ctx: RunContext) => Promise<void>;
|
|
97
|
-
}
|
|
98
|
-
interface AgentSlashCommandSummary {
|
|
99
|
-
name: string;
|
|
100
|
-
description?: string;
|
|
101
|
-
source: 'extension' | 'prompt' | 'skill';
|
|
102
|
-
/**
|
|
103
|
-
* Name of the originating plugin/package, when derivable from Pi's
|
|
104
|
-
* sourceInfo (e.g. a `.pi/extensions/<name>` runtime plugin, or an
|
|
105
|
-
* `npm:`/`git/` package). Surfaced as a tag in the slash-command picker.
|
|
106
|
-
* Absent for built-in/top-level commands with no package origin.
|
|
107
|
-
*/
|
|
108
|
-
sourcePlugin?: string;
|
|
109
|
-
}
|
|
110
|
-
interface MessageAttachment {
|
|
111
|
-
filename?: string;
|
|
112
|
-
mediaType?: string;
|
|
113
|
-
/** data: URL (base64) or remote URL */
|
|
114
|
-
url: string;
|
|
115
|
-
}
|
|
116
|
-
interface SendMessageInput {
|
|
117
|
-
sessionId: string;
|
|
118
|
-
message: string;
|
|
119
|
-
thinkingLevel?: 'off' | 'low' | 'medium' | 'high';
|
|
120
|
-
model?: {
|
|
121
|
-
provider: string;
|
|
122
|
-
id: string;
|
|
123
|
-
};
|
|
124
|
-
attachments?: MessageAttachment[];
|
|
125
|
-
}
|
|
126
|
-
interface RunContext {
|
|
127
|
-
abortSignal: AbortSignal;
|
|
128
|
-
workdir: string;
|
|
129
|
-
userId?: string;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
1
|
interface WorkspaceRuntimeContext {
|
|
133
2
|
/** Agent-visible working directory shared by file-tree and shell execution. */
|
|
134
3
|
readonly runtimeCwd: string;
|
|
@@ -330,8 +199,8 @@ interface Sandbox {
|
|
|
330
199
|
* The optional `onStdout` / `onStderr` callbacks (when implemented)
|
|
331
200
|
* stream output incrementally as bytes arrive. When omitted,
|
|
332
201
|
* implementations buffer normally and surface output via
|
|
333
|
-
* `ExecResult.stdout` / `stderr` only. See `Sandbox.exec` streaming
|
|
334
|
-
* extension
|
|
202
|
+
* `ExecResult.stdout` / `stderr` only. See the `Sandbox.exec` streaming
|
|
203
|
+
* extension added in Phase 1.0.
|
|
335
204
|
*/
|
|
336
205
|
exec(cmd: string, opts?: ExecOptions): Promise<ExecResult>;
|
|
337
206
|
/**
|
|
@@ -478,4 +347,4 @@ interface CommandNotifyPayload {
|
|
|
478
347
|
command?: string;
|
|
479
348
|
}
|
|
480
349
|
|
|
481
|
-
export { type
|
|
350
|
+
export { type CommandNotifyPayload as C, type Entry as E, type FileSearch as F, type IsolatedCodeInput as I, type PluginRestartWarning as P, type Sandbox as S, type Workspace as W, type ExecOptions as a, type ExecResult as b, type IsolatedCodeOutput as c, type SandboxCapability as d, type SandboxHandleRecord as e, type SandboxHandleStore as f, type Stat as g, WORKSPACE_AGENT_PLUGINS_RELOADED_EVENT as h, WORKSPACE_COMMAND_NOTIFY_EVENT as i, type WorkspaceRuntimeContext as j, type WorkspaceChangeEvent as k };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
type ThinkingLevel = 'off' | 'low' | 'medium' | 'high';
|
|
2
|
+
interface ChatModelSelection {
|
|
3
|
+
provider: string;
|
|
4
|
+
id: string;
|
|
5
|
+
}
|
|
6
|
+
interface ChatAttachmentPayload {
|
|
7
|
+
filename?: string;
|
|
8
|
+
mediaType?: string;
|
|
9
|
+
url: string;
|
|
10
|
+
/** Workspace-relative path when the browser upload endpoint persisted the attachment. */
|
|
11
|
+
path?: string;
|
|
12
|
+
}
|
|
13
|
+
interface ChatSubmitPayload {
|
|
14
|
+
message: string;
|
|
15
|
+
displayMessage?: string;
|
|
16
|
+
clientNonce: string;
|
|
17
|
+
model?: ChatModelSelection;
|
|
18
|
+
thinkingLevel?: ThinkingLevel;
|
|
19
|
+
attachments?: ChatAttachmentPayload[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type { ChatSubmitPayload as C, ThinkingLevel as T, ChatAttachmentPayload as a, ChatModelSelection as b };
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ErrorCode
|
|
3
|
+
} from "./chunk-XZKU7FBV.js";
|
|
4
|
+
|
|
5
|
+
// src/shared/tool-ui.ts
|
|
6
|
+
function isRecord(value) {
|
|
7
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
function isToolUiMetadata(value) {
|
|
10
|
+
if (!isRecord(value)) return false;
|
|
11
|
+
return (value.rendererId === void 0 || typeof value.rendererId === "string") && (value.displayGroup === void 0 || typeof value.displayGroup === "string") && (value.icon === void 0 || typeof value.icon === "string");
|
|
12
|
+
}
|
|
13
|
+
function sanitizeToolUiMetadata(value) {
|
|
14
|
+
if (!isToolUiMetadata(value)) return void 0;
|
|
15
|
+
const rendererId = value.rendererId?.trim();
|
|
16
|
+
const displayGroup = value.displayGroup?.trim();
|
|
17
|
+
const icon = value.icon?.trim();
|
|
18
|
+
return {
|
|
19
|
+
...rendererId ? { rendererId } : {},
|
|
20
|
+
...displayGroup ? { displayGroup } : {},
|
|
21
|
+
...icon ? { icon } : {},
|
|
22
|
+
...value.details !== void 0 ? { details: value.details } : {}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function extractToolUiMetadata(output) {
|
|
26
|
+
if (!isRecord(output)) return void 0;
|
|
27
|
+
const details = output.details;
|
|
28
|
+
if (!isRecord(details)) return void 0;
|
|
29
|
+
return sanitizeToolUiMetadata(details.ui);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/shared/chat/piChatSchemas.ts
|
|
33
|
+
import { z } from "zod";
|
|
34
|
+
var nonEmptyString = z.string().min(1);
|
|
35
|
+
var seqNumber = z.number().int().nonnegative();
|
|
36
|
+
var ShallowPayloadSchema = z.union([
|
|
37
|
+
z.string(),
|
|
38
|
+
z.number(),
|
|
39
|
+
z.boolean(),
|
|
40
|
+
z.null(),
|
|
41
|
+
z.array(z.unknown()),
|
|
42
|
+
z.record(z.unknown())
|
|
43
|
+
]);
|
|
44
|
+
function isRecord2(value) {
|
|
45
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
46
|
+
}
|
|
47
|
+
var ToolUiMetadataSchema = z.object({
|
|
48
|
+
rendererId: z.string().optional(),
|
|
49
|
+
displayGroup: z.string().optional(),
|
|
50
|
+
icon: z.string().optional(),
|
|
51
|
+
details: z.unknown().optional()
|
|
52
|
+
});
|
|
53
|
+
function sanitizeToolUiMetadata2(value) {
|
|
54
|
+
if (!isRecord2(value)) return void 0;
|
|
55
|
+
const parsed = ToolUiMetadataSchema.safeParse(value);
|
|
56
|
+
return parsed.success ? parsed.data : void 0;
|
|
57
|
+
}
|
|
58
|
+
var OptionalToolUiMetadataSchema = z.preprocess(
|
|
59
|
+
(value) => sanitizeToolUiMetadata2(value),
|
|
60
|
+
ToolUiMetadataSchema.optional()
|
|
61
|
+
);
|
|
62
|
+
var ChatErrorSchema = z.object({
|
|
63
|
+
code: ErrorCode,
|
|
64
|
+
message: nonEmptyString,
|
|
65
|
+
retryable: z.boolean().optional(),
|
|
66
|
+
details: z.unknown().optional()
|
|
67
|
+
});
|
|
68
|
+
var BoringChatPartSchema = z.discriminatedUnion("type", [
|
|
69
|
+
z.object({ type: z.literal("text"), id: z.string().optional(), text: z.string() }),
|
|
70
|
+
z.object({
|
|
71
|
+
type: z.literal("reasoning"),
|
|
72
|
+
id: nonEmptyString,
|
|
73
|
+
text: z.string(),
|
|
74
|
+
state: z.enum(["streaming", "done"]).optional()
|
|
75
|
+
}),
|
|
76
|
+
z.object({
|
|
77
|
+
type: z.literal("tool-call"),
|
|
78
|
+
id: nonEmptyString,
|
|
79
|
+
toolName: nonEmptyString,
|
|
80
|
+
input: z.unknown().optional(),
|
|
81
|
+
state: z.enum(["input-streaming", "input-available", "output-available", "output-error", "aborted"]),
|
|
82
|
+
output: z.unknown().optional(),
|
|
83
|
+
errorText: z.string().optional(),
|
|
84
|
+
ui: OptionalToolUiMetadataSchema
|
|
85
|
+
}),
|
|
86
|
+
z.object({
|
|
87
|
+
type: z.literal("file"),
|
|
88
|
+
id: z.string().optional(),
|
|
89
|
+
filename: z.string().optional(),
|
|
90
|
+
mediaType: z.string().optional(),
|
|
91
|
+
url: z.string().optional(),
|
|
92
|
+
path: z.string().optional(),
|
|
93
|
+
filesystem: z.string().optional()
|
|
94
|
+
}),
|
|
95
|
+
z.object({
|
|
96
|
+
type: z.literal("notice"),
|
|
97
|
+
id: z.string().optional(),
|
|
98
|
+
level: z.enum(["info", "warning", "error"]),
|
|
99
|
+
text: z.string()
|
|
100
|
+
})
|
|
101
|
+
]);
|
|
102
|
+
var BoringChatMessageSchema = z.object({
|
|
103
|
+
id: nonEmptyString,
|
|
104
|
+
role: z.enum(["user", "assistant", "system"]),
|
|
105
|
+
status: z.enum(["pending", "streaming", "done", "aborted", "error"]).optional(),
|
|
106
|
+
parts: z.array(BoringChatPartSchema),
|
|
107
|
+
createdAt: z.string().optional(),
|
|
108
|
+
clientNonce: z.string().optional(),
|
|
109
|
+
clientSeq: z.number().int().nonnegative().optional(),
|
|
110
|
+
piEntryId: z.string().optional(),
|
|
111
|
+
turnId: z.string().optional()
|
|
112
|
+
});
|
|
113
|
+
var QueuedUserMessageSchema = z.object({
|
|
114
|
+
id: nonEmptyString,
|
|
115
|
+
kind: z.literal("followup"),
|
|
116
|
+
clientNonce: z.string().optional(),
|
|
117
|
+
clientSeq: z.number().int().nonnegative().optional(),
|
|
118
|
+
displayText: z.string(),
|
|
119
|
+
createdAt: z.string().optional()
|
|
120
|
+
});
|
|
121
|
+
var PiChatStatusSchema = z.enum(["idle", "hydrating", "submitted", "streaming", "aborting", "error"]);
|
|
122
|
+
var PiChatSnapshotSchema = z.object({
|
|
123
|
+
protocolVersion: z.literal(1),
|
|
124
|
+
sessionId: nonEmptyString,
|
|
125
|
+
seq: seqNumber,
|
|
126
|
+
status: PiChatStatusSchema,
|
|
127
|
+
activeTurnId: z.string().optional(),
|
|
128
|
+
messages: z.array(BoringChatMessageSchema),
|
|
129
|
+
queue: z.object({ followUps: z.array(QueuedUserMessageSchema) }),
|
|
130
|
+
followUpMode: z.literal("one-at-a-time"),
|
|
131
|
+
error: ChatErrorSchema.optional()
|
|
132
|
+
});
|
|
133
|
+
var baseEvent = z.object({ seq: seqNumber });
|
|
134
|
+
var PiChatEventSchema = z.discriminatedUnion("type", [
|
|
135
|
+
baseEvent.extend({ type: z.literal("agent-start"), turnId: nonEmptyString }),
|
|
136
|
+
baseEvent.extend({ type: z.literal("agent-end"), turnId: nonEmptyString, status: z.enum(["ok", "aborted", "error"]), willRetry: z.boolean().optional() }),
|
|
137
|
+
baseEvent.extend({
|
|
138
|
+
type: z.literal("message-start"),
|
|
139
|
+
messageId: nonEmptyString,
|
|
140
|
+
role: z.enum(["user", "assistant"]),
|
|
141
|
+
clientNonce: z.string().optional(),
|
|
142
|
+
clientSeq: z.number().int().nonnegative().optional(),
|
|
143
|
+
createdAt: z.string().optional(),
|
|
144
|
+
text: z.string().optional(),
|
|
145
|
+
files: z.array(BoringChatPartSchema).optional()
|
|
146
|
+
}),
|
|
147
|
+
baseEvent.extend({
|
|
148
|
+
type: z.literal("message-delta"),
|
|
149
|
+
messageId: nonEmptyString,
|
|
150
|
+
partId: nonEmptyString,
|
|
151
|
+
kind: z.enum(["text", "reasoning"]),
|
|
152
|
+
delta: z.string()
|
|
153
|
+
}),
|
|
154
|
+
baseEvent.extend({
|
|
155
|
+
type: z.literal("message-part-end"),
|
|
156
|
+
messageId: nonEmptyString,
|
|
157
|
+
partId: nonEmptyString,
|
|
158
|
+
kind: z.enum(["text", "reasoning"]),
|
|
159
|
+
text: z.string()
|
|
160
|
+
}),
|
|
161
|
+
baseEvent.extend({ type: z.literal("message-end"), messageId: nonEmptyString, final: BoringChatMessageSchema }),
|
|
162
|
+
baseEvent.extend({
|
|
163
|
+
type: z.literal("tool-call"),
|
|
164
|
+
messageId: nonEmptyString,
|
|
165
|
+
toolCallId: nonEmptyString,
|
|
166
|
+
toolName: nonEmptyString,
|
|
167
|
+
input: ShallowPayloadSchema,
|
|
168
|
+
ui: OptionalToolUiMetadataSchema
|
|
169
|
+
}),
|
|
170
|
+
baseEvent.extend({
|
|
171
|
+
type: z.literal("tool-result"),
|
|
172
|
+
messageId: nonEmptyString,
|
|
173
|
+
toolCallId: nonEmptyString,
|
|
174
|
+
output: ShallowPayloadSchema,
|
|
175
|
+
isError: z.boolean().optional(),
|
|
176
|
+
errorText: z.string().optional(),
|
|
177
|
+
ui: OptionalToolUiMetadataSchema
|
|
178
|
+
}),
|
|
179
|
+
baseEvent.extend({ type: z.literal("queue-updated"), queue: z.object({ followUps: z.array(QueuedUserMessageSchema) }) }),
|
|
180
|
+
baseEvent.extend({
|
|
181
|
+
type: z.literal("followup-consumed"),
|
|
182
|
+
clientNonce: z.string().optional(),
|
|
183
|
+
clientSeq: z.number().int().nonnegative().optional(),
|
|
184
|
+
messageId: nonEmptyString
|
|
185
|
+
}),
|
|
186
|
+
baseEvent.extend({ type: z.literal("file-changed"), path: nonEmptyString, changeType: nonEmptyString }),
|
|
187
|
+
baseEvent.extend({ type: z.literal("ui-command"), command: ShallowPayloadSchema, displayOnly: z.literal(true) }),
|
|
188
|
+
baseEvent.extend({ type: z.literal("usage"), usage: ShallowPayloadSchema }),
|
|
189
|
+
baseEvent.extend({
|
|
190
|
+
type: z.literal("auto-retry-start"),
|
|
191
|
+
attempt: z.number().int().nonnegative(),
|
|
192
|
+
maxAttempts: z.number().int().nonnegative(),
|
|
193
|
+
delayMs: z.number().int().nonnegative(),
|
|
194
|
+
errorMessage: z.string()
|
|
195
|
+
}),
|
|
196
|
+
baseEvent.extend({
|
|
197
|
+
type: z.literal("auto-retry-end"),
|
|
198
|
+
success: z.boolean(),
|
|
199
|
+
attempt: z.number().int().nonnegative(),
|
|
200
|
+
finalError: z.string().optional()
|
|
201
|
+
}),
|
|
202
|
+
baseEvent.extend({ type: z.literal("error"), turnId: z.string().optional(), retryable: z.boolean().optional(), error: ChatErrorSchema })
|
|
203
|
+
]);
|
|
204
|
+
var PiChatHeartbeatFrameSchema = z.object({ type: z.literal("heartbeat"), now: z.string() });
|
|
205
|
+
var PiChatStreamFrameSchema = z.union([PiChatEventSchema, PiChatHeartbeatFrameSchema]);
|
|
206
|
+
var ChatModelSelectionSchema = z.object({
|
|
207
|
+
provider: nonEmptyString,
|
|
208
|
+
id: nonEmptyString
|
|
209
|
+
});
|
|
210
|
+
var ThinkingLevelSchema = z.enum(["off", "low", "medium", "high"]);
|
|
211
|
+
var ChatAttachmentPayloadSchema = z.object({
|
|
212
|
+
filename: z.string().optional(),
|
|
213
|
+
mediaType: z.string().optional(),
|
|
214
|
+
url: nonEmptyString,
|
|
215
|
+
path: z.string().optional()
|
|
216
|
+
});
|
|
217
|
+
var PromptPayloadSchema = z.object({
|
|
218
|
+
message: z.string().min(1).max(1e6),
|
|
219
|
+
displayMessage: z.string().min(1).max(1e6).optional(),
|
|
220
|
+
clientNonce: nonEmptyString.max(128),
|
|
221
|
+
model: ChatModelSelectionSchema.optional(),
|
|
222
|
+
thinkingLevel: ThinkingLevelSchema.optional(),
|
|
223
|
+
attachments: z.array(ChatAttachmentPayloadSchema).max(20).optional()
|
|
224
|
+
});
|
|
225
|
+
var FollowUpPayloadSchema = z.object({
|
|
226
|
+
message: z.string().min(1).max(1e6),
|
|
227
|
+
displayMessage: z.string().min(1).max(1e6).optional(),
|
|
228
|
+
clientNonce: nonEmptyString.max(128),
|
|
229
|
+
clientSeq: z.number().int().nonnegative()
|
|
230
|
+
});
|
|
231
|
+
var QueueClearPayloadSchema = z.preprocess(
|
|
232
|
+
(value) => value ?? {},
|
|
233
|
+
z.object({
|
|
234
|
+
clientNonce: nonEmptyString.max(128).optional(),
|
|
235
|
+
clientSeq: z.number().int().nonnegative().optional()
|
|
236
|
+
}).strict()
|
|
237
|
+
);
|
|
238
|
+
var InterruptPayloadSchema = z.object({}).strict();
|
|
239
|
+
var StopPayloadSchema = z.object({}).strict();
|
|
240
|
+
var CommandReceiptSchema = z.object({
|
|
241
|
+
accepted: z.literal(true),
|
|
242
|
+
cursor: seqNumber
|
|
243
|
+
});
|
|
244
|
+
var PromptReceiptSchema = CommandReceiptSchema.extend({
|
|
245
|
+
clientNonce: nonEmptyString,
|
|
246
|
+
duplicate: z.boolean().optional()
|
|
247
|
+
});
|
|
248
|
+
var FollowUpReceiptSchema = CommandReceiptSchema.extend({
|
|
249
|
+
clientNonce: nonEmptyString,
|
|
250
|
+
clientSeq: z.number().int().nonnegative(),
|
|
251
|
+
queued: z.literal(true),
|
|
252
|
+
duplicate: z.boolean().optional()
|
|
253
|
+
});
|
|
254
|
+
var QueueClearReceiptSchema = CommandReceiptSchema.extend({
|
|
255
|
+
cleared: z.number().int().nonnegative()
|
|
256
|
+
});
|
|
257
|
+
var StopReceiptSchema = CommandReceiptSchema.extend({
|
|
258
|
+
stopped: z.boolean(),
|
|
259
|
+
clearedQueue: z.array(QueuedUserMessageSchema)
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
export {
|
|
263
|
+
isToolUiMetadata,
|
|
264
|
+
sanitizeToolUiMetadata,
|
|
265
|
+
extractToolUiMetadata,
|
|
266
|
+
ToolUiMetadataSchema,
|
|
267
|
+
sanitizeToolUiMetadata2,
|
|
268
|
+
ChatErrorSchema,
|
|
269
|
+
BoringChatPartSchema,
|
|
270
|
+
BoringChatMessageSchema,
|
|
271
|
+
QueuedUserMessageSchema,
|
|
272
|
+
PiChatStatusSchema,
|
|
273
|
+
PiChatSnapshotSchema,
|
|
274
|
+
PiChatEventSchema,
|
|
275
|
+
PiChatHeartbeatFrameSchema,
|
|
276
|
+
PiChatStreamFrameSchema,
|
|
277
|
+
ChatModelSelectionSchema,
|
|
278
|
+
ThinkingLevelSchema,
|
|
279
|
+
ChatAttachmentPayloadSchema,
|
|
280
|
+
PromptPayloadSchema,
|
|
281
|
+
FollowUpPayloadSchema,
|
|
282
|
+
QueueClearPayloadSchema,
|
|
283
|
+
InterruptPayloadSchema,
|
|
284
|
+
StopPayloadSchema,
|
|
285
|
+
CommandReceiptSchema,
|
|
286
|
+
PromptReceiptSchema,
|
|
287
|
+
FollowUpReceiptSchema,
|
|
288
|
+
QueueClearReceiptSchema,
|
|
289
|
+
StopReceiptSchema
|
|
290
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// src/server/logging.ts
|
|
2
|
+
var SENSITIVE_KEYS = new Set([
|
|
3
|
+
"apiKey",
|
|
4
|
+
"api_key",
|
|
5
|
+
"token",
|
|
6
|
+
"secret",
|
|
7
|
+
"password",
|
|
8
|
+
"authorization",
|
|
9
|
+
"cookie",
|
|
10
|
+
"oidcToken",
|
|
11
|
+
"accessToken",
|
|
12
|
+
"refreshToken",
|
|
13
|
+
"ANTHROPIC_API_KEY",
|
|
14
|
+
"OPENAI_API_KEY",
|
|
15
|
+
"VERCEL_OIDC_TOKEN",
|
|
16
|
+
"VERCEL_TEAM_ID"
|
|
17
|
+
].map((key) => key.toLowerCase()));
|
|
18
|
+
function isSensitiveKey(key) {
|
|
19
|
+
return SENSITIVE_KEYS.has(key.toLowerCase());
|
|
20
|
+
}
|
|
21
|
+
function redactValue(key, value, seen) {
|
|
22
|
+
if (key && isSensitiveKey(key) && value != null) return "***";
|
|
23
|
+
if (value == null || typeof value !== "object") return value;
|
|
24
|
+
if (value instanceof Date) return value;
|
|
25
|
+
if (seen.has(value)) return "[Circular]";
|
|
26
|
+
seen.add(value);
|
|
27
|
+
if (Array.isArray(value)) {
|
|
28
|
+
const out2 = value.map((item) => redactValue(void 0, item, seen));
|
|
29
|
+
seen.delete(value);
|
|
30
|
+
return out2;
|
|
31
|
+
}
|
|
32
|
+
const out = {};
|
|
33
|
+
for (const [childKey, childValue] of Object.entries(value)) {
|
|
34
|
+
out[childKey] = redactValue(childKey, childValue, seen);
|
|
35
|
+
}
|
|
36
|
+
seen.delete(value);
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
function redact(fields) {
|
|
40
|
+
const out = {};
|
|
41
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
42
|
+
for (const [k, v] of Object.entries(fields)) {
|
|
43
|
+
out[k] = redactValue(k, v, seen);
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
function isVerbose() {
|
|
48
|
+
return typeof process !== "undefined" && process.env?.BORING_AGENT_VERBOSE === "1";
|
|
49
|
+
}
|
|
50
|
+
function createLogger(prefix) {
|
|
51
|
+
function emit(level, msg, fields) {
|
|
52
|
+
const entry = {
|
|
53
|
+
level,
|
|
54
|
+
prefix,
|
|
55
|
+
msg,
|
|
56
|
+
...fields ? redact(fields) : {},
|
|
57
|
+
t: (/* @__PURE__ */ new Date()).toISOString()
|
|
58
|
+
};
|
|
59
|
+
if (level === "error") {
|
|
60
|
+
console.error(JSON.stringify(entry));
|
|
61
|
+
} else if (level === "warn") {
|
|
62
|
+
console.warn(JSON.stringify(entry));
|
|
63
|
+
} else {
|
|
64
|
+
console.log(JSON.stringify(entry));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
debug(msg, fields) {
|
|
69
|
+
if (isVerbose()) emit("debug", msg, fields);
|
|
70
|
+
},
|
|
71
|
+
info(msg, fields) {
|
|
72
|
+
emit("info", msg, fields);
|
|
73
|
+
},
|
|
74
|
+
warn(msg, fields) {
|
|
75
|
+
emit("warn", msg, fields);
|
|
76
|
+
},
|
|
77
|
+
error(msg, fields) {
|
|
78
|
+
emit("error", msg, fields);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export {
|
|
84
|
+
createLogger
|
|
85
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// src/shared/telemetry.ts
|
|
2
|
+
var noopTelemetry = {
|
|
3
|
+
capture() {
|
|
4
|
+
}
|
|
5
|
+
};
|
|
6
|
+
function safeCapture(telemetry, event) {
|
|
7
|
+
try {
|
|
8
|
+
void Promise.resolve(telemetry.capture(event)).catch(() => {
|
|
9
|
+
});
|
|
10
|
+
} catch {
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
noopTelemetry,
|
|
16
|
+
safeCapture
|
|
17
|
+
};
|