@dsh-workbench/core 0.2.3 → 0.2.4

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/client.js CHANGED
@@ -2216,23 +2216,37 @@ window.__ModuleLoader__.load({
2216
2216
  function tailLines(text, lines = 6) {
2217
2217
  return String(text ?? "").trim().split("\n").slice(-lines).join("\n");
2218
2218
  }
2219
+ function candidateStarts(raw) {
2220
+ const starts = [];
2221
+ for (let index = 0; index < raw.length; index += 1) {
2222
+ const char = raw[index];
2223
+ if (char !== "[" && char !== "{") continue;
2224
+ if (index === 0 || raw[index - 1] === "\n") starts.push(index);
2225
+ }
2226
+ const earliest = [raw.indexOf("["), raw.indexOf("{")].filter((index) => index >= 0);
2227
+ if (earliest.length > 0) {
2228
+ const head = Math.min(...earliest);
2229
+ if (!starts.includes(head)) starts.push(head);
2230
+ }
2231
+ return starts;
2232
+ }
2219
2233
  function parseJsonLoose(text) {
2220
2234
  const raw = String(text ?? "").trim();
2221
2235
  if (!raw) return void 0;
2222
2236
  try {
2223
2237
  return JSON.parse(raw);
2224
2238
  } catch {
2225
- const starts = [raw.indexOf("["), raw.indexOf("{")].filter((index) => index >= 0);
2226
- if (starts.length === 0) return void 0;
2227
- const from = Math.min(...starts);
2228
- const close = raw[from] === "[" ? "]" : "}";
2229
- const to = raw.lastIndexOf(close);
2230
- if (to <= from) return void 0;
2231
- try {
2232
- return JSON.parse(raw.slice(from, to + 1));
2233
- } catch {
2234
- return;
2239
+ for (const from of candidateStarts(raw)) {
2240
+ const close = raw[from] === "[" ? "]" : "}";
2241
+ const to = raw.lastIndexOf(close);
2242
+ if (to <= from) continue;
2243
+ try {
2244
+ return JSON.parse(raw.slice(from, to + 1));
2245
+ } catch {
2246
+ continue;
2247
+ }
2235
2248
  }
2249
+ return;
2236
2250
  }
2237
2251
  }
2238
2252
  var MARKDOWN_IMAGE = /!\[[^\]]*\]\([^)]*\)/g;
@@ -2209,23 +2209,37 @@ function quoteShellArg(value) {
2209
2209
  function tailLines(text, lines = 6) {
2210
2210
  return String(text ?? "").trim().split("\n").slice(-lines).join("\n");
2211
2211
  }
2212
+ function candidateStarts(raw) {
2213
+ const starts = [];
2214
+ for (let index = 0; index < raw.length; index += 1) {
2215
+ const char = raw[index];
2216
+ if (char !== "[" && char !== "{") continue;
2217
+ if (index === 0 || raw[index - 1] === "\n") starts.push(index);
2218
+ }
2219
+ const earliest = [raw.indexOf("["), raw.indexOf("{")].filter((index) => index >= 0);
2220
+ if (earliest.length > 0) {
2221
+ const head = Math.min(...earliest);
2222
+ if (!starts.includes(head)) starts.push(head);
2223
+ }
2224
+ return starts;
2225
+ }
2212
2226
  function parseJsonLoose(text) {
2213
2227
  const raw = String(text ?? "").trim();
2214
2228
  if (!raw) return void 0;
2215
2229
  try {
2216
2230
  return JSON.parse(raw);
2217
2231
  } catch {
2218
- const starts = [raw.indexOf("["), raw.indexOf("{")].filter((index) => index >= 0);
2219
- if (starts.length === 0) return void 0;
2220
- const from = Math.min(...starts);
2221
- const close = raw[from] === "[" ? "]" : "}";
2222
- const to = raw.lastIndexOf(close);
2223
- if (to <= from) return void 0;
2224
- try {
2225
- return JSON.parse(raw.slice(from, to + 1));
2226
- } catch {
2227
- return;
2232
+ for (const from of candidateStarts(raw)) {
2233
+ const close = raw[from] === "[" ? "]" : "}";
2234
+ const to = raw.lastIndexOf(close);
2235
+ if (to <= from) continue;
2236
+ try {
2237
+ return JSON.parse(raw.slice(from, to + 1));
2238
+ } catch {
2239
+ continue;
2240
+ }
2228
2241
  }
2242
+ return;
2229
2243
  }
2230
2244
  }
2231
2245
  var MARKDOWN_IMAGE = /!\[[^\]]*\]\([^)]*\)/g;
@@ -2212,23 +2212,37 @@ function quoteShellArg(value) {
2212
2212
  function tailLines(text, lines = 6) {
2213
2213
  return String(text ?? "").trim().split("\n").slice(-lines).join("\n");
2214
2214
  }
2215
+ function candidateStarts(raw) {
2216
+ const starts = [];
2217
+ for (let index = 0; index < raw.length; index += 1) {
2218
+ const char = raw[index];
2219
+ if (char !== "[" && char !== "{") continue;
2220
+ if (index === 0 || raw[index - 1] === "\n") starts.push(index);
2221
+ }
2222
+ const earliest = [raw.indexOf("["), raw.indexOf("{")].filter((index) => index >= 0);
2223
+ if (earliest.length > 0) {
2224
+ const head = Math.min(...earliest);
2225
+ if (!starts.includes(head)) starts.push(head);
2226
+ }
2227
+ return starts;
2228
+ }
2215
2229
  function parseJsonLoose(text) {
2216
2230
  const raw = String(text ?? "").trim();
2217
2231
  if (!raw) return void 0;
2218
2232
  try {
2219
2233
  return JSON.parse(raw);
2220
2234
  } catch {
2221
- const starts = [raw.indexOf("["), raw.indexOf("{")].filter((index) => index >= 0);
2222
- if (starts.length === 0) return void 0;
2223
- const from = Math.min(...starts);
2224
- const close = raw[from] === "[" ? "]" : "}";
2225
- const to = raw.lastIndexOf(close);
2226
- if (to <= from) return void 0;
2227
- try {
2228
- return JSON.parse(raw.slice(from, to + 1));
2229
- } catch {
2230
- return;
2235
+ for (const from of candidateStarts(raw)) {
2236
+ const close = raw[from] === "[" ? "]" : "}";
2237
+ const to = raw.lastIndexOf(close);
2238
+ if (to <= from) continue;
2239
+ try {
2240
+ return JSON.parse(raw.slice(from, to + 1));
2241
+ } catch {
2242
+ continue;
2243
+ }
2231
2244
  }
2245
+ return;
2232
2246
  }
2233
2247
  }
2234
2248
  var MARKDOWN_IMAGE = /!\[[^\]]*\]\([^)]*\)/g;
@@ -201,23 +201,37 @@ function quoteShellArg(value) {
201
201
  function tailLines(text, lines = 6) {
202
202
  return String(text ?? "").trim().split("\n").slice(-lines).join("\n");
203
203
  }
204
+ function candidateStarts(raw) {
205
+ const starts = [];
206
+ for (let index = 0; index < raw.length; index += 1) {
207
+ const char = raw[index];
208
+ if (char !== "[" && char !== "{") continue;
209
+ if (index === 0 || raw[index - 1] === "\n") starts.push(index);
210
+ }
211
+ const earliest = [raw.indexOf("["), raw.indexOf("{")].filter((index) => index >= 0);
212
+ if (earliest.length > 0) {
213
+ const head = Math.min(...earliest);
214
+ if (!starts.includes(head)) starts.push(head);
215
+ }
216
+ return starts;
217
+ }
204
218
  function parseJsonLoose(text) {
205
219
  const raw = String(text ?? "").trim();
206
220
  if (!raw) return void 0;
207
221
  try {
208
222
  return JSON.parse(raw);
209
223
  } catch {
210
- const starts = [raw.indexOf("["), raw.indexOf("{")].filter((index) => index >= 0);
211
- if (starts.length === 0) return void 0;
212
- const from = Math.min(...starts);
213
- const close = raw[from] === "[" ? "]" : "}";
214
- const to = raw.lastIndexOf(close);
215
- if (to <= from) return void 0;
216
- try {
217
- return JSON.parse(raw.slice(from, to + 1));
218
- } catch {
219
- return;
224
+ for (const from of candidateStarts(raw)) {
225
+ const close = raw[from] === "[" ? "]" : "}";
226
+ const to = raw.lastIndexOf(close);
227
+ if (to <= from) continue;
228
+ try {
229
+ return JSON.parse(raw.slice(from, to + 1));
230
+ } catch {
231
+ continue;
232
+ }
220
233
  }
234
+ return;
221
235
  }
222
236
  }
223
237
  var PANEL_STATE_MAX_TEXT = 2e3;
@@ -2126,6 +2140,18 @@ function textOutput(text) {
2126
2140
  text
2127
2141
  }];
2128
2142
  }
2143
+ function textRender(_args, value) {
2144
+ const text = value?.text;
2145
+ return textOutput(typeof text === "string" ? text : JSON.stringify(value));
2146
+ }
2147
+ var TEXT_OUTPUT = {
2148
+ schema: {
2149
+ type: "object",
2150
+ properties: {},
2151
+ additionalProperties: true
2152
+ },
2153
+ render: textRender
2154
+ };
2129
2155
  function jsonText(value) {
2130
2156
  return JSON.stringify(value);
2131
2157
  }
@@ -7657,6 +7683,8 @@ function parseCommandRows(stdout) {
7657
7683
  name,
7658
7684
  description: textOf(record["description"]),
7659
7685
  access: textOf(record["access"]),
7686
+ browser: record["browser"] === true,
7687
+ siteSession: textOf(record["siteSession"]),
7660
7688
  ...textOf(record["domain"]) === "" ? {} : { domain: textOf(record["domain"]) },
7661
7689
  args: argsOf(record["args"])
7662
7690
  });
@@ -7669,6 +7697,9 @@ function commandOf(plugin, row) {
7669
7697
  name: row.name,
7670
7698
  description: row.description,
7671
7699
  access: row.access,
7700
+ browser: row.browser,
7701
+ siteSession: row.siteSession,
7702
+ ...row.domain === void 0 ? {} : { domain: row.domain },
7672
7703
  args: row.args
7673
7704
  };
7674
7705
  }
@@ -7842,6 +7873,8 @@ var SCHEMA_TYPE = {
7842
7873
  string: "string"
7843
7874
  };
7844
7875
  var KEY_ARG_LIMIT = 3;
7876
+ var RUN_CODE_TOOL = "run_code";
7877
+ var PLUGIN_PROMPT_BUDGET = 4e3;
7845
7878
  function pluginToolName(plugin, command) {
7846
7879
  return `${plugin}_${command}`.toLowerCase().replace(/[^a-z0-9_]+/g, "_").replace(/_{2,}/g, "_").replace(/^_+|_+$/g, "");
7847
7880
  }
@@ -7850,7 +7883,7 @@ function schemaTypeOf(arg) {
7850
7883
  }
7851
7884
  function propertyOf(arg) {
7852
7885
  const type = schemaTypeOf(arg);
7853
- const enumValues = arg.choices.length > 0 ? arg.choices.map((choice) => choice) : void 0;
7886
+ const enumValues = type === "string" && arg.choices.length > 0 ? [...arg.choices] : void 0;
7854
7887
  return {
7855
7888
  type,
7856
7889
  ...arg.help.trim() === "" ? {} : { description: arg.help.trim() },
@@ -7858,6 +7891,9 @@ function propertyOf(arg) {
7858
7891
  ...arg.defaultValue === void 0 ? {} : { default: arg.defaultValue }
7859
7892
  };
7860
7893
  }
7894
+ function pluginPromptChars(command) {
7895
+ return pluginToolDescription(command).length + command.args.reduce((sum, arg) => sum + arg.help.trim().length, 0);
7896
+ }
7861
7897
  function pluginToolParameters(command) {
7862
7898
  const properties = {};
7863
7899
  for (const arg of command.args) properties[arg.name] = propertyOf(arg);
@@ -7877,6 +7913,11 @@ function pluginToolDescription(command) {
7877
7913
  function pluginToolWrites(command) {
7878
7914
  return command.access !== "read";
7879
7915
  }
7916
+ function pluginToolSession(command) {
7917
+ if (!command.browser) return "none";
7918
+ if (command.siteSession === "persistent" || command.siteSession === "ephemeral") return command.siteSession;
7919
+ return command.access === "read" ? "persistent" : "ephemeral";
7920
+ }
7880
7921
  function valuesOf(raw) {
7881
7922
  return typeof raw === "object" && raw !== null ? raw : {};
7882
7923
  }
@@ -7893,9 +7934,9 @@ function pluginToolArgv(command, raw) {
7893
7934
  if (arg.positional) continue;
7894
7935
  const value = values[arg.name];
7895
7936
  if (value === void 0 || value === null) continue;
7896
- if (typeof value === "boolean") argv.push(`--${arg.name}`, value ? "true" : "false");
7897
- else if (Array.isArray(value)) argv.push(`--${arg.name}`, value.map((item) => String(item)).join(","));
7898
- else argv.push(`--${arg.name}`, String(value));
7937
+ if (typeof value === "boolean") argv.push(`--${arg.name}=${value ? "true" : "false"}`);
7938
+ else if (Array.isArray(value)) argv.push(`--${arg.name}=${value.map((item) => String(item)).join(",")}`);
7939
+ else argv.push(`--${arg.name}=${String(value)}`);
7899
7940
  }
7900
7941
  return argv;
7901
7942
  }
@@ -7933,11 +7974,6 @@ function pluginApprovalFor(command) {
7933
7974
  }
7934
7975
  //#endregion
7935
7976
  //#region src/shared/api/host/plugin-units.ts
7936
- var TOOL_OUTPUT_SCHEMA = {
7937
- type: "object",
7938
- properties: {},
7939
- additionalProperties: true
7940
- };
7941
7977
  function signatureOf(version, commands) {
7942
7978
  return [version, ...commands.map((command) => `${command.name}:${command.access}:${command.args.map((arg) => `${arg.name}${arg.required ? "!" : ""}`).join("+")}`)].join("|");
7943
7979
  }
@@ -7947,6 +7983,10 @@ function toolsOf(plugin, commands, taken) {
7947
7983
  const claimed = /* @__PURE__ */ new Set();
7948
7984
  for (const command of commands) {
7949
7985
  const name = pluginToolName(plugin, command.name);
7986
+ if (name === "run_code") {
7987
+ problems.push(`工具名 ${RUN_CODE_TOOL}(${plugin} ${command.name})是 dsh 的保留名(PTC 的传送工具)—— 这条命令这次不合成`);
7988
+ continue;
7989
+ }
7950
7990
  if (taken.has(name) || claimed.has(name)) {
7951
7991
  problems.push(`工具名 ${name}(${plugin} ${command.name})已经被占着 —— 这条命令这次不合成(先来的那份说了算)`);
7952
7992
  continue;
@@ -7989,12 +8029,15 @@ function planOf(options, registered) {
7989
8029
  problems.push(...built.problems);
7990
8030
  for (const tool of built.tools) taken.add(tool.name);
7991
8031
  if (built.tools.length === 0 && commands.length === set.commands.length) problems.push(`「${plugin}」的命令一条都没能合成工具`);
8032
+ const chars = built.tools.reduce((sum, tool) => sum + pluginPromptChars(tool.command), 0);
8033
+ if (chars > 4e3) problems.push(`「${plugin}」合成出来的 ${String(built.tools.length)} 把工具,描述与参数说明合起来 ${String(chars)} 字,超过 ${String(PLUGIN_PROMPT_BUDGET)} 字的合成面预算 —— 这些字每一步请求都跟着走,插件该精简或按工作区少开一点`);
7992
8034
  rows.push({
7993
8035
  plugin,
7994
8036
  pkg: row.pkg,
7995
8037
  version: set.version,
7996
8038
  commands: set.commands.length,
7997
8039
  synthesized: built.tools.length,
8040
+ chars,
7998
8041
  tools: built.tools.map((tool) => tool.name)
7999
8042
  });
8000
8043
  if (built.tools.length === 0) continue;
@@ -8015,7 +8058,7 @@ function planOf(options, registered) {
8015
8058
  problems
8016
8059
  };
8017
8060
  }
8018
- function faceOf(unit, opencliFor) {
8061
+ function faceOf(unit, opencliFor, note) {
8019
8062
  const byTool = new Map(unit.tools.map((tool) => [tool.name, tool.command]));
8020
8063
  const manifest = {
8021
8064
  id: unit.id,
@@ -8043,14 +8086,14 @@ function faceOf(unit, opencliFor) {
8043
8086
  name: tool.name,
8044
8087
  description: pluginToolDescription(tool.command),
8045
8088
  parameters: pluginToolParameters(tool.command),
8046
- output: {
8047
- schema: TOOL_OUTPUT_SCHEMA,
8048
- render: (_args, value) => textOutput(jsonText(value))
8049
- },
8089
+ output: TEXT_OUTPUT,
8050
8090
  async execute(raw, exec) {
8051
8091
  const workspace = sessionWorkspace(exec);
8052
8092
  try {
8053
- return (await opencli.json([tool.command.name, ...pluginToolArgv(tool.command, raw)], workspace === null ? {} : { workdir: workspace })).value;
8093
+ return { text: jsonText((await opencli.json([tool.command.name, ...pluginToolArgv(tool.command, raw)], {
8094
+ session: pluginToolSession(tool.command),
8095
+ ...workspace === null ? {} : { workdir: workspace }
8096
+ })).value) };
8054
8097
  } catch (error) {
8055
8098
  throw new Error(pluginLoginHint(error, tool.command.domain), { cause: error });
8056
8099
  }
@@ -8059,7 +8102,15 @@ function faceOf(unit, opencliFor) {
8059
8102
  return {
8060
8103
  routes: {},
8061
8104
  factsOf: () => [],
8062
- registerTools: () => definitions.map((definition) => tools.register(definition)),
8105
+ registerTools: () => {
8106
+ const disposers = [];
8107
+ for (const definition of definitions) try {
8108
+ disposers.push(tools.register(definition));
8109
+ } catch (error) {
8110
+ note(`「${unit.plugin}」的 ${definition.name} 这把工具没注册上(${error instanceof Error ? error.message : String(error)})—— 只废这一把,同插件其余命令照常`);
8111
+ }
8112
+ return disposers;
8113
+ },
8063
8114
  needsApproval: (call) => {
8064
8115
  const command = call.name === void 0 ? void 0 : byTool.get(call.name);
8065
8116
  return command === void 0 ? void 0 : pluginApprovalFor(command)(call);
@@ -8068,7 +8119,7 @@ function faceOf(unit, opencliFor) {
8068
8119
  }
8069
8120
  };
8070
8121
  }
8071
- function reconcile(registered, units, options) {
8122
+ function reconcile(registered, units, options, note) {
8072
8123
  const wanted = new Map(units.map((unit) => [unit.id, unit]));
8073
8124
  for (const [id, item] of [...registered]) {
8074
8125
  const next = wanted.get(id);
@@ -8081,12 +8132,13 @@ function reconcile(registered, units, options) {
8081
8132
  registered.set(unit.id, {
8082
8133
  signature: unit.signature,
8083
8134
  tools: unit.tools.map((tool) => tool.name),
8084
- drop: options.registry.registerPlugin(faceOf(unit, options.opencliFor))
8135
+ drop: options.registry.registerPlugin(faceOf(unit, options.opencliFor, note))
8085
8136
  });
8086
8137
  }
8087
8138
  }
8088
8139
  function createPluginUnits(options) {
8089
8140
  const registered = /* @__PURE__ */ new Map();
8141
+ const mountProblems = /* @__PURE__ */ new Set();
8090
8142
  let report = {
8091
8143
  ok: false,
8092
8144
  at: 0,
@@ -8096,6 +8148,18 @@ function createPluginUnits(options) {
8096
8148
  let inflight;
8097
8149
  let lastTouch = 0;
8098
8150
  let warned = "";
8151
+ function note(problem) {
8152
+ if (mountProblems.has(problem)) return;
8153
+ mountProblems.add(problem);
8154
+ options.logger?.warn?.(`[dsh-workbench] ${problem}`);
8155
+ }
8156
+ function snapshot() {
8157
+ const extra = [...mountProblems];
8158
+ return extra.length === 0 ? report : {
8159
+ ...report,
8160
+ problems: [...report.problems, ...extra]
8161
+ };
8162
+ }
8099
8163
  function warn(problems) {
8100
8164
  const text = [...problems].sort().join("\n");
8101
8165
  if (text === "" || text === warned) return;
@@ -8103,6 +8167,7 @@ function createPluginUnits(options) {
8103
8167
  options.logger?.warn?.(`[dsh-workbench] opencli 插件命令面:\n${text}`);
8104
8168
  }
8105
8169
  async function run(force) {
8170
+ mountProblems.clear();
8106
8171
  const probed = await options.catalog.refresh(force ? { force: true } : {});
8107
8172
  if (!probed.ok) {
8108
8173
  const problems = [...probed.problems, "这次探测没成功:上面这些插件行的工具面维持在上一份(不是\"这些插件没有命令\")"];
@@ -8113,10 +8178,10 @@ function createPluginUnits(options) {
8113
8178
  problems
8114
8179
  };
8115
8180
  warn(problems);
8116
- return report;
8181
+ return snapshot();
8117
8182
  }
8118
8183
  const plan = planOf(options, registered);
8119
- reconcile(registered, plan.units, options);
8184
+ reconcile(registered, plan.units, options, note);
8120
8185
  report = {
8121
8186
  ok: true,
8122
8187
  at: Date.now(),
@@ -8124,7 +8189,7 @@ function createPluginUnits(options) {
8124
8189
  problems: plan.problems
8125
8190
  };
8126
8191
  warn(plan.problems);
8127
- return report;
8192
+ return snapshot();
8128
8193
  }
8129
8194
  function refresh(callOptions = {}) {
8130
8195
  if (inflight !== void 0) return inflight;
@@ -8145,7 +8210,7 @@ function createPluginUnits(options) {
8145
8210
  options.logger?.warn?.(`[dsh-workbench] 探 opencli 插件命令面时抛了错:${String(error)}`);
8146
8211
  });
8147
8212
  },
8148
- report: () => report,
8213
+ report: () => snapshot(),
8149
8214
  dispose() {
8150
8215
  for (const item of registered.values()) item.drop();
8151
8216
  registered.clear();
@@ -0,0 +1,69 @@
1
+ import type { DshToolDefinition } from '@dsh-workbench/shared';
2
+ import { type WorkspaceStore } from '@dsh-workbench/shared/host';
3
+ import { createPluginUnits } from '../../../shared/api/host/plugin-units';
4
+ import { type UnitRegistry } from '../../../shared/api/host/unit-registry';
5
+ import type { PluginLedger } from '../model/plugin-ledger';
6
+ import { type PanelsService } from '../model/service';
7
+ export declare const COMMANDS: ({
8
+ site: string;
9
+ name: string;
10
+ description: string;
11
+ access: string;
12
+ browser: boolean;
13
+ siteSession: string;
14
+ domain: string;
15
+ args: {
16
+ name: string;
17
+ type: string;
18
+ required: boolean;
19
+ help: string;
20
+ }[];
21
+ } | {
22
+ site: string;
23
+ name: string;
24
+ description: string;
25
+ access: string;
26
+ browser: boolean;
27
+ args: {
28
+ name: string;
29
+ type: string;
30
+ required: boolean;
31
+ help: string;
32
+ }[];
33
+ siteSession?: undefined;
34
+ domain?: undefined;
35
+ })[];
36
+ export interface Harness {
37
+ readonly registry: UnitRegistry;
38
+ readonly panels: PanelsService;
39
+ readonly tools: Map<string, DshToolDefinition>;
40
+ readonly gate: {
41
+ deniedTools(workspace: string | null): readonly string[];
42
+ };
43
+ readonly manager: ReturnType<typeof createPluginUnits>;
44
+ readonly problems: string[];
45
+ readonly definitions: () => DshToolDefinition[];
46
+ readonly commands: () => readonly string[];
47
+ readonly opencliCalls: () => readonly {
48
+ readonly args: readonly string[];
49
+ readonly workdir?: string;
50
+ readonly session?: string;
51
+ }[];
52
+ readonly toolOf: (name: string) => DshToolDefinition | undefined;
53
+ readonly ownerOf: (name: string) => {
54
+ readonly needsApproval?: unknown;
55
+ readonly manifest: unknown;
56
+ } | undefined;
57
+ readonly units: () => readonly string[];
58
+ }
59
+ export declare function deny(h: Harness, workspace: string): string[];
60
+ export declare function harnessOf(options: {
61
+ readonly store: WorkspaceStore;
62
+ readonly ledger: PluginLedger;
63
+ readonly pluginRows: () => unknown;
64
+ readonly commands?: unknown;
65
+ readonly declared?: ReadonlyMap<string, ReadonlySet<string>>;
66
+ readonly moduleTools?: readonly string[];
67
+ readonly opencliReplies?: readonly unknown[];
68
+ readonly failTools?: readonly string[];
69
+ }): Harness;
@@ -14,6 +14,8 @@ export interface PluginCommand {
14
14
  readonly name: string;
15
15
  readonly description: string;
16
16
  readonly access: string;
17
+ readonly browser: boolean;
18
+ readonly siteSession: string;
17
19
  readonly domain?: string;
18
20
  readonly args: readonly PluginCommandArg[];
19
21
  }
@@ -32,6 +34,9 @@ export interface CommandRow {
32
34
  readonly name: string;
33
35
  readonly description: string;
34
36
  readonly access: string;
37
+ readonly browser: boolean;
38
+ readonly siteSession: string;
39
+ readonly domain?: string;
35
40
  readonly args: readonly PluginCommandArg[];
36
41
  }
37
42
  export interface PluginCatalogSnapshot {
@@ -1,9 +1,13 @@
1
- import type { ApprovalDetail, ApprovalPolicy } from '@dsh-workbench/shared/host';
1
+ import type { ApprovalDetail, ApprovalPolicy, OpencliSession } from '@dsh-workbench/shared/host';
2
2
  import type { PluginCommand } from './plugin-catalog';
3
+ export declare const RUN_CODE_TOOL = "run_code";
4
+ export declare const PLUGIN_PROMPT_BUDGET = 4000;
3
5
  export declare function pluginToolName(plugin: string, command: string): string;
6
+ export declare function pluginPromptChars(command: PluginCommand): number;
4
7
  export declare function pluginToolParameters(command: PluginCommand): Record<string, unknown>;
5
8
  export declare function pluginToolDescription(command: PluginCommand): string;
6
9
  export declare function pluginToolWrites(command: PluginCommand): boolean;
10
+ export declare function pluginToolSession(command: PluginCommand): OpencliSession;
7
11
  export declare function pluginToolArgv(command: PluginCommand, raw: unknown): string[];
8
12
  export declare function pluginKeyArgs(command: PluginCommand, raw: unknown): string;
9
13
  export declare function pluginApprovalQuestion(command: PluginCommand, raw: unknown): ApprovalDetail;
@@ -16,6 +16,7 @@ export interface PluginUnitRow {
16
16
  readonly version: string;
17
17
  readonly commands: number;
18
18
  readonly synthesized: number;
19
+ readonly chars: number;
19
20
  readonly tools: readonly string[];
20
21
  }
21
22
  export interface PluginUnitReport {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-workbench/core",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "个人工作台:Agent 工作台外壳(左栏 + 常驻对话 + 自研右侧数据面板)。",
5
5
  "type": "module",
6
6
  "icon": "./icon.svg",
@@ -87,7 +87,7 @@
87
87
  "access": "public"
88
88
  },
89
89
  "dependencies": {
90
- "@dsh-workbench/shared": "0.2.3"
90
+ "@dsh-workbench/shared": "0.2.4"
91
91
  },
92
92
  "scripts": {
93
93
  "build": "node scripts/build.mjs && node scripts/build-types.mjs",