@bradtech/sales-skills 1.0.0

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.
package/.env.dist ADDED
@@ -0,0 +1,18 @@
1
+ # Rename this file to '.env' at the root of the repository
2
+
3
+ # Odoo ERP Configuration
4
+ ODOO_URL="https://your-instance.odoo.com"
5
+ ODOO_DB="your_database_name"
6
+ ODOO_USER="your_email@company.com"
7
+ ODOO_PASSWORD="your_password_or_api_key"
8
+
9
+ # Brevo API Configuration - Retrieve your v3 API key from your Brevo account
10
+ BREVO_API_KEY="your_brevo_v3_api_key"
11
+
12
+ # Path to the Google Service Account key file (optional if placed at root as 'service_account.json')
13
+ GOOGLE_APPLICATION_CREDENTIALS="path/to/your/service_account.json"
14
+
15
+ # Local LM Studio Configuration (optional)
16
+ LM_STUDIO_URL="http://localhost:1234/v1"
17
+ LM_STUDIO_MODEL="qwen2.5-coder-7b-instruct"
18
+
package/AGENT.md ADDED
@@ -0,0 +1,58 @@
1
+ # LLM Agent Instructions: Sales Skills Guidelines
2
+
3
+ This repository follows the core guidelines and styling conventions of the crapougnax ecosystem.
4
+
5
+ ---
6
+
7
+ ## 🧭 Base Guidelines & Personal Rules
8
+
9
+ For base development principles, coding standards, and project rules, all agent actions must comply with the rules defined in:
10
+ 👉 **[Gist: Personal Gemini Rules & Instructions](https://gist.github.com/crapougnax/47971b85aa73dd702f4372a89858111c)**
11
+
12
+ ---
13
+
14
+ ## 🛠 How to Add a New Vendor Skill
15
+
16
+ Vendor skills represent atomic wrappers around third-party APIs. To add a new vendor integration:
17
+
18
+ 1. **Create the Vendor Directory**:
19
+ - Location: `skills/vendor/<vendor_name>/`
20
+ 2. **Implement Client and CLI Runner**:
21
+ - Create scripts inside the vendor directory (e.g., `client.ts` for logic, `cli.ts` for Commander-based runner).
22
+ - Use standard `@quatrain` core libraries for logging, HTTP clients, and prompt helpers:
23
+ - `@quatrain/log` for output reporting.
24
+ - `@quatrain/cli` for interactive prompts.
25
+ - `@quatrain/api-client` (REST) or `@quatrain/api-xmlrpc` (XML-RPC).
26
+ 3. **Prevent Subcommand Collision**:
27
+ - Ensure the command parsing in the main CLI entrypoint (`cli.ts`) is conditionally executed:
28
+ ```typescript
29
+ if (import.meta.main) {
30
+ main().catch(...)
31
+ }
32
+ ```
33
+ 4. **Create the Skill Definition**:
34
+ - Add `skills/vendor/<vendor_name>/SKILL.md` containing YAML frontmatter (`name` and `description`) and detailed instruction triggers.
35
+ 5. **Activate the Skill**:
36
+ - Link the directory into the agent customization workspace folder:
37
+ ```bash
38
+ ln -s ../../skills/vendor/<vendor_name> .agents/skills/<vendor_name>
39
+ ```
40
+
41
+ ---
42
+
43
+ ## 🚀 How to Add a New Composite Action
44
+
45
+ Composite actions orchestrate workflows across multiple vendors. To add a new composite action:
46
+
47
+ 1. **Create the Action Directory**:
48
+ - Location: `skills/actions/<action_name>/`
49
+ 2. **Implement the Action Orchestrator**:
50
+ - Create scripts inside a `scripts/` subdirectory, e.g., `skills/actions/<action_name>/scripts/<action_name>_cli.ts`.
51
+ - Import vendor client instances from `../../../vendor/` relative paths.
52
+ 3. **Create the Skill Definition**:
53
+ - Add `skills/actions/<action_name>/SKILL.md` containing YAML frontmatter (`name` and `description`) and instructions defining the workflow steps.
54
+ 4. **Activate the Action**:
55
+ - Link the directory into the agent customization workspace folder:
56
+ ```bash
57
+ ln -s ../../skills/actions/<action_name> .agents/skills/<action_name>
58
+ ```
package/HOWTO.md ADDED
@@ -0,0 +1,72 @@
1
+ # How-To Guide: Running Sales Skills Commands
2
+
3
+ This document contains standard recipes and commands for testing, verifying, and running the sales-skills suite. Make sure you have run `bun install` and loaded your `.env` before executing these commands.
4
+
5
+ ---
6
+
7
+ ## 1. Odoo ERP Integration
8
+
9
+ ### Search Partners
10
+ Search Odoo contacts by query string (checks names and emails):
11
+ ```bash
12
+ bun run skills/vendor/odoo/cli.ts search-partners --query "infotel" --limit 5 --output ".log/partners.json"
13
+ ```
14
+
15
+ ### Create Contact
16
+ Create a new partner inside Odoo:
17
+ ```bash
18
+ bun run skills/vendor/odoo/cli.ts create-contact --name "John Doe" --email "john.doe@example.com" --output ".log/new_contact.json"
19
+ ```
20
+
21
+ ### Create Meeting
22
+ Schedule a calendar meeting inside Odoo (attendees list expects Odoo partner IDs):
23
+ ```bash
24
+ bun run skills/vendor/odoo/cli.ts create-meeting --name "Introduction Call" --start "2026-06-25 14:00:00" --duration 1.5 --attendees 365940,365941 --output ".log/new_meeting.json"
25
+ ```
26
+
27
+ ---
28
+
29
+ ## 2. Brevo Email Marketing
30
+
31
+ ### List Contacts
32
+ Retrieve contacts from your Brevo mailing list:
33
+ ```bash
34
+ bun run skills/vendor/brevo/cli.ts list-contacts --limit 10 --output ".log/brevo_list.json"
35
+ ```
36
+
37
+ ---
38
+
39
+ ## 3. Google Calendar
40
+
41
+ ### List Events
42
+ List upcoming calendar events for a specific user:
43
+ ```bash
44
+ bun run skills/vendor/google/cli.ts list-events --calendar-id "olivier@brad.ag" --limit 5 --output ".log/google_events.json"
45
+ ```
46
+
47
+ ### Create Event
48
+ Schedule an event in Google Calendar:
49
+ ```bash
50
+ bun run skills/vendor/google/cli.ts create-event --summary "Sync with Partner" --start "2026-06-25 15:30:00" --duration 1.0 --description "Introductory talk" --calendar-id "olivier@brad.ag" --output ".log/event_created.json"
51
+ ```
52
+
53
+ ### Delete Event
54
+ Delete an event by its unique Google Calendar ID:
55
+ ```bash
56
+ bun run skills/vendor/google/cli.ts delete-event --event-id "_example_id" --calendar-id "olivier@brad.ag" --output ".log/event_deleted.json"
57
+ ```
58
+
59
+ ---
60
+
61
+ ## 4. Google Calendar to Odoo CRM Sync (Composite Action)
62
+
63
+ Sync Google Calendar events for a specific date to OdooCRM, prompting for missing contact creation:
64
+ ```bash
65
+ bun run skills/actions/sync-meetings-to-odoo/scripts/sync_meetings_cli.ts --calendar-id "olivier@brad.ag" --date "2026-06-25" --output ".log/sync_run.json"
66
+ ```
67
+ During execution, the CLI will:
68
+ 1. Load calendar events.
69
+ 2. Present list of proposals.
70
+ 3. Wait for `(Y/n)` keyboard confirmations to create contacts, update contacts, and insert meetings.
71
+ 4. Execute confirmed operations.
72
+ 5. Log a final summary of all successful creations to `.log/sync_run.json`.
package/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ # LICENSE
2
+
3
+ This project is licensed under the **GNU Affero General Public License v3.0 (AGPL v3)**.
4
+
5
+ Copyright © 2026 Brad Technology SAS. All Rights Reserved.
6
+
7
+ For full license details, please refer to the official GNU AGPL v3 text at:
8
+ https://www.gnu.org/licenses/agpl-3.0.txt
package/LLM.md ADDED
@@ -0,0 +1,37 @@
1
+ # LLM Agent Skill Activation
2
+
3
+ Activate and update all integration skills for your local or global LLM agents with a single command:
4
+
5
+ ```bash
6
+ bun run setup-skills
7
+ ```
8
+
9
+ ---
10
+
11
+ ## What the Script Sets Up
12
+
13
+ ### 1. Gemini Coding Assistant (Customization Roots)
14
+ - Links all workspace integrations under `skills/` to the local customization directory `.agents/skills/`.
15
+ - Registers rule definitions (`AGENT.md`) to `.agents/AGENTS.md`.
16
+ - Automatically links skills globally to `~/.gemini/config/skills/` if the global config directory exists.
17
+
18
+ ### 2. Claude-based Assistants (Cline, Roo Code, etc.)
19
+ - Exposes workspace guidelines by linking `AGENT.md` directly to `.clinerules` and `.roomodes` at the root.
20
+ - The assistant automatically parses these files at startup to understand available commands.
21
+
22
+ ### 3. Local Models via LM Studio (Agent Runner)
23
+ You can run this skill set with local models (e.g. Qwen-2.5-Coder, Llama-3) hosted via LM Studio:
24
+ 1. Turn on the local server in LM Studio (defaults to `http://localhost:1234/v1`).
25
+ 2. Run the agent using `local-agent`:
26
+ ```bash
27
+ bun run local-agent "Search Odoo for partners at infotel"
28
+ ```
29
+ - Environment variables `LM_STUDIO_URL` and `LM_STUDIO_MODEL` can be defined in your `.env` to override the defaults.
30
+
31
+ ### 4. Other Assistants (OpenAI / Custom GPTs)
32
+ - Register the TS CLI runner commands under your Custom Actions / Functions.
33
+ - Example execute command:
34
+ ```bash
35
+ bun run skills/actions/sync-meetings-to-odoo/scripts/sync_meetings_cli.ts --calendar-id <email> --date <date> --output <output_path>
36
+ ```
37
+
package/README.md ADDED
@@ -0,0 +1,100 @@
1
+ # Brad Sales Skills
2
+
3
+ A suite of TypeScript/Bun integration tools designed to connect Odoo ERP, Brevo, and Google Calendar into a cohesive automated sales assistant.
4
+
5
+ This repository leverages the `@quatrain` ecosystem for unified logging, API clients (both REST and XML-RPC), and interactive prompt helper utilities.
6
+
7
+ ---
8
+
9
+ ## Features
10
+
11
+ ### 1. Atomic Vendor Clients (`skills/vendor/`)
12
+ - **Odoo CRM (`odoo-integration`)**: Search partners, update contacts, create new contacts, and manage calendar events in Odoo using a fast XML-RPC connector (`@quatrain/api-xmlrpc`).
13
+ - **Brevo Email Marketing (`brevo-integration`)**: Query, insert, and update newsletter and CRM contacts via the Brevo REST API client.
14
+ - **Google Calendar (`google-calendar`)**: Access Google Calendars using service account credentials. Supports listing, creating, and deleting events.
15
+
16
+ ### 2. Composite Sync Actions (`skills/actions/`)
17
+ - **Google Calendar to Odoo Meetings Sync (`sync-meetings-to-odoo`)**: An interactive command-line orchestrator that:
18
+ 1. Pulls events from Google Calendar for a target date.
19
+ 2. Resolves attendees' emails against Odoo partners.
20
+ 3. Prompts the user interactively (using inquirer-based helpers) to create missing contacts, update incomplete names, and create Odoo calendar meetings linked to those partners.
21
+
22
+ ---
23
+
24
+ ## Directory Structure
25
+
26
+ ```
27
+ ├── .env.dist # Template for environment configuration
28
+ ├── package.json # Project dependencies (linked local @quatrain workspaces)
29
+ ├── tsconfig.json # Path mappings for direct Bun execution
30
+ ├── service_account.json # (Optional) Google Service Account key file
31
+ ├── skills/ # Skill Definitions & Implementations
32
+ │ ├── actions/ # Composite orchestrators
33
+ │ │ └── sync-meetings-to-odoo/
34
+ │ │ ├── SKILL.md # LLM integration triggers for composite sync
35
+ │ │ └── scripts/
36
+ │ │ └── sync_meetings_cli.ts
37
+ │ └── vendor/ # CLI entry points and definitions for atomic vendors
38
+ │ ├── google/
39
+ │ │ ├── SKILL.md # LLM integration triggers for Google Calendar
40
+ │ │ ├── calendar.ts # Google calendar client
41
+ │ │ └── cli.ts # CLI runner
42
+ │ ├── odoo/
43
+ │ │ ├── SKILL.md # LLM integration triggers for Odoo
44
+ │ │ └── cli.ts # Odoo client & CLI runner
45
+ │ └── brevo/
46
+ │ ├── SKILL.md # LLM integration triggers for Brevo
47
+ │ └── cli.ts # Brevo client & CLI runner
48
+
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Configuration
54
+
55
+ Duplicate `.env.dist` as `.env` and fill in the credentials:
56
+
57
+ ```ini
58
+ # Odoo ERP Configuration
59
+ ODOO_URL="https://your-instance.odoo.com"
60
+ ODOO_DB="your_database_name"
61
+ ODOO_USER="your_email@company.com"
62
+ ODOO_PASSWORD="your_password_or_api_key"
63
+
64
+ # Brevo API Configuration
65
+ BREVO_API_KEY="your_brevo_v3_api_key"
66
+
67
+ # Path to the Google Service Account key file (optional if placed at root as 'service_account.json')
68
+ GOOGLE_APPLICATION_CREDENTIALS="service_account.json"
69
+ ```
70
+
71
+ ### Google Service Account
72
+ Download your Google Cloud Service Account key file and:
73
+ 1. Place it at the root of the repository as `service_account.json`, OR
74
+ 2. Place it anywhere and set its absolute path in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable inside `.env`.
75
+
76
+ ---
77
+
78
+ ## LLM Activation
79
+
80
+ This repository is structured as a **Gemini/Custom Agent Skill Set**. To activate these skills and allow your LLM coding assistant to automatically discover, read, and run these commands, configure customization roots:
81
+
82
+ ### 1. Workspace-Specific Activation (Recommended)
83
+ Create a directory named `.agents` at the root of your workspace, and create/link the skill definitions:
84
+ ```bash
85
+ mkdir -p .agents/skills
86
+ ln -s ../../skills/vendor/google .agents/skills/google-calendar
87
+ ln -s ../../skills/vendor/odoo .agents/skills/odoo-integration
88
+ ln -s ../../skills/vendor/brevo .agents/skills/brevo-integration
89
+ ln -s ../../skills/actions/sync-meetings-to-odoo .agents/skills/sync-meetings-to-odoo
90
+ ```
91
+
92
+ ### 2. Global Activation
93
+ Alternatively, copy or link these directories into your global configuration directory (usually located at `~/.gemini/config/skills/`):
94
+ ```bash
95
+ cp -r skills/vendor/* ~/.gemini/config/skills/
96
+ cp -r skills/actions/* ~/.gemini/config/skills/
97
+ ```
98
+
99
+ Once linked/copied, the LLM agent will detect the frontmatter name and description in each `SKILL.md` (e.g. `google-calendar`, `odoo-integration`), matching user requests to the respective CLI tools and executing actions autonomously.
100
+
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Exit immediately if a command exits with a non-zero status
4
+ set -e
5
+
6
+ WORKSPACE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
7
+ cd "$WORKSPACE_ROOT"
8
+
9
+ echo "=== Sales Skills LLM Activation & Update Script ==="
10
+
11
+ # 1. Local Workspace-Specific Customizations (.agents)
12
+ echo "Setting up local Gemini agent workspace customizations..."
13
+ mkdir -p .agents/skills
14
+
15
+ # Helper to link if target doesn't exist, or update/force symlink
16
+ link_skill() {
17
+ local src="$1"
18
+ local dest=".agents/skills/$2"
19
+ echo "Linking skill '$2' -> '$src'..."
20
+ ln -sfh "../../$src" "$dest"
21
+ }
22
+
23
+ link_skill "skills/vendor/google" "google-calendar"
24
+ link_skill "skills/vendor/odoo" "odoo-integration"
25
+ link_skill "skills/vendor/brevo" "brevo-integration"
26
+ link_skill "skills/actions/sync-meetings-to-odoo" "sync-meetings-to-odoo"
27
+
28
+ # Link AGENT.md as workspace customizations rule AGENTS.md
29
+ echo "Linking AGENT.md -> .agents/AGENTS.md..."
30
+ ln -sf "../AGENT.md" .agents/AGENTS.md
31
+
32
+ # 2. Cline & Roo Code Rule Files
33
+ echo "Setting up rules for Cline and Roo Code assistants..."
34
+ ln -sf "AGENT.md" .clinerules
35
+ ln -sf "AGENT.md" .roomodes
36
+
37
+ # 3. Global Gemini Assistant Skills (Optional)
38
+ GLOBAL_GEMINI_SKILLS_DIR="$HOME/.gemini/config/skills"
39
+ if [ -d "$HOME/.gemini/config" ]; then
40
+ echo "Global Gemini config found. Setting up global skills..."
41
+ mkdir -p "$GLOBAL_GEMINI_SKILLS_DIR"
42
+
43
+ # Link/update skills globally
44
+ ln -sfh "$WORKSPACE_ROOT/skills/vendor/google" "$GLOBAL_GEMINI_SKILLS_DIR/google-calendar"
45
+ ln -sfh "$WORKSPACE_ROOT/skills/vendor/odoo" "$GLOBAL_GEMINI_SKILLS_DIR/odoo-integration"
46
+ ln -sfh "$WORKSPACE_ROOT/skills/vendor/brevo" "$GLOBAL_GEMINI_SKILLS_DIR/brevo-integration"
47
+ ln -sfh "$WORKSPACE_ROOT/skills/actions/sync-meetings-to-odoo" "$GLOBAL_GEMINI_SKILLS_DIR/sync-meetings-to-odoo"
48
+
49
+ echo "Global skills successfully symlinked to $GLOBAL_GEMINI_SKILLS_DIR"
50
+ else
51
+ echo "Global Gemini config path not found. Skipping global registration."
52
+ fi
53
+
54
+ echo "Success! Skills are linked, activated, and updated."
@@ -0,0 +1,172 @@
1
+ import { $ } from "bun";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+
5
+ const LM_STUDIO_URL = process.env.LM_STUDIO_URL || "http://localhost:1234/v1";
6
+ const MODEL_NAME = process.env.LM_STUDIO_MODEL || "qwen2.5-coder-7b-instruct"; // Default fallback model name
7
+
8
+ console.log(`=== LM Studio Local Agent Runner ===`);
9
+ console.log(`Connecting to LM Studio at: ${LM_STUDIO_URL}`);
10
+ console.log(`Using model: ${MODEL_NAME}`);
11
+
12
+ // Define tools according to OpenAI / LM Studio specification
13
+ const TOOLS = [
14
+ {
15
+ type: "function",
16
+ function: {
17
+ name: "search_odoo_partners",
18
+ description: "Search for contacts or companies in Odoo ERP matching a query string.",
19
+ parameters: {
20
+ type: "object",
21
+ properties: {
22
+ query: { type: "string", description: "Search query (email, name, or domain)" },
23
+ limit: { type: "integer", description: "Maximum number of partners to return", default: 5 }
24
+ },
25
+ required: ["query"]
26
+ }
27
+ }
28
+ },
29
+ {
30
+ type: "function",
31
+ function: {
32
+ name: "list_google_events",
33
+ description: "List upcoming calendar events from Google Calendar.",
34
+ parameters: {
35
+ type: "object",
36
+ properties: {
37
+ calendarId: { type: "string", description: "Email address of the calendar owner", default: "primary" },
38
+ limit: { type: "integer", description: "Maximum number of events to fetch", default: 10 }
39
+ },
40
+ required: ["calendarId"]
41
+ }
42
+ }
43
+ },
44
+ {
45
+ type: "function",
46
+ function: {
47
+ name: "sync_meetings_to_odoo",
48
+ description: "Sync meetings from Google Calendar to Odoo CRM interactively, confirming contacts and meetings creation.",
49
+ parameters: {
50
+ type: "object",
51
+ properties: {
52
+ calendarId: { type: "string", description: "Google Calendar owner email (defaults to Odoo login)" },
53
+ date: { type: "string", description: "Target date to sync in YYYY-MM-DD format (defaults to today)" }
54
+ },
55
+ required: ["calendarId"]
56
+ }
57
+ }
58
+ }
59
+ ];
60
+
61
+ // Helper to execute local CLI scripts and return the JSON output
62
+ async function executeTool(name: string, args: any): Promise<any> {
63
+ const logDir = join(process.cwd(), ".log");
64
+ await $`mkdir -p ${logDir}`;
65
+ const outputPath = join(logDir, `lm_studio_${name}_result.json`);
66
+
67
+ console.log(`\n[Executing Tool: ${name} with arguments:`, args, "]");
68
+
69
+ try {
70
+ if (name === "search_odoo_partners") {
71
+ const limit = args.limit || 5;
72
+ await $`bun run skills/vendor/odoo/cli.ts search-partners --query ${args.query} --limit ${limit} --output ${outputPath}`;
73
+ } else if (name === "list_google_events") {
74
+ const limit = args.limit || 10;
75
+ await $`bun run skills/vendor/google/cli.ts list-events --calendar-id ${args.calendarId} --limit ${limit} --output ${outputPath}`;
76
+ } else if (name === "sync_meetings_to_odoo") {
77
+ const dateOption = args.date ? ["--date", args.date] : [];
78
+ // Note: This script is interactive and uses stdin. We spawn it inheriting parent terminal I/O.
79
+ await $`bun run skills/actions/sync-meetings-to-odoo/scripts/sync_meetings_cli.ts --calendar-id ${args.calendarId} ${dateOption} --output ${outputPath}`.inherit();
80
+ } else {
81
+ throw new Error(`Unknown tool name: ${name}`);
82
+ }
83
+
84
+ if (existsSync(outputPath)) {
85
+ const content = readFileSync(outputPath, "utf8");
86
+ return JSON.parse(content);
87
+ }
88
+ return { status: "success", info: "Command ran successfully, but no output JSON was produced." };
89
+ } catch (err: any) {
90
+ console.error(`Tool execution failed: ${err.message}`);
91
+ return { error: err.message };
92
+ }
93
+ }
94
+
95
+ // Simple agent loop
96
+ async function runAgent(prompt: string) {
97
+ const messages: any[] = [
98
+ {
99
+ role: "system",
100
+ content: "You are a helpful sales assistant with access to Odoo CRM, Google Calendar, and Brevo tools. Run actions whenever requested."
101
+ },
102
+ { role: "user", content: prompt }
103
+ ];
104
+
105
+ let loop = true;
106
+ while (loop) {
107
+ try {
108
+ const response = await fetch(`${LM_STUDIO_URL}/chat/completions`, {
109
+ method: "POST",
110
+ headers: { "Content-Type": "application/json" },
111
+ body: JSON.stringify({
112
+ model: MODEL_NAME,
113
+ messages,
114
+ tools: TOOLS,
115
+ tool_choice: "auto"
116
+ })
117
+ });
118
+
119
+ if (!response.ok) {
120
+ throw new Error(`HTTP error ${response.status}: ${await response.text()}`);
121
+ }
122
+
123
+ const result = await response.json();
124
+ const choice = result.choices?.[0];
125
+ const message = choice?.message;
126
+
127
+ if (!message) {
128
+ console.log("No response message received.");
129
+ break;
130
+ }
131
+
132
+ // Add assistant response to history
133
+ messages.push(message);
134
+
135
+ if (message.tool_calls && message.tool_calls.length > 0) {
136
+ for (const toolCall of message.tool_calls) {
137
+ const functionName = toolCall.function.name;
138
+ const functionArgs = JSON.parse(toolCall.function.arguments);
139
+
140
+ const resultPayload = await executeTool(functionName, functionArgs);
141
+
142
+ // Add tool result to history
143
+ messages.push({
144
+ role: "tool",
145
+ tool_call_id: toolCall.id,
146
+ name: functionName,
147
+ content: JSON.stringify(resultPayload)
148
+ });
149
+ }
150
+ } else {
151
+ // Model returned final text answer
152
+ console.log(`\n[Assistant Response]:\n${message.content}`);
153
+ loop = false;
154
+ }
155
+ } catch (err: any) {
156
+ console.error(`Agent loop error: ${err.message}`);
157
+ break;
158
+ }
159
+ }
160
+ }
161
+
162
+ // Run using prompt argument or exit
163
+ const userPrompt = process.argv.slice(2).join(" ");
164
+ if (!userPrompt) {
165
+ console.log("Usage: bun run bin/lm_studio_agent.ts <your prompt here>");
166
+ console.log("Example: bun run bin/lm_studio_agent.ts 'Search Odoo for contacts at infotel'");
167
+ process.exit(1);
168
+ }
169
+
170
+ runAgent(userPrompt).catch((err) => {
171
+ console.error("Agent execution failed:", err);
172
+ });
@@ -0,0 +1,69 @@
1
+ const fs = require('node:fs');
2
+ const path = require('node:path');
3
+ const { execSync } = require('node:child_process');
4
+
5
+ const pkgPath = './package.json';
6
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
7
+
8
+ console.log('[PREPARE] Resolving workspace dependencies for CI install...');
9
+
10
+ // Remove workspaces since they don't exist in CI
11
+ delete pkg.workspaces;
12
+
13
+ let changed = false;
14
+ for (const depType of ['dependencies', 'devDependencies', 'peerDependencies']) {
15
+ if (pkg[depType]) {
16
+ for (const [name, val] of Object.entries(pkg[depType])) {
17
+ if (typeof val === 'string' && (val === 'workspace:*' || val.startsWith('workspace:'))) {
18
+ try {
19
+ // Query the version from the registry
20
+ console.log(`[PREPARE] Querying registry version for ${name}...`);
21
+ const latestVersion = execSync(`npm view ${name} version`, { encoding: 'utf8' }).trim();
22
+ pkg[depType][name] = `^${latestVersion}`;
23
+ console.log(`[PREPARE] Resolved ${name} dependency to ^${latestVersion}`);
24
+ changed = true;
25
+ } catch (err) {
26
+ console.warn(`[WARNING] Failed to resolve version for ${name} from registry: ${err.message}`);
27
+
28
+ // Try local workspace fallback if present
29
+ let resolvedLocal = false;
30
+ const corePkgsDir = path.resolve(process.cwd(), '../../QUATRAIN/Core/packages');
31
+ if (fs.existsSync(corePkgsDir)) {
32
+ try {
33
+ const dirs = fs.readdirSync(corePkgsDir);
34
+ for (const dir of dirs) {
35
+ const localPkgJsonPath = path.join(corePkgsDir, dir, 'package.json');
36
+ if (fs.existsSync(localPkgJsonPath)) {
37
+ const localPkgJson = JSON.parse(fs.readFileSync(localPkgJsonPath, 'utf8'));
38
+ if (localPkgJson.name === name) {
39
+ pkg[depType][name] = `^${localPkgJson.version}`;
40
+ console.log(`[PREPARE] Resolved ${name} from local workspace to ^${localPkgJson.version}`);
41
+ changed = true;
42
+ resolvedLocal = true;
43
+ break;
44
+ }
45
+ }
46
+ }
47
+ } catch (e) {
48
+ // ignore
49
+ }
50
+ }
51
+
52
+ if (!resolvedLocal) {
53
+ // Fallback to '*' if it is not published yet and local workspace not found
54
+ pkg[depType][name] = '*';
55
+ console.log(`[PREPARE] Fallback resolved ${name} dependency to *`);
56
+ changed = true;
57
+ }
58
+ }
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+ if (changed || pkg.hasOwnProperty('workspaces')) {
65
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8');
66
+ console.log('[PREPARE] package.json updated successfully.');
67
+ } else {
68
+ console.log('[PREPARE] No changes made to package.json.');
69
+ }