@jayyuen66/dsh-plugin-shared 0.1.3 → 0.1.5-rc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/README.zh-CN.md +3 -2
- package/dist/index.js +1 -1
- package/dist/locale.js +1 -1
- package/dist/trust.js +1 -1
- package/dist/types/trust.d.ts +22 -1
- package/package.json +27 -26
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ End users do not install or enable it separately: any consumer package pulls it
|
|
|
33
33
|
| | |
|
|
34
34
|
| --- | --- |
|
|
35
35
|
| Node.js | `^22.19.0 \|\| >=24.0.0`, the same clause as the harness root |
|
|
36
|
-
| dsh | `>= 0.2.1-alpha.
|
|
36
|
+
| dsh | `>= 0.2.1-alpha.2`, declared as an **optional** peer (this package needs no host at import time) |
|
|
37
37
|
| Module format | ESM only. `require()` works only where Node supports `require(esm)` |
|
|
38
38
|
| Tree shaking | `"sideEffects": false` |
|
|
39
39
|
|
|
@@ -64,7 +64,7 @@ The subpath column is the in-package specifier; value imports must prefix it wit
|
|
|
64
64
|
| `./lib/record` | `isRecord`, `fieldOf` |
|
|
65
65
|
| `./lib/errors` | `errorText`: semantics aligned with the official `@deepseek-ai/dsh-llm` `errorChain` (cause chain, `AggregateError` members, empty message falling back to `name`, cross-realm `message` read off the value itself, hostile getters degraded), implemented locally with zero dependencies |
|
|
66
66
|
| `./lib/jsonl` | `shrinkJsonlTail`: the pure decision half of JSONL tail halving; trigger policy and error exit stay with the caller |
|
|
67
|
-
| `./lib/trust` | `requestTrust` / `guardTrust` / `trustRejectionText`: request-trust predicate for `/_dsh/*` endpoints (Host authority → `sec-fetch-site` allow-list → byte-exact Origin) |
|
|
67
|
+
| `./lib/trust` | `requestTrust` / `guardTrust` / `trustRejectionText`: request-trust predicate for `/_dsh/*` endpoints (Host authority → `sec-fetch-site` allow-list → byte-exact Origin), plus `isNonLoopbackBindHost` to derive `servingNonLoopback` from the `webServer.host` bind literal |
|
|
68
68
|
| `./lib/job-outcome` | `jobOutcomeOf` + `SettledProcess` + `JobOutcome`: maps a settled subprocess onto the official job registry's outcome |
|
|
69
69
|
| `./lib/canonicalize-region-paths` | Build-time string helper that folds rolldown's `//#region <path>` markers into a `process.cwd()`-independent form. Exported as a subpath precisely because runtime consumers should not pay an import for it |
|
|
70
70
|
|
|
@@ -127,6 +127,7 @@ Known upstream limitation: `@deepseek-ai/dsh-llm`'s own declarations import `@de
|
|
|
127
127
|
- **`errorText` now returns more text** (same name and signature). It went from a single `message` layer to the official `errorChain` semantics: a cause chain renders as `outer: inner`, an `AggregateError` appends `[e1; e2]`, an empty message falls back to `Error.name`, and a cross-realm `Error` yields its own `message` instead of `String()`'s `"Error: ..."`. **Callers that regex the old text must re-check** (a `exec` that pulls a number out of parentheses, for example).
|
|
128
128
|
- `editPathOf` returns a `kind`-discriminated `EditTarget` with only `write` / `read-view`: `"skip"` was never produced, and leaving it in the type only pushed consumers into writing unreachable branches. When no path can be read it still returns the matching arm with `path` set to `undefined`.
|
|
129
129
|
- `isCrossOrigin` / `queryParam` / `checkCsrf` / `requestTrust` / `guardTrust` widened their first parameter from `IncomingMessage` to `HttpRequest`. `readBody` / `guardBody` still take `IncomingMessage` because they consume the request body and `PartialRequest` does not guarantee async iteration.
|
|
130
|
+
- **`servingNonLoopback` must now come from `isNonLoopbackBindHost(webServer.host)`, not from `webServer.host === "0.0.0.0"`.** Host 0.2.1-alpha.2 changed `@deepseek-ai/dsh-host-webserver`'s `Config.host` from the two-value union `'127.0.0.1' | '0.0.0.0'` to any concrete local-interface IP literal and started rejecting wildcard bind addresses at load. The old comparison is therefore constant `false`: a plugin bound to a real interface address stops recognizing its own authority, and every LAN request comes back `403 untrusted host authority`. `TrustOptions` is unchanged, so this is not an API break — it is a fix for a derivation that silently stopped working. `test/trust.test.ts` cross-checks the new predicate against the official `isLoopbackHost`, which became a public export in the same host release.
|
|
130
131
|
|
|
131
132
|
## Quality gates
|
|
132
133
|
|
package/README.zh-CN.md
CHANGED
|
@@ -33,7 +33,7 @@ import { readBody, sendJson } from "@jayyuen66/dsh-plugin-shared/lib/http";
|
|
|
33
33
|
| | |
|
|
34
34
|
| --- | --- |
|
|
35
35
|
| Node.js | `^22.19.0 \|\| >=24.0.0`,与 harness 根同款 |
|
|
36
|
-
| dsh | `>= 0.2.1-alpha.
|
|
36
|
+
| dsh | `>= 0.2.1-alpha.2`,声明为 **optional** peer(本包 import 时不需要宿主在场) |
|
|
37
37
|
| 模块形态 | 仅 ESM。`require()` 只在支持 `require(esm)` 的 Node 上可用 |
|
|
38
38
|
| Tree shaking | `"sideEffects": false` |
|
|
39
39
|
|
|
@@ -64,7 +64,7 @@ import { readBody, sendJson } from "@jayyuen66/dsh-plugin-shared/lib/http";
|
|
|
64
64
|
| `./lib/record` | `isRecord`、`fieldOf` |
|
|
65
65
|
| `./lib/errors` | `errorText`:语义对齐官方 `@deepseek-ai/dsh-llm` 的 `errorChain`(cause 链、`AggregateError` 成员、空 message 回退 name、跨 realm 取自有 message、敌意 getter 降级),本地零依赖实现 |
|
|
66
66
|
| `./lib/jsonl` | `shrinkJsonlTail`:JSONL 尾部收缩的纯决策件;触发策略与错误出口留给调用方 |
|
|
67
|
-
| `./lib/trust` | `requestTrust` / `guardTrust` / `trustRejectionText`:`/_dsh/*` 端点的请求信任判据(Host 权威 → `sec-fetch-site` 白名单 → Origin
|
|
67
|
+
| `./lib/trust` | `requestTrust` / `guardTrust` / `trustRejectionText`:`/_dsh/*` 端点的请求信任判据(Host 权威 → `sec-fetch-site` 白名单 → Origin 逐字比对);`isNonLoopbackBindHost`:由 `webServer.host` 那枚绑定字面量取 `servingNonLoopback` |
|
|
68
68
|
| `./lib/job-outcome` | `jobOutcomeOf` + `SettledProcess` + `JobOutcome`:把落定的子进程映射成官方作业注册表的结局 |
|
|
69
69
|
| `./lib/canonicalize-region-paths` | 构建期字符串件:把 rolldown 写的 `//#region <路径>` 折成与 `process.cwd()` 无关的形态。之所以只给子路径,就是为了让运行期消费方不必为它付一次导入 |
|
|
70
70
|
|
|
@@ -127,6 +127,7 @@ sonarjs 的入口是**惰性解析**的,发生在 `definePluginConfig()` 内
|
|
|
127
127
|
- **`errorText` 的返回值变长了**(签名与名字不变)。它从"单层 message"扩成与官方 `errorChain` 同语义:cause 链拼成 `外: 内`、`AggregateError` 附 `[e1; e2]`、空 message 回退 `Error.name`、跨 realm 的 Error 取其自带 `message` 而不是 `String()` 的 `"Error: …"`。**依赖旧文本做正则匹配的调用方要重新核对**(例如按括号取数的那类 `exec`)。
|
|
128
128
|
- `editPathOf` 的返回类型收成按 `kind` 判别的 `EditTarget`,只保留 `write` / `read-view` 两支——`"skip"` 从来不会被产出,留在类型里只会逼调用方写永不执行的分支。路径取不到时仍返回所属那一支、`path` 为 `undefined`。
|
|
129
129
|
- `isCrossOrigin` / `queryParam` / `checkCsrf` / `requestTrust` / `guardTrust` 的首参数由 `IncomingMessage` **放宽**为 `HttpRequest`。`readBody` / `guardBody` 仍是 `IncomingMessage`:它们要消费请求体,而 `PartialRequest` 不保证可异步迭代。
|
|
130
|
+
- **`servingNonLoopback` 现在要由 `isNonLoopbackBindHost(webServer.host)` 取,别再写 `webServer.host === "0.0.0.0"`。** 宿主 0.2.1-alpha.2 把 `@deepseek-ai/dsh-host-webserver` 的 `Config.host` 从 `'127.0.0.1' | '0.0.0.0'` 换成任意本机接口的 IP 字面量,并在载入时拒掉通配地址。于是那句旧比较恒为 false:绑在真实网卡地址上的插件认不出自己的权威,局域网来的请求整片吃 `403 untrusted host authority`。`TrustOptions` 的签名没动,所以这不是 API 破坏,而是一条**悄悄失效**的取值口径的修复。`test/trust.test.ts` 会把新谓词与官方 `isLoopbackHost`(同一次宿主发布里才转为公开导出)逐字面对表。
|
|
130
131
|
|
|
131
132
|
## 质量门
|
|
132
133
|
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CROSS_ORIGIN_TEXT as e,checkCsrf as t,guardBody as n,isCrossOrigin as r,queryParam as i,readBody as a,sendJson as o}from"./http.js";import{fieldOf as s,isRecord as c}from"./record.js";import{editPathOf as l,parseToolArguments as u,scanToolEvents as d,toolArgumentsBad as f,toolEventRowsOf as p}from"./tool-events.js";import{claimApply as m}from"./card-apply.js";import{deriveProjectKey as h}from"./project-key.js";import{DEFAULT_LOCALE as g,LOCALE_PREFERENCE_FIELD as _,LOCALE_SETTINGS_NAMESPACE as v,messagesFor as y,resolveLocale as b,resolveLocalePreference as x}from"./locale.js";import{settleLessonCall as S}from"./lesson-bus.js";import{truncateEnd as C,truncateStart as w}from"./text.js";import{errorText as T}from"./errors.js";import{shrinkJsonlTail as E}from"./jsonl.js";import{guardTrust as D,
|
|
1
|
+
import{CROSS_ORIGIN_TEXT as e,checkCsrf as t,guardBody as n,isCrossOrigin as r,queryParam as i,readBody as a,sendJson as o}from"./http.js";import{fieldOf as s,isRecord as c}from"./record.js";import{editPathOf as l,parseToolArguments as u,scanToolEvents as d,toolArgumentsBad as f,toolEventRowsOf as p}from"./tool-events.js";import{claimApply as m}from"./card-apply.js";import{deriveProjectKey as h}from"./project-key.js";import{DEFAULT_LOCALE as g,LOCALE_PREFERENCE_FIELD as _,LOCALE_SETTINGS_NAMESPACE as v,messagesFor as y,resolveLocale as b,resolveLocalePreference as x}from"./locale.js";import{settleLessonCall as S}from"./lesson-bus.js";import{truncateEnd as C,truncateStart as w}from"./text.js";import{errorText as T}from"./errors.js";import{shrinkJsonlTail as E}from"./jsonl.js";import{guardTrust as D,isNonLoopbackBindHost as O,requestTrust as k,trustRejectionText as A}from"./trust.js";import{jobOutcomeOf as j}from"./job-outcome.js";export{e as CROSS_ORIGIN_TEXT,g as DEFAULT_LOCALE,_ as LOCALE_PREFERENCE_FIELD,v as LOCALE_SETTINGS_NAMESPACE,t as checkCsrf,m as claimApply,h as deriveProjectKey,l as editPathOf,T as errorText,s as fieldOf,n as guardBody,D as guardTrust,r as isCrossOrigin,O as isNonLoopbackBindHost,c as isRecord,j as jobOutcomeOf,y as messagesFor,u as parseToolArguments,i as queryParam,a as readBody,k as requestTrust,b as resolveLocale,x as resolveLocalePreference,d as scanToolEvents,o as sendJson,S as settleLessonCall,E as shrinkJsonlTail,f as toolArgumentsBad,p as toolEventRowsOf,C as truncateEnd,w as truncateStart,A as trustRejectionText};
|
package/dist/locale.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isRecord as e}from"./record.js";const t=`zh`,n=`locale`,r=`preference`;function i(e){let[t]=(typeof e==`string`?e.trim().toLowerCase():``).split(`-`);return t===`en`||t===`zh`?t:`zh`}function a(t){return i(e(t)?t[r]:void 0)}function o(e,t){return e[t]}export{t as DEFAULT_LOCALE,r as LOCALE_PREFERENCE_FIELD,n as LOCALE_SETTINGS_NAMESPACE,o as messagesFor,i as resolveLocale,a as resolveLocalePreference};
|
|
1
|
+
import{isRecord as e}from"./record.js";const t=`zh`,n=`locale`,r=`preference`;function i(e){let[t]=(typeof e==`string`?e.trim().toLowerCase():``).split(`-`);return t===`en`||t===`zh`?t:`zh`}function a(t){return i(e(t)&&Object.hasOwn(t,`preference`)?t[r]:void 0)}function o(e,t){return e[t]}export{t as DEFAULT_LOCALE,r as LOCALE_PREFERENCE_FIELD,n as LOCALE_SETTINGS_NAMESPACE,o as messagesFor,i as resolveLocale,a as resolveLocalePreference};
|
package/dist/trust.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CROSS_ORIGIN_TEXT as e,sendJson as t}from"./http.js";import n from"node:os";const
|
|
1
|
+
import{CROSS_ORIGIN_TEXT as e,sendJson as t}from"./http.js";import n from"node:os";import{isIPv4 as r,isIPv6 as i}from"node:net";const a=/* @__PURE__ */ new Set([`localhost`,`[::1]`]),o=/* @__PURE__ */ new Set([`same-origin`,`none`]),s=`[::ffff:7f`;function c(e){let t=new URL(`http://[${e.split(`%`,1).join(``)}]`).hostname;return t===`[::1]`||t.startsWith(s)}function l(e){return e===void 0?!1:r(e)?e.split(`.`,1).join(``)!==`127`:i(e)&&!c(e)}const u=`bad-origin`;function d(e,t){let n=e.headers?.[t];return n===void 0?{kind:`absent`}:Array.isArray(n)?n.length===1?{kind:`single`,value:n.join(``)}:{kind:`duplicate`}:{kind:`single`,value:n}}const f=/^[A-Za-z0-9._\-[\]:%]+$/u;function p(e){if(!f.test(e))return null;try{return new URL(`http://${e}`)}catch{return null}}function m(e){let t=e.toLowerCase();if(a.has(t)||t.startsWith(s))return!0;let n=t.split(`.`);return n.length===4&&n[0]===`127`&&n.every(e=>/^\d{1,3}$/u.test(e)&&Number(e)<=255)}function h(){let e=[];for(let t of Object.values(n.networkInterfaces()))for(let{family:n,address:r}of t??[])e.push(n===`IPv6`?`[${r}]`:r);return e}function g(e,t){return m(e)?!0:t.servingNonLoopback===!0&&(t.localInterfaceAddresses??h()).includes(e)}function _(e){let t=d(e,`sec-fetch-site`);return t.kind===`duplicate`?!1:t.kind===`absent`||o.has(t.value)}function v(e){let t=e.socket?.remoteAddress;if(typeof t!=`string`||t===``)return null;let n=t.replaceAll(/^\[|\]$/gu,``).replace(/^::ffff:/iu,``);return m(n)||n===`::1`}function y(e,t){let n=d(e,`host`);if(n.kind===`duplicate`)return`rejected`;if(n.kind===`absent`)return v(e)===!1?`rejected`:null;let r=p(n.value);return r===null||!g(r.hostname,t)?`rejected`:r}function b(e,t={}){let n=y(e,t);if(n===`rejected`)return`untrusted-host`;if(!_(e))return`cross-site`;let r=d(e,`origin`);if(r.kind===`duplicate`)return u;if(r.kind===`absent`)return`trusted`;let i=r.value;if(i===`null`||n===null)return u;let a=p(i.replace(/^[a-z][a-z0-9+.-]*:\/\//iu,``));return a===null?u:a.host===n.host?`trusted`:u}function x(t){return t===`untrusted-host`?`untrusted host authority`:e}function S(e,n,r={}){let i=b(e,r);return i===`trusted`?!0:n.headersSent||n.writableEnded?(console.error(`[shared/trust] rejecting after headers were sent:`,i),!1):(t(n,403,{ok:!1,error:x(i)}),!1)}export{S as guardTrust,l as isNonLoopbackBindHost,b as requestTrust,x as trustRejectionText};
|
package/dist/types/trust.d.ts
CHANGED
|
@@ -4,11 +4,32 @@ import type { HttpRequest } from "./http.ts";
|
|
|
4
4
|
export type TrustVerdict = "trusted" | "untrusted-host" | "cross-site" | "bad-origin";
|
|
5
5
|
/** `requestTrust` / `guardTrust` 的可选入参。 */
|
|
6
6
|
export interface TrustOptions {
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* 宿主是否绑在非回环地址上——由 `isNonLoopbackBindHost(webServer.host)` 取,**不要**再自己比
|
|
9
|
+
* 字面量。缺省按 false(保守)。
|
|
10
|
+
*/
|
|
8
11
|
servingNonLoopback?: boolean;
|
|
9
12
|
/** 注入本机地址面(测试用;缺省取 `os.networkInterfaces()` 的实际值)。 */
|
|
10
13
|
localInterfaceAddresses?: readonly string[];
|
|
11
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* 绑定地址的字面量谓词:`webServer.host` → {@link TrustOptions.servingNonLoopback}。
|
|
17
|
+
*
|
|
18
|
+
* 为什么现在要由本包出这个谓词:`@deepseek-ai/dsh-host-webserver` 的 `Config.host` 在宿主
|
|
19
|
+
* 0.2.1-alpha.2 从 `'127.0.0.1' | '0.0.0.0'` 换成**任意本机接口 IP 字面量**,并把通配地址
|
|
20
|
+
* (`0.0.0.0`、`::` 及其映射形)**在载入时拒掉**。于是消费方沿用至今的那行
|
|
21
|
+
* `webServer.host === "0.0.0.0"` 恒为 false——非回环服务面换了形态(一枚真的网卡地址),
|
|
22
|
+
* 判据却还盯着那枚再也绑不上的字面量,局域网访问会被本模块整片拒成 403。
|
|
23
|
+
*
|
|
24
|
+
* 口径与官方 `isLoopbackHost` 对齐(台架见 `test/trust.test.ts`)。一处**刻意**分歧:非字面量
|
|
25
|
+
* (`localhost`、带方括号的 `[::1]`)本函数按 false,官方那侧 `!isLoopbackHost` 得 true。
|
|
26
|
+
* 宿主自身的 config 校验已经拒掉非字面量,那种值到不了这里;万一到了,false 收紧而非放宽
|
|
27
|
+
* 可放行的 Host 权威——这个方向上宁可错杀。
|
|
28
|
+
*
|
|
29
|
+
* @param host - `webServer.host` 的绑定值;读不到(缺字段、空串、非字面量)按只绑回环处理
|
|
30
|
+
* @returns 绑的是非回环接口地址时为 true
|
|
31
|
+
*/
|
|
32
|
+
export declare function isNonLoopbackBindHost(host: string | undefined): boolean;
|
|
12
33
|
/**
|
|
13
34
|
* 一次判据:Host 权威 → sec-fetch-site(白名单)→ Origin 逐字比对。
|
|
14
35
|
* 纯函数、不写响应;写响应的样板在 `guardTrust`。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jayyuen66/dsh-plugin-shared",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5-rc",
|
|
4
4
|
"description": "dsh 自研插件的共享工具库:tool 事件流记账扫描 + webServer HTTP 样板(sendJson/CORS/CSRF/body 限制)+ 卡片 apply 骨架 + 项目键派生 + 代理对安全截断。作为库包被 import,不由用户启用",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cordis",
|
|
@@ -105,35 +105,36 @@
|
|
|
105
105
|
},
|
|
106
106
|
"devDependencies": {
|
|
107
107
|
"@deepseek-ai/cordis": "4.0.5-alpha.1",
|
|
108
|
-
"@deepseek-ai/dsh-brand": "0.2.1-alpha.
|
|
109
|
-
"@deepseek-ai/dsh-client-locale": "0.2.1-alpha.
|
|
110
|
-
"@deepseek-ai/dsh-
|
|
111
|
-
"@deepseek-ai/dsh-
|
|
112
|
-
"@deepseek-ai/dsh-
|
|
113
|
-
"@deepseek-ai/dsh-
|
|
114
|
-
"@deepseek-ai/dsh-
|
|
115
|
-
"@deepseek-ai/dsh-
|
|
116
|
-
"@deepseek-ai/dsh-
|
|
117
|
-
"@
|
|
118
|
-
"@
|
|
108
|
+
"@deepseek-ai/dsh-brand": "0.2.1-alpha.2",
|
|
109
|
+
"@deepseek-ai/dsh-client-locale": "0.2.1-alpha.2",
|
|
110
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.1-alpha.2",
|
|
111
|
+
"@deepseek-ai/dsh-jobs": "0.2.1-alpha.2",
|
|
112
|
+
"@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
|
|
113
|
+
"@deepseek-ai/dsh-output-retention": "0.2.1-alpha.2",
|
|
114
|
+
"@deepseek-ai/dsh-scope": "0.2.1-alpha.2",
|
|
115
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.2",
|
|
116
|
+
"@deepseek-ai/dsh-shell": "0.2.1-alpha.2",
|
|
117
|
+
"@deepseek-ai/dsh-tools": "0.2.1-alpha.2",
|
|
118
|
+
"@types/node": "26.6.5",
|
|
119
|
+
"@vitest/coverage-v8": "5.0.3",
|
|
119
120
|
"eslint-plugin-sonarjs": "4.2.2",
|
|
120
|
-
"oxfmt": "0.
|
|
121
|
-
"oxlint": "1.
|
|
122
|
-
"oxlint-tsgolint": "7.0.
|
|
123
|
-
"rolldown": "1.2.
|
|
121
|
+
"oxfmt": "0.72.0",
|
|
122
|
+
"oxlint": "1.87.0",
|
|
123
|
+
"oxlint-tsgolint": "7.0.2004",
|
|
124
|
+
"rolldown": "1.2.13",
|
|
124
125
|
"typescript": "7.0.2",
|
|
125
|
-
"vite": "8.3.
|
|
126
|
-
"vitest": "5.0.
|
|
126
|
+
"vite": "8.3.4",
|
|
127
|
+
"vitest": "5.0.3"
|
|
127
128
|
},
|
|
128
129
|
"peerDependencies": {
|
|
129
130
|
"@deepseek-ai/cordis": "4.0.5-alpha.1",
|
|
130
|
-
"@deepseek-ai/dsh": "^0.2.1-alpha.
|
|
131
|
-
"@deepseek-ai/dsh-client-locale": "0.2.1-alpha.
|
|
132
|
-
"@deepseek-ai/dsh-jobs": "0.2.1-alpha.
|
|
133
|
-
"@deepseek-ai/dsh-output-retention": "0.2.1-alpha.
|
|
134
|
-
"@deepseek-ai/dsh-session": "0.2.1-alpha.
|
|
135
|
-
"@deepseek-ai/dsh-shell": "0.2.1-alpha.
|
|
136
|
-
"@deepseek-ai/dsh-tools": "0.2.1-alpha.
|
|
131
|
+
"@deepseek-ai/dsh": "^0.2.1-alpha.2",
|
|
132
|
+
"@deepseek-ai/dsh-client-locale": "0.2.1-alpha.2",
|
|
133
|
+
"@deepseek-ai/dsh-jobs": "0.2.1-alpha.2",
|
|
134
|
+
"@deepseek-ai/dsh-output-retention": "0.2.1-alpha.2",
|
|
135
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.2",
|
|
136
|
+
"@deepseek-ai/dsh-shell": "0.2.1-alpha.2",
|
|
137
|
+
"@deepseek-ai/dsh-tools": "0.2.1-alpha.2"
|
|
137
138
|
},
|
|
138
139
|
"peerDependenciesMeta": {
|
|
139
140
|
"@deepseek-ai/cordis": {
|
|
@@ -160,7 +161,7 @@
|
|
|
160
161
|
},
|
|
161
162
|
"icon": "icon.svg",
|
|
162
163
|
"engines": {
|
|
163
|
-
"dsh": ">=0.2.1-alpha.
|
|
164
|
+
"dsh": ">=0.2.1-alpha.2",
|
|
164
165
|
"node": "^22.19.0 || >=24.0.0"
|
|
165
166
|
},
|
|
166
167
|
"scripts": {
|