@sentry/junior 0.96.0 → 0.97.1

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 (135) hide show
  1. package/dist/{agent-hooks-5URSMY3O.js → agent-hooks-XSUIVRQS.js} +8 -6
  2. package/dist/{reporting → api}/conversations/activity.d.ts +1 -1
  3. package/dist/api/conversations/detail-projection.d.ts +10 -0
  4. package/dist/api/conversations/detail.d.ts +3 -0
  5. package/dist/api/conversations/detail.query.d.ts +3 -0
  6. package/dist/api/conversations/list.d.ts +3 -0
  7. package/dist/api/conversations/list.query.d.ts +94 -0
  8. package/dist/api/conversations/projection.d.ts +14 -0
  9. package/dist/api/conversations/schema.d.ts +683 -0
  10. package/dist/{reporting → api}/conversations/shared.d.ts +1 -5
  11. package/dist/api/conversations/stats.d.ts +3 -0
  12. package/dist/api/conversations/stats.query.d.ts +3 -0
  13. package/dist/api/conversations/subagent.d.ts +3 -0
  14. package/dist/{reporting → api}/conversations/transcript.d.ts +4 -4
  15. package/dist/api/people/list.d.ts +1 -2
  16. package/dist/api/people/list.query.d.ts +3 -4
  17. package/dist/api/people/profile.d.ts +1 -2
  18. package/dist/api/people/profile.query.d.ts +3 -4
  19. package/dist/api/people/schema.d.ts +193 -0
  20. package/dist/api/people/shared.d.ts +31 -9
  21. package/dist/api/schema.d.ts +20 -0
  22. package/dist/api/schema.js +50 -0
  23. package/dist/api-reference.d.ts +4 -3
  24. package/dist/api.d.ts +3 -0
  25. package/dist/api.js +156 -0
  26. package/dist/app.d.ts +1 -4
  27. package/dist/app.js +101 -367
  28. package/dist/build/virtual-config.d.ts +2 -2
  29. package/dist/{catalog-runtime-MSMAYYIK.js → catalog-runtime-PFHVMHDR.js} +3 -2
  30. package/dist/chat/agent/resume.d.ts +3 -1
  31. package/dist/chat/agent/tools.d.ts +2 -1
  32. package/dist/chat/config.d.ts +1 -8
  33. package/dist/chat/conversations/history.d.ts +241 -27
  34. package/dist/chat/conversations/legacy-advisor-session.d.ts +7 -0
  35. package/dist/chat/conversations/legacy-import.d.ts +2 -2
  36. package/dist/chat/conversations/projection.d.ts +19 -3
  37. package/dist/chat/conversations/sql/legacy-history-import.d.ts +1 -1
  38. package/dist/chat/conversations/sql/store.d.ts +15 -9
  39. package/dist/chat/conversations/store.d.ts +9 -4
  40. package/dist/chat/model-profile.d.ts +14 -0
  41. package/dist/chat/pi/transcript.d.ts +5 -3
  42. package/dist/chat/resource-events/store.d.ts +2 -2
  43. package/dist/chat/services/context-compaction.d.ts +15 -0
  44. package/dist/chat/services/turn-result.d.ts +1 -0
  45. package/dist/chat/services/turn-session-record.d.ts +6 -6
  46. package/dist/chat/state/turn-session.d.ts +16 -5
  47. package/dist/chat/task-execution/store.d.ts +2 -2
  48. package/dist/chat/tools/handoff/tool.d.ts +45 -0
  49. package/dist/chat/tools/types.d.ts +7 -2
  50. package/dist/chat/usage.d.ts +25 -25
  51. package/dist/{chunk-RITD7E5L.js → chunk-35BNLDOJ.js} +338 -577
  52. package/dist/{chunk-PMNN6ST4.js → chunk-3ECW2K2O.js} +7 -2
  53. package/dist/{chunk-5C6XTTFI.js → chunk-3F4OPKGF.js} +89 -55
  54. package/dist/chunk-3V7OFJZC.js +264 -0
  55. package/dist/chunk-4ZNGQH7C.js +25 -0
  56. package/dist/{chunk-S5KZ5LPG.js → chunk-5HLDPVYS.js} +14 -447
  57. package/dist/{chunk-DZENG5ML.js → chunk-6U26PYI5.js} +24 -14
  58. package/dist/chunk-AUUCAFDE.js +546 -0
  59. package/dist/{chunk-6APU57E6.js → chunk-B3IT5END.js} +41 -260
  60. package/dist/chunk-CEA3A3UA.js +86 -0
  61. package/dist/{chunk-YDT7SNCN.js → chunk-D5KZYS4T.js} +1 -1
  62. package/dist/{chunk-YDVEH3SB.js → chunk-EEZCY5WX.js} +78 -28
  63. package/dist/{chunk-2NAZZPPS.js → chunk-EOWXRY5E.js} +1 -1
  64. package/dist/{chunk-GQ3GK22G.js → chunk-FBHZJFHI.js} +2 -2
  65. package/dist/{chunk-CZEX6KIQ.js → chunk-G3E7SCME.js} +0 -23
  66. package/dist/chunk-GUAP3H7O.js +319 -0
  67. package/dist/{chunk-BYZWPRJA.js → chunk-H66UCBPW.js} +6 -4
  68. package/dist/{chunk-L7CDEIVJ.js → chunk-LMJPRYHP.js} +4 -2
  69. package/dist/chunk-LUAE4MGW.js +199 -0
  70. package/dist/{chunk-GY34VGP5.js → chunk-LVA4I4H7.js} +3 -1
  71. package/dist/chunk-LVUKF5CE.js +63 -0
  72. package/dist/{chunk-AAZXTVJT.js → chunk-NG2AV7IB.js} +2 -72
  73. package/dist/chunk-ON6YKIQ7.js +260 -0
  74. package/dist/chunk-PDO5BLNM.js +22 -0
  75. package/dist/chunk-QNVHH5PU.js +20 -0
  76. package/dist/{chunk-P3YFQLEN.js → chunk-T533JLM3.js} +8 -10
  77. package/dist/chunk-UAMKJPDF.js +11 -0
  78. package/dist/chunk-VFH4ZKZT.js +66 -0
  79. package/dist/{chunk-UKHVMPX5.js → chunk-WGXMTFNU.js} +15 -17
  80. package/dist/{chunk-MNTINMWR.js → chunk-WJOSZOON.js} +184 -300
  81. package/dist/chunk-WTYEKPXU.js +451 -0
  82. package/dist/{chunk-IYM2SIVG.js → chunk-XIRPQQVE.js} +605 -363
  83. package/dist/cli/chat.js +24 -21
  84. package/dist/cli/check.js +4 -3
  85. package/dist/cli/init.js +12 -0
  86. package/dist/cli/plugins.js +12 -9
  87. package/dist/cli/snapshot-warmup.js +8 -6
  88. package/dist/cli/upgrade.js +265 -137
  89. package/dist/db/db.d.ts +4 -0
  90. package/dist/db/schema/conversations.d.ts +128 -0
  91. package/dist/db/schema.d.ts +129 -60
  92. package/dist/{db-2D6RMG67.js → db-BWXYIKFQ.js} +3 -3
  93. package/dist/detail-GA6NXWQJ.js +43 -0
  94. package/dist/discovery-RMHYSRL7.js +43 -0
  95. package/dist/handlers/health.d.ts +3 -0
  96. package/dist/instrumentation.js +1 -1
  97. package/dist/{legacy-import-VZ2MEGP7.js → legacy-import-3NQJVGQL.js} +4 -4
  98. package/dist/{api/people/list.js → list-A3WFRIYX.js} +26 -16
  99. package/dist/list-UXJI5Q5X.js +27 -0
  100. package/dist/nitro.d.ts +1 -1
  101. package/dist/nitro.js +2 -1
  102. package/dist/plugin-conversations-DDNGC35A.js +36 -0
  103. package/dist/{api/people/profile.js → profile-4RYDXWTF.js} +33 -18
  104. package/dist/reporting/plugin-conversations.d.ts +3 -0
  105. package/dist/reporting-schema.d.ts +140 -0
  106. package/dist/reporting.d.ts +12 -81
  107. package/dist/{runner-JZBRQP4F.js → runner-JALSYH2P.js} +17 -12
  108. package/dist/skills-MAZXZ2KE.js +26 -0
  109. package/dist/stats-XKXH3PTY.js +217 -0
  110. package/dist/subagent-TZ55XY37.js +48 -0
  111. package/dist/usage-schema.d.ts +25 -0
  112. package/dist/{validation-6XOOQGME.js → validation-FMEAEKCY.js} +4 -3
  113. package/migrations/0000_initial.sql +115 -0
  114. package/migrations/0001_conversation_metrics.sql +4 -0
  115. package/migrations/README.md +12 -30
  116. package/migrations/meta/0000_snapshot.json +1 -33
  117. package/migrations/meta/0001_snapshot.json +972 -0
  118. package/migrations/meta/_journal.json +9 -2
  119. package/package.json +13 -17
  120. package/dist/api/people/types.d.ts +0 -85
  121. package/dist/chat/advisor-request.d.ts +0 -4
  122. package/dist/chat/conversations/sql/migrations.d.ts +0 -22
  123. package/dist/chat/tools/advisor/session-store.d.ts +0 -9
  124. package/dist/chat/tools/advisor/tool.d.ts +0 -72
  125. package/dist/chunk-RAIB6WSG.js +0 -142
  126. package/dist/chunk-WM6KHPBQ.js +0 -48
  127. package/dist/db/schema/migrations.d.ts +0 -58
  128. package/dist/reporting/conversations/context.d.ts +0 -8
  129. package/dist/reporting/conversations/details.d.ts +0 -6
  130. package/dist/reporting/conversations/index.d.ts +0 -4
  131. package/dist/reporting/conversations/statistics.d.ts +0 -4
  132. package/dist/reporting/conversations/summaries.d.ts +0 -20
  133. package/dist/reporting/conversations/types.d.ts +0 -191
  134. package/dist/reporting/conversations.d.ts +0 -1
  135. package/dist/reporting.js +0 -1155
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  pluginCatalogRuntime
3
- } from "./chunk-L7CDEIVJ.js";
3
+ } from "./chunk-LMJPRYHP.js";
4
4
  import {
5
5
  logWarn
6
6
  } from "./chunk-I35CTGPO.js";
7
7
  import {
8
8
  skillRoots
9
- } from "./chunk-6APU57E6.js";
9
+ } from "./chunk-3V7OFJZC.js";
10
10
 
11
11
  // src/chat/skills.ts
12
12
  import fs from "fs/promises";
@@ -157,6 +157,9 @@ function parseSkillFile(raw, expectedName) {
157
157
  }
158
158
  var SKILL_CACHE_TTL_MS = 5e3;
159
159
  var skillCache = null;
160
+ function resetSkillDiscoveryCache() {
161
+ skillCache = null;
162
+ }
160
163
  function resolveSkillRoots(options) {
161
164
  const additionalRoots = options?.additionalRoots ?? [];
162
165
  const envRoots = process.env.SKILL_DIRS?.split(path.delimiter).filter(Boolean) ?? [];
@@ -368,7 +371,9 @@ async function loadSkillsByName(skillNames, available) {
368
371
  }
369
372
 
370
373
  export {
374
+ stripFrontmatter,
371
375
  parseSkillFile,
376
+ resetSkillDiscoveryCache,
372
377
  discoverSkills,
373
378
  parseSkillInvocation,
374
379
  findSkillByName,
@@ -9,14 +9,16 @@ import {
9
9
  juniorConversationMessages,
10
10
  juniorConversations,
11
11
  legacyActorProvenance,
12
+ piMessageSchema,
12
13
  readSessionLogEntries
13
- } from "./chunk-RITD7E5L.js";
14
+ } from "./chunk-35BNLDOJ.js";
14
15
  import {
15
16
  botConfig,
16
17
  escapeXml,
17
18
  getStateAdapter,
18
- resolveGatewayModel
19
- } from "./chunk-YDVEH3SB.js";
19
+ resolveGatewayModel,
20
+ unescapeXml
21
+ } from "./chunk-EEZCY5WX.js";
20
22
  import {
21
23
  logWarn,
22
24
  setSpanAttributes
@@ -28,7 +30,7 @@ import {
28
30
  // src/chat/conversations/legacy-import.ts
29
31
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
30
32
  import { eq as eq2 } from "drizzle-orm";
31
- import { z } from "zod";
33
+ import { z as z2 } from "zod";
32
34
 
33
35
  // src/chat/conversations/visible-compactions.ts
34
36
  import { isDeepStrictEqual } from "util";
@@ -462,7 +464,7 @@ async function hydrateConversationMessages(args) {
462
464
  args.conversation.messages = [];
463
465
  return;
464
466
  }
465
- const { ensureLegacyConversationImport: ensureLegacyConversationImport2 } = await import("./legacy-import-VZ2MEGP7.js");
467
+ const { ensureLegacyConversationImport: ensureLegacyConversationImport2 } = await import("./legacy-import-3NQJVGQL.js");
466
468
  await ensureLegacyConversationImport2({ conversationId: args.conversationId });
467
469
  await hydrateConversationCompactions({
468
470
  conversation: args.conversation,
@@ -495,34 +497,21 @@ async function persistConversationMessages(args) {
495
497
  }
496
498
  }
497
499
 
498
- // src/chat/state/ttl.ts
499
- var JUNIOR_THREAD_STATE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
500
-
501
- // src/chat/tools/advisor/session-store.ts
502
- var ADVISOR_SESSION_TTL_MS = JUNIOR_THREAD_STATE_TTL_MS;
503
- function cloneMessages(messages) {
504
- return structuredClone(messages);
505
- }
506
- function getAdvisorSessionKey(conversationId) {
500
+ // src/chat/conversations/legacy-advisor-session.ts
501
+ import { z } from "zod";
502
+ var legacyAdvisorMessagesSchema = z.array(piMessageSchema);
503
+ function key(conversationId) {
507
504
  return `junior:${conversationId}:advisor_session`;
508
505
  }
509
- function createStateAdvisorSessionStore() {
506
+ function createLegacyAdvisorSessionReader() {
510
507
  return {
511
508
  load: async (conversationId) => {
512
509
  const stateAdapter = getStateAdapter();
513
510
  await stateAdapter.connect();
514
- const messages = await stateAdapter.get(
515
- getAdvisorSessionKey(conversationId)
516
- ) ?? [];
517
- return cloneMessages(messages);
518
- },
519
- save: async (conversationId, messages) => {
520
- const stateAdapter = getStateAdapter();
521
- await stateAdapter.connect();
522
- await stateAdapter.set(
523
- getAdvisorSessionKey(conversationId),
524
- cloneMessages(messages),
525
- ADVISOR_SESSION_TTL_MS
511
+ return legacyAdvisorMessagesSchema.parse(
512
+ structuredClone(
513
+ await stateAdapter.get(key(conversationId)) ?? []
514
+ )
526
515
  );
527
516
  }
528
517
  };
@@ -531,6 +520,10 @@ function createStateAdvisorSessionStore() {
531
520
  // src/chat/conversations/sql/legacy-history-import.ts
532
521
  import { eq, sql } from "drizzle-orm";
533
522
  var INITIAL_SESSION_ID = "session_0";
523
+ var ADVISOR_TASK_OPEN = "<advisor-task>\n";
524
+ var ADVISOR_TASK_CLOSE = "\n</advisor-task>";
525
+ var ADVISOR_CONTEXT_OPEN = "<executor-context>\n";
526
+ var ADVISOR_CONTEXT_CLOSE = "\n</executor-context>";
534
527
  function importedAdvisorChildConversationId(parentConversationId) {
535
528
  return `advisor:${parentConversationId}`;
536
529
  }
@@ -542,6 +535,47 @@ function messageTimestampMs(message) {
542
535
  const timestamp = message.timestamp;
543
536
  return typeof timestamp === "number" ? timestamp : void 0;
544
537
  }
538
+ function readAdvisorRequest(text) {
539
+ if (!text.startsWith(ADVISOR_TASK_OPEN) || !text.endsWith(ADVISOR_CONTEXT_CLOSE)) {
540
+ return void 0;
541
+ }
542
+ const taskEnd = text.indexOf(ADVISOR_TASK_CLOSE, ADVISOR_TASK_OPEN.length);
543
+ if (taskEnd < 0) {
544
+ return void 0;
545
+ }
546
+ const contextStart = taskEnd + ADVISOR_TASK_CLOSE.length + 2;
547
+ if (!text.startsWith(ADVISOR_CONTEXT_OPEN, contextStart)) {
548
+ return void 0;
549
+ }
550
+ const task = text.slice(ADVISOR_TASK_OPEN.length, taskEnd);
551
+ const context = text.slice(
552
+ contextStart + ADVISOR_CONTEXT_OPEN.length,
553
+ -ADVISOR_CONTEXT_CLOSE.length
554
+ );
555
+ return `${unescapeXml(task)}
556
+
557
+ Executor context:
558
+ ${unescapeXml(context)}`;
559
+ }
560
+ function normalizeAdvisorMessage(message) {
561
+ const record = message;
562
+ if (record.role !== "user" || !Array.isArray(record.content)) {
563
+ return message;
564
+ }
565
+ let changed = false;
566
+ const content = record.content.map((part) => {
567
+ if (!part || typeof part !== "object" || part.type !== "text" || typeof part.text !== "string") {
568
+ return part;
569
+ }
570
+ const text = readAdvisorRequest(part.text);
571
+ if (text === void 0) {
572
+ return part;
573
+ }
574
+ changed = true;
575
+ return { ...part, text };
576
+ });
577
+ return changed ? { ...record, content } : message;
578
+ }
545
579
  function piEntryProvenance(entry) {
546
580
  if (entry.provenance) {
547
581
  return entry.provenance;
@@ -693,12 +727,15 @@ function convertLegacySessionLog(args) {
693
727
  };
694
728
  }
695
729
  function convertAdvisorMessages(messages, fallbackCreatedAtMs) {
696
- return messages.map((message, seq) => ({
697
- seq,
698
- contextEpoch: 0,
699
- entry: { type: "pi_message", message, provenance: contextProvenance },
700
- createdAtMs: messageTimestampMs(message) ?? fallbackCreatedAtMs
701
- }));
730
+ return messages.map((sourceMessage, seq) => {
731
+ const message = normalizeAdvisorMessage(sourceMessage);
732
+ return {
733
+ seq,
734
+ contextEpoch: 0,
735
+ entry: { type: "pi_message", message, provenance: contextProvenance },
736
+ createdAtMs: messageTimestampMs(message) ?? fallbackCreatedAtMs
737
+ };
738
+ });
702
739
  }
703
740
  function messageRole(entry) {
704
741
  if (entry.type !== "pi_message") {
@@ -835,25 +872,25 @@ async function ensureChildConversationRow(executor, childConversationId, parentC
835
872
  }
836
873
 
837
874
  // src/chat/conversations/legacy-import.ts
838
- var legacyVisibleMessageSchema = z.object({
839
- id: z.string(),
840
- role: z.enum(["user", "assistant", "system"]),
841
- text: z.string(),
842
- createdAtMs: z.number().finite(),
843
- author: z.object({}).passthrough().optional(),
844
- meta: z.object({}).passthrough().optional()
875
+ var legacyVisibleMessageSchema = z2.object({
876
+ id: z2.string(),
877
+ role: z2.enum(["user", "assistant", "system"]),
878
+ text: z2.string(),
879
+ createdAtMs: z2.number().finite(),
880
+ author: z2.object({}).passthrough().optional(),
881
+ meta: z2.object({}).passthrough().optional()
845
882
  });
846
- var legacyCompactionSchema = z.object({
847
- coveredMessageIds: z.array(z.string()),
848
- createdAtMs: z.number().finite(),
849
- id: z.string(),
850
- summary: z.string()
883
+ var legacyCompactionSchema = z2.object({
884
+ coveredMessageIds: z2.array(z2.string()),
885
+ createdAtMs: z2.number().finite(),
886
+ id: z2.string(),
887
+ summary: z2.string()
851
888
  });
852
- var legacyThreadStateSnapshotSchema = z.object({
853
- conversation: z.object({
854
- compactions: z.array(legacyCompactionSchema).optional(),
855
- messages: z.array(legacyVisibleMessageSchema).optional(),
856
- stats: z.object({ updatedAtMs: z.number().finite().optional() }).passthrough().optional()
889
+ var legacyThreadStateSnapshotSchema = z2.object({
890
+ conversation: z2.object({
891
+ compactions: z2.array(legacyCompactionSchema).optional(),
892
+ messages: z2.array(legacyVisibleMessageSchema).optional(),
893
+ stats: z2.object({ updatedAtMs: z2.number().finite().optional() }).passthrough().optional()
857
894
  }).passthrough().optional()
858
895
  });
859
896
  async function loadThreadStateSnapshot(conversationId) {
@@ -911,9 +948,7 @@ async function importConversationFromLegacy(conversationId, deps) {
911
948
  return { imported: false };
912
949
  }
913
950
  const hasAdvisor = entries.some((entry) => entry.type === "subagent_started");
914
- const advisorMessages = hasAdvisor ? await (deps.advisorSessionStore ?? createStateAdvisorSessionStore()).load(
915
- conversationId
916
- ) : [];
951
+ const advisorMessages = hasAdvisor ? await (deps.advisorSessionStore ?? createLegacyAdvisorSessionReader()).load(conversationId) : [];
917
952
  const intrinsic = intrinsicTimestamps(entries, visible, compactions);
918
953
  for (const message of advisorMessages) {
919
954
  const timestamp = message.timestamp;
@@ -952,7 +987,7 @@ async function importConversationFromLegacy(conversationId, deps) {
952
987
  const existingMessage = existingMessages.get(message.id);
953
988
  const projected = toStoredConversationMessage(message);
954
989
  return existingMessage !== void 0 && Object.entries(projected.meta ?? {}).every(
955
- ([key, value]) => isDeepStrictEqual2(existingMessage.meta?.[key], value)
990
+ ([key2, value]) => isDeepStrictEqual2(existingMessage.meta?.[key2], value)
956
991
  ) && (message.meta?.replied !== true || existingMessage.repliedAtMs !== void 0);
957
992
  });
958
993
  if (fullyImported) {
@@ -1031,7 +1066,6 @@ export {
1031
1066
  getConversationMessageSlackTs,
1032
1067
  hydrateConversationMessages,
1033
1068
  persistConversationMessages,
1034
- JUNIOR_THREAD_STATE_TTL_MS,
1035
1069
  importConversationFromLegacy,
1036
1070
  ensureLegacyConversationImport
1037
1071
  };
@@ -0,0 +1,264 @@
1
+ // src/chat/discovery.ts
2
+ import fs, { statSync } from "fs";
3
+ import path from "path";
4
+ import { fileURLToPath } from "url";
5
+ function isDirectory(targetPath) {
6
+ try {
7
+ return statSync(targetPath).isDirectory();
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+ function isFile(targetPath) {
13
+ try {
14
+ return statSync(targetPath).isFile();
15
+ } catch {
16
+ return false;
17
+ }
18
+ }
19
+ function normalizePath(targetPath) {
20
+ return path.resolve(targetPath);
21
+ }
22
+ function uniqueResolvedPathsInOrder(values) {
23
+ const seen = /* @__PURE__ */ new Set();
24
+ const resolved = [];
25
+ for (const value of values) {
26
+ const normalized = normalizePath(value);
27
+ if (seen.has(normalized)) {
28
+ continue;
29
+ }
30
+ seen.add(normalized);
31
+ resolved.push(normalized);
32
+ }
33
+ return resolved;
34
+ }
35
+ function isNodeModulesPath(candidatePath) {
36
+ return path.basename(candidatePath) === "node_modules";
37
+ }
38
+ function isInsidePnpmStore(candidatePath) {
39
+ return candidatePath.split(path.sep).includes(".pnpm");
40
+ }
41
+ function runningFromInstalledPackage() {
42
+ const currentFile = fileURLToPath(import.meta.url);
43
+ const marker = `${path.sep}node_modules${path.sep}@sentry${path.sep}junior${path.sep}`;
44
+ return currentFile.includes(marker);
45
+ }
46
+ function listInstalledPackageNodeModulesDirs() {
47
+ if (!runningFromInstalledPackage()) {
48
+ return [];
49
+ }
50
+ const dirs = [];
51
+ let current = path.resolve(path.dirname(fileURLToPath(import.meta.url)));
52
+ while (true) {
53
+ if (isNodeModulesPath(current) && !isInsidePnpmStore(current) && isDirectory(current)) {
54
+ dirs.push(current);
55
+ }
56
+ const parent = path.dirname(current);
57
+ if (parent === current) {
58
+ break;
59
+ }
60
+ current = parent;
61
+ }
62
+ return dirs;
63
+ }
64
+ function listCwdAncestorNodeModulesDirs(cwd) {
65
+ const resolvedCwd = normalizePath(cwd);
66
+ const dirs = [];
67
+ let current = resolvedCwd;
68
+ while (true) {
69
+ const nodeModulesDir = path.join(current, "node_modules");
70
+ if (isDirectory(nodeModulesDir)) {
71
+ dirs.push(nodeModulesDir);
72
+ }
73
+ if (isFile(path.join(current, "package.json"))) {
74
+ break;
75
+ }
76
+ const parent = path.dirname(current);
77
+ if (parent === current) {
78
+ break;
79
+ }
80
+ current = parent;
81
+ }
82
+ return dirs;
83
+ }
84
+ function discoverNodeModulesDirs(cwd = process.cwd(), options) {
85
+ const explicit = options?.candidateDirs?.filter((dir) => isDirectory(dir)) ?? [];
86
+ if (explicit.length > 0) {
87
+ return uniqueResolvedPathsInOrder(explicit);
88
+ }
89
+ return uniqueResolvedPathsInOrder([
90
+ ...listInstalledPackageNodeModulesDirs(),
91
+ ...listCwdAncestorNodeModulesDirs(cwd)
92
+ ]);
93
+ }
94
+ function discoverProjectRoots(cwd = process.cwd(), options) {
95
+ const roots = discoverNodeModulesDirs(
96
+ cwd,
97
+ options?.nodeModulesDirs ? { candidateDirs: options.nodeModulesDirs } : void 0
98
+ ).map((nodeModulesDir) => path.dirname(nodeModulesDir));
99
+ return uniqueResolvedPathsInOrder([cwd, ...roots]);
100
+ }
101
+ function unique(values) {
102
+ return [...new Set(values)];
103
+ }
104
+ function pathExists(targetPath) {
105
+ try {
106
+ fs.accessSync(targetPath);
107
+ return true;
108
+ } catch {
109
+ return false;
110
+ }
111
+ }
112
+ function hasAnyDataMarkers(appDir) {
113
+ return pathExists(path.join(appDir, "SOUL.md")) || pathExists(path.join(appDir, "WORLD.md"));
114
+ }
115
+ function scoreAppCandidate(appDir) {
116
+ let score = 0;
117
+ if (pathExists(path.join(appDir, "SOUL.md"))) {
118
+ score += 4;
119
+ }
120
+ if (pathExists(path.join(appDir, "WORLD.md"))) {
121
+ score += 2;
122
+ }
123
+ if (pathExists(path.join(appDir, "skills"))) {
124
+ score += 1;
125
+ }
126
+ if (pathExists(path.join(appDir, "plugins"))) {
127
+ score += 1;
128
+ }
129
+ return score;
130
+ }
131
+ function resolveCandidateAppDirs(cwd, projectRoots) {
132
+ const roots = projectRoots ?? discoverProjectRoots(cwd);
133
+ const resolved = [];
134
+ const seen = /* @__PURE__ */ new Set();
135
+ for (const root of roots) {
136
+ const appDir = path.resolve(root, "app");
137
+ if (!pathExists(appDir)) {
138
+ continue;
139
+ }
140
+ if (seen.has(appDir)) {
141
+ continue;
142
+ }
143
+ seen.add(appDir);
144
+ resolved.push(appDir);
145
+ }
146
+ return resolved;
147
+ }
148
+ function homeDir() {
149
+ return resolveHomeDir();
150
+ }
151
+ function resolveHomeDir(cwd = process.cwd(), options) {
152
+ const resolvedCwd = path.resolve(cwd);
153
+ const directApp = path.resolve(resolvedCwd, "app");
154
+ if (pathExists(directApp) && hasAnyDataMarkers(directApp)) {
155
+ return directApp;
156
+ }
157
+ const candidates = resolveCandidateAppDirs(
158
+ resolvedCwd,
159
+ options?.projectRoots
160
+ );
161
+ if (candidates.length === 0) {
162
+ return directApp;
163
+ }
164
+ candidates.sort((left, right) => {
165
+ const leftScore = scoreAppCandidate(left);
166
+ const rightScore = scoreAppCandidate(right);
167
+ if (leftScore !== rightScore) {
168
+ return rightScore - leftScore;
169
+ }
170
+ const leftDistance = path.relative(resolvedCwd, left).split(path.sep).length;
171
+ const rightDistance = path.relative(resolvedCwd, right).split(path.sep).length;
172
+ if (leftDistance !== rightDistance) {
173
+ return leftDistance - rightDistance;
174
+ }
175
+ return left.localeCompare(right);
176
+ });
177
+ return candidates[0];
178
+ }
179
+ function resolveContentRoots(subdir) {
180
+ if (subdir === "data") {
181
+ return [homeDir()];
182
+ }
183
+ return [path.join(homeDir(), subdir)];
184
+ }
185
+ function dataDir() {
186
+ return resolveContentRoots("data")[0];
187
+ }
188
+ function soulPath() {
189
+ return path.join(dataDir(), "SOUL.md");
190
+ }
191
+ function worldPath() {
192
+ return path.join(dataDir(), "WORLD.md");
193
+ }
194
+ function descriptionPath() {
195
+ return path.join(dataDir(), "DESCRIPTION.md");
196
+ }
197
+ function skillsDir() {
198
+ return resolveContentRoots("skills")[0];
199
+ }
200
+ function pluginsDir() {
201
+ return resolveContentRoots("plugins")[0];
202
+ }
203
+ function dataRoots() {
204
+ return unique(resolveContentRoots("data"));
205
+ }
206
+ function skillRoots() {
207
+ return unique(resolveContentRoots("skills"));
208
+ }
209
+ function pluginRoots() {
210
+ return unique(resolveContentRoots("plugins"));
211
+ }
212
+ function soulPathCandidates() {
213
+ const candidates = dataRoots().map((root) => path.join(root, "SOUL.md"));
214
+ return unique(candidates);
215
+ }
216
+ function worldPathCandidates() {
217
+ const candidates = dataRoots().map((root) => path.join(root, "WORLD.md"));
218
+ return unique(candidates);
219
+ }
220
+ function descriptionPathCandidates() {
221
+ const candidates = dataRoots().map(
222
+ (root) => path.join(root, "DESCRIPTION.md")
223
+ );
224
+ return unique(candidates);
225
+ }
226
+ var RESERVED_APP_FILES = /* @__PURE__ */ new Set([
227
+ "SOUL.md",
228
+ "WORLD.md",
229
+ "DESCRIPTION.md",
230
+ "ABOUT.md"
231
+ ]);
232
+ function listReferenceFiles() {
233
+ const appDir = homeDir();
234
+ try {
235
+ const entries = fs.readdirSync(appDir, { withFileTypes: true });
236
+ return entries.filter(
237
+ (entry) => entry.isFile() && entry.name.endsWith(".md") && !RESERVED_APP_FILES.has(entry.name)
238
+ ).map((entry) => path.join(appDir, entry.name)).sort();
239
+ } catch {
240
+ return [];
241
+ }
242
+ }
243
+
244
+ export {
245
+ isDirectory,
246
+ isFile,
247
+ discoverNodeModulesDirs,
248
+ discoverProjectRoots,
249
+ homeDir,
250
+ resolveHomeDir,
251
+ dataDir,
252
+ soulPath,
253
+ worldPath,
254
+ descriptionPath,
255
+ skillsDir,
256
+ pluginsDir,
257
+ dataRoots,
258
+ skillRoots,
259
+ pluginRoots,
260
+ soulPathCandidates,
261
+ worldPathCandidates,
262
+ descriptionPathCandidates,
263
+ listReferenceFiles
264
+ };
@@ -0,0 +1,25 @@
1
+ // src/chat/sleep.ts
2
+ function sleep(ms, signal) {
3
+ if (!signal) {
4
+ return new Promise((resolve) => setTimeout(resolve, ms));
5
+ }
6
+ return new Promise((resolve, reject) => {
7
+ if (signal.aborted) {
8
+ reject(signal.reason);
9
+ return;
10
+ }
11
+ const timeoutId = setTimeout(() => {
12
+ signal.removeEventListener("abort", onAbort);
13
+ resolve();
14
+ }, ms);
15
+ const onAbort = () => {
16
+ clearTimeout(timeoutId);
17
+ reject(signal.reason);
18
+ };
19
+ signal.addEventListener("abort", onAbort, { once: true });
20
+ });
21
+ }
22
+
23
+ export {
24
+ sleep
25
+ };