@pikiloom/kernel 0.3.1 → 0.3.3

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.
@@ -28,6 +28,7 @@ export declare function claudeModelStallMs(): number;
28
28
  export declare const CLAUDE_TRUNCATED_RECOVERY_PROMPT: string;
29
29
  export declare function claudeTruncatedRecoveryEnabled(): boolean;
30
30
  export declare function isClaudeSyntheticResumeNoise(text: string): boolean;
31
+ export declare function isClaudeSlashCommand(prompt: string): boolean;
31
32
  export declare function claudeProducedRealOutput(s: any): boolean;
32
33
  export declare function claudeResumeNoopRetryLimit(): number;
33
34
  export declare function claudeUserEventHasToolResult(ev: any): boolean;
@@ -270,7 +270,13 @@ export class ClaudeDriver {
270
270
  // through its repair to a real answer within this one turn. Bounded (the repair can
271
271
  // no-op more than once); the post-tool stall watchdog is the backstop if the CLI never
272
272
  // engages. Scoped to resumes (input.sessionId) — a fresh session has no dangling turn.
273
+ // Excludes local slash commands (isClaudeSlashCommand): /compact, /clear & friends are
274
+ // LEGITIMATELY output-empty (their effect is a local action, not an assistant reply), so
275
+ // the emptiness that flags a dropped send is normal for them. Re-issuing one is never a
276
+ // repair — for /compact it just fires a second compaction that reports "Not enough
277
+ // messages to compact." A real dropped send is a plain prompt and still self-heals.
273
278
  if (!hasError && !!input.sessionId && !claudeProducedRealOutput(state)
279
+ && !isClaudeSlashCommand(input.prompt)
274
280
  && noopResumeRetries < claudeResumeNoopRetryLimit()) {
275
281
  noopResumeRetries++;
276
282
  let injected = false;
@@ -809,6 +815,15 @@ export function isClaudeSyntheticResumeNoise(text) {
809
815
  const t = (text || '').trim().toLowerCase();
810
816
  return t === 'no response requested.' || t === 'no response requested';
811
817
  }
818
+ // A prompt whose first token is a Claude slash command (/compact, /clear, /cost, /model …, a custom
819
+ // /namespace:command). Such a prompt is a LOCAL action, not a request for a model reply, so an
820
+ // output-empty result is expected — not the dropped-send signature the no-op-resume repair targets.
821
+ // The first token must be a bare command name (letters/digits/_/- with an optional :namespace) ending
822
+ // at whitespace or end-of-string, so a filesystem-style path (/Users/foo) is NOT matched. Pure +
823
+ // exported for hermetic testing.
824
+ export function isClaudeSlashCommand(prompt) {
825
+ return /^\/[a-z0-9][\w-]*(?::[\w-]+)?(?:\s|$)/i.test((prompt || '').trimStart());
826
+ }
812
827
  // True once the turn produced ANY real model output — streamed or whole-message text/reasoning, a
813
828
  // tool use, or a spawned sub-agent. False for a pure no-op (a synthetic resume-repair result that
814
829
  // ran none of the prompt), which is exactly what the no-op-resume recovery keys off. Pure +
@@ -120,6 +120,12 @@ export class Hub {
120
120
  extraArgs: spawn.extraArgs,
121
121
  configOverrides: spawn.configOverrides,
122
122
  extraMcpServers: tools.servers,
123
+ // The managed path's control verb `LoomIO.steer()` can only reach a driver that was
124
+ // launched steer-enabled, so honor the driver's declared capability here — otherwise
125
+ // steer is a silent no-op for steer-capable agents (claude gates registerSteer +
126
+ // --replay-user-messages on this flag). Drivers that don't support steer stay
127
+ // un-steerable; those that steer over their own channel regardless (codex RPC) ignore it.
128
+ steerable: !!driver.capabilities?.steer,
123
129
  };
124
130
  runner.run(driver, turnInput, input.prompt, model, effort)
125
131
  .then(async (result) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikiloom/kernel",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Heterogeneous coding agents (Claude / Codex / Gemini / ACP) -> an interaction-friendly, accumulating session snapshot + control handle, over pluggable surfaces (IM, Web, tunnel, TUI). The reusable core pikiloom itself is built on.",
5
5
  "type": "module",
6
6
  "license": "MIT",