expxagents 0.29.4 → 0.29.6

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.
@@ -1,7 +1,7 @@
1
1
  import readline from 'node:readline';
2
2
  import path from 'node:path';
3
3
  import dotenv from 'dotenv';
4
- import { AgentRunner, SessionManager, SUPPORTED_MODELS, DEFAULT_MODEL } from '@expxagents/agent';
4
+ import { AgentRunner, SessionManager, FEATURED_MODELS, DEFAULT_MODEL, fetchOpenRouterModels } from '@expxagents/agent';
5
5
  import { getVersion } from '../utils/version.js';
6
6
  const C = {
7
7
  reset: '\x1b[0m',
@@ -17,7 +17,7 @@ const C = {
17
17
  bgBlue: '\x1b[44m',
18
18
  };
19
19
  function printBanner(model, version) {
20
- const modelInfo = SUPPORTED_MODELS.find(m => m.id === model);
20
+ const modelInfo = FEATURED_MODELS.find(m => m.id === model);
21
21
  const label = modelInfo?.name ?? model;
22
22
  const cwd = process.cwd();
23
23
  const dir = cwd.split('/').slice(-2).join('/');
@@ -44,7 +44,7 @@ function printHelp() {
44
44
  console.log(` ${C.dim}──────────────────────────────────────${C.reset}`);
45
45
  console.log(` ${C.cyan}/help${C.reset} Show this help`);
46
46
  console.log(` ${C.cyan}/model ${C.dim}<id>${C.reset} Switch model`);
47
- console.log(` ${C.cyan}/models${C.reset} List available models`);
47
+ console.log(` ${C.cyan}/models ${C.dim}[search]${C.reset} List models (e.g. /models claude, /models free)`);
48
48
  console.log(` ${C.cyan}/clear${C.reset} Clear conversation`);
49
49
  console.log(` ${C.cyan}/quit${C.reset} Exit`);
50
50
  console.log('');
@@ -127,28 +127,33 @@ export async function cliChatCommand(options) {
127
127
  printHelp();
128
128
  rl.prompt();
129
129
  return;
130
- case '/models':
131
- console.log(`\n${C.bold}Available models:${C.reset}`);
132
- for (const m of SUPPORTED_MODELS) {
130
+ case '/models': {
131
+ const searchTerm = args.join(' ').toLowerCase();
132
+ console.log(`\n ${C.dim}Fetching models from OpenRouter...${C.reset}`);
133
+ const allModels = await fetchOpenRouterModels(apiKey);
134
+ const filtered = searchTerm
135
+ ? allModels.filter(m => m.id.toLowerCase().includes(searchTerm) || m.name.toLowerCase().includes(searchTerm))
136
+ : allModels.slice(0, 50);
137
+ console.log(`\n${C.bold} ${searchTerm ? `Models matching "${searchTerm}"` : 'Available models'} (${filtered.length}${searchTerm ? '' : ` of ${allModels.length}`}):${C.reset}\n`);
138
+ for (const m of filtered) {
133
139
  const active = m.id === model ? ` ${C.green}(active)${C.reset}` : '';
134
- console.log(` ${C.cyan}${m.id}${C.reset} — ${m.name} (${(m.contextWindow / 1000).toFixed(0)}K ctx)${active}`);
140
+ const featured = FEATURED_MODELS.some(f => f.id === m.id) ? ` ${C.yellow}★${C.reset}` : '';
141
+ console.log(` ${C.cyan}${m.id}${C.reset} — ${m.name} (${(m.contextWindow / 1000).toFixed(0)}K ctx)${featured}${active}`);
142
+ }
143
+ if (!searchTerm && allModels.length > 50) {
144
+ console.log(`\n ${C.dim}Showing 50 of ${allModels.length}. Use /models <search> to filter (e.g. /models claude, /models free)${C.reset}`);
135
145
  }
136
146
  console.log('');
137
147
  rl.prompt();
138
148
  return;
149
+ }
139
150
  case '/model':
140
151
  if (!args[0]) {
141
152
  console.log(`Current model: ${C.yellow}${model}${C.reset}`);
142
153
  }
143
154
  else {
144
155
  model = args[0];
145
- const info = SUPPORTED_MODELS.find(m => m.id === model);
146
- if (info) {
147
- console.log(`${C.green}Switched to ${info.name}${C.reset}`);
148
- }
149
- else {
150
- console.log(`${C.yellow}Warning: "${model}" is not in curated list. Tool use may not work.${C.reset}`);
151
- }
156
+ console.log(`${C.green}Switched to ${model}${C.reset}`);
152
157
  }
153
158
  rl.prompt();
154
159
  return;
@@ -3,7 +3,7 @@ import { createOpenAI } from '@ai-sdk/openai';
3
3
  import { createTools } from './tools/index.js';
4
4
  import { buildSystemPrompt } from './system-prompt.js';
5
5
  import { SessionManager } from './session.js';
6
- import { DEFAULT_MODEL, validateModel } from './models.js';
6
+ import { DEFAULT_MODEL } from './models.js';
7
7
  export class AgentRunner {
8
8
  opts;
9
9
  provider;
@@ -14,9 +14,6 @@ export class AgentRunner {
14
14
  throw new Error('OPENROUTER_API_KEY is not set. Provide apiKey option or set the environment variable.');
15
15
  }
16
16
  const model = opts.model ?? process.env.OPENROUTER_DEFAULT_MODEL ?? DEFAULT_MODEL;
17
- if (!validateModel(model)) {
18
- console.warn(`[agent] Model "${model}" is not in the curated list. Tool use may not work.`);
19
- }
20
17
  this.opts = { ...opts, model, apiKey };
21
18
  this.provider = createOpenAI({
22
19
  baseURL: opts.baseURL ?? 'https://openrouter.ai/api/v1',
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  export type { AgentRunOptions, AgentResult, ToolCallRecord, ModelInfo } from './types.js';
2
2
  export { AgentRunner } from './agent.js';
3
3
  export { SessionManager, type Session } from './session.js';
4
- export { SUPPORTED_MODELS, DEFAULT_MODEL, validateModel, getModelInfo } from './models.js';
4
+ export { SUPPORTED_MODELS, FEATURED_MODELS, DEFAULT_MODEL, getModelInfo, fetchOpenRouterModels } from './models.js';
5
5
  export { createTools } from './tools/index.js';
@@ -1,5 +1,5 @@
1
1
  export { AgentRunner } from './agent.js';
2
2
  export { SessionManager } from './session.js';
3
- export { SUPPORTED_MODELS, DEFAULT_MODEL, validateModel, getModelInfo } from './models.js';
3
+ export { SUPPORTED_MODELS, FEATURED_MODELS, DEFAULT_MODEL, getModelInfo, fetchOpenRouterModels } from './models.js';
4
4
  export { createTools } from './tools/index.js';
5
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,cAAc,EAAgB,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,cAAc,EAAgB,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
@@ -1,5 +1,9 @@
1
1
  import type { ModelInfo } from './types.js';
2
+ /** Featured models shown in /models command. Not a restriction — any OpenRouter model works. */
3
+ export declare const FEATURED_MODELS: ModelInfo[];
4
+ /** @deprecated Use FEATURED_MODELS instead */
2
5
  export declare const SUPPORTED_MODELS: ModelInfo[];
3
6
  export declare const DEFAULT_MODEL = "anthropic/claude-sonnet-4";
4
- export declare function validateModel(id: string): boolean;
5
- export declare function getModelInfo(id: string): ModelInfo | undefined;
7
+ export declare function getModelInfo(id: string): ModelInfo;
8
+ /** Fetches all available models from OpenRouter API */
9
+ export declare function fetchOpenRouterModels(apiKey: string): Promise<ModelInfo[]>;
@@ -1,4 +1,5 @@
1
- export const SUPPORTED_MODELS = [
1
+ /** Featured models shown in /models command. Not a restriction — any OpenRouter model works. */
2
+ export const FEATURED_MODELS = [
2
3
  { id: 'anthropic/claude-sonnet-4', name: 'Claude Sonnet 4', contextWindow: 200000 },
3
4
  { id: 'anthropic/claude-haiku-4', name: 'Claude Haiku 4', contextWindow: 200000 },
4
5
  { id: 'openai/gpt-4o', name: 'GPT-4o', contextWindow: 128000 },
@@ -9,11 +10,36 @@ export const SUPPORTED_MODELS = [
9
10
  { id: 'mistralai/mistral-large', name: 'Mistral Large', contextWindow: 128000 },
10
11
  { id: 'meta-llama/llama-4-maverick', name: 'Llama 4 Maverick', contextWindow: 128000 },
11
12
  ];
13
+ /** @deprecated Use FEATURED_MODELS instead */
14
+ export const SUPPORTED_MODELS = FEATURED_MODELS;
12
15
  export const DEFAULT_MODEL = 'anthropic/claude-sonnet-4';
13
- export function validateModel(id) {
14
- return SUPPORTED_MODELS.some(m => m.id === id);
15
- }
16
+ /** Default context window for unknown models */
17
+ const DEFAULT_CONTEXT_WINDOW = 128000;
16
18
  export function getModelInfo(id) {
17
- return SUPPORTED_MODELS.find(m => m.id === id);
19
+ const featured = FEATURED_MODELS.find(m => m.id === id);
20
+ if (featured)
21
+ return featured;
22
+ // Any OpenRouter model is valid — return sensible defaults
23
+ const name = id.split('/').pop()?.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase()) ?? id;
24
+ return { id, name, contextWindow: DEFAULT_CONTEXT_WINDOW };
25
+ }
26
+ /** Fetches all available models from OpenRouter API */
27
+ export async function fetchOpenRouterModels(apiKey) {
28
+ try {
29
+ const res = await fetch('https://openrouter.ai/api/v1/models', {
30
+ headers: { 'Authorization': `Bearer ${apiKey}` },
31
+ });
32
+ if (!res.ok)
33
+ return FEATURED_MODELS;
34
+ const data = await res.json();
35
+ return data.data.map(m => ({
36
+ id: m.id,
37
+ name: m.name,
38
+ contextWindow: m.context_length ?? DEFAULT_CONTEXT_WINDOW,
39
+ }));
40
+ }
41
+ catch {
42
+ return FEATURED_MODELS;
43
+ }
18
44
  }
19
45
  //# sourceMappingURL=models.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,gBAAgB,GAAgB;IAC3C,EAAE,EAAE,EAAE,2BAA2B,EAAE,IAAI,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,EAAE;IACnF,EAAE,EAAE,EAAE,0BAA0B,EAAE,IAAI,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,EAAE;IACjF,EAAE,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE;IAC9D,EAAE,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,EAAE;IACxE,EAAE,EAAE,EAAE,yBAAyB,EAAE,IAAI,EAAE,kBAAkB,EAAE,aAAa,EAAE,OAAO,EAAE;IACnF,EAAE,EAAE,EAAE,uBAAuB,EAAE,IAAI,EAAE,gBAAgB,EAAE,aAAa,EAAE,OAAO,EAAE;IAC/E,EAAE,EAAE,EAAE,wBAAwB,EAAE,IAAI,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,EAAE;IAC3E,EAAE,EAAE,EAAE,yBAAyB,EAAE,IAAI,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,EAAE;IAC/E,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,EAAE;CACvF,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,2BAA2B,CAAC;AAEzD,MAAM,UAAU,aAAa,CAAC,EAAU;IACtC,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAU;IACrC,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACjD,CAAC"}
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAEA,gGAAgG;AAChG,MAAM,CAAC,MAAM,eAAe,GAAgB;IAC1C,EAAE,EAAE,EAAE,2BAA2B,EAAE,IAAI,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,EAAE;IACnF,EAAE,EAAE,EAAE,0BAA0B,EAAE,IAAI,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,EAAE;IACjF,EAAE,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE;IAC9D,EAAE,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,EAAE;IACxE,EAAE,EAAE,EAAE,yBAAyB,EAAE,IAAI,EAAE,kBAAkB,EAAE,aAAa,EAAE,OAAO,EAAE;IACnF,EAAE,EAAE,EAAE,uBAAuB,EAAE,IAAI,EAAE,gBAAgB,EAAE,aAAa,EAAE,OAAO,EAAE;IAC/E,EAAE,EAAE,EAAE,wBAAwB,EAAE,IAAI,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,EAAE;IAC3E,EAAE,EAAE,EAAE,yBAAyB,EAAE,IAAI,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,EAAE;IAC/E,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,EAAE;CACvF,CAAC;AAEF,8CAA8C;AAC9C,MAAM,CAAC,MAAM,gBAAgB,GAAG,eAAe,CAAC;AAEhD,MAAM,CAAC,MAAM,aAAa,GAAG,2BAA2B,CAAC;AAEzD,gDAAgD;AAChD,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAEtC,MAAM,UAAU,YAAY,CAAC,EAAU;IACrC,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,2DAA2D;IAC3D,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAClG,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,sBAAsB,EAAE,CAAC;AAC7D,CAAC;AAED,uDAAuD;AACvD,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,MAAc;IACxD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,qCAAqC,EAAE;YAC7D,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,MAAM,EAAE,EAAE;SACjD,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,eAAe,CAAC;QACpC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAA4E,CAAC;QACxG,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACzB,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,aAAa,EAAE,CAAC,CAAC,cAAc,IAAI,sBAAsB;SAC1D,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,eAAe,CAAC;IACzB,CAAC;AACH,CAAC"}
@@ -1 +1,6 @@
1
+ /**
2
+ * Loads skill files from .claude/skills/ directories.
3
+ * Returns a map of skill name → skill content.
4
+ */
5
+ export declare function loadSkills(cwd: string): Map<string, string>;
1
6
  export declare function buildSystemPrompt(cwd: string): string;
@@ -1,5 +1,31 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
+ /**
4
+ * Loads skill files from .claude/skills/ directories.
5
+ * Returns a map of skill name → skill content.
6
+ */
7
+ export function loadSkills(cwd) {
8
+ const skills = new Map();
9
+ const skillsDir = path.join(cwd, '.claude', 'skills');
10
+ if (!fs.existsSync(skillsDir))
11
+ return skills;
12
+ try {
13
+ const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
14
+ for (const entry of entries) {
15
+ if (!entry.isDirectory())
16
+ continue;
17
+ const skillFile = path.join(skillsDir, entry.name, 'SKILL.md');
18
+ if (fs.existsSync(skillFile)) {
19
+ const content = fs.readFileSync(skillFile, 'utf-8').trim();
20
+ if (content) {
21
+ skills.set(entry.name, content);
22
+ }
23
+ }
24
+ }
25
+ }
26
+ catch { /* skip unreadable dirs */ }
27
+ return skills;
28
+ }
3
29
  /**
4
30
  * Loads project context files (CLAUDE.md, AGENTS.md, README.md, etc.)
5
31
  * from the working directory, similar to how Claude Code loads CLAUDE.md.
@@ -49,7 +75,25 @@ function loadProjectContext(cwd) {
49
75
  }
50
76
  export function buildSystemPrompt(cwd) {
51
77
  const projectContext = loadProjectContext(cwd);
78
+ const skills = loadSkills(cwd);
52
79
  const dirName = path.basename(cwd);
80
+ // Build skills section
81
+ let skillsSection = '';
82
+ if (skills.size > 0) {
83
+ const skillNames = [...skills.keys()].map(s => `/${s}`).join(', ');
84
+ const skillContents = [...skills.entries()]
85
+ .map(([name, content]) => `### Skill: /${name}\n\n${content}`)
86
+ .join('\n\n---\n\n');
87
+ skillsSection = `
88
+
89
+ ## Installed Skills
90
+
91
+ The following skills are available as slash commands: ${skillNames}
92
+
93
+ When the user types a slash command that matches an installed skill, you MUST follow the skill's instructions exactly. Load any files the skill references (memory, agents, configs) using your tools. Use ask_user for interactive menus and questions.
94
+
95
+ ${skillContents}`;
96
+ }
53
97
  return `You are an AI coding agent working on the "${dirName}" project.
54
98
  You have access to tools for reading, writing, and searching files, running shell commands, and fetching web content.
55
99
 
@@ -66,11 +110,11 @@ Working directory: ${cwd}
66
110
  - Do not modify files you were not asked to change
67
111
  - Prefer small, focused changes over large rewrites
68
112
  - Follow the project conventions described in the project context below
69
- - When the user references project-specific commands or features, use the project context to answer accurately
113
+ - When the user types a slash command (e.g. /expxagents), check if it matches an installed skill and execute it
70
114
 
71
115
  ## Output
72
116
 
73
117
  When you have completed the task, provide a brief summary of what you did.
74
- Do not wrap your final response in markdown code blocks unless the user asked for code.${projectContext}`;
118
+ Do not wrap your final response in markdown code blocks unless the user asked for code.${projectContext}${skillsSection}`;
75
119
  }
76
120
  //# sourceMappingURL=system-prompt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../src/system-prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;GAGG;AACH,SAAS,kBAAkB,CAAC,GAAW;IACrC,MAAM,YAAY,GAAG;QACnB,WAAW;QACX,WAAW;QACX,WAAW;QACX,oBAAoB;KACrB,CAAC;IAEF,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;QACnC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,iCAAiC;YACjC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;YAClD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAClC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvB,IAAI,CAAC;oBACH,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;oBACtE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;wBACzB,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;wBACtE,IAAI,OAAO,EAAE,CAAC;4BACZ,QAAQ,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,OAAO,EAAE,CAAC,CAAC;wBACtE,CAAC;oBACH,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC,CAAC,0BAA0B,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACzC,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;oBAC1D,IAAI,OAAO,EAAE,CAAC;wBACZ,QAAQ,CAAC,IAAI,CAAC,OAAO,OAAO,OAAO,OAAO,EAAE,CAAC,CAAC;oBAChD,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC,CAAC,2BAA2B,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAErC,OAAO,iLAAiL,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;AACzN,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,cAAc,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAEnC,OAAO,8CAA8C,OAAO;;;qBAGzC,GAAG;;;;;;;;;;;;;;;;;;yFAkBiE,cAAc,EAAE,CAAC;AAC1G,CAAC"}
1
+ {"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../src/system-prompt.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expxagents",
3
- "version": "0.29.4",
3
+ "version": "0.29.6",
4
4
  "description": "Multi-agent orchestration platform for AI squads",
5
5
  "author": "ExpxAgents",
6
6
  "license": "MIT",