@reforma/types 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +38 -0
- package/package.json +1 -1
- package/src/api/billing/contracts.ts +5 -0
- package/src/api/billing/credit-ledger-entry.ts +15 -0
- package/src/api/sandbox-clusters/create-sandbox-cluster.ts +4 -2
- package/src/api/sandbox-clusters/sandbox-cluster-provider.enum.ts +3 -1
- package/src/api/sandbox-clusters/sandbox-cluster.ts +6 -0
- package/src/api/sandbox-clusters/update-sandbox-cluster.ts +2 -0
- package/src/api/screenshot/screenshot.ts +24 -0
- package/src/sandbox/ai.ts +60 -9
- package/src/sandbox/index.ts +1 -0
- package/src/sandbox/tools/agent.ts +4 -0
- package/src/sandbox/tools/check-page.ts +29 -0
- package/src/sandbox/tools/get-background-result.ts +9 -0
- package/src/sandbox/tools/index.ts +1 -0
- package/src/sandbox/tools/read-lints.ts +1 -1
- package/src/sandbox/ui-message.ts +33 -22
- package/src/sandbox/ui-parts.ts +49 -0
- package/src/theia/bridge.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -342,6 +342,8 @@ let SandboxClusterNodeStatusEnum = /* @__PURE__ */ function(SandboxClusterNodeSt
|
|
|
342
342
|
// src/api/sandbox-clusters/sandbox-cluster-provider.enum.ts
|
|
343
343
|
let SandboxClusterProviderEnum = /* @__PURE__ */ function(SandboxClusterProviderEnum) {
|
|
344
344
|
SandboxClusterProviderEnum["rke2"] = "rke2";
|
|
345
|
+
/** Vercel Sandbox microVMs; overflow when no `rke2` cluster can take a sandbox. */
|
|
346
|
+
SandboxClusterProviderEnum["vercel"] = "vercel";
|
|
345
347
|
return SandboxClusterProviderEnum;
|
|
346
348
|
}({});
|
|
347
349
|
// src/api/sandbox-clusters/sandbox-cluster-status.enum.ts
|
|
@@ -546,6 +548,35 @@ let McpRuntimeStatus = /* @__PURE__ */ function(McpRuntimeStatus) {
|
|
|
546
548
|
McpRuntimeStatus["error"] = "error";
|
|
547
549
|
return McpRuntimeStatus;
|
|
548
550
|
}({});
|
|
551
|
+
// src/sandbox/ui-parts.ts
|
|
552
|
+
/** Whether the part is a data part (`data-*`). */
|
|
553
|
+
function isDataUIPart(part) {
|
|
554
|
+
return part.type.startsWith("data-");
|
|
555
|
+
}
|
|
556
|
+
/** Whether the part is a text part. */
|
|
557
|
+
function isTextUIPart(part) {
|
|
558
|
+
return part.type === "text";
|
|
559
|
+
}
|
|
560
|
+
/** Whether the part is a file part. */
|
|
561
|
+
function isFileUIPart(part) {
|
|
562
|
+
return part.type === "file";
|
|
563
|
+
}
|
|
564
|
+
/** Whether the part is a reasoning part. */
|
|
565
|
+
function isReasoningUIPart(part) {
|
|
566
|
+
return part.type === "reasoning";
|
|
567
|
+
}
|
|
568
|
+
/** Whether the part is a statically typed tool part (`tool-*`). */
|
|
569
|
+
function isStaticToolUIPart(part) {
|
|
570
|
+
return part.type.startsWith("tool-");
|
|
571
|
+
}
|
|
572
|
+
/** Whether the part is a static or dynamic tool part. */
|
|
573
|
+
function isToolUIPart(part) {
|
|
574
|
+
return isStaticToolUIPart(part) || part.type === "dynamic-tool";
|
|
575
|
+
}
|
|
576
|
+
/** Tool name of a static (`tool-<name>`) or dynamic tool part. */
|
|
577
|
+
function getToolName(part) {
|
|
578
|
+
return part.type === "dynamic-tool" ? part.toolName : part.type.split("-").slice(1).join("-");
|
|
579
|
+
}
|
|
549
580
|
// src/sandbox/usage-metadata.ts
|
|
550
581
|
/** Prompt-window buckets. Tool calls/results live in `conversation`, not `tools`. */
|
|
551
582
|
const CONTEXT_USAGE_BUCKET_IDS = [
|
|
@@ -613,7 +644,14 @@ exports.allocLayerCite = allocLayerCite;
|
|
|
613
644
|
exports.attachedLayerRefKey = attachedLayerRefKey;
|
|
614
645
|
exports.codeEditorStateKey = codeEditorStateKey;
|
|
615
646
|
exports.formatLayerCite = formatLayerCite;
|
|
647
|
+
exports.getToolName = getToolName;
|
|
648
|
+
exports.isDataUIPart = isDataUIPart;
|
|
649
|
+
exports.isFileUIPart = isFileUIPart;
|
|
650
|
+
exports.isReasoningUIPart = isReasoningUIPart;
|
|
616
651
|
exports.isScreenshotTool = isScreenshotTool;
|
|
652
|
+
exports.isStaticToolUIPart = isStaticToolUIPart;
|
|
653
|
+
exports.isTextUIPart = isTextUIPart;
|
|
654
|
+
exports.isToolUIPart = isToolUIPart;
|
|
617
655
|
exports.layerCiteBase = layerCiteBase;
|
|
618
656
|
exports.normalizeAttachedLayerRef = normalizeAttachedLayerRef;
|
|
619
657
|
exports.normalizeLayerSource = normalizeLayerSource;
|
package/package.json
CHANGED
|
@@ -81,6 +81,11 @@ export interface LlmUsageWebhookEvent {
|
|
|
81
81
|
id?: string;
|
|
82
82
|
litellm_call_id?: string;
|
|
83
83
|
call_type?: string;
|
|
84
|
+
/**
|
|
85
|
+
* LiteLLM session id: `x-litellm-trace-id`, or `litellm_session_id` on the
|
|
86
|
+
* Gemini pass-through, which drops `spend_logs_metadata`. Client-controlled.
|
|
87
|
+
*/
|
|
88
|
+
trace_id?: string | null;
|
|
84
89
|
status?: string;
|
|
85
90
|
/** Gateway-computed cost in USD for this request. */
|
|
86
91
|
response_cost?: number;
|
|
@@ -33,6 +33,21 @@ export interface CreditOperation {
|
|
|
33
33
|
/** Who spent the credits when this row is usage-linked; null for grants/purchases. */
|
|
34
34
|
userName: string | null;
|
|
35
35
|
userEmail: string | null;
|
|
36
|
+
/** The agent run behind a usage row; null for grants/purchases. */
|
|
37
|
+
usage: CreditUsageDetails | null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** The agent run a usage charge settled: where it ran and what the gateway saw. */
|
|
41
|
+
export interface CreditUsageDetails {
|
|
42
|
+
projectName: string | null;
|
|
43
|
+
threadTitle: string | null;
|
|
44
|
+
/** Gateway requests (model calls) in the run. */
|
|
45
|
+
requests: number;
|
|
46
|
+
inputTokens: number;
|
|
47
|
+
cacheReadTokens: number;
|
|
48
|
+
cacheWriteTokens: number;
|
|
49
|
+
outputTokens: number;
|
|
50
|
+
models: string[];
|
|
36
51
|
}
|
|
37
52
|
|
|
38
53
|
/** Paged customer ledger. */
|
|
@@ -8,8 +8,10 @@ export interface CreateSandboxCluster {
|
|
|
8
8
|
region: string;
|
|
9
9
|
apiUrl: string;
|
|
10
10
|
ingressDomain: string;
|
|
11
|
-
/** Plaintext kubeconfig YAML; encrypted at rest by the API. */
|
|
12
|
-
kubeconfig
|
|
11
|
+
/** Plaintext kubeconfig YAML; encrypted at rest by the API. Required for `rke2`. */
|
|
12
|
+
kubeconfig?: string;
|
|
13
13
|
status?: SandboxClusterStatusEnum;
|
|
14
14
|
maxSandboxes?: number;
|
|
15
|
+
/** Kubelet `Localhost` seccomp profile path for sandbox pods; omit for `Unconfined`. */
|
|
16
|
+
seccompProfile?: string | null;
|
|
15
17
|
}
|
|
@@ -12,6 +12,12 @@ export interface SandboxCluster {
|
|
|
12
12
|
version: string | null;
|
|
13
13
|
status: SandboxClusterStatusEnum;
|
|
14
14
|
maxSandboxes: number;
|
|
15
|
+
/**
|
|
16
|
+
* Path of the kubelet `Localhost` seccomp profile the cluster's nodes carry,
|
|
17
|
+
* relative to the kubelet seccomp root. `null` runs sandbox pods
|
|
18
|
+
* `Unconfined`, for clusters where no profile is installed.
|
|
19
|
+
*/
|
|
20
|
+
seccompProfile: string | null;
|
|
15
21
|
lastHealthCheckAt: Date | null;
|
|
16
22
|
healthCheckError: string | null;
|
|
17
23
|
createdByUserId: number;
|
|
@@ -40,3 +40,27 @@ export interface ScreenshotUploadResponse {
|
|
|
40
40
|
mediaType: 'image/png' | 'image/jpeg';
|
|
41
41
|
size: number;
|
|
42
42
|
}
|
|
43
|
+
|
|
44
|
+
/** Open a page without capturing it. Same URL rules and viewport defaults as a screenshot. */
|
|
45
|
+
export interface PageInspectRequest {
|
|
46
|
+
url: string;
|
|
47
|
+
headers?: Record<string, string>;
|
|
48
|
+
width?: number;
|
|
49
|
+
height?: number;
|
|
50
|
+
waitUntil?: ScreenshotWaitUntil;
|
|
51
|
+
/** Milliseconds to wait after the page loads. Default 500. Capped at 10000. */
|
|
52
|
+
delayMs?: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** What the browser reported while the page loaded and settled. Each list keeps the first 20 entries. */
|
|
56
|
+
export interface PageInspection {
|
|
57
|
+
/** HTTP status of the document. Omitted when navigation failed. */
|
|
58
|
+
status?: number;
|
|
59
|
+
/** Navigation failure, such as a timeout. */
|
|
60
|
+
error?: string;
|
|
61
|
+
/** Uncaught exceptions thrown in the page. */
|
|
62
|
+
pageErrors: string[];
|
|
63
|
+
console: { type: 'error' | 'warn'; text: string }[];
|
|
64
|
+
/** Subresources that failed or answered 4xx/5xx. */
|
|
65
|
+
failedRequests: { url: string; status?: number; error?: string }[];
|
|
66
|
+
}
|
package/src/sandbox/ai.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ThreadPlan } from './plans';
|
|
2
2
|
import type { ThreadTodo } from './todos';
|
|
3
3
|
import type { ThreadBackgroundJob } from './tools/get-background-result';
|
|
4
|
-
import type { ReformaUIMessage } from './ui-message';
|
|
4
|
+
import type { ReformaUIMessage, ReformaUserUIMessage } from './ui-message';
|
|
5
5
|
import type { ReformaContextUsage } from './usage-metadata';
|
|
6
6
|
|
|
7
7
|
export type ChatThreadSummaryDto = {
|
|
@@ -52,6 +52,63 @@ export type ChatRequestBody = {
|
|
|
52
52
|
/** Keep messages up to and including this id; drop the tail before merge. */
|
|
53
53
|
afterMessageId?: string;
|
|
54
54
|
runConfig?: ChatRunConfig;
|
|
55
|
+
/** "Send now" on a queued item: the item leaves the queue once this turn is accepted. */
|
|
56
|
+
queueItemId?: string;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/** `steer` reaches the running agent at its next step; `next-turn` starts the next run. */
|
|
60
|
+
export type ChatQueueItemMode = 'steer' | 'next-turn';
|
|
61
|
+
|
|
62
|
+
/** User input waiting on a thread run. Owned by the sandbox, in memory only. */
|
|
63
|
+
export type ChatQueueItem = {
|
|
64
|
+
/** Client-chosen id; adding the same id twice is a no-op. */
|
|
65
|
+
id: string;
|
|
66
|
+
mode: ChatQueueItemMode;
|
|
67
|
+
/** Ready-to-send user message. */
|
|
68
|
+
message: ReformaUserUIMessage;
|
|
69
|
+
runConfig?: ChatRunConfig;
|
|
70
|
+
/** Opaque composer state the client needs to reopen the item for editing. */
|
|
71
|
+
draft?: unknown;
|
|
72
|
+
/** Open in an editor. A locked steer is not taken, and a locked head holds the queue. */
|
|
73
|
+
editing: boolean;
|
|
74
|
+
createdAt: number;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/** Why the queue stopped draining. Only "Send now" on an item clears it. */
|
|
78
|
+
export type ChatQueuePause = {
|
|
79
|
+
reason: 'stopped' | 'failed';
|
|
80
|
+
error?: string;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/** Steers first, then next turns, each in send order. */
|
|
84
|
+
export type ChatQueueState = {
|
|
85
|
+
items: ChatQueueItem[];
|
|
86
|
+
paused?: ChatQueuePause;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Sandbox sync value `chat-thread:<threadId>`: thread state without messages.
|
|
91
|
+
* A missing meta field means "unchanged": the idle snapshot of a thread the sandbox has not loaded carries none.
|
|
92
|
+
*/
|
|
93
|
+
export type ChatThreadStateSnapshot = {
|
|
94
|
+
/** Set while a run is in flight, including a run parked on the user. */
|
|
95
|
+
runId?: string;
|
|
96
|
+
queue: ChatQueueState;
|
|
97
|
+
title?: string;
|
|
98
|
+
todos?: ThreadTodo[];
|
|
99
|
+
/** `null`: the thread has no plan. */
|
|
100
|
+
plan?: ThreadPlan | null;
|
|
101
|
+
/** Running background jobs. */
|
|
102
|
+
backgroundJobs?: ThreadBackgroundJob[];
|
|
103
|
+
contextUsage?: ReformaContextUsage;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/** POST `/ai/threads/:threadId/queue` */
|
|
107
|
+
export type ChatQueueAddRequest = Pick<ChatQueueItem, 'id' | 'mode' | 'message' | 'runConfig' | 'draft'>;
|
|
108
|
+
|
|
109
|
+
/** PATCH `/ai/threads/:threadId/queue/:itemId`. `index` is the position inside the item's mode section. */
|
|
110
|
+
export type ChatQueuePatchRequest = Partial<Pick<ChatQueueItem, 'mode' | 'message' | 'draft' | 'editing'>> & {
|
|
111
|
+
index?: number;
|
|
55
112
|
};
|
|
56
113
|
|
|
57
114
|
/**
|
|
@@ -69,6 +126,8 @@ export type ChatThreadDetailDto = {
|
|
|
69
126
|
* The client may attempt stream resume (`GET …/chat/:threadId/stream`) only when this is true.
|
|
70
127
|
*/
|
|
71
128
|
hasActiveStream: boolean;
|
|
129
|
+
/** In-flight run, including one parked on the user. */
|
|
130
|
+
runId?: string;
|
|
72
131
|
/** Active todo list for this thread (empty when none). */
|
|
73
132
|
todos: ThreadTodo[];
|
|
74
133
|
/** Thread plan, when one exists. */
|
|
@@ -78,11 +137,3 @@ export type ChatThreadDetailDto = {
|
|
|
78
137
|
/** Latest prompt-window breakdown; omitted before the first model step. */
|
|
79
138
|
contextUsage?: ReformaContextUsage;
|
|
80
139
|
};
|
|
81
|
-
|
|
82
|
-
/** WS `thread-status` payload when a chat run starts or ends. */
|
|
83
|
-
export type ThreadStatusEvent = {
|
|
84
|
-
threadId: string;
|
|
85
|
-
isActive: boolean;
|
|
86
|
-
/** Set on subagent children so the client can ignore list refresh. */
|
|
87
|
-
parentThreadId?: string;
|
|
88
|
-
};
|
package/src/sandbox/index.ts
CHANGED
|
@@ -7,6 +7,8 @@ export type AgentToolInput = {
|
|
|
7
7
|
message: string;
|
|
8
8
|
/** `new` starts a child. `resume` continues the latest of this name. Omit for the agent default. */
|
|
9
9
|
resume?: 'new' | 'resume';
|
|
10
|
+
/** Run as a background job: a receipt now, the report as a notification later. Root agent only. */
|
|
11
|
+
background?: boolean;
|
|
10
12
|
};
|
|
11
13
|
|
|
12
14
|
export type AgentToolOutput = {
|
|
@@ -17,6 +19,8 @@ export type AgentToolOutput = {
|
|
|
17
19
|
/** Present when the subagent profile used structured output. */
|
|
18
20
|
data?: unknown;
|
|
19
21
|
error?: string;
|
|
22
|
+
/** Set when the subagent runs in the background: the receipt's job id. The report arrives later. */
|
|
23
|
+
jobId?: string;
|
|
20
24
|
};
|
|
21
25
|
|
|
22
26
|
export type AgentUITool = {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Matches sandbox `CheckPage` tool schemas. */
|
|
2
|
+
|
|
3
|
+
export type CheckPageToolInput = {
|
|
4
|
+
/** Preview paths, such as `/` or `/reforma/stories/ui/button?variant=outline`. */
|
|
5
|
+
paths: string[];
|
|
6
|
+
delayMs?: number;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/** One visited path. Empty fields are omitted. */
|
|
10
|
+
export type CheckPageReport = {
|
|
11
|
+
path: string;
|
|
12
|
+
status?: number;
|
|
13
|
+
error?: string;
|
|
14
|
+
pageErrors?: string[];
|
|
15
|
+
console?: { type: 'error' | 'warn'; text: string }[];
|
|
16
|
+
failedRequests?: { url: string; status?: number; error?: string }[];
|
|
17
|
+
/** Dev server output written while the page loaded. */
|
|
18
|
+
serverLog?: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type CheckPageToolOutput = {
|
|
22
|
+
pages?: CheckPageReport[];
|
|
23
|
+
error?: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type CheckPageUITool = {
|
|
27
|
+
input: CheckPageToolInput;
|
|
28
|
+
output: CheckPageToolOutput;
|
|
29
|
+
};
|
|
@@ -6,12 +6,21 @@ export type BackgroundResult = {
|
|
|
6
6
|
error?: string;
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
+
/** A background subagent's job: which agent runs, in which child thread, and whether it waits on the user. */
|
|
10
|
+
export type ThreadBackgroundAgent = {
|
|
11
|
+
name: string;
|
|
12
|
+
childThreadId: string;
|
|
13
|
+
waitingForUser?: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
9
16
|
/** A background job on this thread. `output` / `error` appear when it finishes. */
|
|
10
17
|
export type ThreadBackgroundJob = {
|
|
11
18
|
id: string;
|
|
12
19
|
description: string;
|
|
13
20
|
output?: unknown;
|
|
14
21
|
error?: string;
|
|
22
|
+
/** Set when the job is a subagent; commands and other work leave it out. */
|
|
23
|
+
agent?: ThreadBackgroundAgent;
|
|
15
24
|
};
|
|
16
25
|
|
|
17
26
|
/** Matches sandbox `GetBackgroundResult` tool schemas. */
|
|
@@ -3,6 +3,7 @@ export * from './ask-user-question';
|
|
|
3
3
|
export * from './bash';
|
|
4
4
|
export * from './build';
|
|
5
5
|
export * from './capture-screenshot';
|
|
6
|
+
export * from './check-page';
|
|
6
7
|
export * from './choose-design-direction';
|
|
7
8
|
export * from './commit';
|
|
8
9
|
export * from './commit-design-read';
|
|
@@ -4,14 +4,13 @@ import type { SelectedLayerContext } from '../layers';
|
|
|
4
4
|
import type { CodeEditorState } from '../theia/bridge';
|
|
5
5
|
import type { ReformaTurnGitCommit } from './git/commit';
|
|
6
6
|
import type { VersionStatus } from './git/version';
|
|
7
|
-
import type { ThreadPlan } from './plans';
|
|
8
|
-
import type { ThreadTodo } from './todos';
|
|
9
7
|
import type {
|
|
10
8
|
AgentUITool,
|
|
11
9
|
AskUserQuestionUITool,
|
|
12
10
|
BashUITool,
|
|
13
11
|
BuildUITool,
|
|
14
12
|
CallDynamicToolUITool,
|
|
13
|
+
CheckPageUITool,
|
|
15
14
|
ChooseDesignDirectionUITool,
|
|
16
15
|
CommitDesignReadUITool,
|
|
17
16
|
CommitUITool,
|
|
@@ -47,7 +46,6 @@ import type {
|
|
|
47
46
|
RegisterLocalFontUITool,
|
|
48
47
|
RemoveFileUITool,
|
|
49
48
|
SkillUITool,
|
|
50
|
-
ThreadBackgroundJob,
|
|
51
49
|
TodoWriteUITool,
|
|
52
50
|
WaitingUITool,
|
|
53
51
|
WriteUITool,
|
|
@@ -161,6 +159,12 @@ export type ReformaChatMessageMetadata = {
|
|
|
161
159
|
/** User stopped this assistant turn. Persisted with the message. */
|
|
162
160
|
stopReason?: 'cancelled';
|
|
163
161
|
|
|
162
|
+
/**
|
|
163
|
+
* The user's ChatGPT plan or API key could not pay for this turn.
|
|
164
|
+
* The composer shows a limit plate instead of the generic error row.
|
|
165
|
+
*/
|
|
166
|
+
payerFailure?: PayerFailure;
|
|
167
|
+
|
|
164
168
|
/** Pre/Post/Stop hook context frozen for this assistant turn (server-tagged before persist). */
|
|
165
169
|
turnHookContext?: string;
|
|
166
170
|
};
|
|
@@ -181,7 +185,6 @@ export type RunCreditsSyncEntry = {
|
|
|
181
185
|
*/
|
|
182
186
|
|
|
183
187
|
export type ThreadUpdateData = {
|
|
184
|
-
title?: string;
|
|
185
188
|
/** Emitted when the server assigns a new thread id (draft first message). */
|
|
186
189
|
threadId?: string;
|
|
187
190
|
};
|
|
@@ -212,21 +215,6 @@ export type ProjectUpdateData = {
|
|
|
212
215
|
screenshotUrl?: string | null;
|
|
213
216
|
};
|
|
214
217
|
|
|
215
|
-
/** Transient UI stream payload (`data-thread-todos`); not stored on messages */
|
|
216
|
-
export type ThreadTodosUpdateData = {
|
|
217
|
-
todos: ThreadTodo[];
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
/** Transient UI stream payload (`data-thread-plan`); not stored on messages */
|
|
221
|
-
export type ThreadPlanUpdateData = {
|
|
222
|
-
plan: ThreadPlan;
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
/** Transient UI stream payload (`data-thread-background-jobs`); not stored on messages */
|
|
226
|
-
export type ThreadBackgroundJobsUpdateData = {
|
|
227
|
-
backgroundJobs: ThreadBackgroundJob[];
|
|
228
|
-
};
|
|
229
|
-
|
|
230
218
|
/**
|
|
231
219
|
* Finished background commands, stored on the assistant message (`data-background-result`).
|
|
232
220
|
* `text` is the model note frozen at delivery time.
|
|
@@ -237,6 +225,16 @@ export type BackgroundResultNoticeData = {
|
|
|
237
225
|
text: string;
|
|
238
226
|
};
|
|
239
227
|
|
|
228
|
+
/**
|
|
229
|
+
* A user message the running agent took between steps (`data-user-steer`), stored on the
|
|
230
|
+
* assistant message at that position. The model sees it as a user turn there.
|
|
231
|
+
*/
|
|
232
|
+
export type UserSteerData = {
|
|
233
|
+
message: ReformaUserUIMessage;
|
|
234
|
+
/** Unix ms when the agent took the steer. Missing on parts stored before it was recorded. */
|
|
235
|
+
takenAt?: number;
|
|
236
|
+
};
|
|
237
|
+
|
|
240
238
|
/** Transient UI stream payload (`data-version-status`); mirrors WS `version-status`. */
|
|
241
239
|
export type VersionStatusData = VersionStatus;
|
|
242
240
|
|
|
@@ -307,15 +305,26 @@ export interface ReformaChatDataContextCompactionPayload {
|
|
|
307
305
|
resumeMessageId?: string;
|
|
308
306
|
}
|
|
309
307
|
|
|
308
|
+
/**
|
|
309
|
+
* ChatGPT plan or a user API key could not pay.
|
|
310
|
+
* Streamed as transient `data-payer-failure`, and saved on the assistant message.
|
|
311
|
+
*/
|
|
312
|
+
export type PayerFailure = {
|
|
313
|
+
kind: 'limit' | 'access';
|
|
314
|
+
/** `chatgpt` is an OAuth plan. `api_key` is the user's provider key. */
|
|
315
|
+
payer: 'chatgpt' | 'api_key';
|
|
316
|
+
providerId: 'openai' | 'anthropic' | 'google';
|
|
317
|
+
/** Calendar day (`YYYY-MM-DD`) the provider named. Absent when they did not. */
|
|
318
|
+
resetAt?: string;
|
|
319
|
+
};
|
|
320
|
+
|
|
310
321
|
/** Maps `data-*` suffix keys to payload shapes for {@link ReformaUIMessage}. */
|
|
311
322
|
export type ReformaChatDataTypes = {
|
|
312
323
|
'thread-update': ThreadUpdateData;
|
|
313
324
|
'project-update': ProjectUpdateData;
|
|
314
325
|
'version-status': VersionStatusData;
|
|
315
|
-
'thread-todos': ThreadTodosUpdateData;
|
|
316
|
-
'thread-plan': ThreadPlanUpdateData;
|
|
317
|
-
'thread-background-jobs': ThreadBackgroundJobsUpdateData;
|
|
318
326
|
'background-result': BackgroundResultNoticeData;
|
|
327
|
+
'user-steer': UserSteerData;
|
|
319
328
|
'tool-metadata': ToolMetadataUpdateData;
|
|
320
329
|
'client-tool': ClientToolRequestData;
|
|
321
330
|
'tool-execution-progress': ReformaChatDataToolExecutionProgressPayload;
|
|
@@ -323,6 +332,7 @@ export type ReformaChatDataTypes = {
|
|
|
323
332
|
'redacted-reasoning': ReformaChatDataRedactedReasoningPayload;
|
|
324
333
|
'context-compaction': ReformaChatDataContextCompactionPayload;
|
|
325
334
|
'subagent-status': SubagentStatusUpdateData;
|
|
335
|
+
'payer-failure': PayerFailure;
|
|
326
336
|
};
|
|
327
337
|
|
|
328
338
|
// --- Tool UI parts (third `UIMessage` generic) ---
|
|
@@ -359,6 +369,7 @@ export type ReformaChatUITools = {
|
|
|
359
369
|
MoveFile: MoveFileUITool;
|
|
360
370
|
Navigate: NavigateUITool;
|
|
361
371
|
PageScreenshot: PageScreenshotUITool;
|
|
372
|
+
CheckPage: CheckPageUITool;
|
|
362
373
|
ReadPlan: ReadPlanUITool;
|
|
363
374
|
ReadTodo: ReadTodoUITool;
|
|
364
375
|
TodoWrite: TodoWriteUITool;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DataUIPart,
|
|
3
|
+
DynamicToolUIPart,
|
|
4
|
+
FileUIPart,
|
|
5
|
+
ReasoningUIPart,
|
|
6
|
+
TextUIPart,
|
|
7
|
+
ToolUIPart,
|
|
8
|
+
UIDataTypes,
|
|
9
|
+
UIMessagePart,
|
|
10
|
+
UITools,
|
|
11
|
+
} from 'ai' with { 'resolution-mode': 'import' };
|
|
12
|
+
|
|
13
|
+
// Same contracts as the `ai` part guards. Importing them from `ai` evaluates the whole
|
|
14
|
+
// SDK and its zod schemas, which chat UI outside the editor does not need.
|
|
15
|
+
|
|
16
|
+
/** Whether the part is a data part (`data-*`). */
|
|
17
|
+
export function isDataUIPart<DATA_TYPES extends UIDataTypes>(part: UIMessagePart<DATA_TYPES, UITools>): part is DataUIPart<DATA_TYPES> {
|
|
18
|
+
return part.type.startsWith('data-');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Whether the part is a text part. */
|
|
22
|
+
export function isTextUIPart(part: UIMessagePart<UIDataTypes, UITools>): part is TextUIPart {
|
|
23
|
+
return part.type === 'text';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Whether the part is a file part. */
|
|
27
|
+
export function isFileUIPart(part: UIMessagePart<UIDataTypes, UITools>): part is FileUIPart {
|
|
28
|
+
return part.type === 'file';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Whether the part is a reasoning part. */
|
|
32
|
+
export function isReasoningUIPart(part: UIMessagePart<UIDataTypes, UITools>): part is ReasoningUIPart {
|
|
33
|
+
return part.type === 'reasoning';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Whether the part is a statically typed tool part (`tool-*`). */
|
|
37
|
+
export function isStaticToolUIPart<TOOLS extends UITools>(part: UIMessagePart<UIDataTypes, TOOLS>): part is ToolUIPart<TOOLS> {
|
|
38
|
+
return part.type.startsWith('tool-');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Whether the part is a static or dynamic tool part. */
|
|
42
|
+
export function isToolUIPart<TOOLS extends UITools>(part: UIMessagePart<UIDataTypes, TOOLS>): part is ToolUIPart<TOOLS> | DynamicToolUIPart {
|
|
43
|
+
return isStaticToolUIPart(part) || part.type === 'dynamic-tool';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Tool name of a static (`tool-<name>`) or dynamic tool part. */
|
|
47
|
+
export function getToolName(part: ToolUIPart<UITools> | DynamicToolUIPart): string {
|
|
48
|
+
return part.type === 'dynamic-tool' ? part.toolName : part.type.split('-').slice(1).join('-');
|
|
49
|
+
}
|
package/src/theia/bridge.ts
CHANGED
|
@@ -34,7 +34,7 @@ export type TheiaHostMethods = {
|
|
|
34
34
|
onAttachFiles: (files: readonly CodeEditorState[]) => void;
|
|
35
35
|
/** Switch the parent shell/canvas mode, or activate commenting, while Theia holds keyboard focus. */
|
|
36
36
|
setViewMode: (mode: TheiaHostViewMode) => void;
|
|
37
|
-
/**
|
|
37
|
+
/** Cycle Editor → Design → Code. Preview counts as Editor. */
|
|
38
38
|
toggleCodeShell: () => void;
|
|
39
39
|
};
|
|
40
40
|
|