@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.
Files changed (137) hide show
  1. package/LICENSE +21 -0
  2. package/THIRD-PARTY-NOTICES.md +866 -0
  3. package/dist/chunks/billing-0y7dfkp2.js +146 -0
  4. package/dist/chunks/billing-2v3g7rd9.js +190 -0
  5. package/dist/chunks/billing-3j77ss7y.js +86 -0
  6. package/dist/chunks/billing-3scqmkzb.js +559 -0
  7. package/dist/chunks/billing-4vz9pxyx.js +22 -0
  8. package/dist/chunks/billing-6z2kgtyt.js +51 -0
  9. package/dist/chunks/billing-8rjk35gr.js +444 -0
  10. package/dist/chunks/billing-9nn3yp18.js +176 -0
  11. package/dist/chunks/billing-9qc0eqh4.js +174 -0
  12. package/dist/chunks/billing-a9vqn66p.js +351 -0
  13. package/dist/chunks/billing-bv5zr32b.js +369 -0
  14. package/dist/chunks/billing-cy1rg619.js +302 -0
  15. package/dist/chunks/billing-ejx2hv52.js +323 -0
  16. package/dist/chunks/billing-h13r0byk.js +80 -0
  17. package/dist/chunks/billing-hg64tqf1.js +97 -0
  18. package/dist/chunks/billing-j643d12p.js +197 -0
  19. package/dist/chunks/billing-kn3d30b4.js +276 -0
  20. package/dist/chunks/billing-mvc33pv6.js +36 -0
  21. package/dist/chunks/billing-s4rrspsk.js +7 -0
  22. package/dist/chunks/billing-svrhh5a5.js +307 -0
  23. package/dist/chunks/billing-sxc70w72.js +161 -0
  24. package/dist/chunks/billing-t1qrxe16.js +41 -0
  25. package/dist/chunks/billing-tm34gm2p.js +528 -0
  26. package/dist/chunks/billing-tzr3cebf.js +20 -0
  27. package/dist/chunks/billing-v3hg5rc7.js +373 -0
  28. package/dist/chunks/billing-wmcbg6fw.js +52 -0
  29. package/dist/chunks/billing-ye3wk5r3.js +205 -0
  30. package/dist/chunks/billing-zfpm2rt0.js +29 -0
  31. package/dist/examples/claude-code/LICENSE +21 -0
  32. package/dist/examples/claude-code/billing.d.ts +7 -0
  33. package/dist/examples/claude-code/billing.js +11 -0
  34. package/dist/examples/claude-code/claude-cli.d.ts +35 -0
  35. package/dist/examples/claude-code/claude-cli.js +15 -0
  36. package/dist/examples/claude-code/env.d.ts +1 -0
  37. package/dist/examples/claude-code/env.js +6 -0
  38. package/dist/examples/claude-code/index.d.ts +24 -0
  39. package/dist/examples/claude-code/index.js +149 -0
  40. package/dist/examples/claude-code/inert-mcp.d.ts +1 -0
  41. package/dist/examples/claude-code/inert-mcp.js +6 -0
  42. package/dist/examples/claude-code/model-catalog.d.ts +27 -0
  43. package/dist/examples/claude-code/model-catalog.js +12 -0
  44. package/dist/examples/claude-code/process.d.ts +22 -0
  45. package/dist/examples/claude-code/process.js +25 -0
  46. package/dist/examples/claude-code/replay.d.ts +4 -0
  47. package/dist/examples/claude-code/replay.js +11 -0
  48. package/dist/examples/claude-code/stream.d.ts +3 -0
  49. package/dist/examples/claude-code/stream.js +16 -0
  50. package/dist/examples/claude-code/transcript.d.ts +83 -0
  51. package/dist/examples/claude-code/transcript.js +23 -0
  52. package/dist/examples/claude-code/turn-relay.d.ts +48 -0
  53. package/dist/examples/claude-code/turn-relay.js +9 -0
  54. package/dist/examples/claude-code/wire.d.ts +372 -0
  55. package/dist/examples/claude-code/wire.js +18 -0
  56. package/dist/src/acp/connection.d.ts +24 -0
  57. package/dist/src/acp/connection.js +8 -0
  58. package/dist/src/acp/index.d.ts +54 -0
  59. package/dist/src/acp/index.js +1005 -0
  60. package/dist/src/acp/registry.d.ts +18 -0
  61. package/dist/src/acp/registry.js +9 -0
  62. package/dist/src/acp/thread.d.ts +46 -0
  63. package/dist/src/acp/thread.js +7 -0
  64. package/dist/src/acp/transcript.d.ts +8 -0
  65. package/dist/src/acp/transcript.js +11 -0
  66. package/dist/src/acp/translate.d.ts +33 -0
  67. package/dist/src/acp/translate.js +20 -0
  68. package/dist/src/approvals/approvals.d.ts +189 -0
  69. package/dist/src/approvals/approvals.js +143 -0
  70. package/dist/src/approvals/schema.d.ts +169 -0
  71. package/dist/src/approvals/schema.js +18 -0
  72. package/dist/src/bash-description.d.ts +30 -0
  73. package/dist/src/bash-description.js +18 -0
  74. package/dist/src/browser-tools.d.ts +25 -0
  75. package/dist/src/browser-tools.js +246 -0
  76. package/dist/src/canvas/canvas-compile.d.ts +48 -0
  77. package/dist/src/canvas/canvas-compile.js +8 -0
  78. package/dist/src/canvas/canvas-libraries.d.ts +32 -0
  79. package/dist/src/canvas/canvas-libraries.js +6 -0
  80. package/dist/src/canvas/canvas-preview.d.ts +107 -0
  81. package/dist/src/canvas/canvas-preview.js +12 -0
  82. package/dist/src/canvas/canvas-protocol.d.ts +184 -0
  83. package/dist/src/canvas/canvas-protocol.js +75 -0
  84. package/dist/src/canvas/canvas.d.ts +50 -0
  85. package/dist/src/canvas/canvas.js +221 -0
  86. package/dist/src/canvas/schema.d.ts +47 -0
  87. package/dist/src/canvas/schema.js +8 -0
  88. package/dist/src/claude-code-sdk/index.d.ts +35 -0
  89. package/dist/src/claude-code-sdk/index.js +379 -0
  90. package/dist/src/claude-code-sdk/session.d.ts +50 -0
  91. package/dist/src/claude-code-sdk/session.js +7 -0
  92. package/dist/src/claude-code-sdk/transcript.d.ts +19 -0
  93. package/dist/src/claude-code-sdk/transcript.js +15 -0
  94. package/dist/src/claude-code-sdk/translate.d.ts +18 -0
  95. package/dist/src/claude-code-sdk/translate.js +20 -0
  96. package/dist/src/client/mount.d.ts +44 -0
  97. package/dist/src/client/mount.js +252 -0
  98. package/dist/src/client/notifications.d.ts +36 -0
  99. package/dist/src/client/notifications.js +24 -0
  100. package/dist/src/client/presentation.d.ts +362 -0
  101. package/dist/src/client/presentation.js +391 -0
  102. package/dist/src/client/transcript-tui.d.ts +23 -0
  103. package/dist/src/client/transcript-tui.js +20 -0
  104. package/dist/src/client/transcript.d.ts +23 -0
  105. package/dist/src/client/transcript.js +51 -0
  106. package/dist/src/client.d.ts +53 -0
  107. package/dist/src/client.js +22 -0
  108. package/dist/src/codemode-runtime.d.ts +11 -0
  109. package/dist/src/codemode-runtime.js +10 -0
  110. package/dist/src/codemode-worker.d.ts +1 -0
  111. package/dist/src/codemode-worker.js +2 -0
  112. package/dist/src/codemode.d.ts +21 -0
  113. package/dist/src/codemode.js +170 -0
  114. package/dist/src/core.d.ts +43 -0
  115. package/dist/src/core.js +11 -0
  116. package/dist/src/find-on-path.d.ts +4 -0
  117. package/dist/src/find-on-path.js +8 -0
  118. package/dist/src/openai-astra-context.d.ts +23 -0
  119. package/dist/src/openai-astra-context.js +14 -0
  120. package/dist/src/openai-compaction.d.ts +15 -0
  121. package/dist/src/openai-compaction.js +55 -0
  122. package/dist/src/question/client/questions-tui.d.ts +9 -0
  123. package/dist/src/question/client/questions-tui.js +19 -0
  124. package/dist/src/question/client/questions.d.ts +9 -0
  125. package/dist/src/question/client/questions.js +160 -0
  126. package/dist/src/question/question.d.ts +63 -0
  127. package/dist/src/question/question.js +9 -0
  128. package/dist/src/question/schema.d.ts +101 -0
  129. package/dist/src/question/schema.js +14 -0
  130. package/dist/src/rename.d.ts +79 -0
  131. package/dist/src/rename.js +91 -0
  132. package/dist/src/telemetry.d.ts +36 -0
  133. package/dist/src/telemetry.js +84 -0
  134. package/dist/src/web-search.d.ts +78 -0
  135. package/dist/src/web-search.js +219 -0
  136. package/package.json +190 -3
  137. package/README.md +0 -3
@@ -0,0 +1,528 @@
1
+ import {
2
+ BACKGROUND_TOOL2,
3
+ NYTE_SERVER2,
4
+ NYTE_TOOL_PREFIX2,
5
+ emptyMessage3,
6
+ mirrorCall2,
7
+ Translator3
8
+ } from "./billing-ye3wk5r3.js";
9
+
10
+ // src/claude-code-sdk/session.ts
11
+ import { randomUUID } from "node:crypto";
12
+ import { createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
13
+ import { createAssistantMessageEventStream } from "@nyte-ai/ai";
14
+ import { Type } from "typebox";
15
+ import { Value } from "typebox/value";
16
+ var ALLOW = { behavior: "allow" };
17
+ var SKIPPED = "Nyte did not run this tool call.";
18
+ var toolUseId = Type.String({ minLength: 1 });
19
+ var toolInput = Type.Record(Type.String(), Type.Unknown());
20
+ var APPROVAL_HOOK_SECONDS = 7 * 24 * 60 * 60;
21
+
22
+ class Inbox {
23
+ #items = [];
24
+ #waiter;
25
+ #ended = false;
26
+ has(match) {
27
+ return this.#items.some(match);
28
+ }
29
+ push(item) {
30
+ this.#items.push(item);
31
+ this.#wake();
32
+ }
33
+ clear() {
34
+ this.#items.length = 0;
35
+ }
36
+ end() {
37
+ this.#ended = true;
38
+ this.#wake();
39
+ }
40
+ async next() {
41
+ while (this.#items.length === 0 && !this.#ended)
42
+ await new Promise((resolve) => this.#waiter = resolve);
43
+ return this.#items.shift();
44
+ }
45
+ async* [Symbol.asyncIterator]() {
46
+ for (;; ) {
47
+ const item = await this.next();
48
+ if (item === undefined)
49
+ return;
50
+ yield item;
51
+ }
52
+ }
53
+ #wake() {
54
+ const waiter = this.#waiter;
55
+ this.#waiter = undefined;
56
+ waiter?.();
57
+ }
58
+ }
59
+ function toolError(text) {
60
+ return { content: [{ type: "text", text }], isError: true };
61
+ }
62
+ function reply(message) {
63
+ return {
64
+ content: message.content.map((block) => block.type === "text" ? { type: "text", text: block.text } : { type: "image", data: block.data, mimeType: block.mimeType }),
65
+ isError: message.isError
66
+ };
67
+ }
68
+ function resultText(content) {
69
+ if (!Array.isArray(content))
70
+ return content ?? "";
71
+ return content.map((block) => block.type === "text" ? block.text : `[${block.type} content]`).join(`
72
+ `);
73
+ }
74
+ function storePath(key) {
75
+ return key.subpath === undefined ? key.sessionId : `${key.sessionId}/${key.subpath}`;
76
+ }
77
+ function memoryStore(session, history) {
78
+ const files = new Map([[session, [...history]]]);
79
+ return {
80
+ append: async (key, entries) => {
81
+ files.set(storePath(key), [...files.get(storePath(key)) ?? [], ...entries]);
82
+ },
83
+ load: async (key) => files.get(storePath(key)) ?? null
84
+ };
85
+ }
86
+
87
+ class ClaudeCodeSession2 {
88
+ key;
89
+ known = [];
90
+ #prompts = new Inbox;
91
+ #turn = new Inbox;
92
+ #results = new Map;
93
+ #questions = new Map;
94
+ #asking = new Set;
95
+ #changes = new Set;
96
+ #replies = new Map;
97
+ #gates = new Map;
98
+ #permits = new Map;
99
+ #approve;
100
+ #server;
101
+ #query;
102
+ #tools;
103
+ #order = [];
104
+ #settings;
105
+ #background = [];
106
+ #notes = [];
107
+ #idle = true;
108
+ #held = false;
109
+ #stderr = "";
110
+ #failure;
111
+ constructor(launch) {
112
+ this.key = launch.key;
113
+ this.#settings = { effort: launch.effort, ultracode: launch.ultracode };
114
+ this.#tools = launch.tools;
115
+ this.#approve = launch.approve;
116
+ const session = launch.session;
117
+ this.#server = createSdkMcpServer({ name: NYTE_SERVER2, tools: [] });
118
+ this.#server.instance.server.registerCapabilities({ tools: { listChanged: true } });
119
+ this.#server.instance.server.fallbackRequestHandler = async (request, extra) => {
120
+ if (request.method === "tools/list")
121
+ return {
122
+ tools: this.#tools.map((tool) => ({
123
+ name: tool.name,
124
+ description: tool.description,
125
+ inputSchema: { ...tool.parameters, type: "object" }
126
+ }))
127
+ };
128
+ if (request.method !== "tools/call")
129
+ throw new Error(`Nyte does not serve ${request.method}.`);
130
+ const { _meta: meta } = extra;
131
+ const id = meta?.["claudecode/toolUseId"];
132
+ return Value.Check(toolUseId, id) ? await this.#call(id, extra.signal) : toolError("Claude Code sent no tool use id for this Nyte tool call.");
133
+ };
134
+ const options = {
135
+ model: launch.model,
136
+ cwd: launch.cwd,
137
+ systemPrompt: { type: "preset", preset: "claude_code" },
138
+ includePartialMessages: true,
139
+ mcpServers: { [NYTE_SERVER2]: this.#server },
140
+ permissionMode: "default",
141
+ canUseTool: async (name, input, { signal, toolUseID, agentID }) => {
142
+ if (name.startsWith(NYTE_TOOL_PREFIX2))
143
+ return agentID === undefined ? ALLOW : { behavior: "deny", message: "Only the main agent can use Nyte's tools." };
144
+ if (name === "AskUserQuestion") {
145
+ if (agentID !== undefined)
146
+ return { behavior: "deny", message: "Only the main agent can ask the user questions." };
147
+ const answers = await this.#question(toolUseID, signal);
148
+ return answers === null ? { behavior: "deny", message: "The user did not answer." } : { behavior: "allow", updatedInput: { ...input, answers } };
149
+ }
150
+ return await this.#permit(toolUseID, name, input, agentID === undefined, signal);
151
+ },
152
+ hooks: {
153
+ PreToolUse: [
154
+ {
155
+ hooks: [(input, _id, { signal }) => this.#beforeTool(input, signal)],
156
+ timeout: APPROVAL_HOOK_SECONDS
157
+ }
158
+ ]
159
+ },
160
+ thinking: launch.thinking ? { type: "adaptive", display: "summarized" } : { type: "disabled" },
161
+ env: {
162
+ ...process.env,
163
+ ...launch.env,
164
+ CLAUDE_AGENT_SDK_CLIENT_APP: "nyte",
165
+ CLAUDE_CODE_EMIT_SESSION_STATE_EVENTS: "1"
166
+ },
167
+ stderr: (chunk) => this.#stderr = (this.#stderr + chunk).slice(-4096),
168
+ pathToClaudeCodeExecutable: launch.claude
169
+ };
170
+ if (launch.effort !== undefined)
171
+ options.effort = launch.effort;
172
+ if (launch.ultracode)
173
+ options.settings = { ultracode: true, enableWorkflows: true };
174
+ if (launch.history.length > 0) {
175
+ options.resume = session;
176
+ options.sessionStore = memoryStore(session, launch.history);
177
+ }
178
+ this.#query = launch.query({ prompt: this.#prompts, options });
179
+ this.#pump();
180
+ }
181
+ get closed() {
182
+ return this.#failure !== undefined;
183
+ }
184
+ async configure(effort, ultracode) {
185
+ if (this.#settings.effort === effort && this.#settings.ultracode === ultracode)
186
+ return;
187
+ this.#settings = { effort, ultracode };
188
+ await this.#query.applyFlagSettings({
189
+ effortLevel: effort ?? null,
190
+ ultracode: ultracode ? true : null,
191
+ enableWorkflows: ultracode ? true : null
192
+ });
193
+ }
194
+ expose(tools) {
195
+ if (JSON.stringify(tools) === JSON.stringify(this.#tools))
196
+ return;
197
+ this.#tools = tools;
198
+ this.#server.instance.sendToolListChanged();
199
+ }
200
+ deliver(messages) {
201
+ for (const message of messages) {
202
+ if (message.role !== "toolResult")
203
+ continue;
204
+ const id = message.toolCallId;
205
+ if (this.#replies.has(id))
206
+ this.#reply(id).resolve(reply(message));
207
+ else
208
+ this.#gates.get(id)?.resolve({
209
+ behavior: "deny",
210
+ message: message.content.flatMap((block) => block.type === "text" ? [block.text] : []).join(`
211
+ `) || SKIPPED
212
+ });
213
+ }
214
+ }
215
+ recording(id) {
216
+ const position = this.#order.findIndex((known) => known === id);
217
+ for (const [index, earlier] of this.#order.entries()) {
218
+ if (index > position)
219
+ break;
220
+ this.#gate(earlier).resolve(index === position ? ALLOW : { behavior: "deny", message: SKIPPED });
221
+ }
222
+ }
223
+ send(content) {
224
+ if (this.#idle)
225
+ this.#turn.clear();
226
+ this.#idle = false;
227
+ this.#held = false;
228
+ this.#prompts.push({
229
+ type: "user",
230
+ message: { role: "user", content: [...content] },
231
+ parent_tool_use_id: null,
232
+ origin: { kind: "human" }
233
+ });
234
+ }
235
+ respond(model, signal) {
236
+ const stream = createAssistantMessageEventStream();
237
+ const output = emptyMessage3(model);
238
+ const translator = new Translator3(model, output, stream);
239
+ const abort = () => this.close(new Error("Request was aborted"));
240
+ signal?.addEventListener("abort", abort, { once: true });
241
+ (async () => {
242
+ try {
243
+ stream.push({ type: "start", partial: output });
244
+ let failure;
245
+ for (;; ) {
246
+ const item = await this.#turn.next();
247
+ if (item === undefined)
248
+ throw this.#failure ?? new Error("Claude Code exited.");
249
+ if (item.type === "system") {
250
+ if (item.state !== "idle" || !this.#held)
251
+ continue;
252
+ this.#held = false;
253
+ this.#idle = true;
254
+ if (output.stopReason === "pending")
255
+ output.stopReason = "stop";
256
+ break;
257
+ }
258
+ if (item.type === "result" && this.#held)
259
+ continue;
260
+ if (item.type === "assistant") {
261
+ if (item.error !== undefined)
262
+ failure = item.message.content.flatMap((block) => block.type === "text" ? [block.text] : []).join(`
263
+ `);
264
+ continue;
265
+ }
266
+ if (item.type === "result") {
267
+ if (item.subtype !== "success")
268
+ throw new Error(failure ?? (item.errors.join(`
269
+ `) || `Claude Code failed: ${item.subtype}`));
270
+ if (item.is_error)
271
+ throw new Error(failure ?? item.result);
272
+ this.#idle = true;
273
+ if (output.stopReason === "pending")
274
+ output.stopReason = "stop";
275
+ break;
276
+ }
277
+ this.#held = false;
278
+ const stop = translator.apply(item.event);
279
+ if (stop === "tool_use") {
280
+ if (output.content.some((block) => block.type === "toolCall"))
281
+ break;
282
+ continue;
283
+ }
284
+ if (stop !== undefined && this.#background.length > 0) {
285
+ translator.append(mirrorCall2(`claude-code-background-${randomUUID()}`, BACKGROUND_TOOL2, {
286
+ tasks: [...this.#background]
287
+ }));
288
+ output.stopReason = "toolUse";
289
+ this.#held = true;
290
+ break;
291
+ }
292
+ }
293
+ if (output.stopReason === "error")
294
+ throw new Error(output.errorMessage ?? "Claude Code failed.");
295
+ if (output.stopReason === "aborted" || output.stopReason === "pending")
296
+ throw new Error("Claude Code ended without a response.");
297
+ stream.push({ type: "done", reason: output.stopReason, message: output });
298
+ } catch (error) {
299
+ output.stopReason = signal?.aborted === true ? "aborted" : "error";
300
+ output.errorMessage = error instanceof Error ? error.message : String(error);
301
+ stream.push({ type: "error", reason: output.stopReason, error: output });
302
+ this.close(error instanceof Error ? error : new Error(String(error)));
303
+ } finally {
304
+ signal?.removeEventListener("abort", abort);
305
+ stream.end();
306
+ }
307
+ })();
308
+ return stream;
309
+ }
310
+ get asking() {
311
+ return this.#asking.size > 0;
312
+ }
313
+ answer(id, answers) {
314
+ this.#pending(id).resolve(answers);
315
+ }
316
+ async result(id, signal) {
317
+ await this.#until(() => this.#results.has(id), signal);
318
+ const output = this.#results.get(id);
319
+ if (output === undefined)
320
+ throw this.#failure ?? new Error("Claude Code is no longer running this turn.");
321
+ return output;
322
+ }
323
+ async background(signal) {
324
+ await this.#until(() => this.#turn.has((item) => item.type === "stream_event" || item.type === "system"), signal);
325
+ if (this.#failure !== undefined)
326
+ throw this.#failure;
327
+ const notes = this.#notes.splice(0);
328
+ return notes.length === 0 ? "Background work finished." : notes.join(`
329
+
330
+ `);
331
+ }
332
+ close(reason = new Error("Claude Code closed.")) {
333
+ if (this.#failure !== undefined)
334
+ return;
335
+ this.#failure = reason;
336
+ for (const pending of this.#questions.values())
337
+ pending.resolve(null);
338
+ for (const pending of this.#replies.values())
339
+ pending.resolve(toolError(reason.message));
340
+ for (const pending of this.#gates.values())
341
+ pending.resolve({ behavior: "deny", message: reason.message });
342
+ this.#prompts.end();
343
+ this.#turn.end();
344
+ this.#query.close();
345
+ this.#changed();
346
+ }
347
+ #pending(id) {
348
+ const known = this.#questions.get(id);
349
+ if (known !== undefined)
350
+ return known;
351
+ const created = Promise.withResolvers();
352
+ this.#questions.set(id, created);
353
+ return created;
354
+ }
355
+ async#question(id, signal) {
356
+ const pending = this.#pending(id);
357
+ const cancel = () => this.answer(id, null);
358
+ this.#asking.add(id);
359
+ signal.addEventListener("abort", cancel, { once: true });
360
+ try {
361
+ return await pending.promise;
362
+ } finally {
363
+ this.#asking.delete(id);
364
+ signal.removeEventListener("abort", cancel);
365
+ }
366
+ }
367
+ #reply(id) {
368
+ const known = this.#replies.get(id);
369
+ if (known !== undefined)
370
+ return known;
371
+ const created = Promise.withResolvers();
372
+ this.#replies.set(id, created);
373
+ return created;
374
+ }
375
+ #gate(id) {
376
+ const known = this.#gates.get(id);
377
+ if (known !== undefined)
378
+ return known;
379
+ const created = Promise.withResolvers();
380
+ this.#gates.set(id, created);
381
+ return created;
382
+ }
383
+ async#call(id, signal) {
384
+ const pending = this.#reply(id);
385
+ const cancel = () => pending.resolve(toolError("Request was aborted"));
386
+ signal.addEventListener("abort", cancel, { once: true });
387
+ try {
388
+ return await pending.promise;
389
+ } finally {
390
+ this.#replies.delete(id);
391
+ signal.removeEventListener("abort", cancel);
392
+ }
393
+ }
394
+ #permit(id, name, input, main, signal) {
395
+ const known = this.#permits.get(id);
396
+ if (known !== undefined)
397
+ return known;
398
+ const decided = (async () => {
399
+ if (main) {
400
+ const recorded = await this.#recorded(id, signal);
401
+ if (recorded.behavior === "deny")
402
+ return recorded;
403
+ }
404
+ return this.#approve(name, input, signal);
405
+ })();
406
+ this.#permits.set(id, decided);
407
+ return decided;
408
+ }
409
+ async#beforeTool(input, signal) {
410
+ if (input.hook_event_name !== "PreToolUse" || input.tool_name.startsWith(NYTE_TOOL_PREFIX2) || input.tool_name === "AskUserQuestion")
411
+ return {};
412
+ const decided = await this.#permit(input.tool_use_id, input.tool_name, Value.Check(toolInput, input.tool_input) ? input.tool_input : {}, input.agent_id === undefined, signal);
413
+ return decided.behavior === "allow" ? {} : {
414
+ hookSpecificOutput: {
415
+ hookEventName: "PreToolUse",
416
+ permissionDecision: "deny",
417
+ permissionDecisionReason: decided.message
418
+ }
419
+ };
420
+ }
421
+ async#recorded(id, signal) {
422
+ const pending = this.#gate(id);
423
+ const cancel = () => pending.resolve({ behavior: "deny", message: "Request was aborted" });
424
+ signal.addEventListener("abort", cancel, { once: true });
425
+ try {
426
+ return await pending.promise;
427
+ } finally {
428
+ signal.removeEventListener("abort", cancel);
429
+ }
430
+ }
431
+ async#until(ready, signal) {
432
+ while (!ready() && this.#failure === undefined) {
433
+ signal.throwIfAborted();
434
+ await new Promise((resolve) => {
435
+ const done = () => {
436
+ this.#changes.delete(done);
437
+ signal.removeEventListener("abort", done);
438
+ resolve();
439
+ };
440
+ this.#changes.add(done);
441
+ signal.addEventListener("abort", done, { once: true });
442
+ });
443
+ }
444
+ if (signal.aborted) {
445
+ this.close(new Error("Request was aborted"));
446
+ signal.throwIfAborted();
447
+ }
448
+ }
449
+ async#pump() {
450
+ try {
451
+ for await (const message of this.#query)
452
+ this.#route(message);
453
+ this.close(new Error(`Claude Code exited.${this.#detail()}`));
454
+ } catch (error) {
455
+ const message = error instanceof Error ? error.message : String(error);
456
+ this.close(new Error(`${message}${this.#detail()}`, { cause: error }));
457
+ }
458
+ }
459
+ #detail() {
460
+ const tail = this.#stderr.trim().slice(-500);
461
+ return tail === "" ? "" : ` (${tail})`;
462
+ }
463
+ #route(message) {
464
+ switch (message.type) {
465
+ case "stream_event":
466
+ if (message.parent_tool_use_id !== null)
467
+ break;
468
+ this.#track(message.event);
469
+ this.#turn.push(message);
470
+ break;
471
+ case "assistant":
472
+ if (message.parent_tool_use_id === null)
473
+ this.#turn.push(message);
474
+ break;
475
+ case "result":
476
+ this.#turn.push(message);
477
+ break;
478
+ case "user": {
479
+ const content = message.message.content;
480
+ if (message.parent_tool_use_id !== null || !Array.isArray(content))
481
+ break;
482
+ for (const block of content)
483
+ if (block.type === "tool_result")
484
+ this.#results.set(block.tool_use_id, {
485
+ text: resultText(block.content),
486
+ isError: block.is_error === true
487
+ });
488
+ break;
489
+ }
490
+ case "system":
491
+ if (message.subtype === "background_tasks_changed")
492
+ this.#background = message.tasks.flatMap((task) => task.ambient === true ? [] : [task.description]);
493
+ else if (message.subtype === "task_notification")
494
+ this.#notes.push(message.summary);
495
+ else if (message.subtype === "session_state_changed" && message.state === "idle")
496
+ this.#turn.push(message);
497
+ break;
498
+ default:
499
+ break;
500
+ }
501
+ this.#changed();
502
+ }
503
+ #track(event) {
504
+ if (event.type === "message_start") {
505
+ for (const id of this.#order) {
506
+ this.#gates.delete(id);
507
+ this.#permits.delete(id);
508
+ }
509
+ this.#order = [];
510
+ return;
511
+ }
512
+ if (event.type !== "content_block_start" || event.content_block.type !== "tool_use")
513
+ return;
514
+ const id = event.content_block.id;
515
+ if (event.content_block.name.startsWith(NYTE_TOOL_PREFIX2)) {
516
+ this.#reply(id);
517
+ return;
518
+ }
519
+ this.#order.push(id);
520
+ this.#gate(id);
521
+ }
522
+ #changed() {
523
+ for (const change of this.#changes)
524
+ change();
525
+ }
526
+ }
527
+
528
+ export { ClaudeCodeSession2 };
@@ -0,0 +1,20 @@
1
+ import {
2
+ envFlagEnabled2
3
+ } from "./billing-s4rrspsk.js";
4
+
5
+ // examples/claude-code/billing.ts
6
+ var ALLOW_USAGE_CREDITS_ENV = "NYTE_CLAUDE_CODE_ALLOW_USAGE_CREDITS";
7
+ var USAGE_CREDITS_REJECTION = /third-party apps now draw from your extra usage|out of extra usage|draws? from your usage credits/iu;
8
+ function usageCreditsAllowed2(env) {
9
+ return envFlagEnabled2(env[ALLOW_USAGE_CREDITS_ENV]);
10
+ }
11
+ function usageCreditsChargeError2(info) {
12
+ return new Error("Claude Code billing: this request was charged to Claude usage credits instead of your plan limits " + `(rate limit status ${info.status ?? "unknown"}${info.rateLimitType ? `, ${info.rateLimitType}` : ""}). ` + "Nyte stopped so further requests are not charged. To stay on plan limits only, turn off usage credits at " + `claude.ai/settings/usage. To allow usage credits, set ${ALLOW_USAGE_CREDITS_ENV}=1.`);
13
+ }
14
+ function describeUsageCreditsRejection2(message) {
15
+ if (!USAGE_CREDITS_REJECTION.test(message))
16
+ return;
17
+ return "Claude Code billing: Anthropic did not accept this request on your Claude plan limits and wants to charge " + "it to usage credits. This happens when your plan limit is used up, or when Anthropic classifies the " + "request as third-party app usage. Nyte will not retry it. Original error: " + message;
18
+ }
19
+
20
+ export { usageCreditsAllowed2, usageCreditsChargeError2, describeUsageCreditsRejection2 };