@sayknow-cli/coding-agent 0.5.16 → 0.5.17

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/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.5.17] - 2026-09-16
6
+
7
+ ### Fixed
8
+
9
+ - Compute the bundled UI-skill directive before workflow-state lookups in `UserPromptSubmit`, and isolate each lookup so a Linux CI recovery/activation failure cannot return empty context for `animate` / `ralplan` routing.
10
+
5
11
  ## [0.5.16] - 2026-09-16
6
12
 
7
13
  ### Fixed
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@sayknow-cli/coding-agent",
4
- "version": "0.5.16",
4
+ "version": "0.5.17",
5
5
  "description": "Sayknow-CLI CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://sayknow-cli.com",
7
7
  "author": "jaybeyond",
@@ -54,12 +54,12 @@
54
54
  "@agentclientprotocol/sdk": "1.3.0",
55
55
  "@babel/parser": "^7.29.3",
56
56
  "@mozilla/readability": "^0.6.0",
57
- "@sayknow-cli/stats": "0.5.16",
58
- "@sayknow-cli/agent-core": "0.5.16",
59
- "@sayknow-cli/ai": "0.5.16",
60
- "@sayknow-cli/natives": "0.5.16",
61
- "@sayknow-cli/tui": "0.5.16",
62
- "@sayknow-cli/utils": "0.5.16",
57
+ "@sayknow-cli/stats": "0.5.17",
58
+ "@sayknow-cli/agent-core": "0.5.17",
59
+ "@sayknow-cli/ai": "0.5.17",
60
+ "@sayknow-cli/natives": "0.5.17",
61
+ "@sayknow-cli/tui": "0.5.17",
62
+ "@sayknow-cli/utils": "0.5.17",
63
63
  "@puppeteer/browsers": "^2.13.0",
64
64
  "@types/turndown": "5.0.6",
65
65
  "@xterm/headless": "^6.0.0",
@@ -306,43 +306,80 @@ async function dispatchSkcNativeSkillHookInner(
306
306
  const hookEventName = readHookEventName(payload);
307
307
  const cwd = (options.cwd ?? safeString(payload.cwd).trim()) || process.cwd();
308
308
  if (hookEventName === "UserPromptSubmit") {
309
- const recoveryDiagnostics = await collectUserPromptStateRecoveryDiagnostics({
310
- cwd,
311
- sessionId: readSessionId(payload),
312
- threadId: readThreadId(payload),
313
- stateDir: options.stateDir,
314
- prompt: readPromptText(payload),
315
- sessionFile: readSessionFile(payload),
316
- });
317
- const recoveryContext = buildStateRecoveryDiagnosticsContext(recoveryDiagnostics);
318
309
  const prompt = readPromptText(payload);
319
- const skillState = prompt
320
- ? await recordSkillActivation({
321
- cwd,
322
- text: prompt,
323
- sessionId: readSessionId(payload),
324
- threadId: readThreadId(payload),
325
- turnId: readTurnId(payload),
326
- stateDir: options.stateDir,
327
- })
328
- : null;
329
- const effectiveSkillConfig = skillState
330
- ? await resolveEffectiveSkillConfig(cwd, options.effectiveSkillConfig, options.configPaths, {
331
- sessionId: readSessionId(payload),
332
- threadId: readThreadId(payload),
333
- stateDir: options.stateDir,
334
- })
335
- : undefined;
336
- const activeUltragoalContext = skillState
337
- ? null
338
- : await buildActiveUltragoalPromptContext({
339
- cwd,
340
- sessionId: readSessionId(payload),
341
- threadId: readThreadId(payload),
342
- stateDir: options.stateDir,
343
- prompt,
344
- sessionFile: readSessionFile(payload),
345
- });
310
+ // Compute the bundled UI-skill directive first so a later state/recovery
311
+ // lookup cannot abort the turn without it.
312
+ const uiSkillContext = buildUiSkillActivationContext(prompt);
313
+ let externalUiContext: string | null = null;
314
+ try {
315
+ externalUiContext = await buildExternalUiSkillContext({
316
+ cwd,
317
+ home: options.home ?? os.homedir(),
318
+ text: prompt,
319
+ });
320
+ } catch {
321
+ externalUiContext = null;
322
+ }
323
+
324
+ let recoveryContext: string | null = null;
325
+ try {
326
+ const recoveryDiagnostics = await collectUserPromptStateRecoveryDiagnostics({
327
+ cwd,
328
+ sessionId: readSessionId(payload),
329
+ threadId: readThreadId(payload),
330
+ stateDir: options.stateDir,
331
+ prompt,
332
+ sessionFile: readSessionFile(payload),
333
+ });
334
+ recoveryContext = buildStateRecoveryDiagnosticsContext(recoveryDiagnostics);
335
+ } catch {
336
+ recoveryContext = null;
337
+ }
338
+
339
+ let skillState = null;
340
+ try {
341
+ skillState = prompt
342
+ ? await recordSkillActivation({
343
+ cwd,
344
+ text: prompt,
345
+ sessionId: readSessionId(payload),
346
+ threadId: readThreadId(payload),
347
+ turnId: readTurnId(payload),
348
+ stateDir: options.stateDir,
349
+ })
350
+ : null;
351
+ } catch {
352
+ skillState = null;
353
+ }
354
+
355
+ let effectiveSkillConfig: EffectiveSkillConfigInput | undefined;
356
+ try {
357
+ effectiveSkillConfig = skillState
358
+ ? await resolveEffectiveSkillConfig(cwd, options.effectiveSkillConfig, options.configPaths, {
359
+ sessionId: readSessionId(payload),
360
+ threadId: readThreadId(payload),
361
+ stateDir: options.stateDir,
362
+ })
363
+ : undefined;
364
+ } catch {
365
+ effectiveSkillConfig = undefined;
366
+ }
367
+
368
+ let activeUltragoalContext: string | null = null;
369
+ try {
370
+ activeUltragoalContext = skillState
371
+ ? null
372
+ : await buildActiveUltragoalPromptContext({
373
+ cwd,
374
+ sessionId: readSessionId(payload),
375
+ threadId: readThreadId(payload),
376
+ stateDir: options.stateDir,
377
+ prompt,
378
+ sessionFile: readSessionFile(payload),
379
+ });
380
+ } catch {
381
+ activeUltragoalContext = null;
382
+ }
346
383
  if (activeUltragoalContext?.startsWith("BLOCK_ULTRAGOAL_COMPLETION:")) {
347
384
  return {
348
385
  hookEventName,
@@ -356,25 +393,9 @@ async function dispatchSkcNativeSkillHookInner(
356
393
  },
357
394
  };
358
395
  }
359
- // Frontend skills SKC routes to but does not vendor (license-restricted
360
- // collections). Resolved against the user's own install roots. A lookup
361
- // failure must not swallow the bundled UI-skill directive.
362
- let externalUiContext: string | null = null;
363
- try {
364
- externalUiContext = await buildExternalUiSkillContext({
365
- cwd,
366
- home: options.home ?? os.homedir(),
367
- text: prompt,
368
- });
369
- } catch {
370
- externalUiContext = null;
371
- }
372
396
  const additionalContext = [
373
397
  skillState ? buildSkillActivationAdditionalContext(skillState, effectiveSkillConfig) : activeUltragoalContext,
374
- // Bundled frontend UI skills are advertised independently of workflow
375
- // activation: they have no mode state and must fire even when a
376
- // workflow keyword already matched.
377
- buildUiSkillActivationContext(prompt),
398
+ uiSkillContext,
378
399
  externalUiContext,
379
400
  recoveryContext,
380
401
  classifyQuestionOnlyPrompt(prompt),