@looplia/looplia-cli 0.7.3 → 0.7.5

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.
@@ -8,8 +8,10 @@ import {
8
8
  applyPreset,
9
9
  buildSummarizePrompt,
10
10
  clearClaudeCodePathCache,
11
+ createBuildHooks,
11
12
  createClaudeAgentExecutor,
12
13
  createQueryLogger,
14
+ createWorkflowHooks,
13
15
  ensureWorkspace,
14
16
  executeAgenticQueryStreaming,
15
17
  executeInteractiveQueryStreaming,
@@ -31,7 +33,7 @@ import {
31
33
  validateConfig,
32
34
  writeLoopliaSettings,
33
35
  writeUserProfile
34
- } from "./chunk-MHR5TPHE.js";
36
+ } from "./chunk-GIZRTNY3.js";
35
37
  import "./chunk-VRBGWKZ6.js";
36
38
  import "./chunk-Y55L47HC.js";
37
39
  export {
@@ -42,8 +44,10 @@ export {
42
44
  applyPreset,
43
45
  buildSummarizePrompt,
44
46
  clearClaudeCodePathCache,
47
+ createBuildHooks,
45
48
  createClaudeAgentExecutor,
46
49
  createQueryLogger,
50
+ createWorkflowHooks,
47
51
  ensureWorkspace,
48
52
  executeAgenticQueryStreaming,
49
53
  executeInteractiveQueryStreaming,
package/dist/cli.js CHANGED
@@ -1,18 +1,14 @@
1
1
  #!/usr/bin/env bun
2
2
  import {
3
3
  ensureWorkflowSkills,
4
- extractWorkflowSkills,
5
4
  findSkill,
6
5
  getAvailableSkills,
7
6
  getInstalledSkills,
8
7
  installSkill,
9
- isInputlessWorkflow,
10
8
  loadCompiledRegistry,
11
- parseWorkflow,
12
9
  removeSkill,
13
- updateSkill,
14
- validateUserProfile
15
- } from "./chunk-VYGRYFSY.js";
10
+ updateSkill
11
+ } from "./chunk-4TKNQ5RW.js";
16
12
  import "./chunk-QQGRKUSM.js";
17
13
  import {
18
14
  addSource,
@@ -28,21 +24,29 @@ import {
28
24
  PRESETS,
29
25
  applyPreset,
30
26
  copyPlugins,
27
+ createBuildHooks,
31
28
  createClaudeAgentExecutor,
29
+ createWorkflowHooks,
32
30
  downloadRemotePlugins,
33
31
  ensureWorkspace,
32
+ extractWorkflowSkills,
33
+ generateValidationManifest,
34
34
  getConfigPath,
35
+ getFinalStep,
35
36
  getLoopliaPluginPath,
36
37
  getSettingsDisplayInfo,
37
38
  initializeCommandEnvironment,
39
+ isInputlessWorkflow,
38
40
  isLoopliaInitialized,
39
41
  maskAuthToken,
42
+ parseWorkflow,
40
43
  readLoopliaSettings,
41
44
  readUserProfile,
42
45
  removeLoopliaSettings,
46
+ validateUserProfile,
43
47
  writeLoopliaSettings,
44
48
  writeUserProfile
45
- } from "./chunk-MHR5TPHE.js";
49
+ } from "./chunk-GIZRTNY3.js";
46
50
  import "./chunk-VRBGWKZ6.js";
47
51
  import {
48
52
  copyOutputsToDestination,
@@ -24968,9 +24972,9 @@ init_esm_shims();
24968
24972
 
24969
24973
  // src/commands/build.ts
24970
24974
  init_esm_shims();
24971
- import { existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
24975
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
24972
24976
  import { homedir as homedir2 } from "os";
24973
- import { resolve } from "path";
24977
+ import { join as join2, resolve } from "path";
24974
24978
 
24975
24979
  // src/components/index.ts
24976
24980
  init_esm_shims();
@@ -32868,7 +32872,7 @@ async function* analyzeDescriptionStreaming(description, workspace, questionCall
32868
32872
  const { createSandboxDirectories: createSandboxDirectories2, generateSandboxId: generateSandboxId2 } = await import("./sandbox-XVMNWAJO.js");
32869
32873
  const sandboxId = generateSandboxId2("build");
32870
32874
  createSandboxDirectories2(workspace, sandboxId);
32871
- const { executeInteractiveQueryStreaming } = await import("./claude-agent-sdk-SQ6YU4VE.js");
32875
+ const { executeInteractiveQueryStreaming } = await import("./claude-agent-sdk-W5MXMV4Q.js");
32872
32876
  const prompt = `${buildAnalysisPrompt(description)} --sandbox-id ${sandboxId}`;
32873
32877
  const generator = executeInteractiveQueryStreaming(
32874
32878
  prompt,
@@ -34115,9 +34119,13 @@ async function executeBatch(prompt, workspace, executor) {
34115
34119
  console.error("\u23F3 Building workflow...");
34116
34120
  const { createSandboxDirectories: createSandboxDirectories2, generateSandboxId: generateSandboxId2 } = await import("./sandbox-XVMNWAJO.js");
34117
34121
  const sandboxId = generateSandboxId2("build");
34122
+ const sandboxDir = join2(workspace, "sandbox", sandboxId);
34118
34123
  createSandboxDirectories2(workspace, sandboxId);
34124
+ createBuildValidationJson(sandboxDir, sandboxId, "untitled");
34125
+ process.env.LOOPLIA_SANDBOX_ID = sandboxId;
34126
+ process.env.LOOPLIA_SANDBOX_ROOT = join2(workspace, "sandbox");
34119
34127
  const promptWithSandbox = `${prompt} --sandbox-id ${sandboxId}`;
34120
- const exec2 = executor ?? createClaudeAgentExecutor({ workspace });
34128
+ const exec2 = executor ?? createClaudeAgentExecutor({ workspace, buildHooks: createBuildHooks() });
34121
34129
  const result = await exec2.executePrompt(promptWithSandbox, {
34122
34130
  workspace,
34123
34131
  contentId: sandboxId
@@ -34125,17 +34133,65 @@ async function executeBatch(prompt, workspace, executor) {
34125
34133
  if (result.success && result.data) {
34126
34134
  return result.data;
34127
34135
  }
34136
+ if (result.success && !result.data) {
34137
+ const validation = readBuildValidationSync(sandboxDir);
34138
+ if (validation?.workflowValidated && validation.workflowPath) {
34139
+ return {
34140
+ status: "success",
34141
+ workflowPath: validation.workflowPath,
34142
+ workflowName: validation.workflowName ?? void 0
34143
+ };
34144
+ }
34145
+ }
34128
34146
  return {
34129
34147
  status: "error",
34130
34148
  error: result.error?.message ?? "Unknown error"
34131
34149
  };
34132
34150
  }
34151
+ function createBuildValidationJson(sandboxDir, sandboxId, workflowName) {
34152
+ const validation = {
34153
+ type: "build",
34154
+ workflow: workflowName,
34155
+ version: "1.0.0",
34156
+ sandboxId,
34157
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
34158
+ status: "building",
34159
+ workflowValidated: false,
34160
+ workflowPath: null,
34161
+ workflowName: null
34162
+ };
34163
+ writeFileSync2(
34164
+ join2(sandboxDir, "validation.json"),
34165
+ JSON.stringify(validation, null, 2),
34166
+ "utf-8"
34167
+ );
34168
+ }
34169
+ function readBuildValidationSync(sandboxDir) {
34170
+ try {
34171
+ const { readFileSync: readFileSync3 } = __require("fs");
34172
+ const content = readFileSync3(
34173
+ join2(sandboxDir, "validation.json"),
34174
+ "utf-8"
34175
+ );
34176
+ const manifest = JSON.parse(content);
34177
+ if (manifest.type === "build") {
34178
+ return manifest;
34179
+ }
34180
+ return;
34181
+ } catch {
34182
+ return;
34183
+ }
34184
+ }
34133
34185
  async function* executeInteractiveStreamingBatch(prompt, workspace, questionCallback) {
34134
34186
  const { createSandboxDirectories: createSandboxDirectories2, generateSandboxId: generateSandboxId2 } = await import("./sandbox-XVMNWAJO.js");
34135
34187
  const sandboxId = generateSandboxId2("build");
34188
+ const sandboxDir = join2(workspace, "sandbox", sandboxId);
34136
34189
  createSandboxDirectories2(workspace, sandboxId);
34190
+ createBuildValidationJson(sandboxDir, sandboxId, "untitled");
34191
+ process.env.LOOPLIA_SANDBOX_ID = sandboxId;
34192
+ process.env.LOOPLIA_SANDBOX_ROOT = join2(workspace, "sandbox");
34137
34193
  const promptWithSandbox = `${prompt} --sandbox-id ${sandboxId}`;
34138
- const { executeInteractiveQueryStreaming } = await import("./claude-agent-sdk-SQ6YU4VE.js");
34194
+ const { executeInteractiveQueryStreaming } = await import("./claude-agent-sdk-W5MXMV4Q.js");
34139
34195
  const schema = {
34140
34196
  type: "object",
34141
34197
  properties: {
@@ -34149,7 +34205,7 @@ async function* executeInteractiveStreamingBatch(prompt, workspace, questionCall
34149
34205
  const generator = executeInteractiveQueryStreaming(
34150
34206
  promptWithSandbox,
34151
34207
  schema,
34152
- { workspace },
34208
+ { workspace, buildHooks: createBuildHooks() },
34153
34209
  questionCallback
34154
34210
  );
34155
34211
  let iterResult = await generator.next();
@@ -34158,6 +34214,19 @@ async function* executeInteractiveStreamingBatch(prompt, workspace, questionCall
34158
34214
  iterResult = await generator.next();
34159
34215
  }
34160
34216
  const executorResult = iterResult.value;
34217
+ if (executorResult.success && !executorResult.data) {
34218
+ const validation = readBuildValidationSync(sandboxDir);
34219
+ if (validation?.workflowValidated && validation.workflowPath) {
34220
+ return {
34221
+ success: true,
34222
+ data: {
34223
+ status: "success",
34224
+ workflowPath: validation.workflowPath,
34225
+ workflowName: validation.workflowName ?? void 0
34226
+ }
34227
+ };
34228
+ }
34229
+ }
34161
34230
  if (executorResult.success) {
34162
34231
  return {
34163
34232
  success: true,
@@ -34456,8 +34525,12 @@ Usage:
34456
34525
  Available presets:
34457
34526
  ANTHROPIC_CLAUDE_HAIKU Anthropic Claude Haiku (default)
34458
34527
  ANTHROPIC_CLAUDE_SONNET Anthropic Claude Sonnet
34528
+ CLAUDE_CODE_SUBSCRIPTION_HAIKU Claude Haiku via subscription (macOS)
34529
+ CLAUDE_CODE_SUBSCRIPTION_SONNET Claude Sonnet via subscription (macOS)
34530
+ CLAUDE_CODE_SUBSCRIPTION_OPUS Claude Opus via subscription (macOS)
34459
34531
  ZENMUX_ANTHROPIC_HAIKU45 ZenMux Claude Haiku 4.5
34460
34532
  ZENMUX_ZAI_GLM47 ZenMux GLM-4.7
34533
+ ZENMUX_ZAI_GLM47FLASHX ZenMux GLM-4.7-FlashX
34461
34534
  ZENMUX_ZAI_GLM46VFLASH ZenMux GLM-4.6v-Flash
34462
34535
  ZENMUX_MINIMAX_M21 ZenMux MiniMax-M2.1
34463
34536
  ZENMUX_GOOGLE_GEMINI3FLASH ZenMux Gemini-3-Flash
@@ -34466,10 +34539,14 @@ Available presets:
34466
34539
  ZENMUX_XAI_GROK41FAST ZenMux Grok-4.1-Fast
34467
34540
  ZENMUX_DEEPSEEK_V32 ZenMux DeepSeek-v3.2
34468
34541
  ZENMUX_MISTRAL_LARGE2512 ZenMux Mistral-Large-2512
34542
+ OPENROUTER_PRESET OpenRouter (user-configured preset)
34543
+ OPENROUTER_ZAI_GLM47FLASH OpenRouter GLM-4.7-Flash
34544
+ OLLAMA_GLM47_CLOUD Ollama GLM-4.7 Cloud
34545
+ OLLAMA_MINIMAX_M21_CLOUD Ollama MiniMax-M2.1 Cloud
34469
34546
 
34470
34547
  Configuration keys for 'set':
34471
- api-provider Provider type: anthropic, zenmux, custom
34472
- base-url API base URL (for zenmux/custom)
34548
+ api-provider Provider type: anthropic, zenmux, openrouter, ollama, custom
34549
+ base-url API base URL (for zenmux/openrouter/ollama/custom)
34473
34550
  auth-token Authentication token (fallback if env var not set)
34474
34551
  main-model Model for main agent
34475
34552
  executor-model Model for skill executor
@@ -34477,9 +34554,13 @@ Configuration keys for 'set':
34477
34554
  API keys (set in .env - looplia auto-maps based on provider):
34478
34555
  ANTHROPIC_API_KEY For Anthropic (direct)
34479
34556
  ZENMUX_API_KEY For ZenMux (auto-mapped to ANTHROPIC_API_KEY)
34557
+ OPENROUTER_API_KEY For OpenRouter (auto-mapped to ANTHROPIC_AUTH_TOKEN)
34558
+ OLLAMA_API_KEY For Ollama (optional, defaults to "ollama")
34480
34559
 
34481
34560
  Examples:
34482
34561
  looplia config provider preset ZENMUX_ZAI_GLM47
34562
+ looplia config provider preset OPENROUTER_PRESET
34563
+ looplia config provider preset OLLAMA_GLM47_CLOUD
34483
34564
  looplia config provider show
34484
34565
  `);
34485
34566
  }
@@ -34605,7 +34686,9 @@ async function showProviderConfig() {
34605
34686
  console.log(` Preset: ${info.preset}`);
34606
34687
  }
34607
34688
  console.log(` Provider: ${info.provider}`);
34608
- if (info.authToken) {
34689
+ if (info.authTokenSource === "subscription") {
34690
+ console.log(" Auth Source: Claude Code Subscription (OAuth)");
34691
+ } else if (info.authToken) {
34609
34692
  console.log(` Auth Token: ${maskAuthToken(info.authToken)}`);
34610
34693
  }
34611
34694
  console.log("\n Agent Models:");
@@ -34772,7 +34855,7 @@ async function runConfigCommand(args) {
34772
34855
 
34773
34856
  // src/commands/init.ts
34774
34857
  init_esm_shims();
34775
- import { dirname, join as join2 } from "path";
34858
+ import { dirname, join as join3 } from "path";
34776
34859
  import { createInterface } from "readline";
34777
34860
  import { fileURLToPath } from "url";
34778
34861
 
@@ -34782,7 +34865,7 @@ init_esm_shims();
34782
34865
  // src/commands/init.ts
34783
34866
  function getCliBundledPluginsPath() {
34784
34867
  const currentFile = typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath(import.meta.url));
34785
- return join2(currentFile, "..", "plugins");
34868
+ return join3(currentFile, "..", "plugins");
34786
34869
  }
34787
34870
  function printInitHelp() {
34788
34871
  console.log(`
@@ -35092,10 +35175,10 @@ import {
35092
35175
  existsSync as existsSync4,
35093
35176
  mkdirSync as mkdirSync3,
35094
35177
  readFileSync as readFileSync2,
35095
- writeFileSync as writeFileSync2
35178
+ writeFileSync as writeFileSync3
35096
35179
  } from "fs";
35097
35180
  import { homedir as homedir3 } from "os";
35098
- import { basename, join as join3, resolve as resolve2 } from "path";
35181
+ import { basename, join as join4, resolve as resolve2 } from "path";
35099
35182
  var RUN_COMMAND = COMMANDS.RUN;
35100
35183
  function generateSandboxIdFromFile(filePath) {
35101
35184
  const filename = basename(filePath, ".md");
@@ -35112,8 +35195,8 @@ function createInitialValidationJson(sandboxDir, sandboxId, workflowId) {
35112
35195
  status: "pending",
35113
35196
  steps: {}
35114
35197
  };
35115
- writeFileSync2(
35116
- join3(sandboxDir, "validation.json"),
35198
+ writeFileSync3(
35199
+ join4(sandboxDir, "validation.json"),
35117
35200
  JSON.stringify(validation, null, 2),
35118
35201
  "utf-8"
35119
35202
  );
@@ -35125,7 +35208,7 @@ function createSandbox(workspace, filePath, workflowId) {
35125
35208
  const absolutePath = resolve2(filePath);
35126
35209
  copyFileSync(
35127
35210
  absolutePath,
35128
- join3(sandboxDir, "inputs", SANDBOX_CONTENT_FILENAME)
35211
+ join4(sandboxDir, "inputs", SANDBOX_CONTENT_FILENAME)
35129
35212
  );
35130
35213
  createInitialValidationJson(sandboxDir, sandboxId, workflowId);
35131
35214
  } catch (error) {
@@ -35143,8 +35226,8 @@ function createSandboxWithInputs(workspace, workflowId, inputs) {
35143
35226
  const sandboxDir = createSandboxDirectories(workspace, sandboxId);
35144
35227
  for (const [name, parsedInput] of Object.entries(inputs)) {
35145
35228
  if (parsedInput.type === "json") {
35146
- writeFileSync2(
35147
- join3(sandboxDir, "inputs", `${name}.json`),
35229
+ writeFileSync3(
35230
+ join4(sandboxDir, "inputs", `${name}.json`),
35148
35231
  parsedInput.value,
35149
35232
  "utf-8"
35150
35233
  );
@@ -35153,7 +35236,7 @@ function createSandboxWithInputs(workspace, workflowId, inputs) {
35153
35236
  if (!existsSync4(absolutePath)) {
35154
35237
  throw new Error(`Input file not found: ${parsedInput.value}`);
35155
35238
  }
35156
- copyFileSync(absolutePath, join3(sandboxDir, "inputs", `${name}.md`));
35239
+ copyFileSync(absolutePath, join4(sandboxDir, "inputs", `${name}.md`));
35157
35240
  }
35158
35241
  }
35159
35242
  createInitialValidationJson(sandboxDir, sandboxId, workflowId);
@@ -35326,7 +35409,7 @@ function ensureWorkspace3(mock) {
35326
35409
  const workspace = getWorkspacePath2();
35327
35410
  if (!existsSync4(workspace)) {
35328
35411
  if (mock) {
35329
- mkdirSync3(join3(workspace, "sandbox"), { recursive: true });
35412
+ mkdirSync3(join4(workspace, "sandbox"), { recursive: true });
35330
35413
  } else {
35331
35414
  console.error("Workspace not initialized. Run: looplia init");
35332
35415
  process.exit(1);
@@ -35338,7 +35421,7 @@ function buildRunPrompt(workflowId, sandboxId) {
35338
35421
  return `${RUN_COMMAND} ${workflowId} --sandbox-id ${sandboxId}`;
35339
35422
  }
35340
35423
  function parseWorkflowFile(workspace, workflowId) {
35341
- const workflowPath = join3(workspace, "workflows", `${workflowId}.md`);
35424
+ const workflowPath = join4(workspace, "workflows", `${workflowId}.md`);
35342
35425
  if (!existsSync4(workflowPath)) {
35343
35426
  return null;
35344
35427
  }
@@ -35366,7 +35449,10 @@ function executeMock2(args) {
35366
35449
  }
35367
35450
  async function executeStreaming(prompt, workspace, workflowId, requiredSkills) {
35368
35451
  const contentId = crypto.randomUUID();
35369
- const executor = createClaudeAgentExecutor({ workspace });
35452
+ const executor = createClaudeAgentExecutor({
35453
+ workspace,
35454
+ runHooks: createWorkflowHooks()
35455
+ });
35370
35456
  const generator = executor.executePromptStreaming(prompt, {
35371
35457
  workspace,
35372
35458
  contentId,
@@ -35394,14 +35480,21 @@ async function executeStreaming(prompt, workspace, workflowId, requiredSkills) {
35394
35480
  async function executeBatch2(prompt, workspace, workflowId, requiredSkills) {
35395
35481
  console.error("\u23F3 Processing...");
35396
35482
  const contentId = crypto.randomUUID();
35397
- const executor = createClaudeAgentExecutor({ workspace });
35483
+ const executor = createClaudeAgentExecutor({
35484
+ workspace,
35485
+ runHooks: createWorkflowHooks()
35486
+ });
35398
35487
  const result = await executor.executePrompt(prompt, {
35399
35488
  workspace,
35400
35489
  contentId,
35401
35490
  requiredSkills
35402
35491
  });
35403
- if (result.success && result.data) {
35404
- return result.data;
35492
+ if (result.success) {
35493
+ return result.data ?? {
35494
+ status: "success",
35495
+ workflowId,
35496
+ sessionId: result.sessionId
35497
+ };
35405
35498
  }
35406
35499
  return {
35407
35500
  status: "error",
@@ -35411,7 +35504,7 @@ async function executeBatch2(prompt, workspace, workflowId, requiredSkills) {
35411
35504
  }
35412
35505
  function resolveSandboxId(workspace, parsed, allowInputless) {
35413
35506
  if (parsed.sandboxId) {
35414
- const sandboxDir = join3(workspace, "sandbox", parsed.sandboxId);
35507
+ const sandboxDir = join4(workspace, "sandbox", parsed.sandboxId);
35415
35508
  if (!existsSync4(sandboxDir)) {
35416
35509
  console.error(`Error: Sandbox not found: ${parsed.sandboxId}`);
35417
35510
  console.error(`Path: ${sandboxDir}`);
@@ -35508,6 +35601,27 @@ async function handleJitInstallation(workflowInfo) {
35508
35601
  return true;
35509
35602
  }
35510
35603
  }
35604
+ function populateValidationManifest(workspace, sandboxId, workflowId, workflowInfo) {
35605
+ if (!workflowInfo?.parsed?.definition) {
35606
+ return;
35607
+ }
35608
+ const manifest = generateValidationManifest(workflowInfo.parsed.definition);
35609
+ const finalStepId = getFinalStep(workflowInfo.parsed.definition);
35610
+ const sandboxDir = join4(workspace, "sandbox", sandboxId);
35611
+ const validationPath = join4(sandboxDir, "validation.json");
35612
+ if (!existsSync4(validationPath)) {
35613
+ createInitialValidationJson(sandboxDir, sandboxId, workflowId);
35614
+ }
35615
+ if (!existsSync4(validationPath)) {
35616
+ return;
35617
+ }
35618
+ const existing = JSON.parse(
35619
+ readFileSync2(validationPath, "utf-8")
35620
+ );
35621
+ existing.steps = manifest.steps;
35622
+ existing.finalStepId = finalStepId;
35623
+ writeFileSync3(validationPath, JSON.stringify(existing, null, 2), "utf-8");
35624
+ }
35511
35625
  async function runRunCommand(args) {
35512
35626
  const parsed = parseArgs3(args);
35513
35627
  if (parsed.help) {
@@ -35524,6 +35638,14 @@ async function runRunCommand(args) {
35524
35638
  const workflowInfo = parseWorkflowFile(workspace, parsed.workflowId);
35525
35639
  const allowInputless = workflowInfo?.isInputless ?? false;
35526
35640
  const sandboxId = resolveSandboxId(workspace, parsed, allowInputless);
35641
+ process.env.LOOPLIA_SANDBOX_ID = sandboxId;
35642
+ process.env.LOOPLIA_SANDBOX_ROOT = join4(workspace, "sandbox");
35643
+ populateValidationManifest(
35644
+ workspace,
35645
+ sandboxId,
35646
+ parsed.workflowId,
35647
+ workflowInfo
35648
+ );
35527
35649
  if (!(parsed.mock || await handleJitInstallation(workflowInfo))) {
35528
35650
  process.exit(1);
35529
35651
  }
@@ -35622,7 +35744,7 @@ async function skillAdd(nameOrUrl, from) {
35622
35744
  }
35623
35745
  if (GITHUB_URL_PATTERN.test(nameOrUrl)) {
35624
35746
  console.log(`Installing skill from URL: ${nameOrUrl}...`);
35625
- const { installSkillFromUrl } = await import("./dist-PMEIK6PJ.js");
35747
+ const { installSkillFromUrl } = await import("./dist-3XSIQAV3.js");
35626
35748
  const result2 = await installSkillFromUrl(nameOrUrl, true);
35627
35749
  switch (result2.status) {
35628
35750
  case "installed":
@@ -35859,7 +35981,7 @@ async function runSkillCommand(args) {
35859
35981
  }
35860
35982
 
35861
35983
  // src/index.ts
35862
- var VERSION = "0.7.3";
35984
+ var VERSION = "0.7.5";
35863
35985
  function printHelp5() {
35864
35986
  console.log(`
35865
35987
  looplia - Content intelligence CLI (v${VERSION})
@@ -11,7 +11,7 @@ import {
11
11
  loadCompiledRegistry,
12
12
  removeSkill,
13
13
  updateSkill
14
- } from "./chunk-VYGRYFSY.js";
14
+ } from "./chunk-4TKNQ5RW.js";
15
15
  import {
16
16
  syncRegistrySources,
17
17
  syncSource
@@ -32,7 +32,7 @@ import {
32
32
  CORE_SKILLS,
33
33
  ensureWorkspace,
34
34
  isCoreSkill
35
- } from "./chunk-MHR5TPHE.js";
35
+ } from "./chunk-GIZRTNY3.js";
36
36
  import "./chunk-VRBGWKZ6.js";
37
37
  import "./chunk-Y55L47HC.js";
38
38
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@looplia/looplia-cli",
3
- "version": "0.7.3",
3
+ "version": "0.7.5",
4
4
  "description": "Looplia CLI - AI-powered workflow automation tool",
5
5
  "type": "module",
6
6
  "license": "Elastic-2.0",
@@ -26,6 +26,29 @@ Use this skill when:
26
26
 
27
27
  ---
28
28
 
29
+ ## ⚠️ CRITICAL EXECUTION MODEL - READ FIRST
30
+
31
+ **YOU (the model reading this skill) must execute the step loop directly. DO NOT delegate.**
32
+
33
+ ```
34
+ ┌─────────────────────────────────────────────────────────────────────┐
35
+ │ YOU (main agent) iterate through steps, making ONE Task call each │
36
+ │ │
37
+ │ FOR step IN workflow.steps: │
38
+ │ 1. Call Task(general-purpose) for THIS STEP ONLY │
39
+ │ 2. WAIT for Task to complete │
40
+ │ 3. Validate output │
41
+ │ 4. THEN move to next step │
42
+ │ │
43
+ │ ❌ WRONG: Task("Execute all workflow steps...") │
44
+ │ ✅ RIGHT: Task("Execute step: summary"), Task("Execute step: ideas")│
45
+ └─────────────────────────────────────────────────────────────────────┘
46
+ ```
47
+
48
+ **3 steps = 3 Task calls. You MUST make 3 separate Task tool invocations.**
49
+
50
+ ---
51
+
29
52
  ## CRITICAL: Task Invocation with general-purpose Subagent
30
53
 
31
54
  **v0.6.9:** Using built-in `general-purpose` subagent for ALL workflow steps (all providers).
@@ -76,25 +99,37 @@ Each `Task(general-purpose)` creates a **separate context window**:
76
99
 
77
100
  **NEVER batch multiple steps** - this defeats context isolation.
78
101
 
79
- ### Anti-Patterns
102
+ ### Anti-Patterns (VIOLATIONS = TEST FAILURE)
80
103
 
81
- ❌ **WRONG - Delegating entire workflow:**
104
+ ❌ **FATAL ERROR - Delegating entire workflow to one Task:**
82
105
  ```json
83
106
  {
84
107
  "description": "Execute workflow: writing-kit",
85
108
  "prompt": "Run all workflow steps..."
86
109
  }
87
110
  ```
88
- This pollutes the subagent context with ALL steps.
111
+ **This is WRONG.** You made 1 Task call. Tests expect 3. TEST WILL FAIL.
89
112
 
90
- **CORRECT - One step per Task:**
91
- ```json
92
- {
93
- "description": "Execute step: summary",
94
- "prompt": "Execute skill 'media-reviewer' for step 'summary'..."
95
- }
113
+ **FATAL ERROR - Executing skills inline without Task:**
96
114
  ```
97
- Each step gets a fresh, focused context window.
115
+ Skill("media-reviewer") // NO! You must use Task wrapper
116
+ Skill("idea-synthesis") // NO! You must use Task wrapper
117
+ ```
118
+ **This is WRONG.** Each step MUST be wrapped in a Task call.
119
+
120
+ ✅ **CORRECT - One Task call per step (3 steps = 3 Task calls):**
121
+ ```
122
+ Task("Execute step: summary") // Task #1
123
+ → Subagent invokes Skill("media-reviewer")
124
+
125
+ Task("Execute step: ideas") // Task #2
126
+ → Subagent invokes Skill("idea-synthesis")
127
+
128
+ Task("Execute step: writing-kit") // Task #3
129
+ → Subagent invokes Skill("writing-kit-assembler")
130
+ ```
131
+
132
+ **Verification**: Count your Task tool calls. If workflow has 3 steps, you MUST have 3 Task calls.
98
133
 
99
134
  ---
100
135
 
@@ -243,18 +278,38 @@ Input:
243
278
  Computed order: [analyze-content, generate-ideas, build-writing-kit]
244
279
  ```
245
280
 
246
- ### Phase 5: Step Execution Loop
281
+ ### Phase 5: Step Execution Loop (YOU MUST DO THIS)
282
+
283
+ **YOU execute this loop. DO NOT delegate the loop to a subagent.**
247
284
 
248
- **Execute steps ONE AT A TIME (context isolation):**
285
+ ```
286
+ YOU (main agent) must:
287
+ ┌────────────────────────────────────────────────────────────────┐
288
+ │ for (const step of steps) { │
289
+ │ // 1. YOU call Task tool │
290
+ │ await Task({ │
291
+ │ subagent_type: "general-purpose", │
292
+ │ description: `Execute step: ${step.id}`, │
293
+ │ prompt: `Execute skill '${step.skill}' for step...` │
294
+ │ }); │
295
+ │ │
296
+ │ // 2. YOU wait for Task to complete │
297
+ │ // 3. YOU validate output │
298
+ │ // 4. YOU update validation.json │
299
+ │ // 5. YOU move to next step │
300
+ │ } │
301
+ └────────────────────────────────────────────────────────────────┘
302
+ ```
249
303
 
304
+ **Execution checklist:**
250
305
  1. Get first unvalidated step from dependency order
251
- 2. Make ONE `Task(general-purpose)` call for THIS step only
252
- 3. WAIT for Task completion before proceeding
253
- 4. Validate output, update validation.json
254
- 5. REPEAT for next unvalidated step
255
- 6. STOP when ALL steps are validated
306
+ 2. **YOU** make ONE `Task(general-purpose)` call for THIS step only
307
+ 3. **YOU** WAIT for Task completion before proceeding
308
+ 4. **YOU** validate output, update validation.json
309
+ 5. **YOU** REPEAT for next unvalidated step
310
+ 6. **YOU** STOP when ALL steps are validated
256
311
 
257
- **MANDATORY:** Each step = separate context window = separate Task call.
312
+ **MANDATORY:** 3 steps = 3 Task calls. Count them. If you made fewer, you did it wrong.
258
313
 
259
314
  ```
260
315
  FOR EACH step in dependency order:
@@ -39,9 +39,7 @@ steps:
39
39
  Include meta information (difficulty, time to write, audience).
40
40
  Calculate relevance scores based on user profile.
41
41
  needs: [summary, ideas]
42
- input:
43
- - ${{ steps.summary.output }}
44
- - ${{ steps.ideas.output }}
42
+ input: ["${{ steps.summary.output }}", "${{ steps.ideas.output }}"]
45
43
  output: ${{ sandbox }}/outputs/writing-kit.json
46
44
  final: true
47
45
  validate: