@nyte-ai/plugin 0.0.25-beta.1 → 0.0.25-nightly.20261101.40

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 (88) hide show
  1. package/THIRD-PARTY-NOTICES.md +49 -32
  2. package/dist/chunks/bash-description-0ah30s12.js +33 -0
  3. package/dist/chunks/bash-description-4h0hnsv4.js +68 -0
  4. package/dist/chunks/{bash-description-dnvgk30y.js → bash-description-4rfavmha.js} +32 -1
  5. package/dist/chunks/bash-description-5dpf5hpt.js +724 -0
  6. package/dist/chunks/{bash-description-yyd9jznf.js → bash-description-94km1hm2.js} +1 -1
  7. package/dist/chunks/{bash-description-svrhh5a5.js → bash-description-99k8z2r7.js} +3 -2
  8. package/dist/chunks/bash-description-9gw9ets8.js +162 -0
  9. package/dist/chunks/{bash-description-h13r0byk.js → bash-description-axnga0jz.js} +3 -3
  10. package/dist/chunks/bash-description-b78pre8c.js +147 -0
  11. package/dist/chunks/{bash-description-ye3wk5r3.js → bash-description-bas41ptb.js} +6 -24
  12. package/dist/chunks/{bash-description-2v3g7rd9.js → bash-description-bj5yh7tr.js} +26 -64
  13. package/dist/chunks/{bash-description-6z2kgtyt.js → bash-description-bkhr9zrz.js} +4 -4
  14. package/dist/chunks/{bash-description-hg64tqf1.js → bash-description-f754ge33.js} +49 -3
  15. package/dist/chunks/{bash-description-zz15raxk.js → bash-description-ff18794t.js} +1 -1
  16. package/dist/chunks/{bash-description-wmcbg6fw.js → bash-description-g7gfy7nw.js} +1 -1
  17. package/dist/chunks/{bash-description-1neewp76.js → bash-description-hp4rb8k4.js} +4 -3
  18. package/dist/chunks/bash-description-myvnmtt2.js +125 -0
  19. package/dist/chunks/{bash-description-9nn3yp18.js → bash-description-q2v8wbn8.js} +9 -1
  20. package/dist/chunks/bash-description-qwyy182r.js +452 -0
  21. package/dist/chunks/bash-description-rxpx004v.js +295 -0
  22. package/dist/chunks/{bash-description-eqp7ap2w.js → bash-description-z1581a29.js} +23 -9
  23. package/dist/src/acp/connection.d.ts +3 -1
  24. package/dist/src/acp/connection.js +3 -3
  25. package/dist/src/acp/index.d.ts +7 -4
  26. package/dist/src/acp/index.js +41 -8
  27. package/dist/src/acp/registry.d.ts +9 -0
  28. package/dist/src/acp/registry.js +5 -3
  29. package/dist/src/acp/thread.js +2 -2
  30. package/dist/src/acp/transcript.js +2 -2
  31. package/dist/src/acp/translate.d.ts +10 -2
  32. package/dist/src/acp/translate.js +3 -1
  33. package/dist/src/approvals/approvals.d.ts +1 -1
  34. package/dist/src/approvals/approvals.js +2 -2
  35. package/dist/src/approvals/schema.d.ts +3 -3
  36. package/dist/src/approvals/schema.js +1 -1
  37. package/dist/src/browser-tools.js +8 -2
  38. package/dist/src/canvas/canvas-compile.js +2 -2
  39. package/dist/src/canvas/canvas-preview.js +2 -2
  40. package/dist/src/canvas/canvas-protocol.d.ts +46 -0
  41. package/dist/src/canvas/canvas-protocol.js +11 -1
  42. package/dist/src/canvas/canvas.d.ts +17 -3
  43. package/dist/src/canvas/canvas.js +75 -31
  44. package/dist/src/canvas/schema.d.ts +28 -7
  45. package/dist/src/canvas/schema.js +2 -2
  46. package/dist/src/claude-code-sdk/index.d.ts +0 -10
  47. package/dist/src/claude-code-sdk/index.js +19 -179
  48. package/dist/src/claude-code-sdk/session.d.ts +22 -23
  49. package/dist/src/claude-code-sdk/session.js +6 -3
  50. package/dist/src/claude-code-sdk/transcript.d.ts +0 -6
  51. package/dist/src/claude-code-sdk/transcript.js +2 -4
  52. package/dist/src/claude-code-sdk/translate.d.ts +1 -5
  53. package/dist/src/claude-code-sdk/translate.js +2 -8
  54. package/dist/src/client/mount.d.ts +4 -2
  55. package/dist/src/client/mount.js +3 -0
  56. package/dist/src/client/notifications.d.ts +12 -4
  57. package/dist/src/client/notifications.js +25 -10
  58. package/dist/src/client/presentation.d.ts +138 -8
  59. package/dist/src/client/presentation.js +86 -371
  60. package/dist/src/codemode.js +151 -46
  61. package/dist/src/core.d.ts +1 -1
  62. package/dist/src/question/client/questions-tui.js +3 -3
  63. package/dist/src/question/client/questions.js +3 -3
  64. package/dist/src/question/question.js +84 -5
  65. package/dist/src/question/schema.js +3 -3
  66. package/dist/src/rename.d.ts +7 -35
  67. package/dist/src/rename.js +115 -48
  68. package/dist/src/subagents.d.ts +30 -0
  69. package/dist/src/subagents.js +323 -0
  70. package/dist/src/tool-search.d.ts +49 -0
  71. package/dist/src/tool-search.js +14 -0
  72. package/dist/src/web/body.d.ts +3 -0
  73. package/dist/src/web/body.js +6 -0
  74. package/dist/src/web/fetch.d.ts +16 -0
  75. package/dist/src/web/fetch.js +8 -0
  76. package/dist/src/web/html-markdown.d.ts +9 -0
  77. package/dist/src/web/html-markdown.js +10 -0
  78. package/dist/src/web/index.d.ts +24 -0
  79. package/dist/src/web/index.js +93 -0
  80. package/dist/src/web/providers.d.ts +60 -0
  81. package/dist/src/web/providers.js +11 -0
  82. package/dist/src/web/search.d.ts +21 -0
  83. package/dist/src/web/search.js +6 -0
  84. package/package.json +16 -7
  85. package/dist/chunks/bash-description-3j77ss7y.js +0 -86
  86. package/dist/chunks/bash-description-wbe8w0te.js +0 -530
  87. package/dist/src/web-search.d.ts +0 -78
  88. package/dist/src/web-search.js +0 -219
@@ -1,16 +1,23 @@
1
+ import {
2
+ DEFAULT_SEARCH_LIMIT2,
3
+ createToolSearchDocument2,
4
+ rankTools2
5
+ } from "../chunks/bash-description-b78pre8c.js";
6
+
1
7
  // src/codemode.ts
2
8
  import { CodemodeSandbox } from "@earendil-works/pi-codemode";
3
- import { renderToolSample } from "@earendil-works/pi-codemode/declarations";
9
+ import { renderToolSample, toCodemodeIdentifier } from "@earendil-works/pi-codemode/declarations";
4
10
  import { CODEMODE_SOURCE_GRAMMAR, parseCodemodeSource } from "@earendil-works/pi-codemode/source";
5
- import { dev } from "@nyte-ai/core";
11
+ import { estimateTextTokens } from "@nyte-ai/ai/utils/estimate";
12
+ import { attachFile, dev } from "@nyte-ai/core";
6
13
  import { isJson, isJsonObject, SdkError, standard } from "@nyte-ai/schema";
7
14
  import { Type } from "typebox";
8
15
  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
16
  - \`await tools.<name>({ ...args })\` resolves to the tool's output, or its text, and rejects with an Error on failure.
10
17
  - Optional first line: \`// @options: {"timeout_ms": 60000}\`
11
18
  - \`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;
19
+ - \`ALL_TOOLS\`, \`await searchTools(query, { limit?, namespace? })\`, \`await describeTool(name)\` and \`await describeNamespace(name)\` find unlisted tools, such as MCP tools, and their declarations.`;
20
+ var LISTING_TOKENS = 3000;
14
21
  var parameters = standard(Type.Object({ code: Type.String({ description: "Raw JavaScript source." }) }));
15
22
  function codemodePlugin(runtime) {
16
23
  return {
@@ -18,32 +25,94 @@ function codemodePlugin(runtime) {
18
25
  activate(api) {
19
26
  api.contribute.tools.add(codemode(api, runtime));
20
27
  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
- });
28
+ const text = listTools(siblings.tools.list());
29
+ if (text !== null)
30
+ draft.set("codemode", { id: "codemode", order: 96, text });
33
31
  });
34
32
  }
35
33
  };
36
34
  }
37
- function summarize(description) {
38
- const [line = ""] = description.trim().split(`
35
+ function listTools(definitions) {
36
+ const sections = definitions.flatMap((definition) => {
37
+ if (definition.exposure !== "code")
38
+ return [];
39
+ const inputSchema = toJsonSchema(definition.parameters, "input");
40
+ const outputSchema = definition.output === undefined ? { type: "string" } : toJsonSchema(definition.output, "output");
41
+ if (inputSchema === null || outputSchema === null)
42
+ return [];
43
+ const id = toCodemodeIdentifier(definition.name);
44
+ const sample = renderToolSample({
45
+ name: definition.name,
46
+ description: definition.description,
47
+ inputSchema,
48
+ outputSchema
49
+ }).trim();
50
+ const section = `### \`${id}\`${id === definition.name ? "" : ` (\`${definition.name}\`)`}
51
+ ${sample}`;
52
+ return [
53
+ {
54
+ namespace: definition.namespace,
55
+ name: definition.name,
56
+ section,
57
+ cost: estimateTextTokens(section)
58
+ }
59
+ ];
60
+ });
61
+ if (sections.length === 0)
62
+ return null;
63
+ const groups = [
64
+ ...Map.groupBy(sections, (entry) => entry.namespace?.name ?? "").entries()
65
+ ].toSorted((left, right) => left[0].localeCompare(right[0])).map((pair) => ({ namespace: pair[1][0]?.namespace, entries: pair[1] }));
66
+ const shown = selectListed(groups, LISTING_TOKENS);
67
+ return [
68
+ "Tools you reach only from a codemode script, as `await tools.<name>(args)`:",
69
+ ...groups.flatMap((group) => {
70
+ const visible = group.entries.filter((entry) => shown.has(entry.name));
71
+ if (group.namespace === undefined)
72
+ return visible.map((entry) => entry.section);
73
+ const listing = visible.length === group.entries.length ? "" : visible.length === 0 ? " (tools not listed)" : " (some tools not listed)";
74
+ const description = group.namespace.description?.trim() ?? "";
75
+ return [
76
+ `## ${group.namespace.name}${listing}${description === "" ? "" : `
77
+ ${description}`}`,
78
+ ...visible.map((entry) => entry.section)
79
+ ];
80
+ })
81
+ ].join(`
82
+
39
83
  `);
40
- return line.length > SUMMARY_CHARS ? `${line.slice(0, SUMMARY_CHARS)}…` : line;
84
+ }
85
+ function selectListed(groups, budget) {
86
+ const queues = groups.map((group) => group.entries.toSorted((a, b) => a.cost - b.cost));
87
+ const shown = new Set;
88
+ let remaining = budget;
89
+ let active = queues.filter((queue) => queue.length > 0);
90
+ while (active.length > 0)
91
+ active = active.filter((queue) => {
92
+ const next = queue[0];
93
+ if (next === undefined || next.cost > remaining)
94
+ return false;
95
+ remaining -= next.cost;
96
+ shown.add(next.name);
97
+ queue.shift();
98
+ return queue.length > 0;
99
+ });
100
+ return shown;
101
+ }
102
+ function toJsonSchema(schema, direction) {
103
+ try {
104
+ const converted = schema["~standard"].jsonSchema[direction]({ target: "draft-2020-12" });
105
+ return isJson(converted) && isJsonObject(converted) ? converted : null;
106
+ } catch {
107
+ return null;
108
+ }
41
109
  }
42
110
  function codemode(api, runtime) {
43
111
  return {
44
112
  name: "codemode",
45
113
  description: DESCRIPTION,
46
114
  parameters,
115
+ exposure: "model-only",
47
116
  grammar: { kind: "lark", source: CODEMODE_SOURCE_GRAMMAR },
48
117
  class: () => ({ kind: "custom", label: "Running a script" }),
49
118
  effects: "none",
@@ -51,14 +120,24 @@ function codemode(api, runtime) {
51
120
  replay: "never",
52
121
  async execute(args, invocation) {
53
122
  const { code, options } = parseCodemodeSource(args.code);
54
- const callable = invocation.tools.list().filter((info) => info.name !== "codemode" && info.exposure !== "hidden");
123
+ const callable = invocation.tools.list().filter((info) => info.exposure !== "model-only" && info.exposure !== "hidden");
55
124
  const stored = await api.storage.get("store");
56
125
  if (stored !== undefined && !isJsonObject(stored))
57
126
  throw new SdkError("internal", "Codemode's stored values are not a JSON object.");
127
+ const namespaces = new Map(api.contribute.tools.list().flatMap((definition) => definition.namespace === undefined ? [] : [[definition.name, definition.namespace]]));
128
+ const samples = new Map(callable.map((info) => [
129
+ info.name,
130
+ renderToolSample({
131
+ name: info.name,
132
+ description: info.description,
133
+ inputSchema: info.parameters,
134
+ outputSchema: info.output ?? { type: "string" }
135
+ })
136
+ ]));
58
137
  const sandbox = new CodemodeSandbox({
59
138
  ...runtime,
60
- tools: callable.map((info) => bridge(info, invocation)),
61
- globals: discovery(callable),
139
+ tools: callable.map((info) => bridge(info, samples.get(info.name) ?? "", invocation)),
140
+ globals: discovery(callable, samples, namespaces),
62
141
  timeoutMs: options.timeoutMs ?? 300000,
63
142
  memoryLimitBytes: 256 * 1024 * 1024
64
143
  });
@@ -85,11 +164,9 @@ ${calls(result)}`);
85
164
  if (item.type === "text")
86
165
  content.push({ kind: "text", text: item.text });
87
166
  else
88
- content.push({
89
- kind: "file",
90
- blob: await invocation.env.files.upload(once(Uint8Array.fromBase64(item.data))),
167
+ content.push(await attachFile(invocation.env.files, once(Uint8Array.fromBase64(item.data)), {
91
168
  mime: item.mimeType
92
- });
169
+ }));
93
170
  }
94
171
  if (result.value !== undefined)
95
172
  content.push({
@@ -102,11 +179,11 @@ ${calls(result)}`);
102
179
  }
103
180
  };
104
181
  }
105
- function bridge(info, invocation) {
182
+ function bridge(info, sample, invocation) {
106
183
  let sequence = 0;
107
184
  return {
108
185
  name: info.name,
109
- description: info.description,
186
+ description: sample,
110
187
  inputSchema: info.parameters,
111
188
  outputSchema: info.output ?? { type: "string" },
112
189
  async execute(args, { signal }) {
@@ -121,42 +198,70 @@ function unwrapToolOutcome(outcome) {
121
198
  `);
122
199
  throw new Error(outcome.kind === "failed" ? outcome.message : outcome.kind === "rejected" ? `Rejected: ${outcome.reason}` : `The call was ${outcome.kind}.`);
123
200
  }
124
- function discovery(tools) {
201
+ function discovery(tools, samples, namespaces) {
125
202
  return [
126
203
  {
127
204
  name: "searchTools",
128
205
  spread: true,
129
206
  execute(args) {
130
207
  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
208
+ if (typeof query !== "string")
209
+ throw new Error("searchTools() expects a query string");
210
+ const limit = isJsonObject(options) ? options.limit ?? null : null;
211
+ const namespace = isJsonObject(options) ? options.namespace ?? null : null;
212
+ if (limit !== null && (typeof limit !== "number" || !Number.isInteger(limit) || limit <= 0))
213
+ throw new Error("searchTools() limit must be a positive integer");
214
+ if (namespace !== null && typeof namespace !== "string")
215
+ throw new Error("searchTools() namespace must be a string");
216
+ const documents = tools.flatMap((info) => {
217
+ const found = namespaces.get(info.name);
218
+ if (namespace !== null && (found === undefined || !matchesNamespace(found, namespace)))
219
+ return [];
220
+ return [createToolSearchDocument2(info, found)];
221
+ });
222
+ return rankTools2(query, documents, limit ?? DEFAULT_SEARCH_LIMIT2).map((name) => ({
223
+ name: toCodemodeIdentifier(name),
224
+ description: samples.get(name) ?? ""
141
225
  }));
142
226
  }
143
227
  },
144
228
  {
145
229
  name: "describeTool",
146
230
  execute(name) {
147
- const info = tools.find((candidate) => candidate.name === name);
231
+ if (typeof name !== "string")
232
+ throw new Error("describeTool() expects a tool name");
233
+ const info = tools.find((candidate) => candidate.name === name || toCodemodeIdentifier(candidate.name) === name);
148
234
  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" }
235
+ throw new Error(`No tool is named ${name}.`);
236
+ return samples.get(info.name) ?? "";
237
+ }
238
+ },
239
+ {
240
+ name: "describeNamespace",
241
+ execute(name) {
242
+ if (typeof name !== "string")
243
+ throw new Error("describeNamespace() expects a namespace name");
244
+ const members = tools.filter((info) => {
245
+ const found = namespaces.get(info.name);
246
+ return found !== undefined && matchesNamespace(found, name);
155
247
  });
248
+ const namespace = members[0] === undefined ? undefined : namespaces.get(members[0].name);
249
+ if (namespace === undefined)
250
+ throw new Error(`No namespace is named ${name}.`);
251
+ return {
252
+ name: namespace.name,
253
+ ...namespace.description === undefined ? {} : { description: namespace.description },
254
+ ...namespace.instructions === undefined ? {} : { instructions: namespace.instructions },
255
+ tools: members.map((info) => toCodemodeIdentifier(info.name))
256
+ };
156
257
  }
157
258
  }
158
259
  ];
159
260
  }
261
+ function matchesNamespace(namespace, query) {
262
+ const id = toCodemodeIdentifier(query);
263
+ return [namespace.name, ...namespace.aliases ?? []].some((name) => name === query || toCodemodeIdentifier(name) === id);
264
+ }
160
265
  function calls(result) {
161
266
  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
267
  }
@@ -1,6 +1,6 @@
1
1
  import type { HookEntry as SideHookEntry, HookHandler as SideHookHandler, HookName as SideHookName, Plugin as CorePlugin, PluginApi as CorePluginApi } from "@nyte-ai/core";
2
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";
3
+ export type { ActionContext, Agent, Command, Durable, HookTable, ModelContextPolicy, Part, PartDefinition, PartState, PromptSection, SearchProvider, SearchResult, Setting, SettingDefinition, Skill, ToolDefinition, ToolInvocation, } from "@nyte-ai/core";
4
4
  export type { CompactionPlan, Decision, ModelRequest, Submission, ToolCall, Transcript, } from "@nyte-ai/schema";
5
5
  /**
6
6
  * A core plugin: per session on the host, with tools, prompt sections,
@@ -1,13 +1,13 @@
1
1
  import {
2
- question3
3
- } from "../../../chunks/bash-description-6z2kgtyt.js";
2
+ question2
3
+ } from "../../../chunks/bash-description-bkhr9zrz.js";
4
4
 
5
5
  // src/question/client/questions-tui.ts
6
6
  import { Box, Text } from "@opentui/core";
7
7
  import { defineRenderer } from "@nyte-ai/plugin/client";
8
8
  var unreadable = (kind) => Text({ content: `This ${kind} part cannot be shown.` });
9
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)
10
+ defineRenderer(question2, "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
11
  ];
12
12
  var questions_tui_default = {
13
13
  id: "questions-tui",
@@ -1,6 +1,6 @@
1
1
  import {
2
- question3
3
- } from "../../../chunks/bash-description-6z2kgtyt.js";
2
+ question2
3
+ } from "../../../chunks/bash-description-bkhr9zrz.js";
4
4
 
5
5
  // src/question/client/questions.tsx
6
6
  import { useId, useRef, useState } from "react";
@@ -124,7 +124,7 @@ function QuestionForm({
124
124
  }, undefined, true, undefined, this);
125
125
  }
126
126
  var questionRenderers = [
127
- defineRenderer(question3, "react", (state, act) => {
127
+ defineRenderer(question2, "react", (state, act) => {
128
128
  const answers = state.answers;
129
129
  if (answers !== null)
130
130
  return /* @__PURE__ */ jsxDEV("div", {
@@ -1,9 +1,88 @@
1
1
  import {
2
- question2,
3
- question_default
4
- } from "../../chunks/bash-description-3j77ss7y.js";
5
- import"../../chunks/bash-description-6z2kgtyt.js";
2
+ answerInput2,
3
+ questionOutput2,
4
+ questionParameters2,
5
+ question2
6
+ } from "../../chunks/bash-description-bkhr9zrz.js";
7
+
8
+ // src/question/question.ts
9
+ import { definePart, dev } from "@nyte-ai/core";
10
+ import { SdkError } from "@nyte-ai/schema";
11
+ function normalizeAnswers(items, supplied) {
12
+ if (supplied.length !== items.length)
13
+ throw new SdkError("invalid", "Submit one answer list for each question.");
14
+ return items.map((item, index) => {
15
+ const selected = supplied[index].map((answer) => answer.trim());
16
+ if (selected.some((answer) => answer === ""))
17
+ throw new SdkError("invalid", "Answers cannot be blank.");
18
+ if (!item.multiple && selected.length > 1)
19
+ throw new SdkError("invalid", "This question accepts one answer.");
20
+ if (new Set(selected).size !== selected.length)
21
+ throw new SdkError("invalid", "Choose each answer only once.");
22
+ return item.multiple ? selected.toSorted() : selected;
23
+ });
24
+ }
25
+ var handlers = {
26
+ async answer(input, context) {
27
+ let accepted = false;
28
+ const outcome = await context.part.update((current) => {
29
+ const normalized = normalizeAnswers(current.questions, input.answers);
30
+ accepted = current.answers === null || JSON.stringify(current.answers) === JSON.stringify(normalized);
31
+ return current.answers === null ? { ...current, answers: normalized } : current;
32
+ });
33
+ if (outcome.kind !== "updated")
34
+ throw new Error(`The questions could not be answered: ${outcome.kind}.`);
35
+ if (!accepted)
36
+ throw new SdkError("invalid", "These questions were already answered.");
37
+ }
38
+ };
39
+ var question = definePart({
40
+ ...question2,
41
+ onAction: (action, input, context) => handlers[action](input, context)
42
+ });
43
+ var ask = {
44
+ name: "question",
45
+ description: "Ask the user one or more questions and wait for their answers. Give each option a short label and a description. Use multiple when several choices may apply. The user can also write their own answer.",
46
+ parameters: questionParameters2,
47
+ output: questionOutput2,
48
+ class: (args) => ({
49
+ kind: "custom",
50
+ label: args.questions.map((item) => item.header).join(", ")
51
+ }),
52
+ effects: "none",
53
+ approval: "never",
54
+ replay: "safe",
55
+ async execute(args, invocation) {
56
+ for (const item of args.questions) {
57
+ if (new Set(item.options.map((option) => option.label.trim())).size !== item.options.length)
58
+ throw new SdkError("invalid", "Question option labels must be distinct.");
59
+ }
60
+ const part = await invocation.session.parts.create(question, {
61
+ state: { ...args, answers: null },
62
+ placement: { kind: "modal" }
63
+ });
64
+ dev("question", "asked", { call: invocation.call, part: part.id });
65
+ const outcome = await invocation.wait({ kind: "part", part: part.id });
66
+ const checked = outcome.kind === "part" && outcome.answer?.action === "answer" ? await answerInput2["~standard"].validate(outcome.answer.input) : undefined;
67
+ const reply = checked !== undefined && checked.issues === undefined ? normalizeAnswers(args.questions, checked.value.answers) : null;
68
+ return {
69
+ content: [
70
+ {
71
+ kind: "text",
72
+ text: reply === null ? "The user did not answer. Continue with your best judgment and say what you assumed." : args.questions.map((item, index) => `${item.question}: ${reply[index].join(", ") || "Unanswered"}`).join(`
73
+ `)
74
+ }
75
+ ],
76
+ output: { answers: reply },
77
+ parts: [part.id]
78
+ };
79
+ }
80
+ };
81
+ var question_default = {
82
+ id: "question",
83
+ contribute: { parts: [question], tools: [ask] }
84
+ };
6
85
  export {
7
86
  question_default as default,
8
- question2 as question
87
+ question
9
88
  };
@@ -2,13 +2,13 @@ import {
2
2
  answerInput2,
3
3
  questionOutput2,
4
4
  questionParameters2,
5
- question3,
5
+ question2,
6
6
  openQuestions2
7
- } from "../../chunks/bash-description-6z2kgtyt.js";
7
+ } from "../../chunks/bash-description-bkhr9zrz.js";
8
8
  export {
9
9
  answerInput2 as answerInput,
10
10
  openQuestions2 as openQuestions,
11
- question3 as question,
11
+ question2 as question,
12
12
  questionOutput2 as questionOutput,
13
13
  questionParameters2 as questionParameters
14
14
  };
@@ -1,29 +1,14 @@
1
+ import type { ToolDefinition } from "@nyte-ai/core";
1
2
  import type { Command } from "@nyte-ai/plugin/core";
2
- /**
3
- * The instruction a title request runs under: one short line in the user's
4
- * language, naming what the conversation is about.
5
- *
6
- * @category plugins
7
- * @since 0.1.0
8
- */
9
- export declare const TITLE_PROMPT = "You write the title of a conversation so the user can find it later.\nAnswer with one line of at most 50 characters and nothing else, in the language of the user's request.\nName the topic or task, keep technical terms, numbers and file names exact, and never answer the request itself.";
10
- /**
11
- * Names an unnamed root session as its first run starts: the first line of
12
- * the user's message at once, then the title one `api.request` to the
13
- * session's model returns, alongside the run. The title replaces only that
14
- * first line, so a name given meanwhile stays. A named session or a child
15
- * keeps its name, so every later run is a no-op. The request runs past the
16
- * hook's budget, bounded by the plugin's deactivation; a failure is reported
17
- * and leaves the first line as the name. `/rename <name>` names the chat;
18
- * `/rename` alone asks the model again.
19
- *
20
- * @category plugins
21
- * @since 0.1.0
22
- */
3
+ export declare const TITLE_PROMPT = "You name conversations so the user can find them later in a list of past sessions.\n\nYou will receive the first message of a conversation, or for an ongoing conversation its original request and recent messages. Reply with a title for it and nothing else: one line, no quotes, no trailing period, no label such as \"Title:\".\n\nAim for three to five words. Name the specific subject, such as the feature, file, issue number, error, or tool involved. Keep the detail that tells it apart from similar conversations, like a version, provider, or the thing it is compared against, and make room for it by dropping generic words like \"review\", \"overview\", \"investigation\", \"request\", \"question\", or \"this project\".\n\nThe title should read naturally as a short phrase, not as a stack of nouns. Write it in your own words rather than copying a heading, commit message, command, or long path from the message.\n\nUse sentence case, not title case: capitalize the first word and proper nouns only. Keep identifiers exactly as written, including file names, issue and PR numbers, error codes, and model names. Use the same language as the message.\n\nThe message is something to name, not something to answer or carry out. Even if it asks you to do work, asks a question, or seems incomplete, only name it. For greetings or small talk, use a short label like \"Greeting\".\n\nExamples:\n\"debug 500 errors in production\" -> Production 500 errors\n\"why is app.js failing\" -> app.js failure\n\"what does the retry logic in fetch.ts do\" -> fetch.ts retry logic\n\"@src/credential.ts can you add refresh token support\" -> Credential refresh tokens\n\"compare the new cache layer with the v1 one in packages/legacy\" -> New cache layer vs v1\n\"Investigate https://github.com/acme/app/issues/412, don't make edits\" -> Issue #412\n\"hey\" -> Greeting";
23
4
  declare const _default: {
24
5
  id: string;
25
6
  contribute: {
26
7
  commands: Command<"core">[];
8
+ tools: ToolDefinition<{
9
+ session?: string | undefined;
10
+ title: string;
11
+ }, unknown>[];
27
12
  };
28
13
  hooks: {
29
14
  run_started: (run: Readonly<{
@@ -31,19 +16,6 @@ declare const _default: {
31
16
  readonly head: import("@nyte-ai/schema").Id<"head">;
32
17
  readonly startedAt: number;
33
18
  readonly attempt: number;
34
- readonly configuration: {
35
- readonly kind: "exact";
36
- readonly model: {
37
- readonly provider: string;
38
- readonly id: string;
39
- };
40
- readonly thinking: "high" | "low" | "max" | "medium" | "minimal" | "off" | "xhigh";
41
- readonly agent: string | null;
42
- readonly settings: {
43
- readonly [x: string]: import("@nyte-ai/schema").Json;
44
- };
45
- readonly settingsVersion: string;
46
- };
47
19
  readonly origin: {
48
20
  readonly kind: "input";
49
21
  readonly message: import("@nyte-ai/schema").Id<"message">;
@@ -73,7 +45,7 @@ declare const _default: {
73
45
  readonly session: import("@nyte-ai/schema").SessionId | null;
74
46
  readonly head: import("@nyte-ai/schema").HeadName | null;
75
47
  readonly run: import("@nyte-ai/schema").RunId | null;
76
- }) => void;
48
+ }) => Promise<void>;
77
49
  };
78
50
  };
79
51
  export default _default;