@dsh-workbench/shared 0.3.10 → 0.3.11
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/dist/api/dsh-client.d.ts +1 -0
- package/dist/api/dsh.d.ts +18 -0
- package/dist/api/host-write.d.ts +0 -15
- package/dist/api/host-write.js +1 -35
- package/dist/api/unit-board.d.ts +0 -21
- package/dist/api/unit-board.js +1 -45
- package/dist/components/icons.d.ts +0 -6
- package/dist/components/icons.js +0 -12
- package/dist/config/storage.d.ts +0 -4
- package/dist/config/storage.js +0 -11
- package/dist/host/browser-find.js +1 -1
- package/dist/host/browser-read.js +5 -5
- package/dist/host/tool-approval.d.ts +12 -0
- package/dist/host/tool-approval.js +4 -0
- package/dist/i18n/en.js +39 -19
- package/dist/i18n/index.d.ts +40 -20
- package/dist/i18n/zh.d.ts +39 -19
- package/dist/i18n/zh.js +39 -19
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/blocker-action.d.ts +0 -15
- package/dist/lib/blocker-action.js +1 -25
- package/dist/lib/react-types.d.ts +5 -0
- package/dist/lib/react-types.js +1 -0
- package/dist/lib/react.d.ts +14 -13
- package/dist/lib/react.js +11 -11
- package/package.json +1 -1
- package/src/api/dsh-client.ts +4 -1
- package/src/api/dsh.ts +16 -0
- package/src/api/host-write.ts +0 -42
- package/src/api/unit-board.ts +0 -45
- package/src/components/icons.tsx +0 -16
- package/src/config/storage.test.ts +1 -25
- package/src/config/storage.ts +0 -12
- package/src/host/__tests__/browser-find.test.ts +1 -1
- package/src/host/__tests__/browser-read.test.ts +1 -1
- package/src/host/browser-find.ts +1 -1
- package/src/host/browser-read.ts +5 -5
- package/src/host/tool-approval.ts +17 -0
- package/src/i18n/en.ts +41 -19
- package/src/i18n/zh.ts +41 -19
- package/src/index.ts +1 -1
- package/src/lib/blocker-action.ts +0 -27
- package/src/lib/react-types.ts +5 -0
- package/src/lib/react.ts +14 -13
- package/src/api/__tests__/host-write.test.ts +0 -75
- package/src/api/__tests__/unit-board.test.ts +0 -76
- package/src/lib/blocker-action.test.ts +0 -40
package/dist/api/dsh-client.d.ts
CHANGED
|
@@ -245,6 +245,7 @@ export interface DshConversationService {
|
|
|
245
245
|
export interface DshSessionsService {
|
|
246
246
|
readonly list: {
|
|
247
247
|
getSnapshot(): SessionsSnapshot;
|
|
248
|
+
subscribe?(listener: () => void): () => void;
|
|
248
249
|
};
|
|
249
250
|
scope(sessionId: string): unknown | undefined;
|
|
250
251
|
create?(request: {
|
package/dist/api/dsh.d.ts
CHANGED
|
@@ -222,6 +222,24 @@ export interface DshToolRunContext {
|
|
|
222
222
|
} | undefined;
|
|
223
223
|
} | undefined;
|
|
224
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* dsh 的审批服务(服务名 `approval`):读一个会话此刻生效的审批策略。
|
|
227
|
+
* 方法可选:服务缺席或老版本没有它时,调用方必须当成「不知道」而不是「已关闭」。
|
|
228
|
+
*/
|
|
229
|
+
export interface DshApprovalService {
|
|
230
|
+
effectivePolicy?(session: unknown): 'ask' | 'never' | undefined;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* dsh 的沙箱策略服务(服务名 `sandboxPolicy`):按会话解析这次调用生效的文件边界。
|
|
234
|
+
* 方法可选:服务缺席或老版本没有它时,调用方必须当成「不知道」而不是「完全放行」。
|
|
235
|
+
*/
|
|
236
|
+
export interface DshSandboxPolicy {
|
|
237
|
+
resolve?(request?: {
|
|
238
|
+
readonly session?: unknown;
|
|
239
|
+
}): {
|
|
240
|
+
readonly mode?: string;
|
|
241
|
+
} | undefined;
|
|
242
|
+
}
|
|
225
243
|
/**
|
|
226
244
|
* dsh 的工具表;register 回的清理函数负责在插件卸载时摘掉这条工具。
|
|
227
245
|
*/
|
package/dist/api/host-write.d.ts
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
|
-
import type { ApiResponse } from './workbench-client.js';
|
|
2
1
|
/**
|
|
3
2
|
* 宿主写口的五条通道(偏好、动作、供给、工坊调试、工坊录制),是写路由的第一段。
|
|
4
3
|
*/
|
|
5
4
|
export type WriteChannel = 'prefs' | 'actions' | 'provision' | 'diy-debug' | 'diy-record';
|
|
6
|
-
/**
|
|
7
|
-
* 由通道与资源拼出写路由。
|
|
8
|
-
* @param channel 写通道。
|
|
9
|
-
* @param resource 该通道下的资源名。
|
|
10
|
-
* @returns 路由字符串;provision 只有一段,其余是 channel/resource。
|
|
11
|
-
*/
|
|
12
|
-
export declare function writeRoute(channel: WriteChannel, resource: string): string;
|
|
13
5
|
/**
|
|
14
6
|
* 写通道统一的结果:成了带值,没成带一句能给人看的话(可选明细与帮助链接)。
|
|
15
7
|
*/
|
|
@@ -22,10 +14,3 @@ export type WriteOutcome<T> = {
|
|
|
22
14
|
readonly detail?: string;
|
|
23
15
|
readonly helpUrl?: string;
|
|
24
16
|
};
|
|
25
|
-
/**
|
|
26
|
-
* 把写通道的响应翻成 WriteOutcome。
|
|
27
|
-
* @param response 写口回的响应;null 表示请求本身没成(网络断了,宿主没答)。
|
|
28
|
-
* @param networkText 拿不到任何服务端文案时兜底的那句。
|
|
29
|
-
* @returns 失败时 message 优先用服务端自己的话,没有才用响应正文或 networkText。
|
|
30
|
-
*/
|
|
31
|
-
export declare function writeOutcomeOf<T>(response: ApiResponse<T> | null, networkText: string): WriteOutcome<T>;
|
package/dist/api/host-write.js
CHANGED
|
@@ -1,35 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* 由通道与资源拼出写路由。
|
|
3
|
-
* @param channel 写通道。
|
|
4
|
-
* @param resource 该通道下的资源名。
|
|
5
|
-
* @returns 路由字符串;provision 只有一段,其余是 channel/resource。
|
|
6
|
-
*/
|
|
7
|
-
export function writeRoute(channel, resource) {
|
|
8
|
-
if (channel === 'provision')
|
|
9
|
-
return 'provision';
|
|
10
|
-
return `${channel}/${resource}`;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* 把写通道的响应翻成 WriteOutcome。
|
|
14
|
-
* @param response 写口回的响应;null 表示请求本身没成(网络断了,宿主没答)。
|
|
15
|
-
* @param networkText 拿不到任何服务端文案时兜底的那句。
|
|
16
|
-
* @returns 失败时 message 优先用服务端自己的话,没有才用响应正文或 networkText。
|
|
17
|
-
*/
|
|
18
|
-
export function writeOutcomeOf(response, networkText) {
|
|
19
|
-
if (response === null)
|
|
20
|
-
return { ok: false, message: networkText };
|
|
21
|
-
if (!response.ok) {
|
|
22
|
-
const box = response;
|
|
23
|
-
const own = typeof box.error?.message === 'string' && box.error.message !== '' ? box.error.message : undefined;
|
|
24
|
-
const fallback = typeof box.text === 'string' && box.text !== '' ? box.text : networkText;
|
|
25
|
-
const detail = typeof box.error?.detail === 'string' ? box.error.detail : undefined;
|
|
26
|
-
const helpUrl = typeof box.error?.helpUrl === 'string' && box.error.helpUrl !== '' ? box.error.helpUrl : undefined;
|
|
27
|
-
return {
|
|
28
|
-
ok: false,
|
|
29
|
-
message: own ?? fallback,
|
|
30
|
-
...(detail === undefined ? {} : { detail }),
|
|
31
|
-
...(helpUrl === undefined ? {} : { helpUrl }),
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
return { ok: true, value: response };
|
|
35
|
-
}
|
|
1
|
+
export {};
|
package/dist/api/unit-board.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import type { ModuleBlocker } from './blocker.js';
|
|
2
|
-
import type { CapabilityPayload } from './workbench-contract.js';
|
|
3
|
-
import type { ApiError } from './workbench-client.js';
|
|
4
2
|
/**
|
|
5
3
|
* 卡片闸的两种档:capability 按环境读数判,none 无条件放行。
|
|
6
4
|
*/
|
|
@@ -11,13 +9,6 @@ export type GateMode = 'capability' | 'none';
|
|
|
11
9
|
export interface UnitGate {
|
|
12
10
|
readonly gated: boolean;
|
|
13
11
|
}
|
|
14
|
-
/**
|
|
15
|
-
* 判这张卡现在能不能画。
|
|
16
|
-
* @param capability 环境读数;还没读到给 null。
|
|
17
|
-
* @param mode 闸档。
|
|
18
|
-
* @returns mode 为 none 或读数还没到都放行(先放行让它读);读到明确不通过(ok 与 unchecked 之外)才拦。
|
|
19
|
-
*/
|
|
20
|
-
export declare function gateOf(capability: CapabilityPayload | null, mode: GateMode): UnitGate;
|
|
21
12
|
/**
|
|
22
13
|
* 一个单元攒下的卡住态:blocker 顶掉卡片,notice 只提示;组装方产出,卡片消费。
|
|
23
14
|
*/
|
|
@@ -25,15 +16,3 @@ export interface UnitBlockers {
|
|
|
25
16
|
readonly blocker?: ModuleBlocker;
|
|
26
17
|
readonly notice?: ModuleBlocker;
|
|
27
18
|
}
|
|
28
|
-
/**
|
|
29
|
-
* 把候选卡住态分档,每档只留第一个。
|
|
30
|
-
* @param candidates 候选(可能含 undefined),按优先级从高到低给。
|
|
31
|
-
* @returns 分出的 blocker 与 notice;已经有 blocker 时不带 notice(挡住就不必再提示)。
|
|
32
|
-
*/
|
|
33
|
-
export declare function splitBlocker(candidates: readonly (ModuleBlocker | undefined)[]): UnitBlockers;
|
|
34
|
-
/**
|
|
35
|
-
* 由读口错误算出「出错搭车强探」的防抖键:同一个键只自动重探一次。
|
|
36
|
-
* @param error 读口错误;undefined 表示这次没有错误。
|
|
37
|
-
* @returns 键字符串;空 code 归一到 unknown。
|
|
38
|
-
*/
|
|
39
|
-
export declare function probeKeyOf(error: ApiError | undefined): string | null;
|
package/dist/api/unit-board.js
CHANGED
|
@@ -1,45 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* 判这张卡现在能不能画。
|
|
3
|
-
* @param capability 环境读数;还没读到给 null。
|
|
4
|
-
* @param mode 闸档。
|
|
5
|
-
* @returns mode 为 none 或读数还没到都放行(先放行让它读);读到明确不通过(ok 与 unchecked 之外)才拦。
|
|
6
|
-
*/
|
|
7
|
-
export function gateOf(capability, mode) {
|
|
8
|
-
if (mode === 'none')
|
|
9
|
-
return { gated: true };
|
|
10
|
-
if (capability === null)
|
|
11
|
-
return { gated: true };
|
|
12
|
-
return { gated: capability.status === 'ok' || capability.status === 'unchecked' };
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* 把候选卡住态分档,每档只留第一个。
|
|
16
|
-
* @param candidates 候选(可能含 undefined),按优先级从高到低给。
|
|
17
|
-
* @returns 分出的 blocker 与 notice;已经有 blocker 时不带 notice(挡住就不必再提示)。
|
|
18
|
-
*/
|
|
19
|
-
export function splitBlocker(candidates) {
|
|
20
|
-
let blocker;
|
|
21
|
-
let notice;
|
|
22
|
-
for (const candidate of candidates) {
|
|
23
|
-
if (candidate === undefined)
|
|
24
|
-
continue;
|
|
25
|
-
if (candidate.severity === 'block') {
|
|
26
|
-
blocker ??= candidate;
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
notice ??= candidate;
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
...(blocker === undefined ? {} : { blocker }),
|
|
33
|
-
...(blocker !== undefined || notice === undefined ? {} : { notice }),
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* 由读口错误算出「出错搭车强探」的防抖键:同一个键只自动重探一次。
|
|
38
|
-
* @param error 读口错误;undefined 表示这次没有错误。
|
|
39
|
-
* @returns 键字符串;空 code 归一到 unknown。
|
|
40
|
-
*/
|
|
41
|
-
export function probeKeyOf(error) {
|
|
42
|
-
if (error === undefined)
|
|
43
|
-
return null;
|
|
44
|
-
return error.code === '' ? 'unknown' : error.code;
|
|
45
|
-
}
|
|
1
|
+
export {};
|
|
@@ -28,12 +28,6 @@ export declare function IconOpencli({ size }: IconProps): JSX.Element;
|
|
|
28
28
|
* @returns 一枚 `aria-hidden` 的 svg。
|
|
29
29
|
*/
|
|
30
30
|
export declare function IconNpm({ size }: IconProps): JSX.Element;
|
|
31
|
-
/**
|
|
32
|
-
* 四宫格:"模块"这个概念的通用单色图标(侧栏、面板那颗钮、市场节的标题);默认 16px。
|
|
33
|
-
* @param props.size - 边长像素,同时给 `width` 与 `height`。
|
|
34
|
-
* @returns 一枚 `aria-hidden` 的 svg。
|
|
35
|
-
*/
|
|
36
|
-
export declare function IconModules({ size }: IconProps): JSX.Element;
|
|
37
31
|
/**
|
|
38
32
|
* 模块类型标:渐变方块 + 白四宫格,用在"这是个模块"的行首;品牌物,颜色不跟主题走。默认 16px。
|
|
39
33
|
* @param props.size - 边长像素,同时给 `width` 与 `height`。
|
package/dist/components/icons.js
CHANGED
|
@@ -45,18 +45,6 @@ export function IconNpm({ size = 16 }) {
|
|
|
45
45
|
return (h(Shell, { size: size, viewBox: "0 0 1024 1024" },
|
|
46
46
|
h("path", { d: "M64 337.76h896v298.72H512v49.792H312.896v-49.824H64z m49.792 248.928h99.552v-149.376h49.76v149.344h49.792v-199.104H113.792z m248.896-199.136v248.928h99.552v-49.792h99.552v-199.136z m99.552 49.792H512v99.584h-49.792z m149.344-49.792v199.136h99.552v-149.376h49.792v149.344h49.792v-149.344h49.792v149.344h49.792v-199.104z", fill: "#CB3837" })));
|
|
47
47
|
}
|
|
48
|
-
/**
|
|
49
|
-
* 四宫格:"模块"这个概念的通用单色图标(侧栏、面板那颗钮、市场节的标题);默认 16px。
|
|
50
|
-
* @param props.size - 边长像素,同时给 `width` 与 `height`。
|
|
51
|
-
* @returns 一枚 `aria-hidden` 的 svg。
|
|
52
|
-
*/
|
|
53
|
-
export function IconModules({ size = 16 }) {
|
|
54
|
-
return (h("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true" },
|
|
55
|
-
h("rect", { x: "2.5", y: "2.5", width: "4.6", height: "4.6", rx: "1.2", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
56
|
-
h("rect", { x: "8.9", y: "2.5", width: "4.6", height: "4.6", rx: "1.2", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
57
|
-
h("rect", { x: "2.5", y: "8.9", width: "4.6", height: "4.6", rx: "1.2", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
58
|
-
h("rect", { x: "8.9", y: "8.9", width: "4.6", height: "4.6", rx: "1.2", stroke: "currentColor", strokeWidth: "1.2" })));
|
|
59
|
-
}
|
|
60
48
|
/**
|
|
61
49
|
* 模块类型标:渐变方块 + 白四宫格,用在"这是个模块"的行首;品牌物,颜色不跟主题走。默认 16px。
|
|
62
50
|
* @param props.size - 边长像素,同时给 `width` 与 `height`。
|
package/dist/config/storage.d.ts
CHANGED
|
@@ -2,7 +2,3 @@
|
|
|
2
2
|
export declare function readText(key: string): string | null;
|
|
3
3
|
/** 写一段文本进 localStorage;`value` 为 null 时删掉这个键,写不进去就静默作罢。 */
|
|
4
4
|
export declare function writeText(key: string, value: string | null): void;
|
|
5
|
-
/** 读一个布尔开关:键不存在时返回 `fallback`,只有存进去的 `'true'` 算真。 */
|
|
6
|
-
export declare function readFlag(key: string, fallback: boolean): boolean;
|
|
7
|
-
/** 把一个布尔开关写进 localStorage(存 `'true'` / `'false'`);失败静默。 */
|
|
8
|
-
export declare function writeFlag(key: string, value: boolean): void;
|
package/dist/config/storage.js
CHANGED
|
@@ -18,14 +18,3 @@ export function writeText(key, value) {
|
|
|
18
18
|
catch {
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
/** 读一个布尔开关:键不存在时返回 `fallback`,只有存进去的 `'true'` 算真。 */
|
|
22
|
-
export function readFlag(key, fallback) {
|
|
23
|
-
const raw = readText(key);
|
|
24
|
-
if (raw === null)
|
|
25
|
-
return fallback;
|
|
26
|
-
return raw === 'true';
|
|
27
|
-
}
|
|
28
|
-
/** 把一个布尔开关写进 localStorage(存 `'true'` / `'false'`);失败静默。 */
|
|
29
|
-
export function writeFlag(key, value) {
|
|
30
|
-
writeText(key, value ? 'true' : 'false');
|
|
31
|
-
}
|
|
@@ -77,8 +77,8 @@ async function evalOnce(shell, command, session, script, timeoutMs, retryMs) {
|
|
|
77
77
|
result: {
|
|
78
78
|
ok: false,
|
|
79
79
|
code: 'cli-exec-failed',
|
|
80
|
-
message: '
|
|
81
|
-
hint: '
|
|
80
|
+
message: '读不了:后台服务起不来',
|
|
81
|
+
hint: '确认后台服务能跑起来,再重试',
|
|
82
82
|
detail: error instanceof Error ? error.message : String(error),
|
|
83
83
|
},
|
|
84
84
|
};
|
|
@@ -116,8 +116,8 @@ async function evalOnce(shell, command, session, script, timeoutMs, retryMs) {
|
|
|
116
116
|
result: {
|
|
117
117
|
ok: false,
|
|
118
118
|
code: 'cli-exec-failed',
|
|
119
|
-
message: '
|
|
120
|
-
hint: '
|
|
119
|
+
message: '读到的格式不对',
|
|
120
|
+
hint: '让 agent 检查一下这条读',
|
|
121
121
|
detail: tailLines(attempt.stdout, 4),
|
|
122
122
|
},
|
|
123
123
|
};
|
|
@@ -142,7 +142,7 @@ async function openOnce(shell, command, session, url, timeoutMs) {
|
|
|
142
142
|
ok: false,
|
|
143
143
|
code: 'cli-exec-failed',
|
|
144
144
|
message: '打不开那个页面',
|
|
145
|
-
hint: '
|
|
145
|
+
hint: '确认后台服务能跑起来,再重试',
|
|
146
146
|
detail: error instanceof Error ? error.message : String(error),
|
|
147
147
|
helpUrl: url,
|
|
148
148
|
};
|
|
@@ -31,10 +31,17 @@ export interface ApprovalCall {
|
|
|
31
31
|
readonly workspace?: string | undefined;
|
|
32
32
|
readonly session?: string | undefined;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* 套件对一次写调用给出的判定:`read` 只是看看、`allow` 会写但本套件不问、`deny` 这一次根本跑不成
|
|
36
|
+
* (连问都不该问,`reason` 原样交给 agent)、`ask` 要用户点头(`question` 接在明细后,`fallback` 是没明细时的整句)。
|
|
37
|
+
*/
|
|
34
38
|
export type ApprovalVerdict = {
|
|
35
39
|
readonly kind: 'read';
|
|
36
40
|
} | {
|
|
37
41
|
readonly kind: 'allow';
|
|
42
|
+
} | {
|
|
43
|
+
readonly kind: 'deny';
|
|
44
|
+
readonly reason: string;
|
|
38
45
|
} | {
|
|
39
46
|
readonly kind: 'ask';
|
|
40
47
|
readonly reason: string;
|
|
@@ -42,10 +49,15 @@ export type ApprovalVerdict = {
|
|
|
42
49
|
readonly fallback: ApprovalDetail;
|
|
43
50
|
};
|
|
44
51
|
export type ApprovalPolicy = (call: ApprovalCall) => ApprovalVerdict | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* 闸门的输入:`skipAsk` 为真表示会话已经不要审批提示(完全权限)—— 认领检查、`{blocked}` 与套件自己的
|
|
54
|
+
* `deny` 照旧,只是不再返回 `ask`;dsh 在 `approval: never` 下会把 `ask` 直接拒掉。
|
|
55
|
+
*/
|
|
45
56
|
export interface ApprovalContext {
|
|
46
57
|
readonly writes?: boolean | undefined;
|
|
47
58
|
readonly policy?: ApprovalPolicy | undefined;
|
|
48
59
|
readonly declaredNote?: boolean | undefined;
|
|
60
|
+
readonly skipAsk?: boolean | undefined;
|
|
49
61
|
readonly detailOf?: ((call: ApprovalCall) => ApprovalFacts | undefined | Promise<ApprovalFacts | undefined>) | undefined;
|
|
50
62
|
}
|
|
51
63
|
export declare function approvalFor(call: ApprovalCall, context?: ApprovalContext): Promise<AskDecision | undefined>;
|
|
@@ -65,6 +65,8 @@ export async function approvalFor(call, context = {}) {
|
|
|
65
65
|
}
|
|
66
66
|
if (verdict?.kind === 'read' || verdict?.kind === 'allow')
|
|
67
67
|
return undefined;
|
|
68
|
+
if (verdict?.kind === 'deny')
|
|
69
|
+
return { kind: 'deny', reason: verdict.reason };
|
|
68
70
|
if (verdict?.kind !== 'ask') {
|
|
69
71
|
return {
|
|
70
72
|
kind: 'deny',
|
|
@@ -81,6 +83,8 @@ export async function approvalFor(call, context = {}) {
|
|
|
81
83
|
}
|
|
82
84
|
if (facts !== undefined && 'blocked' in facts)
|
|
83
85
|
return { kind: 'deny', reason: facts.blocked };
|
|
86
|
+
if (context.skipAsk === true)
|
|
87
|
+
return undefined;
|
|
84
88
|
return {
|
|
85
89
|
kind: 'ask',
|
|
86
90
|
reason: verdict.reason,
|
package/dist/i18n/en.js
CHANGED
|
@@ -87,7 +87,7 @@ export const en = {
|
|
|
87
87
|
'panels.buildModule': 'Build a module',
|
|
88
88
|
'panels.failed': 'Could not save the change. Try again.',
|
|
89
89
|
'panels.dragHint': 'Drag to reorder',
|
|
90
|
-
'panels.unknownStep': 'No
|
|
90
|
+
'panels.unknownStep': 'No panel for this view yet',
|
|
91
91
|
'panels.labelWithHint': '{label} ({hint})',
|
|
92
92
|
'panels.hintJoin': '; ',
|
|
93
93
|
'panels.dep.failed': '⚠ failed to start',
|
|
@@ -122,6 +122,14 @@ export const en = {
|
|
|
122
122
|
'panels.market.install': 'Install',
|
|
123
123
|
'panels.market.update': 'Update',
|
|
124
124
|
'panels.market.swapSlow': 'Not swapped yet — maybe a slow or failed download. Press Update again; if it stays like this, restart dsh.',
|
|
125
|
+
'panels.market.updateNoChange': 'Not updated: you were on {from}, and after the run the disk still has that version; the newest on the registry is {latest}.',
|
|
126
|
+
'panels.market.updateUnknownVersion': '(unknown)',
|
|
127
|
+
'panels.market.updateGone': 'Not updated: after the run the module cannot be read from disk.',
|
|
128
|
+
'panels.market.updateRestored': 'Not updated: the new version was missing from disk, so {version} was put back.',
|
|
129
|
+
'panels.market.updateBehind': 'Installed {installed}, but the newest on the registry is {latest} — not the latest; you can update once more.',
|
|
130
|
+
'panels.market.selfUpdateFailed': 'Self-update failed: {reason}',
|
|
131
|
+
'panels.market.selfUpdateUnknown': 'the outside process left no reason (see ~/.dsh/workbench/self-update.log)',
|
|
132
|
+
'panels.market.selfUpdateRolledBack': 'Not swapped; rolled back to {version}.',
|
|
125
133
|
'panels.market.uninstall': 'Uninstall',
|
|
126
134
|
'panels.market.uninstallLabel': 'Uninstall {name}',
|
|
127
135
|
'panels.market.installing': 'Installing…',
|
|
@@ -152,7 +160,7 @@ export const en = {
|
|
|
152
160
|
'panels.market.pluginKeptUnsure': 'Files kept for now: some modules on this machine do not say what they use, so it is unclear who needs it.',
|
|
153
161
|
'panels.market.pluginKeptHeld': 'Files kept: this one is yours, and a module letting go will not remove it.',
|
|
154
162
|
'panels.market.pluginKeptUnnamed': 'Files kept for now: this one cannot be identified as a plugin, so it is unclear who needs it.',
|
|
155
|
-
'panels.market.pluginBroken': 'This install is broken: it cannot be identified
|
|
163
|
+
'panels.market.pluginBroken': 'This plugin install is broken: it cannot be identified. Uninstall it first, then ask the agent to reinstall it by package name.',
|
|
156
164
|
'panels.market.restartNeeded': 'The new version is installed — restart once to pick it up.',
|
|
157
165
|
'panels.market.foot': 'After installing, enable it in the panel page of that project.',
|
|
158
166
|
'panels.market.recheck': 'Check for updates',
|
|
@@ -197,7 +205,7 @@ export const en = {
|
|
|
197
205
|
'panels.market.add.cancelledTitle': 'Cancelled',
|
|
198
206
|
'panels.market.add.failureNetworkHost': 'Cannot reach {host}. Git URLs and .tgz links bypass the registry, so this machine needs direct access or a proxy; if the module is also on npm, use its package name instead.',
|
|
199
207
|
'panels.market.add.problemInvalid': 'Cannot read this package name or address: {reason}',
|
|
200
|
-
'panels.market.add.problemInstalled': 'This module is already installed',
|
|
208
|
+
'panels.market.add.problemInstalled': 'This module is already installed (add @version to switch versions)',
|
|
201
209
|
'panels.market.add.problemNotFound': 'No such module found',
|
|
202
210
|
'panels.market.add.problemNotPackage': 'That path does not exist or is not a valid module package',
|
|
203
211
|
'panels.market.add.problemNotBundle': 'This package cannot be installed here: {reason}. This entry recognises workbench modules and opencli plugins by package name, and installs either; but a git URL or a tarball does not reveal what it is — if it is really one of those two, use its package name or a local folder instead.',
|
|
@@ -218,7 +226,7 @@ export const en = {
|
|
|
218
226
|
'panels.market.add.failureIntegrity': 'The downloaded package failed its integrity check',
|
|
219
227
|
'panels.market.add.failureTimeout': 'The install timed out',
|
|
220
228
|
'panels.market.add.failurePnpmMissing': 'pnpm was not found, cannot install',
|
|
221
|
-
'panels.market.add.failureInstalled': 'It is already in this
|
|
229
|
+
'panels.market.add.failureInstalled': 'It is already installed in this workbench. The same package cannot be installed over itself: uninstall it first, then install again. The uninstall did not succeed this time.',
|
|
222
230
|
'panels.market.add.failureGeneric': 'Something went wrong during install — see the install details',
|
|
223
231
|
'panels.market.add.approveTitle': 'Your approval is needed for install scripts',
|
|
224
232
|
'panels.market.add.approveCaution': 'Only allow packages you trust: install scripts run on this machine with your permissions.',
|
|
@@ -256,7 +264,7 @@ export const en = {
|
|
|
256
264
|
'panels.market.add.doneApplied': 'Installed and live.',
|
|
257
265
|
'panels.market.add.doneRestart': 'Installed — restart once to pick it up.',
|
|
258
266
|
'panels.market.add.restartWhy': 'Why this needs a restart: {reason}',
|
|
259
|
-
'panels.market.add.restartWhy.no-hmr': 'this
|
|
267
|
+
'panels.market.add.restartWhy.no-hmr': 'this configuration only applies changes at startup (hot reload is off)',
|
|
260
268
|
'panels.market.add.restartWhy.package-moved': 'an installed package now resolves to another directory, or the change replaced something dsh itself provides',
|
|
261
269
|
'panels.market.add.restartWhy.host-module': 'the change reaches modules dsh itself loaded',
|
|
262
270
|
'panels.market.add.restartWhy.unmanaged-plugin': 'the change reaches a plugin running outside the plugin list',
|
|
@@ -271,17 +279,17 @@ export const en = {
|
|
|
271
279
|
'panels.market.add.remove': 'Remove it',
|
|
272
280
|
'panels.market.add.problem.invalidSpec': "That is not a spec we accept: it cannot be empty or start with a dash.",
|
|
273
281
|
'panels.market.add.problem.alreadyInstalled': 'That package is already in the profile (add @version to switch versions).',
|
|
274
|
-
'panels.market.add.problem.notFound': 'No such package on that source.',
|
|
275
|
-
'panels.market.add.problem.notAPackage': 'There is no package at that location.',
|
|
276
|
-
'panels.market.add.problem.notABundle': 'It is an npm package, but not a dsh plugin (
|
|
277
|
-
'panels.market.add.problem.network': 'The source is unreachable.',
|
|
278
|
-
'panels.market.add.problem.unknown': 'The check did not pass (reason unknown).',
|
|
282
|
+
'panels.market.add.problem.notFound': 'No such package on that source. Try another name or version.',
|
|
283
|
+
'panels.market.add.problem.notAPackage': 'There is no package at that location. Pick a folder that contains a package.json.',
|
|
284
|
+
'panels.market.add.problem.notABundle': 'It is an npm package, but not a dsh plugin (it is missing the dsh wiring declaration).',
|
|
285
|
+
'panels.market.add.problem.network': 'The source is unreachable. Check the network and retry.',
|
|
286
|
+
'panels.market.add.problem.unknown': 'The check did not pass (reason unknown). Open the install details for the raw output, or retry.',
|
|
279
287
|
'panels.market.add.reason.invalidSpec': 'the spec is not accepted',
|
|
280
288
|
'panels.market.add.reason.incompatible': 'it wants a different dsh version than this machine runs',
|
|
281
289
|
'panels.market.add.reason.notBundle': 'it is not a dsh plugin package',
|
|
282
290
|
'panels.market.add.reason.notRemovable': 'it ships with the installation and cannot be removed',
|
|
283
291
|
'panels.market.add.reason.bundleInUse': 'something is still using it',
|
|
284
|
-
'panels.market.add.reason.stopProfile': 'this
|
|
292
|
+
'panels.market.add.reason.stopProfile': 'this configuration has no hot reload, so stop the process first',
|
|
285
293
|
'panels.market.add.reason.staleApproval': 'the scripts to allow changed — start over',
|
|
286
294
|
'panels.market.add.reason.operationError': 'pnpm failed (see the install output)',
|
|
287
295
|
'panels.market.add.reason.buildBlocked': 'pnpm blocked install scripts',
|
|
@@ -336,11 +344,11 @@ export const en = {
|
|
|
336
344
|
'env.bridge.extensionLink': 'Get the extension in the Chrome Web Store',
|
|
337
345
|
'env.bridge.profile': 'Several browser profiles are connected but none is the default: list them (command below), then pick one.',
|
|
338
346
|
'env.bridge.stale': 'The default browser profile is stale (it names an extension instance that no longer exists): pick one again.',
|
|
339
|
-
'env.bridge.unknown': 'Could not tell what went wrong
|
|
347
|
+
'env.bridge.unknown': 'Could not tell what went wrong. Expand the raw output and follow the steps in it.',
|
|
340
348
|
'env.fix.title': 'How to fix it',
|
|
341
349
|
'env.fix.why': 'The workbench uses its own opencli (installed separately from the one in your terminal), and it is not set up on this machine yet.',
|
|
342
350
|
'env.fix.whyPath': 'opencli is installed, but this environment cannot find it \u2014 usually a PATH or shell-session issue.',
|
|
343
|
-
'env.fix.whyShell': 'The workbench has no shell channel, so it cannot fetch data \u2014
|
|
351
|
+
'env.fix.whyShell': 'The workbench has no shell channel, so it cannot fetch data \u2014 you cannot install this from here; someone needs to fix the background environment.',
|
|
344
352
|
'env.fix.step': 'Run this in a terminal, then hit Retry:',
|
|
345
353
|
'env.fix.stepPath': 'Open a new terminal window (or make sure npm\u2019s global bin directory is on PATH), then hit Retry.',
|
|
346
354
|
'env.fix.stepShell': 'Restart the workbench (or dsh); if it keeps happening, the shell channel is not wired up.',
|
|
@@ -352,9 +360,9 @@ export const en = {
|
|
|
352
360
|
'env.diy.ok': 'Available',
|
|
353
361
|
'env.diy.short': 'Cannot load',
|
|
354
362
|
'env.diy.hold': 'DIY mode cannot load \u2014 upgrade dsh, then hit Retry; or enter the workbench first.',
|
|
355
|
-
'env.diy.why': '
|
|
356
|
-
'env.diy.rows': 'This dsh is missing these
|
|
357
|
-
'env.diy.noRow': 'The health check did not find \u201cWorkbench DIY\u201d in dsh\u2019s
|
|
363
|
+
'env.diy.why': 'The dsh on this machine is older than the one this workbench was verified against, so DIY mode cannot load. Panels and everything else are unaffected. Upgrade dsh and restart.',
|
|
364
|
+
'env.diy.rows': 'This dsh is missing these items: {rows}',
|
|
365
|
+
'env.diy.noRow': 'The health check did not find \u201cWorkbench DIY mode\u201d in dsh\u2019s mode roster \u2014 the workbench install most likely did not include the matching mode patch.',
|
|
358
366
|
'env.diy.step': 'Upgrade dsh, then restart the workbench:',
|
|
359
367
|
'env.diy.continue': 'Enter the workbench anyway',
|
|
360
368
|
'env.copyCommand': 'Copy command',
|
|
@@ -390,6 +398,18 @@ export const en = {
|
|
|
390
398
|
'board.title': 'Workbench panel',
|
|
391
399
|
'panel.conversation': 'Conversation',
|
|
392
400
|
'panels.label': 'Global panels',
|
|
401
|
+
'workbenchSettings.nav': 'Workbench settings',
|
|
402
|
+
'workbenchSettings.lead': 'Settings the workbench itself owns live here.',
|
|
403
|
+
'sidebarEdition.nav': 'Session list',
|
|
404
|
+
'sidebarEdition.lead': 'Which whole left column to use: the official dsh one, or the workbench’s own.',
|
|
405
|
+
'sidebarEdition.official': 'Official',
|
|
406
|
+
'sidebarEdition.officialHint': 'Matches dsh exactly and stays stable: search, view options, show more, archive, add workspace — no waiting for us to catch up. Pick it to keep things simple.',
|
|
407
|
+
'sidebarEdition.custom': 'Custom',
|
|
408
|
+
'sidebarEdition.customHint': 'Built for multi-project work: one project per dropdown, recency-first sessions, edge fades, marquee, DIY new session. Easier when you juggle projects.',
|
|
409
|
+
'sidebarEdition.saving': 'Configuring…',
|
|
410
|
+
'sidebarEdition.reloadRequired': 'Saved. Reload the page to apply — no workbench restart needed.',
|
|
411
|
+
'sidebarEdition.reload': 'Reload page',
|
|
412
|
+
'sidebarEdition.failed': 'That choice did not save; try again.',
|
|
393
413
|
'configSync.nav': 'Config sync',
|
|
394
414
|
'configSync.lead': 'Bring over the rows another profile configures explicitly — pick any profile as the source.',
|
|
395
415
|
'configSync.source': 'Source',
|
|
@@ -412,8 +432,8 @@ export const en = {
|
|
|
412
432
|
'configSync.code.expandAria': 'Expand the diff ({count} more lines)',
|
|
413
433
|
'configSync.code.expand': 'Show {count} more lines',
|
|
414
434
|
'configSync.missing': '{pkg} is not installed: the row will not take effect — run `dsh plugin --profile {profile} add {pkg}`, or install it from the module market',
|
|
415
|
-
'configSync.apply': 'Sync {count} selected',
|
|
416
|
-
'configSync.applyNone': '
|
|
435
|
+
'configSync.apply': 'Sync {count} selected items',
|
|
436
|
+
'configSync.applyNone': 'Choose what to sync',
|
|
417
437
|
'configSync.applying': 'Writing…',
|
|
418
438
|
'configSync.applied': 'Written to the workbench config · applied',
|
|
419
439
|
'configSync.appliedIds': 'Written this time: {ids}',
|
|
@@ -421,7 +441,7 @@ export const en = {
|
|
|
421
441
|
'configSync.nothing': 'Nothing to sync',
|
|
422
442
|
'configSync.unreadable': 'Cannot read {path}: {reason}',
|
|
423
443
|
'configSync.noSource': 'This machine has no other profile to sync from',
|
|
424
|
-
'configSync.emptyProviders': 'The workbench has no model provider yet — sync the
|
|
444
|
+
'configSync.emptyProviders': 'The workbench has no model provider yet — sync the model-provider rows from some profile, or configure one under Models.',
|
|
425
445
|
'configSync.failed': 'The sync did not go through; try again.',
|
|
426
446
|
'debug.workspace': 'this workspace',
|
|
427
447
|
'debug.status': 'Debugging “{title}”',
|