@huaqiu/dsh-kicad 0.4.2
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 +143 -0
- package/cordis.patch.yml +15 -0
- package/lib/index.d.mts +284 -0
- package/lib/index.mjs +957 -0
- package/package.json +41 -0
- package/skills/kicad-ipc/SKILL.md +81 -0
- package/skills/kicad-ipc/agents/openai.yaml +3 -0
- package/skills/kicad-ipc/references/ipc-pcb-workflows.md +145 -0
- package/skills/kicad-ipc/scripts/add_footprint_from_board_template.py +72 -0
- package/skills/kicad-ipc/scripts/create_copper_zone.py +85 -0
- package/skills/kicad-ipc/scripts/create_track.py +73 -0
- package/skills/kicad-ipc/scripts/create_via.py +58 -0
- package/skills/kicad-ipc/scripts/diagnose_ipc_connection.py +49 -0
- package/skills/kicad-ipc/scripts/kipy_common.py +80 -0
- package/skills/kicad-ipc/scripts/move_rotate_footprint.py +64 -0
- package/skills/kicad-ipc/scripts/refill_zones.py +33 -0
- package/skills/kicad-ipc/scripts/remove_selected_items.py +40 -0
- package/skills/kicad-ipc/scripts/update_selected_track_width.py +54 -0
- package/skills/kicad-ipc/scripts/verify_live_ipc.py +91 -0
- package/src/config.ts +79 -0
- package/src/index.ts +230 -0
- package/src/ipc.ts +300 -0
- package/src/paths.ts +66 -0
- package/src/scripts.ts +131 -0
- package/src/tools.ts +634 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 深圳华秋智联股份有限公司
|
|
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
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# @huaqiu/dsh-kicad
|
|
2
|
+
|
|
3
|
+
KiCad agent capabilities for DeepSeek Harness, shipped as **one** DSH plugin: the
|
|
4
|
+
executable KiCad tools *and* the `kicad-ipc` skill that teaches the agent how to use
|
|
5
|
+
them. Installing the Huaqiu DSH PCB/EDA bundle makes both available out of the box —
|
|
6
|
+
there is no separate skill installation step.
|
|
7
|
+
|
|
8
|
+
Migrated from the standalone `kicad-agent` repository.
|
|
9
|
+
|
|
10
|
+
## What you get
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
@huaqiu/dsh-kicad
|
|
14
|
+
├── Tools 10 KiCad tools, registered with ctx.tools.register(defineTool(...))
|
|
15
|
+
└── Skills kicad-ipc — SKILL.md + references/ + 11 python script templates
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Tools
|
|
19
|
+
|
|
20
|
+
| Tool | Script | Effect |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| `kicad_ipc_diagnose` | `diagnose_ipc_connection.py` | read |
|
|
23
|
+
| `kicad_ipc_verify_live` | `verify_live_ipc.py` | probe (commit dropped) |
|
|
24
|
+
| `kicad_pcb_create_track` | `create_track.py` | mutate |
|
|
25
|
+
| `kicad_pcb_create_via` | `create_via.py` | mutate |
|
|
26
|
+
| `kicad_pcb_create_copper_zone` | `create_copper_zone.py` | mutate |
|
|
27
|
+
| `kicad_pcb_add_footprint_from_template` | `add_footprint_from_board_template.py` | mutate |
|
|
28
|
+
| `kicad_pcb_move_rotate_footprint` | `move_rotate_footprint.py` | mutate |
|
|
29
|
+
| `kicad_pcb_update_selected_track_width` | `update_selected_track_width.py` | mutate |
|
|
30
|
+
| `kicad_pcb_refill_zones` | `refill_zones.py` | mutate |
|
|
31
|
+
| `kicad_pcb_remove_selected_items` | `remove_selected_items.py` | mutate (needs `confirm`) |
|
|
32
|
+
|
|
33
|
+
Every tool returns the same envelope:
|
|
34
|
+
|
|
35
|
+
```jsonc
|
|
36
|
+
{ "ok": true, "script": "create_track", "effect": "mutate", "output": "…" }
|
|
37
|
+
{ "ok": false, "script": "create_track", "effect": "mutate",
|
|
38
|
+
"error": { "kind": "FAILED_PRECONDITION", "message": "…" } }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`error.kind` is one of `FAILED_PRECONDITION` (KiCad IPC cannot run at all — do not
|
|
42
|
+
retry), `UNAVAILABLE` (KiCad unreachable — retry once after checking the environment),
|
|
43
|
+
`DEADLINE_EXCEEDED` (timed out), `INVALID_ARGUMENT` (board untouched), `INTERNAL`
|
|
44
|
+
(script failed; the commit was dropped).
|
|
45
|
+
|
|
46
|
+
### Skill
|
|
47
|
+
|
|
48
|
+
`skills/kicad-ipc/SKILL.md` is the agent's operating guidance: when to use KiCad, how to
|
|
49
|
+
inspect current state, how to verify mutations, and when to stop and ask. It is *not* an
|
|
50
|
+
IPC API specification — the tool schemas are the executable interface, the skill is the
|
|
51
|
+
reasoning around them.
|
|
52
|
+
|
|
53
|
+
Progressive disclosure: `references/ipc-pcb-workflows.md` holds version matrices, the
|
|
54
|
+
public CRUD table and failure handling; `scripts/` holds runnable templates. Both are
|
|
55
|
+
reachable by the agent because the skill is registered with a `resourceBase` pointing at
|
|
56
|
+
its directory.
|
|
57
|
+
|
|
58
|
+
## How the plugin is wired
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
# cordis.patch.yml
|
|
62
|
+
- insert:
|
|
63
|
+
- id: huaqiu-dsh-kicad
|
|
64
|
+
name: '@huaqiu/dsh-kicad'
|
|
65
|
+
inject: ['skills', 'tools']
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`inject` must match `export const inject` in `src/index.ts`. `skills` is required —
|
|
69
|
+
that is the DSH runtime's own plugin-bundled skill channel (`ctx.skills.register`).
|
|
70
|
+
`apply()` registers the skill and the ten tools and returns a single disposer.
|
|
71
|
+
|
|
72
|
+
The skill is located relative to the **loaded module**, not the source tree, so one
|
|
73
|
+
resolver works for `src/` (tests), `lib/` (built) and an npm install:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
<package>/lib/index.mjs -> <package>/skills/kicad-ipc
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
That is why `files[]` must contain `skills` — otherwise npm strips it and `apply()`
|
|
80
|
+
throws loudly instead of silently degrading.
|
|
81
|
+
|
|
82
|
+
## Runtime requirements
|
|
83
|
+
|
|
84
|
+
KiCad IPC is not bundled; these are host requirements, the same ones `kicad-agent` had:
|
|
85
|
+
|
|
86
|
+
- KiCad **9.0+** with the KiCad API service enabled (Preferences → Plugins) and PCB
|
|
87
|
+
Editor restarted, with a `.kicad_pcb` open.
|
|
88
|
+
- A Python interpreter with the official `kicad-python` package (`kipy`) whose version
|
|
89
|
+
matches the running KiCad. Configure it with plugin config `pythonPath` or
|
|
90
|
+
`$DSH_KICAD_PYTHON` (default `python3`).
|
|
91
|
+
- DSH running with **Full Access** — a non-Full-Access sandbox cannot reach KiCad's
|
|
92
|
+
named pipe on Windows.
|
|
93
|
+
|
|
94
|
+
`KICAD_API_SOCKET` / `KICAD_API_TOKEN` are injected by KiCad and read by `kipy`. This
|
|
95
|
+
package never guesses, hardcodes or scans for them.
|
|
96
|
+
|
|
97
|
+
### Configuration
|
|
98
|
+
|
|
99
|
+
| Setting | Env | Default |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| `pythonPath` | `DSH_KICAD_PYTHON` | `python3` |
|
|
102
|
+
| `skillsDir` | `DSH_KICAD_SKILLS_DIR` | bundled `skills/kicad-ipc` |
|
|
103
|
+
| `timeoutMs` | — | `30000` |
|
|
104
|
+
| `diagnosticTimeoutMs` | — | `15000` |
|
|
105
|
+
| `refillTimeoutMs` | — | `150000` |
|
|
106
|
+
|
|
107
|
+
## Boundaries
|
|
108
|
+
|
|
109
|
+
- **No HQ Edge dependency.** Unlike `@huaqiu/dsh-eda-host`, this plugin talks to KiCad
|
|
110
|
+
directly: no runtime, executable, service, port, config or artifact dependency, and no
|
|
111
|
+
`@hqedge/*` import.
|
|
112
|
+
- **KiCad is the source of truth.** The adapter returns what KiCad said, verbatim. There
|
|
113
|
+
is no second authoritative representation of board state in this package.
|
|
114
|
+
- **The scripts own the protocol.** The adapter shells out to the migrated Python
|
|
115
|
+
templates rather than re-implementing KiCad IPC in TypeScript.
|
|
116
|
+
|
|
117
|
+
## Layout
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
packages/dsh-kicad/
|
|
121
|
+
src/index.ts # plugin entry: apply() registers skill + tools
|
|
122
|
+
src/tools.ts # 10 defineTool definitions
|
|
123
|
+
src/ipc.ts # KiCad IPC adapter (script runner + error classification)
|
|
124
|
+
src/scripts.ts # bundled script registry
|
|
125
|
+
src/paths.ts # runtime skill-directory resolution
|
|
126
|
+
src/config.ts # python interpreter / timeouts
|
|
127
|
+
skills/kicad-ipc/
|
|
128
|
+
SKILL.md
|
|
129
|
+
agents/openai.yaml
|
|
130
|
+
references/ipc-pcb-workflows.md
|
|
131
|
+
scripts/*.py
|
|
132
|
+
test/ # plugin loading, tool registration, skill discovery, bundling
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Tests
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
pnpm --filter @huaqiu/dsh-kicad test
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
46 tests covering plugin loading, the disposer, skill discovery, tool registration, argv
|
|
142
|
+
construction, pre-flight validation, semantic error mapping and packaging. Execution is
|
|
143
|
+
exercised against a fake interpreter, so no KiCad or `kipy` is needed.
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# DSH bundle patch: inserts the Huaqiu KiCad plugin into a profile's layer stack.
|
|
2
|
+
#
|
|
3
|
+
# This one row delivers BOTH halves of `dsh-kicad` (task: dsh-kicad-skill-plugin):
|
|
4
|
+
# the KiCad tools and the bundled `kicad-ipc` skill. The plugin registers the
|
|
5
|
+
# skill itself at load time via `ctx.skills.register()`, so there is no separate
|
|
6
|
+
# skill installation step and no second skill registration mechanism.
|
|
7
|
+
#
|
|
8
|
+
# The entry `inject` MUST match the node-half module contract (`src/index.ts`
|
|
9
|
+
# `export const inject`): `skills` + `tools`. `skills` is REQUIRED — without it
|
|
10
|
+
# `apply()`'s `ctx.skills` access throws `cannot get property "skills" without
|
|
11
|
+
# inject`.
|
|
12
|
+
- insert:
|
|
13
|
+
- id: huaqiu-dsh-kicad
|
|
14
|
+
name: '@huaqiu/dsh-kicad'
|
|
15
|
+
inject: ['skills', 'tools']
|
package/lib/index.d.mts
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
2
|
+
import { Context } from "@deepseek-ai/cordis";
|
|
3
|
+
//#region src/config.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for `@huaqiu/dsh-kicad`.
|
|
6
|
+
*
|
|
7
|
+
* Deliberately small. Everything KiCad-specific (socket, token, board state)
|
|
8
|
+
* belongs to KiCad and the bundled scripts — the scripts read
|
|
9
|
+
* `KICAD_API_SOCKET` / `KICAD_API_TOKEN` that KiCad injects, and this package
|
|
10
|
+
* never guesses them. The only host configuration here is *how to reach the
|
|
11
|
+
* Python environment that owns `kipy`*, which is a machine concern, not a
|
|
12
|
+
* design concern.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
15
|
+
*/
|
|
16
|
+
/** Configuration accepted by the plugin's `apply()`. */
|
|
17
|
+
interface KicadConfig {
|
|
18
|
+
/**
|
|
19
|
+
* Python interpreter used to run the bundled KiCad scripts. It must have the
|
|
20
|
+
* official `kicad-python` package (`kipy`) installed.
|
|
21
|
+
*/
|
|
22
|
+
pythonPath: string;
|
|
23
|
+
/** Scripts directory override (defaults to the bundled skill's `scripts/`). */
|
|
24
|
+
skillsDir?: string;
|
|
25
|
+
/** Per-script timeout in milliseconds. */
|
|
26
|
+
timeoutMs: number;
|
|
27
|
+
/** Timeout for the two diagnostic scripts, which are fast but must be prompt. */
|
|
28
|
+
diagnosticTimeoutMs: number;
|
|
29
|
+
/** Timeout for `refill_zones`, which can legitimately block for ~2 minutes. */
|
|
30
|
+
refillTimeoutMs: number;
|
|
31
|
+
}
|
|
32
|
+
type KicadConfigInput = Partial<KicadConfig>;
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/scripts.d.ts
|
|
35
|
+
/**
|
|
36
|
+
* Registry of the KiCad IPC script templates bundled with this package.
|
|
37
|
+
*
|
|
38
|
+
* The scripts are the migrated `kicad-agent` executable surface. They live
|
|
39
|
+
* under `skills/kicad-ipc/scripts/` and are shipped verbatim — this module only
|
|
40
|
+
* describes them so the DSH tools and the skill stay in sync. Nothing here
|
|
41
|
+
* reimplements KiCad IPC: the scripts own it (see `./ipc.ts`).
|
|
42
|
+
*
|
|
43
|
+
* @module
|
|
44
|
+
*/
|
|
45
|
+
/** How one bundled script changes (or does not change) the KiCad board. */
|
|
46
|
+
type ScriptEffect =
|
|
47
|
+
/** Reads only. Safe to run at any time. */
|
|
48
|
+
'read' |
|
|
49
|
+
/** Mutates the board inside a dropped commit — nothing is persisted. */
|
|
50
|
+
'probe' |
|
|
51
|
+
/** Mutates the board and pushes the commit. Persists only with `save`. */
|
|
52
|
+
'mutate';
|
|
53
|
+
interface KicadScript {
|
|
54
|
+
/** Stable id — the script's file stem. */
|
|
55
|
+
readonly id: string;
|
|
56
|
+
/** File name inside `skills/kicad-ipc/scripts/`. */
|
|
57
|
+
readonly file: string;
|
|
58
|
+
/** One-line, agent-facing summary of what the script does. */
|
|
59
|
+
readonly summary: string;
|
|
60
|
+
/** What the script does to the board. */
|
|
61
|
+
readonly effect: ScriptEffect;
|
|
62
|
+
/** Whether the script accepts the shared `--save` flag. */
|
|
63
|
+
readonly supportsSave: boolean;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Every bundled script, keyed by id.
|
|
67
|
+
*
|
|
68
|
+
* Mirrors `skills/kicad-ipc/scripts/` 1:1. Adding a script to the skill means
|
|
69
|
+
* adding it here (and exposing it in `./tools.ts`) — the bundling test asserts
|
|
70
|
+
* that all three stay consistent.
|
|
71
|
+
*/
|
|
72
|
+
declare const KICAD_SCRIPTS: Readonly<Record<string, KicadScript>>;
|
|
73
|
+
/** The bundled script ids, in registration order. */
|
|
74
|
+
declare const KICAD_SCRIPT_IDS: readonly string[];
|
|
75
|
+
/**
|
|
76
|
+
* Look up one script by id.
|
|
77
|
+
* @throws when the id is not part of the bundled set.
|
|
78
|
+
*/
|
|
79
|
+
declare function kicadScript(id: string): KicadScript;
|
|
80
|
+
/** The canonical skill directory name shipped by this package. */
|
|
81
|
+
declare const KICAD_SKILL_NAME = "kicad-ipc";
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/ipc.d.ts
|
|
84
|
+
/**
|
|
85
|
+
* Semantic failure kinds, shared by every KiCad tool.
|
|
86
|
+
*
|
|
87
|
+
* Same vocabulary as `@huaqiu/dsh-eda-host` so the agent's error handling does
|
|
88
|
+
* not have to differ per EDA plugin.
|
|
89
|
+
*/
|
|
90
|
+
type KicadErrorKind =
|
|
91
|
+
/** The environment cannot run KiCad IPC at all (no python, no kipy, no board). */
|
|
92
|
+
'FAILED_PRECONDITION' |
|
|
93
|
+
/** KiCad is installed but unreachable right now — retryable. */
|
|
94
|
+
'UNAVAILABLE' |
|
|
95
|
+
/** The script did not finish inside its timeout. */
|
|
96
|
+
'DEADLINE_EXCEEDED' |
|
|
97
|
+
/** The arguments were rejected before KiCad was touched. */
|
|
98
|
+
'INVALID_ARGUMENT' |
|
|
99
|
+
/** KiCad or the script failed after the connection was established. */
|
|
100
|
+
'INTERNAL';
|
|
101
|
+
interface KicadError {
|
|
102
|
+
kind: KicadErrorKind;
|
|
103
|
+
message: string;
|
|
104
|
+
}
|
|
105
|
+
/** Raw result of one script invocation. */
|
|
106
|
+
interface ScriptRun {
|
|
107
|
+
/** Script identifier (file stem). */
|
|
108
|
+
script: string;
|
|
109
|
+
/** Process exit code; `null` when it never started or was killed. */
|
|
110
|
+
exitCode: number | null;
|
|
111
|
+
stdout: string;
|
|
112
|
+
stderr: string;
|
|
113
|
+
/** Exact argv handed to the interpreter, for auditability. */
|
|
114
|
+
argv: string[];
|
|
115
|
+
/** `true` when the process was killed because the timeout elapsed. */
|
|
116
|
+
timedOut: boolean;
|
|
117
|
+
}
|
|
118
|
+
interface RunScriptOptions {
|
|
119
|
+
/** Directory holding the bundled scripts. */
|
|
120
|
+
scriptsDir: string;
|
|
121
|
+
/** Python interpreter with `kipy` available. */
|
|
122
|
+
pythonPath: string;
|
|
123
|
+
/** Script to run. */
|
|
124
|
+
script: KicadScript;
|
|
125
|
+
/** CLI flags, already stringified (e.g. `['--net', 'GND']`). */
|
|
126
|
+
args?: readonly string[];
|
|
127
|
+
/** Timeout in milliseconds. */
|
|
128
|
+
timeoutMs: number;
|
|
129
|
+
/** Optional cancellation from the tool call. */
|
|
130
|
+
signal?: AbortSignal;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Run one bundled KiCad script.
|
|
134
|
+
*
|
|
135
|
+
* Never throws for script-level failures — the outcome is reported, so a
|
|
136
|
+
* missing `kipy` or a closed KiCad degrades into a typed error the agent can
|
|
137
|
+
* act on instead of crashing the plugin. It only throws when the script itself
|
|
138
|
+
* is not part of the package.
|
|
139
|
+
*/
|
|
140
|
+
declare function runKicadScript(options: RunScriptOptions): Promise<ScriptRun>;
|
|
141
|
+
/**
|
|
142
|
+
* Translate a raw run into a semantic error, or `undefined` on success.
|
|
143
|
+
*
|
|
144
|
+
* Exit codes are part of the scripts' contract:
|
|
145
|
+
*
|
|
146
|
+
* - `diagnose_ipc_connection.py`: 0 ok, 1 unreachable, 2 `kipy` missing,
|
|
147
|
+
* 3 API version mismatch, 4 no board open.
|
|
148
|
+
* - every argparse script: 2 = rejected arguments (KiCad untouched).
|
|
149
|
+
* - anything else non-zero: a real KiCad/script failure.
|
|
150
|
+
*/
|
|
151
|
+
declare function classifyRun(run: ScriptRun): KicadError | undefined;
|
|
152
|
+
/** Convenience: run a script and return its semantic outcome. */
|
|
153
|
+
declare function invokeKicadScript(options: RunScriptOptions): Promise<{
|
|
154
|
+
ok: boolean;
|
|
155
|
+
run: ScriptRun;
|
|
156
|
+
error?: KicadError;
|
|
157
|
+
}>;
|
|
158
|
+
//#endregion
|
|
159
|
+
//#region src/tools.d.ts
|
|
160
|
+
/** Everything a tool needs to reach the bundled scripts. */
|
|
161
|
+
interface KicadToolEnv {
|
|
162
|
+
/** Directory holding the bundled Python scripts. */
|
|
163
|
+
scriptsDir: string;
|
|
164
|
+
/** Python interpreter with `kipy`. */
|
|
165
|
+
pythonPath: string;
|
|
166
|
+
config: KicadConfig;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* All KiCad tools contributed by this plugin.
|
|
170
|
+
*/
|
|
171
|
+
declare function createKicadTools(env: KicadToolEnv): ReturnType<typeof defineTool>[];
|
|
172
|
+
/**
|
|
173
|
+
* Names of every tool this plugin registers — asserted by the tests and used
|
|
174
|
+
* for startup logging.
|
|
175
|
+
*/
|
|
176
|
+
declare function kicadToolNames(): string[];
|
|
177
|
+
//#endregion
|
|
178
|
+
//#region src/paths.d.ts
|
|
179
|
+
/**
|
|
180
|
+
* Absolute path of the bundled `kicad-ipc` skill directory.
|
|
181
|
+
*
|
|
182
|
+
* Resolution order: an explicit override (config / `DSH_KICAD_SKILLS_DIR`),
|
|
183
|
+
* then the package-relative location.
|
|
184
|
+
*
|
|
185
|
+
* @param moduleUrl - `import.meta.url` of the calling module.
|
|
186
|
+
* @param override - explicit directory (plugin config or env var).
|
|
187
|
+
* @returns the resolved directory, whether or not it exists yet.
|
|
188
|
+
*/
|
|
189
|
+
declare function resolveSkillDir(moduleUrl: string, override?: string): string;
|
|
190
|
+
/**
|
|
191
|
+
* Resolve the skill directory and assert the skill is actually present.
|
|
192
|
+
*
|
|
193
|
+
* @throws when `SKILL.md` is missing — this is a packaging failure, not a
|
|
194
|
+
* runtime condition, so it must be loud rather than silently degraded.
|
|
195
|
+
*/
|
|
196
|
+
declare function requireSkillDir(moduleUrl: string, override?: string): string;
|
|
197
|
+
/** Absolute path of the bundled Python script directory. */
|
|
198
|
+
declare function scriptsDir(skillDir: string): string;
|
|
199
|
+
//#endregion
|
|
200
|
+
//#region src/index.d.ts
|
|
201
|
+
/** Plugin id — matches package.json. */
|
|
202
|
+
declare const name = "@huaqiu/dsh-kicad";
|
|
203
|
+
/**
|
|
204
|
+
* Cordis services this half depends on.
|
|
205
|
+
*
|
|
206
|
+
* `skills` is REQUIRED: it is the DSH runtime's skill registry, and registering
|
|
207
|
+
* the bundled `kicad-ipc` skill is this plugin's core job. Without the inject,
|
|
208
|
+
* `apply()`'s `ctx.skills` access would throw
|
|
209
|
+
* `cannot get property "skills" without inject`.
|
|
210
|
+
*
|
|
211
|
+
* `tools` is the DSH node runtime tool registry used for the KiCad tools.
|
|
212
|
+
*
|
|
213
|
+
* Note what is NOT here: `hqEdge`. Unlike `@huaqiu/dsh-eda-host`, this plugin
|
|
214
|
+
* talks to KiCad directly, so it must never depend on the edge bridge.
|
|
215
|
+
*/
|
|
216
|
+
declare const inject: readonly ["skills", "tools"];
|
|
217
|
+
/**
|
|
218
|
+
* The `skills` service as this plugin uses it.
|
|
219
|
+
*
|
|
220
|
+
* `@deepseek-ai/dsh-tools` already augments `Context` with `tools`, but nothing
|
|
221
|
+
* in this workspace augments `skills` — `@deepseek-ai/dsh-skill` is a runtime
|
|
222
|
+
* dependency of the harness, not of this package (we never import it; the
|
|
223
|
+
* service arrives through Cordis injection). Declaring the shape we consume is
|
|
224
|
+
* the same technique `@huaqiu/dsh-eda-host` uses for `hqEdge`.
|
|
225
|
+
*/
|
|
226
|
+
interface SkillRegistration {
|
|
227
|
+
/** Skill id — must match `/^[a-z0-9]+(?:-[a-z0-9]+)*$/` to be discoverable. */
|
|
228
|
+
name: string;
|
|
229
|
+
/** Catalog description shown to the model. */
|
|
230
|
+
description: string;
|
|
231
|
+
/** Full SKILL.md body. */
|
|
232
|
+
content: string;
|
|
233
|
+
/** Where `references/` and `scripts/` live for progressive disclosure. */
|
|
234
|
+
resourceBase: {
|
|
235
|
+
kind: 'directory';
|
|
236
|
+
path: string;
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
declare module '@deepseek-ai/cordis' {
|
|
240
|
+
interface Context {
|
|
241
|
+
/** DSH skill registry, provided by the `@deepseek-ai/dsh-skill` service. */
|
|
242
|
+
skills: {
|
|
243
|
+
/** Register a plugin-bundled skill; returns its unregister disposer. */
|
|
244
|
+
register(skill: SkillRegistration): () => void;
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Extract the `description` field from SKILL.md YAML frontmatter.
|
|
250
|
+
*
|
|
251
|
+
* Only the single-line form is supported (quoted or bare), which is what the
|
|
252
|
+
* migrated skill uses. Returns `undefined` when absent so the caller can fall
|
|
253
|
+
* back rather than registering a skill with an empty description — DSH ignores
|
|
254
|
+
* frontmatter-less skills entirely, so an empty description would silently
|
|
255
|
+
* break discovery.
|
|
256
|
+
*/
|
|
257
|
+
declare function skillDescription(markdown: string): string | undefined;
|
|
258
|
+
/**
|
|
259
|
+
* Read the bundled `kicad-ipc` SKILL.md.
|
|
260
|
+
*
|
|
261
|
+
* Exposed for tests and for callers that want the skill body without loading
|
|
262
|
+
* the plugin (e.g. a packaging check).
|
|
263
|
+
*/
|
|
264
|
+
declare function readBundledSkill(moduleUrl: string, override?: string): {
|
|
265
|
+
dir: string;
|
|
266
|
+
name: string;
|
|
267
|
+
description: string;
|
|
268
|
+
content: string;
|
|
269
|
+
};
|
|
270
|
+
/**
|
|
271
|
+
* Host plugin body — register the `kicad-ipc` skill and the KiCad tools.
|
|
272
|
+
*
|
|
273
|
+
* Both halves are registered here so that one installation delivers both. The
|
|
274
|
+
* skill's `resourceBase` points at the bundled skill directory, which is how
|
|
275
|
+
* the agent reaches `references/ipc-pcb-workflows.md` and `scripts/` as
|
|
276
|
+
* progressive-disclosure resources.
|
|
277
|
+
*
|
|
278
|
+
* @param ctx - real cordis context (node side).
|
|
279
|
+
* @param config - plugin overlay config (python interpreter, timeouts).
|
|
280
|
+
* @returns disposer — unregisters the skill and the tools on plugin dispose.
|
|
281
|
+
*/
|
|
282
|
+
declare function apply(ctx: Context, config?: KicadConfigInput): () => void;
|
|
283
|
+
//#endregion
|
|
284
|
+
export { KICAD_SCRIPTS, KICAD_SCRIPT_IDS, KICAD_SKILL_NAME, type KicadConfig, type KicadConfigInput, type KicadError, type KicadErrorKind, type KicadScript, type ScriptEffect, type ScriptRun, SkillRegistration, apply, classifyRun, createKicadTools, inject, invokeKicadScript, kicadScript, kicadToolNames, name, readBundledSkill, requireSkillDir, resolveSkillDir, runKicadScript, scriptsDir, skillDescription };
|