@looplia/looplia-cli 0.6.8 → 0.6.9

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/dist/cli.js CHANGED
@@ -243,11 +243,12 @@ async function getPluginPaths() {
243
243
  return await getProdPluginPaths();
244
244
  }
245
245
 
246
- // ../../packages/provider/dist/chunk-4PGJBKLH.js
246
+ // ../../packages/provider/dist/chunk-5W3I2MT7.js
247
247
  import { execSync } from "child_process";
248
248
  import { existsSync as existsSync3 } from "fs";
249
+ import { createRequire } from "module";
249
250
  import { homedir as homedir3 } from "os";
250
- import { join as join4 } from "path";
251
+ import { dirname as dirname3, join as join4 } from "path";
251
252
 
252
253
  // ../../node_modules/zod-to-json-schema/dist/esm/Options.js
253
254
  var ignoreOverride = /* @__PURE__ */ Symbol("Let zodToJsonSchema decide on which parser to use");
@@ -5574,7 +5575,7 @@ var zodToJsonSchema = (schema, options) => {
5574
5575
  return combined;
5575
5576
  };
5576
5577
 
5577
- // ../../node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs
5578
+ // ../../packages/provider/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs
5578
5579
  import { join as join5 } from "path";
5579
5580
  import { fileURLToPath as fileURLToPath23 } from "url";
5580
5581
  import { setMaxListeners } from "events";
@@ -27369,7 +27370,7 @@ function query({
27369
27370
  return queryInstance;
27370
27371
  }
27371
27372
 
27372
- // ../../packages/provider/dist/chunk-4PGJBKLH.js
27373
+ // ../../packages/provider/dist/chunk-5W3I2MT7.js
27373
27374
  import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync2 } from "fs";
27374
27375
  import { join as join23 } from "path";
27375
27376
  import {
@@ -27385,6 +27386,22 @@ import { join as join32 } from "path";
27385
27386
  import { cp as cp2, mkdir as mkdir22, readFile as readFile22, rm as rm22, stat as stat2, writeFile as writeFile22 } from "fs/promises";
27386
27387
  import { homedir as homedir32 } from "os";
27387
27388
  import { isAbsolute, join as join42, normalize, resolve } from "path";
27389
+ var LINE_SPLIT_REGEX = /\r?\n/;
27390
+ function findSdkBundledCliPath() {
27391
+ try {
27392
+ const require2 = createRequire(import.meta.url);
27393
+ const sdkPackagePath = require2.resolve(
27394
+ "@anthropic-ai/claude-agent-sdk/package.json"
27395
+ );
27396
+ const sdkDir = dirname3(sdkPackagePath);
27397
+ const cliPath = join4(sdkDir, "cli.js");
27398
+ if (existsSync3(cliPath)) {
27399
+ return cliPath;
27400
+ }
27401
+ } catch {
27402
+ }
27403
+ return;
27404
+ }
27388
27405
  var CLAUDE_CODE_PATHS = [
27389
27406
  // User's local bin (npm global install location)
27390
27407
  join4(homedir3(), ".local", "bin", "claude"),
@@ -27395,36 +27412,42 @@ var CLAUDE_CODE_PATHS = [
27395
27412
  // Windows (if applicable)
27396
27413
  join4(homedir3(), "AppData", "Local", "Programs", "claude", "claude.exe")
27397
27414
  ];
27415
+ var cachedClaudeCodePath;
27398
27416
  function findClaudeCodePath() {
27417
+ if (cachedClaudeCodePath !== void 0) {
27418
+ return cachedClaudeCodePath ?? void 0;
27419
+ }
27399
27420
  const envPath = process.env.CLAUDE_CODE_PATH;
27400
27421
  if (envPath && existsSync3(envPath)) {
27401
- return envPath;
27422
+ cachedClaudeCodePath = envPath;
27423
+ return cachedClaudeCodePath;
27402
27424
  }
27403
27425
  for (const path3 of CLAUDE_CODE_PATHS) {
27404
27426
  if (existsSync3(path3)) {
27405
- return path3;
27427
+ cachedClaudeCodePath = path3;
27428
+ return cachedClaudeCodePath;
27406
27429
  }
27407
27430
  }
27408
27431
  try {
27409
- const whichResult = execSync("which claude", {
27432
+ const pathLookupCommand = process.platform === "win32" ? "where claude" : "which claude";
27433
+ const rawResult = execSync(pathLookupCommand, {
27410
27434
  encoding: "utf-8",
27411
27435
  stdio: ["pipe", "pipe", "pipe"]
27412
27436
  }).trim();
27413
- if (whichResult && existsSync3(whichResult)) {
27414
- return whichResult;
27437
+ const firstResult = rawResult.split(LINE_SPLIT_REGEX).find((line) => line.trim().length > 0) ?? "";
27438
+ if (firstResult && existsSync3(firstResult)) {
27439
+ cachedClaudeCodePath = firstResult;
27440
+ return cachedClaudeCodePath;
27415
27441
  }
27416
27442
  } catch {
27417
27443
  }
27418
- throw new Error(
27419
- `Claude Code not found. Looplia requires Claude Code to be installed.
27420
-
27421
- Install Claude Code:
27422
- npm install -g @anthropic-ai/claude-code
27423
-
27424
- Or set CLAUDE_CODE_PATH environment variable to your Claude installation.
27425
-
27426
- More info: https://docs.anthropic.com/claude-code`
27427
- );
27444
+ const sdkCliPath = findSdkBundledCliPath();
27445
+ if (sdkCliPath) {
27446
+ cachedClaudeCodePath = sdkCliPath;
27447
+ return cachedClaudeCodePath;
27448
+ }
27449
+ cachedClaudeCodePath = null;
27450
+ return;
27428
27451
  }
27429
27452
  var DEFAULT_CONFIG = {
27430
27453
  model: "claude-haiku-4-5-20251001",
@@ -27489,7 +27512,7 @@ var DEFAULT_SETTINGS = {
27489
27512
  },
27490
27513
  agents: {
27491
27514
  main: "claude-haiku-4-5-20251001",
27492
- executor: "haiku"
27515
+ executor: "claude-haiku-4-5-20251001"
27493
27516
  }
27494
27517
  };
27495
27518
  var PRESETS = {
@@ -27498,13 +27521,19 @@ var PRESETS = {
27498
27521
  name: "Anthropic Claude Haiku",
27499
27522
  apiProvider: "anthropic",
27500
27523
  mainModel: "claude-haiku-4-5-20251001",
27501
- executorModel: "haiku"
27524
+ executorModel: "claude-haiku-4-5-20251001",
27525
+ haikuModel: "claude-haiku-4-5-20251001",
27526
+ sonnetModel: "claude-haiku-4-5-20251001",
27527
+ opusModel: "claude-haiku-4-5-20251001"
27502
27528
  },
27503
27529
  ANTHROPIC_CLAUDE_SONNET: {
27504
27530
  name: "Anthropic Claude Sonnet",
27505
27531
  apiProvider: "anthropic",
27506
27532
  mainModel: "claude-sonnet-4-5-20250514",
27507
- executorModel: "haiku"
27533
+ executorModel: "claude-sonnet-4-5-20250514",
27534
+ haikuModel: "claude-sonnet-4-5-20250514",
27535
+ sonnetModel: "claude-sonnet-4-5-20250514",
27536
+ opusModel: "claude-sonnet-4-5-20250514"
27508
27537
  },
27509
27538
  // ZenMux Presets
27510
27539
  ZENMUX_ANTHROPIC_HAIKU45: {
@@ -27512,98 +27541,140 @@ var PRESETS = {
27512
27541
  apiProvider: "zenmux",
27513
27542
  baseUrl: "https://zenmux.ai/api/anthropic",
27514
27543
  mainModel: "anthropic/claude-haiku-4.5",
27515
- executorModel: "anthropic/claude-haiku-4.5"
27544
+ executorModel: "anthropic/claude-haiku-4.5",
27545
+ haikuModel: "anthropic/claude-haiku-4.5",
27546
+ sonnetModel: "anthropic/claude-haiku-4.5",
27547
+ opusModel: "anthropic/claude-haiku-4.5"
27516
27548
  },
27517
27549
  ZENMUX_ZAI_GLM47: {
27518
27550
  name: "ZenMux GLM-4.7",
27519
27551
  apiProvider: "zenmux",
27520
27552
  baseUrl: "https://zenmux.ai/api/anthropic",
27521
27553
  mainModel: "z-ai/glm-4.7",
27522
- executorModel: "z-ai/glm-4.7"
27554
+ executorModel: "z-ai/glm-4.7",
27555
+ haikuModel: "z-ai/glm-4.7",
27556
+ sonnetModel: "z-ai/glm-4.7",
27557
+ opusModel: "z-ai/glm-4.7"
27523
27558
  },
27524
27559
  ZENMUX_MINIMAX_M21: {
27525
27560
  name: "ZenMux MiniMax-M2.1",
27526
27561
  apiProvider: "zenmux",
27527
27562
  baseUrl: "https://zenmux.ai/api/anthropic",
27528
27563
  mainModel: "minimax/minimax-m2.1",
27529
- executorModel: "minimax/minimax-m2.1"
27564
+ executorModel: "minimax/minimax-m2.1",
27565
+ haikuModel: "minimax/minimax-m2.1",
27566
+ sonnetModel: "minimax/minimax-m2.1",
27567
+ opusModel: "minimax/minimax-m2.1"
27530
27568
  },
27531
27569
  ZENMUX_GOOGLE_GEMINI3FLASH: {
27532
27570
  name: "ZenMux Gemini-3-Flash",
27533
27571
  apiProvider: "zenmux",
27534
27572
  baseUrl: "https://zenmux.ai/api/anthropic",
27535
27573
  mainModel: "google/gemini-3-flash-preview",
27536
- executorModel: "google/gemini-3-flash-preview"
27574
+ executorModel: "google/gemini-3-flash-preview",
27575
+ haikuModel: "google/gemini-3-flash-preview",
27576
+ sonnetModel: "google/gemini-3-flash-preview",
27577
+ opusModel: "google/gemini-3-flash-preview"
27537
27578
  },
27538
27579
  ZENMUX_GOOGLE_GEMINI3FLASH_FREE: {
27539
27580
  name: "ZenMux Gemini-3-Flash (Free)",
27540
27581
  apiProvider: "zenmux",
27541
27582
  baseUrl: "https://zenmux.ai/api/anthropic",
27542
27583
  mainModel: "google/gemini-3-flash-preview-free",
27543
- executorModel: "google/gemini-3-flash-preview-free"
27584
+ executorModel: "google/gemini-3-flash-preview-free",
27585
+ haikuModel: "google/gemini-3-flash-preview-free",
27586
+ sonnetModel: "google/gemini-3-flash-preview-free",
27587
+ opusModel: "google/gemini-3-flash-preview-free"
27544
27588
  },
27545
27589
  ZENMUX_XIAOMI_MIMOV2FLASH: {
27546
27590
  name: "ZenMux MiMo-v2-Flash",
27547
27591
  apiProvider: "zenmux",
27548
27592
  baseUrl: "https://zenmux.ai/api/anthropic",
27549
27593
  mainModel: "xiaomi/mimo-v2-flash",
27550
- executorModel: "xiaomi/mimo-v2-flash"
27594
+ executorModel: "xiaomi/mimo-v2-flash",
27595
+ haikuModel: "xiaomi/mimo-v2-flash",
27596
+ sonnetModel: "xiaomi/mimo-v2-flash",
27597
+ opusModel: "xiaomi/mimo-v2-flash"
27551
27598
  },
27552
27599
  ZENMUX_XAI_GROK41FAST: {
27553
27600
  name: "ZenMux Grok-4.1-Fast",
27554
27601
  apiProvider: "zenmux",
27555
27602
  baseUrl: "https://zenmux.ai/api/anthropic",
27556
27603
  mainModel: "x-ai/grok-4.1-fast",
27557
- executorModel: "x-ai/grok-4.1-fast"
27604
+ executorModel: "x-ai/grok-4.1-fast",
27605
+ haikuModel: "x-ai/grok-4.1-fast",
27606
+ sonnetModel: "x-ai/grok-4.1-fast",
27607
+ opusModel: "x-ai/grok-4.1-fast"
27558
27608
  },
27559
27609
  ZENMUX_DEEPSEEK_V32: {
27560
27610
  name: "ZenMux DeepSeek-v3.2",
27561
27611
  apiProvider: "zenmux",
27562
27612
  baseUrl: "https://zenmux.ai/api/anthropic",
27563
27613
  mainModel: "deepseek/deepseek-v3.2",
27564
- executorModel: "deepseek/deepseek-v3.2"
27614
+ executorModel: "deepseek/deepseek-v3.2",
27615
+ haikuModel: "deepseek/deepseek-v3.2",
27616
+ sonnetModel: "deepseek/deepseek-v3.2",
27617
+ opusModel: "deepseek/deepseek-v3.2"
27565
27618
  },
27566
27619
  ZENMUX_DEEPSEEK_REASONER: {
27567
27620
  name: "ZenMux DeepSeek-Reasoner",
27568
27621
  apiProvider: "zenmux",
27569
27622
  baseUrl: "https://zenmux.ai/api/anthropic",
27570
27623
  mainModel: "deepseek/deepseek-reasoner",
27571
- executorModel: "deepseek/deepseek-reasoner"
27624
+ executorModel: "deepseek/deepseek-reasoner",
27625
+ haikuModel: "deepseek/deepseek-reasoner",
27626
+ sonnetModel: "deepseek/deepseek-reasoner",
27627
+ opusModel: "deepseek/deepseek-reasoner"
27572
27628
  },
27573
27629
  ZENMUX_VOLCENGINE_DOUBAO_SEED: {
27574
27630
  name: "ZenMux Doubao-Seed-1.8",
27575
27631
  apiProvider: "zenmux",
27576
27632
  baseUrl: "https://zenmux.ai/api/anthropic",
27577
27633
  mainModel: "volcengine/doubao-seed-1.8",
27578
- executorModel: "volcengine/doubao-seed-1.8"
27634
+ executorModel: "volcengine/doubao-seed-1.8",
27635
+ haikuModel: "volcengine/doubao-seed-1.8",
27636
+ sonnetModel: "volcengine/doubao-seed-1.8",
27637
+ opusModel: "volcengine/doubao-seed-1.8"
27579
27638
  },
27580
27639
  ZENMUX_MISTRAL_LARGE2512: {
27581
27640
  name: "ZenMux Mistral-Large-2512",
27582
27641
  apiProvider: "zenmux",
27583
27642
  baseUrl: "https://zenmux.ai/api/anthropic",
27584
27643
  mainModel: "mistralai/mistral-large-2512",
27585
- executorModel: "mistralai/mistral-large-2512"
27644
+ executorModel: "mistralai/mistral-large-2512",
27645
+ haikuModel: "mistralai/mistral-large-2512",
27646
+ sonnetModel: "mistralai/mistral-large-2512",
27647
+ opusModel: "mistralai/mistral-large-2512"
27586
27648
  },
27587
27649
  ZENMUX_ZAI_GLM46VFLASH: {
27588
27650
  name: "ZenMux GLM-4.6v-Flash",
27589
27651
  apiProvider: "zenmux",
27590
27652
  baseUrl: "https://zenmux.ai/api/anthropic",
27591
27653
  mainModel: "z-ai/glm-4.6v-flash",
27592
- executorModel: "z-ai/glm-4.6v-flash"
27654
+ executorModel: "z-ai/glm-4.6v-flash",
27655
+ haikuModel: "z-ai/glm-4.6v-flash",
27656
+ sonnetModel: "z-ai/glm-4.6v-flash",
27657
+ opusModel: "z-ai/glm-4.6v-flash"
27593
27658
  },
27594
27659
  ZENMUX_ZAI_GLM46V: {
27595
27660
  name: "ZenMux GLM-4.6v",
27596
27661
  apiProvider: "zenmux",
27597
27662
  baseUrl: "https://zenmux.ai/api/anthropic",
27598
27663
  mainModel: "z-ai/glm-4.6v",
27599
- executorModel: "z-ai/glm-4.6v"
27664
+ executorModel: "z-ai/glm-4.6v",
27665
+ haikuModel: "z-ai/glm-4.6v",
27666
+ sonnetModel: "z-ai/glm-4.6v",
27667
+ opusModel: "z-ai/glm-4.6v"
27600
27668
  },
27601
27669
  ZENMUX_OPENAI_GPT51CODEXMINI: {
27602
27670
  name: "ZenMux GPT-5.1 Codex Mini",
27603
27671
  apiProvider: "zenmux",
27604
27672
  baseUrl: "https://zenmux.ai/api/anthropic",
27605
27673
  mainModel: "openai/gpt-5.1-codex-mini",
27606
- executorModel: "openai/gpt-5.1-codex-mini"
27674
+ executorModel: "openai/gpt-5.1-codex-mini",
27675
+ haikuModel: "openai/gpt-5.1-codex-mini",
27676
+ sonnetModel: "openai/gpt-5.1-codex-mini",
27677
+ opusModel: "openai/gpt-5.1-codex-mini"
27607
27678
  }
27608
27679
  };
27609
27680
  var CONFIG_FILE = "looplia.setting.json";
@@ -27643,23 +27714,33 @@ async function writeLoopliaSettings(settings) {
27643
27714
  async function removeLoopliaSettings() {
27644
27715
  await rm2(getConfigPath(), { force: true });
27645
27716
  }
27717
+ function setEnvIfNotSet(key, value) {
27718
+ if (!process.env[key]) {
27719
+ process.env[key] = value;
27720
+ }
27721
+ }
27722
+ function injectModelTierEnv(mainModel, executorModel) {
27723
+ setEnvIfNotSet("ANTHROPIC_DEFAULT_HAIKU_MODEL", mainModel);
27724
+ setEnvIfNotSet("ANTHROPIC_DEFAULT_SONNET_MODEL", mainModel);
27725
+ setEnvIfNotSet("ANTHROPIC_DEFAULT_OPUS_MODEL", mainModel);
27726
+ setEnvIfNotSet("LOOPLIA_AGENT_MODEL_MAIN", mainModel);
27727
+ setEnvIfNotSet("LOOPLIA_AGENT_MODEL_EXECUTOR", executorModel);
27728
+ }
27646
27729
  function injectLoopliaSettingsEnv(settings) {
27647
27730
  if (settings.apiProvider.type !== "anthropic") {
27648
27731
  if (settings.apiProvider.baseUrl && !process.env.ANTHROPIC_BASE_URL) {
27649
27732
  process.env.ANTHROPIC_BASE_URL = settings.apiProvider.baseUrl;
27650
27733
  }
27651
- if (settings.apiProvider.type === "zenmux" && process.env.ZENMUX_API_KEY) {
27652
- process.env.ANTHROPIC_API_KEY = process.env.ZENMUX_API_KEY;
27653
- } else if (!process.env.ANTHROPIC_API_KEY && settings.apiProvider.authToken) {
27734
+ if (settings.apiProvider.authToken) {
27654
27735
  process.env.ANTHROPIC_API_KEY = settings.apiProvider.authToken;
27736
+ } else {
27737
+ const isZenmuxEndpoint = settings.apiProvider.type === "zenmux" || settings.apiProvider.baseUrl?.includes("zenmux.ai");
27738
+ if (isZenmuxEndpoint && process.env.ZENMUX_API_KEY) {
27739
+ process.env.ANTHROPIC_API_KEY = process.env.ZENMUX_API_KEY;
27740
+ }
27655
27741
  }
27656
27742
  }
27657
- if (!process.env.LOOPLIA_AGENT_MODEL_MAIN) {
27658
- process.env.LOOPLIA_AGENT_MODEL_MAIN = settings.agents.main;
27659
- }
27660
- if (!process.env.LOOPLIA_AGENT_MODEL_EXECUTOR) {
27661
- process.env.LOOPLIA_AGENT_MODEL_EXECUTOR = settings.agents.executor;
27662
- }
27743
+ injectModelTierEnv(settings.agents.main, settings.agents.executor);
27663
27744
  }
27664
27745
  function getSettingsDisplayInfo(settings) {
27665
27746
  if (!settings) {
@@ -28495,14 +28576,10 @@ async function initializeAndValidateApiKey(config2) {
28495
28576
  "API key is required. Set ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN environment variable"
28496
28577
  );
28497
28578
  }
28498
- const isProxyProvider = settings !== null && settings.apiProvider.type !== "anthropic";
28499
- return { apiKey, isProxyProvider };
28579
+ return apiKey;
28500
28580
  }
28501
- function getAgentModels() {
28502
- return {
28503
- mainModel: process.env.LOOPLIA_AGENT_MODEL_MAIN ?? DEFAULT_SETTINGS.agents.main,
28504
- executorModel: process.env.LOOPLIA_AGENT_MODEL_EXECUTOR ?? DEFAULT_SETTINGS.agents.executor
28505
- };
28581
+ function getMainModel() {
28582
+ return process.env.LOOPLIA_AGENT_MODEL_MAIN ?? DEFAULT_SETTINGS.agents.main;
28506
28583
  }
28507
28584
  function* processEvent(event, progressTracker, context) {
28508
28585
  if (event.type === "tool_start" && event.tool === "Skill") {
@@ -28518,8 +28595,8 @@ function* processEvent(event, progressTracker, context) {
28518
28595
  }
28519
28596
  async function* executeAgenticQueryStreaming(prompt, jsonSchema, config2) {
28520
28597
  const resolvedConfig = resolveConfig(config2);
28521
- const { isProxyProvider } = await initializeAndValidateApiKey(config2);
28522
- const { mainModel, executorModel } = getAgentModels();
28598
+ await initializeAndValidateApiKey(config2);
28599
+ const mainModel = getMainModel();
28523
28600
  try {
28524
28601
  const workspace = config2?.workspace ?? await getOrInitWorkspace(
28525
28602
  resolvedConfig.workspace,
@@ -28547,54 +28624,24 @@ async function* executeAgenticQueryStreaming(prompt, jsonSchema, config2) {
28547
28624
  const context = createTransformContext(
28548
28625
  resolvedConfig.model
28549
28626
  );
28550
- const pluginPaths = await getPluginPaths();
28627
+ const pluginPaths = process.env.LOOPLIA_NO_PLUGINS === "true" ? [] : await getPluginPaths();
28628
+ if (process.env.LOOPLIA_DEBUG === "true") {
28629
+ console.error(
28630
+ "[LOOPLIA_DEBUG] Plugin paths:",
28631
+ JSON.stringify(pluginPaths)
28632
+ );
28633
+ }
28551
28634
  const userCwd = process.cwd();
28552
- const loopliaHome = getLoopliaPluginPath();
28553
- const workflowExecutionHint = isProxyProvider ? `
28554
-
28555
- ## Workflow Execution Mode: Inline (Proxy Provider)
28556
-
28557
- When executing looplia workflows (/run commands), use the "workflow-executor-inline" skill.
28558
- Execute all workflow steps INLINE without spawning Task subagents.
28559
- This ensures compatibility with your current API provider.` : "";
28560
- const agents = isProxyProvider ? void 0 : {
28561
- "skill-executor": {
28562
- description: "Universal skill orchestrator for looplia workflow steps. Executes a single workflow step by invoking skills.",
28563
- prompt: `You are the looplia skill-executor. Execute ONE workflow step by invoking the specified skill.
28564
-
28565
- ## Execution Protocol
28566
- 1. Read input files (if provided)
28567
- 2. Invoke the skill using the Skill tool
28568
- 3. Execute the mission with skill context
28569
- 4. Write JSON output to the specified path using Write tool
28570
-
28571
- ## CRITICAL: Output Writing is MANDATORY
28572
- YOU MUST CALL THE WRITE TOOL before completing. If you don't write the file, the workflow fails.
28573
-
28574
- ## Rules
28575
- - ALWAYS invoke the specified skill using Skill tool
28576
- - ALWAYS write output to the exact path using Write tool
28577
- - NEVER return results as text - always write JSON to output file
28578
- - NEVER spawn Task subagents - execute skills directly
28579
- - ALWAYS include contentId in JSON outputs`,
28580
- tools: [
28581
- "Read",
28582
- "Write",
28583
- "Skill",
28584
- "Glob",
28585
- "Grep",
28586
- "WebSearch",
28587
- "WebFetch"
28588
- ],
28589
- model: executorModel
28590
- }
28591
- };
28635
+ const loopliaHome = process.env.LOOPLIA_WORKSPACE_PATH ?? getLoopliaPluginPath();
28636
+ if (process.env.LOOPLIA_DEBUG === "true") {
28637
+ console.error("[LOOPLIA_DEBUG] loopliaHome:", loopliaHome);
28638
+ }
28592
28639
  const claudeCodePath = findClaudeCodePath();
28593
28640
  const result = query({
28594
28641
  prompt,
28595
28642
  options: {
28596
- // v0.6.8: Use system-installed Claude Code
28597
- pathToClaudeCodeExecutable: claudeCodePath,
28643
+ // v0.6.8: Use system-installed Claude Code if available, otherwise SDK uses built-in
28644
+ ...claudeCodePath && { pathToClaudeCodeExecutable: claudeCodePath },
28598
28645
  // v0.6.6: Use configured main model
28599
28646
  model: mainModel,
28600
28647
  // v0.6.5: SDK works relative to ~/.looplia (sandbox, workflows, etc.)
@@ -28604,7 +28651,7 @@ YOU MUST CALL THE WRITE TOOL before completing. If you don't write the file, the
28604
28651
  // v0.6.5: Load plugins from local paths instead of project settings
28605
28652
  plugins: pluginPaths,
28606
28653
  // v0.6.5: Append looplia system prompt + user context to claude_code preset
28607
- // v0.6.6: Add provider-aware workflow hint for proxy providers
28654
+ // v0.6.9: Removed provider-aware hint - unified subagent strategy for all providers
28608
28655
  systemPrompt: {
28609
28656
  type: "preset",
28610
28657
  preset: "claude_code",
@@ -28614,7 +28661,7 @@ YOU MUST CALL THE WRITE TOOL before completing. If you don't write the file, the
28614
28661
 
28615
28662
  User Working Directory: ${userCwd}
28616
28663
 
28617
- When processing --file arguments or user file paths, resolve them against the User Working Directory above.${workflowExecutionHint}`
28664
+ When processing --file arguments or user file paths, resolve them against the User Working Directory above.`
28618
28665
  },
28619
28666
  // v0.6.0: Enable Task for subagent spawning, Write/Glob for file operations
28620
28667
  // v0.6.3: Added WebSearch/WebFetch for input-less search skill
@@ -28627,9 +28674,8 @@ When processing --file arguments or user file paths, resolve them against the Us
28627
28674
  "WebSearch",
28628
28675
  "WebFetch"
28629
28676
  ],
28630
- outputFormat: { type: "json_schema", schema: jsonSchema },
28631
- // v0.6.6: Conditional agents - only for Anthropic Direct API
28632
- agents
28677
+ outputFormat: { type: "json_schema", schema: jsonSchema }
28678
+ // v0.6.9: No custom agents - using built-in general-purpose for workflow steps
28633
28679
  }
28634
28680
  });
28635
28681
  let finalResult;
@@ -28658,6 +28704,25 @@ When processing --file arguments or user file paths, resolve them against the Us
28658
28704
  error: { type: "unknown", message: "No result received" }
28659
28705
  };
28660
28706
  } catch (error2) {
28707
+ if (process.env.LOOPLIA_DEBUG === "true") {
28708
+ const debugInfo = {
28709
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
28710
+ errorType: error2 instanceof Error ? error2.constructor.name : typeof error2,
28711
+ errorMessage: error2 instanceof Error ? error2.message : String(error2),
28712
+ errorStack: error2 instanceof Error ? error2.stack : void 0,
28713
+ cwd: process.cwd(),
28714
+ loopliaHome: getLoopliaPluginPath(),
28715
+ env: {
28716
+ LOOPLIA_DEBUG: process.env.LOOPLIA_DEBUG,
28717
+ NODE_ENV: process.env.NODE_ENV,
28718
+ HOME: process.env.HOME
28719
+ }
28720
+ };
28721
+ console.error(
28722
+ "[LOOPLIA_DEBUG] SDK Error:",
28723
+ JSON.stringify(debugInfo, null, 2)
28724
+ );
28725
+ }
28661
28726
  return mapException(error2);
28662
28727
  }
28663
28728
  }
@@ -32614,11 +32679,11 @@ async function runConfigCommand(args) {
32614
32679
  }
32615
32680
 
32616
32681
  // src/commands/init.ts
32617
- import { dirname as dirname3, join as join7 } from "path";
32682
+ import { dirname as dirname4, join as join7 } from "path";
32618
32683
  import { createInterface as createInterface2 } from "readline";
32619
32684
  import { fileURLToPath as fileURLToPath3 } from "url";
32620
32685
  function getCliBundledPluginsPath() {
32621
- const currentFile = typeof __dirname !== "undefined" ? __dirname : dirname3(fileURLToPath3(import.meta.url));
32686
+ const currentFile = typeof __dirname !== "undefined" ? __dirname : dirname4(fileURLToPath3(import.meta.url));
32622
32687
  return join7(currentFile, "..", "plugins");
32623
32688
  }
32624
32689
  function printInitHelp() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@looplia/looplia-cli",
3
- "version": "0.6.8",
3
+ "version": "0.6.9",
4
4
  "description": "Looplia CLI - AI-powered workflow automation tool",
5
5
  "type": "module",
6
6
  "license": "Elastic-2.0",
@@ -30,7 +30,7 @@
30
30
  "scripts": {
31
31
  "build": "tsup",
32
32
  "dev": "tsup --watch",
33
- "start": "node dist/index.js",
33
+ "start": "node dist/cli.js",
34
34
  "test": "bun run build && bun test",
35
35
  "test:watch": "bun test --watch",
36
36
  "test:unit": "bun test commands/",
@@ -1,11 +1,6 @@
1
1
  {
2
2
  "$schema": "https://code.claude.com/schemas/hooks.json",
3
3
  "hooks": [
4
- {
5
- "event": "SessionStart",
6
- "command": "echo '🚀 Looplia session started'",
7
- "description": "Log session start"
8
- },
9
4
  {
10
5
  "event": "PostToolUse",
11
6
  "matcher": "Write",
@@ -76,6 +76,6 @@ LOCK_FILE="${VALIDATION_JSON}.lock"
76
76
  # Update validation.json to mark step as validated (v0.6.0 uses "steps")
77
77
  jq --arg art "$ARTIFACT" '.steps[$art].validated = true' "$VALIDATION_JSON" > "${VALIDATION_JSON}.tmp"
78
78
  mv "${VALIDATION_JSON}.tmp" "$VALIDATION_JSON"
79
- echo "✓ Validated: $ARTIFACT.json"
79
+ echo "✓ Validated: $ARTIFACT.json" >&2
80
80
 
81
81
  ) 200>"$LOCK_FILE"
@@ -6,14 +6,14 @@ description: |
6
6
  "execute this looplia pipeline", "/run writing-kit", "start the looplia automation", or
7
7
  "process these workflow steps".
8
8
 
9
- Architecture: One workflow step triggers one skill-executor subagent call, which then
10
- invokes multiple skills to accomplish the step's mission. Handles sandbox management,
11
- per-step skill-executor orchestration, and validation state tracking per v0.6.3.
9
+ Architecture: One workflow step triggers one general-purpose subagent call, which then
10
+ invokes skills to accomplish the step's mission. Each step = separate context window.
11
+ Handles sandbox management, per-step orchestration, and validation state tracking.
12
12
 
13
- v0.6.3: Named inputs (${{ inputs.name }}), input-less workflow support.
13
+ v0.6.9: Unified general-purpose subagent strategy for all providers (context offload).
14
14
  ---
15
15
 
16
- # Workflow Executor Skill (v0.6.3)
16
+ # Workflow Executor Skill (v0.6.9)
17
17
 
18
18
  Execute looplia workflows defined in `workflows/*.md` files using the skills-first architecture.
19
19
 
@@ -26,17 +26,17 @@ Use this skill when:
26
26
 
27
27
  ---
28
28
 
29
- ## CRITICAL: Universal Skill-Executor Invocation
29
+ ## CRITICAL: Task Invocation with general-purpose Subagent
30
30
 
31
- **v0.6.1 BREAKING CHANGE:** ALL workflow steps use `skill-executor` subagent.
31
+ **v0.6.9:** Using built-in `general-purpose` subagent for ALL workflow steps (all providers).
32
32
 
33
33
  When executing a step with `skill: {name}` and `mission:`:
34
34
 
35
35
  ```json
36
36
  {
37
- "subagent_type": "skill-executor",
37
+ "subagent_type": "general-purpose",
38
38
  "description": "Execute step: {step.id}",
39
- "prompt": "Execute skill '{step.skill}' for step '{step.id}'.\n\nMission: {step.mission}\n\nInput: {resolved input}\nOutput: {step.output}\nValidation: {step.validate}"
39
+ "prompt": "Execute skill '{step.skill}' for step '{step.id}'.\n\n## Mission\n{step.mission}\n\n## Execution Protocol\n1. Read input files (if provided)\n2. Invoke the skill using Skill tool\n3. Execute the mission with skill context\n4. Write JSON output to the specified path using Write tool\n\n## CRITICAL: Output Writing is MANDATORY\nYOU MUST CALL THE WRITE TOOL before completing. If you don't write the file, the workflow fails.\n\n## Rules\n- ALWAYS invoke the specified skill using Skill tool\n- ALWAYS write output to the exact path using Write tool\n- NEVER return results as text - always write JSON to output file\n- NEVER spawn Task subagents - execute skills directly\n- ALWAYS include contentId in JSON outputs\n\nInput: {resolved input path}\nOutput: {step.output}\nValidation: {step.validate JSON}"
40
40
  }
41
41
  ```
42
42
 
@@ -54,23 +54,22 @@ When executing a step with `skill: {name}` and `mission:`:
54
54
  **Task tool call:**
55
55
  ```json
56
56
  {
57
- "subagent_type": "skill-executor",
57
+ "subagent_type": "general-purpose",
58
58
  "description": "Execute step: analyze-content",
59
- "prompt": "Execute skill 'media-reviewer' for step 'analyze-content'.\n\nMission: Deep analysis of video transcript. Extract key themes, important quotes, and narrative structure.\n\nInput: sandbox/video-2025-01-15-abc123/inputs/content.md\nOutput: sandbox/video-2025-01-15-abc123/outputs/analysis.json\nValidation: {\"required_fields\":[\"contentId\",\"headline\",\"keyThemes\"]}"
59
+ "prompt": "Execute skill 'media-reviewer' for step 'analyze-content'.\n\n## Mission\nDeep analysis of video transcript. Extract key themes, important quotes, and narrative structure.\n\n## Execution Protocol\n1. Read input files (if provided)\n2. Invoke the skill using Skill tool\n3. Execute the mission with skill context\n4. Write JSON output to the specified path using Write tool\n\n## CRITICAL: Output Writing is MANDATORY\nYOU MUST CALL THE WRITE TOOL before completing. If you don't write the file, the workflow fails.\n\n## Rules\n- ALWAYS invoke the specified skill using Skill tool\n- ALWAYS write output to the exact path using Write tool\n- NEVER return results as text - always write JSON to output file\n- NEVER spawn Task subagents - execute skills directly\n- ALWAYS include contentId in JSON outputs\n\nInput: sandbox/video-2025-01-15-abc123/inputs/content.md\nOutput: sandbox/video-2025-01-15-abc123/outputs/analysis.json\nValidation: {\"required_fields\":[\"contentId\",\"headline\",\"keyThemes\"]}"
60
60
  }
61
61
  ```
62
62
 
63
63
  ### Rules
64
64
 
65
- - **ALWAYS** use `subagent_type: "skill-executor"` for ALL workflow steps
65
+ - **ALWAYS** use `subagent_type: "general-purpose"` for ALL workflow steps
66
66
  - **NEVER** use custom subagent_type per step (removed in v0.6.1)
67
- - **NEVER** use `subagent_type: "general-purpose"` for workflow steps
68
67
  - **VALIDATE** that step has both `skill:` and `mission:` fields
69
68
  - **REJECT** steps using deprecated `run:` syntax
70
69
 
71
70
  ### Why Per-Step Task Calls (Context Isolation)
72
71
 
73
- Each `Task(skill-executor)` creates a **separate context window**:
72
+ Each `Task(general-purpose)` creates a **separate context window**:
74
73
  - Isolates step processing from main agent context
75
74
  - Prevents context pollution across steps
76
75
  - Enables focused execution with only relevant inputs
@@ -249,7 +248,7 @@ Computed order: [analyze-content, generate-ideas, build-writing-kit]
249
248
  **Execute steps ONE AT A TIME (context isolation):**
250
249
 
251
250
  1. Get first unvalidated step from dependency order
252
- 2. Make ONE `Task(skill-executor)` call for THIS step only
251
+ 2. Make ONE `Task(general-purpose)` call for THIS step only
253
252
  3. WAIT for Task completion before proceeding
254
253
  4. Validate output, update validation.json
255
254
  5. REPEAT for next unvalidated step
@@ -271,10 +270,10 @@ FOR EACH step in dependency order:
271
270
  ┌─────────┐ ┌─────────────────────────────┐
272
271
  │ SKIP │ │ 1. INVOKE Task tool: │
273
272
  │ (done) │ │ subagent_type: │
274
- └─────────┘ │ "skill-executor"
273
+ └─────────┘ │ "general-purpose"
275
274
  │ │
276
- │ 2. skill-executor invokes
277
- the specified skill
275
+ │ 2. Subagent invokes the
276
+ │ specified skill
278
277
  │ │
279
278
  │ 3. VALIDATE output │
280
279
  │ │
@@ -302,9 +301,9 @@ For step:
302
301
  Invoke Task tool:
303
302
  ```json
304
303
  {
305
- "subagent_type": "skill-executor",
304
+ "subagent_type": "general-purpose",
306
305
  "description": "Execute step: analyze-content",
307
- "prompt": "Execute skill 'media-reviewer' for step 'analyze-content'.\n\nMission: Deep analysis of video transcript. Extract key themes, important quotes with timestamps, and narrative structure.\n\nInput: sandbox/article-2025-12-18-xk7m/inputs/content.md\nOutput: sandbox/article-2025-12-18-xk7m/outputs/analysis.json\nValidation: {\"required_fields\":[\"contentId\",\"headline\",\"keyThemes\"]}"
306
+ "prompt": "Execute skill 'media-reviewer' for step 'analyze-content'.\n\n## Mission\nDeep analysis of video transcript. Extract key themes, important quotes with timestamps, and narrative structure.\n\n## Execution Protocol\n1. Read input files (if provided)\n2. Invoke the skill using Skill tool\n3. Execute the mission with skill context\n4. Write JSON output to the specified path using Write tool\n\n## CRITICAL: Output Writing is MANDATORY\nYOU MUST CALL THE WRITE TOOL before completing.\n\n## Rules\n- ALWAYS invoke the specified skill using Skill tool\n- ALWAYS write output to the exact path using Write tool\n- NEVER return results as text - always write JSON to output file\n- ALWAYS include contentId in JSON outputs\n\nInput: sandbox/article-2025-12-18-xk7m/inputs/content.md\nOutput: sandbox/article-2025-12-18-xk7m/outputs/analysis.json\nValidation: {\"required_fields\":[\"contentId\",\"headline\",\"keyThemes\"]}"
308
307
  }
309
308
  ```
310
309
 
@@ -350,9 +349,9 @@ When step with `final: true` passes validation:
350
349
 
351
350
  ---
352
351
 
353
- ## Variable Substitution (v0.6.3)
352
+ ## Variable Substitution (v0.6.9)
354
353
 
355
- Resolve variables before passing to skill-executor:
354
+ Resolve variables before passing to general-purpose subagent:
356
355
 
357
356
  | Variable | Resolution | Example |
358
357
  |----------|------------|---------|
@@ -435,21 +434,21 @@ input: ${{ steps.analyze-content.output }}
435
434
  4. [ORDER] Computed: [analyze-content, generate-ideas, build-writing-kit]
436
435
 
437
436
  5. [STEP] analyze-content
438
- - Task tool: subagent_type="skill-executor"
437
+ - Task tool: subagent_type="general-purpose"
439
438
  - Skill: media-reviewer
440
439
  - Output: outputs/analysis.json
441
440
  - Validate: PASSED
442
441
  - Update: validation.json (analyze-content.validated = true)
443
442
 
444
443
  6. [STEP] generate-ideas
445
- - Task tool: subagent_type="skill-executor"
444
+ - Task tool: subagent_type="general-purpose"
446
445
  - Skill: idea-synthesis
447
446
  - Output: outputs/ideas.json
448
447
  - Validate: PASSED
449
448
  - Update: validation.json (generate-ideas.validated = true)
450
449
 
451
450
  7. [STEP] build-writing-kit
452
- - Task tool: subagent_type="skill-executor"
451
+ - Task tool: subagent_type="general-purpose"
453
452
  - Skill: writing-kit-assembler
454
453
  - Output: outputs/writing-kit.json
455
454
  - Validate: PASSED
@@ -463,7 +462,7 @@ input: ${{ steps.analyze-content.output }}
463
462
  ## File References
464
463
 
465
464
  - Workflow definitions: `workflows/*.md`
466
- - Skill-executor: Inline subagent defined in CLI (see query-executor.ts)
465
+ - Subagent: Built-in `general-purpose` agent (v0.6.9)
467
466
  - Skill definitions: `plugins/*/skills/*/SKILL.md`
468
467
  - Sandbox storage: `sandbox/{sandbox-id}/`
469
468
  - Validator script: `.claude/skills/workflow-validator/scripts/validate.ts`