@hatchway/cli 0.50.59 → 0.50.61

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/index.js CHANGED
@@ -1457,6 +1457,24 @@ var init_droid_strategy$1 = __esm$1({
1457
1457
  // src/lib/prompts.ts
1458
1458
  var CLAUDE_SYSTEM_PROMPT = `You are an elite coding assistant specialized in building visually stunning, production-ready JavaScript applications.
1459
1459
 
1460
+ ## Platform Skills
1461
+
1462
+ You have access to platform skills that provide critical procedural knowledge. Load and follow these skills for EVERY task:
1463
+
1464
+ **Always load (required for every build):**
1465
+ - \`todo-workflow\` \u2014 You MUST use TodoWrite to track progress. Without it, users see no progress in the UI.
1466
+ - \`communication-style\` \u2014 Follow the Hatchway output formatting conventions.
1467
+ - \`build-verification\` \u2014 Use the fix-verify loop for all dependency and build errors.
1468
+ - \`context-awareness\` \u2014 Read existing code before modifying. Never write blind.
1469
+ - \`dependency-management\` \u2014 Install all dependencies upfront in a single operation.
1470
+
1471
+ **Load when relevant:**
1472
+ - \`architectural-thinking\` \u2014 Load when starting a new feature or multi-file change.
1473
+ - \`design-excellence\` \u2014 Load when building or styling user-facing UI.
1474
+ - \`template-originality\` \u2014 Load only when building a new project from a template scaffold.
1475
+
1476
+ Load each skill by reading its SKILL.md file, then follow its instructions throughout the task.
1477
+
1460
1478
  ## Plan Mode
1461
1479
 
1462
1480
  If you use ExitPlanMode to submit a plan, the system will automatically approve it.
@@ -4419,11 +4437,41 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
4419
4437
  }
4420
4438
  yield transformed;
4421
4439
  }
4422
- // Log system init message to verify skill discovery
4440
+ // Capture SDK init message this is the authoritative source for skill discovery
4423
4441
  if (sdkMessage.type === 'system' && sdkMessage.subtype === 'init') {
4424
4442
  const initMsg = sdkMessage;
4425
- process.stderr.write(`[native-sdk] SDK init - skills: ${JSON.stringify(initMsg.skills ?? [])}\n`);
4426
- process.stderr.write(`[native-sdk] SDK init - tools: ${(initMsg.tools ?? []).length} tools loaded\n`);
4443
+ const discoveredSkills = initMsg.skills ?? [];
4444
+ const loadedPlugins = initMsg.plugins ?? [];
4445
+ const toolCount = (initMsg.tools ?? []).length;
4446
+ process.stderr.write(`[native-sdk] SDK init — skills: [${discoveredSkills.join(', ')}] (${discoveredSkills.length})\n`);
4447
+ process.stderr.write(`[native-sdk] SDK init — plugins: ${JSON.stringify(loadedPlugins)}\n`);
4448
+ process.stderr.write(`[native-sdk] SDK init — tools: ${toolCount} loaded\n`);
4449
+ if (discoveredSkills.length > 0) {
4450
+ Sentry.logger.info('SDK initialized with skills', {
4451
+ skillCount: String(discoveredSkills.length),
4452
+ skills: discoveredSkills.join(', '),
4453
+ pluginCount: String(loadedPlugins.length),
4454
+ plugins: loadedPlugins.map(p => p.name).join(', '),
4455
+ toolCount: String(toolCount),
4456
+ model: initMsg.model ?? modelId,
4457
+ workingDirectory,
4458
+ });
4459
+ }
4460
+ else {
4461
+ Sentry.logger.warn('SDK initialized but no skills discovered', {
4462
+ pluginCount: String(loadedPlugins.length),
4463
+ plugins: JSON.stringify(loadedPlugins),
4464
+ toolCount: String(toolCount),
4465
+ model: initMsg.model ?? modelId,
4466
+ workingDirectory,
4467
+ platformPluginDir: platformPluginDir ?? 'null',
4468
+ });
4469
+ }
4470
+ }
4471
+ // Capture tool_use_summary messages — these indicate skill content loading
4472
+ if (sdkMessage.type === 'tool_use_summary') {
4473
+ const summaryMsg = sdkMessage;
4474
+ process.stderr.write(`[native-sdk] Tool use summary: ${summaryMsg.summary}\n`);
4427
4475
  }
4428
4476
  // Log result messages
4429
4477
  if (sdkMessage.type === 'result') {
@@ -7940,6 +7988,29 @@ function transformAgentMessageToSSE(agentMessage) {
7940
7988
  return cleaned;
7941
7989
  };
7942
7990
  for (const block of message.content) {
7991
+ // Detect skill invocations: the SDK loads skills via Read tool calls to SKILL.md files
7992
+ if (block.type === 'tool_use' && block.name === 'Read') {
7993
+ const filePath = block.input?.file_path || block.input?.filePath || block.input?.path || '';
7994
+ if (typeof filePath === 'string' && filePath.includes('SKILL.md')) {
7995
+ // Extract skill name from path: .../skills/<skill-name>/SKILL.md
7996
+ const skillMatch = filePath.match(/skills\/([^/]+)\/SKILL\.md/);
7997
+ const skillName = skillMatch ? skillMatch[1] : 'unknown';
7998
+ // Emit a skill-invocation event so the frontend can display it
7999
+ events.push({
8000
+ type: 'tool-input-available',
8001
+ toolCallId: block.id,
8002
+ toolName: 'SkillLoad',
8003
+ input: {
8004
+ skillName,
8005
+ filePath,
8006
+ },
8007
+ });
8008
+ // Store tool name as SkillLoad so output is also tagged
8009
+ transformerState.toolNames.set(block.id, 'SkillLoad');
8010
+ // Skip normal tool_use processing for this block
8011
+ continue;
8012
+ }
8013
+ }
7943
8014
  if (block.type === 'text' && block.text) {
7944
8015
  let text = String(block.text);
7945
8016
  // CRITICAL: Remove ALL task status formats from text BEFORE processing