@deepseek-ai/dsh-client-ui-goal 0.1.6-alpha.2 → 0.1.7-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 -1
- package/README.zh.md +3 -1
- package/lib/client.js +18 -9
- package/lib/types/client/activation-source.d.ts +1 -1
- package/lib/types/client/index.d.ts +8 -0
- package/package.json +17 -17
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-goal/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: ac23ac87c5b1bfe3eb849679c30a2ed283f33455
|
|
6
|
+
README.zh.md: bc9971a5e8917bf636de34a742530b113e4e4453
|
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ The Web GUI goal surface shows both the durable goal state and its current proce
|
|
|
25
25
|
<a id="use-this-package"></a>
|
|
26
26
|
## Use this package
|
|
27
27
|
|
|
28
|
-
Mount this plugin alongside `ui-conversation` and the goal domain package; the strip then appears as the second card in the composer-context stack (after Todo, before Queue) whenever the session has a goal. An armed active goal offers pause; an active-but-disarmed or paused goal offers resume; edit rewrites the objective; clear removes the goal and suppresses the strip until the projection catches up.
|
|
28
|
+
Mount this plugin alongside `ui-conversation` and the goal domain package; the strip then appears as the second card in the composer-context stack (after Todo, before Queue) whenever the session has a goal. Todo and Goal use the same panel elevation above the composer. An armed active goal offers pause; an active-but-disarmed or paused goal offers resume; edit rewrites the objective; clear removes the goal and suppresses the strip until the projection catches up.
|
|
29
29
|
|
|
30
30
|
### The command-input bubble
|
|
31
31
|
|
|
@@ -45,6 +45,8 @@ A rejected mutation surfaces the Remote error inline on the strip; loading, abse
|
|
|
45
45
|
|
|
46
46
|
The durable goal arrives through `useProjection('goal')` (seeded by the history tail page and updated by `session/projection` frames). The inject face carries a registrant-private activation hook source plus the four mutation verbs. That source starts only while the framework hook observes it, reads `ctx.remote.goals.get`, subscribes to `goal/activation-changed`, and refreshes on running-state or connection resets. Live-event epochs invalidate in-flight reads, so a stale HTTP result cannot overwrite a newer activation edge; running refreshes retain the last known activation until the read resolves. The strip owns no domain store or cross-plugin cache. Each mutation reads the CAS ref from the session's current projected value at call time, and the RPC's compare-and-set is the staleness guard. The strip single-flights mutations synchronously because a pending render cannot fence same-frame clicks. The command-input projection is a separate Conversation Definition that builds a `command-input` Chat Node before the generic command result Node; it never creates `user/message` or a model turn.
|
|
47
47
|
|
|
48
|
+
Activation reads hold a temporary `goalActivation` Client reference and send `goals.get` only after that Session's initial history open succeeds. A stale binding or failed open sends no RPC. Rejected reads are logged without changing the projected goal or last known activation; the temporary reference is released when the read settles.
|
|
49
|
+
|
|
48
50
|
</details>
|
|
49
51
|
|
|
50
52
|
-----
|
package/README.zh.md
CHANGED
|
@@ -25,7 +25,7 @@ Web GUI 的 goal 界面同时显示持久 goal 状态及当前的进程本地激
|
|
|
25
25
|
<a id="use-this-package"></a>
|
|
26
26
|
## 使用本包
|
|
27
27
|
|
|
28
|
-
与 `ui-conversation` 及 goal 领域包一起挂载本插件;只要会话存在目标,条带就会作为 composer 上下文堆栈的第二张卡片出现(位于 Todo 之后、Queue
|
|
28
|
+
与 `ui-conversation` 及 goal 领域包一起挂载本插件;只要会话存在目标,条带就会作为 composer 上下文堆栈的第二张卡片出现(位于 Todo 之后、Queue 之前)。Todo 与 Goal 使用相同的面板 elevation,使其位于 composer 层级之上。已 armed 的 active goal 提供暂停动作;active-but-disarmed 或 paused 的 goal 提供恢复;编辑重写目标文本;清除移除目标,并在投影追上之前抑制条带。
|
|
29
29
|
|
|
30
30
|
### 指令输入气泡
|
|
31
31
|
|
|
@@ -45,6 +45,8 @@ Web GUI 的 goal 界面同时显示持久 goal 状态及当前的进程本地激
|
|
|
45
45
|
|
|
46
46
|
持久 goal 经 `useProjection('goal')` 到达(由历史尾页播种、`session/projection` 帧更新)。注入面携带注册方私有的激活钩子源与四个变更动词。该源仅在框架钩子观察它时启动;启动后会读取 `ctx.remote.goals.get`、订阅 `goal/activation-changed`,并在 running 状态或连接重置时刷新。实时事件 epoch 会让在途读取失效,因此较旧的 HTTP 响应不能覆盖较新的 activation 变化;running 刷新会保留最后一次已知 activation,直到读取完成。条带不持有领域存储或跨插件缓存。每个变更在调用时从会话当前投影值读取 CAS ref,比较并交换(RPC 的 CAS)就是陈旧性护栏。由于 React 的 pending 渲染无法拦住同一帧内的点击,条带会同步为变更建立 single-flight 防护。指令输入投影是独立的 Conversation Definition,在通用命令结果 Node 之前构建 `command-input` Chat Node;它绝不创建 `user/message` 或模型轮次。
|
|
47
47
|
|
|
48
|
+
激活状态读取持有临时的 `goalActivation` 客户端引用,仅在该会话首次历史打开成功后发送 `goals.get`。binding 已失效或打开失败时不发送 RPC。读取被拒绝时记录错误,不改变投影中的目标或最后一次已知激活状态;读取结束时释放临时引用。
|
|
49
|
+
|
|
48
50
|
</details>
|
|
49
51
|
|
|
50
52
|
-----
|
package/lib/client.js
CHANGED
|
@@ -57,6 +57,8 @@ window.__ModuleLoader__.load({
|
|
|
57
57
|
revision: goal.revision,
|
|
58
58
|
activation: goal.activation
|
|
59
59
|
});
|
|
60
|
+
}, (error) => {
|
|
61
|
+
console.warn("[ui-goal] goal activation read failed:", error);
|
|
60
62
|
});
|
|
61
63
|
};
|
|
62
64
|
const refreshProjection = () => {
|
|
@@ -124,7 +126,7 @@ window.__ModuleLoader__.load({
|
|
|
124
126
|
}
|
|
125
127
|
//#endregion
|
|
126
128
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-goal/src/client/GoalBar.module.css.mjs
|
|
127
|
-
const css$1 = ".nLMEza_dock{box-sizing:border-box;width:calc(100% - var(--dsh-composer-side-clearance) - var(--dsh-composer-side-clearance) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset));margin:0 auto}.nLMEza_bar{box-sizing:border-box;width:100%;max-width:calc(var(--dsh-composer-card-max-width) - 4 * var(--dsh-composer-dock-inset))
|
|
129
|
+
const css$1 = ".nLMEza_dock{box-sizing:border-box;width:calc(100% - var(--dsh-composer-side-clearance) - var(--dsh-composer-side-clearance) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset) - var(--dsh-composer-dock-inset));margin:0 auto}.nLMEza_bar{isolation:isolate;box-sizing:border-box;width:100%;max-width:calc(var(--dsh-composer-card-max-width) - 4 * var(--dsh-composer-dock-inset));--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);height:36px;box-shadow:var(--dsw-elevation-panel);border:0;border-radius:12px;align-items:center;gap:10px;margin:0 auto;padding:4px 5px 4px 12px;display:flex;position:relative}.nLMEza_bar:before{z-index:-1;border-radius:inherit;background:var(--dsw-specific-menu);backdrop-filter:var(--dsw-menu-backdrop-filter);content:\"\";pointer-events:none;position:absolute;inset:0}.nLMEza_goalGlyph{color:var(--dsw-alias-label-tertiary);flex:none;display:inline-flex}.nLMEza_label{color:var(--dsw-alias-label-primary);flex:none;font-size:13px;font-weight:500;line-height:24px}.nLMEza_objective{min-width:0;color:var(--dsw-alias-label-primary-dimmed);text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:13px;line-height:20px;overflow:hidden}.nLMEza_error{min-width:0;color:var(--dsw-alias-state-error-primary);text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:12px;line-height:20px;overflow:hidden}.nLMEza_objectiveInput{border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-base);min-width:0;height:26px;color:var(--dsw-alias-label-primary);border-radius:6px;outline:none;flex:1;padding:0 8px;font-size:13px;line-height:20px}.nLMEza_objectiveInput:focus{border-color:var(--dsw-alias-state-business-primary)}.nLMEza_objectiveInput::placeholder{color:var(--dsw-alias-label-caption)}.nLMEza_actions{flex:none;align-items:center;gap:10px;display:flex}.nLMEza_iconBtn{corner-shape:round;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:999px;justify-content:center;align-items:center;padding:0;display:inline-flex}.nLMEza_iconBtn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.nLMEza_iconBtn:disabled{opacity:.4;cursor:default}";
|
|
128
130
|
const tagId$1 = "@deepseek-ai/dsh-client-ui-goal/GoalBar.module.css";
|
|
129
131
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
130
132
|
const tag = document.createElement("style");
|
|
@@ -242,7 +244,7 @@ window.__ModuleLoader__.load({
|
|
|
242
244
|
},
|
|
243
245
|
disabled: pending || draft.trim() === "",
|
|
244
246
|
"aria-label": t("action.save"),
|
|
245
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
247
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutlineRegular, { size: 14 })
|
|
246
248
|
})
|
|
247
249
|
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
248
250
|
label: t("action.cancel"),
|
|
@@ -256,7 +258,7 @@ window.__ModuleLoader__.load({
|
|
|
256
258
|
},
|
|
257
259
|
disabled: pending,
|
|
258
260
|
"aria-label": t("action.cancel"),
|
|
259
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
261
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCloseOutlineRegular, { size: 14 })
|
|
260
262
|
})
|
|
261
263
|
})]
|
|
262
264
|
})
|
|
@@ -275,7 +277,7 @@ window.__ModuleLoader__.load({
|
|
|
275
277
|
children: [
|
|
276
278
|
(0, react_jsx_runtime.jsx)("span", {
|
|
277
279
|
className: GoalBar_module_css_default.goalGlyph,
|
|
278
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
280
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconGoalOutlineRegular, { size: 14 })
|
|
279
281
|
}),
|
|
280
282
|
(0, react_jsx_runtime.jsx)("span", {
|
|
281
283
|
className: GoalBar_module_css_default.label,
|
|
@@ -305,7 +307,7 @@ window.__ModuleLoader__.load({
|
|
|
305
307
|
runAction(onPause);
|
|
306
308
|
},
|
|
307
309
|
"aria-label": t("action.pause"),
|
|
308
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
310
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPauseOutlineRegular, { size: 14 })
|
|
309
311
|
})
|
|
310
312
|
}),
|
|
311
313
|
showResume && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
@@ -320,7 +322,7 @@ window.__ModuleLoader__.load({
|
|
|
320
322
|
runAction(onResume);
|
|
321
323
|
},
|
|
322
324
|
"aria-label": t("action.resume"),
|
|
323
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
325
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlayOutlineRegular, { size: 14 })
|
|
324
326
|
})
|
|
325
327
|
}),
|
|
326
328
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
@@ -336,7 +338,7 @@ window.__ModuleLoader__.load({
|
|
|
336
338
|
setEditing(true);
|
|
337
339
|
},
|
|
338
340
|
"aria-label": t("action.edit"),
|
|
339
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
341
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular, { size: 14 })
|
|
340
342
|
})
|
|
341
343
|
}),
|
|
342
344
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
@@ -351,7 +353,7 @@ window.__ModuleLoader__.load({
|
|
|
351
353
|
handleClear(goal.id);
|
|
352
354
|
},
|
|
353
355
|
"aria-label": t("action.clear"),
|
|
354
|
-
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
356
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineRegular, { size: 14 })
|
|
355
357
|
})
|
|
356
358
|
})
|
|
357
359
|
]
|
|
@@ -558,7 +560,14 @@ window.__ModuleLoader__.load({
|
|
|
558
560
|
hooks: { goalActivation: createGoalActivationSource({
|
|
559
561
|
projection: binding.session.projections.faceOf("goal"),
|
|
560
562
|
session: binding.session,
|
|
561
|
-
getGoal: () =>
|
|
563
|
+
getGoal: async () => {
|
|
564
|
+
if (sessions.binding(sessionId) !== binding) throw new Error(`ui-goal: session "${sessionId}" is unavailable`);
|
|
565
|
+
return sessions.using(sessionId, { source: "goalActivation" }, async (reference) => {
|
|
566
|
+
const state = reference.binding.session.getSnapshot();
|
|
567
|
+
if (state.openState !== "open") throw state.openError ?? /* @__PURE__ */ new Error(`session "${sessionId}" is not open`);
|
|
568
|
+
return ctx.remote.goals.get(sessionId);
|
|
569
|
+
});
|
|
570
|
+
},
|
|
562
571
|
subscribeActivation: (listener) => ctx.remote.$on("goal/activation-changed", (event) => {
|
|
563
572
|
if (event.sessionId === sessionId) listener(event.goal);
|
|
564
573
|
}),
|
|
@@ -11,7 +11,7 @@ export interface GoalActivationDeps {
|
|
|
11
11
|
readonly session: HostObservable<{
|
|
12
12
|
readonly running: boolean;
|
|
13
13
|
}>;
|
|
14
|
-
/** Read
|
|
14
|
+
/** Read live activation after initial history; rejected reads leave the current snapshot unchanged. */
|
|
15
15
|
readonly getGoal: () => Promise<RemoteResult<GoalView | undefined>>;
|
|
16
16
|
/** Subscribe to activation edges after the transport delivers them. */
|
|
17
17
|
readonly subscribeActivation: (listener: (goal: GoalActivationChanged['goal']) => void) => () => void;
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* `useProjection('goal')`. A registrant-private activation hook source owns
|
|
5
5
|
* the live Remote read and event subscription; the inject face carries that
|
|
6
6
|
* hook plus the four mutation verbs through the generated Goal Remote API.
|
|
7
|
+
* Activation reads retain the Client Session through completion and wait
|
|
8
|
+
* for its initial history open to succeed before contacting the Host.
|
|
7
9
|
* This plugin does not create goals; deployments may expose /goal separately.
|
|
8
10
|
*/
|
|
9
11
|
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
@@ -11,6 +13,12 @@ import { type GoalKey } from './locales.ts';
|
|
|
11
13
|
export { GoalBar, GoalDock } from './GoalBar.tsx';
|
|
12
14
|
export type { GoalActionResult, GoalBarActions, } from './slots.ts';
|
|
13
15
|
export type { GoalKey } from './locales.ts';
|
|
16
|
+
declare module '@deepseek-ai/dsh-api-session-controller/client' {
|
|
17
|
+
interface SessionReferenceSourceMap {
|
|
18
|
+
/** A live goal read waiting for initial history and its RPC result. */
|
|
19
|
+
goalActivation: unknown;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
14
22
|
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
15
23
|
interface LocaleNamespaceMap {
|
|
16
24
|
/** The goal strip's copy. */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-client-ui-goal",
|
|
3
3
|
"description": "Session goal surface: GoalBar docked above the composer, read from the goal session projection",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.7-alpha.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -41,28 +41,28 @@
|
|
|
41
41
|
},
|
|
42
42
|
"license": "MIT",
|
|
43
43
|
"peerDependencies": {
|
|
44
|
-
"@deepseek-ai/cordis": "
|
|
44
|
+
"@deepseek-ai/cordis": "~4.0.4"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@testing-library/react": "^16.1.0",
|
|
48
48
|
"@types/react": "~18.3.1",
|
|
49
49
|
"react": "^18.2.0",
|
|
50
50
|
"react-dom": "^18.2.0",
|
|
51
|
-
"@deepseek-ai/dsh-api-
|
|
52
|
-
"@deepseek-ai/dsh-api-
|
|
53
|
-
"@deepseek-ai/dsh-client-locale": "
|
|
54
|
-
"@deepseek-ai/dsh-client-ui-chat": "
|
|
55
|
-
"@deepseek-ai/dsh-client-ui-conversation": "
|
|
56
|
-
"@deepseek-ai/dsh-client-ui-primitives": "
|
|
57
|
-
"@deepseek-ai/dsh-client-test-runtime": "
|
|
58
|
-
"@deepseek-ai/dsh-client-ui-slots": "
|
|
59
|
-
"@deepseek-ai/dsh-
|
|
60
|
-
"@deepseek-ai/dsh-client-ui-session": "
|
|
61
|
-
"@deepseek-ai/dsh-goal": "
|
|
62
|
-
"@deepseek-ai/dsh-
|
|
63
|
-
"@deepseek-ai/dsh-
|
|
64
|
-
"@deepseek-ai/
|
|
65
|
-
"@deepseek-ai/
|
|
51
|
+
"@deepseek-ai/dsh-api-session-controller": "0.1.7-alpha.2",
|
|
52
|
+
"@deepseek-ai/dsh-api-remotes": "0.1.7-alpha.2",
|
|
53
|
+
"@deepseek-ai/dsh-client-locale": "0.1.7-alpha.2",
|
|
54
|
+
"@deepseek-ai/dsh-client-ui-chat": "0.1.7-alpha.2",
|
|
55
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.7-alpha.2",
|
|
56
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.7-alpha.2",
|
|
57
|
+
"@deepseek-ai/dsh-client-test-runtime": "0.1.7-alpha.2",
|
|
58
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.7-alpha.2",
|
|
59
|
+
"@deepseek-ai/dsh-commands": "0.1.7-alpha.2",
|
|
60
|
+
"@deepseek-ai/dsh-client-ui-session": "0.1.7-alpha.2",
|
|
61
|
+
"@deepseek-ai/dsh-goal": "0.1.7-alpha.2",
|
|
62
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.7-alpha.2",
|
|
63
|
+
"@deepseek-ai/dsh-session": "0.1.7-alpha.2",
|
|
64
|
+
"@deepseek-ai/dsh-typert-protocol": "0.1.7-alpha.2",
|
|
65
|
+
"@deepseek-ai/cordis": "~4.0.4"
|
|
66
66
|
},
|
|
67
67
|
"files": [
|
|
68
68
|
"lib/index.js",
|