@nyte-ai/host 0.0.25-beta.1 → 0.0.25-nightly.20261025.2

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.
@@ -55,6 +55,11 @@ SOFTWARE.
55
55
  `@earendil-works/pi-codemode` 1.0.0 supply the MCP client and QuickJS
56
56
  executor. Tool discovery and code-mode integration are adapted from commit
57
57
  `86dfceec402ad77e563bf4feab5f26c42d5f5db6`.
58
+ - BM25 tool search (`tool_search`, `searchTools()`), tool namespaces with
59
+ `describeNamespace()`, the budgeted codemode listing and the one-line MCP
60
+ server summary (`packages/plugin/src/tool-search.ts`,
61
+ `packages/plugin/src/codemode.ts`, `packages/core/src/builtins/mcp.ts`) are
62
+ ported from commit `d5b3de22d0e24a3e9c38a9410d3329b099717283`.
58
63
  - Transcript reconciliation, checkpoint instruction snapshots, provider system
59
64
  updates, and cache warming are ported from the 1.0.0 release commit
60
65
  `a13d35a742c6ef8462812a28fbe1d8c8b7431c32`.
@@ -312,11 +317,14 @@ Copyright 2025 OpenAI
312
317
  front of the queue (`packages/tui/src/model/interactions.ts`) is its
313
318
  `onEmptySubmit`. The rename
314
319
  plugin's context construction, prompt, model fallback, and output cleanup
315
- (`packages/plugin/src/rename.ts`) port OpenCode v2. The web-search
316
- plugin set (`packages/plugin/src/web-search.ts`) ports its Exa, Firecrawl,
317
- Parallel, and Tavily adapters, its stateless MCP `tools/call` transport and
318
- response bounds, its result and error vocabulary, and its arrangement of one
319
- plugin per provider from OpenCode v2.
320
+ (`packages/plugin/src/rename.ts`) port OpenCode v2. The web plugin
321
+ (`packages/plugin/src/web/`) ports OpenCode v2's web search and fetch tools:
322
+ the search provider registry any plugin can add to (`searchProviders` in
323
+ `packages/core/src/contract/plugin.ts`), its Exa, Firecrawl, Parallel, and
324
+ Tavily adapters, their stateless MCP `tools/call` transport and response
325
+ bounds, the result and error vocabulary, `web_fetch`'s Accept headers,
326
+ Cloudflare-challenge retry and size limits, and the streaming HTML-to-Markdown
327
+ and HTML-to-text converters (`packages/plugin/src/web/html-markdown.ts`).
320
328
  - Core's ripgrep resolver and search adapter (`packages/core/src/ripgrep.ts`,
321
329
  `packages/core/src/ripgrep/binary.ts`) and filename search
322
330
  (`packages/core/src/file-search.ts`) adapt OpenCode v2's core implementation.
@@ -21,7 +21,7 @@ import {
21
21
  checkToolSchemas2,
22
22
  TracingMcpClient2,
23
23
  bridgeTools2
24
- } from "./canvas-preview-vaatfznm.js";
24
+ } from "./canvas-preview-ez9zdfq4.js";
25
25
 
26
26
  // src/mcp/hub.ts
27
27
  import { join } from "node:path";
@@ -206,7 +206,11 @@ function hub(input) {
206
206
  state: () => state,
207
207
  brief: () => ({
208
208
  name: entry.name,
209
+ description: link.entry.description,
209
210
  instructions: listed?.instructions ?? null,
211
+ exposures: [
212
+ ...new Set([link.entry.exposure, ...link.entry.toolExposure.map((pair) => pair[1])])
213
+ ],
210
214
  unavailable: listed === null && (state.kind === "failed" || state.kind === "needs-sign-in") ? state.kind : null
211
215
  }),
212
216
  challenge: () => challenge,
@@ -217,7 +221,7 @@ function hub(input) {
217
221
  bridged = {
218
222
  entry: link.entry,
219
223
  listed,
220
- tools: bridgeTools2(link.entry, listed.tools, call)
224
+ tools: bridgeTools2(link.entry, listed, call)
221
225
  };
222
226
  return bridged.tools;
223
227
  },
@@ -12,7 +12,7 @@ import {
12
12
  } from "./canvas-preview-8xc0vn7v.js";
13
13
  import {
14
14
  localProvider2
15
- } from "./canvas-preview-9bxhwjrh.js";
15
+ } from "./canvas-preview-dr46h8mm.js";
16
16
  import {
17
17
  importLegacyTrust2
18
18
  } from "./canvas-preview-9aqczacs.js";
@@ -21,13 +21,13 @@ import {
21
21
  } from "./canvas-preview-4e0pxa32.js";
22
22
  import {
23
23
  listen2
24
- } from "./canvas-preview-8sv3j0vt.js";
24
+ } from "./canvas-preview-sdvgxnpf.js";
25
25
  import {
26
26
  nodeImages2
27
27
  } from "./canvas-preview-y5y6ghaw.js";
28
28
  import {
29
29
  createMcpHub2
30
- } from "./canvas-preview-gh7c9831.js";
30
+ } from "./canvas-preview-27v3zkz4.js";
31
31
  import {
32
32
  loadPluginDirectory2,
33
33
  pluginLoader2
@@ -65,12 +65,14 @@ import openaiAstraContext from "@nyte-ai/plugin/core/openai-astra-context";
65
65
  import { openaiCompaction } from "@nyte-ai/plugin/core/openai-compaction";
66
66
  import question from "@nyte-ai/plugin/core/question";
67
67
  import rename from "@nyte-ai/plugin/core/rename";
68
+ import subagents from "@nyte-ai/plugin/core/subagents";
68
69
  import telemetry from "@nyte-ai/plugin/core/telemetry";
69
- import webSearch from "@nyte-ai/plugin/core/web-search";
70
+ import toolSearch from "@nyte-ai/plugin/core/tool-search";
71
+ import web from "@nyte-ai/plugin/core/web";
70
72
  // package.json
71
73
  var package_default = {
72
74
  name: "@nyte-ai/host",
73
- version: "0.0.25-beta.1",
75
+ version: "0.0.25-nightly.20261025.2",
74
76
  private: false,
75
77
  license: "MIT",
76
78
  repository: {
@@ -251,9 +253,11 @@ async function composeOpen(options, input) {
251
253
  approvals,
252
254
  question,
253
255
  rename,
256
+ subagents,
254
257
  bashDescription,
255
- webSearch,
258
+ web,
256
259
  codemode,
260
+ toolSearch,
257
261
  openaiCompaction(models),
258
262
  openaiAstraContext,
259
263
  telemetry,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createHandler2
3
- } from "./canvas-preview-1r9sgbj3.js";
3
+ } from "./canvas-preview-75bmwhsr.js";
4
4
 
5
5
  // src/listen-fetch.ts
6
6
  import { SdkError } from "@nyte-ai/schema";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  bindConnection2
3
- } from "./canvas-preview-2yzyt077.js";
3
+ } from "./canvas-preview-tq7ny7fm.js";
4
4
  import {
5
5
  createStreamChannels2
6
6
  } from "./canvas-preview-rp4x6y1h.js";
@@ -21,7 +21,7 @@ import {
21
21
  } from "./canvas-preview-crmzxxt8.js";
22
22
  import {
23
23
  localWorktrees2
24
- } from "./canvas-preview-bg63k8n7.js";
24
+ } from "./canvas-preview-z2xdr07w.js";
25
25
 
26
26
  // src/local/provider.ts
27
27
  import { constants, realpathSync } from "node:fs";
@@ -59,13 +59,21 @@ class TracingMcpClient2 extends McpClient {
59
59
  return super.request(method, traceparent === null || params?._meta !== undefined ? params : { ...params, _meta: { traceparent } }, options);
60
60
  }
61
61
  }
62
- function bridgeTools2(entry, tools, call) {
63
- const names = tools.map((tool) => toolName(entry.name, tool.name));
62
+ function bridgeTools2(entry, listed, call) {
63
+ const names = listed.tools.map((tool) => toolName(entry.name, tool.name));
64
64
  const counts = Map.groupBy(names, (name) => name);
65
- return tools.map((tool, index) => {
65
+ const description = entry.description?.trim() ?? "";
66
+ const instructions = listed.instructions?.trim() ?? "";
67
+ const namespace = {
68
+ name: `mcp__${entry.name}`.replace(/[^A-Za-z0-9_]/g, "_"),
69
+ aliases: [entry.name],
70
+ ...description === "" ? {} : { description },
71
+ ...instructions === "" ? {} : { instructions }
72
+ };
73
+ return listed.tools.map((tool, index) => {
66
74
  const name = names[index];
67
75
  const unique = (counts.get(name)?.length ?? 0) > 1 ? hashed(name, tool.name) : name;
68
- return bridge(entry, tool, call, unique);
76
+ return bridge(entry, tool, call, unique, namespace);
69
77
  });
70
78
  }
71
79
  function toolName(server, tool) {
@@ -82,14 +90,15 @@ function globMatches(pattern, value) {
82
90
  const source = pattern.split("*").map((part) => part.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).join(".*");
83
91
  return new RegExp(`^${source}$`).test(value);
84
92
  }
85
- function bridge(entry, tool, call, name) {
93
+ function bridge(entry, tool, call, name, namespace) {
86
94
  const output = tool.outputSchema;
95
+ const exposure = toolExposure2(entry, tool.name);
87
96
  const definition = {
88
97
  name,
89
- namespace: `mcp/${entry.name}`,
98
+ namespace,
90
99
  description: tool.description ?? tool.title ?? tool.name,
91
100
  parameters: passthrough(tool.inputSchema),
92
- exposure: toolExposure2(entry, tool.name),
101
+ exposure: exposure === "code" ? "deferred" : exposure,
93
102
  class: () => ({ kind: "custom", label: `${entry.name}: ${tool.title ?? tool.name}` }),
94
103
  effects: tool.annotations?.readOnlyHint === true ? "none" : "workspace",
95
104
  replay: tool.annotations?.readOnlyHint === true || tool.annotations?.idempotentHint === true ? "safe" : "never",
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  listenFetch2
3
- } from "./canvas-preview-da6dwy05.js";
3
+ } from "./canvas-preview-4rstzyd7.js";
4
4
 
5
5
  // src/listen.ts
6
6
  import { createServer } from "node:http";
@@ -116,6 +116,7 @@ function bindConnection2(connection, options) {
116
116
  "workspaces.inspect": ({ target }) => connection.workspaces.inspect(target),
117
117
  "workspaces.add": ({ target, options }) => connection.workspaces.add(target, options),
118
118
  "workspaces.forget": ({ id }) => connection.workspaces.forget(id),
119
+ "workspaces.cleanWorktrees": () => connection.workspaces.cleanWorktrees(),
119
120
  "sessions.watch": async (input) => sessionsFrames(connection.sessions.watch(input)),
120
121
  "sessions.start": async (input) => {
121
122
  const { session, receipt } = await connection.sessions.start(input);
@@ -53,6 +53,21 @@ var TYPE_WORDS = new Set([
53
53
  "revert",
54
54
  "update"
55
55
  ]);
56
+ var REGENERABLE = new Set([
57
+ "node_modules",
58
+ ".turbo",
59
+ ".next",
60
+ ".nuxt",
61
+ ".svelte-kit",
62
+ ".vite",
63
+ ".parcel-cache",
64
+ "dist",
65
+ "build",
66
+ "coverage",
67
+ "target",
68
+ ".venv",
69
+ "__pycache__"
70
+ ]);
56
71
  var MAX_ATTEMPTS = 100;
57
72
  function gitCommand(binary = "git") {
58
73
  return async (cwd, args, env) => {
@@ -115,8 +130,8 @@ function localWorktrees2(options) {
115
130
  };
116
131
  const claimBranch = async (root, parent, listed, input, head) => {
117
132
  for (let attempt = 1;attempt <= MAX_ATTEMPTS; attempt++) {
118
- const branch = branchName(input.title, attempt);
119
- const folder = join(parent, branch);
133
+ const branch = `${input.prefix ?? ""}${branchName(input.title, attempt)}`;
134
+ const folder = join(parent, branch.replaceAll("/", "-"));
120
135
  if (listed.some((worktree) => worktree.path === folder) || await stat(folder).catch(() => null) !== null)
121
136
  continue;
122
137
  const [created] = await Promise.allSettled([
@@ -168,7 +183,7 @@ function localWorktrees2(options) {
168
183
  const realParent = await realpath(parent);
169
184
  const branch = claimed ?? await claimBranch(repo.root, realParent, listed, input, head);
170
185
  const base = claimed === null ? head : await commitAt(repo.root, `refs/heads/${claimed}`) ?? head;
171
- const folder = join(realParent, branch);
186
+ const folder = join(realParent, branch.replaceAll("/", "-"));
172
187
  const tree = await workingTree(repo);
173
188
  await addWorktree2(repo.root, { path: folder, branch }, options);
174
189
  if (tree !== (await git(folder, ["rev-parse", "HEAD^{tree}"])).trim()) {
@@ -196,6 +211,25 @@ function localWorktrees2(options) {
196
211
  return { folder: "removed", branch: "kept" };
197
212
  await git(common, ["branch", "-D", worktree.branch]);
198
213
  return { folder: "removed", branch: "deleted" };
214
+ },
215
+ async clean(target) {
216
+ const path = "path" in target ? target.path : null;
217
+ if (path === null || await stat(path).catch(() => null) === null)
218
+ return false;
219
+ const root = (await git(path, ["rev-parse", "--show-toplevel"])).trim();
220
+ const within = await realpath(folders).catch(() => null);
221
+ if (within === null || !root.startsWith(`${within}/`))
222
+ return false;
223
+ const status = await git(root, [
224
+ "status",
225
+ "--porcelain",
226
+ "--ignored=traditional",
227
+ "--untracked-files=normal",
228
+ "-z"
229
+ ]);
230
+ const regenerable = status.split("\x00").filter((entry) => entry.startsWith("!! ") && entry.endsWith("/")).map((entry) => entry.slice(3, -1)).filter((folder) => REGENERABLE.has(basename(folder)));
231
+ await Promise.all(regenerable.map((folder) => rm(join(root, folder), { recursive: true, force: true })));
232
+ return regenerable.length > 0;
199
233
  }
200
234
  };
201
235
  }
package/dist/src/index.js CHANGED
@@ -11,15 +11,15 @@ import"../chunks/canvas-preview-wg80rbc2.js";
11
11
  import {
12
12
  identitySigner2
13
13
  } from "../chunks/canvas-preview-5mex725c.js";
14
- import"../chunks/canvas-preview-2yzyt077.js";
14
+ import"../chunks/canvas-preview-tq7ny7fm.js";
15
15
  import"../chunks/canvas-preview-rp4x6y1h.js";
16
- import"../chunks/canvas-preview-1r9sgbj3.js";
16
+ import"../chunks/canvas-preview-75bmwhsr.js";
17
17
  import {
18
18
  listenFetch2
19
- } from "../chunks/canvas-preview-da6dwy05.js";
19
+ } from "../chunks/canvas-preview-4rstzyd7.js";
20
20
  import {
21
21
  listen2
22
- } from "../chunks/canvas-preview-8sv3j0vt.js";
22
+ } from "../chunks/canvas-preview-sdvgxnpf.js";
23
23
  import"../chunks/canvas-preview-0nq75h9k.js";
24
24
  import"../chunks/canvas-preview-bxnqt8cd.js";
25
25
  import"../chunks/canvas-preview-yjz0f7n4.js";
@@ -51,17 +51,17 @@ import {
51
51
  addWorktree2,
52
52
  hasBranch2,
53
53
  localWorktrees2
54
- } from "../chunks/canvas-preview-bg63k8n7.js";
54
+ } from "../chunks/canvas-preview-z2xdr07w.js";
55
55
  import {
56
56
  localProvider2
57
- } from "../chunks/canvas-preview-9bxhwjrh.js";
57
+ } from "../chunks/canvas-preview-dr46h8mm.js";
58
58
  import"../chunks/canvas-preview-kdqgrstc.js";
59
59
  import"../chunks/canvas-preview-5z63am63.js";
60
60
  import"../chunks/canvas-preview-pkzqg96v.js";
61
- import"../chunks/canvas-preview-vaatfznm.js";
61
+ import"../chunks/canvas-preview-ez9zdfq4.js";
62
62
  import {
63
63
  createMcpHub2
64
- } from "../chunks/canvas-preview-gh7c9831.js";
64
+ } from "../chunks/canvas-preview-27v3zkz4.js";
65
65
  import"../chunks/canvas-preview-9aqczacs.js";
66
66
  import"../chunks/canvas-preview-4e0pxa32.js";
67
67
  import"../chunks/canvas-preview-befkjea2.js";
@@ -84,7 +84,7 @@ import {
84
84
  } from "../chunks/canvas-preview-mstbvwz3.js";
85
85
  import {
86
86
  openHost2
87
- } from "../chunks/canvas-preview-dt89p9pm.js";
87
+ } from "../chunks/canvas-preview-3kmevzjy.js";
88
88
  import {
89
89
  postgresStore2
90
90
  } from "../chunks/canvas-preview-4b6sayhg.js";
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  listenFetch2
3
- } from "../chunks/canvas-preview-da6dwy05.js";
4
- import"../chunks/canvas-preview-1r9sgbj3.js";
5
- import"../chunks/canvas-preview-2yzyt077.js";
3
+ } from "../chunks/canvas-preview-4rstzyd7.js";
4
+ import"../chunks/canvas-preview-75bmwhsr.js";
5
+ import"../chunks/canvas-preview-tq7ny7fm.js";
6
6
  import"../chunks/canvas-preview-rp4x6y1h.js";
7
7
  export {
8
8
  listenFetch2 as listenFetch
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  listen2
3
- } from "../chunks/canvas-preview-8sv3j0vt.js";
4
- import"../chunks/canvas-preview-da6dwy05.js";
5
- import"../chunks/canvas-preview-1r9sgbj3.js";
6
- import"../chunks/canvas-preview-2yzyt077.js";
3
+ } from "../chunks/canvas-preview-sdvgxnpf.js";
4
+ import"../chunks/canvas-preview-4rstzyd7.js";
5
+ import"../chunks/canvas-preview-75bmwhsr.js";
6
+ import"../chunks/canvas-preview-tq7ny7fm.js";
7
7
  import"../chunks/canvas-preview-rp4x6y1h.js";
8
8
  export {
9
9
  listen2 as listen
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  localProvider2
3
- } from "../../chunks/canvas-preview-9bxhwjrh.js";
4
- import"../../chunks/canvas-preview-bg63k8n7.js";
3
+ } from "../../chunks/canvas-preview-dr46h8mm.js";
4
+ import"../../chunks/canvas-preview-z2xdr07w.js";
5
5
  import"../../chunks/canvas-preview-5ekjx6sw.js";
6
6
  import"../../chunks/canvas-preview-8xc0vn7v.js";
7
7
  import"../../chunks/canvas-preview-1sq7z9jq.js";
@@ -3,7 +3,7 @@ import {
3
3
  addWorktree2,
4
4
  hasBranch2,
5
5
  localWorktrees2
6
- } from "../../chunks/canvas-preview-bg63k8n7.js";
6
+ } from "../../chunks/canvas-preview-z2xdr07w.js";
7
7
  import"../../chunks/canvas-preview-bxnqt8cd.js";
8
8
  export {
9
9
  addWorktree2 as addWorktree,
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createMcpHub2
3
- } from "../../chunks/canvas-preview-gh7c9831.js";
3
+ } from "../../chunks/canvas-preview-27v3zkz4.js";
4
4
  import"../../chunks/canvas-preview-pkzqg96v.js";
5
5
  import"../../chunks/canvas-preview-5z63am63.js";
6
- import"../../chunks/canvas-preview-vaatfznm.js";
6
+ import"../../chunks/canvas-preview-ez9zdfq4.js";
7
7
  import"../../chunks/canvas-preview-kdqgrstc.js";
8
8
  import"../../chunks/canvas-preview-mgcx2b2p.js";
9
9
  export {
@@ -25,5 +25,12 @@ export type McpCall = (name: string, args: Record<string, unknown>, options: Mcp
25
25
  export declare class TracingMcpClient extends McpClient {
26
26
  request<Result = unknown>(method: string, params?: Record<string, unknown>, options?: McpRequestOptions): Promise<Result>;
27
27
  }
28
- /** Turns a server's listed tools into session tools named `mcp__<server>__<tool>`. */
29
- export declare function bridgeTools(entry: McpServerEntry, tools: readonly Tool[], call: McpCall): ToolDefinition[];
28
+ /**
29
+ * Turns a server's listed tools into session tools named
30
+ * `mcp__<server>__<tool>`, in the namespace `mcp__<server>` (alias
31
+ * `<server>`) that carries the server's description and instructions.
32
+ */
33
+ export declare function bridgeTools(entry: McpServerEntry, listed: {
34
+ readonly tools: readonly Tool[];
35
+ readonly instructions: string | null;
36
+ }, call: McpCall): ToolDefinition[];
@@ -3,7 +3,7 @@ import {
3
3
  checkToolSchemas2,
4
4
  TracingMcpClient2,
5
5
  bridgeTools2
6
- } from "../../chunks/canvas-preview-vaatfznm.js";
6
+ } from "../../chunks/canvas-preview-ez9zdfq4.js";
7
7
  export {
8
8
  TracingMcpClient2 as TracingMcpClient,
9
9
  bridgeTools2 as bridgeTools,
package/dist/src/open.js CHANGED
@@ -1,23 +1,23 @@
1
1
  import {
2
2
  openHost2
3
- } from "../chunks/canvas-preview-dt89p9pm.js";
3
+ } from "../chunks/canvas-preview-3kmevzjy.js";
4
4
  import"../chunks/canvas-preview-4e0pxa32.js";
5
5
  import"../chunks/canvas-preview-y5y6ghaw.js";
6
6
  import"../chunks/canvas-preview-ec2mt7es.js";
7
7
  import"../chunks/canvas-preview-befkjea2.js";
8
8
  import"../chunks/canvas-preview-9aqczacs.js";
9
- import"../chunks/canvas-preview-9bxhwjrh.js";
10
- import"../chunks/canvas-preview-bg63k8n7.js";
9
+ import"../chunks/canvas-preview-dr46h8mm.js";
10
+ import"../chunks/canvas-preview-z2xdr07w.js";
11
11
  import"../chunks/canvas-preview-5ekjx6sw.js";
12
12
  import"../chunks/canvas-preview-8xc0vn7v.js";
13
13
  import"../chunks/canvas-preview-1sq7z9jq.js";
14
14
  import"../chunks/canvas-preview-vm9zdp2t.js";
15
15
  import"../chunks/canvas-preview-crmzxxt8.js";
16
16
  import"../chunks/canvas-preview-tjhabynd.js";
17
- import"../chunks/canvas-preview-gh7c9831.js";
17
+ import"../chunks/canvas-preview-27v3zkz4.js";
18
18
  import"../chunks/canvas-preview-pkzqg96v.js";
19
19
  import"../chunks/canvas-preview-5z63am63.js";
20
- import"../chunks/canvas-preview-vaatfznm.js";
20
+ import"../chunks/canvas-preview-ez9zdfq4.js";
21
21
  import"../chunks/canvas-preview-drctegz4.js";
22
22
  import"../chunks/canvas-preview-kn7kvbfj.js";
23
23
  import"../chunks/canvas-preview-yjz0f7n4.js";
@@ -26,10 +26,10 @@ import"../chunks/canvas-preview-s94ebwf5.js";
26
26
  import"../chunks/canvas-preview-kdqgrstc.js";
27
27
  import"../chunks/canvas-preview-mstbvwz3.js";
28
28
  import"../chunks/canvas-preview-zaaj99wd.js";
29
- import"../chunks/canvas-preview-8sv3j0vt.js";
30
- import"../chunks/canvas-preview-da6dwy05.js";
31
- import"../chunks/canvas-preview-1r9sgbj3.js";
32
- import"../chunks/canvas-preview-2yzyt077.js";
29
+ import"../chunks/canvas-preview-sdvgxnpf.js";
30
+ import"../chunks/canvas-preview-4rstzyd7.js";
31
+ import"../chunks/canvas-preview-75bmwhsr.js";
32
+ import"../chunks/canvas-preview-tq7ny7fm.js";
33
33
  import"../chunks/canvas-preview-rp4x6y1h.js";
34
34
  import"../chunks/canvas-preview-skzwvw4d.js";
35
35
  import"../chunks/canvas-preview-bxnqt8cd.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  bindConnection2
3
- } from "../../chunks/canvas-preview-2yzyt077.js";
3
+ } from "../../chunks/canvas-preview-tq7ny7fm.js";
4
4
  export {
5
5
  bindConnection2 as bindConnection
6
6
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createHandler2
3
- } from "../../chunks/canvas-preview-1r9sgbj3.js";
4
- import"../../chunks/canvas-preview-2yzyt077.js";
3
+ } from "../../chunks/canvas-preview-75bmwhsr.js";
4
+ import"../../chunks/canvas-preview-tq7ny7fm.js";
5
5
  import"../../chunks/canvas-preview-rp4x6y1h.js";
6
6
  export {
7
7
  createHandler2 as createHandler
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nyte-ai/host",
3
- "version": "0.0.25-beta.1",
3
+ "version": "0.0.25-nightly.20261025.2",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -88,11 +88,11 @@
88
88
  "dependencies": {
89
89
  "@earendil-works/pi-mcp": "^1.3.0",
90
90
  "@lydell/node-pty": "^1.2.0-beta.15",
91
- "@nyte-ai/ai": "0.0.25-beta.1",
92
- "@nyte-ai/core": "0.0.25-beta.1",
93
- "@nyte-ai/plugin": "0.0.25-beta.1",
94
- "@nyte-ai/protocol": "0.0.25-beta.1",
95
- "@nyte-ai/schema": "0.0.25-beta.1",
91
+ "@nyte-ai/ai": "0.0.25-nightly.20261025.2",
92
+ "@nyte-ai/core": "0.0.25-nightly.20261025.2",
93
+ "@nyte-ai/plugin": "0.0.25-nightly.20261025.2",
94
+ "@nyte-ai/protocol": "0.0.25-nightly.20261025.2",
95
+ "@nyte-ai/schema": "0.0.25-nightly.20261025.2",
96
96
  "@silvia-odwyer/photon": "^0.3.3",
97
97
  "fflate": "^0.8.3",
98
98
  "ignore": "^7.0.13",
@@ -57,6 +57,22 @@ const TYPE_WORDS = new Set([
57
57
  "update",
58
58
  ]);
59
59
 
60
+ const REGENERABLE = new Set([
61
+ "node_modules",
62
+ ".turbo",
63
+ ".next",
64
+ ".nuxt",
65
+ ".svelte-kit",
66
+ ".vite",
67
+ ".parcel-cache",
68
+ "dist",
69
+ "build",
70
+ "coverage",
71
+ "target",
72
+ ".venv",
73
+ "__pycache__",
74
+ ]);
75
+
60
76
  /** How many names `create` tries before giving up: `<words>`, then `<two words>-2` up to this. */
61
77
  const MAX_ATTEMPTS = 100;
62
78
 
@@ -207,12 +223,12 @@ export function localWorktrees(options?: {
207
223
  root: string,
208
224
  parent: string,
209
225
  listed: readonly ListedWorktree[],
210
- input: { readonly name: string; readonly title: string | null },
226
+ input: { readonly name: string; readonly title: string | null; readonly prefix?: string },
211
227
  head: string,
212
228
  ): Promise<string> => {
213
229
  for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
214
- const branch = branchName(input.title, attempt);
215
- const folder = join(parent, branch);
230
+ const branch = `${input.prefix ?? ""}${branchName(input.title, attempt)}`;
231
+ const folder = join(parent, branch.replaceAll("/", "-"));
216
232
 
217
233
  if (
218
234
  listed.some((worktree) => worktree.path === folder) ||
@@ -292,7 +308,7 @@ export function localWorktrees(options?: {
292
308
  const base =
293
309
  claimed === null ? head : ((await commitAt(repo.root, `refs/heads/${claimed}`)) ?? head);
294
310
 
295
- const folder = join(realParent, branch);
311
+ const folder = join(realParent, branch.replaceAll("/", "-"));
296
312
  const tree = await workingTree(repo);
297
313
 
298
314
  await addWorktree(repo.root, { path: folder, branch }, options);
@@ -334,6 +350,35 @@ export function localWorktrees(options?: {
334
350
 
335
351
  return { folder: "removed", branch: "deleted" };
336
352
  },
353
+ async clean(target) {
354
+ const path = "path" in target ? target.path : null;
355
+
356
+ if (path === null || (await stat(path).catch(() => null)) === null) return false;
357
+ const root = (await git(path, ["rev-parse", "--show-toplevel"])).trim();
358
+ const within = await realpath(folders).catch(() => null);
359
+
360
+ if (within === null || !root.startsWith(`${within}/`)) return false;
361
+
362
+ const status = await git(root, [
363
+ "status",
364
+ "--porcelain",
365
+ "--ignored=traditional",
366
+ "--untracked-files=normal",
367
+ "-z",
368
+ ]);
369
+
370
+ const regenerable = status
371
+ .split("\0")
372
+ .filter((entry) => entry.startsWith("!! ") && entry.endsWith("/"))
373
+ .map((entry) => entry.slice(3, -1))
374
+ .filter((folder) => REGENERABLE.has(basename(folder)));
375
+
376
+ await Promise.all(
377
+ regenerable.map((folder) => rm(join(root, folder), { recursive: true, force: true })),
378
+ );
379
+
380
+ return regenerable.length > 0;
381
+ },
337
382
  };
338
383
  }
339
384
 
package/src/mcp/hub.ts CHANGED
@@ -303,7 +303,11 @@ function hub(input: {
303
303
  state: () => state,
304
304
  brief: () => ({
305
305
  name: entry.name,
306
+ description: link.entry.description,
306
307
  instructions: listed?.instructions ?? null,
308
+ exposures: [
309
+ ...new Set([link.entry.exposure, ...link.entry.toolExposure.map((pair) => pair[1])]),
310
+ ],
307
311
  unavailable:
308
312
  listed === null && (state.kind === "failed" || state.kind === "needs-sign-in")
309
313
  ? state.kind
@@ -317,7 +321,7 @@ function hub(input: {
317
321
  bridged = {
318
322
  entry: link.entry,
319
323
  listed,
320
- tools: bridgeTools(link.entry, listed.tools, call),
324
+ tools: bridgeTools(link.entry, listed, call),
321
325
  };
322
326
 
323
327
  return bridged.tools;
package/src/mcp/tools.ts CHANGED
@@ -7,7 +7,7 @@ import type {
7
7
  Tool,
8
8
  } from "@earendil-works/pi-mcp";
9
9
  import { followedTrace, startSpan, traceparent } from "@nyte-ai/core";
10
- import type { ExecutionEnv, ToolDefinition } from "@nyte-ai/core";
10
+ import type { ExecutionEnv, ToolDefinition, ToolNamespace } from "@nyte-ai/core";
11
11
  import { isJson, isJsonObject } from "@nyte-ai/schema";
12
12
  import type {
13
13
  Json,
@@ -142,20 +142,33 @@ export class TracingMcpClient extends McpClient {
142
142
  }
143
143
  }
144
144
 
145
- /** Turns a server's listed tools into session tools named `mcp__<server>__<tool>`. */
145
+ /**
146
+ * Turns a server's listed tools into session tools named
147
+ * `mcp__<server>__<tool>`, in the namespace `mcp__<server>` (alias
148
+ * `<server>`) that carries the server's description and instructions.
149
+ */
146
150
  export function bridgeTools(
147
151
  entry: McpServerEntry,
148
- tools: readonly Tool[],
152
+ listed: { readonly tools: readonly Tool[]; readonly instructions: string | null },
149
153
  call: McpCall,
150
154
  ): ToolDefinition[] {
151
- const names = tools.map((tool) => toolName(entry.name, tool.name));
155
+ const names = listed.tools.map((tool) => toolName(entry.name, tool.name));
152
156
  const counts = Map.groupBy(names, (name) => name);
157
+ const description = entry.description?.trim() ?? "";
158
+ const instructions = listed.instructions?.trim() ?? "";
159
+
160
+ const namespace: ToolNamespace = {
161
+ name: `mcp__${entry.name}`.replace(/[^A-Za-z0-9_]/g, "_"),
162
+ aliases: [entry.name],
163
+ ...(description === "" ? {} : { description }),
164
+ ...(instructions === "" ? {} : { instructions }),
165
+ };
153
166
 
154
- return tools.map((tool, index) => {
167
+ return listed.tools.map((tool, index) => {
155
168
  const name = names[index];
156
169
  const unique = (counts.get(name)?.length ?? 0) > 1 ? hashed(name, tool.name) : name;
157
170
 
158
- return bridge(entry, tool, call, unique);
171
+ return bridge(entry, tool, call, unique, namespace);
159
172
  });
160
173
  }
161
174
 
@@ -182,20 +195,23 @@ function globMatches(pattern: string, value: string): boolean {
182
195
  return new RegExp(`^${source}$`).test(value);
183
196
  }
184
197
 
198
+ /** One listed tool as a session tool. Codemode's go unlisted like `deferred` ones; the session's prompt names their server instead. */
185
199
  function bridge(
186
200
  entry: McpServerEntry,
187
201
  tool: Tool,
188
202
  call: McpCall,
189
203
  name: string,
204
+ namespace: ToolNamespace,
190
205
  ): ToolDefinition<JsonObject> {
191
206
  const output = tool.outputSchema;
207
+ const exposure = toolExposure(entry, tool.name);
192
208
 
193
209
  const definition: ToolDefinition<JsonObject> = {
194
210
  name,
195
- namespace: `mcp/${entry.name}`,
211
+ namespace,
196
212
  description: tool.description ?? tool.title ?? tool.name,
197
213
  parameters: passthrough(tool.inputSchema),
198
- exposure: toolExposure(entry, tool.name),
214
+ exposure: exposure === "code" ? "deferred" : exposure,
199
215
  class: () => ({ kind: "custom", label: `${entry.name}: ${tool.title ?? tool.name}` }),
200
216
  effects: tool.annotations?.readOnlyHint === true ? "none" : "workspace",
201
217
  replay:
package/src/open.ts CHANGED
@@ -32,8 +32,10 @@ import openaiAstraContext from "@nyte-ai/plugin/core/openai-astra-context";
32
32
  import { openaiCompaction } from "@nyte-ai/plugin/core/openai-compaction";
33
33
  import question from "@nyte-ai/plugin/core/question";
34
34
  import rename from "@nyte-ai/plugin/core/rename";
35
+ import subagents from "@nyte-ai/plugin/core/subagents";
35
36
  import telemetry from "@nyte-ai/plugin/core/telemetry";
36
- import webSearch from "@nyte-ai/plugin/core/web-search";
37
+ import toolSearch from "@nyte-ai/plugin/core/tool-search";
38
+ import web from "@nyte-ai/plugin/core/web";
37
39
  import manifest from "../package.json" with { type: "json" };
38
40
  import { credentialStore } from "./credentials.ts";
39
41
  import { identitySigner } from "./identity-key.ts";
@@ -125,9 +127,11 @@ async function composeOpen(
125
127
  approvals,
126
128
  question,
127
129
  rename,
130
+ subagents,
128
131
  bashDescription,
129
- webSearch,
132
+ web,
130
133
  codemode,
134
+ toolSearch,
131
135
  openaiCompaction(models),
132
136
  openaiAstraContext,
133
137
  telemetry,
@@ -255,6 +255,7 @@ export function bindConnection(connection: Connection, options: BindingOptions):
255
255
  "workspaces.inspect": ({ target }) => connection.workspaces.inspect(target),
256
256
  "workspaces.add": ({ target, options }) => connection.workspaces.add(target, options),
257
257
  "workspaces.forget": ({ id }) => connection.workspaces.forget(id),
258
+ "workspaces.cleanWorktrees": () => connection.workspaces.cleanWorktrees(),
258
259
 
259
260
  "sessions.watch": async (input) => sessionsFrames(connection.sessions.watch(input)),
260
261
  "sessions.start": async (input) => {