@nyte-ai/core 0.0.19 → 0.0.23

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 (112) hide show
  1. package/dist/chunks/{compose-xaegezm3.js → compose-1tdb9ezw.js} +17 -18
  2. package/dist/chunks/{compose-5489evqa.js → compose-1xn3eecn.js} +29 -29
  3. package/dist/chunks/{compose-s5522cth.js → compose-2gsbcjgv.js} +12 -12
  4. package/dist/chunks/{compose-57j0pme0.js → compose-2rha31fc.js} +3 -3
  5. package/dist/chunks/{compose-m1ecjzm2.js → compose-42egt9y7.js} +7 -7
  6. package/dist/chunks/{compose-qknd62yj.js → compose-4ppmas7g.js} +2 -2
  7. package/dist/chunks/{compose-z6hbq6y0.js → compose-5njywhy8.js} +4 -4
  8. package/dist/chunks/{compose-h3pch7ch.js → compose-8pp3vtv0.js} +2 -2
  9. package/dist/chunks/{compose-tb5ywdfk.js → compose-917xy085.js} +13 -8
  10. package/dist/chunks/{compose-q1d09qpr.js → compose-97y00axn.js} +6 -6
  11. package/dist/chunks/{compose-q1rrtq3a.js → compose-9jvn2wvh.js} +140 -31
  12. package/dist/chunks/{compose-jrqn6xhy.js → compose-a40dnhy5.js} +5 -5
  13. package/dist/chunks/{compose-rd5e5nxg.js → compose-ad80nkkn.js} +1 -1
  14. package/dist/chunks/{compose-r1pxdxbw.js → compose-ae5t6v5b.js} +2 -2
  15. package/dist/chunks/{compose-hf6xkwdw.js → compose-ay7t13m9.js} +6 -6
  16. package/dist/chunks/{compose-pnsvwd3m.js → compose-bbhk8vnr.js} +1 -1
  17. package/dist/chunks/{compose-eemt6sea.js → compose-byse0eqj.js} +3 -3
  18. package/dist/chunks/{compose-ks2rdteq.js → compose-bz70g01d.js} +2 -2
  19. package/dist/chunks/{compose-mamr4qwf.js → compose-c4z4kp98.js} +77 -22
  20. package/dist/chunks/{compose-0827b2k4.js → compose-c9wxgbjp.js} +1 -1
  21. package/dist/chunks/{compose-c2rnebv0.js → compose-d95fwwvw.js} +1 -1
  22. package/dist/chunks/{compose-gxvetm0j.js → compose-ee0h1pk1.js} +3 -3
  23. package/dist/chunks/{compose-4770pb1s.js → compose-enq3x3rq.js} +3 -3
  24. package/dist/chunks/{compose-prchdrqk.js → compose-fnncnk81.js} +3 -3
  25. package/dist/chunks/{compose-bjx8s01m.js → compose-fqsqjbrf.js} +1 -1
  26. package/dist/chunks/{compose-v9yf9mrh.js → compose-gj2ypr7q.js} +2 -2
  27. package/dist/chunks/{compose-zch4zapc.js → compose-hfrjm4a1.js} +1 -1
  28. package/dist/chunks/{compose-w2ac7xjx.js → compose-hfsn6pnt.js} +1 -1
  29. package/dist/chunks/{compose-6m60v1pk.js → compose-ht1tbyr3.js} +3 -3
  30. package/dist/chunks/{compose-31zqcfte.js → compose-jeemzja1.js} +2 -2
  31. package/dist/chunks/{compose-jhs91x01.js → compose-jwy1gba9.js} +1 -1
  32. package/dist/chunks/{compose-se7wwcq1.js → compose-m01wspwf.js} +1 -1
  33. package/dist/chunks/{compose-n93897b0.js → compose-m91ffwss.js} +1 -1
  34. package/dist/chunks/{compose-47f47sgy.js → compose-matk94se.js} +4 -4
  35. package/dist/chunks/{compose-hms4hf6p.js → compose-mcz93154.js} +63 -47
  36. package/dist/chunks/{compose-exfx5b4d.js → compose-mdwr0er9.js} +2 -2
  37. package/dist/chunks/{compose-y9c31w4e.js → compose-nkxwrphm.js} +30 -13
  38. package/dist/chunks/{compose-seyhq3fb.js → compose-nw5hdpxk.js} +6 -6
  39. package/dist/chunks/{compose-1g03zpvn.js → compose-qjxtbzgq.js} +5 -5
  40. package/dist/chunks/{compose-jehg40ce.js → compose-qxfq6dn9.js} +5 -5
  41. package/dist/chunks/{compose-azq5jxr2.js → compose-r8tz1xfj.js} +4 -4
  42. package/dist/chunks/{compose-ccrh32hd.js → compose-sprfv38c.js} +2 -2
  43. package/dist/chunks/{compose-pe0cgbv0.js → compose-t9fcqtby.js} +4 -4
  44. package/dist/chunks/{compose-g2a1f1yx.js → compose-tppkp915.js} +2 -2
  45. package/dist/chunks/{compose-5cmp34zp.js → compose-v46qmh60.js} +11 -11
  46. package/dist/chunks/{compose-gvrqkyn4.js → compose-w6zb11k1.js} +3 -3
  47. package/dist/chunks/{compose-m6nsbnkk.js → compose-xvbyp65f.js} +5 -5
  48. package/dist/chunks/compose-yfcb6w2h.js +58 -0
  49. package/dist/chunks/{compose-54svedb8.js → compose-yr19b453.js} +7 -7
  50. package/dist/chunks/{compose-0rx7ygxq.js → compose-zaanjpb7.js} +1 -1
  51. package/dist/src/agent/compaction.js +23 -23
  52. package/dist/src/agent/request.js +14 -14
  53. package/dist/src/agent/tool-runner.d.ts +2 -0
  54. package/dist/src/agent/tool-runner.js +18 -15
  55. package/dist/src/agent/transcript.js +20 -20
  56. package/dist/src/agent/turn.js +28 -27
  57. package/dist/src/api/connection.js +41 -40
  58. package/dist/src/api/head.js +27 -26
  59. package/dist/src/api/part.js +8 -8
  60. package/dist/src/api/server.js +30 -29
  61. package/dist/src/api/session.js +33 -32
  62. package/dist/src/builtins/delegation.js +2 -2
  63. package/dist/src/builtins/environment.js +1 -2
  64. package/dist/src/compose.js +50 -49
  65. package/dist/src/contract/parts.d.ts +4 -0
  66. package/dist/src/contract/parts.js +1 -1
  67. package/dist/src/contract/tools.d.ts +10 -1
  68. package/dist/src/contract/workspace.d.ts +2 -0
  69. package/dist/src/drive/execution.js +28 -27
  70. package/dist/src/engine/admission.js +10 -10
  71. package/dist/src/engine/batches.js +8 -8
  72. package/dist/src/engine/branch-summary.js +7 -7
  73. package/dist/src/engine/durable.js +6 -6
  74. package/dist/src/engine/fence.js +6 -6
  75. package/dist/src/engine/jobs.d.ts +1 -0
  76. package/dist/src/engine/jobs.js +15 -13
  77. package/dist/src/engine/move.js +9 -9
  78. package/dist/src/engine/part-definitions.js +2 -2
  79. package/dist/src/engine/principals.js +5 -5
  80. package/dist/src/engine/receipts.js +7 -7
  81. package/dist/src/engine/runs.js +11 -11
  82. package/dist/src/engine/start.js +22 -21
  83. package/dist/src/engine/waits.js +5 -5
  84. package/dist/src/env/browser.js +13 -13
  85. package/dist/src/env/environment.js +15 -15
  86. package/dist/src/env/mcp.js +17 -17
  87. package/dist/src/env/session-changes.d.ts +10 -0
  88. package/dist/src/env/session-changes.js +15 -0
  89. package/dist/src/env/trust.js +16 -16
  90. package/dist/src/env/workspaces.js +20 -19
  91. package/dist/src/env/worktrees.js +21 -20
  92. package/dist/src/extend/activation.js +21 -20
  93. package/dist/src/extend/hooks.js +8 -8
  94. package/dist/src/extend/models.js +13 -13
  95. package/dist/src/extend/plugin-api.js +5 -5
  96. package/dist/src/extend/plugin-runtime.js +27 -26
  97. package/dist/src/extend/registry.js +12 -12
  98. package/dist/src/extend/resources.js +17 -17
  99. package/dist/src/extend/settings.js +23 -22
  100. package/dist/src/extend/workspace-commands.js +28 -27
  101. package/dist/src/fold/commit.js +4 -4
  102. package/dist/src/fold/seen.js +5 -5
  103. package/dist/src/fold/view.js +6 -6
  104. package/dist/src/fold/watch.js +3 -3
  105. package/dist/src/harness.d.ts +1 -0
  106. package/dist/src/harness.js +51 -50
  107. package/dist/src/index.d.ts +1 -1
  108. package/dist/src/index.js +1 -1
  109. package/dist/src/server.js +49 -48
  110. package/dist/src/store/parts.js +2 -2
  111. package/dist/src/testing.js +52 -51
  112. package/package.json +6 -5
@@ -4,10 +4,6 @@ import {
4
4
  import {
5
5
  lineDiff2
6
6
  } from "./compose-j50h13pg.js";
7
- import {
8
- followedTrace2,
9
- traceparent2
10
- } from "./compose-sd0stm97.js";
11
7
 
12
8
  // src/builtins/environment.ts
13
9
  import { PatchEntrySchema, standard, writePatch } from "@nyte-ai/schema";
@@ -17,6 +13,8 @@ var READ_CHARS = 50 * 1024;
17
13
  var LIST_LIMIT = 500;
18
14
  var SHELL_BYTES = 32 * 1024;
19
15
  var PROGRESS_BYTES = 4 * 1024;
16
+ var PROGRESS_MS = 80;
17
+ var FIRST_OUTPUT_MS = 1000;
20
18
  var MIME_TYPES = new Map([
21
19
  ["png", "image/png"],
22
20
  ["jpg", "image/jpeg"],
@@ -49,7 +47,16 @@ var listParameters = standard(Type.Object({
49
47
  }));
50
48
  var bashParameters = standard(Type.Object({
51
49
  command: Type.String({ description: "The shell command to run." }),
52
- description: Type.Optional(Type.String({ description: "What the command does, in a few words, for the user." }))
50
+ description: Type.Optional(Type.String({ description: "What the command does, in a few words, for the user." })),
51
+ background: Type.Optional(Type.Boolean({
52
+ description: "Start the command and return a job id with its first output instead of waiting for it to exit. Use for servers, watchers, and other long-lived commands, without a trailing &. The command keeps running across turns, and you are told when it exits; read its output or stop it with the job tool. Do not use it to speed up ordinary commands."
53
+ }))
54
+ }));
55
+ var jobParameters = standard(Type.Object({
56
+ id: Type.String({ description: "The job id a background bash call returned." }),
57
+ action: Type.Enum(["output", "stop"], {
58
+ description: "output reads the job's state and latest output; stop ends it."
59
+ })
53
60
  }));
54
61
  var read = {
55
62
  name: "read",
@@ -177,21 +184,102 @@ var bash = {
177
184
  class: (args) => args.description === undefined ? { kind: "shell", command: args.command } : { kind: "shell", command: args.command, description: args.description },
178
185
  replay: "never",
179
186
  async execute(args, invocation) {
180
- const { env } = invocation;
181
- const trace = followedTrace2(invocation.session.id);
182
- const job = await env.exec(args.command, {
183
- cwd: env.cwd,
184
- signal: invocation.signal,
185
- env: trace === null ? undefined : { TRACEPARENT: traceparent2(trace) }
187
+ const { foreground, signal } = invocation;
188
+ const running = await foreground.start({
189
+ command: args.command,
190
+ title: args.description ?? args.command
191
+ });
192
+ const stop = () => void running.stop().catch(() => {
193
+ return;
194
+ });
195
+ signal.addEventListener("abort", stop, { once: true });
196
+ if (signal.aborted)
197
+ stop();
198
+ const shell = createShellOutput((tail) => invocation.progress({ text: tail }));
199
+ const frames = running.output()[Symbol.asyncIterator]();
200
+ try {
201
+ const exited = await shell.read(frames, args.background === true ? AbortSignal.any([foreground.released, AbortSignal.timeout(FIRST_OUTPUT_MS)]) : foreground.released);
202
+ if (!exited && (foreground.released.aborted || foreground.release())) {
203
+ await frames.return?.();
204
+ return text(shell.render(`[running in the background as job ${running.id}: you are told when it exits; the job tool reads its output or stops it]`));
205
+ }
206
+ if (!exited)
207
+ await shell.read(frames, new AbortController().signal);
208
+ const end = await running.settled();
209
+ const exit = end.kind === "exited" ? end.code ?? shell.code() : shell.code();
210
+ return text(shell.render(end.kind === "lost" ? "[the process was lost]" : `[exit code ${exit ?? "none"}${end.reason === "exited" ? "" : `, ${end.reason}`}]`));
211
+ } catch (error) {
212
+ stop();
213
+ throw error;
214
+ } finally {
215
+ signal.removeEventListener("abort", stop);
216
+ }
217
+ }
218
+ };
219
+ var job = {
220
+ name: "job",
221
+ description: "Read the state and latest output of a job a background bash call started, or stop it.",
222
+ parameters: jobParameters,
223
+ class: (args) => ({
224
+ kind: "custom",
225
+ label: args.action === "stop" ? `Stopping job ${args.id}` : `Reading job ${args.id}`
226
+ }),
227
+ effects: "none",
228
+ replay: "safe",
229
+ async execute(args, invocation) {
230
+ const { jobs } = invocation.workspace;
231
+ const find = async () => (await jobs.list()).find((view) => view.id === args.id && view.session === invocation.session.id);
232
+ const found = await find();
233
+ if (found === undefined)
234
+ return text(`This chat has no job ${args.id}.`);
235
+ if (args.action === "stop")
236
+ await invocation.workspace.job(found.id).stop();
237
+ const view = args.action === "stop" ? await find() ?? found : found;
238
+ const tail = view.tail.trimEnd();
239
+ const state = describeJobState(view.state);
240
+ return text(tail === "" ? `Job ${view.id} ${state}.` : `Job ${view.id} ${state}:
241
+ ${tail}`);
242
+ }
243
+ };
244
+ function describeJobState(state) {
245
+ if (state.kind === "running")
246
+ return "is running";
247
+ if (state.kind === "lost")
248
+ return "was lost with the host";
249
+ return state.reason === "exited" ? `exited with code ${state.code ?? "none"}` : `ended (${state.reason}) with code ${state.code ?? "none"}`;
250
+ }
251
+ function createShellOutput(progress) {
252
+ const chunks = [];
253
+ let kept = 0;
254
+ let dropped = 0;
255
+ let code = null;
256
+ let pending = null;
257
+ let published = Number.NEGATIVE_INFINITY;
258
+ let timer;
259
+ const publish = () => {
260
+ clearTimeout(timer);
261
+ timer = undefined;
262
+ published = Date.now();
263
+ progress(decodeOutputTail(chunks, PROGRESS_BYTES));
264
+ };
265
+ const follow = async (frames, until) => {
266
+ const detached = new Promise((resolve) => {
267
+ if (until.aborted)
268
+ resolve(null);
269
+ until.addEventListener("abort", () => resolve(null), { once: true });
186
270
  });
187
- const chunks = [];
188
- let kept = 0;
189
- let dropped = 0;
190
- let code = null;
191
- for await (const frame of job.output()) {
271
+ for (;; ) {
272
+ pending ??= frames.next();
273
+ const next = await Promise.race([pending, detached]);
274
+ if (next === null)
275
+ return false;
276
+ pending = null;
277
+ if (next.done === true)
278
+ return true;
279
+ const frame = next.value;
192
280
  if (frame.kind === "exit") {
193
281
  code = frame.code;
194
- break;
282
+ return true;
195
283
  }
196
284
  if (frame.kind === "gap")
197
285
  continue;
@@ -202,19 +290,38 @@ var bash = {
202
290
  kept -= first?.byteLength ?? 0;
203
291
  dropped += first?.byteLength ?? 0;
204
292
  }
205
- invocation.progress({ text: decodeOutputTail(chunks, PROGRESS_BYTES) });
293
+ if (timer !== undefined)
294
+ continue;
295
+ const wait = published + PROGRESS_MS - Date.now();
296
+ if (wait > 0)
297
+ timer = setTimeout(publish, wait);
298
+ else
299
+ publish();
206
300
  }
207
- const end = await job.settled();
208
- const exit = end.kind === "exited" ? end.code ?? code : code;
209
- const joined = joinBytes(chunks);
210
- const cut = Math.max(0, joined.byteLength - SHELL_BYTES);
211
- const output = new TextDecoder().decode(joined.subarray(cut)).trimEnd();
212
- const truncated = dropped + cut > 0 ? [`[truncated: the first ${dropped + cut} bytes of output are not shown]`] : [];
213
- const status = end.kind === "lost" ? "[the process was lost]" : `[exit code ${exit ?? "none"}${end.reason === "exited" ? "" : `, ${end.reason}`}]`;
214
- return text([...truncated, ...output === "" ? [] : [output], status].join(`
215
- `));
216
- }
217
- };
301
+ };
302
+ return {
303
+ async read(frames, until) {
304
+ try {
305
+ const ended = await follow(frames, until);
306
+ if (timer !== undefined)
307
+ publish();
308
+ return ended;
309
+ } finally {
310
+ clearTimeout(timer);
311
+ timer = undefined;
312
+ }
313
+ },
314
+ code: () => code,
315
+ render(status) {
316
+ const joined = joinBytes(chunks);
317
+ const cut = Math.max(0, joined.byteLength - SHELL_BYTES);
318
+ const output = new TextDecoder().decode(joined.subarray(cut)).trimEnd();
319
+ const truncated = dropped + cut > 0 ? [`[truncated: the first ${dropped + cut} bytes of output are not shown]`] : [];
320
+ return [...truncated, ...output === "" ? [] : [output], status].join(`
321
+ `);
322
+ }
323
+ };
324
+ }
218
325
  function joinBytes(chunks) {
219
326
  const joined = new Uint8Array(chunks.reduce((size, chunk) => size + chunk.byteLength, 0));
220
327
  let offset = 0;
@@ -233,7 +340,9 @@ function decodeOutputTail(chunks, limit) {
233
340
  tail.unshift(chunk);
234
341
  size += chunk.byteLength;
235
342
  }
236
- const text = new TextDecoder().decode(joinBytes(tail).subarray(Math.max(0, size - limit)));
343
+ const text = new TextDecoder().decode(joinBytes(tail).subarray(Math.max(0, size - limit)), {
344
+ stream: true
345
+ });
237
346
  const [, ...whole] = text.split(`
238
347
  `);
239
348
  return (size > limit && whole.length > 0 ? whole.join(`
@@ -241,7 +350,7 @@ function decodeOutputTail(chunks, limit) {
241
350
  }
242
351
  var environmentPlugin2 = {
243
352
  id: "environment",
244
- contribute: { tools: [read, write, edit, list, bash] },
353
+ contribute: { tools: [read, write, edit, list, bash, job] },
245
354
  activate(api) {
246
355
  const cwd = tryReadCwd(() => api.env);
247
356
  if (cwd !== null)
@@ -19,17 +19,17 @@ import {
19
19
  } from "./compose-bj54tkph.js";
20
20
  import {
21
21
  commit2
22
- } from "./compose-pnsvwd3m.js";
22
+ } from "./compose-bbhk8vnr.js";
23
23
  import {
24
24
  WORKSPACE_TRUST2
25
- } from "./compose-h3pch7ch.js";
25
+ } from "./compose-8pp3vtv0.js";
26
26
  import {
27
27
  SKILL_PATHS2,
28
28
  dropScans2
29
- } from "./compose-mamr4qwf.js";
29
+ } from "./compose-c4z4kp98.js";
30
30
  import {
31
31
  trustChanged2
32
- } from "./compose-tb5ywdfk.js";
32
+ } from "./compose-917xy085.js";
33
33
  import {
34
34
  settingInfos2,
35
35
  readSettingLayers2,
@@ -37,7 +37,7 @@ import {
37
37
  } from "./compose-qwbe95qs.js";
38
38
  import {
39
39
  publishCatalog2
40
- } from "./compose-r1pxdxbw.js";
40
+ } from "./compose-ae5t6v5b.js";
41
41
 
42
42
  // src/extend/settings.ts
43
43
  import { isJson, SdkError } from "@nyte-ai/schema";
@@ -15,7 +15,7 @@ import {
15
15
  } from "./compose-vn7b7fdj.js";
16
16
  import {
17
17
  settleAnswersFrom2
18
- } from "./compose-c2rnebv0.js";
18
+ } from "./compose-d95fwwvw.js";
19
19
  import {
20
20
  collectSessionEvents2
21
21
  } from "./compose-kwkna3cg.js";
@@ -9,13 +9,13 @@ import {
9
9
  } from "./compose-bj54tkph.js";
10
10
  import {
11
11
  sendNow2
12
- } from "./compose-pe0cgbv0.js";
12
+ } from "./compose-t9fcqtby.js";
13
13
  import {
14
14
  callable2
15
15
  } from "./compose-ry29956g.js";
16
16
  import {
17
17
  stepPluginApi2
18
- } from "./compose-0827b2k4.js";
18
+ } from "./compose-c9wxgbjp.js";
19
19
  import {
20
20
  settingInfos2
21
21
  } from "./compose-qwbe95qs.js";
@@ -6,7 +6,7 @@ import {
6
6
  } from "./compose-bj54tkph.js";
7
7
  import {
8
8
  compaction2
9
- } from "./compose-bjx8s01m.js";
9
+ } from "./compose-fqsqjbrf.js";
10
10
  import {
11
11
  decodeRunRecord2,
12
12
  decodePartRecord2
@@ -39,19 +39,19 @@ import {
39
39
  import {
40
40
  settling2,
41
41
  failedParts2
42
- } from "./compose-c2rnebv0.js";
42
+ } from "./compose-d95fwwvw.js";
43
43
  import {
44
44
  ZERO_USAGE2
45
45
  } from "./compose-84272xbk.js";
46
46
  import {
47
47
  commit2
48
- } from "./compose-pnsvwd3m.js";
48
+ } from "./compose-bbhk8vnr.js";
49
49
  import {
50
50
  withFold2
51
51
  } from "./compose-xhtgytrh.js";
52
52
  import {
53
53
  modelInfo2
54
- } from "./compose-exfx5b4d.js";
54
+ } from "./compose-mdwr0er9.js";
55
55
  import {
56
56
  extractUserText2
57
57
  } from "./compose-rxsqmcgq.js";
@@ -60,12 +60,12 @@ import {
60
60
  requestEvent2,
61
61
  rideRef2,
62
62
  complete2
63
- } from "./compose-ccrh32hd.js";
63
+ } from "./compose-sprfv38c.js";
64
64
  import {
65
65
  projectedCommit2,
66
66
  requestBody2,
67
67
  estimateTranscriptTokens2
68
- } from "./compose-4770pb1s.js";
68
+ } from "./compose-enq3x3rq.js";
69
69
 
70
70
  // src/agent/compaction.ts
71
71
  import { asId, isJsonObject, SdkError } from "@nyte-ai/schema";
@@ -13,7 +13,7 @@ import {
13
13
  } from "./compose-vn7b7fdj.js";
14
14
  import {
15
15
  publishSet2
16
- } from "./compose-rd5e5nxg.js";
16
+ } from "./compose-ad80nkkn.js";
17
17
 
18
18
  // src/fold/commit.ts
19
19
  import { SdkError } from "@nyte-ai/schema";
@@ -14,14 +14,14 @@ import {
14
14
  } from "./compose-vn7b7fdj.js";
15
15
  import {
16
16
  storedAnswer2
17
- } from "./compose-c2rnebv0.js";
17
+ } from "./compose-d95fwwvw.js";
18
18
  import {
19
19
  waitIndex2,
20
20
  wokenIndex2
21
21
  } from "./compose-0wq555bd.js";
22
22
  import {
23
23
  changeCall2
24
- } from "./compose-pnsvwd3m.js";
24
+ } from "./compose-bbhk8vnr.js";
25
25
  import {
26
26
  holdLease2
27
27
  } from "./compose-vzvm76dn.js";
@@ -30,7 +30,7 @@ import {
30
30
  readParkedWait2,
31
31
  waitingOn2,
32
32
  lapsed2
33
- } from "./compose-ks2rdteq.js";
33
+ } from "./compose-bz70g01d.js";
34
34
 
35
35
  // src/engine/durable.ts
36
36
  import { isJson, isJsonObject, SdkError } from "@nyte-ai/schema";
@@ -20,7 +20,7 @@ import {
20
20
  } from "./compose-vn7b7fdj.js";
21
21
  import {
22
22
  storedAnswer2
23
- } from "./compose-c2rnebv0.js";
23
+ } from "./compose-d95fwwvw.js";
24
24
  import {
25
25
  WAITS2,
26
26
  TIME2,
@@ -35,7 +35,7 @@ import {
35
35
  import {
36
36
  commit2,
37
37
  changeCall2
38
- } from "./compose-pnsvwd3m.js";
38
+ } from "./compose-bbhk8vnr.js";
39
39
  import {
40
40
  readRunEnd2
41
41
  } from "./compose-xhtgytrh.js";
@@ -11,18 +11,21 @@ import {
11
11
  import {
12
12
  classifyFileSupport2,
13
13
  readWorkspace2
14
- } from "./compose-qknd62yj.js";
14
+ } from "./compose-4ppmas7g.js";
15
15
  import {
16
16
  WORKSPACE_TRUST2,
17
17
  projectTrust2
18
- } from "./compose-h3pch7ch.js";
18
+ } from "./compose-8pp3vtv0.js";
19
19
 
20
20
  // src/extend/resources.ts
21
21
  import { SdkError, standard } from "@nyte-ai/schema";
22
22
  import { Type } from "typebox";
23
+ import { isMap, isScalar, parseDocument } from "yaml";
23
24
  var CONTEXT_NAMES = ["AGENTS.override.md", "AGENTS.md", "CLAUDE.md"];
24
25
  var SKILL_DIRECTORIES = [".nyte/skills", ".agents/skills"];
25
26
  var FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/;
27
+ var ABSOLUTE = /^(?:\/|[A-Za-z]:[\\/])/;
28
+ var LINK_HOPS = 8;
26
29
  var SKILL_PATHS2 = "skills.paths";
27
30
  var scanIssues = new WeakMap;
28
31
  async function scanResources2(kernel, session) {
@@ -169,13 +172,13 @@ async function scan(kernel, workspace, attach) {
169
172
  const root = env !== null && env.cwd.startsWith("/") ? env.cwd : null;
170
173
  const home = kernel.home;
171
174
  const [projectSkills, userSkills, pathSkills] = await Promise.all([
172
- project === null ? [] : skillsIn(project, SKILL_DIRECTORIES, "project"),
173
- user === null ? [] : skillsIn(user, SKILL_DIRECTORIES, "user"),
174
- user === null ? [] : skillsAt(user, await skillPaths(kernel.store))
175
+ project === null ? [] : skillsIn(project, SKILL_DIRECTORIES, "project", root),
176
+ user === null ? [] : skillsIn(user, SKILL_DIRECTORIES, "user", home),
177
+ user === null ? [] : skillsAt(user, await skillPaths(kernel.store), home)
175
178
  ]);
176
179
  const { kept: skills, dropped } = byName([
177
180
  ...projectSkills,
178
- ...[...userSkills, ...pathSkills].map((skill) => home === null || /^(?:\/|[A-Za-z]:[\\/])/.test(skill.location) ? skill : { ...skill, location: join(home, skill.location) })
181
+ ...[...userSkills, ...pathSkills].map((skill) => home === null || ABSOLUTE.test(skill.location) ? skill : { ...skill, location: join(home, skill.location) })
179
182
  ]);
180
183
  const issues = dropped.map(({ item, over }) => ({
181
184
  severity: "warning",
@@ -269,21 +272,57 @@ async function skillPaths(store) {
269
272
  const value = await readKv2(store, kvRef2("host", "settings", SKILL_PATHS2));
270
273
  return Array.isArray(value) ? value.flatMap((entry) => typeof entry === "string" ? [entry] : []) : [];
271
274
  }
272
- async function skillsIn(files, directories, scope) {
273
- const listed = await Promise.all(directories.map(async (directory) => (await listDirectChildren(files, directory, "directory")).map((name) => ({
274
- name,
275
- location: `${directory}/${name}/SKILL.md`
275
+ async function skillsIn(files, directories, scope, root) {
276
+ const listed = await Promise.all(directories.map(async (directory) => (await listDirectChildren(files, directory, ["directory", "symlink"])).map((entry) => ({
277
+ ...entry,
278
+ path: `${directory}/${entry.name}`
276
279
  }))));
277
- const read = await Promise.all(listed.flat().map(async ({ name, location }) => {
280
+ const candidates = listed.flat().toSorted((left, right) => Number(left.kind === "symlink") - Number(right.kind === "symlink"));
281
+ const targets = await Promise.all(candidates.map(async ({ kind, path }) => kind === "directory" ? resolvePath(root, path) : linkedDirectory(files, path, root)));
282
+ const loaded = new Set;
283
+ const read = await Promise.all(candidates.map(async ({ name, path }, index) => {
284
+ const target = targets[index];
285
+ if (target === undefined || target === null || loaded.has(target))
286
+ return [];
287
+ loaded.add(target);
288
+ const location = `${path}/SKILL.md`;
278
289
  const content = await readText(files, location);
279
290
  return content === null ? [] : [parseSkillMetadata(content, name, location, scope)];
280
291
  }));
281
292
  return read.flat();
282
293
  }
283
- async function skillsAt(files, paths) {
294
+ async function linkedDirectory(files, path, root) {
295
+ let at = resolvePath(root, path);
296
+ for (let hop = 0;hop < LINK_HOPS; hop += 1) {
297
+ const found = await files.stat(at).catch(() => null);
298
+ if (found?.kind === "directory")
299
+ return at;
300
+ if (found?.kind !== "symlink" || found.target === undefined)
301
+ return null;
302
+ const parent = at.slice(0, Math.max(at.lastIndexOf("/"), 0));
303
+ at = resolvePath(root, ABSOLUTE.test(found.target) ? found.target : join(parent, found.target));
304
+ }
305
+ return null;
306
+ }
307
+ function resolvePath(root, path) {
308
+ const full = root === null || ABSOLUTE.test(path) ? path : join(root, path);
309
+ const absolute = full.startsWith("/");
310
+ const parts = [];
311
+ for (const part of full.split("/")) {
312
+ if (part === "" || part === "." || part === ".." && absolute && parts.length === 0)
313
+ continue;
314
+ if (part === ".." && parts.length > 0 && parts.at(-1) !== "..")
315
+ parts.pop();
316
+ else
317
+ parts.push(part);
318
+ }
319
+ const normal = `${absolute ? "/" : ""}${parts.join("/")}`;
320
+ return root !== null && normal.startsWith(join(root, "")) ? normal.slice(join(root, "").length) : normal;
321
+ }
322
+ async function skillsAt(files, paths, root) {
284
323
  const found = await Promise.all(userSkillPaths(paths).map(async (path) => {
285
324
  if (!path.endsWith(".md"))
286
- return skillsIn(files, [path], "path");
325
+ return skillsIn(files, [path], "path", root);
287
326
  const content = await readText(files, path);
288
327
  const name = path.split("/").at(-1)?.slice(0, -".md".length) ?? path;
289
328
  return content === null ? [] : [parseSkillMetadata(content, name, path, "path")];
@@ -291,8 +330,8 @@ async function skillsAt(files, paths) {
291
330
  return found.flat();
292
331
  }
293
332
  async function promptsIn(files, scope) {
294
- const names = await listDirectChildren(files, ".nyte/prompts", "file");
295
- return names.flatMap((name) => name.endsWith(".md") ? [{ name: name.slice(0, -".md".length), location: `.nyte/prompts/${name}`, scope }] : []);
333
+ const entries = await listDirectChildren(files, ".nyte/prompts", ["file"]);
334
+ return entries.flatMap(({ name }) => name.endsWith(".md") ? [{ name: name.slice(0, -".md".length), location: `.nyte/prompts/${name}`, scope }] : []);
296
335
  }
297
336
  function parseSkillMetadata(content, fallback, location, scope) {
298
337
  const fields = frontmatter(content);
@@ -322,18 +361,18 @@ async function firstContext(files, at) {
322
361
  }));
323
362
  return read.find((context) => context !== null) ?? null;
324
363
  }
325
- async function listDirectChildren(files, directory, kind) {
326
- const names = new Set;
364
+ async function listDirectChildren(files, directory, kinds) {
365
+ const children = new Map;
327
366
  for await (const frame of files.scan({ directory })) {
328
367
  if (frame.kind !== "entries")
329
368
  continue;
330
369
  for (const entry of frame.entries) {
331
370
  const relative = entry.path.startsWith(`${directory}/`) ? entry.path.slice(directory.length + 1) : entry.path;
332
- if (entry.kind === kind && relative !== "" && !relative.includes("/"))
333
- names.add(relative);
371
+ if (kinds.includes(entry.kind) && relative !== "" && !relative.includes("/"))
372
+ children.set(relative, entry.kind);
334
373
  }
335
374
  }
336
- return [...names].sort();
375
+ return [...children].map(([name, kind]) => ({ name, kind })).sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0);
337
376
  }
338
377
  async function readText(files, path) {
339
378
  const document = await files.read(path).catch((error) => {
@@ -344,9 +383,25 @@ async function readText(files, path) {
344
383
  return document?.kind === "text" ? document.contents : null;
345
384
  }
346
385
  function frontmatter(content) {
347
- const fields = new Map;
348
386
  const block = FRONTMATTER.exec(content)?.[1];
349
- for (const line of block?.split(/\r?\n/) ?? []) {
387
+ if (block === undefined)
388
+ return new Map;
389
+ const document = parseDocument(block);
390
+ if (document.errors.length > 0 || !isMap(document.contents))
391
+ return frontmatterLines(block);
392
+ const fields = new Map;
393
+ for (const { key, value } of document.contents.items) {
394
+ if (!isScalar(key) || !isScalar(value))
395
+ continue;
396
+ const text = value.value === null ? "" : value.toString().trim();
397
+ if (text !== "")
398
+ fields.set(String(key.value), text);
399
+ }
400
+ return fields;
401
+ }
402
+ function frontmatterLines(block) {
403
+ const fields = new Map;
404
+ for (const line of block.split(/\r?\n/)) {
350
405
  const pair = /^([A-Za-z][\w-]*):\s*(.*)$/.exec(line);
351
406
  const key = pair?.[1];
352
407
  const value = pair?.[2]?.trim();
@@ -11,7 +11,7 @@ import {
11
11
  } from "./compose-vn7b7fdj.js";
12
12
  import {
13
13
  commit2
14
- } from "./compose-pnsvwd3m.js";
14
+ } from "./compose-bbhk8vnr.js";
15
15
 
16
16
  // src/extend/plugin-api.ts
17
17
  import { isJsonObject, SdkError } from "@nyte-ai/schema";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./compose-bj54tkph.js";
4
4
  import {
5
5
  tool2
6
- } from "./compose-bjx8s01m.js";
6
+ } from "./compose-fqsqjbrf.js";
7
7
  import {
8
8
  decodePartRecord2
9
9
  } from "./compose-gxjc6vz9.js";
@@ -14,16 +14,16 @@ import {
14
14
  } from "./compose-vn7b7fdj.js";
15
15
  import {
16
16
  commit2
17
- } from "./compose-pnsvwd3m.js";
17
+ } from "./compose-bbhk8vnr.js";
18
18
  import {
19
19
  readWorkspace2,
20
20
  workspaceRecords2
21
- } from "./compose-qknd62yj.js";
21
+ } from "./compose-4ppmas7g.js";
22
22
  import {
23
23
  sessionsOn2,
24
24
  byIdentity2,
25
25
  changed2
26
- } from "./compose-tb5ywdfk.js";
26
+ } from "./compose-917xy085.js";
27
27
 
28
28
  // src/env/worktrees.ts
29
29
  import { asId, SdkError } from "@nyte-ai/schema";
@@ -10,7 +10,7 @@ import {
10
10
  tool2,
11
11
  compaction2,
12
12
  branchSummary2
13
- } from "./compose-bjx8s01m.js";
13
+ } from "./compose-fqsqjbrf.js";
14
14
  import {
15
15
  decodeRunRecord2
16
16
  } from "./compose-gxjc6vz9.js";
@@ -32,13 +32,13 @@ import {
32
32
  } from "./compose-c4238qkb.js";
33
33
  import {
34
34
  scanResources2
35
- } from "./compose-mamr4qwf.js";
35
+ } from "./compose-c4z4kp98.js";
36
36
  import {
37
37
  hiddenOwners2
38
38
  } from "./compose-bd8c5n7k.js";
39
39
  import {
40
40
  toolSource2
41
- } from "./compose-r1pxdxbw.js";
41
+ } from "./compose-ae5t6v5b.js";
42
42
 
43
43
  // src/agent/transcript.ts
44
44
  import { isJsonObject } from "@nyte-ai/schema";
@@ -16,16 +16,16 @@ import {
16
16
  } from "./compose-vn7b7fdj.js";
17
17
  import {
18
18
  commit2
19
- } from "./compose-pnsvwd3m.js";
19
+ } from "./compose-bbhk8vnr.js";
20
20
  import {
21
21
  withFold2
22
22
  } from "./compose-xhtgytrh.js";
23
23
  import {
24
24
  waitFor2
25
- } from "./compose-ks2rdteq.js";
25
+ } from "./compose-bz70g01d.js";
26
26
  import {
27
27
  stopRun2
28
- } from "./compose-gvrqkyn4.js";
28
+ } from "./compose-w6zb11k1.js";
29
29
 
30
30
  // src/engine/receipts.ts
31
31
  import { asId, SdkError } from "@nyte-ai/schema";
@@ -44,7 +44,7 @@ var thinking2 = definePart2({
44
44
  var tool2 = definePart2({
45
45
  kind: "tool",
46
46
  state: ToolPartStateSchema,
47
- actions: { stop: { input: EMPTY_INPUT } },
47
+ actions: { stop: { input: EMPTY_INPUT }, background: { input: EMPTY_INPUT } },
48
48
  fallback: (state, { id }) => `${clip(state.name)} ${state.phase}${state.phase === "settled" ? ` ${state.outcome.kind}` : ""} [${id}]`
49
49
  });
50
50
  var compaction2 = definePart2({
@@ -6,10 +6,10 @@ import {
6
6
  } from "./compose-zfjxkavf.js";
7
7
  import {
8
8
  readWorkspace2
9
- } from "./compose-qknd62yj.js";
9
+ } from "./compose-4ppmas7g.js";
10
10
  import {
11
11
  projectTrust2
12
- } from "./compose-h3pch7ch.js";
12
+ } from "./compose-8pp3vtv0.js";
13
13
 
14
14
  // src/env/mcp.ts
15
15
  import { SdkError } from "@nyte-ai/schema";