dsh-claude-compat 0.8.2 → 0.8.4

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/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
  <a href="README.zh-CN.md"><img src="https://img.shields.io/badge/🌐_įŽ€äŊ“中文-į‚šæˆ‘é˜…č¯ģ中文-red?style=for-the-badge" alt="įŽ€äŊ“中文"></a>
9
9
  <img src="https://img.shields.io/npm/dm/dsh-claude-compat?style=flat-square&label=downloads/month&color=brightgreen" alt="npm downloads/month">
10
10
  <img src="https://img.shields.io/npm/dt/dsh-claude-compat?style=flat-square&label=total%20downloads&color=blue" alt="npm total downloads">
11
- <img src="https://img.shields.io/badge/version-0.8.1-blue?style=flat-square" alt="Version">
11
+ <img src="https://img.shields.io/badge/version-0.8.4-blue?style=flat-square" alt="Version">
12
12
  <img src="https://img.shields.io/badge/license-MIT-orange?style=flat-square" alt="License">
13
13
  </p>
14
14
 
package/README.zh-CN.md CHANGED
@@ -8,7 +8,7 @@
8
8
  <a href="README.md"><img src="https://img.shields.io/badge/🌐_English-Click_me-red?style=for-the-badge" alt="English"></a>
9
9
  <img src="https://img.shields.io/npm/dm/dsh-claude-compat?style=flat-square&label=downloads/month&color=brightgreen" alt="npm downloads/month">
10
10
  <img src="https://img.shields.io/npm/dt/dsh-claude-compat?style=flat-square&label=total%20downloads&color=blue" alt="npm total downloads">
11
- <img src="https://img.shields.io/badge/version-0.8.1-blue?style=flat-square" alt="Version">
11
+ <img src="https://img.shields.io/badge/version-0.8.4-blue?style=flat-square" alt="Version">
12
12
  <img src="https://img.shields.io/badge/license-MIT-orange?style=flat-square" alt="License">
13
13
  </p>
14
14
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-claude-compat",
3
- "version": "0.8.2",
3
+ "version": "0.8.4",
4
4
  "description": "DeepSeek Harness plugin: bridge Claude Code's .claude/ directories (project and ~/.claude: skills, commands, rules) into DSH native skill registry and message-stream rules injection.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/hooks.js CHANGED
@@ -13,6 +13,7 @@ import { readFileSync } from 'node:fs';
13
13
  import { join } from 'node:path';
14
14
  import { createUserMessage } from '@deepseek-ai/dsh-llm';
15
15
  import {
16
+ CLAUDE_COMPAT_SOURCE_KIND,
16
17
  findProjectRootSync,
17
18
  resolveUserClaudeDir,
18
19
  } from './lib.js';
@@ -108,7 +109,7 @@ export function mapPostHookOutput(exitCode, stdout, { warn = console.warn } = {}
108
109
  kind: 'accept',
109
110
  additionalContexts: [createUserMessage({
110
111
  content: [{ type: 'text', text: additional }],
111
- source: { kind: 'plugin', plugin: 'dsh-claude-compat', form: 'hook-context' },
112
+ source: { kind: CLAUDE_COMPAT_SOURCE_KIND, form: 'hook-context' },
112
113
  })],
113
114
  };
114
115
  }
@@ -339,7 +340,7 @@ async function runPromptHooks(hooks, agent, config) {
339
340
  if (text === '') continue;
340
341
  extra.push(createUserMessage({
341
342
  content: [{ type: 'text', text }],
342
- source: { kind: 'plugin', plugin: 'dsh-claude-compat', form: 'hook-context' },
343
+ source: { kind: CLAUDE_COMPAT_SOURCE_KIND, form: 'hook-context' },
343
344
  }));
344
345
  }
345
346
  return extra.length > 0 ? extra : undefined;
package/src/index.js CHANGED
@@ -54,6 +54,7 @@ import { registerHooks } from './hooks.js';
54
54
  import { mountMcpServers, mountMcpConfigs } from './mcp.js';
55
55
  import { discoverPluginContent, readInstalledClaudePlugins, translatePluginMcp } from './plugins.js';
56
56
  import {
57
+ CLAUDE_COMPAT_SOURCE_KIND,
57
58
  findProjectRoot,
58
59
  findProjectRootSync,
59
60
  listMdFilesSync,
@@ -405,18 +406,16 @@ function registerRulesSection(ctx, config) {
405
406
  ctx.on('agent/pre-step', async ({ agent, messages }, next) => {
406
407
  const decision = await next();
407
408
  if (decision.kind !== 'enter') return decision;
408
- const present = (list) => list.some((m) => m?.source?.kind === 'plugin' && m.source.plugin === 'dsh-claude-compat');
409
- // Take one snapshot outside the loop: Session has no `events` property
410
- // (dsh 0.1.2-rc.1) — snapshotEvents() is the public API. Indexing the
411
- // snapshot by seq is stable and avoids re-materializing per node.
412
- const events = agent.session.snapshotEvents();
409
+ const present = (list) => list.some((m) => m?.source?.kind === CLAUDE_COMPAT_SOURCE_KIND);
410
+ // dsh 0.1.2 made the event log private — exact lookup is eventAt(seq),
411
+ // the same API dsh core uses for its own surface scans. Legacy dsh
412
+ // exposed a plain session.events array; keep an optional fallback.
413
413
  const alreadyInjected = present(messages)
414
414
  || present(decision.messages)
415
415
  || agent.session.surface.nodes.some((seq) => {
416
- const event = events[seq];
416
+ const event = agent.session.eventAt?.(seq) ?? agent.session.events?.[seq];
417
417
  return event?.type === 'user/message'
418
- && event.data?.source?.kind === 'plugin'
419
- && event.data.source.plugin === 'dsh-claude-compat';
418
+ && event.data?.source?.kind === CLAUDE_COMPAT_SOURCE_KIND;
420
419
  });
421
420
  if (alreadyInjected) return decision;
422
421
  // Session cwd, NOT process.cwd() — the DSH process may be launched from
@@ -431,7 +430,7 @@ function registerRulesSection(ctx, config) {
431
430
  // of the message array. Not in system prompt.
432
431
  cache.set(cwd, createUserMessage({
433
432
  content: [{ type: 'text', text }],
434
- source: { kind: 'plugin', plugin: 'dsh-claude-compat', form: 'rules' },
433
+ source: { kind: CLAUDE_COMPAT_SOURCE_KIND, form: 'rules' },
435
434
  }));
436
435
  }
437
436
  return {
package/src/lib.js CHANGED
@@ -8,6 +8,15 @@ import { dirname, join, resolve } from 'node:path';
8
8
  import { homedir } from 'node:os';
9
9
  import { parse } from 'yaml';
10
10
 
11
+ // Producer-owned source kind for every message this plugin injects. dsh's
12
+ // session format v4 admission (session-format-v3-to-v4/src/message-sources.ts)
13
+ // rejects the retired V3 `kind: 'plugin'` wrapper: a third-party producer must
14
+ // emit its own kind. dsh derives exactly this string for us — `producerKind()`
15
+ // falls through RENAMED_PRODUCERS and RELEASED_SAME_NAME_PRODUCERS to
16
+ // `plugin:${plugin}` — so a V3 log migrated by dsh and a message we emit today
17
+ // carry the identical kind. Emission and dedup must both use this constant.
18
+ export const CLAUDE_COMPAT_SOURCE_KIND = 'plugin:dsh-claude-compat';
19
+
11
20
  export function resolveUserClaudeDir(dir) {
12
21
  if (dir === undefined || dir === null || dir === '') return join(homedir(), '.claude');
13
22
  if (dir === '~') return homedir();