@hydraharness/harness-client-runtime 0.0.0-stage → 0.1.1-rc.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/LICENSE +21 -0
- package/README.md +96 -2
- package/lib/client.js +10964 -0
- package/lib/index.js +6 -0
- package/lib/invariant.js +36 -0
- package/lib/types/client/agents/scope.d.ts +35 -0
- package/lib/types/client/contract/conversation.d.ts +242 -0
- package/lib/types/client/contract/session.d.ts +97 -0
- package/lib/types/client/contract/sessions-port.d.ts +55 -0
- package/lib/types/client/contract/sessions.d.ts +164 -0
- package/lib/types/client/contract/settings-scope.d.ts +79 -0
- package/lib/types/client/contract/store.d.ts +90 -0
- package/lib/types/client/contract/workspaces.d.ts +102 -0
- package/lib/types/client/conversation/definition-registry.d.ts +30 -0
- package/lib/types/client/conversation/event-registry.d.ts +27 -0
- package/lib/types/client/conversation/view-registry.d.ts +15 -0
- package/lib/types/client/index.d.ts +128 -0
- package/lib/types/client/ordered-baseline.d.ts +12 -0
- package/lib/types/client/sessions/assistant-timing.d.ts +34 -0
- package/lib/types/client/sessions/context-provenance.d.ts +58 -0
- package/lib/types/client/sessions/conversation-assembler.d.ts +107 -0
- package/lib/types/client/sessions/conversation-context.d.ts +22 -0
- package/lib/types/client/sessions/conversation-location-index.d.ts +70 -0
- package/lib/types/client/sessions/conversation-versions.d.ts +25 -0
- package/lib/types/client/sessions/conversation.d.ts +422 -0
- package/lib/types/client/sessions/failure-display.d.ts +7 -0
- package/lib/types/client/sessions/lineage.d.ts +47 -0
- package/lib/types/client/sessions/manager.d.ts +300 -0
- package/lib/types/client/sessions/notifier.d.ts +35 -0
- package/lib/types/client/sessions/partial.d.ts +40 -0
- package/lib/types/client/sessions/pending.d.ts +55 -0
- package/lib/types/client/sessions/projection-store.d.ts +111 -0
- package/lib/types/client/sessions/provide.d.ts +79 -0
- package/lib/types/client/sessions/queue-mirror.d.ts +33 -0
- package/lib/types/client/sessions/remotes.d.ts +10 -0
- package/lib/types/client/sessions/request-inspection.d.ts +74 -0
- package/lib/types/client/sessions/service.d.ts +415 -0
- package/lib/types/client/sessions/session.d.ts +287 -0
- package/lib/types/client/sessions/steering-history.d.ts +23 -0
- package/lib/types/client/sessions/subagent-lineage.d.ts +24 -0
- package/lib/types/client/sessions/tool-call-tree.d.ts +45 -0
- package/lib/types/client/slots.d.ts +191 -0
- package/lib/types/client/time-zone.d.ts +8 -0
- package/lib/types/client/workspaces/manager.d.ts +182 -0
- package/lib/types/client/workspaces/path.d.ts +17 -0
- package/lib/types/client/workspaces/service.d.ts +179 -0
- package/lib/types/client/workspaces/workspace.d.ts +65 -0
- package/lib/types/index.d.ts +4 -0
- package/lib/types/invariant.d.ts +16 -0
- package/package.json +94 -3
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { ConversationEventInput, ConversationNodeDefinition, ConversationPublication, ConversationViewDefinition, ConversationViewSnapshotMap, ConversationViewSnapshotStore } from '../contract/conversation.ts';
|
|
2
|
+
/** Event Registry subset consumed by a Session-owned Assembler. */
|
|
3
|
+
export interface ConversationEventDefinitions {
|
|
4
|
+
/** @returns ordinary Definitions in registration order. */
|
|
5
|
+
entries(): readonly ConversationNodeDefinition[];
|
|
6
|
+
/** @returns unmatched-event fallback, when registered. */
|
|
7
|
+
fallbackEntry(): ConversationNodeDefinition | undefined;
|
|
8
|
+
}
|
|
9
|
+
/** View Registry subset consumed by a Session-owned Assembler. */
|
|
10
|
+
export interface ConversationViewDefinitions {
|
|
11
|
+
/** @returns view builder factories in registration order. */
|
|
12
|
+
entries(): readonly ConversationViewDefinition[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Session-owned incremental engine that assembles business Contexts from a
|
|
16
|
+
* contiguous Event window and materializes registered view snapshots.
|
|
17
|
+
*/
|
|
18
|
+
export declare class ConversationNodeAssembler implements ConversationViewSnapshotStore {
|
|
19
|
+
private readonly eventDefinitions;
|
|
20
|
+
private readonly viewDefinitions;
|
|
21
|
+
private readonly contexts;
|
|
22
|
+
private readonly contextsByKind;
|
|
23
|
+
private readonly contextsBySeq;
|
|
24
|
+
private readonly inputs;
|
|
25
|
+
private readonly locationIndex;
|
|
26
|
+
private readonly dirty;
|
|
27
|
+
private readonly revised;
|
|
28
|
+
private readonly dependents;
|
|
29
|
+
private readonly views;
|
|
30
|
+
private hasMore;
|
|
31
|
+
private replacePending;
|
|
32
|
+
private timelineDirty;
|
|
33
|
+
/**
|
|
34
|
+
* @param eventDefinitions - live Event Definition registry.
|
|
35
|
+
* @param viewDefinitions - live view builder registry.
|
|
36
|
+
*/
|
|
37
|
+
constructor(eventDefinitions: ConversationEventDefinitions, viewDefinitions: ConversationViewDefinitions);
|
|
38
|
+
/**
|
|
39
|
+
* Replace the complete loaded window after open, resync, or gap repair.
|
|
40
|
+
* @param entries - complete contiguous window.
|
|
41
|
+
* @param hasMore - whether older history remains outside the window.
|
|
42
|
+
* @returns immediate publication request.
|
|
43
|
+
*/
|
|
44
|
+
replaceWindow(entries: readonly ConversationEventInput[], hasMore: boolean): ConversationPublication;
|
|
45
|
+
/**
|
|
46
|
+
* Add one contiguous live tail event without scanning existing Contexts.
|
|
47
|
+
* @param input - appended Event and optional wire view.
|
|
48
|
+
* @returns highest requested publication cadence.
|
|
49
|
+
*/
|
|
50
|
+
append(input: ConversationEventInput): ConversationPublication;
|
|
51
|
+
/**
|
|
52
|
+
* Add an older page while preserving existing Context and view identities.
|
|
53
|
+
* @param entries - newly loaded older Events.
|
|
54
|
+
* @param hasMore - whether history still precedes the expanded window.
|
|
55
|
+
* @returns highest requested publication cadence.
|
|
56
|
+
*/
|
|
57
|
+
prepend(entries: readonly ConversationEventInput[], hasMore: boolean): ConversationPublication;
|
|
58
|
+
/**
|
|
59
|
+
* Rebuild against the current Registry set after a low-frequency plugin change.
|
|
60
|
+
* @returns immediate publication request.
|
|
61
|
+
*/
|
|
62
|
+
rebuildRegistry(): ConversationPublication;
|
|
63
|
+
/**
|
|
64
|
+
* Materialize dirty Contexts and advance every registered view builder.
|
|
65
|
+
* @returns whether any view snapshot was rebuilt or incrementally applied.
|
|
66
|
+
*/
|
|
67
|
+
flush(): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Read the latest snapshot of a registered target.
|
|
70
|
+
* @param target - registered view target.
|
|
71
|
+
* @returns target snapshot, or undefined when no builder is registered.
|
|
72
|
+
*/
|
|
73
|
+
snapshot(target: string): unknown;
|
|
74
|
+
get<Target extends Extract<keyof ConversationViewSnapshotMap, string>>(target: Target): ConversationViewSnapshotMap[Target] | undefined;
|
|
75
|
+
private sortedInputs;
|
|
76
|
+
private matchInput;
|
|
77
|
+
private collectInput;
|
|
78
|
+
private dispatchInput;
|
|
79
|
+
private acceptMatch;
|
|
80
|
+
private applyPendingMatches;
|
|
81
|
+
private replayContexts;
|
|
82
|
+
private replayContext;
|
|
83
|
+
private replaceDependencies;
|
|
84
|
+
private replayRevisedDependents;
|
|
85
|
+
private readerFor;
|
|
86
|
+
private previousContext;
|
|
87
|
+
/** Insert one newly discovered start into its Definition's ordered predecessor index. */
|
|
88
|
+
private indexStartedContext;
|
|
89
|
+
private indexStartedContexts;
|
|
90
|
+
private replayDependencies;
|
|
91
|
+
private refreshMatchLocations;
|
|
92
|
+
private buildNode;
|
|
93
|
+
private buildLocationData;
|
|
94
|
+
private replaceLocationData;
|
|
95
|
+
private applyDirtyLocationData;
|
|
96
|
+
private resetViewBuilders;
|
|
97
|
+
}
|
|
98
|
+
/** Structural registry pair accepted by Session and SessionManager. */
|
|
99
|
+
export interface ConversationRuntime {
|
|
100
|
+
readonly events: ConversationEventDefinitions & {
|
|
101
|
+
subscribe(listener: () => void): () => void;
|
|
102
|
+
};
|
|
103
|
+
readonly views: ConversationViewDefinitions & {
|
|
104
|
+
subscribe(listener: () => void): () => void;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=conversation-assembler.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ConversationNode } from './conversation.ts';
|
|
2
|
+
import type { ConversationPromptSnapshot } from './request-inspection.ts';
|
|
3
|
+
/** Operation that started a new append-only model context. */
|
|
4
|
+
export type ConversationContextOriginKind = 'compaction' | 'rewind' | 'rewrite';
|
|
5
|
+
/** One immutable model-context generation reconstructed from surface replacements. */
|
|
6
|
+
export interface ConversationContext {
|
|
7
|
+
/** Zero-based generation within the session; stable across later appends. */
|
|
8
|
+
id: number;
|
|
9
|
+
/** Previous generation in this session; absent for the initial context. */
|
|
10
|
+
parentId?: number;
|
|
11
|
+
/** Why this generation exists; absent for the initial context. */
|
|
12
|
+
origin?: ConversationContextOriginKind;
|
|
13
|
+
/** Event seq of the replacement that created this generation. */
|
|
14
|
+
originSeq?: number;
|
|
15
|
+
/** Unix epoch ms of the replacement that created this generation. */
|
|
16
|
+
createdAt?: number;
|
|
17
|
+
/** Latest request header observed in this generation, inherited until a later header replaces it. */
|
|
18
|
+
prompt?: ConversationPromptSnapshot;
|
|
19
|
+
/** Final frozen nodes for historical generations, or current folded nodes for the tail. */
|
|
20
|
+
nodes: readonly ConversationNode[];
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=conversation-context.d.ts.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { SessionEvent } from '@hydraharness/harness-session/types';
|
|
2
|
+
import type { ConversationEventInput, ConversationLocation, ConversationLocationData, ConversationTimelineSnapshot } from '../contract/conversation.ts';
|
|
3
|
+
/** One Context's previous and next Location-data publication. */
|
|
4
|
+
export interface ConversationLocationDataChange {
|
|
5
|
+
readonly owner: string;
|
|
6
|
+
readonly previous: ConversationLocationData | null;
|
|
7
|
+
readonly next: ConversationLocationData | null;
|
|
8
|
+
}
|
|
9
|
+
/** Session-owned Turn/Step timeline and event-to-Location index. */
|
|
10
|
+
export declare class ConversationLocationIndex {
|
|
11
|
+
private coordinates;
|
|
12
|
+
private locations;
|
|
13
|
+
private seqsByTurn;
|
|
14
|
+
private timeline;
|
|
15
|
+
private readonly turnDataStores;
|
|
16
|
+
private readonly stepDataStores;
|
|
17
|
+
private currentTurn;
|
|
18
|
+
private currentStep;
|
|
19
|
+
/**
|
|
20
|
+
* Return the current reference-stable timeline.
|
|
21
|
+
* @returns current timeline snapshot.
|
|
22
|
+
*/
|
|
23
|
+
snapshot(): ConversationTimelineSnapshot;
|
|
24
|
+
/**
|
|
25
|
+
* Replace all Definition-owned Location values while preserving reader identities.
|
|
26
|
+
* @param entries - complete current set of Definition-owned Location values.
|
|
27
|
+
* @returns whether any published Location data changed.
|
|
28
|
+
*/
|
|
29
|
+
replaceData(entries: readonly {
|
|
30
|
+
readonly owner: string;
|
|
31
|
+
readonly data: ConversationLocationData;
|
|
32
|
+
}[]): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Apply changed Context publications without rebuilding Turn/Step membership.
|
|
35
|
+
* @param changes - incremental removals and replacements from published Contexts.
|
|
36
|
+
* @returns whether any published Location data changed.
|
|
37
|
+
*/
|
|
38
|
+
applyData(changes: readonly ConversationLocationDataChange[]): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Resolve the latest Location for one event.
|
|
41
|
+
* @param event - event already ingested into this index.
|
|
42
|
+
* @returns current Location, falling back to session when it has no Turn/Step affinity.
|
|
43
|
+
*/
|
|
44
|
+
locationOf(event: SessionEvent): ConversationLocation;
|
|
45
|
+
/**
|
|
46
|
+
* Rebuild timeline facts after replace/prepend or a boundary append.
|
|
47
|
+
* @param entries - complete current window in ascending seq order.
|
|
48
|
+
* @returns seqs whose resolved Location changed.
|
|
49
|
+
*/
|
|
50
|
+
rebuild(entries: readonly ConversationEventInput[]): ReadonlySet<number>;
|
|
51
|
+
/**
|
|
52
|
+
* Append one Turn/Step boundary while revisiting only the owning Turn.
|
|
53
|
+
* @param event - contiguous tail boundary event.
|
|
54
|
+
* @returns seqs whose immutable Location reference changed.
|
|
55
|
+
*/
|
|
56
|
+
appendBoundary(event: SessionEvent): ReadonlySet<number>;
|
|
57
|
+
/**
|
|
58
|
+
* Index one non-boundary tail event without rescanning the window.
|
|
59
|
+
* @param event - contiguous appended event.
|
|
60
|
+
*/
|
|
61
|
+
appendNonBoundary(event: SessionEvent): void;
|
|
62
|
+
private indexTurnSeq;
|
|
63
|
+
private turnData;
|
|
64
|
+
private stepData;
|
|
65
|
+
private mutableTurnData;
|
|
66
|
+
private mutableStepData;
|
|
67
|
+
private storeFor;
|
|
68
|
+
private resolve;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=conversation-location-index.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Pure grouping of prompt revisions into one navigable conversation. */
|
|
2
|
+
import type { SessionId } from '@hydraharness/harness-api-remotes/client';
|
|
3
|
+
import type { SessionVersionId } from '@hydraharness/harness-session/types';
|
|
4
|
+
import type { SessionListState, SessionSummary } from './service.ts';
|
|
5
|
+
/** A stored transcript path, with its selection state and owning session. */
|
|
6
|
+
export type ConversationVersion = Omit<SessionSummary, 'id'> & {
|
|
7
|
+
id: SessionId | SessionVersionId;
|
|
8
|
+
selected?: boolean;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* List the original conversation followed by its revisions in creation order.
|
|
12
|
+
* @param list - current session list.
|
|
13
|
+
* @param sessionId - any version of the conversation.
|
|
14
|
+
* @returns available versions, oldest first.
|
|
15
|
+
*/
|
|
16
|
+
export declare function conversationVersions(list: SessionListState, sessionId: SessionId): ConversationVersion[];
|
|
17
|
+
/**
|
|
18
|
+
* Map every version to one sidebar row: current, last viewed, otherwise latest.
|
|
19
|
+
* Archiving any member hides the conversation as a whole.
|
|
20
|
+
* @param list - current session list and selection.
|
|
21
|
+
* @param archived - archived session identities.
|
|
22
|
+
* @returns representatives addressed by every member identity.
|
|
23
|
+
*/
|
|
24
|
+
export declare function conversationRepresentatives(list: SessionListState, archived: ReadonlySet<SessionId>): Map<SessionId, SessionSummary>;
|
|
25
|
+
//# sourceMappingURL=conversation-versions.d.ts.map
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
import type { CommandId } from '@hydraharness/harness-commands/brand';
|
|
2
|
+
import type { MessageId } from '@hydraharness/harness-llm/brand';
|
|
3
|
+
import type { ContentBlock } from '@hydraharness/harness-llm/types';
|
|
4
|
+
import type { ImageAttachmentRef } from '@hydraharness/harness-attachment';
|
|
5
|
+
import type { LlmRetryEventData } from '@hydraharness/harness-llm-retry/types';
|
|
6
|
+
import type { TodoItem } from '@hydraharness/harness-session/types';
|
|
7
|
+
import type { RpcError, SessionId, SubagentAddress, ToolCallView, ToolResultView } from '@hydraharness/harness-api-remotes/client';
|
|
8
|
+
import type { PendingInteraction } from './pending.ts';
|
|
9
|
+
import type { ContextProvenanceView, KnownContextForm } from './context-provenance.ts';
|
|
10
|
+
import type { ChatConversationViewNode, ConversationTimelineSnapshot, ConversationViewSnapshotStore } from '../contract/conversation.ts';
|
|
11
|
+
export type { TodoItem };
|
|
12
|
+
/** Request configuration recorded for one provider call. */
|
|
13
|
+
export interface AssistantRequestConfig {
|
|
14
|
+
provider: string;
|
|
15
|
+
model: string;
|
|
16
|
+
purpose?: string;
|
|
17
|
+
thinking?: string;
|
|
18
|
+
reasoningEffort?: string;
|
|
19
|
+
temperature?: number;
|
|
20
|
+
maxTokens?: number;
|
|
21
|
+
stop?: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
/** Stable provider/model identity reported for one completed request. */
|
|
24
|
+
export interface AssistantProvenanceView {
|
|
25
|
+
provider: string;
|
|
26
|
+
model: string;
|
|
27
|
+
}
|
|
28
|
+
/** Assistant content blocks sorted by what the UI cares about
|
|
29
|
+
* (text body / collapsible reasoning / tool-call card head / other fallback). */
|
|
30
|
+
export type AssistantBlock = {
|
|
31
|
+
kind: 'text';
|
|
32
|
+
text: string;
|
|
33
|
+
} | {
|
|
34
|
+
kind: 'reasoning';
|
|
35
|
+
text: string;
|
|
36
|
+
} | {
|
|
37
|
+
kind: 'image';
|
|
38
|
+
attachment: ImageAttachmentRef;
|
|
39
|
+
} | {
|
|
40
|
+
kind: 'tool-call';
|
|
41
|
+
callId: string;
|
|
42
|
+
name: string;
|
|
43
|
+
argsRaw: string;
|
|
44
|
+
} | {
|
|
45
|
+
kind: 'other';
|
|
46
|
+
block: unknown;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* core ContentBlock[] -> AssistantBlock[] (classifier shared by finalized messages and partial block-end).
|
|
50
|
+
* @param content - core content blocks verbatim.
|
|
51
|
+
* @returns UI-classified blocks in source order.
|
|
52
|
+
*/
|
|
53
|
+
export declare function toAssistantBlocks(content: readonly ContentBlock[]): AssistantBlock[];
|
|
54
|
+
/**
|
|
55
|
+
* Classify one block (ToolCallBlock fields are id/arguments, mapped to callId/argsRaw).
|
|
56
|
+
* @param block - one core content block.
|
|
57
|
+
* @returns the UI classification.
|
|
58
|
+
*/
|
|
59
|
+
export declare function toAssistantBlock(block: ContentBlock): AssistantBlock;
|
|
60
|
+
/** A finalized user message. */
|
|
61
|
+
export interface UserMessageNode {
|
|
62
|
+
kind: 'user';
|
|
63
|
+
seq: number;
|
|
64
|
+
/** Unix epoch ms from the source session event. */
|
|
65
|
+
time: number;
|
|
66
|
+
content: readonly ContentBlock[];
|
|
67
|
+
source: unknown;
|
|
68
|
+
}
|
|
69
|
+
/** Recorded boundaries used to derive assistant latency and throughput. */
|
|
70
|
+
export interface AssistantTiming {
|
|
71
|
+
/** Matching step/start timestamp, or null when it is outside the current event window. */
|
|
72
|
+
stepStartTime: number | null;
|
|
73
|
+
/** First non-empty text/reasoning/tool delta timestamp, or null when no token delta was recorded. */
|
|
74
|
+
firstTokenTime: number | null;
|
|
75
|
+
/** Final assistant/message timestamp. */
|
|
76
|
+
completedTime: number;
|
|
77
|
+
}
|
|
78
|
+
/** A finalized assistant message or an interruption-frozen streaming prefix. */
|
|
79
|
+
export interface AssistantMessageNode {
|
|
80
|
+
kind: 'assistant';
|
|
81
|
+
seq: number;
|
|
82
|
+
/**
|
|
83
|
+
* Stable identity carried from the `assistant/message` event. Absent only on
|
|
84
|
+
* synthetic interruption fallbacks assembled from chunks without a durable
|
|
85
|
+
* assistant message.
|
|
86
|
+
*/
|
|
87
|
+
messageId?: MessageId;
|
|
88
|
+
/** Unix epoch ms from the source session event (or turn/end when frozen from a partial). */
|
|
89
|
+
time: number;
|
|
90
|
+
turn: number;
|
|
91
|
+
step: number;
|
|
92
|
+
blocks: readonly AssistantBlock[];
|
|
93
|
+
usage?: unknown;
|
|
94
|
+
provenance?: AssistantProvenanceView;
|
|
95
|
+
requestConfig?: AssistantRequestConfig;
|
|
96
|
+
/** Timing derived from the recorded step/chunk/message event sequence. */
|
|
97
|
+
timing?: AssistantTiming;
|
|
98
|
+
/** Prefix of an aborted turn, rendered with a "Stopped" marker. A durable
|
|
99
|
+
* finalized prefix uses its event seq; a chunk-only fallback uses a fractional
|
|
100
|
+
* seq derived from the closing boundary to keep it ordered inside the flow. */
|
|
101
|
+
interrupted?: true;
|
|
102
|
+
}
|
|
103
|
+
/** A human message admitted from the next-step inbox while a turn was running. */
|
|
104
|
+
export interface SteeringMessageNode {
|
|
105
|
+
kind: 'steering';
|
|
106
|
+
/** Stable message identity shared with its pre-admission inbox occurrence. */
|
|
107
|
+
messageId: MessageId;
|
|
108
|
+
seq: number;
|
|
109
|
+
/** Unix epoch ms from the source session event. */
|
|
110
|
+
time: number;
|
|
111
|
+
content: readonly ContentBlock[];
|
|
112
|
+
source: unknown;
|
|
113
|
+
}
|
|
114
|
+
/** A context/system injection surfaced in the flow. */
|
|
115
|
+
export interface ContextMessageNode {
|
|
116
|
+
kind: 'context';
|
|
117
|
+
seq: number;
|
|
118
|
+
/** Unix epoch ms from the source session event. */
|
|
119
|
+
time: number;
|
|
120
|
+
content: readonly ContentBlock[];
|
|
121
|
+
source: unknown;
|
|
122
|
+
/** Role and producer name projected from `source` ({@link contextProvenance}). */
|
|
123
|
+
provenance: ContextProvenanceView;
|
|
124
|
+
/** Producer-declared information form ({@link contextForm}); null presents as opaque. */
|
|
125
|
+
form: KnownContextForm | null;
|
|
126
|
+
}
|
|
127
|
+
/** Durable notice that a closed failed step is waiting for a model-request retry. */
|
|
128
|
+
export type ModelRetryNode = LlmRetryEventData & {
|
|
129
|
+
kind: 'model-retry';
|
|
130
|
+
seq: number;
|
|
131
|
+
/** Unix epoch ms from the llm/retry session event. */
|
|
132
|
+
time: number;
|
|
133
|
+
/**
|
|
134
|
+
* Client-derived lifecycle: scheduled until a retry turn starts, started
|
|
135
|
+
* once it does, or cancelled when the failed turn aborts first.
|
|
136
|
+
*/
|
|
137
|
+
retryState: 'scheduled' | 'started' | 'cancelled';
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Durable terminal failure for a turn that ended with an error reason; the
|
|
141
|
+
* turn's settled retry chain renders separately and never replaces this node.
|
|
142
|
+
*/
|
|
143
|
+
export interface TurnErrorNode {
|
|
144
|
+
kind: 'turn-error';
|
|
145
|
+
/** Seq of the owning turn/end event. */
|
|
146
|
+
seq: number;
|
|
147
|
+
/** Unix epoch ms from the turn/end event. */
|
|
148
|
+
time: number;
|
|
149
|
+
turn: number;
|
|
150
|
+
step: number;
|
|
151
|
+
message: string;
|
|
152
|
+
code?: string;
|
|
153
|
+
}
|
|
154
|
+
/** Durable notice for a turn ended by the per-request output-token cap. */
|
|
155
|
+
export interface TurnMaxTokensNode {
|
|
156
|
+
kind: 'turn-max-tokens';
|
|
157
|
+
/** Seq of the owning turn/end event. */
|
|
158
|
+
seq: number;
|
|
159
|
+
/** Unix epoch ms from the turn/end event. */
|
|
160
|
+
time: number;
|
|
161
|
+
turn: number;
|
|
162
|
+
step: number;
|
|
163
|
+
}
|
|
164
|
+
/** A tool result paired (when in-window) with its call head. */
|
|
165
|
+
export interface ToolResultNode {
|
|
166
|
+
kind: 'tool-result';
|
|
167
|
+
seq: number;
|
|
168
|
+
/** Unix epoch ms from the tool/result session event. */
|
|
169
|
+
time: number;
|
|
170
|
+
callId: string;
|
|
171
|
+
/** Call head backfilled from the in-window tool/call; null when window truncation left the call outside (card head shows callId). */
|
|
172
|
+
call: {
|
|
173
|
+
name: string;
|
|
174
|
+
argsRaw: string;
|
|
175
|
+
} | null;
|
|
176
|
+
/** Unix epoch ms of the paired tool/call when the call is still in-window; used for call-row duration. */
|
|
177
|
+
callTime: number | null;
|
|
178
|
+
content: readonly ContentBlock[];
|
|
179
|
+
isError: boolean;
|
|
180
|
+
error?: {
|
|
181
|
+
name: string;
|
|
182
|
+
code: string;
|
|
183
|
+
};
|
|
184
|
+
meta?: unknown;
|
|
185
|
+
/** Host-computed render intent from the paired tool/call's wire view; null = generic JSON card (documented default). */
|
|
186
|
+
callView: ToolCallView | null;
|
|
187
|
+
/** Host-computed render intent from this tool/result's wire view; null = same default. */
|
|
188
|
+
resultView: ToolResultView | null;
|
|
189
|
+
/** Child calls owned by this call, in dispatch order. */
|
|
190
|
+
subCalls: readonly ToolCallBlock[];
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* One landed compaction, marked at the checkpoint's own log position. The
|
|
194
|
+
* conversation it shadowed on the model surface stays in the transcript above
|
|
195
|
+
* it: the marker reports where the model stopped seeing that history, it does
|
|
196
|
+
* not replace it. The framed checkpoint payload is an instruction envelope
|
|
197
|
+
* written for the model and never renders.
|
|
198
|
+
*/
|
|
199
|
+
export interface CompactionSummaryNode {
|
|
200
|
+
kind: 'compaction';
|
|
201
|
+
/** Seq of the replacement `user/message` that landed the checkpoint. */
|
|
202
|
+
seq: number;
|
|
203
|
+
/** Unix epoch ms of the checkpoint event. */
|
|
204
|
+
time: number;
|
|
205
|
+
/** Summary text from the checkpoint's cited `compaction/summary` event; null when
|
|
206
|
+
* the window cut left that event outside (the marker is then not expandable). */
|
|
207
|
+
summary: string | null;
|
|
208
|
+
/** Seq of the loaded `compaction/summary` event, or null when that event is outside the window. */
|
|
209
|
+
summaryEventSeq: number | null;
|
|
210
|
+
/** Number of surface items replaced, or null when the summary event is unavailable or malformed. */
|
|
211
|
+
shadowedItemCount: number | null;
|
|
212
|
+
/** Estimated token price of the replaced items, or null when the summary event is unavailable or malformed. */
|
|
213
|
+
shadowedTokenCount: number | null;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Fallback for surface events this UI version does not know: the documented
|
|
217
|
+
* default arm of `SessionEventMap`, which is merge-extensible, so the
|
|
218
|
+
* projection's switch cannot end in `assertNever`. No event produces this node
|
|
219
|
+
* today — `isAppendSurfaceEvent` admits only the three types in core's
|
|
220
|
+
* `SurfaceEventType`, and each has its own arm — and it exists so widening that
|
|
221
|
+
* set core-side degrades to a raw row instead of dropping the event silently.
|
|
222
|
+
*/
|
|
223
|
+
export interface UnknownSurfaceNode {
|
|
224
|
+
kind: 'unknown';
|
|
225
|
+
seq: number;
|
|
226
|
+
/** Unix epoch ms from the source session event when known. */
|
|
227
|
+
time: number;
|
|
228
|
+
type: string;
|
|
229
|
+
data: unknown;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* One slash-command lifecycle folded from the log-only `command/run` /
|
|
233
|
+
* `command/done` pair (paired by commandId, mirroring tool call↔result).
|
|
234
|
+
* Log-only events are not surface events, so the command Definition indexes
|
|
235
|
+
* them separately and the Chat builder orders the resulting node by seq. A window cut
|
|
236
|
+
* between the pair soft-falls like tool pairs: a done with no in-window run
|
|
237
|
+
* still builds a node (name/args null), and a run with no done renders as
|
|
238
|
+
* still executing.
|
|
239
|
+
*/
|
|
240
|
+
export interface CommandNode {
|
|
241
|
+
kind: 'command';
|
|
242
|
+
/** Seq of the command/run event; the done event's seq when only the done is in-window. */
|
|
243
|
+
seq: number;
|
|
244
|
+
/** Unix epoch ms of the anchoring event. */
|
|
245
|
+
time: number;
|
|
246
|
+
/** Pairing id minted by the host executor. */
|
|
247
|
+
commandId: CommandId;
|
|
248
|
+
/** Command name (run payload's structured field); null when the run fell outside the window. */
|
|
249
|
+
name: string | null;
|
|
250
|
+
/**
|
|
251
|
+
* Verbatim rawInput after the name, including separator whitespace; null
|
|
252
|
+
* when omitted by the command or when the run fell outside the window.
|
|
253
|
+
*/
|
|
254
|
+
args: string | null;
|
|
255
|
+
/** Settlement outcome (done payload); null while the command is still executing. */
|
|
256
|
+
outcome: {
|
|
257
|
+
kind: 'success' | 'error';
|
|
258
|
+
text?: string;
|
|
259
|
+
/** Earlier authoritative domain event for a richer client-computed presentation. */
|
|
260
|
+
sourceEventSeq?: number;
|
|
261
|
+
} | null;
|
|
262
|
+
}
|
|
263
|
+
/** Finalized conversation node union (kind discriminates; seq is the React key). */
|
|
264
|
+
export type ConversationNode = UserMessageNode | AssistantMessageNode | SteeringMessageNode | ContextMessageNode | ModelRetryNode | TurnErrorNode | TurnMaxTokensNode | ToolResultNode | CommandNode | CompactionSummaryNode | UnknownSurfaceNode;
|
|
265
|
+
/** In-flight tool card material: tool/call seen, tool/result not yet. */
|
|
266
|
+
export interface RunningToolCall {
|
|
267
|
+
callId: string;
|
|
268
|
+
name: string;
|
|
269
|
+
argsRaw: string;
|
|
270
|
+
turn: number;
|
|
271
|
+
step: number;
|
|
272
|
+
/** Unix epoch ms when the tool/call event was logged. */
|
|
273
|
+
time: number;
|
|
274
|
+
/** Host-computed render intent riding the tool/call frame; null = generic JSON card. */
|
|
275
|
+
callView: ToolCallView | null;
|
|
276
|
+
/** Child calls owned by this call, in dispatch order. */
|
|
277
|
+
subCalls: readonly ToolCallBlock[];
|
|
278
|
+
}
|
|
279
|
+
/** One running or settled call, recursively owning its child calls. */
|
|
280
|
+
export type ToolCallBlock = RunningToolCall | ToolResultNode;
|
|
281
|
+
/** One transient inbox occurrence from the authoritative `session/queue` snapshot. */
|
|
282
|
+
export interface QueuedMessage {
|
|
283
|
+
readonly id: MessageId;
|
|
284
|
+
/** Stable message identity used for transient-to-durable steering handoff. */
|
|
285
|
+
readonly messageId: MessageId;
|
|
286
|
+
/** Agent-resolved placement; only queued rows accept queue mutations. */
|
|
287
|
+
readonly placement: 'queued' | 'steering' | 'context';
|
|
288
|
+
/** Complete content used to render pending steering before it becomes durable. */
|
|
289
|
+
readonly content: readonly ContentBlock[];
|
|
290
|
+
readonly preview: string;
|
|
291
|
+
/** Complete editable text; null when the message contains non-text blocks. */
|
|
292
|
+
readonly text: string | null;
|
|
293
|
+
}
|
|
294
|
+
/** In-progress assistant output (chunk accumulator product). */
|
|
295
|
+
export interface PartialAssistant {
|
|
296
|
+
turn: number;
|
|
297
|
+
step: number;
|
|
298
|
+
blocks: readonly AssistantBlock[];
|
|
299
|
+
}
|
|
300
|
+
/** History-open lifecycle of a Session window. */
|
|
301
|
+
export type OpenState = 'cold' | 'loading' | 'open' | 'error';
|
|
302
|
+
/**
|
|
303
|
+
* Input-area shape of an OPEN session, derived at snapshot assembly (the one
|
|
304
|
+
* place that knows the predicate — consumers switch, never re-derive):
|
|
305
|
+
*
|
|
306
|
+
* - `blank`: the authoritative blank bit is still set and no prompt was
|
|
307
|
+
* attempted — the UI renders the blank-session guidance hero.
|
|
308
|
+
* - `engaging`: a first prompt was attempted, but no accepted turn or other
|
|
309
|
+
* authoritative activity signal has arrived — the UI keeps the composer
|
|
310
|
+
* visible through admission and error frames.
|
|
311
|
+
* - `active`: the session is non-blank beyond its pending first prompt,
|
|
312
|
+
* contains visible non-command Chat content, is running, or owns a pending
|
|
313
|
+
* interaction — the ordinary conversation view.
|
|
314
|
+
*
|
|
315
|
+
* A failed first prompt stays `engaging` (composer + error strip — retry
|
|
316
|
+
* semantics; returning to the hero would discard the error context).
|
|
317
|
+
* Sessions whose window is not open (`loading`/`error`) are outside phase
|
|
318
|
+
* jurisdiction: consumers branch on {@link ConversationSnapshot.openState}
|
|
319
|
+
* first.
|
|
320
|
+
*/
|
|
321
|
+
export type ComposerPhase = 'blank' | 'engaging' | 'active';
|
|
322
|
+
/** Send/stop failure surfaced in the input error strip; op picks the user-facing copy (send failed vs stop failed). */
|
|
323
|
+
export interface PromptError {
|
|
324
|
+
op: 'send' | 'stop';
|
|
325
|
+
error: RpcError;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Stable live per-key reader. An old ChatSnapshot observes later flushes
|
|
329
|
+
* through this store.
|
|
330
|
+
*/
|
|
331
|
+
export interface ChatNodeStore {
|
|
332
|
+
/** @param key - stable Conversation Context key. @returns current Node, when visible or hidden. */
|
|
333
|
+
get(key: string): ChatConversationViewNode | undefined;
|
|
334
|
+
/** @returns all currently materialized Nodes without imposing render order. */
|
|
335
|
+
values(): readonly ChatConversationViewNode[];
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Stable live Location index. An old ChatSnapshot observes later membership
|
|
339
|
+
* changes through this index.
|
|
340
|
+
*/
|
|
341
|
+
export interface ChatLocationNodeIndex {
|
|
342
|
+
/** @param turn - owning turn. @returns ordered Chat Node keys in the turn. */
|
|
343
|
+
getTurn(turn: number): readonly string[];
|
|
344
|
+
/** @param turn - owning turn. @param step - owning step. @returns ordered Chat Node keys in the step. */
|
|
345
|
+
getStep(turn: number, step: number): readonly string[];
|
|
346
|
+
}
|
|
347
|
+
/** Compatibility projection backing StatsLine and the legacy top-level snapshot fields. */
|
|
348
|
+
export interface LegacyConversationSlice {
|
|
349
|
+
readonly nodes: readonly ConversationNode[];
|
|
350
|
+
readonly turnTimings: ReadonlyMap<number, {
|
|
351
|
+
readonly startTime: number;
|
|
352
|
+
readonly endTime?: number;
|
|
353
|
+
}>;
|
|
354
|
+
readonly turnEnds: ReadonlyMap<number, number>;
|
|
355
|
+
readonly partial: PartialAssistant | null;
|
|
356
|
+
readonly runningCalls: readonly RunningToolCall[];
|
|
357
|
+
}
|
|
358
|
+
/** Incremental Chat publication with immutable order and stable live keyed readers. */
|
|
359
|
+
export interface ChatSnapshot {
|
|
360
|
+
readonly order: readonly string[];
|
|
361
|
+
readonly nodes: ChatNodeStore;
|
|
362
|
+
readonly locations: ChatLocationNodeIndex;
|
|
363
|
+
readonly timeline: ConversationTimelineSnapshot;
|
|
364
|
+
readonly legacy: LegacyConversationSlice;
|
|
365
|
+
}
|
|
366
|
+
/** Empty target store used by fixtures and Sessions without registered views. */
|
|
367
|
+
export declare const EMPTY_CONVERSATION_VIEWS: ConversationViewSnapshotStore;
|
|
368
|
+
/** Empty Chat target used before a view builder is registered. */
|
|
369
|
+
export declare const EMPTY_CHAT_SNAPSHOT: ChatSnapshot;
|
|
370
|
+
/** The immutable snapshot contract Session hands to uSES (see the web client architecture RFC). */
|
|
371
|
+
export interface ConversationSnapshot {
|
|
372
|
+
sessionId: SessionId;
|
|
373
|
+
/** Registered target snapshots assembled from Session events. */
|
|
374
|
+
views: ConversationViewSnapshotStore;
|
|
375
|
+
/** Final Chat target assembled from independently registered business Definitions. */
|
|
376
|
+
chat: ChatSnapshot;
|
|
377
|
+
/** Legacy top-level compatibility field mirrored from the registered Chat Definitions. */
|
|
378
|
+
nodes: readonly ConversationNode[];
|
|
379
|
+
/** Exact in-window `turn/start` time and optional matching `turn/end` time. */
|
|
380
|
+
turnTimings: ReadonlyMap<number, {
|
|
381
|
+
readonly startTime: number;
|
|
382
|
+
readonly endTime?: number;
|
|
383
|
+
}>;
|
|
384
|
+
/** In-window completed turn number -> its `turn/end` event seq. */
|
|
385
|
+
turnEnds: ReadonlyMap<number, number>;
|
|
386
|
+
partial: PartialAssistant | null;
|
|
387
|
+
runningCalls: readonly RunningToolCall[];
|
|
388
|
+
pending: readonly PendingInteraction[];
|
|
389
|
+
/** Authoritative transient inbox snapshot, including queued and steering placements. */
|
|
390
|
+
queue: readonly QueuedMessage[];
|
|
391
|
+
running: boolean;
|
|
392
|
+
/**
|
|
393
|
+
* Catalog-discovered continuation address. Its parent availability controls
|
|
394
|
+
* human input; null means ordinary session transport.
|
|
395
|
+
*/
|
|
396
|
+
subagent: {
|
|
397
|
+
address: SubagentAddress;
|
|
398
|
+
parentAvailable: boolean;
|
|
399
|
+
} | null;
|
|
400
|
+
/** Input-area shape (see {@link ComposerPhase}); derived here, switched on by consumers. */
|
|
401
|
+
composerPhase: ComposerPhase;
|
|
402
|
+
/** Set after host/session-removed; the UI grays out and disables input. */
|
|
403
|
+
removed: boolean;
|
|
404
|
+
openState: OpenState;
|
|
405
|
+
openError: RpcError | null;
|
|
406
|
+
hasMore: boolean;
|
|
407
|
+
loadingOlder: boolean;
|
|
408
|
+
promptError: PromptError | null;
|
|
409
|
+
/**
|
|
410
|
+
* Whether this session still has an empty log (no user message yet).
|
|
411
|
+
* Mirrors the host summary's derived blank bit: seeded from `session.list`
|
|
412
|
+
* / the `host/session-added` frame, flipped false by the first ACCEPTED
|
|
413
|
+
* prompt locally (on the RPC success response — acceptance proves the
|
|
414
|
+
* user message is in the host log; a rejected first prompt keeps the
|
|
415
|
+
* session blank and reusable) and by any `running: true` status remotely,
|
|
416
|
+
* and re-aligned by every list re-pull (the summary stays authoritative).
|
|
417
|
+
* Blank sessions are hidden from session lists and reused by New Session.
|
|
418
|
+
*/
|
|
419
|
+
blank: boolean;
|
|
420
|
+
lastAgentError: string | null;
|
|
421
|
+
}
|
|
422
|
+
//# sourceMappingURL=conversation.d.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a durable failure into copy that is safe to expose in the GUI.
|
|
3
|
+
* @param failure - Failure value preserved by the session event.
|
|
4
|
+
* @returns Display-safe copy for client projections.
|
|
5
|
+
*/
|
|
6
|
+
export declare function displayFailureMessage(failure: unknown): string;
|
|
7
|
+
//# sourceMappingURL=failure-display.d.ts.map
|