@qilin-agent/client-ui-conversation 3.1.4 → 3.1.6
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 +5 -3
- package/README.zh.md +5 -3
- package/lib/client.js +4636 -337
- package/lib/index.js +13 -9
- package/lib/types/client/contract/conversation.d.ts +10 -0
- package/lib/types/client/contract/draft-editor.d.ts +23 -0
- package/lib/types/client/contract/input.d.ts +34 -10
- package/lib/types/client/contract/records.d.ts +8 -3
- package/lib/types/client/contract/slots.d.ts +11 -2
- package/lib/types/client/contract/views.d.ts +2 -1
- package/lib/types/client/conversation/assembler.d.ts +3 -0
- package/lib/types/client/draft.d.ts +22 -0
- package/lib/types/client/index.d.ts +2 -2
- package/lib/types/client/input/decorations.d.ts +1 -1
- package/lib/types/client/input/editor/CommandChip.d.ts +13 -0
- package/lib/types/client/input/editor/command-chip-node.d.ts +87 -0
- package/lib/types/client/input/editor/command-chip-selection.d.ts +20 -0
- package/lib/types/client/input/editor/projection.d.ts +3 -0
- package/lib/types/client/input/editor/runtime.d.ts +19 -11
- package/lib/types/client/input/editor/text-ref.d.ts +2 -7
- package/lib/types/client/input/facade.d.ts +50 -17
- package/lib/types/client/input/hub.d.ts +2 -1
- package/lib/types/client/input/machine.d.ts +9 -5
- package/lib/types/client/locales.d.ts +2 -16
- package/lib/types/client/skeleton/DefaultConversationViews.d.ts +2 -2
- package/lib/types/client/stores.d.ts +8 -1
- package/lib/types/conversation-settings.d.ts +4 -0
- package/lib/types/index.d.ts +20 -5
- package/package.json +35 -35
- package/lib/types/client/input/editor/claim-decor.d.ts +0 -23
- package/lib/types/client/settings/ContentWidthRow.d.ts +0 -26
package/lib/index.js
CHANGED
|
@@ -26,21 +26,25 @@ const CONTENT_WIDTH_STEP = 20;
|
|
|
26
26
|
/** Content width before the user picks one. */
|
|
27
27
|
const DEFAULT_CONTENT_WIDTH = 0;
|
|
28
28
|
/** Durable conversation schema; also the wire envelope the browser scope validates against. */
|
|
29
|
-
const
|
|
29
|
+
const ConversationSettingsFields = {
|
|
30
30
|
[BUSY_ENTER_FIELD]: z.union([...BUSY_ENTER_BEHAVIORS]).default(DEFAULT_BUSY_ENTER_BEHAVIOR),
|
|
31
31
|
[CONTENT_WIDTH_FIELD]: z.natural().max(CONTENT_WIDTH_MAX).default(0)
|
|
32
|
-
}
|
|
32
|
+
};
|
|
33
|
+
z.object(ConversationSettingsFields);
|
|
33
34
|
//#endregion
|
|
34
35
|
//#region lib/types/index.js
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
/** Live preferences projected to the browser. */
|
|
37
|
+
const Config = z.object({
|
|
38
|
+
[BUSY_ENTER_FIELD]: ConversationSettingsFields[BUSY_ENTER_FIELD].volatile(),
|
|
39
|
+
[CONTENT_WIDTH_FIELD]: ConversationSettingsFields[CONTENT_WIDTH_FIELD].volatile()
|
|
40
|
+
});
|
|
41
|
+
/** Host preferences are consumed through the configuration form projection.
|
|
42
|
+
* @param ctx Plugin context used for optional settings presentation.
|
|
39
43
|
*/
|
|
40
44
|
function apply(ctx) {
|
|
41
|
-
ctx.inject(["settings"], (
|
|
42
|
-
|
|
45
|
+
ctx.inject(["settings"], (child) => {
|
|
46
|
+
child.effect(() => child.settings.configure({ auto: false }, ctx.fiber));
|
|
43
47
|
});
|
|
44
48
|
}
|
|
45
49
|
//#endregion
|
|
46
|
-
export { BUSY_ENTER_BEHAVIORS, BUSY_ENTER_FIELD, CONTENT_WIDTH_ADAPTIVE, CONTENT_WIDTH_FIELD, CONTENT_WIDTH_MAX, CONTENT_WIDTH_MIN, CONTENT_WIDTH_STEP, CONVERSATION_SETTINGS_NAMESPACE, DEFAULT_BUSY_ENTER_BEHAVIOR, DEFAULT_CONTENT_WIDTH, apply };
|
|
50
|
+
export { BUSY_ENTER_BEHAVIORS, BUSY_ENTER_FIELD, CONTENT_WIDTH_ADAPTIVE, CONTENT_WIDTH_FIELD, CONTENT_WIDTH_MAX, CONTENT_WIDTH_MIN, CONTENT_WIDTH_STEP, CONVERSATION_SETTINGS_NAMESPACE, Config, DEFAULT_BUSY_ENTER_BEHAVIOR, DEFAULT_CONTENT_WIDTH, apply };
|
|
@@ -5,6 +5,16 @@ import type { ConversationGroupData, ConversationGroupedView, ConversationGroupI
|
|
|
5
5
|
export interface ConversationMatchResult {
|
|
6
6
|
readonly id: string;
|
|
7
7
|
readonly role: 'start' | 'update';
|
|
8
|
+
/**
|
|
9
|
+
* Claim this event on the Definition's target: no other Definition of the
|
|
10
|
+
* same target receives it, and that target's unmatched-event fallback does
|
|
11
|
+
* not run. Definitions of other targets and Definitions without a target
|
|
12
|
+
* still receive it. Two claims on one target, or a claim from a Definition
|
|
13
|
+
* without a target, throw during dispatch. A claim returned by the fallback
|
|
14
|
+
* itself has no effect, because the fallback runs only when no Definition of
|
|
15
|
+
* its target matched.
|
|
16
|
+
*/
|
|
17
|
+
readonly exclusive?: true;
|
|
8
18
|
}
|
|
9
19
|
/** Merge-extensible business values published against one Turn. */
|
|
10
20
|
export interface ConversationTurnDataMap {
|
|
@@ -16,6 +16,29 @@ export interface ReferenceInsert {
|
|
|
16
16
|
readonly appearance?: 'session' | 'file' | 'folder';
|
|
17
17
|
readonly clipboardText: string;
|
|
18
18
|
}
|
|
19
|
+
/** Persisted reference data without the current editor's occurrence identity. */
|
|
20
|
+
export type DraftReference = Omit<Occurrence, 'occurrenceId'>;
|
|
21
|
+
/**
|
|
22
|
+
* Persisted command chip opening a draft. The claim itself (its submit
|
|
23
|
+
* closure) is not persisted; the input rebuilds it from the token through the
|
|
24
|
+
* trigger pipeline when the draft is restored.
|
|
25
|
+
*/
|
|
26
|
+
export interface DraftCommand {
|
|
27
|
+
/** Claim token with its argument separator, e.g. `/goal `; the draft text starts with the token without the separator. */
|
|
28
|
+
readonly token: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Editor-independent content. Reference spans are ordered, non-overlapping UTF-16
|
|
32
|
+
* ranges whose text equals clipboardText and that follow a leading command
|
|
33
|
+
* token; runtime node identities are excluded.
|
|
34
|
+
*/
|
|
35
|
+
export interface DraftSnapshot {
|
|
36
|
+
readonly text: string;
|
|
37
|
+
readonly references: readonly DraftReference[];
|
|
38
|
+
readonly command?: DraftCommand;
|
|
39
|
+
}
|
|
40
|
+
/** Plain initial text or an existing document with explicit reference identities. */
|
|
41
|
+
export type DraftInput = string | DraftSnapshot;
|
|
19
42
|
/** Keyboard keys intercepted by an open trigger menu. */
|
|
20
43
|
export type ArbitrateKey = 'up' | 'down' | 'enter' | 'escape' | 'tab' | 'tabBack';
|
|
21
44
|
/** Trigger-menu keyboard routing result. */
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* here is the submit plane (phase, claim, attempt) alone.
|
|
8
8
|
*/
|
|
9
9
|
import type { Context } from '@qilin-agent/kylin';
|
|
10
|
+
import type { SessionBinding } from '@qilin-agent/api-session-controller/client';
|
|
10
11
|
import type { InboxState } from '@qilin-agent/agent/types';
|
|
11
12
|
import type { ObservableSnapshot, SnapshotStore } from '@qilin-agent/client-store';
|
|
12
13
|
import type { Branded } from '@qilin-agent/brand';
|
|
@@ -35,7 +36,7 @@ export interface SubmitOutcome {
|
|
|
35
36
|
export interface CommandClaim {
|
|
36
37
|
/** Catalog command name without the leading slash (the key of per-command composer copy such as `hint.*`). */
|
|
37
38
|
readonly name: string;
|
|
38
|
-
/**
|
|
39
|
+
/** Command spelling followed by its argument separator; the composer shows the spelling as a chip and inserts the separator after it. */
|
|
39
40
|
readonly token: string;
|
|
40
41
|
readonly hint?: string;
|
|
41
42
|
readonly attachments?: boolean;
|
|
@@ -109,6 +110,13 @@ export interface InputTriggerController {
|
|
|
109
110
|
adjudicate(line: string, signal: AbortSignal, envelope: {
|
|
110
111
|
readonly attachments: number;
|
|
111
112
|
}): Promise<PickOutcome>;
|
|
113
|
+
/**
|
|
114
|
+
* Resolve the claim a persisted command chip names without acting on it.
|
|
115
|
+
* @param token - command spelling without its argument separator, e.g. '/goal'.
|
|
116
|
+
* @param signal - restore-attempt abort.
|
|
117
|
+
* @returns the claim, or undefined when no source claims the token; rejects when catalog warmup fails.
|
|
118
|
+
*/
|
|
119
|
+
resolveClaim(token: string, signal: AbortSignal): Promise<CommandClaim | undefined>;
|
|
112
120
|
/**
|
|
113
121
|
* @param source - chip owner, or undefined for a text reference.
|
|
114
122
|
* @param reference - source id and glyph.
|
|
@@ -154,14 +162,14 @@ export type DraftAttachmentId = Branded<'DraftAttachmentId'>;
|
|
|
154
162
|
* applied the edit after phase and span guards).
|
|
155
163
|
*/
|
|
156
164
|
export interface InputTarget {
|
|
157
|
-
/** Replace the trigger span with
|
|
165
|
+
/** Replace the leading trigger span with a command chip and enter claimed (span-CAS'd). */
|
|
158
166
|
beginCommand(claim: CommandClaim, span: TokenSpan): boolean;
|
|
159
167
|
/** Replace the trigger span with one reference chip (span-CAS'd). */
|
|
160
168
|
insertReference(ref: ReferenceInsert, span: TokenSpan): boolean;
|
|
161
169
|
}
|
|
162
170
|
/** Per-session input facade owned by the conversation wiring layer. */
|
|
163
171
|
export interface SessionInput extends InputTarget {
|
|
164
|
-
/** Replace the whole draft
|
|
172
|
+
/** Replace the whole draft with plain text, removing inline reference chips. */
|
|
165
173
|
setDraft(text: string): void;
|
|
166
174
|
/** Append ordered browser-owned attachment ids; busy admission phases refuse. */
|
|
167
175
|
addAttachments(ids: readonly DraftAttachmentId[]): boolean;
|
|
@@ -196,7 +204,21 @@ export interface SessionInput extends InputTarget {
|
|
|
196
204
|
export interface SessionInputResolver {
|
|
197
205
|
/** Resolve the facade for one session-scope ctx. */
|
|
198
206
|
for(actx: Context): SessionInput;
|
|
207
|
+
/**
|
|
208
|
+
* Prepare the exact retained Session before navigation publishes it.
|
|
209
|
+
* @param binding - target Session generation, already retained by the caller.
|
|
210
|
+
* @param options - content to adopt and explicit permission to replace existing text.
|
|
211
|
+
* @returns applied, preserved, or blocked by a pending submission or disposal.
|
|
212
|
+
*/
|
|
213
|
+
requestDraftInitialization(binding: SessionBinding, options: DraftInitializationOptions): DraftInitializationResult;
|
|
199
214
|
}
|
|
215
|
+
/** Initial text for a target Session; attachments remain under their existing owner. */
|
|
216
|
+
export interface DraftInitializationOptions {
|
|
217
|
+
readonly prompt?: string;
|
|
218
|
+
readonly clearPreviousDraft?: boolean;
|
|
219
|
+
}
|
|
220
|
+
/** An initialization request never waits for a React mount or a remote catalog. */
|
|
221
|
+
export type DraftInitializationResult = 'applied' | 'preserved' | 'blocked';
|
|
200
222
|
/**
|
|
201
223
|
* The public input action face provided to every session-scope slot
|
|
202
224
|
* component: stable-identity void callbacks, mirroring the
|
|
@@ -213,8 +235,10 @@ export interface InputActions {
|
|
|
213
235
|
* @returns false when the draft changed or submission locked the editor.
|
|
214
236
|
*/
|
|
215
237
|
insertText(text: string, span: TokenSpan): boolean;
|
|
216
|
-
/** Replace the whole draft
|
|
238
|
+
/** Replace the whole draft with plain text, removing inline reference chips. */
|
|
217
239
|
setDraft(text: string): void;
|
|
240
|
+
/** Write the current semantic document through the mounted persistence callback. */
|
|
241
|
+
persistDraft(): void;
|
|
218
242
|
/** Append ordered browser-owned attachment ids; busy admission phases refuse. */
|
|
219
243
|
addAttachments(ids: readonly DraftAttachmentId[]): boolean;
|
|
220
244
|
/** Remove one browser-owned attachment id; busy admission phases refuse. */
|
|
@@ -272,15 +296,15 @@ export interface SubmitAttempt {
|
|
|
272
296
|
/**
|
|
273
297
|
* Submit-machine input events (the machine's single write path). Text
|
|
274
298
|
* mutation lives in the editor; the machine only observes the draft through
|
|
275
|
-
* event payloads (
|
|
299
|
+
* event payloads (leading command chip, enter snapshots, settlement decisions).
|
|
276
300
|
*/
|
|
277
301
|
export type InputEvent =
|
|
278
|
-
/**
|
|
302
|
+
/** Editor content changed; carries the claim of the leading command chip, if any (zero effects). */
|
|
279
303
|
{
|
|
280
304
|
readonly type: 'draft-changed';
|
|
281
|
-
readonly
|
|
305
|
+
readonly command: CommandClaim | undefined;
|
|
282
306
|
}
|
|
283
|
-
/** The editor
|
|
307
|
+
/** The editor inserted a command chip: enter claimed. */
|
|
284
308
|
| {
|
|
285
309
|
readonly type: 'claim';
|
|
286
310
|
readonly claim: CommandClaim;
|
|
@@ -299,12 +323,12 @@ export type InputEvent =
|
|
|
299
323
|
readonly attempt: SubmitAttempt;
|
|
300
324
|
readonly message: string;
|
|
301
325
|
}
|
|
302
|
-
/** Settlement carries the
|
|
326
|
+
/** Settlement carries the leading command chip's claim, which the claim follows after a failure. */
|
|
303
327
|
| {
|
|
304
328
|
readonly type: 'submit-settled';
|
|
305
329
|
readonly attempt: SubmitAttempt;
|
|
306
330
|
readonly ok: boolean;
|
|
307
|
-
readonly
|
|
331
|
+
readonly command: CommandClaim | undefined;
|
|
308
332
|
readonly outcome?: SubmitOutcome;
|
|
309
333
|
readonly message?: string;
|
|
310
334
|
}
|
|
@@ -122,8 +122,9 @@ export type ModelRetryNode = LlmRetryEventData & {
|
|
|
122
122
|
retryState: 'scheduled' | 'started' | 'cancelled';
|
|
123
123
|
};
|
|
124
124
|
/**
|
|
125
|
-
* Durable terminal
|
|
126
|
-
*
|
|
125
|
+
* Durable terminal notice for a turn that ended with an error, a sign-out
|
|
126
|
+
* cancellation, or an interruption by a QiLin stop; the turn's settled retry
|
|
127
|
+
* chain renders separately and never replaces this node.
|
|
127
128
|
*/
|
|
128
129
|
export interface TurnErrorNode {
|
|
129
130
|
kind: 'turn-error';
|
|
@@ -135,7 +136,11 @@ export interface TurnErrorNode {
|
|
|
135
136
|
step: number;
|
|
136
137
|
/** Sanitized provider message; empty when a known code owns localized copy. */
|
|
137
138
|
message: string;
|
|
138
|
-
/**
|
|
139
|
+
/**
|
|
140
|
+
* Stable provider failure code when recorded, or a Client display code:
|
|
141
|
+
* `ACCOUNT_SIGNED_OUT` for a sign-out cancellation, `INTERRUPTED` for a turn
|
|
142
|
+
* closed after QiLin stopped.
|
|
143
|
+
*/
|
|
139
144
|
code?: string;
|
|
140
145
|
}
|
|
141
146
|
/** Durable notice for a turn ended by the per-request output-token cap. */
|
|
@@ -11,7 +11,7 @@ import type { SessionId } from '@qilin-agent/session/types';
|
|
|
11
11
|
import type { WorkspaceId } from '@qilin-agent/workspace/types';
|
|
12
12
|
import type { ComposerBlock } from './composer-blocks.ts';
|
|
13
13
|
import type { DraftAttachmentId, InputActions, InputNotice, InputState } from './input.ts';
|
|
14
|
-
import type { ComposerKeyboard, EditSelection } from './draft-editor.ts';
|
|
14
|
+
import type { ComposerKeyboard, DraftSnapshot, EditSelection } from './draft-editor.ts';
|
|
15
15
|
import type { createConversationStore } from '../stores.ts';
|
|
16
16
|
import type { BusyEnterBehavior } from './composer-submission.ts';
|
|
17
17
|
import type { ConversationSnapshot } from './snapshot.ts';
|
|
@@ -211,6 +211,11 @@ declare module '@qilin-agent/client-ui-slots' {
|
|
|
211
211
|
scope: 'session-maybe';
|
|
212
212
|
owner: HeroAgentPresetOwnerProps;
|
|
213
213
|
};
|
|
214
|
+
/** Compact options right-aligned in the New Session row after the workspace and preset controls; rendered only with a Session. */
|
|
215
|
+
'conversation.hero.options': {
|
|
216
|
+
kind: 'list';
|
|
217
|
+
scope: 'session';
|
|
218
|
+
};
|
|
214
219
|
/** Full-width entries above the composer card. */
|
|
215
220
|
'conversation.input.dock': {
|
|
216
221
|
kind: 'list';
|
|
@@ -312,6 +317,10 @@ declare module '@qilin-agent/client-ui-slots' {
|
|
|
312
317
|
kind: 'single';
|
|
313
318
|
scope: 'session-maybe';
|
|
314
319
|
};
|
|
320
|
+
'conversation.hero.options': {
|
|
321
|
+
kind: 'list';
|
|
322
|
+
scope: 'session';
|
|
323
|
+
};
|
|
315
324
|
};
|
|
316
325
|
inject: ConversationInjected;
|
|
317
326
|
locale: 'conversation';
|
|
@@ -414,7 +423,7 @@ export interface ConversationSessionInjected {
|
|
|
414
423
|
readonly conversationViews: ObservableSnapshot<readonly ViewTab[]>;
|
|
415
424
|
};
|
|
416
425
|
/** Bind input draft persistence to the Session-owned store instance. */
|
|
417
|
-
|
|
426
|
+
bindDraftPersistence: (write: (draft: DraftSnapshot) => void) => () => void;
|
|
418
427
|
/** Select and activate one View while addressing an opaque focus request to it. */
|
|
419
428
|
openView: (view: string, focus: string) => void;
|
|
420
429
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** Conversation view and session-local presentation state. */
|
|
2
|
+
import type { DraftInput } from './draft-editor.ts';
|
|
2
3
|
/**
|
|
3
4
|
* One conversation view tab, projected from a 'conversation.view' slot
|
|
4
5
|
* entry's registration options (label falls back to the entry id).
|
|
@@ -27,7 +28,7 @@ export interface ConversationViewRequest {
|
|
|
27
28
|
/** The conversation store's own state: the composer draft, the selected View, and one pending focus request. */
|
|
28
29
|
export interface ConversationStoreState {
|
|
29
30
|
/** Composer draft (persisted; survives session switches and reloads). */
|
|
30
|
-
draft:
|
|
31
|
+
draft: DraftInput;
|
|
31
32
|
/** Preferred `conversation.view` entry id; null resolves to Chat when registered. */
|
|
32
33
|
view: string | null;
|
|
33
34
|
/** One-shot focus request addressed to the selected View. */
|
|
@@ -43,6 +43,9 @@ export declare class ConversationNodeAssembler implements ConversationViewSnapsh
|
|
|
43
43
|
private readonly groups;
|
|
44
44
|
private readonly pendingGroupStores;
|
|
45
45
|
private readonly activeTargets;
|
|
46
|
+
/** Matches of the event in dispatch, kept by index; dispatch is not reentrant and reuses both arrays. */
|
|
47
|
+
private readonly matchedDefinitions;
|
|
48
|
+
private readonly matchedResults;
|
|
46
49
|
private hasMore;
|
|
47
50
|
private replacePending;
|
|
48
51
|
private timelineDirty;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DraftInput, DraftSnapshot, Occurrence } from './contract/draft-editor.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Copy input into the semantic draft representation without editor runtime identities.
|
|
4
|
+
* @param input - plain text or caller-owned structured content.
|
|
5
|
+
* @returns an owned snapshot ready for editor import.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveDraftInput(input: DraftInput): DraftSnapshot;
|
|
8
|
+
/**
|
|
9
|
+
* Decode persisted drafts, accepting the earlier plain-string representation.
|
|
10
|
+
* @param value - JSON value read from browser storage.
|
|
11
|
+
* @returns the decoded draft, or undefined for invalid data.
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseStoredDraft(value: unknown): DraftSnapshot | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Export reference identities without their editor-local occurrence ids.
|
|
16
|
+
* @param text - current clipboard projection.
|
|
17
|
+
* @param occurrences - matching reference projections from the same document revision.
|
|
18
|
+
* @param commandToken - claim token of the command chip opening the document, if any.
|
|
19
|
+
* @returns an editor-independent snapshot.
|
|
20
|
+
*/
|
|
21
|
+
export declare function snapshotDraft(text: string, occurrences: readonly Occurrence[], commandToken?: string): DraftSnapshot;
|
|
22
|
+
//# sourceMappingURL=draft.d.ts.map
|
|
@@ -25,8 +25,8 @@ export type { ConversationLocationDataChange } from './conversation/location-ind
|
|
|
25
25
|
export { ConversationViewRegistry } from './conversation/view-registry.ts';
|
|
26
26
|
export type { ConversationKey } from './locales.ts';
|
|
27
27
|
export type { ComposerAttachment, ComposerAttachmentsOwnerProps, ComposerAttachmentsProps, ComposerFileAttachment, ComposerImageAttachment, DraftFileUpload, DraftFileUploads, ComposerBarInjected, ComposerBarOwnerProps, ComposerBarProps, ComposerChainProps, ConversationHeaderActionOwnerProps, ConversationHeaderCornerOwnerProps, ConversationHeaderLineageOwnerProps, ConversationContentInputProps, ConversationContentProps, ConversationInjected, ConversationSessionHeaderInjected, ConversationSessionHeaderSlotProps, ConversationSessionInjected, ConversationSessionSlotProps, ConversationSlotProps, ConversationViewsProps, ConversationWidthControlsInputProps, ConversationWidthControlsProps, ConversationStore, ConvViewOwnerProps, ConvViewProps, EmptyWorkspaceOwnerProps, HeroAgentPresetOwnerProps, HeroBrandMarkOwnerProps, InputControlOwnerProps, InputZone, MessageImageLoader, MessageImageSource, MessageImagesOwnerProps, RenderMessageImages, UseConversation, UseConversationViews, } from './contract/slots.ts';
|
|
28
|
-
export type { BeginCommandRequest, CommandClaim, ConsumeTokenRequest, DraftAttachmentId, InputActions, InputState, InsertReferenceRequest, InsertTextRequest, PickOutcome, SessionInput, SessionInputResolver, SubmitAttachment, SubmitOutcome, } from './contract/input.ts';
|
|
29
|
-
export type { ArbitrateKey, ArbitrateOutcome, ReferenceInsert, TokenSpan } from './contract/draft-editor.ts';
|
|
28
|
+
export type { BeginCommandRequest, CommandClaim, ConsumeTokenRequest, DraftAttachmentId, DraftInitializationOptions, DraftInitializationResult, InputActions, InputState, InsertReferenceRequest, InsertTextRequest, PickOutcome, SessionInput, SessionInputResolver, SubmitAttachment, SubmitOutcome, } from './contract/input.ts';
|
|
29
|
+
export type { ArbitrateKey, ArbitrateOutcome, DraftInput, DraftReference, DraftSnapshot, ReferenceInsert, TokenSpan } from './contract/draft-editor.ts';
|
|
30
30
|
export type { ComposerBlock, ComposerBlocks } from './contract/composer-blocks.ts';
|
|
31
31
|
declare module '@qilin-agent/kylin' {
|
|
32
32
|
interface Context {
|
|
@@ -25,7 +25,7 @@ export interface TextRefRange {
|
|
|
25
25
|
* exact lexicon member; a `/name` token must end at whitespace or the draft
|
|
26
26
|
* end ('/name/x' is a path, '/name。' is prose).
|
|
27
27
|
* @param draft - draft text.
|
|
28
|
-
* @param lexicon - per-trigger name lists
|
|
28
|
+
* @param lexicon - per-trigger name lists; missing catalogs match no named tokens.
|
|
29
29
|
* @returns matched ranges in draft order.
|
|
30
30
|
*/
|
|
31
31
|
export declare function scanTextRefs(draft: string, lexicon: ReadonlyMap<'/' | '@', readonly string[]>): TextRefRange[];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
/** Display inputs of the command chip. */
|
|
3
|
+
export interface CommandChipProps {
|
|
4
|
+
/** Claimed token without its argument separator, e.g. `/goal`. */
|
|
5
|
+
readonly token: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Render the claimed command chip.
|
|
9
|
+
* @param props - the token to display.
|
|
10
|
+
* @returns the chip body.
|
|
11
|
+
*/
|
|
12
|
+
export declare function CommandChip({ token }: CommandChipProps): ReactNode;
|
|
13
|
+
//# sourceMappingURL=CommandChip.d.ts.map
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CommandChipNode: the claimed slash command as one atomic Lexical decorator
|
|
3
|
+
* on the document's leading seat. The node carries the claim it was inserted
|
|
4
|
+
* for, so a history restore of the node restores the claim with it.
|
|
5
|
+
* `getTextContent()` answers the token without its argument separator; the
|
|
6
|
+
* separator is an ordinary text node after the chip. The detect projection
|
|
7
|
+
* counts the chip as one U+FFFC; see projection.ts.
|
|
8
|
+
*/
|
|
9
|
+
import type { JSX } from 'react';
|
|
10
|
+
import type { LexicalEditor, LexicalNode, NodeKey, SerializedLexicalNode, Spread } from 'lexical';
|
|
11
|
+
import { DecoratorNode } from 'lexical';
|
|
12
|
+
import type { CommandClaim } from '../../contract/input.ts';
|
|
13
|
+
/** JSON form of one command chip (Lexical node serialization contract). */
|
|
14
|
+
export type SerializedCommandChipNode = Spread<{
|
|
15
|
+
text: string;
|
|
16
|
+
}, SerializedLexicalNode>;
|
|
17
|
+
/** One claimed command as an atomic decorator node. */
|
|
18
|
+
export declare class CommandChipNode extends DecoratorNode<JSX.Element> {
|
|
19
|
+
/** The claim this chip anchors; its submit closure has no JSON form. */
|
|
20
|
+
__claim: CommandClaim;
|
|
21
|
+
/** Lexical node registry type tag. */
|
|
22
|
+
static getType(): string;
|
|
23
|
+
/**
|
|
24
|
+
* Clone with identity (Lexical writable-copy contract).
|
|
25
|
+
* @param node - node to clone.
|
|
26
|
+
* @returns a copy carrying the same NodeKey and claim.
|
|
27
|
+
*/
|
|
28
|
+
static clone(node: CommandChipNode): CommandChipNode;
|
|
29
|
+
/**
|
|
30
|
+
* Rebuild one chip from its JSON form. JSON cannot carry the claim's
|
|
31
|
+
* submit closure, so an imported command is its literal token text.
|
|
32
|
+
* @param json - serialized chip.
|
|
33
|
+
* @returns a plain text node holding the token.
|
|
34
|
+
*/
|
|
35
|
+
static importJSON(json: SerializedCommandChipNode): LexicalNode;
|
|
36
|
+
/**
|
|
37
|
+
* @param claim - the command claim the chip anchors.
|
|
38
|
+
* @param key - Lexical clone-path key; absent for fresh nodes.
|
|
39
|
+
*/
|
|
40
|
+
constructor(claim: CommandClaim, key?: NodeKey);
|
|
41
|
+
/** Serialize to the JSON node form (the token text alone). */
|
|
42
|
+
exportJSON(): SerializedCommandChipNode;
|
|
43
|
+
/**
|
|
44
|
+
* Mount the chip's host element; the decorator portal renders into it.
|
|
45
|
+
* @returns an inline, non-editable span carrying the test/e2e anchor.
|
|
46
|
+
*/
|
|
47
|
+
createDOM(): HTMLElement;
|
|
48
|
+
/** Host element never changes shape. */
|
|
49
|
+
updateDOM(): boolean;
|
|
50
|
+
/** The chip sits in the text line. */
|
|
51
|
+
isInline(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Arrows step across the chip and the default character deletion removes
|
|
54
|
+
* it whole, for the reason documented on ReferenceChipNode.isKeyboardSelectable;
|
|
55
|
+
* registerCommandChipSelection inserts the selecting step before that deletion.
|
|
56
|
+
*/
|
|
57
|
+
isKeyboardSelectable(): boolean;
|
|
58
|
+
/** Clipboard / persistence projection: the token without its separator. */
|
|
59
|
+
getTextContent(): string;
|
|
60
|
+
/** The claim this chip anchors. */
|
|
61
|
+
getClaim(): CommandClaim;
|
|
62
|
+
/** React face rendered into the host element by the decorator portal. */
|
|
63
|
+
decorate(): JSX.Element;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Mint one chip node for a claim.
|
|
67
|
+
* @param claim - the command claim.
|
|
68
|
+
* @returns the fresh node.
|
|
69
|
+
*/
|
|
70
|
+
export declare function $createCommandChipNode(claim: CommandClaim): CommandChipNode;
|
|
71
|
+
/**
|
|
72
|
+
* Command chip type guard.
|
|
73
|
+
* @param node - any node or nullish.
|
|
74
|
+
* @returns whether the node is a CommandChipNode.
|
|
75
|
+
*/
|
|
76
|
+
export declare function $isCommandChipNode(node: LexicalNode | null | undefined): node is CommandChipNode;
|
|
77
|
+
/**
|
|
78
|
+
* Keep command chips on the leading seat. A chip anywhere but the first
|
|
79
|
+
* child of the first block (text, a line break, or a block inserted before
|
|
80
|
+
* it) becomes its literal token, which releases the claim. Inserting a
|
|
81
|
+
* sibling before the chip or moving it to another block marks the chip dirty;
|
|
82
|
+
* a block inserted before the chip's block marks only that block dirty.
|
|
83
|
+
* @param editor - the shell-owned editor.
|
|
84
|
+
* @returns the unregister disposer.
|
|
85
|
+
*/
|
|
86
|
+
export declare function registerCommandChipSeat(editor: LexicalEditor): () => void;
|
|
87
|
+
//# sourceMappingURL=command-chip-node.d.ts.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Two-step command chip deletion. A character deletion whose direction
|
|
3
|
+
* reaches the command chip from a collapsed caret first selects the chip; the
|
|
4
|
+
* next deletion in that direction removes it. Deletions arrive as the
|
|
5
|
+
* character-deletion command (Backspace, Delete, and the platform shortcuts
|
|
6
|
+
* the engine maps to them) or as a deletion input event, which some platforms
|
|
7
|
+
* apply without that command. A key that produces no character deletion, a
|
|
8
|
+
* click, blur, or a caret that no longer touches the chip clears the
|
|
9
|
+
* selection. The selected state is presentation on the chip's host and the
|
|
10
|
+
* root element; the editor selection stays a collapsed range beside the chip,
|
|
11
|
+
* so typing and arrows keep their plain-text behavior.
|
|
12
|
+
*/
|
|
13
|
+
import type { LexicalEditor } from 'lexical';
|
|
14
|
+
/**
|
|
15
|
+
* Register two-step deletion for the command chip.
|
|
16
|
+
* @param editor - the shell-owned editor.
|
|
17
|
+
* @returns the unregister disposer, which also clears a selected chip.
|
|
18
|
+
*/
|
|
19
|
+
export declare function registerCommandChipSelection(editor: LexicalEditor): () => void;
|
|
20
|
+
//# sourceMappingURL=command-chip-selection.d.ts.map
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import type { LexicalNode, NodeKey, Point } from 'lexical';
|
|
11
11
|
import type { Occurrence } from '../../contract/draft-editor.ts';
|
|
12
|
+
import type { CommandClaim } from '../../contract/input.ts';
|
|
12
13
|
/** The detect-projection stand-in for one chip (object replacement character). */
|
|
13
14
|
export declare const ATOMIC_CHAR = "\uFFFC";
|
|
14
15
|
/** One leaf (or gap) of the composer document in projection coordinates. */
|
|
@@ -75,6 +76,8 @@ export interface EditorProjection {
|
|
|
75
76
|
} | null;
|
|
76
77
|
/** Collapsed caret in detect coordinates; null while the selection is absent or ranged. */
|
|
77
78
|
readonly caret: number | null;
|
|
79
|
+
/** Claim of the command chip opening the document; undefined without one. */
|
|
80
|
+
readonly command: CommandClaim | undefined;
|
|
78
81
|
}
|
|
79
82
|
/**
|
|
80
83
|
* Fold one selection point to a detect offset.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/** The Composer model's private Lexical editor, projections, and node operations. */
|
|
2
2
|
import type { ObservableSnapshot } from '@qilin-agent/client-store';
|
|
3
3
|
import type { LexicalEditor } from 'lexical';
|
|
4
|
-
import type {
|
|
4
|
+
import type { DraftReference, ReferenceInsert } from '../../contract/draft-editor.ts';
|
|
5
|
+
import type { CommandClaim } from '../../contract/input.ts';
|
|
5
6
|
import type { EditorProjection } from './projection.ts';
|
|
6
7
|
import type { DetectSpan } from './span-map.ts';
|
|
7
8
|
type Lexicon = ReadonlyMap<'/' | '@', readonly string[]>;
|
|
@@ -9,7 +10,6 @@ type Lexicon = ReadonlyMap<'/' | '@', readonly string[]>;
|
|
|
9
10
|
interface DraftEditorRuntimeDeps {
|
|
10
11
|
readonly onUpdate: () => void;
|
|
11
12
|
readonly openReference: (source: string | undefined, reference: Pick<ReferenceInsert, 'ref' | 'appearance'>) => boolean;
|
|
12
|
-
readonly activeClaimToken: () => string | null;
|
|
13
13
|
readonly lexicon: () => Lexicon;
|
|
14
14
|
readonly resolveLexicon: () => ObservableSnapshot<Lexicon> | undefined;
|
|
15
15
|
}
|
|
@@ -24,6 +24,7 @@ export declare class DraftEditorRuntime {
|
|
|
24
24
|
private occurrenceSeq;
|
|
25
25
|
/** Live lexicon subscription disposer; undefined until the controller resolves. */
|
|
26
26
|
private lexiconOff;
|
|
27
|
+
private lexiconSource;
|
|
27
28
|
/** @param deps - model callbacks used by editor listeners and transforms. */
|
|
28
29
|
constructor(deps: DraftEditorRuntimeDeps);
|
|
29
30
|
/**
|
|
@@ -44,12 +45,10 @@ export declare class DraftEditorRuntime {
|
|
|
44
45
|
*/
|
|
45
46
|
private applyEdit;
|
|
46
47
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* shell is created inside the sessions provide materialization), so the
|
|
50
|
-
* first interactive updates retry until it can.
|
|
48
|
+
* Reconnect decorations when the optional trigger provider changes.
|
|
49
|
+
* The rescan reads the current editor and does not replace its content.
|
|
51
50
|
*/
|
|
52
|
-
|
|
51
|
+
refreshLexiconSubscription(): void;
|
|
53
52
|
/**
|
|
54
53
|
* Re-project inside the existing editor update callback.
|
|
55
54
|
* @returns the projection preceding this read.
|
|
@@ -103,19 +102,28 @@ export declare class DraftEditorRuntime {
|
|
|
103
102
|
* @returns whether the range mapped and the edit applied.
|
|
104
103
|
*/
|
|
105
104
|
insertReference(span: DetectSpan, ref: ReferenceInsert, tail: string): boolean;
|
|
106
|
-
/**
|
|
107
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Replace a span with a command chip followed by the claim token's
|
|
107
|
+
* argument separator, unless the separator already follows.
|
|
108
|
+
* @param span - detect-coordinate range.
|
|
109
|
+
* @param claim - the command claim the chip anchors.
|
|
110
|
+
* @param tail - the character following the range before editing.
|
|
111
|
+
* @param mergeHistory - merge into the previous history entry (a restored
|
|
112
|
+
* draft's chip is part of its seed, not an undoable step).
|
|
113
|
+
* @returns whether the range mapped and the edit applied.
|
|
114
|
+
*/
|
|
115
|
+
insertCommand(span: DetectSpan, claim: CommandClaim, tail: string, mergeHistory?: boolean): boolean;
|
|
108
116
|
/**
|
|
109
117
|
* Clear committed content using the model's suffix decision inside the editor update.
|
|
110
118
|
* @param prefixLength - returns the clipboard-prefix length to remove, or null to clear the root.
|
|
111
119
|
*/
|
|
112
120
|
clearCommittedDraft(prefixLength: (clipboardText: string) => number | null): void;
|
|
113
121
|
/**
|
|
114
|
-
*
|
|
122
|
+
* Import semantic content or a model-selected failure snapshot with fresh reference nodes.
|
|
115
123
|
* @param draft - clipboard text.
|
|
116
124
|
* @param occurrences - reference occurrences in clipboard order.
|
|
117
125
|
*/
|
|
118
|
-
restoreDraft(draft: string, occurrences: readonly
|
|
126
|
+
restoreDraft(draft: string, occurrences: readonly DraftReference[]): void;
|
|
119
127
|
/** Cut the editor's undo history after a committed clear or restoration. */
|
|
120
128
|
clearHistory(): void;
|
|
121
129
|
}
|
|
@@ -28,17 +28,12 @@ export declare class TextRefNode extends TextNode {
|
|
|
28
28
|
canInsertTextBefore(): boolean;
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
-
* Register the plain-text reference entity transform.
|
|
32
|
-
* has precedence on the leading-token seat: while a command claim holds, the
|
|
33
|
-
* claimed token must stay a plain TextNode (transforms register per concrete
|
|
34
|
-
* node class, so a TextRefNode would never receive the TextNode claim
|
|
35
|
-
* transform and the warn color would be lost).
|
|
31
|
+
* Register the plain-text reference entity transform.
|
|
36
32
|
* @param editor - the shell-owned editor.
|
|
37
33
|
* @param lexiconOf - live per-trigger name-roll accessor (the controller's aggregated store).
|
|
38
|
-
* @param activeToken - live claim token accessor; null while unclaimed.
|
|
39
34
|
* @returns the unregister disposer.
|
|
40
35
|
*/
|
|
41
|
-
export declare function registerTextRefDecoration(editor: LexicalEditor, lexiconOf: () => ReadonlyMap<'/' | '@', readonly string[]
|
|
36
|
+
export declare function registerTextRefDecoration(editor: LexicalEditor, lexiconOf: () => ReadonlyMap<'/' | '@', readonly string[]>): () => void;
|
|
42
37
|
/**
|
|
43
38
|
* Force a re-scan of the whole document (transforms only visit dirty nodes;
|
|
44
39
|
* a lexicon roll change dirties nothing on its own). Queued, not discrete —
|