@nyte-ai/plugin 0.0.0-stage → 0.0.19
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/LICENSE +21 -0
- package/THIRD-PARTY-NOTICES.md +866 -0
- package/dist/chunks/billing-0y7dfkp2.js +146 -0
- package/dist/chunks/billing-2v3g7rd9.js +190 -0
- package/dist/chunks/billing-3j77ss7y.js +86 -0
- package/dist/chunks/billing-3scqmkzb.js +559 -0
- package/dist/chunks/billing-4vz9pxyx.js +22 -0
- package/dist/chunks/billing-6z2kgtyt.js +51 -0
- package/dist/chunks/billing-8rjk35gr.js +444 -0
- package/dist/chunks/billing-9nn3yp18.js +176 -0
- package/dist/chunks/billing-9qc0eqh4.js +174 -0
- package/dist/chunks/billing-a9vqn66p.js +351 -0
- package/dist/chunks/billing-bv5zr32b.js +369 -0
- package/dist/chunks/billing-cy1rg619.js +302 -0
- package/dist/chunks/billing-ejx2hv52.js +323 -0
- package/dist/chunks/billing-h13r0byk.js +80 -0
- package/dist/chunks/billing-hg64tqf1.js +97 -0
- package/dist/chunks/billing-j643d12p.js +197 -0
- package/dist/chunks/billing-kn3d30b4.js +276 -0
- package/dist/chunks/billing-mvc33pv6.js +36 -0
- package/dist/chunks/billing-s4rrspsk.js +7 -0
- package/dist/chunks/billing-svrhh5a5.js +307 -0
- package/dist/chunks/billing-sxc70w72.js +161 -0
- package/dist/chunks/billing-t1qrxe16.js +41 -0
- package/dist/chunks/billing-tm34gm2p.js +528 -0
- package/dist/chunks/billing-tzr3cebf.js +20 -0
- package/dist/chunks/billing-v3hg5rc7.js +373 -0
- package/dist/chunks/billing-wmcbg6fw.js +52 -0
- package/dist/chunks/billing-ye3wk5r3.js +205 -0
- package/dist/chunks/billing-zfpm2rt0.js +29 -0
- package/dist/examples/claude-code/LICENSE +21 -0
- package/dist/examples/claude-code/billing.d.ts +7 -0
- package/dist/examples/claude-code/billing.js +11 -0
- package/dist/examples/claude-code/claude-cli.d.ts +35 -0
- package/dist/examples/claude-code/claude-cli.js +15 -0
- package/dist/examples/claude-code/env.d.ts +1 -0
- package/dist/examples/claude-code/env.js +6 -0
- package/dist/examples/claude-code/index.d.ts +24 -0
- package/dist/examples/claude-code/index.js +149 -0
- package/dist/examples/claude-code/inert-mcp.d.ts +1 -0
- package/dist/examples/claude-code/inert-mcp.js +6 -0
- package/dist/examples/claude-code/model-catalog.d.ts +27 -0
- package/dist/examples/claude-code/model-catalog.js +12 -0
- package/dist/examples/claude-code/process.d.ts +22 -0
- package/dist/examples/claude-code/process.js +25 -0
- package/dist/examples/claude-code/replay.d.ts +4 -0
- package/dist/examples/claude-code/replay.js +11 -0
- package/dist/examples/claude-code/stream.d.ts +3 -0
- package/dist/examples/claude-code/stream.js +16 -0
- package/dist/examples/claude-code/transcript.d.ts +83 -0
- package/dist/examples/claude-code/transcript.js +23 -0
- package/dist/examples/claude-code/turn-relay.d.ts +48 -0
- package/dist/examples/claude-code/turn-relay.js +9 -0
- package/dist/examples/claude-code/wire.d.ts +372 -0
- package/dist/examples/claude-code/wire.js +18 -0
- package/dist/src/acp/connection.d.ts +24 -0
- package/dist/src/acp/connection.js +8 -0
- package/dist/src/acp/index.d.ts +54 -0
- package/dist/src/acp/index.js +1005 -0
- package/dist/src/acp/registry.d.ts +18 -0
- package/dist/src/acp/registry.js +9 -0
- package/dist/src/acp/thread.d.ts +46 -0
- package/dist/src/acp/thread.js +7 -0
- package/dist/src/acp/transcript.d.ts +8 -0
- package/dist/src/acp/transcript.js +11 -0
- package/dist/src/acp/translate.d.ts +33 -0
- package/dist/src/acp/translate.js +20 -0
- package/dist/src/approvals/approvals.d.ts +189 -0
- package/dist/src/approvals/approvals.js +143 -0
- package/dist/src/approvals/schema.d.ts +169 -0
- package/dist/src/approvals/schema.js +18 -0
- package/dist/src/bash-description.d.ts +30 -0
- package/dist/src/bash-description.js +18 -0
- package/dist/src/browser-tools.d.ts +25 -0
- package/dist/src/browser-tools.js +246 -0
- package/dist/src/canvas/canvas-compile.d.ts +48 -0
- package/dist/src/canvas/canvas-compile.js +8 -0
- package/dist/src/canvas/canvas-libraries.d.ts +32 -0
- package/dist/src/canvas/canvas-libraries.js +6 -0
- package/dist/src/canvas/canvas-preview.d.ts +107 -0
- package/dist/src/canvas/canvas-preview.js +12 -0
- package/dist/src/canvas/canvas-protocol.d.ts +184 -0
- package/dist/src/canvas/canvas-protocol.js +75 -0
- package/dist/src/canvas/canvas.d.ts +50 -0
- package/dist/src/canvas/canvas.js +221 -0
- package/dist/src/canvas/schema.d.ts +47 -0
- package/dist/src/canvas/schema.js +8 -0
- package/dist/src/claude-code-sdk/index.d.ts +35 -0
- package/dist/src/claude-code-sdk/index.js +379 -0
- package/dist/src/claude-code-sdk/session.d.ts +50 -0
- package/dist/src/claude-code-sdk/session.js +7 -0
- package/dist/src/claude-code-sdk/transcript.d.ts +19 -0
- package/dist/src/claude-code-sdk/transcript.js +15 -0
- package/dist/src/claude-code-sdk/translate.d.ts +18 -0
- package/dist/src/claude-code-sdk/translate.js +20 -0
- package/dist/src/client/mount.d.ts +44 -0
- package/dist/src/client/mount.js +252 -0
- package/dist/src/client/notifications.d.ts +36 -0
- package/dist/src/client/notifications.js +24 -0
- package/dist/src/client/presentation.d.ts +362 -0
- package/dist/src/client/presentation.js +391 -0
- package/dist/src/client/transcript-tui.d.ts +23 -0
- package/dist/src/client/transcript-tui.js +20 -0
- package/dist/src/client/transcript.d.ts +23 -0
- package/dist/src/client/transcript.js +51 -0
- package/dist/src/client.d.ts +53 -0
- package/dist/src/client.js +22 -0
- package/dist/src/codemode-runtime.d.ts +11 -0
- package/dist/src/codemode-runtime.js +10 -0
- package/dist/src/codemode-worker.d.ts +1 -0
- package/dist/src/codemode-worker.js +2 -0
- package/dist/src/codemode.d.ts +21 -0
- package/dist/src/codemode.js +170 -0
- package/dist/src/core.d.ts +43 -0
- package/dist/src/core.js +11 -0
- package/dist/src/find-on-path.d.ts +4 -0
- package/dist/src/find-on-path.js +8 -0
- package/dist/src/openai-astra-context.d.ts +23 -0
- package/dist/src/openai-astra-context.js +14 -0
- package/dist/src/openai-compaction.d.ts +15 -0
- package/dist/src/openai-compaction.js +55 -0
- package/dist/src/question/client/questions-tui.d.ts +9 -0
- package/dist/src/question/client/questions-tui.js +19 -0
- package/dist/src/question/client/questions.d.ts +9 -0
- package/dist/src/question/client/questions.js +160 -0
- package/dist/src/question/question.d.ts +63 -0
- package/dist/src/question/question.js +9 -0
- package/dist/src/question/schema.d.ts +101 -0
- package/dist/src/question/schema.js +14 -0
- package/dist/src/rename.d.ts +79 -0
- package/dist/src/rename.js +91 -0
- package/dist/src/telemetry.d.ts +36 -0
- package/dist/src/telemetry.js +84 -0
- package/dist/src/web-search.d.ts +78 -0
- package/dist/src/web-search.js +219 -0
- package/package.json +190 -3
- package/README.md +0 -3
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
import {
|
|
2
|
+
findOnPath2
|
|
3
|
+
} from "../../chunks/billing-4vz9pxyx.js";
|
|
4
|
+
import {
|
|
5
|
+
answerInput2
|
|
6
|
+
} from "../../chunks/billing-6z2kgtyt.js";
|
|
7
|
+
import {
|
|
8
|
+
question2
|
|
9
|
+
} from "../../chunks/billing-3j77ss7y.js";
|
|
10
|
+
import {
|
|
11
|
+
CLAUDE_CODE_PROVIDER2,
|
|
12
|
+
MIRROR_TOOL3,
|
|
13
|
+
BACKGROUND_TOOL2,
|
|
14
|
+
emptyMessage3,
|
|
15
|
+
Translator3
|
|
16
|
+
} from "../../chunks/billing-ye3wk5r3.js";
|
|
17
|
+
import {
|
|
18
|
+
ClaudeCodeSession2
|
|
19
|
+
} from "../../chunks/billing-tm34gm2p.js";
|
|
20
|
+
import {
|
|
21
|
+
mirrorArguments3,
|
|
22
|
+
userBlocks3,
|
|
23
|
+
messageKey3,
|
|
24
|
+
sessionEntries2,
|
|
25
|
+
flatPrompt2
|
|
26
|
+
} from "../../chunks/billing-2v3g7rd9.js";
|
|
27
|
+
|
|
28
|
+
// src/claude-code-sdk/index.ts
|
|
29
|
+
import { randomUUID } from "node:crypto";
|
|
30
|
+
import { access } from "node:fs/promises";
|
|
31
|
+
import { homedir } from "node:os";
|
|
32
|
+
import { join } from "node:path";
|
|
33
|
+
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
34
|
+
import {
|
|
35
|
+
acquireSessionResources,
|
|
36
|
+
anthropicProvider,
|
|
37
|
+
clampThinkingLevel,
|
|
38
|
+
createAssistantMessageEventStream,
|
|
39
|
+
getCurrentTools,
|
|
40
|
+
getCurrentSystemPrompt,
|
|
41
|
+
lazyStream,
|
|
42
|
+
registerSessionResourceCleanup
|
|
43
|
+
} from "@nyte-ai/ai";
|
|
44
|
+
import { processEnvironment } from "@nyte-ai/core";
|
|
45
|
+
import { standard } from "@nyte-ai/schema";
|
|
46
|
+
import { Type } from "typebox";
|
|
47
|
+
import { Value } from "typebox/value";
|
|
48
|
+
var API = "claude-agent-sdk";
|
|
49
|
+
var EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
50
|
+
var NOT_RUNNING = "Claude Code is no longer running this turn. Send a message to continue.";
|
|
51
|
+
var CLAUDE_CODE_HAS_ITS_OWN = new Set([
|
|
52
|
+
"read",
|
|
53
|
+
"write",
|
|
54
|
+
"edit",
|
|
55
|
+
"list",
|
|
56
|
+
"bash",
|
|
57
|
+
"web_search",
|
|
58
|
+
"question"
|
|
59
|
+
]);
|
|
60
|
+
var ultracodeSetting = {
|
|
61
|
+
id: "claude_code.ultracode",
|
|
62
|
+
label: "Claude Code ultracode",
|
|
63
|
+
schema: standard(Type.Boolean()),
|
|
64
|
+
choices: [
|
|
65
|
+
{ value: false, label: "Off" },
|
|
66
|
+
{ value: true, label: "On", badge: "ultracode" }
|
|
67
|
+
],
|
|
68
|
+
default: false,
|
|
69
|
+
scope: "session"
|
|
70
|
+
};
|
|
71
|
+
function effortFor(model, reasoning) {
|
|
72
|
+
if (reasoning === undefined)
|
|
73
|
+
return;
|
|
74
|
+
const level = clampThinkingLevel(model, reasoning);
|
|
75
|
+
if (level === "off")
|
|
76
|
+
return;
|
|
77
|
+
const mapped = model.thinkingLevelMap?.[level] ?? level;
|
|
78
|
+
return EFFORTS.find((effort) => effort === mapped) ?? (level === "minimal" ? "low" : undefined);
|
|
79
|
+
}
|
|
80
|
+
async function findClaudeCode() {
|
|
81
|
+
await processEnvironment();
|
|
82
|
+
return await findOnPath2("claude", process.env.PATH ?? "");
|
|
83
|
+
}
|
|
84
|
+
async function claudeCodeConfigured() {
|
|
85
|
+
if (await findClaudeCode() === undefined)
|
|
86
|
+
return false;
|
|
87
|
+
try {
|
|
88
|
+
await access(process.env.CLAUDE_CONFIG_DIR ?? join(homedir(), ".claude"));
|
|
89
|
+
return true;
|
|
90
|
+
} catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function answerOnce(start, model, context, options) {
|
|
95
|
+
const stream = createAssistantMessageEventStream();
|
|
96
|
+
const output = emptyMessage3(model);
|
|
97
|
+
const translator = new Translator3(model, output, stream);
|
|
98
|
+
const controller = new AbortController;
|
|
99
|
+
const abort = () => controller.abort();
|
|
100
|
+
options?.signal?.addEventListener("abort", abort, { once: true });
|
|
101
|
+
(async () => {
|
|
102
|
+
try {
|
|
103
|
+
stream.push({ type: "start", partial: output });
|
|
104
|
+
const claude = await findClaudeCode();
|
|
105
|
+
for await (const message of start({
|
|
106
|
+
prompt: flatPrompt2(context.messages),
|
|
107
|
+
options: {
|
|
108
|
+
model: model.id,
|
|
109
|
+
abortController: controller,
|
|
110
|
+
systemPrompt: getCurrentSystemPrompt(context.messages),
|
|
111
|
+
tools: [],
|
|
112
|
+
settingSources: [],
|
|
113
|
+
strictMcpConfig: true,
|
|
114
|
+
maxTurns: 1,
|
|
115
|
+
persistSession: false,
|
|
116
|
+
includePartialMessages: true,
|
|
117
|
+
thinking: { type: "disabled" },
|
|
118
|
+
env: { ...process.env, ...options?.env },
|
|
119
|
+
pathToClaudeCodeExecutable: claude
|
|
120
|
+
}
|
|
121
|
+
})) {
|
|
122
|
+
if (message.type === "stream_event" && message.parent_tool_use_id === null)
|
|
123
|
+
translator.apply(message.event);
|
|
124
|
+
else if (message.type === "result" && message.subtype !== "success")
|
|
125
|
+
throw new Error(message.errors.join(`
|
|
126
|
+
`) || `Claude Code failed: ${message.subtype}`);
|
|
127
|
+
}
|
|
128
|
+
if (output.stopReason === "pending" || output.stopReason === "aborted")
|
|
129
|
+
throw new Error("Claude Code ended without a response.");
|
|
130
|
+
if (output.stopReason === "error")
|
|
131
|
+
throw new Error(output.errorMessage ?? "Claude Code failed.");
|
|
132
|
+
stream.push({ type: "done", reason: output.stopReason, message: output });
|
|
133
|
+
} catch (error) {
|
|
134
|
+
output.stopReason = options?.signal?.aborted === true ? "aborted" : "error";
|
|
135
|
+
output.errorMessage = error instanceof Error ? error.message : String(error);
|
|
136
|
+
stream.push({ type: "error", reason: output.stopReason, error: output });
|
|
137
|
+
} finally {
|
|
138
|
+
options?.signal?.removeEventListener("abort", abort);
|
|
139
|
+
stream.end();
|
|
140
|
+
}
|
|
141
|
+
})();
|
|
142
|
+
return stream;
|
|
143
|
+
}
|
|
144
|
+
var nonEmpty = Type.String({ minLength: 1 });
|
|
145
|
+
function field(input, key) {
|
|
146
|
+
const value = input[key];
|
|
147
|
+
return Value.Check(nonEmpty, value) ? value : undefined;
|
|
148
|
+
}
|
|
149
|
+
var claudeQuestions = Type.Array(Type.Object({
|
|
150
|
+
question: Type.String(),
|
|
151
|
+
header: Type.String(),
|
|
152
|
+
options: Type.Array(Type.Object({ label: Type.String(), description: Type.String() })),
|
|
153
|
+
multiSelect: Type.Optional(Type.Boolean())
|
|
154
|
+
}));
|
|
155
|
+
async function askUser(session, id, input, invocation) {
|
|
156
|
+
if (!Value.Check(claudeQuestions, input.questions))
|
|
157
|
+
return { answers: null, part: null };
|
|
158
|
+
const questions = input.questions.map((item) => ({
|
|
159
|
+
question: item.question,
|
|
160
|
+
header: item.header.slice(0, 30),
|
|
161
|
+
options: item.options.map(({ label, description }) => ({ label, description })),
|
|
162
|
+
multiple: item.multiSelect === true
|
|
163
|
+
}));
|
|
164
|
+
const part = await invocation.session.parts.create(question2, {
|
|
165
|
+
state: { questions, answers: null },
|
|
166
|
+
placement: { kind: "modal" }
|
|
167
|
+
});
|
|
168
|
+
const outcome = await invocation.wait({ kind: "part", part: part.id });
|
|
169
|
+
const checked = outcome.kind === "part" && outcome.answer?.action === "answer" ? await answerInput2["~standard"].validate(outcome.answer.input) : undefined;
|
|
170
|
+
if (checked === undefined || checked.issues !== undefined)
|
|
171
|
+
return { answers: null, part: part.id };
|
|
172
|
+
const answers = questions.flatMap((item, index) => {
|
|
173
|
+
const chosen = checked.value.answers[index]?.join(", ") ?? "";
|
|
174
|
+
return chosen === "" ? [] : [[item.question, chosen]];
|
|
175
|
+
});
|
|
176
|
+
return { answers: answers.length === 0 ? null : Object.fromEntries(answers), part: part.id };
|
|
177
|
+
}
|
|
178
|
+
function classifyClaudeTool(name, input) {
|
|
179
|
+
const path = field(input, "file_path") ?? field(input, "notebook_path");
|
|
180
|
+
const command = field(input, "command");
|
|
181
|
+
const description = field(input, "description");
|
|
182
|
+
switch (name) {
|
|
183
|
+
case "Read":
|
|
184
|
+
return path === undefined ? { kind: "custom", label: name } : { kind: "read", path };
|
|
185
|
+
case "Edit":
|
|
186
|
+
case "MultiEdit":
|
|
187
|
+
case "Write":
|
|
188
|
+
case "NotebookEdit":
|
|
189
|
+
return path === undefined ? { kind: "custom", label: name } : { kind: "edit", path };
|
|
190
|
+
case "Bash":
|
|
191
|
+
if (command === undefined)
|
|
192
|
+
return { kind: "custom", label: name };
|
|
193
|
+
return description === undefined ? { kind: "shell", command } : { kind: "shell", command, description };
|
|
194
|
+
case "Agent":
|
|
195
|
+
case "Task":
|
|
196
|
+
return {
|
|
197
|
+
kind: "delegate",
|
|
198
|
+
child: null,
|
|
199
|
+
role: "task",
|
|
200
|
+
title: description ?? null
|
|
201
|
+
};
|
|
202
|
+
case "Skill":
|
|
203
|
+
return { kind: "custom", label: `Skill ${field(input, "skill") ?? ""}`.trim() };
|
|
204
|
+
case "Workflow":
|
|
205
|
+
return {
|
|
206
|
+
kind: "custom",
|
|
207
|
+
label: `Workflow ${field(input, "title") ?? field(input, "name") ?? ""}`.trim()
|
|
208
|
+
};
|
|
209
|
+
case "AskUserQuestion": {
|
|
210
|
+
const headers = Value.Check(claudeQuestions, input.questions) ? input.questions.map((item) => item.header).join(", ") : "";
|
|
211
|
+
return { kind: "custom", label: `Asking ${headers}`.trim() };
|
|
212
|
+
}
|
|
213
|
+
case BACKGROUND_TOOL2:
|
|
214
|
+
return { kind: "custom", label: "Waiting for background work" };
|
|
215
|
+
default: {
|
|
216
|
+
const subject = field(input, "pattern") ?? field(input, "url") ?? field(input, "query");
|
|
217
|
+
return { kind: "custom", label: subject === undefined ? name : `${name} ${subject}` };
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function mirrorTool(sessions) {
|
|
222
|
+
return {
|
|
223
|
+
name: MIRROR_TOOL3,
|
|
224
|
+
description: "A tool Claude Code ran. Claude Code reports the result; Nyte records it.",
|
|
225
|
+
parameters: standard(mirrorArguments3),
|
|
226
|
+
exposure: "hidden",
|
|
227
|
+
approval: "runtime",
|
|
228
|
+
replay: "safe",
|
|
229
|
+
class: ({ name, input }) => classifyClaudeTool(name, input),
|
|
230
|
+
async execute({ id, name, input }, invocation) {
|
|
231
|
+
const session = sessions.get(invocation.session.id);
|
|
232
|
+
if (session === undefined || session.closed)
|
|
233
|
+
throw new Error(NOT_RUNNING);
|
|
234
|
+
if (name === BACKGROUND_TOOL2)
|
|
235
|
+
return { content: [{ kind: "text", text: await session.background(invocation.signal) }] };
|
|
236
|
+
session.recording(id);
|
|
237
|
+
let parts = [];
|
|
238
|
+
if (name === "AskUserQuestion") {
|
|
239
|
+
const asked = await askUser(session, id, input, invocation);
|
|
240
|
+
session.answer(id, asked.answers);
|
|
241
|
+
parts = asked.part === null ? [] : [asked.part];
|
|
242
|
+
}
|
|
243
|
+
const output = await session.result(id, invocation.signal);
|
|
244
|
+
if (output.isError)
|
|
245
|
+
throw new Error(output.text);
|
|
246
|
+
return { content: [{ kind: "text", text: output.text }], parts };
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function claudeCodeSdk(start = query) {
|
|
251
|
+
const catalog = anthropicProvider();
|
|
252
|
+
const sessions = new Map;
|
|
253
|
+
const bindings = new Map;
|
|
254
|
+
registerSessionResourceCleanup((id) => {
|
|
255
|
+
for (const [key, session] of sessions) {
|
|
256
|
+
if (id !== undefined && key !== id)
|
|
257
|
+
continue;
|
|
258
|
+
sessions.delete(key);
|
|
259
|
+
session.close();
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
async function respond(model, context, options) {
|
|
263
|
+
const id = options?.sessionId;
|
|
264
|
+
const binding = id === undefined ? undefined : bindings.get(id);
|
|
265
|
+
if (id === undefined || binding === undefined)
|
|
266
|
+
throw new Error("Claude Code answers inside a Nyte session with the claude-code-sdk plugin.");
|
|
267
|
+
const effort = effortFor(model, options?.reasoning);
|
|
268
|
+
const ultracode = await binding.ultracode();
|
|
269
|
+
const key = JSON.stringify([model.id, binding.cwd, options?.reasoning !== undefined]);
|
|
270
|
+
const messages = context.messages.filter((message) => message.role !== "system");
|
|
271
|
+
const keys = messages.map(messageKey3);
|
|
272
|
+
const tools = getCurrentTools(context.messages).filter((tool) => !CLAUDE_CODE_HAS_ITS_OWN.has(tool.name));
|
|
273
|
+
let session = sessions.get(id);
|
|
274
|
+
const continues = session !== undefined && !session.closed && !session.asking && session.key === key && session.known.length < keys.length && session.known.every((known, index) => keys[index] === known);
|
|
275
|
+
const prompt = messages.slice(messages.findLastIndex((message) => message.role !== "user") + 1);
|
|
276
|
+
if (!continues) {
|
|
277
|
+
session?.close();
|
|
278
|
+
if (prompt.length === 0)
|
|
279
|
+
throw new Error(NOT_RUNNING);
|
|
280
|
+
const claude = await findClaudeCode();
|
|
281
|
+
const claudeSession = randomUUID();
|
|
282
|
+
session = new ClaudeCodeSession2({
|
|
283
|
+
key,
|
|
284
|
+
model: model.id,
|
|
285
|
+
cwd: binding.cwd,
|
|
286
|
+
thinking: options?.reasoning !== undefined,
|
|
287
|
+
effort,
|
|
288
|
+
ultracode,
|
|
289
|
+
env: options?.env,
|
|
290
|
+
session: claudeSession,
|
|
291
|
+
history: sessionEntries2(messages.slice(0, -prompt.length), {
|
|
292
|
+
session: claudeSession,
|
|
293
|
+
model: model.id,
|
|
294
|
+
cwd: binding.cwd
|
|
295
|
+
}),
|
|
296
|
+
tools,
|
|
297
|
+
query: start,
|
|
298
|
+
claude,
|
|
299
|
+
approve: binding.approve
|
|
300
|
+
});
|
|
301
|
+
sessions.set(id, session);
|
|
302
|
+
}
|
|
303
|
+
if (session === undefined)
|
|
304
|
+
throw new Error(NOT_RUNNING);
|
|
305
|
+
session.expose(tools);
|
|
306
|
+
session.deliver(messages);
|
|
307
|
+
await session.configure(effort, ultracode);
|
|
308
|
+
if (prompt.length > 0)
|
|
309
|
+
session.send(prompt.flatMap((message) => message.role === "user" ? userBlocks3(message) : []));
|
|
310
|
+
const live = session;
|
|
311
|
+
const stream = live.respond(model, options?.signal);
|
|
312
|
+
stream.result().then((message) => {
|
|
313
|
+
live.known = message.stopReason === "error" || message.stopReason === "aborted" ? [] : [...keys, messageKey3(message)];
|
|
314
|
+
});
|
|
315
|
+
return stream;
|
|
316
|
+
}
|
|
317
|
+
const stream = (model, context, options) => getCurrentTools(context.messages).length === 0 ? answerOnce(start, model, context, options) : lazyStream(model, () => respond(model, context, options));
|
|
318
|
+
const provider = {
|
|
319
|
+
id: CLAUDE_CODE_PROVIDER2,
|
|
320
|
+
name: "Claude Code",
|
|
321
|
+
baseUrl: "process://claude-code",
|
|
322
|
+
capabilities: { steer: true },
|
|
323
|
+
auth: {
|
|
324
|
+
apiKey: {
|
|
325
|
+
name: "Claude Code login",
|
|
326
|
+
resolve: async ({ signal }) => {
|
|
327
|
+
signal.throwIfAborted();
|
|
328
|
+
return await claudeCodeConfigured() ? { auth: {}, source: "Claude Code login" } : undefined;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
getModels: () => catalog.getModels().map(({ compat: _compat, ...model }) => ({
|
|
333
|
+
...model,
|
|
334
|
+
provider: CLAUDE_CODE_PROVIDER2,
|
|
335
|
+
api: API,
|
|
336
|
+
baseUrl: "process://claude-code"
|
|
337
|
+
})),
|
|
338
|
+
refreshModels: async (context) => {
|
|
339
|
+
await catalog.refreshModels?.(context);
|
|
340
|
+
},
|
|
341
|
+
stream: (model, context, options) => stream(model, context, {
|
|
342
|
+
signal: options?.signal,
|
|
343
|
+
sessionId: options?.sessionId,
|
|
344
|
+
env: options?.env
|
|
345
|
+
}),
|
|
346
|
+
streamSimple: stream
|
|
347
|
+
};
|
|
348
|
+
const plugin = {
|
|
349
|
+
id: "claude-code-sdk",
|
|
350
|
+
contribute: { tools: [mirrorTool(sessions)], settings: [ultracodeSetting] },
|
|
351
|
+
activate(api) {
|
|
352
|
+
const id = api.session.id;
|
|
353
|
+
const binding = {
|
|
354
|
+
cwd: api.env.cwd,
|
|
355
|
+
ultracode: async () => await api.contribute.settings.value(ultracodeSetting.id) === true,
|
|
356
|
+
approve: async (name, input, signal) => {
|
|
357
|
+
const verdict = await api.approve({ name, class: classifyClaudeTool(name, input) }, signal);
|
|
358
|
+
return verdict.kind === "allow" ? { behavior: "allow" } : { behavior: "deny", message: verdict.reason };
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
const release = acquireSessionResources(id);
|
|
362
|
+
bindings.set(id, binding);
|
|
363
|
+
const unbind = () => {
|
|
364
|
+
if (bindings.get(id) === binding)
|
|
365
|
+
bindings.delete(id);
|
|
366
|
+
release();
|
|
367
|
+
};
|
|
368
|
+
if (api.signal.aborted)
|
|
369
|
+
unbind();
|
|
370
|
+
else
|
|
371
|
+
api.signal.addEventListener("abort", unbind, { once: true });
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
return { provider, plugin };
|
|
375
|
+
}
|
|
376
|
+
export {
|
|
377
|
+
claudeCodeSdk,
|
|
378
|
+
ultracodeSetting
|
|
379
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { CanUseTool, EffortLevel, PermissionResult, Query, SDKMessage, SessionStoreEntry, query } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import type { Api, AssistantMessageEventStream, Message, Model, Tool } from "@nyte-ai/ai";
|
|
3
|
+
import type { ContentBlock } from "./transcript.ts";
|
|
4
|
+
interface Launch {
|
|
5
|
+
readonly key: string;
|
|
6
|
+
readonly model: string;
|
|
7
|
+
readonly cwd: string;
|
|
8
|
+
readonly thinking: boolean;
|
|
9
|
+
readonly effort: EffortLevel | undefined;
|
|
10
|
+
readonly ultracode: boolean;
|
|
11
|
+
readonly env: Record<string, string | undefined> | undefined;
|
|
12
|
+
readonly session: string;
|
|
13
|
+
readonly history: readonly SessionStoreEntry[];
|
|
14
|
+
readonly tools: readonly Tool[];
|
|
15
|
+
readonly query: StartQuery;
|
|
16
|
+
/** The installed `claude` to run; without one the Agent SDK looks for its own. */
|
|
17
|
+
readonly claude: string | undefined;
|
|
18
|
+
readonly approve: Approve;
|
|
19
|
+
}
|
|
20
|
+
/** Decides a call Claude Code asks to run under Nyte's permissions policy, by the tool's own name. */
|
|
21
|
+
export type Approve = (name: string, input: Parameters<CanUseTool>[1], signal: AbortSignal) => Promise<PermissionResult>;
|
|
22
|
+
/** Starts Claude Code: the Agent SDK's `query`, or a stand-in with the parts of its `Query` a session uses. */
|
|
23
|
+
export type StartQuery = (params: Parameters<typeof query>[0]) => AsyncIterable<SDKMessage> & Pick<Query, "applyFlagSettings" | "close">;
|
|
24
|
+
export type QuestionAnswers = Record<string, string> | null;
|
|
25
|
+
interface ClaudeToolOutput {
|
|
26
|
+
readonly text: string;
|
|
27
|
+
readonly isError: boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare class ClaudeCodeSession {
|
|
30
|
+
#private;
|
|
31
|
+
readonly key: string;
|
|
32
|
+
known: readonly string[];
|
|
33
|
+
constructor(launch: Launch);
|
|
34
|
+
get closed(): boolean;
|
|
35
|
+
configure(effort: EffortLevel | undefined, ultracode: boolean): Promise<void>;
|
|
36
|
+
/** Serves `tools` as the Nyte MCP server's tools from now on, telling Claude Code when they changed. */
|
|
37
|
+
expose(tools: readonly Tool[]): void;
|
|
38
|
+
/** Answers Claude Code from Nyte's tool results: a Nyte tool call gets its result, and a call Claude Code asked to run but Nyte settled without running it is denied with that result. */
|
|
39
|
+
deliver(messages: readonly Message[]): void;
|
|
40
|
+
/** Lets Claude Code's call `id` go on to its approval now that Nyte records it (so the workspace snapshot before it is taken), and denies the calls before it in the same message that Nyte settled without running. */
|
|
41
|
+
recording(id: string): void;
|
|
42
|
+
send(content: readonly ContentBlock[]): void;
|
|
43
|
+
respond(model: Model<Api>, signal: AbortSignal | undefined): AssistantMessageEventStream;
|
|
44
|
+
get asking(): boolean;
|
|
45
|
+
answer(id: string, answers: QuestionAnswers): void;
|
|
46
|
+
result(id: string, signal: AbortSignal): Promise<ClaudeToolOutput>;
|
|
47
|
+
background(signal: AbortSignal): Promise<string>;
|
|
48
|
+
close(reason?: Error): void;
|
|
49
|
+
}
|
|
50
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { SDKUserMessage, SessionStoreEntry } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import type { Message, UserMessage } from "@nyte-ai/ai";
|
|
3
|
+
import { Type } from "typebox";
|
|
4
|
+
type MessageParam = SDKUserMessage["message"];
|
|
5
|
+
export type ContentBlock = Exclude<MessageParam["content"], string>[number];
|
|
6
|
+
export declare const mirrorArguments: Type.TObject<{
|
|
7
|
+
id: Type.TString;
|
|
8
|
+
name: Type.TString;
|
|
9
|
+
input: Type.TRecord<"^.*$", Type.TUnknown>;
|
|
10
|
+
}>;
|
|
11
|
+
export declare function userBlocks(message: UserMessage): ContentBlock[];
|
|
12
|
+
export declare function messageKey(message: Message): string;
|
|
13
|
+
export declare function sessionEntries(messages: readonly Message[], input: {
|
|
14
|
+
readonly session: string;
|
|
15
|
+
readonly model: string;
|
|
16
|
+
readonly cwd: string;
|
|
17
|
+
}): SessionStoreEntry[];
|
|
18
|
+
export declare function flatPrompt(messages: readonly Message[]): string;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mirrorArguments3,
|
|
3
|
+
userBlocks3,
|
|
4
|
+
messageKey3,
|
|
5
|
+
sessionEntries2,
|
|
6
|
+
flatPrompt2
|
|
7
|
+
} from "../../chunks/billing-2v3g7rd9.js";
|
|
8
|
+
import"../../chunks/billing-ye3wk5r3.js";
|
|
9
|
+
export {
|
|
10
|
+
flatPrompt2 as flatPrompt,
|
|
11
|
+
messageKey3 as messageKey,
|
|
12
|
+
mirrorArguments3 as mirrorArguments,
|
|
13
|
+
sessionEntries2 as sessionEntries,
|
|
14
|
+
userBlocks3 as userBlocks
|
|
15
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { SDKPartialAssistantMessage } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import type { Api, AssistantMessage, AssistantMessageEventStream, Model, ToolCall } from "@nyte-ai/ai";
|
|
3
|
+
type StreamEvent = SDKPartialAssistantMessage["event"];
|
|
4
|
+
export declare const CLAUDE_CODE_PROVIDER = "claude-code";
|
|
5
|
+
export declare const MIRROR_TOOL = "claude_code";
|
|
6
|
+
export declare const BACKGROUND_TOOL = "BackgroundTasks";
|
|
7
|
+
export declare const NYTE_SERVER = "nyte";
|
|
8
|
+
export declare const NYTE_TOOL_PREFIX = "mcp__nyte__";
|
|
9
|
+
export declare function emptyMessage(model: Model<Api>): AssistantMessage;
|
|
10
|
+
export declare function mirrorCall(id: string, name: string, input: Record<string, unknown>): ToolCall;
|
|
11
|
+
export declare class Translator {
|
|
12
|
+
#private;
|
|
13
|
+
constructor(model: Model<Api>, output: AssistantMessage, stream: AssistantMessageEventStream);
|
|
14
|
+
/** Applies one stream event. Returns the raw stop reason at a message's end, and `"tool_use"` as soon as a Nyte tool call's input is complete: Claude Code waits for Nyte to run it before it runs the message's later calls. */
|
|
15
|
+
apply(event: StreamEvent): string | undefined;
|
|
16
|
+
append(call: ToolCall): void;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CLAUDE_CODE_PROVIDER2,
|
|
3
|
+
MIRROR_TOOL3,
|
|
4
|
+
BACKGROUND_TOOL2,
|
|
5
|
+
NYTE_SERVER2,
|
|
6
|
+
NYTE_TOOL_PREFIX2,
|
|
7
|
+
emptyMessage3,
|
|
8
|
+
mirrorCall2,
|
|
9
|
+
Translator3
|
|
10
|
+
} from "../../chunks/billing-ye3wk5r3.js";
|
|
11
|
+
export {
|
|
12
|
+
BACKGROUND_TOOL2 as BACKGROUND_TOOL,
|
|
13
|
+
CLAUDE_CODE_PROVIDER2 as CLAUDE_CODE_PROVIDER,
|
|
14
|
+
MIRROR_TOOL3 as MIRROR_TOOL,
|
|
15
|
+
NYTE_SERVER2 as NYTE_SERVER,
|
|
16
|
+
NYTE_TOOL_PREFIX2 as NYTE_TOOL_PREFIX,
|
|
17
|
+
Translator3 as Translator,
|
|
18
|
+
emptyMessage3 as emptyMessage,
|
|
19
|
+
mirrorCall2 as mirrorCall
|
|
20
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Connection, Session } from "@nyte-ai/core";
|
|
2
|
+
import type { Decision, Placement, SessionInfo, SubmitDraft } from "@nyte-ai/schema";
|
|
3
|
+
import type { Plugin, PluginApi } from "../client.ts";
|
|
4
|
+
import type { PartMessage } from "./presentation.ts";
|
|
5
|
+
type Notification = Parameters<PluginApi["ui"]["notify"]>[0];
|
|
6
|
+
/**
|
|
7
|
+
* What a client hands the plugins it mounts: its connection, the frameworks
|
|
8
|
+
* it draws, the session on screen, and where notices and plugin errors go.
|
|
9
|
+
*
|
|
10
|
+
* @category plugins
|
|
11
|
+
*/
|
|
12
|
+
export interface MountOptions {
|
|
13
|
+
readonly connection: Connection;
|
|
14
|
+
readonly plugins: readonly Plugin[];
|
|
15
|
+
readonly client: PluginApi["client"];
|
|
16
|
+
readonly session: () => Session | null;
|
|
17
|
+
readonly notify: (input: Notification) => void;
|
|
18
|
+
readonly report: (plugin: string, message: string) => void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The mounted client plugins: their renderers and the hooks a client fires.
|
|
22
|
+
*
|
|
23
|
+
* @category plugins
|
|
24
|
+
*/
|
|
25
|
+
export interface ClientPlugins {
|
|
26
|
+
readonly ids: readonly string[];
|
|
27
|
+
/** The view a plugin renderer draws for a part, or undefined when none draws its kind. */
|
|
28
|
+
draw(session: Session, message: PartMessage, placement: Placement): unknown;
|
|
29
|
+
/** Feeds the session directory; each run that ends after the first list fires `run_ended_anywhere`. */
|
|
30
|
+
sessionsChanged(sessions: readonly SessionInfo[]): void;
|
|
31
|
+
switched(previous: Session | null, next: Session): Promise<void>;
|
|
32
|
+
beforeSubmit(draft: SubmitDraft): Promise<Decision<SubmitDraft>>;
|
|
33
|
+
dispose(): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Activates client plugins once per app, all at once: their registries, hooks
|
|
37
|
+
* and the first renderer per part kind, in plugin order, among the frameworks
|
|
38
|
+
* the client draws. A plugin whose activation fails is reported and the rest
|
|
39
|
+
* still mount.
|
|
40
|
+
*
|
|
41
|
+
* @category plugins
|
|
42
|
+
*/
|
|
43
|
+
export declare function mountClientPlugins(options: MountOptions): Promise<ClientPlugins>;
|
|
44
|
+
export {};
|