dsh-jira-tasks 1.2.0 → 1.3.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/README.en.md +55 -12
- package/README.md +55 -12
- package/package.json +13 -2
package/README.en.md
CHANGED
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
Shows the current JIRA project's **open / reopened** issues **assigned to the current user** below the DSH composer input. The JIRA base URL and token are configured in **Settings → JIRA 配置** (the settings dialog's left navigation) (`JIRA_BASE_URL` / `JIRA_API_TOKEN` act as fallback); the project key and JQL are **configured per workspace** and persisted.
|
|
8
8
|
|
|
9
|
-
> **DSH
|
|
9
|
+
> **DSH versions targeted: 0.1.7 and 0.2.0 (verified on `0.1.7-rc.2` and `0.2.0-rc.2`), on both the browser (web profile) and the Desktop app (the Electron-owned desktop profile).**
|
|
10
|
+
> The client slots `conversation.input.dock` / `plugins.item` / `settings.section`, the settings service `ctx.configForms` (namespace = profile entry id `jira-tasks`), and the `ctx.effect` / `configForms.whileServed` disposal contracts are unchanged between 0.1.7 and 0.2.0 (verified package by package), so one `lib/` covers both; the 0.1.6-era `settingsScope` / `settings.register` / `settings.plugin.item` APIs are gone and no longer used.
|
|
11
|
+
> The package declares its DSH range as `>=0.1.7-rc.2 <0.3.0-0` (`engines.dsh` plus an optional `@deepseek-ai/dsh` peer): since 0.2.0 DSH checks that range **on install and on profile startup**, skipping a mismatched bundle and offering the exact-version `allow-version` exemption in the plugin manager. The peer is marked `optional` so `pnpm` never pulls the whole `@deepseek-ai/dsh` tree into the profile.
|
|
10
12
|
|
|
11
13
|
## Features
|
|
12
14
|
|
|
@@ -21,7 +23,7 @@ Shows the current JIRA project's **open / reopened** issues **assigned to the cu
|
|
|
21
23
|
|
|
22
24
|
## Install
|
|
23
25
|
|
|
24
|
-
Published to npm
|
|
26
|
+
Published to npm. For the **browser (web profile)**:
|
|
25
27
|
|
|
26
28
|
```bash
|
|
27
29
|
dsh plugin --profile web add dsh-jira-tasks
|
|
@@ -35,19 +37,35 @@ dsh plugin --profile web add github:liu3734/jira-tasks-dsh-plugin
|
|
|
35
37
|
|
|
36
38
|
**Restart DSH** to activate.
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
### Desktop app (DeepSeek Harness.app)
|
|
41
|
+
|
|
42
|
+
The Desktop app does not use the `web` profile; it boots the Electron-owned **`desktop` profile** (`~/.dsh/profiles/desktop/`). That profile name is reserved: an npm-installed `dsh` **refuses** both boot and plugin operations for `--profile desktop` (`profile "desktop" is managed exclusively by the Electron application`). Use the Desktop-provided command instead:
|
|
43
|
+
|
|
44
|
+
1. Open the Desktop app once (it initializes the desktop profile), then **quit it completely**
|
|
45
|
+
2. In the app menu, open **Manage dsh Command** → Install (puts the Desktop's own `dsh` on your PATH)
|
|
46
|
+
3. Install the plugin:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
dsh plugin --profile desktop add dsh-jira-tasks
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
4. Confirm `"dsh-jira-tasks"` is listed in `dsh.profile.bundles` of `~/.dsh/profiles/desktop/package.json`, then start the Desktop app
|
|
53
|
+
|
|
54
|
+
> The renderer's origin is `dsh-app://app`. Electron forwards every non-static request to the local Host with its cookie, so the plugin's absolute-path `fetch("/jira/api/search")` keeps working; `target="_blank"` issue links are handed to the system browser. The project key / JQL live in that origin's localStorage, so **they are separate from the browser configuration at `http://127.0.0.1:<port>`** — configure each surface once.
|
|
55
|
+
|
|
56
|
+
> **Nothing shows up? Check `dsh.profile.bundles` first.** DSH mounts this package as a profile layer only when `"dsh-jira-tasks"` is listed in `dsh.profile.bundles` of that profile's `package.json` (`~/.dsh/profiles/web/package.json` or `~/.dsh/profiles/desktop/package.json`); being in `dependencies` alone is not enough — the startup log then prints `patch: entry "jira-tasks" not found` and the plugin silently never loads. `dsh plugin --profile <name> add` normally appends that row, but it will not re-append when the package is already a dependency; add `"dsh-jira-tasks"` to `dsh.profile.bundles` by hand.
|
|
39
57
|
|
|
40
58
|
> Using GitHub Packages instead: configure `@liu3734:registry=https://npm.pkg.github.com/` plus a read token in the profile's `.npmrc`, then run `dsh plugin --profile web add @liu3734/dsh-jira-tasks`.
|
|
41
59
|
|
|
42
60
|
<details>
|
|
43
61
|
<summary>Manual install (without npm)</summary>
|
|
44
62
|
|
|
45
|
-
1. Copy this repository (its root is the package directory)
|
|
46
|
-
2. Edit
|
|
63
|
+
1. Copy this repository (its root is the package directory) into the profile's `packages/dsh-jira-tasks/` (`~/.dsh/profiles/web/` for the browser, `~/.dsh/profiles/desktop/` for the Desktop app; skip `.git/`)
|
|
64
|
+
2. Edit that profile's `package.json`:
|
|
47
65
|
- Add to `dependencies`: `"dsh-jira-tasks": "file:./packages/dsh-jira-tasks"`
|
|
48
66
|
- Append to `dsh.profile.bundles`: `"dsh-jira-tasks"`
|
|
49
67
|
3. Run `pnpm install` in the profile directory
|
|
50
|
-
4. Restart DSH
|
|
68
|
+
4. Restart DSH (the Desktop app must be fully quit and reopened)
|
|
51
69
|
|
|
52
70
|
> Note: `pnpm install` **copies** the package into `node_modules/` (not a symlink) — after editing sources, sync `node_modules/dsh-jira-tasks` or re-run install.
|
|
53
71
|
</details>
|
|
@@ -109,10 +127,33 @@ project = "{projectKey}" AND status in ("开启", "重新开启") AND assignee =
|
|
|
109
127
|
|
|
110
128
|
> The status names follow the Chinese workflow (`开启`/`重新开启`). For English statuses (Open/Reopened), set a custom JQL in ⚙.
|
|
111
129
|
|
|
130
|
+
## Compatibility & verification
|
|
131
|
+
|
|
132
|
+
| Dimension | Coverage |
|
|
133
|
+
|---|---|
|
|
134
|
+
| DSH versions | `0.1.7-rc.2` and `0.2.0-rc.2` (verified); declared range `>=0.1.7-rc.2 <0.3.0-0` — the 0.1.7 and 0.2.x lines, excluding 0.3.0 and its prereleases |
|
|
135
|
+
| Surfaces | Browser (`dsh web` / web profile) and the Desktop app (Electron, desktop profile, renderer origin `dsh-app://app`) |
|
|
136
|
+
| Host APIs | `Config` / `webServer.register` / `subprocess.spawn` / `credentials.resolve` / `settings.configure` — signatures unchanged from 0.1.7 to 0.2.0 |
|
|
137
|
+
| Client APIs | `window.__ModuleLoader__.load`, `slots.inject/register`, `configForms.get/whileServed`, `remote.credentials`, slots `conversation.input.dock` / `plugins.item` / `settings.section` — contracts unchanged from 0.1.7 to 0.2.0 |
|
|
138
|
+
|
|
139
|
+
How it was verified (a throwaway `DSH_HOME`, the user's own profile untouched):
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Boot the target dsh in isolation; the profile's dsh.profile.bundles lists dsh-jira-tasks
|
|
143
|
+
DSH_HOME=/tmp/dsh-check node <dsh-0.2.0-rc.2>/lib/bin.js --profile web --no-open --port 19399
|
|
144
|
+
|
|
145
|
+
curl -sX POST http://127.0.0.1:19399/jira/api/test -d '{}' # connectivity / auth
|
|
146
|
+
curl -sX POST http://127.0.0.1:19399/jira/api/search -d '{"projectKey":"<KEY>"}' # issue query
|
|
147
|
+
curl -s "http://127.0.0.1:19399/?token=<token from the startup log>" | grep -o dsh-jira-tasks # client bundle in __DSH_BOOT__
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
For the Desktop app additionally confirm the client bundle appears in the app's `Code Cache` (the renderer loaded and executed it) and that `dsh.jiraTasks.config.v1` exists in its `localStorage` (the panel works and writes per workspace).
|
|
151
|
+
|
|
112
152
|
## Uninstall
|
|
113
153
|
|
|
114
154
|
```bash
|
|
115
|
-
dsh plugin --profile web remove dsh-jira-tasks
|
|
155
|
+
dsh plugin --profile web remove dsh-jira-tasks # browser
|
|
156
|
+
dsh plugin --profile desktop remove dsh-jira-tasks # Desktop app (needs the Desktop-provided dsh)
|
|
116
157
|
```
|
|
117
158
|
|
|
118
159
|
## Troubleshooting
|
|
@@ -145,10 +186,11 @@ JIRA_TASKS_TOKEN (settings card) > JIRA_API_TOKEN > JIRA_TOKEN
|
|
|
145
186
|
<details>
|
|
146
187
|
<summary>Panel does not appear</summary>
|
|
147
188
|
|
|
148
|
-
- Make sure it is installed and DSH was **restarted
|
|
149
|
-
- Check
|
|
150
|
-
- Check the DSH startup log: `patch: entry "jira-tasks" not found` means the profile layer was never composed; `webserver: duplicate exact route` means a route was registered twice (the plugin releases its routes through `ctx.effect`, so this points at a second copy)
|
|
151
|
-
- A
|
|
189
|
+
- Make sure it is installed and DSH was **restarted** (the Desktop app must be fully quit and reopened); in new sessions the panel sits below the input
|
|
190
|
+
- Check `dsh.profile.bundles` in the right profile: `~/.dsh/profiles/web/package.json` for the browser, **`~/.dsh/profiles/desktop/package.json` for the Desktop app** (the most common cause of a silent no-show — see the Install note; that profile can only be edited with the Desktop-provided `dsh`)
|
|
191
|
+
- Check the DSH startup log: `patch: entry "jira-tasks" not found` means the profile layer was never composed; `Plugin dsh-jira-tasks@<version> is incompatible with dsh <runtime>` means the running version falls outside the declared `>=0.1.7-rc.2 <0.3.0-0` range, so the bundle is skipped (follow the message, using `dsh plugin allow-version` or the plugin manager, to grant the exact-version exemption); `webserver: duplicate exact route` means a route was registered twice (the plugin releases its routes through `ctx.effect`, so this points at a second copy)
|
|
192
|
+
- A console error `client-modules: could not load "dsh-jira-tasks"` means `/plugins/dsh-jira-tasks/client.js` was not served — confirm `exports["./client"]` resolves to the built `lib/client.js`
|
|
193
|
+
- The Desktop panel says "unconfigured" although you configured it: project key / JQL are stored per **origin**, so `dsh-app://app` (the built-in window) and `http://127.0.0.1:<port>` (a browser) hold two independent configurations
|
|
152
194
|
</details>
|
|
153
195
|
|
|
154
196
|
## Architecture & Implementation Details
|
|
@@ -168,8 +210,9 @@ JIRA_TASKS_TOKEN (settings card) > JIRA_API_TOKEN > JIRA_TOKEN
|
|
|
168
210
|
└──────────────────────────────────────────────┘ └────────────────────────────────────┘
|
|
169
211
|
|
|
170
212
|
- **Host**: declares the entry's own `Config` (`baseUrl`, `volatile` — since DSH 0.1.5 a settings page is built from it; `settings.configure({ auto: false }, ctx.fiber)` turns the auto-generated page off and hands its disposer back to `ctx.effect`) plus `webServer` routes `POST /jira/api/search` and `POST /jira/api/test`, each wrapped in its own `ctx.effect` (a reload otherwise hits "duplicate route" and fails activation; non-POST requests get 405); the token comes from the `credentials` service resolved in the order `JIRA_TASKS_TOKEN` (written by the Settings card) → `JIRA_API_TOKEN` → `JIRA_TOKEN` (`$DSH_HOME/.credentials.yaml` / environment, hot-reloaded), so a saved card token overrides the environment; queries run through `subprocess` spawning `curl` directly, with the auth header passed via stdin (`--config -`) so the token never appears in argv.
|
|
171
|
-
- **Client**: a standard `window.__ModuleLoader__.load({ id, factory })` web bundle requiring only `"react"`; registers **only `conversation.input.dock`** (`order: 10`) — that seat renders in both new and active sessions and is a full-width row of `composerStack` (`flex-direction: column`), where the panel's own CSS `order: 99` places it below the input card at the card's width. `conversation.composer.dock` is deliberately NOT used: in 0.1.7
|
|
213
|
+
- **Client**: a standard `window.__ModuleLoader__.load({ id, factory })` web bundle requiring only `"react"`; registers **only `conversation.input.dock`** (`order: 10`) — that seat renders in both new and active sessions and is a full-width row of `composerStack` (`flex-direction: column`), where the panel's own CSS `order: 99` places it below the input card at the card's width. `conversation.composer.dock` is deliberately NOT used: in 0.1.7 and 0.2.0 alike that seat renders into InputBar's `.dock` **row**, side by side with the context meter, so a full-width panel there gets its right-hand content covered by the meter. The address/token form comes from `ctx.configForms.get("jira-tasks")` and the token is written through `remote.credentials` to `JIRA_TASKS_TOKEN`; `configForms.whileServed` keeps it hidden when the host serves no such namespace. It is registered in **two places**: the Plugins-panel card `plugins.item` (`id: "jira-tasks"`, `order: 41`) and a Settings-navigation section `settings.section` (`id: "jira-tasks"`, `order: 30` — above Agent presets' 20, so it sits below it; `label: "JIRA 配置"`; ids outside the shell's `navIcon` allow-list fall back to the default gear icon). Both share one `JiraSettingsPage`, whose outer container is chosen by the external `variant: "page"` prop (`li.jt-set-card` card vs `div.jt-set-page` page) while the field block is the same array. The card's `summary` view is rendered by a dispatcher that calls **no hooks**, while the form lives in a separate `JiraSettingsPage`, so flipping `view` on one mounted instance never changes its hook count.
|
|
172
214
|
- **Why not the `shell` service**: `shell` wraps commands with `sandbox-exec`, which is broken on some macOS versions (`sandbox_apply: Operation not permitted`); `subprocess` is the raw process seam without this issue.
|
|
215
|
+
- **Why the Desktop app needs no code branch**: its Host is the same DSH as the web profile (same `@deepseek-ai/dsh-web-app` + `dsh-host-webserver`); only the renderer origin differs (`dsh-app://app`), and Electron's `protocol.handle` forwards every non-static request to the local Host with its cookie, so both `fetch("/jira/api/*")` and `/plugins/...` work. `http(s)` `target="_blank"` links are handed to the system browser by the main window's `setWindowOpenHandler`. The only difference that matters is origin-scoped localStorage, so each surface keeps its own project key / JQL.
|
|
173
216
|
- **One registration covers both states**: `conversation.input.dock` renders whenever a session and its input exist, so new and active sessions need no separate registrations (the older `composer.dock` + blank-session de-duplication was both unnecessary under 0.1.7 and the cause of the meter-row collision).
|
|
174
217
|
|
|
175
218
|
**Differences from the dynamic version**
|
package/README.md
CHANGED
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
在 DSH 会话**输入框下方**展示当前 JIRA 项目**指派给当前用户**的「开启 / 重新开启」任务列表。JIRA 地址与令牌在**设置 → JIRA 配置**(设置对话框左侧导航)中配置(`JIRA_BASE_URL` / `JIRA_API_TOKEN` 作为回退);项目 Key 与 JQL **按工作区配置**并持久化。
|
|
8
8
|
|
|
9
|
-
> **适配的 DSH 版本:0.1.7(`0.1.7-rc.2
|
|
9
|
+
> **适配的 DSH 版本:0.1.7 与 0.2.0(`0.1.7-rc.2`、`0.2.0-rc.2` 实测),浏览器(web profile)与桌面端(Electron 独占的 desktop profile)通用。**
|
|
10
|
+
> 客户端槽位 `conversation.input.dock` / `plugins.item` / `settings.section`、设置服务 `ctx.configForms`(命名空间 = profile 条目 id `jira-tasks`)、`ctx.effect` / `configForms.whileServed` 的注销契约在 0.1.7 → 0.2.0 之间没有变化(逐包 diff 过),所以同一份 `lib/` 同时覆盖两版;0.1.6 及更早版本的 `settingsScope` / `settings.register` / `settings.plugin.item` 已不再使用。
|
|
11
|
+
> 包内声明了 DSH 兼容范围 `>=0.1.7-rc.2 <0.3.0-0`(`engines.dsh` + 可选 peer `@deepseek-ai/dsh`):0.2.0 起 DSH 会在**安装与启动**时校验该范围,不满足的版本会被跳过并在插件管理器里给出 `allow-version` 精确豁免入口(peer 标了 `optional`,`pnpm` 不会把整套 `@deepseek-ai/dsh` 装进 profile)。
|
|
10
12
|
|
|
11
13
|
## 功能
|
|
12
14
|
|
|
@@ -30,7 +32,7 @@
|
|
|
30
32
|
|
|
31
33
|
## 安装
|
|
32
34
|
|
|
33
|
-
包已发布到公共 npm(`dsh-jira-tasks`);仓库的发布工作流同时把同一版本发布到 GitHub Packages(作用域包名 `@liu3734/dsh-jira-tasks
|
|
35
|
+
包已发布到公共 npm(`dsh-jira-tasks`);仓库的发布工作流同时把同一版本发布到 GitHub Packages(作用域包名 `@liu3734/dsh-jira-tasks`)。**浏览器(web profile)**从 npm 安装(推荐):
|
|
34
36
|
|
|
35
37
|
```bash
|
|
36
38
|
dsh plugin --profile web add dsh-jira-tasks
|
|
@@ -44,19 +46,35 @@ dsh plugin --profile web add github:liu3734/jira-tasks-dsh-plugin
|
|
|
44
46
|
|
|
45
47
|
**重启 DSH** 后生效。
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
### 桌面端(DeepSeek Harness.app)
|
|
50
|
+
|
|
51
|
+
桌面端不用 `web` profile,而是 Electron 独占的 **`desktop` profile**(`~/.dsh/profiles/desktop/`)。该 profile 名被应用保留:**npm 全局安装的 `dsh` 会直接拒绝** `--profile desktop` 的 boot 与 plugin 操作(`profile "desktop" is managed exclusively by the Electron application`),必须用桌面端自带的命令:
|
|
52
|
+
|
|
53
|
+
1. 先打开一次桌面端(由应用初始化 desktop profile),然后**完全退出桌面端**
|
|
54
|
+
2. 应用内菜单 → **管理 dsh 命令 / Manage dsh Command** → Install,把桌面端自带的 `dsh` 装进 PATH
|
|
55
|
+
3. 安装插件:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
dsh plugin --profile desktop add dsh-jira-tasks
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
4. 确认 `~/.dsh/profiles/desktop/package.json` 的 `dsh.profile.bundles` 里有 `"dsh-jira-tasks"`,再启动桌面端
|
|
62
|
+
|
|
63
|
+
> 桌面端渲染进程的 origin 是 `dsh-app://app`。非静态资源的请求由 Electron 转发到本机 Host,所以插件的 `fetch("/jira/api/search")` 这类绝对路径照常可用;任务链接的 `target="_blank"` 由 Electron 交给系统浏览器打开。项目 Key / JQL 存在该 origin 的 localStorage 里,**与浏览器访问 `http://127.0.0.1:<port>` 时的配置互不相通**,两边各配一次即可。
|
|
64
|
+
|
|
65
|
+
> **装完没反应?先查 `dsh.profile.bundles`。** DSH 只有当对应 profile 的 `package.json`(`~/.dsh/profiles/web/package.json` 或 `~/.dsh/profiles/desktop/package.json`)里的 `dsh.profile.bundles` 列了 `"dsh-jira-tasks"` 时才把本包当作 profile 层挂载;只出现在 `dependencies` 里不够——此时启动日志会打 `patch: entry "jira-tasks" not found`,插件静默不加载。`dsh plugin --profile <name> add` 一般会补上这一行,但该包已在 `dependencies` 中时重装不会重新补,手动往 `dsh.profile.bundles` 追加 `"dsh-jira-tasks"` 即可。
|
|
48
66
|
|
|
49
67
|
> 若改用 GitHub Packages 源:先在 profile 的 `.npmrc` 配置 `@liu3734:registry=https://npm.pkg.github.com/` 及读取令牌,再执行 `dsh plugin --profile web add @liu3734/dsh-jira-tasks`。
|
|
50
68
|
|
|
51
69
|
<details>
|
|
52
70
|
<summary>手动安装(不使用 npm)</summary>
|
|
53
71
|
|
|
54
|
-
1. 将本仓库(仓库根目录即包目录)复制为
|
|
55
|
-
2.
|
|
72
|
+
1. 将本仓库(仓库根目录即包目录)复制为 profile 内的 `packages/dsh-jira-tasks/`(可忽略 `.git/`)——web 用 `~/.dsh/profiles/web/`,桌面端用 `~/.dsh/profiles/desktop/`
|
|
73
|
+
2. 编辑该 profile 的 `package.json`:
|
|
56
74
|
- `dependencies` 增加:`"dsh-jira-tasks": "file:./packages/dsh-jira-tasks"`
|
|
57
75
|
- `dsh.profile.bundles` 追加:`"dsh-jira-tasks"`
|
|
58
76
|
3. 在 profile 目录执行 `pnpm install`
|
|
59
|
-
4. 重启 DSH
|
|
77
|
+
4. 重启 DSH(桌面端需完全退出后重新打开)
|
|
60
78
|
|
|
61
79
|
> 注:`pnpm install` 会把包**复制**到 `node_modules/`(非符号链接),改动源码后需同步 `node_modules/dsh-jira-tasks` 或重跑 install。
|
|
62
80
|
</details>
|
|
@@ -118,10 +136,33 @@ project = "{projectKey}" AND status in ("开启", "重新开启") AND assignee =
|
|
|
118
136
|
|
|
119
137
|
> 状态名按中文工作流("开启"/"重新开启")配置;若 JIRA 用英文状态(Open/Reopened),在 ⚙ 中填写自定义 JQL 即可。
|
|
120
138
|
|
|
139
|
+
## 兼容性与验证
|
|
140
|
+
|
|
141
|
+
| 维度 | 覆盖 |
|
|
142
|
+
|---|---|
|
|
143
|
+
| DSH 版本 | `0.1.7-rc.2`、`0.2.0-rc.2`(实测);声明范围 `>=0.1.7-rc.2 <0.3.0-0`,即 0.1.7 与 0.2.x,不含 0.3.0 及其预发布 |
|
|
144
|
+
| 运行形态 | 浏览器(`dsh web` / web profile)、桌面端 DeepSeek Harness.app(Electron,desktop profile,渲染进程 origin `dsh-app://app`) |
|
|
145
|
+
| 宿主侧 | `Config` / `webServer.register` / `subprocess.spawn` / `credentials.resolve` / `settings.configure`:0.1.7 → 0.2.0 签名未变 |
|
|
146
|
+
| 客户端 | `window.__ModuleLoader__.load`、`slots.inject/register`、`configForms.get/whileServed`、`remote.credentials`、槽位 `conversation.input.dock` / `plugins.item` / `settings.section`:0.1.7 → 0.2.0 契约未变 |
|
|
147
|
+
|
|
148
|
+
验证方式(不改动用户 profile,临时 `DSH_HOME` 起真实服务):
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# 用目标版本的 dsh 起一个隔离实例,profile 的 dsh.profile.bundles 含 dsh-jira-tasks
|
|
152
|
+
DSH_HOME=/tmp/dsh-check node <dsh-0.2.0-rc.2>/lib/bin.js --profile web --no-open --port 19399
|
|
153
|
+
|
|
154
|
+
curl -sX POST http://127.0.0.1:19399/jira/api/test -d '{}' # 连通性 / 鉴权
|
|
155
|
+
curl -sX POST http://127.0.0.1:19399/jira/api/search -d '{"projectKey":"<KEY>"}' # 任务查询
|
|
156
|
+
curl -s "http://127.0.0.1:19399/?token=<启动日志里的 token>" | grep -o dsh-jira-tasks # 客户端进入 __DSH_BOOT__ 模块图
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
桌面端另需确认:客户端 bundle 出现在应用 `Code Cache`(说明浏览器端已加载执行)、`localStorage` 里存在 `dsh.jiraTasks.config.v1`(说明面板可用且按工作区写入)。
|
|
160
|
+
|
|
121
161
|
## 卸载
|
|
122
162
|
|
|
123
163
|
```bash
|
|
124
|
-
dsh plugin --profile web remove dsh-jira-tasks
|
|
164
|
+
dsh plugin --profile web remove dsh-jira-tasks # 浏览器
|
|
165
|
+
dsh plugin --profile desktop remove dsh-jira-tasks # 桌面端(需桌面端自带的 dsh 命令)
|
|
125
166
|
```
|
|
126
167
|
|
|
127
168
|
## 常见问题
|
|
@@ -157,10 +198,11 @@ JIRA_TASKS_TOKEN(设置页) > JIRA_API_TOKEN > JIRA_TOKEN
|
|
|
157
198
|
<details>
|
|
158
199
|
<summary>面板不显示</summary>
|
|
159
200
|
|
|
160
|
-
- 确认已安装并**重启 DSH
|
|
161
|
-
-
|
|
162
|
-
- 检查 DSH 启动日志:出现 `patch: entry "jira-tasks" not found` 即为 profile 层未挂载;出现 `webserver: duplicate exact route` 说明同一路由被注册了两次(插件自身已用 `ctx.effect` 释放旧路由,若仍有说明有第二份副本)
|
|
163
|
-
-
|
|
201
|
+
- 确认已安装并**重启 DSH**(桌面端要完全退出应用再打开);新会话面板位于输入框下方
|
|
202
|
+
- 检查对应 profile 的 `dsh.profile.bundles` 是否包含 `"dsh-jira-tasks"`:浏览器看 `~/.dsh/profiles/web/package.json`,**桌面端看 `~/.dsh/profiles/desktop/package.json`**(最常见的漏装原因,见「安装」一节的提示;桌面端该 profile 只能用应用自带的 dsh 命令改)
|
|
203
|
+
- 检查 DSH 启动日志:出现 `patch: entry "jira-tasks" not found` 即为 profile 层未挂载;出现 `Plugin dsh-jira-tasks@<版本> is incompatible with dsh <运行版本>` 说明运行版本落在声明范围 `>=0.1.7-rc.2 <0.3.0-0` 之外,该包会被跳过(可按提示用 `dsh plugin allow-version` 或插件管理器授精确版本豁免);出现 `webserver: duplicate exact route` 说明同一路由被注册了两次(插件自身已用 `ctx.effect` 释放旧路由,若仍有说明有第二份副本)
|
|
204
|
+
- 浏览器 / 桌面端控制台若报 `client-modules: could not load "dsh-jira-tasks"`,说明 `/plugins/dsh-jira-tasks/client.js` 没取到——确认 `package.json` 的 `exports["./client"]` 指向已构建的 `lib/client.js`
|
|
205
|
+
- 桌面端面板显示「未配置」但你记得配过:项目 Key / JQL 按 **origin** 存 localStorage,`dsh-app://app`(桌面端内置窗口)与 `http://127.0.0.1:<port>`(浏览器)是两份独立配置
|
|
164
206
|
</details>
|
|
165
207
|
|
|
166
208
|
## 架构与实现细节
|
|
@@ -181,8 +223,9 @@ JIRA_TASKS_TOKEN(设置页) > JIRA_API_TOKEN > JIRA_TOKEN
|
|
|
181
223
|
```
|
|
182
224
|
|
|
183
225
|
- **Host**:声明条目自身的 `Config`(`baseUrl`,`volatile`,DSH 0.1.5 起设置页的表单直接来自它;`settings.configure({ auto: false }, ctx.fiber)` 关掉自动生成页,并把返回的注销函数交回 `ctx.effect`)与 `webServer` 路由 `POST /jira/api/search`、`POST /jira/api/test`(两条路由各自包在 `ctx.effect` 里,卸载/重载时先释放,否则重挂载会撞上「重复路由」直接抛错;非 POST 返回 405);令牌经 `credentials` 服务按 `JIRA_TASKS_TOKEN`(设置页写入)→ `JIRA_API_TOKEN` → `JIRA_TOKEN` 的顺序解析(`$DSH_HOME/.credentials.yaml` / 环境变量,热加载),因此设置页保存的令牌能覆盖环境变量;查询用 `subprocess` 直接 `spawn curl`,认证头经 stdin(`--config -`)传入,令牌不进入命令行参数。
|
|
184
|
-
- **Client**:`window.__ModuleLoader__.load({ id, factory })` 标准 web bundle,仅 `require("react")`;**只注册 `conversation.input.dock` 一处**(`order: 10`)。该槽位在新会话与活跃会话下都会渲染,属于 `composerStack`(`flex-direction: column`)的整宽纵向行;面板元素自身 `flex order: 99` 排到输入卡之后,即输入框下方,并以 `--dsh-composer-side-clearance` / `--dsh-composer-card-max-width` 与输入卡等宽。之所以不用 `conversation.composer.dock`:0.1.7
|
|
226
|
+
- **Client**:`window.__ModuleLoader__.load({ id, factory })` 标准 web bundle,仅 `require("react")`;**只注册 `conversation.input.dock` 一处**(`order: 10`)。该槽位在新会话与活跃会话下都会渲染,属于 `composerStack`(`flex-direction: column`)的整宽纵向行;面板元素自身 `flex order: 99` 排到输入卡之后,即输入框下方,并以 `--dsh-composer-side-clearance` / `--dsh-composer-card-max-width` 与输入卡等宽。之所以不用 `conversation.composer.dock`:0.1.7 / 0.2.0 里那一槽位都渲染进 InputBar 的 `.dock`**横向** flex 行,与上下文占用环并排,整宽面板会被占用环压住右侧内容。插件地址与令牌的表单来自 `ctx.configForms.get("jira-tasks")`(地址)与 `remote.credentials`(令牌写入 `JIRA_TASKS_TOKEN`),并用 `configForms.whileServed` 保证宿主未提供该命名空间时不显示。表单**注册在两处**:插件面板卡片 `plugins.item`(`id: "jira-tasks"`,`order: 41`,原入口保留)与设置对话框左侧导航项 `settings.section`(`id: "jira-tasks"`,`order: 30` —— 大于「Agent 预设」的 20,所以显示在它下方;`label: "JIRA 配置"`;未在 `navIcon` 白名单里的 id 由设置外壳回退成默认齿轮图标)。两者共用同一个 `JiraSettingsPage`:由外部 prop `variant: "page"` 决定外层容器(`li.jt-set-card` 卡片 / `div.jt-set-page` 整页),字段区是同一份数组。`plugins.item` 的摘要位由一个**不调用任何 hook** 的分发组件负责,表单在独立的 `JiraSettingsPage` 里,避免同一实例在 `view` 切换时改变 hook 数量。
|
|
185
227
|
- **为什么不用 `shell` 服务**:`shell` 会套 `sandbox-exec`,部分 macOS 上不可用(`sandbox_apply: Operation not permitted`);`subprocess` 是原始进程缝,无此问题。
|
|
228
|
+
- **桌面端为什么不用改代码**:桌面端 Host 与 web profile 是同一套 DSH(同样是 `@deepseek-ai/dsh-web-app` + `dsh-host-webserver`),渲染进程 origin 是 `dsh-app://app`,非静态资源请求由 Electron 的 `protocol.handle` 带上 Host cookie 转发到本机 Host,所以 `fetch("/jira/api/*")` 与 `/plugins/...` 都照常工作;`http(s)` 的 `target="_blank"` 由主窗口的 `setWindowOpenHandler` 交给系统浏览器。唯一差异是 localStorage 按 origin 隔离,配置需在桌面端与浏览器各存一份。
|
|
186
229
|
- **一处注册覆盖两种会话**:`conversation.input.dock` 只要有 session + input 就会渲染,新会话与活跃会话无需分别注册(旧版曾用 `composer.dock` + 空白判定去重,0.1.7 下既不必要、又会与占用环抢同一行)。
|
|
187
230
|
|
|
188
231
|
**与动态插件版的差异**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-jira-tasks",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "JIRA open tasks panel for DeepSeek Harness (DSH) 0.1.7: shows the current user's open/reopened issues below the composer, per-workspace project key, persistent profile bundle.",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "JIRA open tasks panel for DeepSeek Harness (DSH) 0.1.7 and 0.2.0, web and Desktop: shows the current user's open/reopened issues below the composer, per-workspace project key, persistent profile bundle.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -9,6 +9,17 @@
|
|
|
9
9
|
"./client": "./lib/client.js",
|
|
10
10
|
"./package.json": "./package.json"
|
|
11
11
|
},
|
|
12
|
+
"engines": {
|
|
13
|
+
"dsh": ">=0.1.7-rc.2 <0.3.0-0"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"@deepseek-ai/dsh": ">=0.1.7-rc.2 <0.3.0-0"
|
|
17
|
+
},
|
|
18
|
+
"peerDependenciesMeta": {
|
|
19
|
+
"@deepseek-ai/dsh": {
|
|
20
|
+
"optional": true
|
|
21
|
+
}
|
|
22
|
+
},
|
|
12
23
|
"dependencies": {
|
|
13
24
|
"@deepseek-ai/schemastery": "^3.18.2"
|
|
14
25
|
},
|