@deepseek-ai/dsh-client-ui-commands 0.1.2-rc.1 → 0.1.3-alpha.2
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 +2 -2
- package/README.md +3 -5
- package/README.zh.md +3 -5
- package/lib/client.js +23 -76
- package/lib/types/client/locales.d.ts +2 -2
- package/lib/types/client/service.d.ts +8 -7
- package/package.json +15 -15
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/client/ui-commands/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: e1264d10bd8ff807d8f348339e0c055607579407
|
|
6
|
+
README.zh.md: c5323149aea1e38ff09262db9bd2aacad7b284ea
|
package/README.md
CHANGED
|
@@ -31,9 +31,9 @@ Mount this plugin alongside `ui-input-trigger` and `ui-conversation`; the `/` so
|
|
|
31
31
|
|
|
32
32
|
A contribution is a client-owned command — a host-name collision fails loud. A decoration adds a bare-invocation popup to an EXISTING host command: the host command keeps its catalog row, its argument claim, and its lifecycle logging, and a decorated name with no host row in the session's directory never fires. Menu queries fuzzy-match ordered, case-insensitive subsequences of command names; prefixes rank first.
|
|
33
33
|
|
|
34
|
-
###
|
|
34
|
+
### Attachment-carrying submissions
|
|
35
35
|
|
|
36
|
-
When the composer submits with
|
|
36
|
+
When the composer submits with images or generic files, only a host command declaring `input.attachments` proceeds. Every other command route throws the localized `attachmentsUnsupported` refusal, rendered as a transient toast while the draft and attachment cards stay in place. Handler errors preserve the same draft state for retry.
|
|
37
37
|
|
|
38
38
|
-----
|
|
39
39
|
|
|
@@ -43,7 +43,7 @@ When the composer submits with image attachments, only a host command declaring
|
|
|
43
43
|
<details>
|
|
44
44
|
<summary>Implementation internals — click to expand</summary>
|
|
45
45
|
|
|
46
|
-
`src/client/contract.ts` is the fixed business contract: `CommandUiContract.register(name, spec)` and `decorate(name, spec)` are everything a business package consumes. `CommandDirectory` is the one wire-derived cache, keyed by session: ordinary sessions fetch through `command.list({sessionId})`, entries are soft-invalidated by the forwarded `commands/change` owner event and hard-invalidated by `connection/reset`, and epoch-guarded so a superseded pull can never overwrite a newer one. `matchSpace` answers synchronously from this cache only; `matchEnter` strong-waits it on the SubmitAttempt signal and rejects on warmup failure. After `command.execute` returns a matched result, the browser emits a local `command/executed` acknowledgment; other clients receive the durable command nodes through the Host event stream but never this acknowledgment. `PopupSelectController` is the headless shell state; `PopupSelectView` self-registers into `conversation.input.overlay` with per-session resolution.
|
|
46
|
+
`src/client/contract.ts` is the fixed business contract: `CommandUiContract.register(name, spec)` and `decorate(name, spec)` are everything a business package consumes. `CommandDirectory` is the one wire-derived cache, keyed by session: ordinary sessions fetch through `command.list({sessionId})`, entries are soft-invalidated by the forwarded `commands/change` owner event and hard-invalidated by `connection/reset`, and epoch-guarded so a superseded pull can never overwrite a newer one. `matchSpace` answers synchronously from this cache only; `matchEnter` strong-waits it on the SubmitAttempt signal and rejects on warmup failure. After `command.execute` returns a matched result, the browser emits a local `command/executed` acknowledgment; other clients receive the durable command nodes through the Host event stream but never this acknowledgment. `PopupSelectController` is the headless shell state; `PopupSelectView` self-registers into `conversation.input.overlay` with per-session resolution.
|
|
47
47
|
|
|
48
48
|
</details>
|
|
49
49
|
|
|
@@ -56,8 +56,6 @@ Read these pages when the command surface is not enough. They move from the comm
|
|
|
56
56
|
|
|
57
57
|
- [ui-input-trigger](../ui-input-trigger/README.md) — the pipeline the `/` source registers into.
|
|
58
58
|
- [ui-conversation](../ui-conversation/README.md) — declares the input overlay slot and owns the composer.
|
|
59
|
-
- [Web command surfaces and assembly](../../../.agents/notes/implemented/architecture/2026-07-25-web-command-surfaces-and-assembly.md) — the design decision behind the command surfaces.
|
|
60
|
-
- [Web slash-command fuzzy discovery](../../../.agents/notes/implemented/feature/2026-08-04-web-slash-command-fuzzy-discovery.md) — the menu ranking rationale.
|
|
61
59
|
- [Client package map](../README.md) — adjacent browser UI packages.
|
|
62
60
|
|
|
63
61
|
-----
|
package/README.zh.md
CHANGED
|
@@ -31,9 +31,9 @@ kind: "package-reference"
|
|
|
31
31
|
|
|
32
32
|
贡献项是客户端自有命令——与宿主命令同名会明确报错。装饰为**已存在的**宿主命令添加裸调用弹窗:宿主命令保留其目录行、参数声明与生命周期记账,被装饰的名字在会话目录中无宿主行时永不触发。菜单查询按顺序且不区分大小写地模糊匹配命令名的子序列;前缀排名最高。
|
|
33
33
|
|
|
34
|
-
###
|
|
34
|
+
### 带附件提交
|
|
35
35
|
|
|
36
|
-
composer
|
|
36
|
+
composer 携带图片或通用文件提交时,只有声明了 `input.attachments` 的宿主命令继续。其余命令路径都会抛出本地化的 `attachmentsUnsupported` 拒绝,以瞬态 toast 呈现,草稿与附件卡保持原位。处理器返回错误时保留相同草稿状态供用户重试。
|
|
37
37
|
|
|
38
38
|
-----
|
|
39
39
|
|
|
@@ -43,7 +43,7 @@ composer 携带图片附件提交时,只有声明了 `input.images` 的宿主
|
|
|
43
43
|
<details>
|
|
44
44
|
<summary>实现细节——点击展开</summary>
|
|
45
45
|
|
|
46
|
-
`src/client/contract.ts` 是固定的业务约定:`CommandUiContract.register(name, spec)` 与 `decorate(name, spec)` 是业务包消费的全部内容。`CommandDirectory` 是唯一的 wire 派生缓存,以会话为 key:普通会话经 `command.list({sessionId})` 拉取;条目由转发的 `commands/change` owner 事件软失效、由 `connection/reset` 硬失效,并以 epoch 把关,被取代的旧拉取永远无法覆盖更新的结果。`matchSpace` 只凭该缓存同步应答;`matchEnter` 在 SubmitAttempt 信号上强等缓存,预热失败即拒绝。`command.execute` 返回匹配结果后,浏览器发布本地 `command/executed` 确认;其他客户端经宿主事件流收到持久命令节点,但收不到这条确认。`PopupSelectController` 是不含界面的外壳状态;`PopupSelectView` 自注册进 `conversation.input.overlay
|
|
46
|
+
`src/client/contract.ts` 是固定的业务约定:`CommandUiContract.register(name, spec)` 与 `decorate(name, spec)` 是业务包消费的全部内容。`CommandDirectory` 是唯一的 wire 派生缓存,以会话为 key:普通会话经 `command.list({sessionId})` 拉取;条目由转发的 `commands/change` owner 事件软失效、由 `connection/reset` 硬失效,并以 epoch 把关,被取代的旧拉取永远无法覆盖更新的结果。`matchSpace` 只凭该缓存同步应答;`matchEnter` 在 SubmitAttempt 信号上强等缓存,预热失败即拒绝。`command.execute` 返回匹配结果后,浏览器发布本地 `command/executed` 确认;其他客户端经宿主事件流收到持久命令节点,但收不到这条确认。`PopupSelectController` 是不含界面的外壳状态;`PopupSelectView` 自注册进 `conversation.input.overlay`,按会话解析。
|
|
47
47
|
|
|
48
48
|
</details>
|
|
49
49
|
|
|
@@ -56,8 +56,6 @@ composer 携带图片附件提交时,只有声明了 `input.images` 的宿主
|
|
|
56
56
|
|
|
57
57
|
- [ui-input-trigger](../ui-input-trigger/README.zh.md)——`/` source 注册进的流水线。
|
|
58
58
|
- [ui-conversation](../ui-conversation/README.zh.md)——声明输入浮层槽位并拥有 composer。
|
|
59
|
-
- [Web 命令表面与组装](../../../.agents/notes/implemented/architecture/2026-07-25-web-command-surfaces-and-assembly.zh.md)——命令表面背后的设计决策。
|
|
60
|
-
- [Web 斜杠命令模糊发现](../../../.agents/notes/implemented/feature/2026-08-04-web-slash-command-fuzzy-discovery.zh.md)——菜单排名的原理。
|
|
61
59
|
- [客户端包映射](../README.zh.md)——相邻的浏览器 UI 包。
|
|
62
60
|
|
|
63
61
|
-----
|
package/lib/client.js
CHANGED
|
@@ -5,10 +5,10 @@ window.__ModuleLoader__.load({
|
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
7
|
let _deepseek_ai_cordis = require("@deepseek-ai/cordis");
|
|
8
|
+
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
8
9
|
let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
9
10
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
11
|
let react = require("react");
|
|
11
|
-
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
12
12
|
//#region lib/types/client/directory.js
|
|
13
13
|
/** One session key's cache cell. */
|
|
14
14
|
var Entry = class {
|
|
@@ -432,8 +432,9 @@ window.__ModuleLoader__.load({
|
|
|
432
432
|
* CommandUiRuntime (`ctx.commandUi`): the '/' command source over the
|
|
433
433
|
* session-keyed directory, the client-contribution registry, and the
|
|
434
434
|
* per-session popupSelect controllers. Candidate synthesis merges the host
|
|
435
|
-
* catalog with contributions by availability, then
|
|
436
|
-
*
|
|
435
|
+
* catalog with contributions by availability, then position filtering and
|
|
436
|
+
* the `/` menu's shared name ranking (ui-primitives `rankByName`); a
|
|
437
|
+
* host/contribution name collision fails loud. Every execute
|
|
437
438
|
* addresses the session's agent by sessionId — sessions are always
|
|
438
439
|
* agent-backed.
|
|
439
440
|
*/
|
|
@@ -443,60 +444,6 @@ window.__ModuleLoader__.load({
|
|
|
443
444
|
const separator = trimmed.search(/\s/u);
|
|
444
445
|
return (separator === -1 ? trimmed : trimmed.slice(0, separator)).slice(1);
|
|
445
446
|
}
|
|
446
|
-
/** Extra weight for command-name starts and separator boundaries. */
|
|
447
|
-
function boundaryBonus(name, index) {
|
|
448
|
-
return index === 0 || name.charAt(index - 1) === "-" || name.charAt(index - 1) === "_" ? 8 : 0;
|
|
449
|
-
}
|
|
450
|
-
/**
|
|
451
|
-
* Score the strongest ordered-subsequence alignment in O(name × query).
|
|
452
|
-
* Boundary and adjacent matches earn weight; skipped and leading characters
|
|
453
|
-
* cost weight.
|
|
454
|
-
*/
|
|
455
|
-
function fuzzyScore(name, query) {
|
|
456
|
-
if (query === "") return 0;
|
|
457
|
-
if (query.length > name.length) return void 0;
|
|
458
|
-
const noMatch = Number.NEGATIVE_INFINITY;
|
|
459
|
-
let previous = Array(name.length).fill(noMatch);
|
|
460
|
-
for (let index = 0; index < name.length; index++) if (name.charAt(index) === query.charAt(0)) previous[index] = 1 + boundaryBonus(name, index) - index;
|
|
461
|
-
for (let queryIndex = 1; queryIndex < query.length; queryIndex++) {
|
|
462
|
-
const current = Array(name.length).fill(noMatch);
|
|
463
|
-
let bestGapped = noMatch;
|
|
464
|
-
for (let index = 0; index < name.length; index++) {
|
|
465
|
-
const gappedIndex = index - 2;
|
|
466
|
-
if (gappedIndex >= 0) {
|
|
467
|
-
const prior = previous[gappedIndex] ?? noMatch;
|
|
468
|
-
if (prior !== noMatch) bestGapped = Math.max(bestGapped, prior + gappedIndex);
|
|
469
|
-
}
|
|
470
|
-
if (name.charAt(index) !== query.charAt(queryIndex)) continue;
|
|
471
|
-
const bonus = 1 + boundaryBonus(name, index);
|
|
472
|
-
const adjacent = index > 0 ? previous[index - 1] ?? noMatch : noMatch;
|
|
473
|
-
if (adjacent !== noMatch) current[index] = adjacent + bonus + 4;
|
|
474
|
-
if (bestGapped !== noMatch) current[index] = Math.max(current[index] ?? noMatch, bestGapped + bonus + 1 - index);
|
|
475
|
-
}
|
|
476
|
-
previous = current;
|
|
477
|
-
}
|
|
478
|
-
let best = noMatch;
|
|
479
|
-
for (const score of previous) best = Math.max(best, score);
|
|
480
|
-
return best === noMatch ? void 0 : best;
|
|
481
|
-
}
|
|
482
|
-
/** Case-insensitive fuzzy filtering with stable ordering for equal matches. */
|
|
483
|
-
function fuzzyCandidates(candidates, rawQuery) {
|
|
484
|
-
const query = rawQuery.toLowerCase();
|
|
485
|
-
if (query === "") return candidates;
|
|
486
|
-
const ranked = [];
|
|
487
|
-
candidates.forEach((candidate, index) => {
|
|
488
|
-
const name = candidate.name.toLowerCase();
|
|
489
|
-
const score = fuzzyScore(name, query);
|
|
490
|
-
if (score !== void 0) ranked.push({
|
|
491
|
-
candidate,
|
|
492
|
-
index,
|
|
493
|
-
prefix: name.startsWith(query),
|
|
494
|
-
score
|
|
495
|
-
});
|
|
496
|
-
});
|
|
497
|
-
ranked.sort((left, right) => Number(right.prefix) - Number(left.prefix) || right.score - left.score || left.index - right.index);
|
|
498
|
-
return ranked.map((match) => match.candidate);
|
|
499
|
-
}
|
|
500
447
|
/** Command surface: session-keyed directory + '/' source + contribution registry + per-session popups. */
|
|
501
448
|
var CommandUiRuntime = class extends _deepseek_ai_cordis.Service {
|
|
502
449
|
static inject = [
|
|
@@ -637,7 +584,7 @@ window.__ModuleLoader__.load({
|
|
|
637
584
|
if (this.focusHooks.get(id) === focus) this.focusHooks.delete(id);
|
|
638
585
|
};
|
|
639
586
|
}
|
|
640
|
-
/** Menu candidates: host catalog + contribution availability, then position filtering and
|
|
587
|
+
/** Menu candidates: host catalog + contribution availability, then position filtering and the shared name ranking. */
|
|
641
588
|
async candidates(session, req) {
|
|
642
589
|
const list = await this.directory.ensureReady(session.sessionId, req.signal);
|
|
643
590
|
const rows = [];
|
|
@@ -658,7 +605,7 @@ window.__ModuleLoader__.load({
|
|
|
658
605
|
description: contribution.description
|
|
659
606
|
});
|
|
660
607
|
}
|
|
661
|
-
return
|
|
608
|
+
return (0, _deepseek_ai_dsh_client_ui_primitives.rankByName)(rows.filter((c) => req.position === "leading" || c.hint === void 0), req.query);
|
|
662
609
|
}
|
|
663
610
|
/** Decision table, menu column: contribution/decorated-host → popup; host input → claim; host bare → detached execute. */
|
|
664
611
|
dispatch(pick) {
|
|
@@ -704,10 +651,10 @@ window.__ModuleLoader__.load({
|
|
|
704
651
|
* bare host commands act on the bare token only; leadingInput claims
|
|
705
652
|
* args-tolerant.
|
|
706
653
|
*
|
|
707
|
-
* Envelope policy: an enter submission carrying
|
|
708
|
-
* through a command declaring
|
|
654
|
+
* Envelope policy: an enter submission carrying attachments resolves only
|
|
655
|
+
* through a command declaring attachment acceptance. Every other command route —
|
|
709
656
|
* popup, non-accepting claim, bare detached execute — throws the refusal
|
|
710
|
-
* so the machine surfaces one composer notice and the draft and
|
|
657
|
+
* so the machine surfaces one composer notice and the draft and attachments
|
|
711
658
|
* stay in place; nothing executes and nothing is dropped.
|
|
712
659
|
*/
|
|
713
660
|
async matchEnter(session, line, signal, envelope) {
|
|
@@ -718,13 +665,13 @@ window.__ModuleLoader__.load({
|
|
|
718
665
|
const bare = ws === -1;
|
|
719
666
|
const name = token.slice(1);
|
|
720
667
|
if (name === "") return void 0;
|
|
721
|
-
const
|
|
722
|
-
throw new Error(this.t("notice.
|
|
668
|
+
const refuseAttachments = () => {
|
|
669
|
+
throw new Error(this.t("notice.attachmentsUnsupported", { command: name }));
|
|
723
670
|
};
|
|
724
671
|
const contribution = this.live.contributions.get(name);
|
|
725
672
|
if (contribution !== void 0 && contribution.available(session)) {
|
|
726
673
|
if (!bare) return void 0;
|
|
727
|
-
if (envelope.
|
|
674
|
+
if (envelope.attachments > 0) refuseAttachments();
|
|
728
675
|
this.openPopup(name, contribution.ui, session, {
|
|
729
676
|
via: "enter",
|
|
730
677
|
token
|
|
@@ -737,7 +684,7 @@ window.__ModuleLoader__.load({
|
|
|
737
684
|
if (bare) {
|
|
738
685
|
const decoration = this.live.decorations.get(name);
|
|
739
686
|
if (decoration !== void 0 && decoration.available(session)) {
|
|
740
|
-
if (envelope.
|
|
687
|
+
if (envelope.attachments > 0) refuseAttachments();
|
|
741
688
|
this.openPopup(name, decoration.ui, session, {
|
|
742
689
|
via: "enter",
|
|
743
690
|
token
|
|
@@ -746,11 +693,11 @@ window.__ModuleLoader__.load({
|
|
|
746
693
|
}
|
|
747
694
|
}
|
|
748
695
|
if (desc.input !== void 0) {
|
|
749
|
-
if (envelope.
|
|
696
|
+
if (envelope.attachments > 0 && desc.input.attachments !== true) refuseAttachments();
|
|
750
697
|
return { claim: this.leadingClaim(desc, session) };
|
|
751
698
|
}
|
|
752
699
|
if (!bare) return void 0;
|
|
753
|
-
if (envelope.
|
|
700
|
+
if (envelope.attachments > 0) refuseAttachments();
|
|
754
701
|
this.consumeVia(session.sessionId, {
|
|
755
702
|
via: "enter",
|
|
756
703
|
token
|
|
@@ -770,8 +717,8 @@ window.__ModuleLoader__.load({
|
|
|
770
717
|
return {
|
|
771
718
|
token,
|
|
772
719
|
...desc.input !== void 0 ? { hint: desc.input.hint } : {},
|
|
773
|
-
...desc.input?.
|
|
774
|
-
submit: (args, _actx,
|
|
720
|
+
...desc.input?.attachments === true ? { attachments: true } : {},
|
|
721
|
+
submit: (args, _actx, attachments) => this.execute(session, token + args, attachments)
|
|
775
722
|
};
|
|
776
723
|
}
|
|
777
724
|
/**
|
|
@@ -782,18 +729,18 @@ window.__ModuleLoader__.load({
|
|
|
782
729
|
* executor durably logged the lifecycle (`command/run`/`command/done`) and
|
|
783
730
|
* the outcome renders as a persistent flow node — the composer never
|
|
784
731
|
* echoes it. A handler error result reports an error outcome so the
|
|
785
|
-
* composer keeps the
|
|
732
|
+
* composer keeps the draft and attachments for correction.
|
|
786
733
|
* A refused call throws.
|
|
787
734
|
*/
|
|
788
|
-
async execute(session, line,
|
|
789
|
-
const result = await this.ctx.remote.commands.execute(session.sessionId, line,
|
|
735
|
+
async execute(session, line, attachments = []) {
|
|
736
|
+
const result = await this.ctx.remote.commands.execute(session.sessionId, line, attachments);
|
|
790
737
|
if (!result.ok) throw new Error(`command.execute failed: ${result.error.code}: ${result.error.message}`);
|
|
791
738
|
if (result.value === void 0) return {
|
|
792
739
|
kind: "error",
|
|
793
740
|
text: `unknown or malformed command: ${line}`
|
|
794
741
|
};
|
|
795
742
|
this.notifyExecuted(session.sessionId, submittedCommandName(line), result.value.result);
|
|
796
|
-
if (
|
|
743
|
+
if (attachments.length > 0 && result.value.result.kind === "error") return {
|
|
797
744
|
kind: "error",
|
|
798
745
|
text: result.value.result.text
|
|
799
746
|
};
|
|
@@ -1087,7 +1034,7 @@ window.__ModuleLoader__.load({
|
|
|
1087
1034
|
"status.empty": "无选项",
|
|
1088
1035
|
"overlay.aria": "/{command} 选项",
|
|
1089
1036
|
"listbox.aria": "/{command} 匹配项",
|
|
1090
|
-
"notice.
|
|
1037
|
+
"notice.attachmentsUnsupported": "/{command} 不接受附件,请先移除附件"
|
|
1091
1038
|
};
|
|
1092
1039
|
/** English dictionary, checked complete against the zh key set. */
|
|
1093
1040
|
const en = {
|
|
@@ -1098,7 +1045,7 @@ window.__ModuleLoader__.load({
|
|
|
1098
1045
|
"status.empty": "No options",
|
|
1099
1046
|
"overlay.aria": "/{command} options",
|
|
1100
1047
|
"listbox.aria": "/{command} matches",
|
|
1101
|
-
"notice.
|
|
1048
|
+
"notice.attachmentsUnsupported": "/{command} does not accept attachments; remove them first"
|
|
1102
1049
|
};
|
|
1103
1050
|
//#endregion
|
|
1104
1051
|
//#region lib/types/client/index.js
|
|
@@ -8,7 +8,7 @@ export declare const zh: {
|
|
|
8
8
|
'status.empty': string;
|
|
9
9
|
'overlay.aria': string;
|
|
10
10
|
'listbox.aria': string;
|
|
11
|
-
'notice.
|
|
11
|
+
'notice.attachmentsUnsupported': string;
|
|
12
12
|
};
|
|
13
13
|
/** The command namespace key union. */
|
|
14
14
|
export type CommandKey = keyof typeof zh;
|
|
@@ -21,6 +21,6 @@ export declare const en: {
|
|
|
21
21
|
'status.empty': string;
|
|
22
22
|
'overlay.aria': string;
|
|
23
23
|
'listbox.aria': string;
|
|
24
|
-
'notice.
|
|
24
|
+
'notice.attachmentsUnsupported': string;
|
|
25
25
|
};
|
|
26
26
|
//# sourceMappingURL=locales.d.ts.map
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* CommandUiRuntime (`ctx.commandUi`): the '/' command source over the
|
|
3
3
|
* session-keyed directory, the client-contribution registry, and the
|
|
4
4
|
* per-session popupSelect controllers. Candidate synthesis merges the host
|
|
5
|
-
* catalog with contributions by availability, then
|
|
6
|
-
*
|
|
5
|
+
* catalog with contributions by availability, then position filtering and
|
|
6
|
+
* the `/` menu's shared name ranking (ui-primitives `rankByName`); a
|
|
7
|
+
* host/contribution name collision fails loud. Every execute
|
|
7
8
|
* addresses the session's agent by sessionId — sessions are always
|
|
8
9
|
* agent-backed.
|
|
9
10
|
*/
|
|
@@ -73,7 +74,7 @@ export declare class CommandUiRuntime extends Service implements CommandUiContra
|
|
|
73
74
|
* @returns the unbind disposer.
|
|
74
75
|
*/
|
|
75
76
|
bindComposerFocus(id: SessionId, focus: () => void): () => void;
|
|
76
|
-
/** Menu candidates: host catalog + contribution availability, then position filtering and
|
|
77
|
+
/** Menu candidates: host catalog + contribution availability, then position filtering and the shared name ranking. */
|
|
77
78
|
private candidates;
|
|
78
79
|
/** Decision table, menu column: contribution/decorated-host → popup; host input → claim; host bare → detached execute. */
|
|
79
80
|
private dispatch;
|
|
@@ -85,10 +86,10 @@ export declare class CommandUiRuntime extends Service implements CommandUiContra
|
|
|
85
86
|
* bare host commands act on the bare token only; leadingInput claims
|
|
86
87
|
* args-tolerant.
|
|
87
88
|
*
|
|
88
|
-
* Envelope policy: an enter submission carrying
|
|
89
|
-
* through a command declaring
|
|
89
|
+
* Envelope policy: an enter submission carrying attachments resolves only
|
|
90
|
+
* through a command declaring attachment acceptance. Every other command route —
|
|
90
91
|
* popup, non-accepting claim, bare detached execute — throws the refusal
|
|
91
|
-
* so the machine surfaces one composer notice and the draft and
|
|
92
|
+
* so the machine surfaces one composer notice and the draft and attachments
|
|
92
93
|
* stay in place; nothing executes and nothing is dropped.
|
|
93
94
|
*/
|
|
94
95
|
private matchEnter;
|
|
@@ -104,7 +105,7 @@ export declare class CommandUiRuntime extends Service implements CommandUiContra
|
|
|
104
105
|
* executor durably logged the lifecycle (`command/run`/`command/done`) and
|
|
105
106
|
* the outcome renders as a persistent flow node — the composer never
|
|
106
107
|
* echoes it. A handler error result reports an error outcome so the
|
|
107
|
-
* composer keeps the
|
|
108
|
+
* composer keeps the draft and attachments for correction.
|
|
108
109
|
* A refused call throws.
|
|
109
110
|
*/
|
|
110
111
|
private execute;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-client-ui-commands",
|
|
3
3
|
"description": "Client command surface: global directory cache, '/' source, three command UI kinds, popupSelect registry",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.3-alpha.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -46,21 +46,21 @@
|
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/react": "~18.3.1",
|
|
48
48
|
"react": "^18.2.0",
|
|
49
|
-
"@deepseek-ai/dsh-api-remotes": "^0.1.
|
|
50
|
-
"@deepseek-ai/dsh-client-connection": "^0.1.
|
|
51
|
-
"@deepseek-ai/dsh-client-locale": "^0.1.
|
|
52
|
-
"@deepseek-ai/dsh-client-test-runtime": "^0.1.
|
|
53
|
-
"@deepseek-ai/dsh-client-ui-
|
|
54
|
-
"@deepseek-ai/dsh-client-ui-
|
|
55
|
-
"@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.
|
|
56
|
-
"@deepseek-ai/dsh-client-ui-slots": "^0.1.
|
|
57
|
-
"@deepseek-ai/dsh-commands": "^0.1.2-rc.1",
|
|
49
|
+
"@deepseek-ai/dsh-api-remotes": "^0.1.3-alpha.2",
|
|
50
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.3-alpha.2",
|
|
51
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.3-alpha.2",
|
|
52
|
+
"@deepseek-ai/dsh-client-test-runtime": "^0.1.3-alpha.2",
|
|
53
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.3-alpha.2",
|
|
54
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.3-alpha.2",
|
|
55
|
+
"@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.3-alpha.2",
|
|
56
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.3-alpha.2",
|
|
58
57
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
59
|
-
"@deepseek-ai/dsh-api-session-controller": "^0.1.
|
|
60
|
-
"@deepseek-ai/dsh-client-store": "^0.1.
|
|
61
|
-
"@deepseek-ai/dsh-session": "^0.1.
|
|
62
|
-
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.
|
|
63
|
-
"@deepseek-ai/dsh-client-ui-session": "^0.1.
|
|
58
|
+
"@deepseek-ai/dsh-api-session-controller": "^0.1.3-alpha.2",
|
|
59
|
+
"@deepseek-ai/dsh-client-store": "^0.1.3-alpha.2",
|
|
60
|
+
"@deepseek-ai/dsh-session": "^0.1.3-alpha.2",
|
|
61
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.3-alpha.2",
|
|
62
|
+
"@deepseek-ai/dsh-client-ui-session": "^0.1.3-alpha.2",
|
|
63
|
+
"@deepseek-ai/dsh-commands": "^0.1.3-alpha.2"
|
|
64
64
|
},
|
|
65
65
|
"files": [
|
|
66
66
|
"lib/index.js",
|