@deepseek-harness-tui/dsh-tui 0.10.1 → 0.10.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.md +5 -146
- package/lib/types/adapter/ports/channel-session.d.ts +3 -1
- package/lib/types/adapter/ports/channel-session.d.ts.map +1 -1
- package/lib/types/components/Chat/JobCard.d.ts.map +1 -1
- package/lib/types/components/Chat/JobCard.js +8 -1
- package/lib/types/components/Markdown.d.ts +2 -2
- package/lib/types/components/Markdown.d.ts.map +1 -1
- package/lib/types/components/Markdown.js +28 -3
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +10 -9
- package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
- package/lib/types/components/StreamingMarkdown.js +61 -9
- package/lib/types/dsh-adapter/channel/binding-events.d.ts +5 -0
- package/lib/types/dsh-adapter/channel/binding-events.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/binding-events.js +12 -2
- package/lib/types/dsh-adapter/channel/input-delivery.d.ts +5 -2
- package/lib/types/dsh-adapter/channel/input-delivery.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/input-delivery.js +71 -7
- package/lib/types/dsh-adapter/channel/permissions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/permissions.js +10 -7
- package/lib/types/dsh-adapter/channel/session-rewind.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-rewind.js +9 -2
- package/lib/types/dsh-adapter/channel/session-tree-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-tree-actions.js +9 -3
- package/lib/types/dsh-adapter/channel/skill-catalog.d.ts +8 -2
- package/lib/types/dsh-adapter/channel/skill-catalog.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/skill-catalog.js +49 -17
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +5 -2
- package/lib/types/dsh-adapter/compat/liveSession.d.ts +5 -3
- package/lib/types/dsh-adapter/compat/liveSession.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/liveSession.js +5 -3
- package/lib/types/dsh-adapter/sessions/digest.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/digest.js +40 -19
- package/lib/types/dsh-adapter/sessions/frames.js +2 -0
- package/lib/types/dsh-adapter/sessions/list.js +3 -3
- package/lib/types/dsh-adapter/sessions/store.d.ts +2 -2
- package/lib/types/dsh-adapter/sessions/store.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/store.js +12 -11
- package/lib/types/dsh-adapter/sessions/types.d.ts +2 -0
- package/lib/types/dsh-adapter/sessions/types.d.ts.map +1 -1
- package/lib/types/ink/components/ScrollBox.d.ts.map +1 -1
- package/lib/types/ink/components/ScrollBox.js +30 -33
- package/lib/types/ink/dom.d.ts.map +1 -1
- package/lib/types/ink/dom.js +32 -64
- package/lib/types/ink/get-max-width.d.ts +7 -15
- package/lib/types/ink/get-max-width.d.ts.map +1 -1
- package/lib/types/ink/get-max-width.js +7 -20
- package/lib/types/ink/ink.d.ts +1 -0
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +22 -3
- package/lib/types/ink/layout/node.d.ts +2 -0
- package/lib/types/ink/layout/node.d.ts.map +1 -1
- package/lib/types/ink/layout/yoga.d.ts +1 -0
- package/lib/types/ink/layout/yoga.d.ts.map +1 -1
- package/lib/types/ink/layout/yoga.js +3 -0
- package/lib/types/ink/node-cache.d.ts +11 -0
- package/lib/types/ink/node-cache.d.ts.map +1 -1
- package/lib/types/ink/node-cache.js +3 -0
- package/lib/types/ink/output.d.ts +6 -1
- package/lib/types/ink/output.d.ts.map +1 -1
- package/lib/types/ink/output.js +55 -65
- package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
- package/lib/types/ink/render-node-to-output.js +92 -67
- package/lib/types/ink/tabstops.d.ts +3 -2
- package/lib/types/ink/tabstops.d.ts.map +1 -1
- package/lib/types/ink/tabstops.js +5 -4
- package/lib/types/ink/wrap-text.js +2 -2
- package/lib/types/native-ts/yoga-layout/index.d.ts +8 -3
- package/lib/types/native-ts/yoga-layout/index.d.ts.map +1 -1
- package/lib/types/native-ts/yoga-layout/index.js +23 -8
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +20 -8
- package/package.json +3 -2
|
@@ -14,6 +14,59 @@ export function createInputDelivery(ctx, owner, binding, state, notify, trackPen
|
|
|
14
14
|
* through this chain to keep the send order FIFO.
|
|
15
15
|
*/
|
|
16
16
|
let inputChain = Promise.resolve();
|
|
17
|
+
/**
|
|
18
|
+
* Attached-context registry (issue #842): `deliverUserText(..., attach)`
|
|
19
|
+
* records the model-facing companion message under the DELIVERED user
|
|
20
|
+
* message's id. The resident `agent/pre-step` listener below claims an entry
|
|
21
|
+
* exactly once — on the step that admits its user message — and appends it
|
|
22
|
+
* AFTER `next()`'s batch, the same shape and order as dsh-tool-skill's
|
|
23
|
+
* gesture boundary. The map is emptied on claim, on inbox discard and on
|
|
24
|
+
* channel release (owner.own below).
|
|
25
|
+
*/
|
|
26
|
+
const attachedByMessageId = new Map();
|
|
27
|
+
/** Claim the batch's registered attachments, deleting each entry so a later
|
|
28
|
+
* step can never append it a second time. */
|
|
29
|
+
const claimAttachments = (messages) => {
|
|
30
|
+
if (attachedByMessageId.size === 0)
|
|
31
|
+
return [];
|
|
32
|
+
const attached = [];
|
|
33
|
+
for (const message of messages) {
|
|
34
|
+
const context = attachedByMessageId.get(message.id);
|
|
35
|
+
if (context === undefined)
|
|
36
|
+
continue;
|
|
37
|
+
attachedByMessageId.delete(message.id);
|
|
38
|
+
attached.push(context);
|
|
39
|
+
}
|
|
40
|
+
return attached;
|
|
41
|
+
};
|
|
42
|
+
/** Drop an attachment whose user message will never be claimed (inbox discard). */
|
|
43
|
+
const retireAttachment = (messageId) => {
|
|
44
|
+
attachedByMessageId.delete(messageId);
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Resident `agent/pre-step` listener (D3/D4): `await next()` lets every
|
|
48
|
+
* later transform run first; the waterfall applies AFTER-next transforms in
|
|
49
|
+
* registration order, so registering at channel construction keeps this
|
|
50
|
+
* append LAST (范例: presets/liangshen/instruction-hint.mjs). A rejected
|
|
51
|
+
* step never claims — no context message without its admitted user line —
|
|
52
|
+
* and a released owner returns the decision untouched. One `owner.own`
|
|
53
|
+
* lifetime covers both the subscription and the whole registry (D5).
|
|
54
|
+
*/
|
|
55
|
+
const disposePreStep = ctx.on('agent/pre-step', async (_payload, next) => {
|
|
56
|
+
const decision = await next();
|
|
57
|
+
if (decision.kind === 'reject')
|
|
58
|
+
return decision;
|
|
59
|
+
if (!owner.current())
|
|
60
|
+
return decision;
|
|
61
|
+
const attached = claimAttachments(decision.messages);
|
|
62
|
+
if (attached.length === 0)
|
|
63
|
+
return decision;
|
|
64
|
+
return { ...decision, messages: [...decision.messages, ...attached] };
|
|
65
|
+
});
|
|
66
|
+
owner.own(() => {
|
|
67
|
+
disposePreStep();
|
|
68
|
+
attachedByMessageId.clear();
|
|
69
|
+
});
|
|
17
70
|
/** D-6 fence: the submission belongs to the session it was typed in. */
|
|
18
71
|
const current = (origin) => owner.current() && binding.agent === origin.agent && state().agentBindingGeneration === origin.generation;
|
|
19
72
|
/** D-6: bind the submission to the session it was typed in AT ENQUEUE
|
|
@@ -36,7 +89,7 @@ export function createInputDelivery(ctx, owner, binding, state, notify, trackPen
|
|
|
36
89
|
* never the file dump) and each resolved reference appends a model-facing
|
|
37
90
|
* attachment block. The pending preview tracks the typed text.
|
|
38
91
|
*/
|
|
39
|
-
const deliverUserText = async (text, placement, images, origin) => {
|
|
92
|
+
const deliverUserText = async (text, placement, images, origin, attach) => {
|
|
40
93
|
const orderedImages = orderedComposerImages(text, images, origin.stagedImages);
|
|
41
94
|
// A `[Image #N]` placeholder whose staging was evicted (FIFO cap) or
|
|
42
95
|
// whose draft capability was lost (history/rewind/session switch) would
|
|
@@ -58,6 +111,11 @@ export function createInputDelivery(ctx, owner, binding, state, notify, trackPen
|
|
|
58
111
|
content: expansion.blocks,
|
|
59
112
|
source: { kind: 'user' },
|
|
60
113
|
});
|
|
114
|
+
// The message is real from here on: remember its attached context BEFORE
|
|
115
|
+
// the agent call so the pre-step listener can find it (D6). A throwing
|
|
116
|
+
// followup/steer rolls both the pending preview and this entry back.
|
|
117
|
+
if (attach !== undefined)
|
|
118
|
+
attachedByMessageId.set(message.id, attach);
|
|
61
119
|
// Track BEFORE the agent call: a synchronous throw inside
|
|
62
120
|
// followup/steer rolls the preview back; otherwise the inbox events
|
|
63
121
|
// retire it once the message is claimed or discarded.
|
|
@@ -69,6 +127,8 @@ export function createInputDelivery(ctx, owner, binding, state, notify, trackPen
|
|
|
69
127
|
origin.agent.followup(message);
|
|
70
128
|
}
|
|
71
129
|
catch (error) {
|
|
130
|
+
if (attach !== undefined)
|
|
131
|
+
attachedByMessageId.delete(message.id);
|
|
72
132
|
untrackPending(message.id);
|
|
73
133
|
throw error;
|
|
74
134
|
}
|
|
@@ -156,7 +216,7 @@ export function createInputDelivery(ctx, owner, binding, state, notify, trackPen
|
|
|
156
216
|
* stale text with a notice instead of sending the old conversation's
|
|
157
217
|
* words to the new session.
|
|
158
218
|
*/
|
|
159
|
-
const runUserTextDecision = async (text, placement, images, origin) => {
|
|
219
|
+
const runUserTextDecision = async (text, placement, images, origin, attach) => {
|
|
160
220
|
// Stale detection compares the AGENT REFERENCE, not the id: session ids
|
|
161
221
|
// are reusable (A → /new → /resume A lands back on the same id with a
|
|
162
222
|
// fresh agent), so an id check has an ABA hole. Both origin values are
|
|
@@ -198,7 +258,7 @@ export function createInputDelivery(ctx, owner, binding, state, notify, trackPen
|
|
|
198
258
|
text = decision.text.trim();
|
|
199
259
|
}
|
|
200
260
|
try {
|
|
201
|
-
await deliverUserText(text, placement, images, origin);
|
|
261
|
+
await deliverUserText(text, placement, images, origin, attach);
|
|
202
262
|
}
|
|
203
263
|
catch (error) {
|
|
204
264
|
// The FIFO must survive a failed expansion/send: surface it, then let
|
|
@@ -208,18 +268,20 @@ export function createInputDelivery(ctx, owner, binding, state, notify, trackPen
|
|
|
208
268
|
notify(t('send-failed', { err: message }), { color: 'error' });
|
|
209
269
|
}
|
|
210
270
|
};
|
|
211
|
-
const dispatchUserText = (text, placement, images = []) => {
|
|
271
|
+
const dispatchUserText = (text, placement, images = [], attach) => {
|
|
212
272
|
const origin = captureOrigin();
|
|
213
273
|
const capturedImages = composer.captureDraftImages(text, images);
|
|
214
|
-
inputChain = inputChain.then(() => runUserTextDecision(text, placement, capturedImages, origin)).catch((error) => {
|
|
274
|
+
inputChain = inputChain.then(() => runUserTextDecision(text, placement, capturedImages, origin, attach)).catch((error) => {
|
|
215
275
|
// The chain must survive a failed decision: log, then continue with
|
|
216
276
|
// the next queued submission.
|
|
217
277
|
ctx.logger.warn('dsh-tui: tui/input dispatch failed: %o', error);
|
|
218
278
|
});
|
|
219
279
|
};
|
|
220
280
|
/** Public companion for callers that own a line but not a draft (skill
|
|
221
|
-
* registrations): same decision pass and FIFO as a typed submit.
|
|
222
|
-
|
|
281
|
+
* registrations): same decision pass and FIFO as a typed submit. The
|
|
282
|
+
* optional `attach` is registered by `deliverUserText` only once its user
|
|
283
|
+
* message is real, then appended at the end of that message's step batch. */
|
|
284
|
+
const deliverUserTextNow = (text, placement, images = [], attach) => dispatchUserText(text, placement, images, attach);
|
|
223
285
|
/** Main's `clearStagedImages`: revoke capabilities AND release the FIFO so
|
|
224
286
|
* a task parked on the replaced session cannot wedge the new one, and drop
|
|
225
287
|
* every pending-decision indicator owned by the session being replaced. */
|
|
@@ -232,6 +294,8 @@ export function createInputDelivery(ctx, owner, binding, state, notify, trackPen
|
|
|
232
294
|
return {
|
|
233
295
|
dispatchUserText,
|
|
234
296
|
deliverUserText: deliverUserTextNow,
|
|
297
|
+
claimAttachments,
|
|
298
|
+
retireAttachment,
|
|
235
299
|
withDecisionPending,
|
|
236
300
|
clearStagedImages,
|
|
237
301
|
stageImage: (input) => composer.stageImage(input),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/permissions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAE5D,OAAO,KAAK,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAA;AAE3G,eAAO,MAAM,wBAAwB,WAAW,CAAA;AAEhD,eAAO,MAAM,4BAA4B,MAAM,CAAA;AAE/C,eAAO,MAAM,mCAAmC,MAAM,CAAA;AAEtD;;gFAEgF;AAChF,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACtE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;IACnC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;CAClD;AAED,iDAAiD;AACjD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC,SAAS,CAAC,CAAA;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAA;CAChD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,oEAAoE;AACpE,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,uBAAuB,GAAG,SAAS,CAE7F;AAED;;iFAEiF;AACjF,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,wBAAwB,GAAG,wBAAwB,CAQ3G;AAED,wBAAgB,6BAA6B,IAAI,SAAS,sBAAsB,EAAE,CAkBjF;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC,GAAG,wBAAwB,CAU5G;AAED,wBAAgB,mCAAmC,IAAI,wBAAwB,CAE9E;AAED,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,GAAG,SAAS,CAclG;AAED;;;0CAG0C;AAC1C,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,sBAAsB,EAAE,CAwBhG;AAED;;;wCAGwC;AACxC,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GACf,wBAAwB,
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/permissions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAE5D,OAAO,KAAK,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAA;AAE3G,eAAO,MAAM,wBAAwB,WAAW,CAAA;AAEhD,eAAO,MAAM,4BAA4B,MAAM,CAAA;AAE/C,eAAO,MAAM,mCAAmC,MAAM,CAAA;AAEtD;;gFAEgF;AAChF,MAAM,WAAW,uBAAwB,SAAQ,uBAAuB;IACtE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;IACnC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;CAClD;AAED,iDAAiD;AACjD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC,SAAS,CAAC,CAAA;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAA;CAChD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,oEAAoE;AACpE,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,uBAAuB,GAAG,SAAS,CAE7F;AAED;;iFAEiF;AACjF,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,wBAAwB,GAAG,wBAAwB,CAQ3G;AAED,wBAAgB,6BAA6B,IAAI,SAAS,sBAAsB,EAAE,CAkBjF;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC,GAAG,wBAAwB,CAU5G;AAED,wBAAgB,mCAAmC,IAAI,wBAAwB,CAE9E;AAED,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,GAAG,SAAS,CAclG;AAED;;;0CAG0C;AAC1C,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,sBAAsB,EAAE,CAwBhG;AAED;;;wCAGwC;AACxC,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,GACf,wBAAwB,CAyE1B"}
|
|
@@ -80,16 +80,16 @@ export function normalizePermissionPresetOption(value) {
|
|
|
80
80
|
* bundles (see `canonicalPresetFor`). */
|
|
81
81
|
export function permissionBundlesFromService(service) {
|
|
82
82
|
const runtime = permissionPresetRuntime(service);
|
|
83
|
-
|
|
84
|
-
if (typeof resolve !== 'function')
|
|
83
|
+
if (runtime === undefined || typeof runtime.resolve !== 'function')
|
|
85
84
|
return [];
|
|
86
|
-
const names = Array.isArray(runtime
|
|
85
|
+
const names = Array.isArray(runtime.names) ? runtime.names : [];
|
|
87
86
|
const bundles = [];
|
|
88
87
|
for (const name of names) {
|
|
89
88
|
if (typeof name !== 'string')
|
|
90
89
|
continue;
|
|
91
90
|
try {
|
|
92
|
-
|
|
91
|
+
// The registry resolves atoms on instance state; never detach `resolve`.
|
|
92
|
+
const spec = runtime.resolve(name);
|
|
93
93
|
if (!isRecord(spec))
|
|
94
94
|
continue;
|
|
95
95
|
const sandbox = spec.sandbox;
|
|
@@ -115,12 +115,15 @@ export function permissionPresetSnapshotFromService(service, subject) {
|
|
|
115
115
|
return unavailablePermissionPresetSnapshot();
|
|
116
116
|
try {
|
|
117
117
|
const capturedNames = Array.isArray(runtime.names) ? runtime.names : [];
|
|
118
|
-
const current = runtime.current;
|
|
119
|
-
const optionOf = runtime.optionOf;
|
|
120
118
|
if (capturedNames.length === 0)
|
|
121
119
|
return unavailablePermissionPresetSnapshot();
|
|
122
|
-
if (typeof current !== 'function' || typeof optionOf !== 'function')
|
|
120
|
+
if (typeof runtime.current !== 'function' || typeof runtime.optionOf !== 'function') {
|
|
123
121
|
return unavailablePermissionPresetSnapshot();
|
|
122
|
+
}
|
|
123
|
+
// Readback lives on the registry instance; bind so the calls below keep
|
|
124
|
+
// reaching it through the same object instead of a detached reference.
|
|
125
|
+
const current = runtime.current.bind(runtime);
|
|
126
|
+
const optionOf = runtime.optionOf.bind(runtime);
|
|
124
127
|
const names = [];
|
|
125
128
|
for (const name of capturedNames) {
|
|
126
129
|
if (typeof name !== 'string' || name.trim() === '' || name === PERMISSION_PRESET_CUSTOM || names.includes(name)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-rewind.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/session-rewind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,wBAAwB,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAQvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEvD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtD,KAAK,WAAW,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,KAAK,GAAG,UAAU,GAAG,OAAO,CAAC,CAAA;AAgB/E,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC,CAAA;IACjF,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC9B,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,YAAY,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,SAAS,GAAG,MAAM,CAAA;IAC1K,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1F,IAEa,KAAK,OAAO,EAAE,OAAM,MAAM,GAAG,IAAW,KAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"session-rewind.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/session-rewind.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,wBAAwB,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAQvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEvD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtD,KAAK,WAAW,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,KAAK,GAAG,UAAU,GAAG,OAAO,CAAC,CAAA;AAgB/E,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC,CAAA;IACjF,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC9B,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,YAAY,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,SAAS,GAAG,MAAM,CAAA;IAC1K,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1F,IAEa,KAAK,OAAO,EAAE,OAAM,MAAM,GAAG,IAAW,KAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwFhF"}
|
|
@@ -76,7 +76,14 @@ export function createRewindToAction(ctx, state, deps) {
|
|
|
76
76
|
parentSession: deps.binding.agent.session.id,
|
|
77
77
|
agentPreset: composed.agentPreset,
|
|
78
78
|
agentOptions: { provider: state.provider, model: state.model },
|
|
79
|
-
setup:
|
|
79
|
+
setup: async (agentCtx, agent) => {
|
|
80
|
+
// The cut keeps pre-turn inbox insertions but drops their claims.
|
|
81
|
+
// Newer hosts replay those inherited splices, so cancel the restored
|
|
82
|
+
// queue durably in the CHILD before publication or preset setup.
|
|
83
|
+
// Clearing only state.pending would hide, not revoke, the old work.
|
|
84
|
+
agent.inbox.clear();
|
|
85
|
+
return composed.setup?.(agentCtx, agent);
|
|
86
|
+
},
|
|
80
87
|
})));
|
|
81
88
|
}
|
|
82
89
|
catch {
|
|
@@ -97,7 +104,7 @@ export function createRewindToAction(ctx, state, deps) {
|
|
|
97
104
|
await deps.binding.abandon(handle);
|
|
98
105
|
return null;
|
|
99
106
|
}
|
|
100
|
-
const sourceSessionId = deps.adoptForkedAgent(handle, adoption,
|
|
107
|
+
const sourceSessionId = deps.adoptForkedAgent(handle, adoption, snapshotLiveSessionEvents(handle.agent.session), composed.agentPreset, childId);
|
|
101
108
|
try {
|
|
102
109
|
void dispatchTuiDecision(ctx, 'tui/rewind-done', {
|
|
103
110
|
text: row.text,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-tree-actions.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/session-tree-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,wBAAwB,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AASvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtD,KAAK,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,KAAK,GAAG,UAAU,GAAG,OAAO,CAAC,CAAA;AAYnF,+GAA+G;AAC/G,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC,CAAA;IACjF,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC9B,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,YAAY,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,SAAS,GAAG,MAAM,CAAA;IAC1K,qBAAqB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;CACnG,IAEa,WAAW,MAAM,EAAE,KAAK,MAAM,EAAE,OAAM,QAAQ,GAAG,MAAiB,KAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"session-tree-actions.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/session-tree-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,wBAAwB,CAAA;AAC7E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AASvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACtD,KAAK,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,KAAK,GAAG,UAAU,GAAG,OAAO,CAAC,CAAA;AAYnF,+GAA+G;AAC/G,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACpC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC,CAAA;IACjF,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC9B,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,YAAY,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,SAAS,GAAG,MAAM,CAAA;IAC1K,qBAAqB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;CACnG,IAEa,WAAW,MAAM,EAAE,KAAK,MAAM,EAAE,OAAM,QAAQ,GAAG,MAAiB,KAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4G1G"}
|
|
@@ -96,11 +96,17 @@ export function createTreeRewindAction(ctx, state, deps) {
|
|
|
96
96
|
parentSession: SessionId(sessionId),
|
|
97
97
|
agentPreset: composed.agentPreset,
|
|
98
98
|
agentOptions: { provider: state.provider, model: state.model },
|
|
99
|
-
setup: closeAfterCreate ? async (agentCtx, agent) => {
|
|
99
|
+
setup: closeAfterCreate || mode === 'rewind' ? async (agentCtx, agent) => {
|
|
100
100
|
// V3 requires seed.length === inheritedEventCount. The constructor
|
|
101
101
|
// inserts the inherited marker, then these closers belong to the
|
|
102
102
|
// child and persist before publication, without falsifying the cut.
|
|
103
|
-
|
|
103
|
+
if (closeAfterCreate)
|
|
104
|
+
closeLiveForkTurn(agent.session, target.closeTurn);
|
|
105
|
+
// Re-editing starts with no historical pending work. Cancel through
|
|
106
|
+
// the child's Inbox so a later resume cannot resurrect the queue.
|
|
107
|
+
// A plain fork deliberately keeps its separate semantics.
|
|
108
|
+
if (mode === 'rewind')
|
|
109
|
+
agent.inbox.clear();
|
|
104
110
|
return composed.setup?.(agentCtx, agent);
|
|
105
111
|
} : composed.setup,
|
|
106
112
|
})));
|
|
@@ -124,7 +130,7 @@ export function createTreeRewindAction(ctx, state, deps) {
|
|
|
124
130
|
deps.notify(t('rewind-session-changed'), { color: 'error' });
|
|
125
131
|
return null;
|
|
126
132
|
}
|
|
127
|
-
const replay = closeAfterCreate ? snapshotLiveSessionEvents(handle.agent.session) : seed;
|
|
133
|
+
const replay = closeAfterCreate || mode === 'rewind' ? snapshotLiveSessionEvents(handle.agent.session) : seed;
|
|
128
134
|
const sourceSessionId = deps.adoptForkedAgent(handle, adoption, replay, composed.agentPreset, childId);
|
|
129
135
|
deps.notifySessionSwitched(mode === 'fork' ? 'fork' : 'rewind', String(childId), sourceSessionId);
|
|
130
136
|
return restoredText;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Context } from '@deepseek-ai/cordis';
|
|
2
2
|
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
3
|
+
import { type UserMessage } from '@deepseek-ai/dsh-llm';
|
|
3
4
|
import type { CommandRuntime } from '@deepseek-ai/dsh-commands';
|
|
4
5
|
import { type LocalCommand, type LocalizedDescriptions } from '../../commands.js';
|
|
5
6
|
import type { ChannelOwner } from './owner.js';
|
|
@@ -12,12 +13,17 @@ export declare function createSkillCatalog(ctx: Context, deps: {
|
|
|
12
13
|
cwd(): string;
|
|
13
14
|
setCommands(commands: LocalCommand[]): void;
|
|
14
15
|
commandDescriptions(name: string): LocalizedDescriptions | undefined;
|
|
15
|
-
|
|
16
|
+
/** Submit a user line through the channel's delivery pipeline. The
|
|
17
|
+
* fallback skill path rides this same entry point and attaches the
|
|
18
|
+
* rendered body, so the line stays a plain user message (fence, pending
|
|
19
|
+
* preview and `@` expansion included) and the body is appended to that
|
|
20
|
+
* message's step batch — never a turn of its own. */
|
|
21
|
+
deliverUserText(text: string, placement: 'followup', attach?: UserMessage): void;
|
|
16
22
|
}): {
|
|
17
23
|
start: () => void;
|
|
18
24
|
release: () => void;
|
|
19
25
|
refreshCommands: () => void;
|
|
20
|
-
refreshSkillCommands: () => Promise<void>;
|
|
26
|
+
refreshSkillCommands: (fromRetry?: boolean) => Promise<void>;
|
|
21
27
|
registryFor: (agent: Agent) => SkillRegistry | undefined;
|
|
22
28
|
viewOptions: (agent: Agent) => {
|
|
23
29
|
scope: Agent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-catalog.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/skill-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"skill-catalog.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/skill-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAE/D,OAAO,EAA8E,KAAK,YAAY,EAAE,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAI7J,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAKxD,oFAAoF;AACpF,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,KAAK,CAAC,CAAA;IAC5C,cAAc,EAAE,cAAc,GAAG,SAAS,CAAA;IAC1C,KAAK,IAAI,KAAK,CAAA;IACd,GAAG,IAAI,MAAM,CAAA;IACb,WAAW,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI,CAAA;IAC3C,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAAA;IACpE;;;;0DAIsD;IACtD,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;CACjF;iBA4JiB,IAAI;mBARF,IAAI;2BAhII,IAAI;mDAoDwB,OAAO,CAAC,IAAI,CAAC;yBAtDzC,KAAK,KAAG,aAAa,GAAG,SAAS;yBADjC,KAAK,KAAG;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;EA+JlE"}
|
|
@@ -5,13 +5,23 @@ import { t } from '../../i18n.js';
|
|
|
5
5
|
import { serviceForAgent } from '../presets.js';
|
|
6
6
|
import { hasCommandErrorCode, mapCommandError } from '../command-errors.js';
|
|
7
7
|
const SKILL_COMMAND_RETRY_MS = 800;
|
|
8
|
+
const MAX_SKILL_RETRY_ATTEMPTS = 3;
|
|
8
9
|
/** Owns the merged catalog, host registrations, retry timer and all skill reads. */
|
|
9
10
|
export function createSkillCatalog(ctx, deps) {
|
|
10
11
|
let commandListSeq = 0;
|
|
12
|
+
let skillCommandSeq = 0;
|
|
11
13
|
let lastGoodSkills;
|
|
12
14
|
const registrations = new Map();
|
|
13
15
|
const refused = new Set();
|
|
14
16
|
let retry;
|
|
17
|
+
let retryAttempts = 0;
|
|
18
|
+
let released = false;
|
|
19
|
+
const resetRetry = () => {
|
|
20
|
+
if (retry !== undefined)
|
|
21
|
+
clearTimeout(retry);
|
|
22
|
+
retry = undefined;
|
|
23
|
+
retryAttempts = 0;
|
|
24
|
+
};
|
|
15
25
|
const viewOptions = (agent) => ({ scope: agent, cwd: deps.cwd() });
|
|
16
26
|
const registryFor = (agent) => serviceForAgent(ctx, agent, 'skills');
|
|
17
27
|
const refreshCommands = () => {
|
|
@@ -57,16 +67,18 @@ export function createSkillCatalog(ctx, deps) {
|
|
|
57
67
|
restore();
|
|
58
68
|
return;
|
|
59
69
|
}
|
|
60
|
-
|
|
70
|
+
// Cache the observation, not the delta: registered skills are already
|
|
71
|
+
// in merged on later reads. Local/host collisions still win on restore.
|
|
72
|
+
const skills = [];
|
|
61
73
|
for (const skill of observation.skills) {
|
|
62
|
-
if (isUserInvocable(skill) && !
|
|
63
|
-
|
|
74
|
+
if (isUserInvocable(skill) && !skills.some(command => command.name === skill.name)) {
|
|
75
|
+
skills.push({ name: skill.name, description: skill.description, skill: true });
|
|
64
76
|
}
|
|
65
77
|
}
|
|
66
|
-
|
|
67
|
-
|
|
78
|
+
lastGoodSkills = { agent: target, commands: skills };
|
|
79
|
+
const added = skills.filter(entry => !merged.some(command => command.name === entry.name));
|
|
68
80
|
if (added.length > 0 && deps.owner.current() && target === deps.agent())
|
|
69
|
-
deps.setCommands(
|
|
81
|
+
deps.setCommands([...merged, ...added]);
|
|
70
82
|
}).catch((error) => {
|
|
71
83
|
if (!deps.owner.current() || token !== commandListSeq || target !== deps.agent())
|
|
72
84
|
return;
|
|
@@ -74,9 +86,14 @@ export function createSkillCatalog(ctx, deps) {
|
|
|
74
86
|
restore();
|
|
75
87
|
});
|
|
76
88
|
};
|
|
77
|
-
const refreshSkillCommands = async () => {
|
|
78
|
-
if (!deps.owner.current() || deps.commandService === undefined)
|
|
89
|
+
const refreshSkillCommands = async (fromRetry = false) => {
|
|
90
|
+
if (released || !deps.owner.current() || deps.commandService === undefined)
|
|
79
91
|
return;
|
|
92
|
+
// Explicit refreshes (including skills/change and agent swaps) supersede
|
|
93
|
+
// the old ladder. Only the timer continuation consumes the same budget.
|
|
94
|
+
if (!fromRetry)
|
|
95
|
+
resetRetry();
|
|
96
|
+
const token = ++skillCommandSeq;
|
|
80
97
|
const target = deps.agent();
|
|
81
98
|
const registry = registryFor(target);
|
|
82
99
|
if (registry === undefined)
|
|
@@ -86,15 +103,27 @@ export function createSkillCatalog(ctx, deps) {
|
|
|
86
103
|
observation = await registry.snapshot(viewOptions(target));
|
|
87
104
|
}
|
|
88
105
|
catch (error) {
|
|
89
|
-
if (deps.owner.current())
|
|
106
|
+
if (deps.owner.current() && token === skillCommandSeq && target === deps.agent())
|
|
90
107
|
ctx.logger.warn('skill commands: catalog read failed: %o', error);
|
|
91
108
|
return;
|
|
92
109
|
}
|
|
93
|
-
if (!deps.owner.current() || target !== deps.agent())
|
|
110
|
+
if (!deps.owner.current() || token !== skillCommandSeq || target !== deps.agent())
|
|
111
|
+
return;
|
|
112
|
+
if (!observation.complete) {
|
|
113
|
+
if (retry === undefined && retryAttempts < MAX_SKILL_RETRY_ATTEMPTS) {
|
|
114
|
+
const delay = SKILL_COMMAND_RETRY_MS * 2 ** retryAttempts++;
|
|
115
|
+
retry = setTimeout(() => {
|
|
116
|
+
retry = undefined;
|
|
117
|
+
if (token === skillCommandSeq && target === deps.agent())
|
|
118
|
+
void refreshSkillCommands(true);
|
|
119
|
+
}, delay);
|
|
120
|
+
retry.unref?.();
|
|
121
|
+
}
|
|
122
|
+
// Partial reads cannot revoke callable handlers or replace descriptions.
|
|
123
|
+
// Keep the last-good registrations until an authoritative observation.
|
|
94
124
|
return;
|
|
95
|
-
if (!observation.complete && retry === undefined) {
|
|
96
|
-
retry = setTimeout(() => { retry = undefined; void refreshSkillCommands(); }, SKILL_COMMAND_RETRY_MS);
|
|
97
125
|
}
|
|
126
|
+
resetRetry();
|
|
98
127
|
const wanted = new Map(observation.skills
|
|
99
128
|
.filter(isUserInvocable)
|
|
100
129
|
.filter(skill => parseCommandName(`/${skill.name}`)?.name === skill.name)
|
|
@@ -129,7 +158,12 @@ export function createSkillCatalog(ctx, deps) {
|
|
|
129
158
|
return { kind: 'error', text: t('skill-unavailable', { name }) };
|
|
130
159
|
if (!deps.owner.current() || invoker !== deps.agent())
|
|
131
160
|
return { kind: 'error', text: t('skill-unavailable', { name }) };
|
|
132
|
-
|
|
161
|
+
// No `skill` tool: deliver the gesture as the user's own line and
|
|
162
|
+
// attach the rendered body. The channel's resident pre-step
|
|
163
|
+
// listener appends the body AFTER the admitted batch — the same
|
|
164
|
+
// shape/order as dsh-tool-skill's gesture boundary (#842).
|
|
165
|
+
const bodyMessage = createUserMessage({ content: [{ type: 'text', text: renderSkillContent(skill) }], source: { kind: 'skill-invocation', name, form: 'instructions' } });
|
|
166
|
+
deps.deliverUserText(`/${name}${rawInput}`, 'followup', bodyMessage);
|
|
133
167
|
return { kind: 'success' };
|
|
134
168
|
},
|
|
135
169
|
});
|
|
@@ -144,14 +178,12 @@ export function createSkillCatalog(ctx, deps) {
|
|
|
144
178
|
}
|
|
145
179
|
}
|
|
146
180
|
};
|
|
147
|
-
let released = false;
|
|
148
181
|
const release = () => {
|
|
149
182
|
if (released)
|
|
150
183
|
return;
|
|
151
184
|
released = true;
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
retry = undefined;
|
|
185
|
+
skillCommandSeq += 1;
|
|
186
|
+
resetRetry();
|
|
155
187
|
for (const entry of registrations.values())
|
|
156
188
|
entry.dispose();
|
|
157
189
|
registrations.clear();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/channel.ts"],"names":[],"mappings":"AAUA,OAAO,EAA4B,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AA0BxF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,KAAK,KAAK,EAAqE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/channel.ts"],"names":[],"mappings":"AAUA,OAAO,EAA4B,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AA0BxF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,KAAK,KAAK,EAAqE,MAAM,wBAAwB,CAAA;AAwCtH,OAAO,KAAK,EAAyE,YAAY,EAA8T,MAAM,oBAAoB,CAAA;AAgCzb,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAkBnD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,EACZ,YAAY,EAAE,KAAK,EACnB,OAAO,EAAE,oBAAoB,GAC5B,YAAY,CAUd;AAs3BD,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,YAAY,EAAE,cAAc,EAAE,uBAAuB,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,YAAY,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,SAAS,EAAE,gBAAgB,EAAE,cAAc,EAAE,4BAA4B,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACryB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA"}
|
|
@@ -235,7 +235,7 @@ function createChannelWithOwner(ctx, initialAgent, options, owner) {
|
|
|
235
235
|
const { warning: contextWarning, resetContextWarning, checkContextWarning, trackPending, untrackPending } = bookkeeping;
|
|
236
236
|
const composer = createComposerImages(ctx, owner, { generation: () => state.agentBindingGeneration });
|
|
237
237
|
const inputDelivery = createInputDelivery(ctx, owner, binding, () => state, (...args) => notify(...args), trackPending, untrackPending, composer);
|
|
238
|
-
const { dispatchUserText, deliverUserText, withDecisionPending, clearStagedImages } = inputDelivery;
|
|
238
|
+
const { dispatchUserText, deliverUserText, retireAttachment, withDecisionPending, clearStagedImages } = inputDelivery;
|
|
239
239
|
/**
|
|
240
240
|
* The `tui/session-switch` decision event (pi's `session_before_switch`),
|
|
241
241
|
* fired before `/new` or `/resume` replaces the live session (rewind has
|
|
@@ -475,7 +475,9 @@ function createChannelWithOwner(ctx, initialAgent, options, owner) {
|
|
|
475
475
|
cwd: () => state.cwd,
|
|
476
476
|
setCommands(commands) { state.commandList = commands; state.emit(); },
|
|
477
477
|
commandDescriptions: name => commandTrees?.descriptions(name),
|
|
478
|
-
|
|
478
|
+
// Attached-context pass-through (T03 consumes the third parameter in the
|
|
479
|
+
// fallback branch): the skill catalog never loses the FIFO/decision fence.
|
|
480
|
+
deliverUserText: (text, placement, attach) => deliverUserText(text, placement, [], attach),
|
|
479
481
|
});
|
|
480
482
|
const skillViewOptions = skillCatalog.viewOptions;
|
|
481
483
|
const skillRegistryFor = skillCatalog.registryFor;
|
|
@@ -649,6 +651,7 @@ function createChannelWithOwner(ctx, initialAgent, options, owner) {
|
|
|
649
651
|
subagents: subagentProjection,
|
|
650
652
|
agentView,
|
|
651
653
|
messageObserver,
|
|
654
|
+
retireAttachment,
|
|
652
655
|
});
|
|
653
656
|
const bindAgent = bindingEvents.bind;
|
|
654
657
|
const sessionAdoption = createSessionAdoption(state, {
|
|
@@ -47,9 +47,11 @@ export interface LiveSessionSeedMetadata {
|
|
|
47
47
|
* Create-time seed ownership fields. Every copied source prefix is inherited
|
|
48
48
|
* state for domain projections, even when `/fork` deliberately omits
|
|
49
49
|
* `parentSession` so the copy is presented as an independent root. The exact
|
|
50
|
-
* cut
|
|
51
|
-
*
|
|
52
|
-
*
|
|
50
|
+
* cut distinguishes copied history from child-owned events. Not every
|
|
51
|
+
* projection skips inherited events: newer inbox folds restore pending input
|
|
52
|
+
* from them, so rewind must cancel that work through the child's Inbox API.
|
|
53
|
+
* A child snapshot length cannot reliably be used as the cut because
|
|
54
|
+
* construction may append `session/end-seed`.
|
|
53
55
|
*/
|
|
54
56
|
export declare function liveSessionSeedMetadata(session: unknown, inheritedCount: number): LiveSessionSeedMetadata;
|
|
55
57
|
/** Close an open turn with the `turn/end` shape a real user cancellation writes. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"liveSession.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/compat/liveSession.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAoChF;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,YAAY,EAAE,CAWnF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAI1D;AAMD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAQlF;AAED,iFAAiF;AACjF,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG;IAC1D,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5C,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;CACxC,CAcA;AASD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,EAAE,CA4BxF;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE;QACb,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;QAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAC5B,CAAA;IACD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CACtC;AAED
|
|
1
|
+
{"version":3,"file":"liveSession.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/compat/liveSession.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAoChF;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,YAAY,EAAE,CAWnF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAI1D;AAMD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAQlF;AAED,iFAAiF;AACjF,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG;IAC1D,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5C,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;CACxC,CAcA;AASD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,EAAE,CA4BxF;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE;QACb,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;QAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAC5B,CAAA;IACD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CACtC;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,MAAM,GACrB,uBAAuB,CAQzB;AAED,oFAAoF;AACpF,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CASjF;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAoBtE;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,YAAY,EAAE,CAAA;IACtC,4EAA4E;IAC5E,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,CAAA;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,YAAY,EAAE,kBAAkB,CAAC,cAAc,CAAC,CAAA;IACzD,QAAQ,CAAC,KAAK,CAAC,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAA;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,wBAAwB,GAAG,kBAAkB,CAiB9F"}
|
|
@@ -148,9 +148,11 @@ export function sliceLiveSessionSeed(session, boundary) {
|
|
|
148
148
|
* Create-time seed ownership fields. Every copied source prefix is inherited
|
|
149
149
|
* state for domain projections, even when `/fork` deliberately omits
|
|
150
150
|
* `parentSession` so the copy is presented as an independent root. The exact
|
|
151
|
-
* cut
|
|
152
|
-
*
|
|
153
|
-
*
|
|
151
|
+
* cut distinguishes copied history from child-owned events. Not every
|
|
152
|
+
* projection skips inherited events: newer inbox folds restore pending input
|
|
153
|
+
* from them, so rewind must cancel that work through the child's Inbox API.
|
|
154
|
+
* A child snapshot length cannot reliably be used as the cut because
|
|
155
|
+
* construction may append `session/end-seed`.
|
|
154
156
|
*/
|
|
155
157
|
export function liveSessionSeedMetadata(session, inheritedCount) {
|
|
156
158
|
if (usesIsSeeded(session)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/sessions/digest.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE3E,6EAA6E;AAC7E,eAAO,MAAM,iBAAiB,QAAY,CAAA;AAC1C,+EAA+E;AAC/E,eAAO,MAAM,eAAe,MAAM,CAAA;AAClC,+EAA+E;AAC/E,eAAO,MAAM,iBAAiB,QAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/sessions/digest.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE3E,6EAA6E;AAC7E,eAAO,MAAM,iBAAiB,QAAY,CAAA;AAC1C,+EAA+E;AAC/E,eAAO,MAAM,eAAe,MAAM,CAAA;AAClC,+EAA+E;AAC/E,eAAO,MAAM,iBAAiB,QAAa,CAAA;AAwG3C;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,aAAa,CAyDtE;AAID,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,CAAA;IACxC,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,8EAA8E;IAC9E,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAC7B;AA2GD,sEAAsE;AACtE,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC;IAAE,KAAK,EAAE,YAAY,GAAG,SAAS,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,CAgCjE;AA8CD;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,oBAAoB,CAAC,CAS/B;AAED,iFAAiF;AACjF,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAiB7B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,EAAE,CAyB1E"}
|