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
@@ -1,11 +1,15 @@
1
1
  import path from 'pathe';
2
2
  import { z } from 'zod';
3
+ import type { Context } from '../../core/context';
3
4
  import type { SkillManager, SkillMetadata } from '../../skill/skill';
4
- import { createTool } from '../tool';
5
+ import { createTool, type Tool } from '../tool';
5
6
  import { safeStringify } from '../../utils/safeStringify';
7
+ import { createTaskTool } from './task';
8
+ import { randomUUID } from '../../utils/randomUUID';
6
9
 
7
10
  function renderAvailableSkills(skills: SkillMetadata[]): string {
8
11
  return skills
12
+ .filter((skill) => skill.modelInvocable !== false)
9
13
  .map(
10
14
  (skill) =>
11
15
  `<skill>\n<name>${skill.name}</name>\n<description>${skill.description}</description>\n</skill>`,
@@ -14,7 +18,7 @@ function renderAvailableSkills(skills: SkillMetadata[]): string {
14
18
  }
15
19
 
16
20
  function generateDescription(skillManager: SkillManager): string {
17
- const skills = skillManager.getSkills();
21
+ const skills = skillManager.getSkills({ modelInvocable: true });
18
22
  return `Execute a skill within the main conversation
19
23
  <skills_instructions>
20
24
  When users ask you to perform tasks, check if any of the available skills below match the task. If a skill matches, use this tool to invoke it. Skills provide specialized knowledge and procedures for specific tasks.
@@ -24,22 +28,38 @@ ${renderAvailableSkills(skills)}
24
28
  </available_skills>`;
25
29
  }
26
30
 
27
- export function createSkillTool(opts: { skillManager: SkillManager }) {
31
+ export interface CreateSkillToolOpts {
32
+ skillManager: SkillManager;
33
+ context: Context;
34
+ tools: Tool[];
35
+ sessionId: string;
36
+ signal?: AbortSignal;
37
+ }
38
+
39
+ export function createSkillTool(opts: CreateSkillToolOpts) {
40
+ const { skillManager, context, tools, sessionId, signal } = opts;
41
+
28
42
  return createTool({
29
43
  name: 'skill',
30
- description: generateDescription(opts.skillManager),
44
+ description: generateDescription(skillManager),
31
45
  parameters: z.object({
32
46
  skill: z.string().describe('The skill name to execute'),
47
+ args: z
48
+ .string()
49
+ .optional()
50
+ .describe('Optional arguments to pass to the skill'),
33
51
  }),
34
52
  getDescription: ({ params }) => {
35
- return params.skill;
53
+ return params.args
54
+ ? `${params.skill} ${params.args}`
55
+ : params.skill;
36
56
  },
37
- async execute({ skill }) {
57
+ async execute({ skill, args }) {
38
58
  const trimmed = skill.trim();
39
59
  const skillName = trimmed.startsWith('/')
40
60
  ? trimmed.substring(1)
41
61
  : trimmed;
42
- const foundSkill = opts.skillManager.getSkill(skillName);
62
+ const foundSkill = skillManager.getSkill(skillName);
43
63
 
44
64
  if (!foundSkill) {
45
65
  return {
@@ -48,9 +68,67 @@ export function createSkillTool(opts: { skillManager: SkillManager }) {
48
68
  };
49
69
  }
50
70
 
51
- const body = await opts.skillManager.readSkillBody(foundSkill);
71
+ // Check if skill can be invoked by model
72
+ if (foundSkill.modelInvocable === false) {
73
+ return {
74
+ isError: true,
75
+ llmContent: `Skill "${skillName}" cannot be invoked by the model`,
76
+ };
77
+ }
78
+
79
+ const skillArgs = args || '';
80
+ const body = await skillManager.readSkillBody(foundSkill, skillArgs);
52
81
  const baseDir = path.dirname(foundSkill.path);
53
82
 
83
+ // If skill has context: 'fork', use task tool for isolated execution
84
+ if (foundSkill.context === 'fork') {
85
+ if (!context.agentManager) {
86
+ return {
87
+ isError: true,
88
+ llmContent: `Skill "${skillName}" requires fork execution but agent manager is not available`,
89
+ };
90
+ }
91
+
92
+ // Create filtered tools list based on allowedTools
93
+ // Exclude 'skill' tool itself to prevent recursive invocation loops
94
+ const allowedTools = foundSkill.allowedTools;
95
+ const filteredTools = allowedTools
96
+ ? tools.filter(
97
+ (t) =>
98
+ t.name !== 'skill' &&
99
+ allowedTools.some(
100
+ (allowed) =>
101
+ allowed.toLowerCase() === t.name.toLowerCase(),
102
+ ),
103
+ )
104
+ : tools.filter((t) => t.name !== 'skill');
105
+
106
+ // Create task tool with filtered tools
107
+ const taskTool = createTaskTool({
108
+ context,
109
+ tools: filteredTools,
110
+ sessionId,
111
+ signal,
112
+ });
113
+
114
+ // Execute skill as a task
115
+ const agentType = foundSkill.agent || 'general-purpose';
116
+ const prompt = `Base directory for this skill: ${baseDir}\n\n${body}`;
117
+
118
+ // Generate a unique toolCallId for tracking
119
+ const toolCallId = `skill-${skillName}-${randomUUID()}`;
120
+
121
+ return taskTool.execute(
122
+ {
123
+ description: `Execute skill: ${skillName}`,
124
+ prompt,
125
+ subagent_type: agentType,
126
+ },
127
+ toolCallId,
128
+ );
129
+ }
130
+
131
+ // Inline execution (default)
54
132
  const messages = [
55
133
  {
56
134
  type: 'text',
@@ -1,4 +1,5 @@
1
1
  import type {
2
+ ImagePart,
2
3
  NormalizedMessage,
3
4
  ReasoningPart,
4
5
  TextPart,
@@ -154,6 +155,23 @@ export function normalizeMessagesForCompact(
154
155
  };
155
156
  }
156
157
 
158
+ // Filter out image parts from user messages in compact mode
159
+ // Images consume too many tokens and are not needed for summarization
160
+ if (message.role === 'user') {
161
+ if (Array.isArray(message.content)) {
162
+ const filteredContent = message.content.filter(
163
+ (part): part is TextPart => part.type === 'text',
164
+ );
165
+ return {
166
+ ...message,
167
+ content: (filteredContent.length > 0
168
+ ? filteredContent
169
+ : message.content) as Array<TextPart | ImagePart>,
170
+ };
171
+ }
172
+ return message;
173
+ }
174
+
157
175
  return message;
158
176
  })
159
177
  .filter((message) => {