@zhangj1164/dsh-github-issue 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/README.i18n.yaml +6 -0
- package/README.md +115 -3
- package/README.zh.md +115 -0
- package/cordis.patch.yml +19 -0
- package/lib/client.d.ts +2 -0
- package/lib/client.js +1 -0
- package/lib/index.d.ts +198 -0
- package/lib/index.js +627 -0
- package/lib/invariant.d.ts +14 -0
- package/lib/invariant.js +19 -0
- package/lib/types.d.ts +137 -0
- package/lib/types.js +1 -0
- package/package.json +70 -6
package/README.i18n.yaml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Bilingual-pair consistency record: the git blob hash of each
|
|
2
|
+
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
|
+
# after editing either side, bring the other along and re-record with:
|
|
4
|
+
# pnpm run verify-translation-pairing --write packages/github-issue/dsh-github-issue/README.md
|
|
5
|
+
README.md: baeca3fc3ff4e7ddf76c99dbd493de6e5edaf176
|
|
6
|
+
README.zh.md: b3eaa79ec320c87c0fa68fa97fcf025fd958090a
|
package/README.md
CHANGED
|
@@ -1,3 +1,115 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# @zhangj1164/dsh-github-issue
|
|
2
|
+
|
|
3
|
+
English | [中文](README.zh.md)
|
|
4
|
+
|
|
5
|
+
GitHub issue generation and optimization service for DeepSeek Harness. Builds structured issue reports from telemetry analysis, constructs pre-filled issue-creation URLs, and optimizes natural-language issue descriptions with the configured model.
|
|
6
|
+
|
|
7
|
+
## Plugin
|
|
8
|
+
|
|
9
|
+
`GithubIssueService extends TypertRemoteService` with `static inject = ['llm']`. The service uses `ctx.get('llm')` for model calls and exposes three Remote methods callable by the client UI.
|
|
10
|
+
|
|
11
|
+
| Config | Default | Meaning |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `repoUrl` | `https://github.com/zhangj1164/dsh-mega-plugins` | Default repository URL for issue prefill when a request omits `repoUrl`. |
|
|
14
|
+
| `maxPrefillUrlLength` | `7000` | Longest pre-filled issue URL to produce, counted in characters. GitHub refuses a request URL that is too long and shows an error page instead of the new-issue form, and it publishes no stable constant for the boundary, so this carries headroom and is deployment-tunable. `0` disables shortening. |
|
|
15
|
+
| `prefillTruncationNote` | a Chinese note | Appended to the issue body when the URL had to be shortened, so the reader knows the body is partial. |
|
|
16
|
+
| `provider` | unset | Provider route for model calls. Unset follows the deployment's `agentDefaultModel` selection, so a deployment can pin issue generation from `cordis.yml` alone. |
|
|
17
|
+
| `model` | unset | Model id for model calls. Unset follows the same fallback as `provider`. |
|
|
18
|
+
|
|
19
|
+
## Remote methods
|
|
20
|
+
|
|
21
|
+
| Method | Behavior |
|
|
22
|
+
|---|---|
|
|
23
|
+
| `generateReport(request)` | Calls the model with a built-in structuring prompt to produce a uniform GitHub issue report from telemetry failure analysis. Returns a `GithubIssueReport` with title, body, and labels. The request names the `pluginIds` it covers — one report spans a whole suite — plus the analysis window and, per failure group, the route, the last failure time, and the attempts that followed it; the per-group facts are optional, and a missing one is passed to the model as `not recorded` rather than omitted. |
|
|
24
|
+
| `prefilledIssueUrl(request)` | Builds a pre-filled GitHub issue-creation URL from a report. Validates the repo URL; returns `invalid-url` on failure. Shortens the body when the composed URL would exceed `maxPrefillUrlLength`, which is a budget the title and labels also spend and percent-encoding inflates, so the check is on the URL rather than the body alone. |
|
|
25
|
+
| `optimizeIssue(request)` | Rewrites a natural-language description into a structured issue following a pinned Markdown template. Returns `empty-input` for blank descriptions, `route-missing` when no route resolves, `llm-failure` when the model call failed. |
|
|
26
|
+
|
|
27
|
+
## Model route
|
|
28
|
+
|
|
29
|
+
Both model-calling methods resolve their route the way the memo service does: the request's `provider`/`model`, then this service's `Config`, then the deployment's `agentDefaultModel` selection. The request fields are therefore optional, and the client UI sends them only when the user picked a model — the browser never has to publish a route for a call to work.
|
|
30
|
+
|
|
31
|
+
A blank value counts as absent rather than as a value, so an omitted field still reaches the deployment default instead of travelling to the model as an unusable route. When nothing resolves a route, the call returns `route-missing` and **no model call is attempted**: a call without an adapter cannot succeed, and reporting it as `llm-failure` would name the model for a routing problem.
|
|
32
|
+
|
|
33
|
+
## Failure facts
|
|
34
|
+
|
|
35
|
+
A failed call keeps what DSH reported instead of collapsing it into one message. `llm-failure` carries the machine-routing code and the route in its message — `model call to provider "custom" model "glm-5-2-260617" failed: NO_ADAPTER: no adapter registered for provider "custom"` — so `NO_ADAPTER` (a route this deployment never registered), `AUTH`, `RATE_LIMIT`, and `EMPTY_RESPONSE` (the model genuinely returned no text) stay distinguishable. Reporting all of them as "the model produced no output" is what sent a user hunting for a model problem in a request that never reached a model.
|
|
36
|
+
|
|
37
|
+
A stream that throws a transport error rather than yielding a terminal `finish` chunk becomes `LLM_STREAM_THREW`, not an exception escaping the call.
|
|
38
|
+
|
|
39
|
+
## Telemetry
|
|
40
|
+
|
|
41
|
+
Both model-calling methods report to the local telemetry service when the deployment has one, and behave identically when it does not. The service is read with `ctx.get('telemetry')` and deliberately **not** declared in `static inject`: this package installs on its own bundle, and a diagnostic dependency must never be the reason a service refuses to activate.
|
|
42
|
+
|
|
43
|
+
| Event | Recorded |
|
|
44
|
+
|---|---|
|
|
45
|
+
| A call that worked | Action `optimizeIssue` / `generateReport` as `success`, with the route that served it |
|
|
46
|
+
| A failed call | The preserved DSH code, message, and HTTP status, the route, and the `github-issue:<action>` feature anchor |
|
|
47
|
+
| A call with no resolvable route | Code `NO_MODEL_ROUTE` — the same code `@zhangj1164/dsh-memo` uses for that condition, so one report can group both packages |
|
|
48
|
+
|
|
49
|
+
`generateReport` also records which plugin's analysis it was given. Recording only successful calls would answer "which route served these calls" while leaving "has that route changed since it broke?" open, so both halves are recorded.
|
|
50
|
+
|
|
51
|
+
## Issue report template
|
|
52
|
+
|
|
53
|
+
Both `generateReport` and `optimizeIssue` use built-in system prompts that pin a uniform Markdown structure. The first line is always a `## ` heading used as the issue title. The template includes sections for plugin, action, expected/actual behavior, route and timing, and reproduction steps.
|
|
54
|
+
|
|
55
|
+
`generateReport` receives the analysis window and, per failure group, the route, the last failure time, and how many attempts of the same action followed it. Its system prompt requires those facts to be stated, forbids proposing a mechanism the analysis does not evidence — sampling parameters, token budgets, timeouts, chunking, and response parsing are named as examples — and requires a fact the analysis does not carry to be written as `not recorded`. Writing that collection must be added is explicitly ruled out: a missing fact can be an older event as easily as a gap, and the report cannot tell which.
|
|
56
|
+
|
|
57
|
+
## Requirement mapping
|
|
58
|
+
|
|
59
|
+
- **Req 8** — `generateReport` turns telemetry failure analysis into a uniform GitHub issue report that correlates each failure group against the plugin's feature code.
|
|
60
|
+
- **Req 9** — `prefilledIssueUrl` builds a pre-filled GitHub issue-creation URL so the user can jump to the project's new-issue page with the report already filled in.
|
|
61
|
+
- **Req 10** — Packaged as a standalone DSH plugin: this package declares its own `dsh.bundle` with `cordis.patch.yml`, so a deployment can install it on its own and any UI plugin can reach it. See "Adopting this plugin" below.
|
|
62
|
+
- **Req 11** — `optimizeIssue` rewrites a natural-language description into a structured issue using the configured model and a built-in structuring prompt. The `ui-memo` package calls this directly for its "Add Issue" editor.
|
|
63
|
+
- **Req 12** — Reusable: the issue report template, the prefill URL builder, and the optimization prompt are all generic and not memo-specific.
|
|
64
|
+
|
|
65
|
+
## Adopting this plugin
|
|
66
|
+
|
|
67
|
+
Install the package and add it to your deployment's composition:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
pnpm add @zhangj1164/dsh-github-issue
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```yaml
|
|
74
|
+
# your cordis.yml, or your own bundle's patch
|
|
75
|
+
- insert:
|
|
76
|
+
- id: github-issue
|
|
77
|
+
name: @zhangj1164/dsh-github-issue
|
|
78
|
+
config:
|
|
79
|
+
repoUrl: https://github.com/your-org/your-repo
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Read the service from any plugin with `ctx.get('githubIssue')`. It is optional from the consumer's side, so guard the read:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
const issues = ctx.get('githubIssue')
|
|
86
|
+
if (issues !== undefined) {
|
|
87
|
+
const { report } = await issues.generateReport({ analysis, repoUrl })
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The service has no dependency on `@zhangj1164/dsh-memo`; memo is one consumer among possible others.
|
|
92
|
+
|
|
93
|
+
This bundle is the sole owner of the `github-issue` entry id. `@zhangj1164/dsh-memo` injects the service but does not insert this row, so the standalone bundle and the memo suite compose without a conflict and `pnpm run verify-bundle-entries` finds no overlap. A memo deployment therefore names the whole suite:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
dsh plugin --profile web add @zhangj1164/dsh-telemetry @zhangj1164/dsh-github-issue @zhangj1164/dsh-memo @zhangj1164/dsh-client-ui-memo
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`@zhangj1164/dsh-github-issue` is named explicitly rather than pulled in as a peer: a profile sets `autoInstallPeers: false`, so an install brings in only what the command names, and `@zhangj1164/dsh-memo` alone would leave this row unresolvable.
|
|
100
|
+
|
|
101
|
+
## Exports
|
|
102
|
+
|
|
103
|
+
Every subpath resolves to the flat `lib/*.js` layout tsdown emits.
|
|
104
|
+
|
|
105
|
+
| Subpath | Contents |
|
|
106
|
+
|---|---|
|
|
107
|
+
| `@zhangj1164/dsh-github-issue` | The `GithubIssueService` plugin and its Config. |
|
|
108
|
+
| `@zhangj1164/dsh-github-issue/types` | Wire types: `GithubIssueReport`, request and result shapes. |
|
|
109
|
+
| `@zhangj1164/dsh-github-issue/client` | The browser-facing type face. |
|
|
110
|
+
| `@zhangj1164/dsh-github-issue/invariant` | Invariant definitions. |
|
|
111
|
+
|
|
112
|
+
## Known Limitations
|
|
113
|
+
|
|
114
|
+
- **Model dependency** — `inject: ['llm']` means the service will not activate without an LLM provider.
|
|
115
|
+
- **Service-only surface** — this package registers no model tool and ships no browser UI. Installing it on its own gives a deployment `ctx.get('githubIssue')` and nothing a user can see or click; the visible entry point is `@zhangj1164/dsh-client-ui-memo`'s issue editor and log-analysis action, which reach it over Remote. Treat it as a backend that a UI plugin consumes, not as a standalone feature.
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# @zhangj1164/dsh-github-issue
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 中文
|
|
4
|
+
|
|
5
|
+
DSH 的 GitHub issue 生成与优化服务。从遥测分析构建结构化 issue 报告、生成预填 issue 创建 URL,并使用配置的模型优化自然语言 issue 描述。
|
|
6
|
+
|
|
7
|
+
## 插件
|
|
8
|
+
|
|
9
|
+
`GithubIssueService extends TypertRemoteService`,`static inject = ['llm']`。服务通过 `ctx.get('llm')` 调用模型,暴露三个可由客户端 UI 直接调用的 Remote 方法。
|
|
10
|
+
|
|
11
|
+
| 配置 | 默认值 | 含义 |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `repoUrl` | `https://github.com/zhangj1164/dsh-mega-plugins` | 请求未提供 `repoUrl` 时使用的默认仓库 URL。 |
|
|
14
|
+
| `maxPrefillUrlLength` | `7000` | 生成的预填 issue URL 长度上限(字符)。GitHub 对过长的请求 URL 不打开新建 issue 表单而是返回错误页,且未公开稳定的边界常量,因此该值留有余量并可由部署方调整。`0` 表示不截断。 |
|
|
15
|
+
| `prefillTruncationNote` | 一段中文说明 | URL 需要缩短时追加到 issue 正文末尾,让读者知道正文是部分内容。 |
|
|
16
|
+
| `provider` | 未设置 | 模型调用的 provider 路由。未设置时跟随部署的 `agentDefaultModel` 选择,因此部署方仅通过 `cordis.yml` 就能把 issue 生成固定到某条路由。 |
|
|
17
|
+
| `model` | 未设置 | 模型调用的 model id。未设置时与 `provider` 采用同一回退。 |
|
|
18
|
+
|
|
19
|
+
## Remote 方法
|
|
20
|
+
|
|
21
|
+
| 方法 | 行为 |
|
|
22
|
+
|---|---|
|
|
23
|
+
| `generateReport(request)` | 使用内置结构化提示词调用模型,从遥测失败分析生成统一的 GitHub issue 报告。返回包含标题、正文和标签的 `GithubIssueReport`。请求用 `pluginIds` 说明它覆盖哪些插件——一份报告覆盖整个套件——并携带分析时间窗,以及每组的路由、最近一次失败时间和之后的尝试次数;每组字段都可选,缺省时会以 `not recorded` 传给模型,而不是省略。 |
|
|
24
|
+
| `prefilledIssueUrl(request)` | 从报告构建预填 GitHub issue 创建 URL。校验仓库 URL;失败时返回 `invalid-url`。当拼装出的 URL 超过 `maxPrefillUrlLength` 时缩短正文——标题与标签占用同一份额度,百分号编码还会放大它,因此判定基于 URL 而不是仅基于正文长度。 |
|
|
25
|
+
| `optimizeIssue(request)` | 将自然语言描述重写为按固定 Markdown 模板组织的 issue。空描述返回 `empty-input`,无路由可解析时返回 `route-missing`,模型调用失败返回 `llm-failure`。 |
|
|
26
|
+
|
|
27
|
+
## 模型路由
|
|
28
|
+
|
|
29
|
+
两个会调用模型的方法都按与 memo 服务相同的方式解析路由:请求里的 `provider`/`model`,其次本服务的 `Config`,最后部署的 `agentDefaultModel` 选择。因此请求里的这两个字段是可选的,客户端 UI 只在用户显式选择模型时才发送——浏览器无需为了调用成功而发布路由。
|
|
30
|
+
|
|
31
|
+
空字符串按「未提供」处理而不是当作取值,这样省略的字段仍能落到部署默认值,而不会以不可用的路由发往模型。当各处都解析不出路由时,调用返回 `route-missing`,并且**不会发起任何模型调用**:没有适配器的调用不可能成功,把它报成 `llm-failure` 等于用模型的名义解释路由问题。
|
|
32
|
+
|
|
33
|
+
## 失败事实
|
|
34
|
+
|
|
35
|
+
失败的调用会保留 DSH 报告的内容,而不是折叠成一条消息。`llm-failure` 的消息里带着机器路由码与路由——`model call to provider "custom" model "glm-5-2-260617" failed: NO_ADAPTER: no adapter registered for provider "custom"`——因此 `NO_ADAPTER`(本部署未注册的路由)、`AUTH`、`RATE_LIMIT` 与 `EMPTY_RESPONSE`(模型确实没有产出文本)之间仍然可区分。把它们一律报成「模型没有输出」,正是让用户在从未到达模型的请求里去找模型问题的原因。
|
|
36
|
+
|
|
37
|
+
流本身抛出传输错误而不是产出终止 `finish` 块时,报为 `LLM_STREAM_THREW`,而不是让异常逃逸出调用。
|
|
38
|
+
|
|
39
|
+
## 遥测
|
|
40
|
+
|
|
41
|
+
两个会调用模型的方法在部署装有遥测服务时都会上报,没有时行为完全相同。该服务通过 `ctx.get('telemetry')` 读取,并**刻意不**写进 `static inject`:本包可以单独作为 bundle 安装,诊断依赖绝不能成为服务拒绝激活的理由。
|
|
42
|
+
|
|
43
|
+
| 事件 | 记录内容 |
|
|
44
|
+
|---|---|
|
|
45
|
+
| 成功的调用 | 动作 `optimizeIssue` / `generateReport`,`success`,并带上服务本次调用的路由 |
|
|
46
|
+
| 失败的调用 | 保留的 DSH 码、消息与 HTTP 状态、路由,以及 `github-issue:<action>` 特性锚点 |
|
|
47
|
+
| 无法解析路由的调用 | 码 `NO_MODEL_ROUTE`——与 `@zhangj1164/dsh-memo` 对同一情形使用的码一致,因此一份报告可以把两个包归到一起 |
|
|
48
|
+
|
|
49
|
+
`generateReport` 还会记录它拿到的分析属于哪个插件。只记录成功的调用能回答「这些调用走的哪条路由」,却回答不了「那条路由在其出错之后是否已经变了」,所以两半都要记。
|
|
50
|
+
|
|
51
|
+
## Issue 报告模板
|
|
52
|
+
|
|
53
|
+
`generateReport` 和 `optimizeIssue` 均使用内置系统提示词,固定统一的 Markdown 结构。首行始终是 `## ` 标题,用作 issue 标题。模板包含插件、操作、预期/实际行为、路由与时间,以及复现步骤等部分。
|
|
54
|
+
|
|
55
|
+
`generateReport` 会收到分析时间窗,以及每组的失败路由、最近一次失败时间和之后的同动作尝试次数。它的系统提示词要求陈述这些事实,禁止提出分析未提供证据的机制——采样参数、token 预算、超时、分块与响应解析被点名为反例——并要求分析未携带的事实写作 `not recorded`。它也明确禁止写「需要补充采集」:缺失的事实既可能是旧事件,也可能是采集缺口,报告无从区分。
|
|
56
|
+
|
|
57
|
+
## 需求映射
|
|
58
|
+
|
|
59
|
+
- **需求 8** — `generateReport` 将遥测失败分析转化为统一的 GitHub issue 报告,将每个失败组与插件功能代码关联。
|
|
60
|
+
- **需求 9** — `prefilledIssueUrl` 构建预填的 GitHub issue 创建 URL,用户可直接跳转到项目的新建 issue 页面,报告已预填。
|
|
61
|
+
- **需求 10** — 封装为独立的 DSH 插件:此包自带 `dsh.bundle` 与 `cordis.patch.yml`,部署方可以单独安装,任何 UI 插件都能接入。见下文「接入本插件」。
|
|
62
|
+
- **需求 11** — `optimizeIssue` 使用配置的模型和内置的结构化提示词,将自然语言描述重写为结构化 issue。`ui-memo` 包直接调用此方法实现"添加 Issue"编辑器。
|
|
63
|
+
- **需求 12** — 可复用:issue 报告模板、预填 URL 构建器和优化提示词都是通用的,不特定于备忘功能。
|
|
64
|
+
|
|
65
|
+
## 接入本插件
|
|
66
|
+
|
|
67
|
+
安装该包,并把它加进你的部署组合:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
pnpm add @zhangj1164/dsh-github-issue
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```yaml
|
|
74
|
+
# 你的 cordis.yml,或你自己 bundle 的 patch
|
|
75
|
+
- insert:
|
|
76
|
+
- id: github-issue
|
|
77
|
+
name: @zhangj1164/dsh-github-issue
|
|
78
|
+
config:
|
|
79
|
+
repoUrl: https://github.com/your-org/your-repo
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
任何插件都可以通过 `ctx.get('githubIssue')` 读取该服务。从消费者角度看它是可选的,因此请做存在性判断:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
const issues = ctx.get('githubIssue')
|
|
86
|
+
if (issues !== undefined) {
|
|
87
|
+
const { report } = await issues.generateReport({ analysis, repoUrl })
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
该服务不依赖 `@zhangj1164/dsh-memo`;备忘只是可能的消费者之一。
|
|
92
|
+
|
|
93
|
+
本 bundle 是 `github-issue` 这个条目 id 的唯一归属方。`@zhangj1164/dsh-memo` 注入该服务,但不插入这一行,因此独立 bundle 与备忘套件可以无冲突地组合,`pnpm run verify-bundle-entries` 也找不到任何重叠。备忘部署因此需要点名整套:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
dsh plugin --profile web add @zhangj1164/dsh-telemetry @zhangj1164/dsh-github-issue @zhangj1164/dsh-memo @zhangj1164/dsh-client-ui-memo
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`@zhangj1164/dsh-github-issue` 要点名安装,而不是作为 peer 被带入:profile 设置了 `autoInstallPeers: false`,安装只引入命令点名的包,只装 `@zhangj1164/dsh-memo` 会让这一行无法解析。
|
|
100
|
+
|
|
101
|
+
## 导出
|
|
102
|
+
|
|
103
|
+
每个子路径都指向 tsdown 产出的扁平 `lib/*.js` 布局。
|
|
104
|
+
|
|
105
|
+
| 子路径 | 内容 |
|
|
106
|
+
|---|---|
|
|
107
|
+
| `@zhangj1164/dsh-github-issue` | `GithubIssueService` 插件及其 Config。 |
|
|
108
|
+
| `@zhangj1164/dsh-github-issue/types` | 线上类型:`GithubIssueReport`、请求与结果结构。 |
|
|
109
|
+
| `@zhangj1164/dsh-github-issue/client` | 面向浏览器端的类型面。 |
|
|
110
|
+
| `@zhangj1164/dsh-github-issue/invariant` | 不变量定义。 |
|
|
111
|
+
|
|
112
|
+
## 已知限制
|
|
113
|
+
|
|
114
|
+
- **模型依赖** — `inject: ['llm']` 意味着服务在没有 LLM 提供方时不会激活。
|
|
115
|
+
- **只有服务,没有界面** — 本包不注册模型工具,也不附带浏览器 UI。单独安装只会给部署带来 `ctx.get('githubIssue')`,用户看不到也点不到任何东西;可见的入口是 `@zhangj1164/dsh-client-ui-memo` 的 issue 编辑器与日志分析动作,它们经 Remote 调用本服务。请把它当作供 UI 插件消费的后端,而不是一个能独立使用的功能。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @zhangj1164/dsh-github-issue bundle patch: inserts the GitHub issue service into the host
|
|
2
|
+
# composition on its own, so a deployment can install this plugin without the
|
|
3
|
+
# memo suite. Any plugin that wants issue-report generation reads
|
|
4
|
+
# ctx.get('githubIssue'); @zhangj1164/dsh-memo is one such consumer, not a requirement.
|
|
5
|
+
#
|
|
6
|
+
# This bundle is the sole owner of the `github-issue` entry id. `@zhangj1164/dsh-memo`
|
|
7
|
+
# injects the service but does not insert this row, so installing the two
|
|
8
|
+
# together composes cleanly:
|
|
9
|
+
#
|
|
10
|
+
# dsh plugin --profile web add @zhangj1164/dsh-telemetry @zhangj1164/dsh-github-issue @zhangj1164/dsh-memo @zhangj1164/dsh-client-ui-memo
|
|
11
|
+
#
|
|
12
|
+
# `repoUrl` is the repository new-issue links point at. Deployments override it
|
|
13
|
+
# in their own cordis.patch.yml; the value below is this project's own.
|
|
14
|
+
|
|
15
|
+
- insert:
|
|
16
|
+
- id: github-issue
|
|
17
|
+
name: "@zhangj1164/dsh-github-issue"
|
|
18
|
+
config:
|
|
19
|
+
repoUrl: https://github.com/zhangj1164/dsh-mega-plugins
|
package/lib/client.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { GithubIssueAnalysisWindow, GithubIssueFailureGroupInput, GithubIssueFailureRoute, GithubIssueGenerateReportRequest, GithubIssueGenerateReportResult, GithubIssueOptimizeRequest, GithubIssueOptimizeResult, GithubIssuePrefillRequest, GithubIssuePrefillResult, GithubIssueReport } from "./types.js";
|
|
2
|
+
export type { GithubIssueAnalysisWindow, GithubIssueFailureGroupInput, GithubIssueFailureRoute, GithubIssueGenerateReportRequest, GithubIssueGenerateReportResult, GithubIssueOptimizeRequest, GithubIssueOptimizeResult, GithubIssuePrefillRequest, GithubIssuePrefillResult, GithubIssueReport };
|
package/lib/client.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { GithubIssueAnalysisWindow, GithubIssueFailureGroupInput, GithubIssueFailureRoute, GithubIssueGenerateReportRequest, GithubIssueGenerateReportResult, GithubIssueOptimizeRequest, GithubIssueOptimizeResult, GithubIssuePrefillRequest, GithubIssuePrefillResult, GithubIssueReport } from "./types.js";
|
|
2
|
+
import s from "@deepseek-ai/schemastery";
|
|
3
|
+
import { TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
4
|
+
import { GenerateOptions, StreamChunk } from "@deepseek-ai/dsh-llm";
|
|
5
|
+
import { Context } from "@deepseek-ai/cordis";
|
|
6
|
+
//#region src/llm-text.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* Minimal shape of the DSH `llm` service this helper needs. Declared
|
|
9
|
+
* structurally so a caller never has to depend on the concrete service class.
|
|
10
|
+
*/
|
|
11
|
+
interface LlmTextSource {
|
|
12
|
+
stream(options: GenerateOptions): AsyncIterable<StreamChunk>;
|
|
13
|
+
}
|
|
14
|
+
/** The model route a request should be sent to. */
|
|
15
|
+
interface LlmRoute {
|
|
16
|
+
/** Registered DSH provider route, or an empty string when unresolved. */
|
|
17
|
+
readonly provider: string;
|
|
18
|
+
/** Model id, or an empty string when unresolved. */
|
|
19
|
+
readonly model: string;
|
|
20
|
+
}
|
|
21
|
+
/** Serializable failure facts preserved from a DSH terminal `finish` chunk. */
|
|
22
|
+
interface LlmTextFailure {
|
|
23
|
+
/** DSH provider-neutral machine-routing code (`NO_ADAPTER`, `AUTH`, …). */
|
|
24
|
+
readonly code: string;
|
|
25
|
+
/** DSH human-readable failure message. */
|
|
26
|
+
readonly message: string;
|
|
27
|
+
/** HTTP status returned by the provider, when DSH supplied one. */
|
|
28
|
+
readonly status?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The outcome of one model text call: either the concatenated text, or the
|
|
32
|
+
* reason the call produced no text.
|
|
33
|
+
*/
|
|
34
|
+
type LlmTextResult = {
|
|
35
|
+
readonly ok: true;
|
|
36
|
+
readonly text: string;
|
|
37
|
+
} | {
|
|
38
|
+
readonly ok: false;
|
|
39
|
+
readonly failure: LlmTextFailure;
|
|
40
|
+
};
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/index.d.ts
|
|
43
|
+
/** Deployment configuration for the GitHub-issue service. */
|
|
44
|
+
interface Config {
|
|
45
|
+
/**
|
|
46
|
+
* The GitHub repository URL for issue prefill (e.g.
|
|
47
|
+
* `https://github.com/owner/repo`). Used as the default when a request omits
|
|
48
|
+
* `repoUrl`. The deployment sets this to the real project repository.
|
|
49
|
+
*/
|
|
50
|
+
readonly repoUrl: string;
|
|
51
|
+
/**
|
|
52
|
+
* Longest pre-filled issue URL to produce, counted in characters.
|
|
53
|
+
*
|
|
54
|
+
* GitHub refuses a request URL that is too long and shows an error page
|
|
55
|
+
* instead of the new-issue form, and it publishes no stable constant for the
|
|
56
|
+
* boundary, so this is a deployment-tunable value carrying headroom rather
|
|
57
|
+
* than a hardcoded number.
|
|
58
|
+
*/
|
|
59
|
+
readonly maxPrefillUrlLength: number;
|
|
60
|
+
/**
|
|
61
|
+
* Appended to the issue body when the URL had to be shortened to fit
|
|
62
|
+
* {@link Config.maxPrefillUrlLength}, so the reader knows the body is partial.
|
|
63
|
+
*/
|
|
64
|
+
readonly prefillTruncationNote: string;
|
|
65
|
+
/**
|
|
66
|
+
* Provider route for model calls; unset to follow this deployment's
|
|
67
|
+
* `agentDefaultModel` selection. Set it to pin issue generation to one route
|
|
68
|
+
* without touching memo's own route.
|
|
69
|
+
*/
|
|
70
|
+
readonly provider?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Model id for model calls; unset to follow this deployment's
|
|
73
|
+
* `agentDefaultModel` selection.
|
|
74
|
+
*/
|
|
75
|
+
readonly model?: string;
|
|
76
|
+
}
|
|
77
|
+
/** Schemastery configuration for the GitHub-issue service. */
|
|
78
|
+
declare const Config: s<Config>;
|
|
79
|
+
declare module '@deepseek-ai/cordis' {
|
|
80
|
+
interface Context {
|
|
81
|
+
githubIssue: GithubIssueService;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* GitHub-issue generation and optimization service over the configured model.
|
|
86
|
+
*/
|
|
87
|
+
declare class GithubIssueService extends TypertRemoteService {
|
|
88
|
+
static inject: string[];
|
|
89
|
+
static Config: s<Config>;
|
|
90
|
+
private readonly repoUrl;
|
|
91
|
+
private readonly maxPrefillUrlLength;
|
|
92
|
+
private readonly prefillTruncationNote;
|
|
93
|
+
/** Configured provider route, or `undefined` to follow `agentDefaultModel`. */
|
|
94
|
+
private readonly provider?;
|
|
95
|
+
/** Configured model id, or `undefined` to follow `agentDefaultModel`. */
|
|
96
|
+
private readonly model?;
|
|
97
|
+
/**
|
|
98
|
+
* @param ctx - Host context carrying the llm service.
|
|
99
|
+
* @param config - Validated deployment configuration.
|
|
100
|
+
*/
|
|
101
|
+
constructor(ctx: Context, config: Config);
|
|
102
|
+
/**
|
|
103
|
+
* Resolve the model route for one model call.
|
|
104
|
+
*
|
|
105
|
+
* The caller's explicit request wins, then this service's validated `Config`,
|
|
106
|
+
* then the deployment's `agentDefaultModel` selection — the same order the
|
|
107
|
+
* memo service uses, so one deployment-level answer decides both. A blank
|
|
108
|
+
* half is treated as absent rather than as a value: it is the shape an
|
|
109
|
+
* omitted field arrives in, and letting it win would send a call with no
|
|
110
|
+
* adapter, whose failure ("the model produced no output") blames the model
|
|
111
|
+
* for a routing problem.
|
|
112
|
+
*
|
|
113
|
+
* @param request - the caller's optional route.
|
|
114
|
+
* @returns the resolved route, or `undefined` when nothing resolved one.
|
|
115
|
+
*/
|
|
116
|
+
private resolveRoute;
|
|
117
|
+
/**
|
|
118
|
+
* Generate a uniform GitHub issue report from a telemetry failure analysis.
|
|
119
|
+
* Calls the configured model with a built-in structuring prompt.
|
|
120
|
+
* @param request - the analysis input from the telemetry service.
|
|
121
|
+
* @returns the generated report or an LLM failure.
|
|
122
|
+
*/
|
|
123
|
+
generateReport(request: GithubIssueGenerateReportRequest): Promise<GithubIssueGenerateReportResult>;
|
|
124
|
+
/**
|
|
125
|
+
* Build a pre-filled GitHub issue-creation URL from a report.
|
|
126
|
+
*
|
|
127
|
+
* The body is shortened when the finished URL would exceed the configured
|
|
128
|
+
* limit. The check is on the URL rather than on the body alone because the
|
|
129
|
+
* title and labels spend the same budget and percent-encoding inflates it,
|
|
130
|
+
* so a body-length rule would still produce a URL GitHub refuses.
|
|
131
|
+
*
|
|
132
|
+
* @param request - the repository URL and the report to prefill.
|
|
133
|
+
* @returns the prefill URL or an invalid-URL failure.
|
|
134
|
+
*/
|
|
135
|
+
prefilledIssueUrl(request: GithubIssuePrefillRequest): GithubIssuePrefillResult;
|
|
136
|
+
/**
|
|
137
|
+
* Optimize a natural-language issue description into a structured report
|
|
138
|
+
* using the configured model and a built-in structuring prompt.
|
|
139
|
+
* @param request - the raw description and model route.
|
|
140
|
+
* @returns the structured report or an LLM failure.
|
|
141
|
+
*/
|
|
142
|
+
optimizeIssue(request: GithubIssueOptimizeRequest): Promise<GithubIssueOptimizeResult>;
|
|
143
|
+
/**
|
|
144
|
+
* Report one model failure and return the business failure.
|
|
145
|
+
*
|
|
146
|
+
* The preserved DSH code goes into both the message and the telemetry event:
|
|
147
|
+
* the message is what a user reads, and the event is what a later analysis
|
|
148
|
+
* groups on. Reporting either as a bare "the model produced no output" is how
|
|
149
|
+
* an unroutable provider was mistaken for a model that answered nothing.
|
|
150
|
+
*
|
|
151
|
+
* @param action - the method the failure happened in, and its telemetry action.
|
|
152
|
+
* @param route - the route the call was sent to.
|
|
153
|
+
* @param failure - the preserved DSH failure facts.
|
|
154
|
+
* @returns the business failure to return to the caller.
|
|
155
|
+
*/
|
|
156
|
+
private llmFailure;
|
|
157
|
+
/**
|
|
158
|
+
* Report a call that arrived with no resolvable route.
|
|
159
|
+
*
|
|
160
|
+
* Recorded as a failure rather than silently skipped: this is the defect that
|
|
161
|
+
* produced an empty model response from every click of the issue editor's
|
|
162
|
+
* optimize button, and it left no trace anywhere, so it was found by a user
|
|
163
|
+
* report instead of by the telemetry it should have written.
|
|
164
|
+
*
|
|
165
|
+
* @param action - the method the call was made to, and its telemetry action.
|
|
166
|
+
* @returns the business failure to return to the caller.
|
|
167
|
+
*/
|
|
168
|
+
private routeMissing;
|
|
169
|
+
/**
|
|
170
|
+
* The route facts every AI-related telemetry event carries.
|
|
171
|
+
*
|
|
172
|
+
* Success events carry them for the same reason failures do: a record that
|
|
173
|
+
* names the route only when it broke cannot say which route served the calls
|
|
174
|
+
* that worked, so a later analysis cannot tell whether the route changed.
|
|
175
|
+
*
|
|
176
|
+
* @param route - the route the call used.
|
|
177
|
+
* @returns the provider and model to merge into an event's metadata.
|
|
178
|
+
*/
|
|
179
|
+
private routeFacts;
|
|
180
|
+
/**
|
|
181
|
+
* Record one completed call, when this deployment has telemetry mounted.
|
|
182
|
+
*
|
|
183
|
+
* @param action - the method the call was made to.
|
|
184
|
+
* @param result - whether it succeeded.
|
|
185
|
+
* @param metadata - structured context, such as the route.
|
|
186
|
+
*/
|
|
187
|
+
private track;
|
|
188
|
+
/**
|
|
189
|
+
* Record one failure, when this deployment has telemetry mounted.
|
|
190
|
+
*
|
|
191
|
+
* @param action - the method the failure happened in.
|
|
192
|
+
* @param error - the failure code, message, and feature anchor.
|
|
193
|
+
* @param metadata - structured context, such as the attempted route.
|
|
194
|
+
*/
|
|
195
|
+
private trackError;
|
|
196
|
+
}
|
|
197
|
+
//#endregion
|
|
198
|
+
export { Config, type GithubIssueAnalysisWindow, type GithubIssueFailureGroupInput, type GithubIssueFailureRoute, type GithubIssueGenerateReportRequest, type GithubIssueGenerateReportResult, type GithubIssueOptimizeRequest, type GithubIssueOptimizeResult, type GithubIssuePrefillRequest, type GithubIssuePrefillResult, type GithubIssueReport, GithubIssueService, GithubIssueService as default, type LlmRoute, type LlmTextFailure, type LlmTextResult, type LlmTextSource };
|