oricore 1.4.1 → 1.5.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 (34) hide show
  1. package/dist/{chunk-SXDGT4YB.js → chunk-D5X6YFSK.js} +1814 -457
  2. package/dist/chunk-D5X6YFSK.js.map +1 -0
  3. package/dist/{chunk-XKZSVWRX.js → chunk-MZNH54NB.js} +375 -171
  4. package/dist/chunk-MZNH54NB.js.map +1 -0
  5. package/dist/{chunk-AXJGNOSQ.js → chunk-XBRIUBK5.js} +2 -2
  6. package/dist/history-FS6CASR6.js +8 -0
  7. package/dist/index.cjs +2424 -585
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.cts +240 -4
  10. package/dist/index.d.ts +240 -4
  11. package/dist/index.js +298 -14
  12. package/dist/index.js.map +1 -1
  13. package/dist/{session-34VFUDZB.js → session-W73HJB5Q.js} +4 -4
  14. package/dist/undici-NSB7IUB7.js +5 -0
  15. package/package.json +2 -1
  16. package/src/core/loop.ts +79 -25
  17. package/src/core/model/models.ts +69 -0
  18. package/src/core/model/providers.ts +76 -37
  19. package/src/core/model/resolution.ts +13 -0
  20. package/src/index.ts +12 -0
  21. package/src/mcp/mcp.ts +4 -1
  22. package/src/skill/bundled.ts +225 -0
  23. package/src/skill/skill.ts +278 -7
  24. package/src/tools/tool.ts +14 -4
  25. package/src/tools/tools/skill.ts +86 -8
  26. package/src/utils/messageNormalization.ts +18 -0
  27. package/dist/chunk-SXDGT4YB.js.map +0 -1
  28. package/dist/chunk-XKZSVWRX.js.map +0 -1
  29. package/dist/history-3JS745YJ.js +0 -8
  30. package/dist/undici-DJO5UB2C.js +0 -5
  31. /package/dist/{chunk-AXJGNOSQ.js.map → chunk-XBRIUBK5.js.map} +0 -0
  32. /package/dist/{history-3JS745YJ.js.map → history-FS6CASR6.js.map} +0 -0
  33. /package/dist/{session-34VFUDZB.js.map → session-W73HJB5Q.js.map} +0 -0
  34. /package/dist/{undici-DJO5UB2C.js.map → undici-NSB7IUB7.js.map} +0 -0
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  Session,
3
3
  SessionConfigManager,
4
4
  loadSessionMessages
5
- } from "./chunk-AXJGNOSQ.js";
5
+ } from "./chunk-XBRIUBK5.js";
6
6
  import {
7
7
  Compression,
8
8
  ConfigManager,
@@ -19,8 +19,10 @@ import {
19
19
  resolveTools,
20
20
  runLoop,
21
21
  safeStringify
22
- } from "./chunk-XKZSVWRX.js";
23
- import "./chunk-SXDGT4YB.js";
22
+ } from "./chunk-MZNH54NB.js";
23
+ import {
24
+ __require
25
+ } from "./chunk-D5X6YFSK.js";
24
26
 
25
27
  // src/core/context.ts
26
28
  import fs10 from "fs";
@@ -2213,8 +2215,10 @@ var MCPManager = class _MCPManager {
2213
2215
  return true;
2214
2216
  }
2215
2217
  #convertAiSdkToolToLocal(toolName, toolDef, serverName, config) {
2218
+ const safeServerName = serverName.replace(/[^a-zA-Z0-9_-]/g, "");
2219
+ const safeToolName = toolName.replace(/[^a-zA-Z0-9_-]/g, "_");
2216
2220
  return {
2217
- name: `mcp__${serverName.replace(/[^a-zA-Z0-9_-]/g, "")}__${toolName}`,
2221
+ name: `mcp__${safeServerName}__${safeToolName}`,
2218
2222
  description: toolDef.description,
2219
2223
  getDescription: ({ params }) => {
2220
2224
  return formatParamsDescription(params);
@@ -2441,12 +2445,133 @@ import degit from "degit";
2441
2445
  import fs9 from "fs";
2442
2446
  import os3 from "os";
2443
2447
  import path9 from "pathe";
2448
+
2449
+ // src/skill/bundled.ts
2450
+ var BundledSkillRegistry = class {
2451
+ skills = /* @__PURE__ */ new Map();
2452
+ aliases = /* @__PURE__ */ new Map();
2453
+ /**
2454
+ * Register a bundled skill.
2455
+ * @param definition The skill definition
2456
+ */
2457
+ register(definition) {
2458
+ if (!definition.name) {
2459
+ throw new Error("Bundled skill must have a name");
2460
+ }
2461
+ if (!definition.description) {
2462
+ throw new Error("Bundled skill must have a description");
2463
+ }
2464
+ if (!definition.getPrompt) {
2465
+ throw new Error("Bundled skill must have a getPrompt function");
2466
+ }
2467
+ this.skills.set(definition.name, definition);
2468
+ if (definition.aliases) {
2469
+ for (const alias of definition.aliases) {
2470
+ this.aliases.set(alias, definition.name);
2471
+ }
2472
+ }
2473
+ }
2474
+ /**
2475
+ * Get a bundled skill by name or alias.
2476
+ * @param name Skill name or alias
2477
+ * @returns The skill definition or undefined if not found
2478
+ */
2479
+ get(name) {
2480
+ const skill = this.skills.get(name);
2481
+ if (skill) return skill;
2482
+ const aliasedName = this.aliases.get(name);
2483
+ if (aliasedName) {
2484
+ return this.skills.get(aliasedName);
2485
+ }
2486
+ return void 0;
2487
+ }
2488
+ /**
2489
+ * Get all registered bundled skills.
2490
+ * @param context Optional context to filter by isEnabled
2491
+ * @returns Array of skill definitions
2492
+ */
2493
+ getAll(context) {
2494
+ return Array.from(this.skills.values()).filter((skill) => {
2495
+ if (skill.isEnabled === void 0) return true;
2496
+ if (typeof skill.isEnabled === "boolean") return skill.isEnabled;
2497
+ if (typeof skill.isEnabled === "function" && context) {
2498
+ return skill.isEnabled(context);
2499
+ }
2500
+ return true;
2501
+ });
2502
+ }
2503
+ /**
2504
+ * Check if a skill is registered.
2505
+ * @param name Skill name or alias
2506
+ */
2507
+ has(name) {
2508
+ return this.skills.has(name) || this.aliases.has(name);
2509
+ }
2510
+ /**
2511
+ * Unregister a skill.
2512
+ * @param name Skill name
2513
+ */
2514
+ unregister(name) {
2515
+ const skill = this.skills.get(name);
2516
+ if (skill && skill.aliases) {
2517
+ for (const alias of skill.aliases) {
2518
+ this.aliases.delete(alias);
2519
+ }
2520
+ }
2521
+ this.skills.delete(name);
2522
+ }
2523
+ /**
2524
+ * Clear all registered skills.
2525
+ */
2526
+ clear() {
2527
+ this.skills.clear();
2528
+ this.aliases.clear();
2529
+ }
2530
+ };
2531
+ var bundledSkillRegistry = new BundledSkillRegistry();
2532
+ function bundledSkillToMetadata(definition, source = "builtin") {
2533
+ return {
2534
+ name: definition.name,
2535
+ description: definition.description,
2536
+ path: `bundled://${definition.name}`,
2537
+ source,
2538
+ allowedTools: definition.allowedTools,
2539
+ context: definition.context,
2540
+ agent: definition.agent,
2541
+ userInvocable: definition.userInvocable ?? true,
2542
+ modelInvocable: definition.modelInvocable ?? true
2543
+ // Note: bundled skills don't support 'paths' conditional activation
2544
+ };
2545
+ }
2546
+ function createBundledSkill(config) {
2547
+ return {
2548
+ ...config,
2549
+ getPrompt: typeof config.prompt === "string" ? () => config.prompt : config.prompt
2550
+ };
2551
+ }
2552
+ function registerBundledSkill(config) {
2553
+ const skill = createBundledSkill(config);
2554
+ bundledSkillRegistry.register(skill);
2555
+ }
2556
+
2557
+ // src/skill/skill.ts
2558
+ function isDirOrSymlinkToDir(parentDir, entry) {
2559
+ if (entry.isDirectory()) return true;
2560
+ if (entry.isSymbolicLink()) {
2561
+ try {
2562
+ return fs9.statSync(path9.join(parentDir, entry.name)).isDirectory();
2563
+ } catch {
2564
+ }
2565
+ }
2566
+ return false;
2567
+ }
2444
2568
  var SkillSource = /* @__PURE__ */ ((SkillSource2) => {
2445
2569
  SkillSource2["Plugin"] = "plugin";
2446
2570
  SkillSource2["GlobalClaude"] = "global-claude";
2447
2571
  SkillSource2["Global"] = "global";
2448
2572
  SkillSource2["ProjectClaude"] = "project-claude";
2449
2573
  SkillSource2["Project"] = "project";
2574
+ SkillSource2["Builtin"] = "builtin";
2450
2575
  return SkillSource2;
2451
2576
  })(SkillSource || {});
2452
2577
  var MAX_NAME_LENGTH2 = 64;
@@ -2456,21 +2581,119 @@ var SkillManager = class {
2456
2581
  errors = [];
2457
2582
  paths;
2458
2583
  context;
2584
+ /**
2585
+ * Tracks which skills are currently "active" based on file operations.
2586
+ * Skills with `paths` frontmatter are activated when matching files are accessed.
2587
+ */
2588
+ activeSkillNames = /* @__PURE__ */ new Set();
2589
+ /**
2590
+ * Maps alias names to original skill names for bundled skills.
2591
+ */
2592
+ aliasMap = /* @__PURE__ */ new Map();
2459
2593
  constructor(opts) {
2460
2594
  this.context = opts.context;
2461
2595
  this.paths = opts.context.paths;
2462
2596
  }
2463
- getSkills() {
2464
- return Array.from(this.skillsMap.values());
2597
+ /**
2598
+ * Get all loaded skills.
2599
+ * @param options Filter options
2600
+ * @returns Array of skill metadata
2601
+ */
2602
+ getSkills(options) {
2603
+ let skills = Array.from(this.skillsMap.values());
2604
+ if (options?.userInvocable !== void 0) {
2605
+ skills = skills.filter(
2606
+ (s) => (s.userInvocable ?? true) === options.userInvocable
2607
+ );
2608
+ }
2609
+ if (options?.modelInvocable !== void 0) {
2610
+ skills = skills.filter(
2611
+ (s) => (s.modelInvocable ?? true) === options.modelInvocable
2612
+ );
2613
+ }
2614
+ if (options?.activeOnly) {
2615
+ skills = skills.filter((s) => this.activeSkillNames.has(s.name));
2616
+ }
2617
+ return skills;
2465
2618
  }
2619
+ /**
2620
+ * Get a specific skill by name.
2621
+ * Automatically resolves aliases to the original skill.
2622
+ * @param name Skill name or alias
2623
+ * @returns Skill metadata or undefined if not found
2624
+ */
2466
2625
  getSkill(name) {
2467
- return this.skillsMap.get(name);
2626
+ const skill = this.skillsMap.get(name);
2627
+ if (skill) return skill;
2628
+ const originalName = this.aliasMap.get(name);
2629
+ if (originalName) {
2630
+ return this.skillsMap.get(originalName);
2631
+ }
2632
+ return void 0;
2633
+ }
2634
+ /**
2635
+ * Check if a skill is active (has matching paths for current context).
2636
+ * @param name Skill name
2637
+ */
2638
+ isSkillActive(name) {
2639
+ return this.activeSkillNames.has(name);
2640
+ }
2641
+ /**
2642
+ * Activate skills based on file paths.
2643
+ * Skills with `paths` frontmatter that match the given paths will be activated.
2644
+ * @param filePaths Array of file paths to check
2645
+ * @returns Array of newly activated skill names
2646
+ */
2647
+ activateSkillsForPaths(filePaths) {
2648
+ const newlyActivated = [];
2649
+ const minimatch = __require("minimatch");
2650
+ for (const [name, skill] of this.skillsMap) {
2651
+ if (skill.paths && skill.paths.length > 0) {
2652
+ const isMatch = skill.paths.some(
2653
+ (pattern) => filePaths.some((filePath) => minimatch(filePath, pattern))
2654
+ );
2655
+ if (isMatch && !this.activeSkillNames.has(name)) {
2656
+ this.activeSkillNames.add(name);
2657
+ newlyActivated.push(name);
2658
+ }
2659
+ }
2660
+ }
2661
+ return newlyActivated;
2662
+ }
2663
+ /**
2664
+ * Clear all active skill activations.
2665
+ * Useful when switching contexts or projects.
2666
+ */
2667
+ clearActiveSkills() {
2668
+ this.activeSkillNames.clear();
2669
+ }
2670
+ /**
2671
+ * Get all skills that have path-based conditional activation.
2672
+ * @returns Array of skills with paths defined
2673
+ */
2674
+ getConditionalSkills() {
2675
+ return Array.from(this.skillsMap.values()).filter(
2676
+ (s) => s.paths && s.paths.length > 0
2677
+ );
2468
2678
  }
2469
2679
  getErrors() {
2470
2680
  return this.errors;
2471
2681
  }
2472
- async readSkillBody(skill) {
2682
+ /**
2683
+ * Read the body content of a skill.
2684
+ * For file-based skills, reads from disk.
2685
+ * For bundled skills, generates content via getPrompt.
2686
+ */
2687
+ async readSkillBody(skill, args = "") {
2473
2688
  try {
2689
+ if (skill.path.startsWith("bundled://")) {
2690
+ const bundledName = skill.path.replace("bundled://", "");
2691
+ const bundledSkill = bundledSkillRegistry.get(bundledName);
2692
+ if (!bundledSkill) {
2693
+ throw new Error(`Bundled skill "${bundledName}" not found in registry`);
2694
+ }
2695
+ return await bundledSkill.getPrompt(args, this.context);
2696
+ }
2474
2697
  const content = fs9.readFileSync(skill.path, "utf-8");
2475
2698
  const { body } = safeFrontMatter(content, skill.path);
2476
2699
  return body;
@@ -2479,9 +2702,26 @@ var SkillManager = class {
2479
2702
  throw new Error(`Failed to read skill ${skill.name}: ${message}`);
2480
2703
  }
2481
2704
  }
2705
+ /**
2706
+ * Get a bundled skill definition by name.
2707
+ * @param name Bundled skill name
2708
+ * @returns Bundled skill definition or undefined if not found
2709
+ */
2710
+ getBundledSkill(name) {
2711
+ return bundledSkillRegistry.get(name);
2712
+ }
2713
+ /**
2714
+ * Register a bundled skill programmatically.
2715
+ * @param definition Bundled skill definition
2716
+ */
2717
+ registerBundledSkill(definition) {
2718
+ bundledSkillRegistry.register(definition);
2719
+ this.loadBuiltinSkills();
2720
+ }
2482
2721
  async loadSkills() {
2483
2722
  this.skillsMap.clear();
2484
2723
  this.errors = [];
2724
+ this.loadBuiltinSkills();
2485
2725
  const pluginSkills = await this.context.apply({
2486
2726
  hook: "skill",
2487
2727
  args: [],
@@ -2524,6 +2764,22 @@ var SkillManager = class {
2524
2764
  const projectDir = path9.join(this.paths.projectConfigDir, "skills");
2525
2765
  this.loadSkillsFromDirectory(projectDir, "project" /* Project */);
2526
2766
  }
2767
+ /**
2768
+ * Load builtin/bundled skills from the registry.
2769
+ */
2770
+ loadBuiltinSkills() {
2771
+ this.aliasMap.clear();
2772
+ const bundledSkills = bundledSkillRegistry.getAll(this.context);
2773
+ for (const skill of bundledSkills) {
2774
+ const metadata = bundledSkillToMetadata(skill, "builtin" /* Builtin */);
2775
+ this.skillsMap.set(skill.name, metadata);
2776
+ if (skill.aliases) {
2777
+ for (const alias of skill.aliases) {
2778
+ this.aliasMap.set(alias, skill.name);
2779
+ }
2780
+ }
2781
+ }
2782
+ }
2527
2783
  loadSkillsFromDirectory(skillsDir, source) {
2528
2784
  if (!fs9.existsSync(skillsDir)) {
2529
2785
  return;
@@ -2531,7 +2787,7 @@ var SkillManager = class {
2531
2787
  try {
2532
2788
  const entries = fs9.readdirSync(skillsDir, { withFileTypes: true });
2533
2789
  for (const entry of entries) {
2534
- if (entry.isDirectory()) {
2790
+ if (isDirOrSymlinkToDir(skillsDir, entry)) {
2535
2791
  const skillPath = path9.join(skillsDir, entry.name, "SKILL.md");
2536
2792
  if (fs9.existsSync(skillPath)) {
2537
2793
  this.loadSkillFile(skillPath, source);
@@ -2599,10 +2855,19 @@ var SkillManager = class {
2599
2855
  });
2600
2856
  return null;
2601
2857
  }
2858
+ const allowedTools = this.parseStringArrayField(attributes.allowedTools);
2859
+ const context = attributes.context === "inline" || attributes.context === "fork" ? attributes.context : void 0;
2860
+ const paths = this.parseStringArrayField(attributes.paths);
2602
2861
  return {
2603
2862
  name: attributes.name,
2604
2863
  description: attributes.description,
2605
- path: skillPath
2864
+ path: skillPath,
2865
+ allowedTools,
2866
+ context,
2867
+ agent: attributes.agent,
2868
+ paths,
2869
+ userInvocable: attributes.userInvocable ?? true,
2870
+ modelInvocable: attributes.modelInvocable ?? true
2606
2871
  };
2607
2872
  } catch (error) {
2608
2873
  this.errors.push({
@@ -2612,6 +2877,21 @@ var SkillManager = class {
2612
2877
  return null;
2613
2878
  }
2614
2879
  }
2880
+ /**
2881
+ * Parse a field that can be either a comma-separated string or an array of strings.
2882
+ * @param value The value to parse
2883
+ * @returns Array of strings or undefined if empty
2884
+ */
2885
+ parseStringArrayField(value) {
2886
+ if (!value) return void 0;
2887
+ if (Array.isArray(value)) {
2888
+ return value.map((item) => item.trim()).filter((item) => item.length > 0);
2889
+ }
2890
+ if (typeof value === "string") {
2891
+ return value.split(",").map((item) => item.trim()).filter((item) => item.length > 0);
2892
+ }
2893
+ return void 0;
2894
+ }
2615
2895
  async addSkill(source, options = {}) {
2616
2896
  const {
2617
2897
  global: isGlobal = false,
@@ -2741,7 +3021,7 @@ var SkillManager = class {
2741
3021
  if (fs9.existsSync(skillsDir) && fs9.statSync(skillsDir).isDirectory()) {
2742
3022
  const entries2 = fs9.readdirSync(skillsDir, { withFileTypes: true });
2743
3023
  for (const entry of entries2) {
2744
- if (entry.isDirectory()) {
3024
+ if (isDirOrSymlinkToDir(skillsDir, entry)) {
2745
3025
  const skillPath = path9.join(skillsDir, entry.name, "SKILL.md");
2746
3026
  if (fs9.existsSync(skillPath)) {
2747
3027
  skills.push(skillPath);
@@ -2754,7 +3034,7 @@ var SkillManager = class {
2754
3034
  }
2755
3035
  const entries = fs9.readdirSync(dir, { withFileTypes: true });
2756
3036
  for (const entry of entries) {
2757
- if (entry.isDirectory()) {
3037
+ if (isDirOrSymlinkToDir(dir, entry)) {
2758
3038
  const skillPath = path9.join(dir, entry.name, "SKILL.md");
2759
3039
  if (fs9.existsSync(skillPath)) {
2760
3040
  skills.push(skillPath);
@@ -4001,12 +4281,12 @@ var Engine = class {
4001
4281
  const systemPrompt = context.config.systemPrompt || "";
4002
4282
  let sessionHistory = void 0;
4003
4283
  if (options.sessionId) {
4004
- const { loadSessionMessages: loadSessionMessages2 } = await import("./session-34VFUDZB.js");
4284
+ const { loadSessionMessages: loadSessionMessages2 } = await import("./session-W73HJB5Q.js");
4005
4285
  const logPath = context.paths.getSessionLogPath(sessionId);
4006
4286
  try {
4007
4287
  const existingMessages = loadSessionMessages2({ logPath });
4008
4288
  if (existingMessages.length > 0) {
4009
- const { History: History2 } = await import("./history-3JS745YJ.js");
4289
+ const { History: History2 } = await import("./history-FS6CASR6.js");
4010
4290
  sessionHistory = new History2({
4011
4291
  messages: existingMessages
4012
4292
  });
@@ -4208,6 +4488,9 @@ export {
4208
4488
  Usage,
4209
4489
  brainstormMode,
4210
4490
  builtinModes,
4491
+ bundledSkillRegistry,
4492
+ bundledSkillToMetadata,
4493
+ createBundledSkill,
4211
4494
  createEngine,
4212
4495
  debugMode,
4213
4496
  defaultMode,
@@ -4219,6 +4502,7 @@ export {
4219
4502
  planMode,
4220
4503
  randomUUID,
4221
4504
  registerBuiltinModes,
4505
+ registerBundledSkill,
4222
4506
  reviewMode
4223
4507
  };
4224
4508
  //# sourceMappingURL=index.js.map