claude-plugin-dsh 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +154 -2
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +80 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bin/inspect.d.ts +2 -0
- package/dist/bin/inspect.d.ts.map +1 -0
- package/dist/bin/inspect.js +45 -0
- package/dist/bin/inspect.js.map +1 -0
- package/dist/bin/runtime.d.ts +2 -0
- package/dist/bin/runtime.d.ts.map +1 -0
- package/dist/bin/runtime.js +4 -0
- package/dist/bin/runtime.js.map +1 -0
- package/dist/bin/scaffold.d.ts +2 -0
- package/dist/bin/scaffold.d.ts.map +1 -0
- package/dist/bin/scaffold.js +44 -0
- package/dist/bin/scaffold.js.map +1 -0
- package/dist/bin/sync.d.ts +2 -0
- package/dist/bin/sync.d.ts.map +1 -0
- package/dist/bin/sync.js +24 -0
- package/dist/bin/sync.js.map +1 -0
- package/dist/claude-compat.js +825 -0
- package/dist/src/claude-compat.d.ts +8 -0
- package/dist/src/claude-compat.d.ts.map +1 -0
- package/dist/src/claude-compat.js +7 -0
- package/dist/src/claude-compat.js.map +1 -0
- package/dist/src/dsh-types.d.ts +252 -0
- package/dist/src/dsh-types.d.ts.map +1 -0
- package/dist/src/dsh-types.js +6 -0
- package/dist/src/dsh-types.js.map +1 -0
- package/dist/src/hooks.d.ts +38 -0
- package/dist/src/hooks.d.ts.map +1 -0
- package/dist/src/hooks.js +136 -0
- package/dist/src/hooks.js.map +1 -0
- package/dist/src/plugin-files.d.ts +92 -0
- package/dist/src/plugin-files.d.ts.map +1 -0
- package/dist/src/plugin-files.js +198 -0
- package/dist/src/plugin-files.js.map +1 -0
- package/dist/src/plugin.d.ts +35 -0
- package/dist/src/plugin.d.ts.map +1 -0
- package/dist/src/plugin.js +422 -0
- package/dist/src/plugin.js.map +1 -0
- package/dist/src/transcript.d.ts +25 -0
- package/dist/src/transcript.d.ts.map +1 -0
- package/dist/src/transcript.js +198 -0
- package/dist/src/transcript.js.map +1 -0
- package/package.json +54 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mariusz Rakus
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,155 @@
|
|
|
1
|
-
#
|
|
1
|
+
# claude-plugin-dsh
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Run an unmodified [Claude Code](https://docs.claude.com/en/docs/claude-code) plugin inside
|
|
4
|
+
[DeepSeek Harness](https://github.com/deepseek-ai) (DSH).
|
|
5
|
+
|
|
6
|
+
You add a `dsh/` directory next to the plugin's `.claude-plugin/`. It holds a small DSH
|
|
7
|
+
bundle and a copy of `claude-compat.js`. The bundle reads the plugin's own skills, commands,
|
|
8
|
+
agents, hooks and instruction files and wires them into DSH. Claude Code never reads `dsh/`,
|
|
9
|
+
so the same tree keeps working in both harnesses. The vendored runtime is refreshed with
|
|
10
|
+
`sync`, not by hand.
|
|
11
|
+
|
|
12
|
+
TypeScript sources, compiled JavaScript and declarations. The vendored runtime is one file
|
|
13
|
+
with no runtime dependencies. Node 20 or newer; hooks require a POSIX shell.
|
|
14
|
+
|
|
15
|
+
Install the package:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
bun add claude-plugin-dsh
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`bun x claude-plugin-dsh` runs the CLI without installing it.
|
|
22
|
+
The old `claude-plugins-dsh` command name still works as an alias.
|
|
23
|
+
|
|
24
|
+
Adapters may import `createPlugin` and `rootFrom` directly, or vendor the built runtime as
|
|
25
|
+
shown below. Direct imports receive types; vendored copies stay self-contained and must be
|
|
26
|
+
updated with `sync`.
|
|
27
|
+
|
|
28
|
+
## What maps to what
|
|
29
|
+
|
|
30
|
+
| Claude Code | DSH |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `skills/<n>/SKILL.md` | skill at rank 450, so a same-named skill in `~/.dsh/skills` still wins |
|
|
33
|
+
| `commands/<n>.md` | `/<plugin>-<n>` slash command (prefix configurable); the body, with `$ARGUMENTS` and `$1` to `$9`, becomes the next turn |
|
|
34
|
+
| `agents/<n>.md` | skill `<plugin>-agent-<n>`: a role brief to pass to `subagent` or `spawn_teammate` |
|
|
35
|
+
| `CLAUDE.md`-style files you list | system prompt section, with `<!--harness:claude-only-->` blocks removed |
|
|
36
|
+
| `PreToolUse` hook | `tools/pre-execute`; `ask` becomes a DSH approval, `deny` or exit 2 denies, `updatedInput` is denied because DSH cannot rewrite arguments |
|
|
37
|
+
| `PostToolUse` hook | `tools/post-execute`; exit 2 blocks the result and its stderr becomes the feedback, `additionalContext` rides on the decision |
|
|
38
|
+
| `SessionStart` hook | `agent/created` of a root agent (subagents skipped, as in Claude Code) |
|
|
39
|
+
| `UserPromptSubmit` hook | a step carrying a user message; a block keeps the prompt from the model |
|
|
40
|
+
| `Stop`, `SubagentStop` hooks | `agent/turn-stopping`; `{"decision":"block"}` steers one more step |
|
|
41
|
+
| `SessionEnd` hook | `agent/disposed` |
|
|
42
|
+
| `.mcp.json` | not handled here: add `@deepseek-ai/dsh-mcp-client` rows to the bundle patch |
|
|
43
|
+
|
|
44
|
+
Hooks get Claude Code's stdin JSON: `session_id`, `cwd`, `hook_event_name`, `tool_name` using
|
|
45
|
+
Claude names such as `Bash`, `tool_input`, `stop_hook_active` and `transcript_path`.
|
|
46
|
+
`tool_response` uses Claude's per-tool shape: `stdout` and `stderr` for Bash, `file.content`
|
|
47
|
+
for Read, `filePath` plus edit strings for Write and Edit, and `filenames` for Glob. Their
|
|
48
|
+
environment has `CLAUDE_PLUGIN_ROOT` and `CLAUDE_PROJECT_DIR`, plus `CLAUDE_HARNESS=dsh` so a
|
|
49
|
+
script can tell the two harnesses apart. A hook with `args` runs in exec form, as in Claude Code: `command` is spawned directly with those arguments and no shell, and `${CLAUDE_PLUGIN_ROOT}` and `${CLAUDE_PROJECT_DIR}` are replaced inside each argument as plain text. `onFailure: "block"` makes a crash, a timeout or an exit code other than 0 and 2 count as a block. Matching hooks run in parallel, each in its own process
|
|
50
|
+
group. A timeout or a cancelled turn kills the whole group.
|
|
51
|
+
|
|
52
|
+
`transcript_path` points at a Claude-shaped JSONL export of the DSH session under
|
|
53
|
+
`$DSH_HOME/state/claude-compat/transcripts/`. It is mode 0600, grows by appending, and is
|
|
54
|
+
deleted when the agent is disposed.
|
|
55
|
+
|
|
56
|
+
Not mapped: function hooks (`hooks.json` `modules`), `PreCompact`, `Notification`, LSP
|
|
57
|
+
servers, and per-agent model pins.
|
|
58
|
+
|
|
59
|
+
## Add it to a plugin
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
bun x claude-plugin-dsh scaffold --scope @you /path/to/plugin
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`scaffold` writes `dsh/package.json` (package `@you/<plugin>-dsh`, or `<plugin>-dsh` without
|
|
66
|
+
`--scope`), `dsh/locale/en.json` and the runtime copy. You write two small files yourself.
|
|
67
|
+
|
|
68
|
+
`dsh/index.js`:
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
import { createPlugin, rootFrom } from './claude-compat.js'
|
|
72
|
+
|
|
73
|
+
const plugin = createPlugin({
|
|
74
|
+
root: rootFrom(import.meta.url),
|
|
75
|
+
// all optional:
|
|
76
|
+
instructions: ['CLAUDE.md'], // files to put in the system prompt
|
|
77
|
+
skills: { exclude: [], prefix: '' }, // prefix renames x to <prefix>-x; '' keeps x
|
|
78
|
+
commands: { exclude: [], prefix: '' },// default is the plugin name; '' gives /<n>
|
|
79
|
+
agents: { exclude: [], extraDirs: [] },
|
|
80
|
+
hooks: { events: ['PreToolUse'] }, // limit which hook events run
|
|
81
|
+
disableByDefault: [], // skills | commands | agents | instructions | hooks
|
|
82
|
+
})
|
|
83
|
+
export const { name, apply } = plugin
|
|
84
|
+
export default plugin
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`dsh/cordis.patch.yml`:
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
- insert:
|
|
91
|
+
- id: claude-compat-my-plugin
|
|
92
|
+
name: '@you/my-plugin-dsh' # the name in dsh/package.json
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Check what it registers without starting DSH:
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
bun x claude-plugin-dsh inspect /path/to/plugin
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Install into DSH
|
|
102
|
+
|
|
103
|
+
Through DSH's plugin manager:
|
|
104
|
+
|
|
105
|
+
```sh
|
|
106
|
+
dsh plugin --profile web add file:/abs/path/to/plugin/dsh
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Or for every profile, add a row to `~/.dsh/cordis.patch.yml`. DSH picks it up without a restart:
|
|
110
|
+
|
|
111
|
+
```yaml
|
|
112
|
+
- insert:
|
|
113
|
+
- id: claude-compat-my-plugin
|
|
114
|
+
name: "file:///abs/path/to/plugin/dsh/index.js"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
A row config can turn parts off: `config: { disable: [hooks] }`.
|
|
118
|
+
|
|
119
|
+
## Keeping vendored copies current
|
|
120
|
+
|
|
121
|
+
```sh
|
|
122
|
+
bun x claude-plugin-dsh sync plugin-a plugin-b
|
|
123
|
+
bun x claude-plugin-dsh sync --check plugin-a plugin-b
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Development
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
bun install --frozen-lockfile
|
|
130
|
+
bun run typecheck
|
|
131
|
+
bun run test
|
|
132
|
+
bun pm pack
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`bun run build` compiles the typed modules and CLI, emits declarations, and bundles
|
|
136
|
+
`dist/claude-compat.js` for existing adapters. Generated files are not committed.
|
|
137
|
+
`bun run test` runs the Node compatibility suite against the compiled runtime and CLI.
|
|
138
|
+
`prepack` builds before packaging.
|
|
139
|
+
|
|
140
|
+
Publishing requires npm access to the `claude-plugin-dsh` package:
|
|
141
|
+
|
|
142
|
+
```sh
|
|
143
|
+
bun publish
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`prepublishOnly` runs type checking and tests before publication. Do not put registry tokens
|
|
147
|
+
in the repository. Run `inspect` only on trusted plugins: it imports their JavaScript.
|
|
148
|
+
|
|
149
|
+
## Used by
|
|
150
|
+
|
|
151
|
+
The [kolezka](https://github.com/kolezka/marketplace) Claude Code plugins.
|
|
152
|
+
|
|
153
|
+
## License
|
|
154
|
+
|
|
155
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":""}
|
package/dist/bin/cli.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { inspect } from './inspect.js';
|
|
3
|
+
import { scaffold } from './scaffold.js';
|
|
4
|
+
import { sync } from './sync.js';
|
|
5
|
+
const usage = `Usage: claude-plugin-dsh <command> [options] <plugin-dir>...
|
|
6
|
+
|
|
7
|
+
Commands:
|
|
8
|
+
scaffold [--scope @you] <plugin-dir>... Generate manifest, locale and runtime
|
|
9
|
+
inspect <plugin-dir>... List plugin registrations (loads plugin code)
|
|
10
|
+
sync [--check] <plugin-dir>... Copy runtime, or check for drift
|
|
11
|
+
|
|
12
|
+
Options:
|
|
13
|
+
-h, --help Show help
|
|
14
|
+
`;
|
|
15
|
+
class UsageError extends Error {
|
|
16
|
+
}
|
|
17
|
+
async function main(args) {
|
|
18
|
+
const [command, ...rest] = args;
|
|
19
|
+
if ((command === '-h' || command === '--help') && rest.length === 0) {
|
|
20
|
+
console.log(usage);
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
if (command !== 'scaffold' && command !== 'inspect' && command !== 'sync') {
|
|
24
|
+
throw new UsageError(command ? `Unknown command: ${command}` : 'A command is required');
|
|
25
|
+
}
|
|
26
|
+
if (rest.length === 1 && (rest[0] === '-h' || rest[0] === '--help')) {
|
|
27
|
+
console.log(usage);
|
|
28
|
+
return 0;
|
|
29
|
+
}
|
|
30
|
+
let scope;
|
|
31
|
+
let check = false;
|
|
32
|
+
let positional = false;
|
|
33
|
+
const directories = [];
|
|
34
|
+
for (let index = 0; index < rest.length; index++) {
|
|
35
|
+
const arg = rest[index];
|
|
36
|
+
if (arg === undefined)
|
|
37
|
+
continue;
|
|
38
|
+
if (!positional && arg === '--') {
|
|
39
|
+
positional = true;
|
|
40
|
+
}
|
|
41
|
+
else if (!positional && arg === '--scope' && command === 'scaffold') {
|
|
42
|
+
if (scope !== undefined)
|
|
43
|
+
throw new UsageError('--scope may only be supplied once');
|
|
44
|
+
scope = rest[++index];
|
|
45
|
+
if (scope === undefined || !/^@[a-z0-9][a-z0-9._-]*$/.test(scope)) {
|
|
46
|
+
throw new UsageError(`--scope must look like @name, got ${JSON.stringify(scope)}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else if (!positional && arg === '--check' && command === 'sync') {
|
|
50
|
+
if (check)
|
|
51
|
+
throw new UsageError('--check may only be supplied once');
|
|
52
|
+
check = true;
|
|
53
|
+
}
|
|
54
|
+
else if (!positional && arg.startsWith('-')) {
|
|
55
|
+
throw new UsageError(`Unknown option for ${command}: ${arg}`);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
directories.push(arg);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (!directories.length)
|
|
62
|
+
throw new UsageError(`${command} requires at least one plugin directory`);
|
|
63
|
+
if (command === 'scaffold') {
|
|
64
|
+
scaffold(directories, scope ?? '');
|
|
65
|
+
return 0;
|
|
66
|
+
}
|
|
67
|
+
if (command === 'sync')
|
|
68
|
+
return sync(directories, check);
|
|
69
|
+
return inspect(directories);
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
process.exitCode = await main(process.argv.slice(2));
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
76
|
+
if (error instanceof UsageError)
|
|
77
|
+
console.error(usage);
|
|
78
|
+
process.exitCode = error instanceof UsageError ? 64 : 1;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../bin/inspect.ts"],"names":[],"mappings":"AAIA,wBAAsB,OAAO,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAyC7E"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { pathToFileURL } from 'node:url';
|
|
3
|
+
export async function inspect(directories) {
|
|
4
|
+
let failed = false;
|
|
5
|
+
for (const directory of directories) {
|
|
6
|
+
const entry = pathToFileURL(resolve(directory, 'dsh', 'index.js')).href;
|
|
7
|
+
const plugin = await import(entry);
|
|
8
|
+
if (typeof plugin !== 'object' || plugin === null || !('apply' in plugin) || typeof plugin.apply !== 'function') {
|
|
9
|
+
throw new Error(`${entry}: expected a plugin exporting apply`);
|
|
10
|
+
}
|
|
11
|
+
const seen = {
|
|
12
|
+
skills: [], commands: [], sections: [], events: [],
|
|
13
|
+
};
|
|
14
|
+
const ctx = {
|
|
15
|
+
logger: { warn: (message) => console.warn(' warn:', message) },
|
|
16
|
+
skills: { registerProvider: (create) => seen.skills.push(create({ signal: new AbortController().signal, invalidate() { } })) },
|
|
17
|
+
commands: { register: (definition) => seen.commands.push(definition.name) },
|
|
18
|
+
systemPrompt: { section: (section) => seen.sections.push(section) },
|
|
19
|
+
workingDirectory: { get: () => process.cwd() },
|
|
20
|
+
inject: (_services, callback) => callback(ctx),
|
|
21
|
+
effect() { },
|
|
22
|
+
on: (event) => seen.events.push(event),
|
|
23
|
+
};
|
|
24
|
+
await plugin.apply(ctx, {});
|
|
25
|
+
const skills = [];
|
|
26
|
+
for (const provider of seen.skills) {
|
|
27
|
+
for (const candidate of await provider.list({})) {
|
|
28
|
+
const body = await provider.get(candidate, {});
|
|
29
|
+
if (!body?.content) {
|
|
30
|
+
failed = true;
|
|
31
|
+
console.error(` ${candidate.name}: empty body`);
|
|
32
|
+
}
|
|
33
|
+
skills.push(candidate.name);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const prompt = seen.sections.map((section) => typeof section.text === 'string' ? section.text : section.text({})).join('');
|
|
37
|
+
console.log('name' in plugin ? String(plugin.name) : directory);
|
|
38
|
+
console.log(` skills: ${skills.join(', ') || '-'}`);
|
|
39
|
+
console.log(` commands: ${seen.commands.map((command) => '/' + command).join(' ') || '-'}`);
|
|
40
|
+
console.log(` prompt: ${prompt ? `${prompt.length} chars, claude-only left: ${/harness:claude-only/.test(prompt)}` : '-'}`);
|
|
41
|
+
console.log(` events: ${[...new Set(seen.events)].join(', ') || '-'}`);
|
|
42
|
+
}
|
|
43
|
+
return failed ? 1 : 0;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=inspect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../bin/inspect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../bin/runtime.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,QAAiE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../bin/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,2EAA2E;AAC3E,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,qBAAqB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../bin/scaffold.ts"],"names":[],"mappings":"AAsBA,wBAAgB,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAyB5E"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join, resolve } from 'node:path';
|
|
3
|
+
import { runtimePath } from './runtime.js';
|
|
4
|
+
function readManifest(root) {
|
|
5
|
+
const value = JSON.parse(readFileSync(join(root, '.claude-plugin', 'plugin.json'), 'utf8'));
|
|
6
|
+
if (typeof value !== 'object' || value === null || !('name' in value) || typeof value.name !== 'string' || !value.name) {
|
|
7
|
+
throw new Error(`${root}: plugin manifest must contain a name`);
|
|
8
|
+
}
|
|
9
|
+
const version = 'version' in value ? value.version : undefined;
|
|
10
|
+
const description = 'description' in value ? value.description : undefined;
|
|
11
|
+
if (version !== undefined && typeof version !== 'string')
|
|
12
|
+
throw new Error(`${root}: plugin version must be a string`);
|
|
13
|
+
if (description !== undefined && typeof description !== 'string')
|
|
14
|
+
throw new Error(`${root}: plugin description must be a string`);
|
|
15
|
+
return { name: value.name, version: version ?? '0.0.0', description: description ?? '' };
|
|
16
|
+
}
|
|
17
|
+
export function scaffold(directories, scope) {
|
|
18
|
+
for (const directory of directories) {
|
|
19
|
+
const root = resolve(directory);
|
|
20
|
+
const manifest = readManifest(root);
|
|
21
|
+
const dsh = join(root, 'dsh');
|
|
22
|
+
mkdirSync(join(dsh, 'locale'), { recursive: true });
|
|
23
|
+
copyFileSync(runtimePath, join(dsh, 'claude-compat.js'));
|
|
24
|
+
const pkg = {
|
|
25
|
+
name: `${scope ? scope + '/' : ''}${manifest.name}-dsh`,
|
|
26
|
+
version: manifest.version,
|
|
27
|
+
private: true,
|
|
28
|
+
description: `DeepSeek Harness adapter for the ${manifest.name} Claude Code plugin`,
|
|
29
|
+
type: 'module',
|
|
30
|
+
exports: { '.': './index.js', './locale/*.json': './locale/*.json' },
|
|
31
|
+
files: ['index.js', 'claude-compat.js', 'cordis.patch.yml', 'locale/*.json'],
|
|
32
|
+
dsh: { bundle: { patch: './cordis.patch.yml' } },
|
|
33
|
+
};
|
|
34
|
+
writeFileSync(join(dsh, 'package.json'), JSON.stringify(pkg, null, 2) + '\n');
|
|
35
|
+
const locale = { meta: { title: manifest.name, description: manifest.description } };
|
|
36
|
+
writeFileSync(join(dsh, 'locale', 'en.json'), JSON.stringify(locale, null, 2) + '\n');
|
|
37
|
+
for (const required of ['index.js', 'cordis.patch.yml']) {
|
|
38
|
+
if (!existsSync(join(dsh, required)))
|
|
39
|
+
console.warn(`${manifest.name}: dsh/${required} is missing, write it by hand`);
|
|
40
|
+
}
|
|
41
|
+
console.log(`scaffolded ${dsh}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=scaffold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../bin/scaffold.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../bin/sync.ts"],"names":[],"mappings":"AAIA,wBAAgB,IAAI,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAkB3E"}
|
package/dist/bin/sync.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join, resolve } from 'node:path';
|
|
3
|
+
import { runtimePath } from './runtime.js';
|
|
4
|
+
export function sync(directories, check) {
|
|
5
|
+
const canonical = readFileSync(runtimePath);
|
|
6
|
+
let status = 0;
|
|
7
|
+
for (const directory of directories) {
|
|
8
|
+
const dsh = resolve(directory, 'dsh');
|
|
9
|
+
const destination = join(dsh, 'claude-compat.js');
|
|
10
|
+
if (check) {
|
|
11
|
+
if (!existsSync(destination) || !canonical.equals(readFileSync(destination))) {
|
|
12
|
+
console.log(`drift: ${destination}`);
|
|
13
|
+
status = 1;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
mkdirSync(dsh, { recursive: true });
|
|
18
|
+
copyFileSync(runtimePath, destination);
|
|
19
|
+
console.log(`synced: ${destination}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return status;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../bin/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAC3E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE1C,MAAM,UAAU,IAAI,CAAC,WAA8B,EAAE,KAAc;IACjE,MAAM,SAAS,GAAG,YAAY,CAAC,WAAW,CAAC,CAAA;IAC3C,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,KAAK,MAAM,SAAS,IAAI,WAAW,EAAE,CAAC;QACpC,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QACrC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAA;QACjD,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;gBAC7E,OAAO,CAAC,GAAG,CAAC,UAAU,WAAW,EAAE,CAAC,CAAA;gBACpC,MAAM,GAAG,CAAC,CAAA;YACZ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YACnC,YAAY,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;YACtC,OAAO,CAAC,GAAG,CAAC,WAAW,WAAW,EAAE,CAAC,CAAA;QACvC,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
|