@nyte-ai/plugin 0.0.0-stage → 0.0.18

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 (134) hide show
  1. package/LICENSE +21 -0
  2. package/THIRD-PARTY-NOTICES.md +800 -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-6z2kgtyt.js +51 -0
  8. package/dist/chunks/billing-8rjk35gr.js +444 -0
  9. package/dist/chunks/billing-9mfedmsh.js +373 -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-j643d12p.js +197 -0
  18. package/dist/chunks/billing-k2p1t25n.js +109 -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-tzr3cebf.js +20 -0
  26. package/dist/chunks/billing-wmcbg6fw.js +52 -0
  27. package/dist/chunks/billing-wmkxkypm.js +527 -0
  28. package/dist/chunks/billing-ye3wk5r3.js +205 -0
  29. package/dist/chunks/billing-zfpm2rt0.js +29 -0
  30. package/dist/examples/claude-code/LICENSE +21 -0
  31. package/dist/examples/claude-code/billing.d.ts +7 -0
  32. package/dist/examples/claude-code/billing.js +11 -0
  33. package/dist/examples/claude-code/claude-cli.d.ts +35 -0
  34. package/dist/examples/claude-code/claude-cli.js +15 -0
  35. package/dist/examples/claude-code/env.d.ts +1 -0
  36. package/dist/examples/claude-code/env.js +6 -0
  37. package/dist/examples/claude-code/index.d.ts +24 -0
  38. package/dist/examples/claude-code/index.js +149 -0
  39. package/dist/examples/claude-code/inert-mcp.d.ts +1 -0
  40. package/dist/examples/claude-code/inert-mcp.js +6 -0
  41. package/dist/examples/claude-code/model-catalog.d.ts +27 -0
  42. package/dist/examples/claude-code/model-catalog.js +12 -0
  43. package/dist/examples/claude-code/process.d.ts +22 -0
  44. package/dist/examples/claude-code/process.js +25 -0
  45. package/dist/examples/claude-code/replay.d.ts +4 -0
  46. package/dist/examples/claude-code/replay.js +11 -0
  47. package/dist/examples/claude-code/stream.d.ts +3 -0
  48. package/dist/examples/claude-code/stream.js +16 -0
  49. package/dist/examples/claude-code/transcript.d.ts +83 -0
  50. package/dist/examples/claude-code/transcript.js +23 -0
  51. package/dist/examples/claude-code/turn-relay.d.ts +48 -0
  52. package/dist/examples/claude-code/turn-relay.js +9 -0
  53. package/dist/examples/claude-code/wire.d.ts +372 -0
  54. package/dist/examples/claude-code/wire.js +18 -0
  55. package/dist/src/acp/connection.d.ts +24 -0
  56. package/dist/src/acp/connection.js +8 -0
  57. package/dist/src/acp/index.d.ts +54 -0
  58. package/dist/src/acp/index.js +1004 -0
  59. package/dist/src/acp/registry.d.ts +18 -0
  60. package/dist/src/acp/registry.js +8 -0
  61. package/dist/src/acp/thread.d.ts +46 -0
  62. package/dist/src/acp/thread.js +7 -0
  63. package/dist/src/acp/transcript.d.ts +8 -0
  64. package/dist/src/acp/transcript.js +11 -0
  65. package/dist/src/acp/translate.d.ts +33 -0
  66. package/dist/src/acp/translate.js +20 -0
  67. package/dist/src/approvals/approvals.d.ts +189 -0
  68. package/dist/src/approvals/approvals.js +143 -0
  69. package/dist/src/approvals/schema.d.ts +169 -0
  70. package/dist/src/approvals/schema.js +18 -0
  71. package/dist/src/bash-description.d.ts +30 -0
  72. package/dist/src/bash-description.js +18 -0
  73. package/dist/src/browser-tools.d.ts +25 -0
  74. package/dist/src/browser-tools.js +246 -0
  75. package/dist/src/canvas/canvas-compile.d.ts +48 -0
  76. package/dist/src/canvas/canvas-compile.js +8 -0
  77. package/dist/src/canvas/canvas-libraries.d.ts +32 -0
  78. package/dist/src/canvas/canvas-libraries.js +6 -0
  79. package/dist/src/canvas/canvas-preview.d.ts +107 -0
  80. package/dist/src/canvas/canvas-preview.js +12 -0
  81. package/dist/src/canvas/canvas-protocol.d.ts +184 -0
  82. package/dist/src/canvas/canvas-protocol.js +75 -0
  83. package/dist/src/canvas/canvas.d.ts +50 -0
  84. package/dist/src/canvas/canvas.js +221 -0
  85. package/dist/src/canvas/schema.d.ts +47 -0
  86. package/dist/src/canvas/schema.js +8 -0
  87. package/dist/src/claude-code-sdk/index.d.ts +35 -0
  88. package/dist/src/claude-code-sdk/index.js +368 -0
  89. package/dist/src/claude-code-sdk/session.d.ts +48 -0
  90. package/dist/src/claude-code-sdk/session.js +7 -0
  91. package/dist/src/claude-code-sdk/transcript.d.ts +19 -0
  92. package/dist/src/claude-code-sdk/transcript.js +15 -0
  93. package/dist/src/claude-code-sdk/translate.d.ts +18 -0
  94. package/dist/src/claude-code-sdk/translate.js +20 -0
  95. package/dist/src/client/mount.d.ts +44 -0
  96. package/dist/src/client/mount.js +252 -0
  97. package/dist/src/client/notifications.d.ts +35 -0
  98. package/dist/src/client/notifications.js +26 -0
  99. package/dist/src/client/presentation.d.ts +336 -0
  100. package/dist/src/client/presentation.js +373 -0
  101. package/dist/src/client/transcript-tui.d.ts +23 -0
  102. package/dist/src/client/transcript-tui.js +20 -0
  103. package/dist/src/client/transcript.d.ts +23 -0
  104. package/dist/src/client/transcript.js +51 -0
  105. package/dist/src/client.d.ts +53 -0
  106. package/dist/src/client.js +22 -0
  107. package/dist/src/codemode-runtime.d.ts +11 -0
  108. package/dist/src/codemode-runtime.js +10 -0
  109. package/dist/src/codemode-worker.d.ts +1 -0
  110. package/dist/src/codemode-worker.js +2 -0
  111. package/dist/src/codemode.d.ts +21 -0
  112. package/dist/src/codemode.js +170 -0
  113. package/dist/src/core.d.ts +43 -0
  114. package/dist/src/core.js +11 -0
  115. package/dist/src/openai-astra-context.d.ts +23 -0
  116. package/dist/src/openai-astra-context.js +14 -0
  117. package/dist/src/openai-compaction.d.ts +15 -0
  118. package/dist/src/openai-compaction.js +55 -0
  119. package/dist/src/question/client/questions-tui.d.ts +9 -0
  120. package/dist/src/question/client/questions-tui.js +19 -0
  121. package/dist/src/question/client/questions.d.ts +9 -0
  122. package/dist/src/question/client/questions.js +160 -0
  123. package/dist/src/question/question.d.ts +63 -0
  124. package/dist/src/question/question.js +9 -0
  125. package/dist/src/question/schema.d.ts +101 -0
  126. package/dist/src/question/schema.js +14 -0
  127. package/dist/src/rename.d.ts +78 -0
  128. package/dist/src/rename.js +78 -0
  129. package/dist/src/telemetry.d.ts +36 -0
  130. package/dist/src/telemetry.js +84 -0
  131. package/dist/src/web-search.d.ts +78 -0
  132. package/dist/src/web-search.js +219 -0
  133. package/package.json +190 -3
  134. package/README.md +0 -3
@@ -0,0 +1,170 @@
1
+ // src/codemode.ts
2
+ import { CodemodeSandbox } from "@earendil-works/pi-codemode";
3
+ import { renderToolSample } from "@earendil-works/pi-codemode/declarations";
4
+ import { CODEMODE_SOURCE_GRAMMAR, parseCodemodeSource } from "@earendil-works/pi-codemode/source";
5
+ import { dev } from "@nyte-ai/core";
6
+ import { isJson, isJsonObject, SdkError, standard } from "@nyte-ai/schema";
7
+ import { Type } from "typebox";
8
+ var DESCRIPTION = `Run JavaScript that calls other tools. The input is raw JavaScript (not JSON, no code fence), run as an async function body in a QuickJS sandbox: top-level \`await\` and \`return\` work. No Node, file system, network, or timers.
9
+ - \`await tools.<name>({ ...args })\` resolves to the tool's output, or its text, and rejects with an Error on failure.
10
+ - Optional first line: \`// @options: {"timeout_ms": 60000}\`
11
+ - \`text(value)\`, \`console.log(...)\` and \`return\` add output; \`store(key, value)\` and \`load(key)\` keep JSON values across codemode calls in this session.
12
+ - \`ALL_TOOLS\`, \`searchTools(query, { limit?, namespace? })\` and \`describeTool(name)\` find tools and their declarations.`;
13
+ var SUMMARY_CHARS = 160;
14
+ var parameters = standard(Type.Object({ code: Type.String({ description: "Raw JavaScript source." }) }));
15
+ function codemodePlugin(runtime) {
16
+ return {
17
+ id: "codemode",
18
+ activate(api) {
19
+ api.contribute.tools.add(codemode(api, runtime));
20
+ api.contribute.prompt.add((draft, siblings) => {
21
+ const reachable = siblings.tools.list().flatMap((tool) => tool.exposure === "code" || tool.exposure === "deferred" ? [`- ${tool.name}: ${summarize(tool.description)}`] : []).toSorted();
22
+ if (reachable.length === 0)
23
+ return;
24
+ draft.set("codemode", {
25
+ id: "codemode",
26
+ order: 96,
27
+ text: [
28
+ "Tools you reach only from a codemode script, as `await tools.<name>(args)`; `describeTool(name)` inside a script returns a tool's arguments:",
29
+ ...reachable
30
+ ].join(`
31
+ `)
32
+ });
33
+ });
34
+ }
35
+ };
36
+ }
37
+ function summarize(description) {
38
+ const [line = ""] = description.trim().split(`
39
+ `);
40
+ return line.length > SUMMARY_CHARS ? `${line.slice(0, SUMMARY_CHARS)}…` : line;
41
+ }
42
+ function codemode(api, runtime) {
43
+ return {
44
+ name: "codemode",
45
+ description: DESCRIPTION,
46
+ parameters,
47
+ grammar: { kind: "lark", source: CODEMODE_SOURCE_GRAMMAR },
48
+ class: () => ({ kind: "custom", label: "Running a script" }),
49
+ effects: "none",
50
+ approval: "never",
51
+ replay: "never",
52
+ async execute(args, invocation) {
53
+ const { code, options } = parseCodemodeSource(args.code);
54
+ const callable = invocation.tools.list().filter((info) => info.name !== "codemode" && info.exposure !== "hidden");
55
+ const stored = await api.storage.get("store");
56
+ if (stored !== undefined && !isJsonObject(stored))
57
+ throw new SdkError("internal", "Codemode's stored values are not a JSON object.");
58
+ const sandbox = new CodemodeSandbox({
59
+ ...runtime,
60
+ tools: callable.map((info) => bridge(info, invocation)),
61
+ globals: discovery(callable),
62
+ timeoutMs: options.timeoutMs ?? 300000,
63
+ memoryLimitBytes: 256 * 1024 * 1024
64
+ });
65
+ dev("codemode", "run", { call: invocation.call, tools: callable.length });
66
+ let result;
67
+ try {
68
+ result = await sandbox.execute(code, { signal: invocation.signal, store: stored ?? {} });
69
+ } finally {
70
+ await sandbox.close();
71
+ }
72
+ dev("codemode", "end", { call: invocation.call, ok: result.ok, calls: result.calls.length });
73
+ if (!result.ok)
74
+ throw new Error(`${result.error.kind === "script" ? result.error.stack ?? result.error.message : `Script ${result.error.kind}: ${result.error.message}`}
75
+ ${calls(result)}`);
76
+ const writes = Object.entries(result.storeWrites.set).flatMap(([key, value]) => isJson(value) ? [[key, value]] : []);
77
+ if (writes.length > 0 || result.storeWrites.delete.length > 0) {
78
+ const next = { ...stored, ...Object.fromEntries(writes) };
79
+ for (const key of result.storeWrites.delete)
80
+ delete next[key];
81
+ await api.storage.set("store", next);
82
+ }
83
+ const content = [];
84
+ for (const item of result.output) {
85
+ if (item.type === "text")
86
+ content.push({ kind: "text", text: item.text });
87
+ else
88
+ content.push({
89
+ kind: "file",
90
+ blob: await invocation.env.files.upload(once(Uint8Array.fromBase64(item.data))),
91
+ mime: item.mimeType
92
+ });
93
+ }
94
+ if (result.value !== undefined)
95
+ content.push({
96
+ kind: "text",
97
+ text: typeof result.value === "string" ? result.value : JSON.stringify(result.value)
98
+ });
99
+ return {
100
+ content: content.length === 0 ? [{ kind: "text", text: "The script produced no output." }] : content
101
+ };
102
+ }
103
+ };
104
+ }
105
+ function bridge(info, invocation) {
106
+ let sequence = 0;
107
+ return {
108
+ name: info.name,
109
+ description: info.description,
110
+ inputSchema: info.parameters,
111
+ outputSchema: info.output ?? { type: "string" },
112
+ async execute(args, { signal }) {
113
+ const key = `codemode:${info.name}:${sequence++}`;
114
+ return unwrapToolOutcome(await invocation.tools.execute(info.name, isJson(args) ? args : null, { key, signal }));
115
+ }
116
+ };
117
+ }
118
+ function unwrapToolOutcome(outcome) {
119
+ if (outcome.kind === "ok")
120
+ return outcome.output ?? outcome.content.flatMap((item) => item.kind === "text" ? [item.text] : []).join(`
121
+ `);
122
+ throw new Error(outcome.kind === "failed" ? outcome.message : outcome.kind === "rejected" ? `Rejected: ${outcome.reason}` : `The call was ${outcome.kind}.`);
123
+ }
124
+ function discovery(tools) {
125
+ return [
126
+ {
127
+ name: "searchTools",
128
+ spread: true,
129
+ execute(args) {
130
+ const [query, options] = Array.isArray(args) ? args : [];
131
+ const words = new Set(String(query).toLowerCase().split(/[^a-z0-9]+/).filter((word) => word.length > 1));
132
+ const limit = typeof options === "object" && options !== null && "limit" in options && typeof options.limit === "number" ? options.limit : 8;
133
+ const namespace = typeof options === "object" && options !== null && "namespace" in options && typeof options.namespace === "string" ? options.namespace : null;
134
+ return tools.filter((info) => namespace === null || info.namespace === namespace).map((info) => ({
135
+ info,
136
+ score: `${info.name} ${info.description}`.toLowerCase().split(/[^a-z0-9]+/).filter((word) => words.has(word)).length
137
+ })).filter((entry) => entry.score > 0).toSorted((left, right) => right.score - left.score).slice(0, limit).map(({ info }) => ({
138
+ name: info.name,
139
+ namespace: info.namespace,
140
+ description: info.description
141
+ }));
142
+ }
143
+ },
144
+ {
145
+ name: "describeTool",
146
+ execute(name) {
147
+ const info = tools.find((candidate) => candidate.name === name);
148
+ if (info === undefined)
149
+ throw new Error(`No tool is named ${String(name)}.`);
150
+ return renderToolSample({
151
+ name: info.name,
152
+ description: info.description,
153
+ inputSchema: info.parameters,
154
+ outputSchema: info.output ?? { type: "string" }
155
+ });
156
+ }
157
+ }
158
+ ];
159
+ }
160
+ function calls(result) {
161
+ return result.calls.length === 0 ? "No tool calls were made." : `Tool calls made before the failure (not undone): ${result.calls.map((call) => `${call.name} (${call.status})`).join(", ")}`;
162
+ }
163
+ async function* once(bytes) {
164
+ yield bytes;
165
+ }
166
+ var codemode_default = codemodePlugin({});
167
+ export {
168
+ codemodePlugin,
169
+ codemode_default as default
170
+ };
@@ -0,0 +1,43 @@
1
+ import type { HookEntry as SideHookEntry, HookHandler as SideHookHandler, HookName as SideHookName, Plugin as CorePlugin, PluginApi as CorePluginApi } from "@nyte-ai/core";
2
+ export { branchSummary, compaction, definePart, isPart, text, thinking, tool } from "@nyte-ai/core";
3
+ export type { ActionContext, Agent, Command, Durable, HookTable, ModelContextPolicy, Part, PartDefinition, PartState, PromptSection, Setting, SettingDefinition, Skill, ToolDefinition, ToolInvocation, } from "@nyte-ai/core";
4
+ export type { CompactionPlan, Decision, ModelRequest, Submission, ToolCall, Transcript, } from "@nyte-ai/schema";
5
+ /**
6
+ * A core plugin: per session on the host, with tools, prompt sections,
7
+ * agents, parts, commands, settings and core hooks. Author one as an object
8
+ * literal and check it with `satisfies Plugin`.
9
+ *
10
+ * @category plugins
11
+ * @since 0.1.0
12
+ */
13
+ export type Plugin = CorePlugin<"core">;
14
+ /**
15
+ * What a core plugin's `activate` and hook handlers receive: the session,
16
+ * its environment, the registries, storage and `request`.
17
+ *
18
+ * @category plugins
19
+ * @since 0.1.0
20
+ */
21
+ export type PluginApi = CorePluginApi<"core">;
22
+ /**
23
+ * Names a hook a core plugin may handle.
24
+ *
25
+ * @category hooks
26
+ * @since 0.1.0
27
+ */
28
+ export type HookName = SideHookName<"core">;
29
+ /**
30
+ * Returns a core hook handler's signature, for a helper factored out of a
31
+ * plugin's `hooks`.
32
+ *
33
+ * @category hooks
34
+ * @since 0.1.0
35
+ */
36
+ export type HookHandler<N extends HookName> = SideHookHandler<"core", N>;
37
+ /**
38
+ * Returns a core hook entry: a handler, or a handler with an order.
39
+ *
40
+ * @category hooks
41
+ * @since 0.1.0
42
+ */
43
+ export type HookEntry<N extends HookName> = SideHookEntry<"core", N>;
@@ -0,0 +1,11 @@
1
+ // src/core.ts
2
+ import { branchSummary, compaction, definePart, isPart, text, thinking, tool } from "@nyte-ai/core";
3
+ export {
4
+ branchSummary,
5
+ compaction,
6
+ definePart,
7
+ isPart,
8
+ text,
9
+ thinking,
10
+ tool
11
+ };
@@ -0,0 +1,23 @@
1
+ import type { ModelContextPolicy } from "@nyte-ai/core";
2
+ /**
3
+ * The context policy of `gpt-6-astra` on OpenAI and OpenAI Codex: a window
4
+ * of one million tokens, compacted at 400 000.
5
+ *
6
+ * @category plugins
7
+ * @since 0.1.0
8
+ */
9
+ export declare const astra: readonly ModelContextPolicy[];
10
+ /**
11
+ * Gives the astra models their context window and compaction threshold,
12
+ * folded into their `ModelInfo` and the sessions that run them.
13
+ *
14
+ * @category plugins
15
+ * @since 0.1.0
16
+ */
17
+ declare const _default: {
18
+ id: string;
19
+ contribute: {
20
+ modelContext: readonly ModelContextPolicy[];
21
+ };
22
+ };
23
+ export default _default;
@@ -0,0 +1,14 @@
1
+ // src/openai-astra-context.ts
2
+ var astra = ["openai", "openai-codex"].map((provider) => ({
3
+ model: { provider, id: "gpt-6-astra" },
4
+ contextWindow: 1e6,
5
+ compactAt: 400000
6
+ }));
7
+ var openai_astra_context_default = {
8
+ id: "openai-astra-context",
9
+ contribute: { modelContext: astra }
10
+ };
11
+ export {
12
+ astra,
13
+ openai_astra_context_default as default
14
+ };
@@ -0,0 +1,15 @@
1
+ import type { Models } from "@nyte-ai/ai";
2
+ import type { Plugin } from "@nyte-ai/plugin/core";
3
+ /**
4
+ * Returns the plugin that compacts through OpenAI's own endpoint. On
5
+ * `before_compaction`, when the session's model is OpenAI Responses (an API
6
+ * key) or OpenAI Codex Responses (a ChatGPT account), it sends the messages
7
+ * to summarise to the provider's compact endpoint and supplies the opaque
8
+ * window it returns as the plan's `material`; core writes it without a
9
+ * summary request. Any other model, or a provider without credentials,
10
+ * leaves the plan to core. `models` is the host's, for credentials.
11
+ *
12
+ * @category plugins
13
+ * @since 0.1.0
14
+ */
15
+ export declare function openaiCompaction(models: Pick<Models, "getModel" | "getAuth">): Plugin;
@@ -0,0 +1,55 @@
1
+ // src/openai-compaction.ts
2
+ import {
3
+ compactOpenAICodexContext,
4
+ compactOpenAIResponsesContext,
5
+ providerIdentity
6
+ } from "@nyte-ai/ai";
7
+ function openaiCompaction(models) {
8
+ return {
9
+ id: "openai-compaction",
10
+ hooks: {
11
+ before_compaction: async (plan, { signal }) => {
12
+ const model = models.getModel(plan.model.provider, plan.model.id);
13
+ const responses = model?.provider === "openai" && model.api === "openai-responses";
14
+ const codex = model?.provider === "openai-codex" && model.api === "openai-codex-responses";
15
+ if (plan.result !== null || model === undefined || !responses && !codex)
16
+ return plan;
17
+ const auth = await models.getAuth(model, { signal });
18
+ if (auth === undefined)
19
+ return plan;
20
+ const base = { ...model, baseUrl: auth.auth.baseUrl ?? model.baseUrl };
21
+ const options = { apiKey: auth.auth.apiKey, headers: auth.auth.headers, signal };
22
+ const context = {
23
+ messages: [
24
+ ...plan.summarise,
25
+ ...plan.instructions === null ? [] : [{ role: "system", content: plan.instructions, timestamp: Date.now() }]
26
+ ]
27
+ };
28
+ const compacted = codex ? await compactOpenAICodexContext({ ...base, api: "openai-codex-responses" }, context, options) : await compactOpenAIResponsesContext({ ...base, api: "openai-responses" }, context, options);
29
+ return {
30
+ ...plan,
31
+ result: {
32
+ kind: "material",
33
+ ...providerIdentity(model),
34
+ data: compacted.data,
35
+ usage: compacted.usage === undefined ? null : sessionUsage(compacted.usage)
36
+ }
37
+ };
38
+ }
39
+ }
40
+ };
41
+ }
42
+ function sessionUsage(usage) {
43
+ return {
44
+ input: usage.input,
45
+ output: usage.output,
46
+ cacheRead: usage.cacheRead,
47
+ cacheWrite: usage.cacheWrite,
48
+ reasoning: usage.reasoning ?? null,
49
+ total: usage.totalTokens,
50
+ cost: usage.cost
51
+ };
52
+ }
53
+ export {
54
+ openaiCompaction
55
+ };
@@ -0,0 +1,9 @@
1
+ import type { Renderer } from "@nyte-ai/plugin/client";
2
+ export declare const questionRenderers: readonly Renderer[];
3
+ declare const _default: {
4
+ id: string;
5
+ contribute: {
6
+ renderers: readonly Renderer<import("@nyte-ai/plugin/client").PartDefinition<unknown, import("@nyte-ai/core").ActionSchemas>, unknown>[];
7
+ };
8
+ };
9
+ export default _default;
@@ -0,0 +1,19 @@
1
+ import {
2
+ question3
3
+ } from "../../../chunks/billing-6z2kgtyt.js";
4
+
5
+ // src/question/client/questions-tui.ts
6
+ import { Box, Text } from "@opentui/core";
7
+ import { defineRenderer } from "@nyte-ai/plugin/client";
8
+ var unreadable = (kind) => Text({ content: `This ${kind} part cannot be shown.` });
9
+ var questionRenderers = [
10
+ defineRenderer(question3, "tui", (state) => Box({ border: true, title: "Questions", flexDirection: "column" }, ...state.questions.map((item, index) => Box({ flexDirection: "column" }, Text({ content: `${item.header}: ${item.question}` }), ...item.options.map((option) => Text({ content: `${option.label}: ${option.description}` })), ...state.answers === null ? [] : [Text({ content: `Answer: ${state.answers[index].join(", ") || "Unanswered"}` })]))), unreadable)
11
+ ];
12
+ var questions_tui_default = {
13
+ id: "questions-tui",
14
+ contribute: { renderers: questionRenderers }
15
+ };
16
+ export {
17
+ questions_tui_default as default,
18
+ questionRenderers
19
+ };
@@ -0,0 +1,9 @@
1
+ import type { Renderer } from "@nyte-ai/plugin/client";
2
+ export declare const questionRenderers: readonly Renderer[];
3
+ declare const _default: {
4
+ id: string;
5
+ contribute: {
6
+ renderers: readonly Renderer<import("@nyte-ai/plugin/client").PartDefinition<unknown, import("@nyte-ai/core").ActionSchemas>, unknown>[];
7
+ };
8
+ };
9
+ export default _default;
@@ -0,0 +1,160 @@
1
+ import {
2
+ question3
3
+ } from "../../../chunks/billing-6z2kgtyt.js";
4
+
5
+ // src/question/client/questions.tsx
6
+ import { useId, useRef, useState } from "react";
7
+ import { defineRenderer } from "@nyte-ai/plugin/client";
8
+ import { jsxDEV } from "react/jsx-dev-runtime";
9
+ var unreadable = (kind) => /* @__PURE__ */ jsxDEV("div", {
10
+ "data-part": kind,
11
+ children: [
12
+ "This ",
13
+ kind,
14
+ " part cannot be shown."
15
+ ]
16
+ }, undefined, true, undefined, this);
17
+ function QuestionForm({
18
+ questions,
19
+ act
20
+ }) {
21
+ const id = useId();
22
+ const [selected, setSelected] = useState(() => questions.map(() => []));
23
+ const [custom, setCustom] = useState(() => questions.map(() => ""));
24
+ const [status, setStatus] = useState({ kind: "editing" });
25
+ const submitting = useRef(false);
26
+ const blocked = status.kind === "sending" || status.kind === "sent";
27
+ const submit = async () => {
28
+ if (blocked || submitting.current)
29
+ return;
30
+ submitting.current = true;
31
+ setStatus({ kind: "sending" });
32
+ const answers = questions.map((item, index) => {
33
+ const typed = custom[index].trim();
34
+ const choices = selected[index];
35
+ if (typed === "" || choices.includes(typed))
36
+ return choices;
37
+ return item.multiple ? [...choices, typed] : [typed];
38
+ });
39
+ try {
40
+ const outcome = await act("answer", { answers });
41
+ setStatus(outcome.kind === "ok" ? { kind: "sent" } : {
42
+ kind: "failed",
43
+ message: outcome.kind === "rejected" ? outcome.reason : "These questions are no longer waiting."
44
+ });
45
+ } catch {
46
+ setStatus({ kind: "failed", message: "Couldn't send your answers. Try again." });
47
+ }
48
+ submitting.current = false;
49
+ };
50
+ return /* @__PURE__ */ jsxDEV("form", {
51
+ "data-part": "ask/question",
52
+ "aria-label": "Questions",
53
+ onSubmit: (event) => {
54
+ event.preventDefault();
55
+ submit();
56
+ },
57
+ children: [
58
+ questions.map((item, index) => /* @__PURE__ */ jsxDEV("fieldset", {
59
+ disabled: blocked,
60
+ children: [
61
+ /* @__PURE__ */ jsxDEV("legend", {
62
+ children: item.header
63
+ }, undefined, false, undefined, this),
64
+ /* @__PURE__ */ jsxDEV("p", {
65
+ children: item.question
66
+ }, undefined, false, undefined, this),
67
+ item.options.map((option) => /* @__PURE__ */ jsxDEV("label", {
68
+ children: [
69
+ /* @__PURE__ */ jsxDEV("input", {
70
+ type: item.multiple ? "checkbox" : "radio",
71
+ name: `${id}-${index}`,
72
+ value: option.label,
73
+ checked: selected[index].includes(option.label),
74
+ onChange: () => {
75
+ setSelected((current) => current.map((choices, position) => {
76
+ if (position !== index)
77
+ return choices;
78
+ if (!item.multiple)
79
+ return [option.label];
80
+ return choices.includes(option.label) ? choices.filter((choice) => choice !== option.label) : [...choices, option.label];
81
+ }));
82
+ if (!item.multiple)
83
+ setCustom((current) => current.map((typed, position) => position === index ? "" : typed));
84
+ }
85
+ }, undefined, false, undefined, this),
86
+ /* @__PURE__ */ jsxDEV("span", {
87
+ children: option.label
88
+ }, undefined, false, undefined, this),
89
+ /* @__PURE__ */ jsxDEV("span", {
90
+ children: option.description
91
+ }, undefined, false, undefined, this)
92
+ ]
93
+ }, option.label, true, undefined, this)),
94
+ /* @__PURE__ */ jsxDEV("label", {
95
+ children: [
96
+ "Type your own answer",
97
+ /* @__PURE__ */ jsxDEV("textarea", {
98
+ value: custom[index],
99
+ onChange: ({ currentTarget }) => {
100
+ const typed = currentTarget.value;
101
+ setCustom((current) => current.map((value, position) => position === index ? typed : value));
102
+ if (!item.multiple && typed.trim() !== "")
103
+ setSelected((current) => current.map((choices, position) => position === index ? [] : choices));
104
+ }
105
+ }, undefined, false, undefined, this)
106
+ ]
107
+ }, undefined, true, undefined, this)
108
+ ]
109
+ }, index, true, undefined, this)),
110
+ /* @__PURE__ */ jsxDEV("button", {
111
+ type: "submit",
112
+ disabled: blocked,
113
+ children: status.kind === "sending" ? "Sending answers…" : "Submit answers"
114
+ }, undefined, false, undefined, this),
115
+ status.kind === "failed" && /* @__PURE__ */ jsxDEV("p", {
116
+ role: "alert",
117
+ children: status.message
118
+ }, undefined, false, undefined, this),
119
+ status.kind === "sent" && /* @__PURE__ */ jsxDEV("p", {
120
+ role: "status",
121
+ children: "Answers sent."
122
+ }, undefined, false, undefined, this)
123
+ ]
124
+ }, undefined, true, undefined, this);
125
+ }
126
+ var questionRenderers = [
127
+ defineRenderer(question3, "react", (state, act) => {
128
+ const answers = state.answers;
129
+ if (answers !== null)
130
+ return /* @__PURE__ */ jsxDEV("div", {
131
+ "data-part": "ask/question",
132
+ "aria-label": "Answers",
133
+ children: state.questions.map((item, index) => /* @__PURE__ */ jsxDEV("section", {
134
+ children: [
135
+ /* @__PURE__ */ jsxDEV("h3", {
136
+ children: item.header
137
+ }, undefined, false, undefined, this),
138
+ /* @__PURE__ */ jsxDEV("p", {
139
+ children: item.question
140
+ }, undefined, false, undefined, this),
141
+ /* @__PURE__ */ jsxDEV("p", {
142
+ children: [
143
+ "Answer: ",
144
+ answers[index].join(", ") || "Unanswered"
145
+ ]
146
+ }, undefined, true, undefined, this)
147
+ ]
148
+ }, index, true, undefined, this))
149
+ }, undefined, false, undefined, this);
150
+ return /* @__PURE__ */ jsxDEV(QuestionForm, {
151
+ questions: state.questions,
152
+ act
153
+ }, JSON.stringify(state.questions), false, undefined, this);
154
+ }, unreadable)
155
+ ];
156
+ var questions_default = { id: "questions", contribute: { renderers: questionRenderers } };
157
+ export {
158
+ questions_default as default,
159
+ questionRenderers
160
+ };
@@ -0,0 +1,63 @@
1
+ import type { ToolDefinition } from "@nyte-ai/core";
2
+ export declare const question: import("@nyte-ai/core").PartDefinition<{
3
+ answers: string[][] | null;
4
+ questions: {
5
+ multiple?: boolean | undefined;
6
+ options: {
7
+ description: string;
8
+ label: string;
9
+ }[];
10
+ question: string;
11
+ header: string;
12
+ }[];
13
+ }, {
14
+ answer: {
15
+ input: import("@nyte-ai/schema").Schema<{
16
+ answers: string[][];
17
+ }>;
18
+ };
19
+ }>;
20
+ /**
21
+ * Contributes the question tool and its grouped modal. The durable wait
22
+ * resumes after one complete submission from any client.
23
+ *
24
+ * @category plugins
25
+ * @since 0.1.0
26
+ */
27
+ declare const _default: {
28
+ id: string;
29
+ contribute: {
30
+ parts: import("@nyte-ai/core").PartDefinition<{
31
+ answers: string[][] | null;
32
+ questions: {
33
+ multiple?: boolean | undefined;
34
+ options: {
35
+ description: string;
36
+ label: string;
37
+ }[];
38
+ question: string;
39
+ header: string;
40
+ }[];
41
+ }, {
42
+ answer: {
43
+ input: import("@nyte-ai/schema").Schema<{
44
+ answers: string[][];
45
+ }>;
46
+ };
47
+ }>[];
48
+ tools: ToolDefinition<{
49
+ questions: {
50
+ multiple?: boolean | undefined;
51
+ options: {
52
+ description: string;
53
+ label: string;
54
+ }[];
55
+ question: string;
56
+ header: string;
57
+ }[];
58
+ }, {
59
+ answers: string[][] | null;
60
+ }>[];
61
+ };
62
+ };
63
+ export default _default;
@@ -0,0 +1,9 @@
1
+ import {
2
+ question2,
3
+ question_default
4
+ } from "../../chunks/billing-3j77ss7y.js";
5
+ import"../../chunks/billing-6z2kgtyt.js";
6
+ export {
7
+ question_default as default,
8
+ question2 as question
9
+ };