@pluno/product-agent-web 0.1.220 → 0.1.221
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 +8 -0
- package/dist/activeUsersCounter.d.ts +0 -7
- package/dist/adapters/web/activeUsers.d.ts +4 -0
- package/dist/adapters/web/backendHttp.d.ts +12 -0
- package/dist/adapters/web/backendTransport.d.ts +54 -0
- package/dist/adapters/web/directoryAdapters.d.ts +85 -0
- package/dist/adapters/web/directoryScope.d.ts +42 -0
- package/dist/adapters/web/modelScope.d.ts +3 -0
- package/dist/adapters/web/socketIOTransport.d.ts +72 -0
- package/dist/chatPresentation.d.ts +2 -0
- package/dist/core/active-users/reducer.d.ts +47 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/model-selection/commands.d.ts +22 -0
- package/dist/core/model-selection/contracts.d.ts +3 -1
- package/dist/core/model-selection/events.d.ts +15 -0
- package/dist/core/model-selection/reducer.d.ts +4 -0
- package/dist/core/model-selection/selectors.d.ts +10 -0
- package/dist/core/model-selection/state.d.ts +22 -0
- package/dist/core/protocol/modelRouting.d.ts +2 -0
- package/dist/core/session-directory/contracts.d.ts +202 -0
- package/dist/core/session-directory/membership.d.ts +4 -0
- package/dist/core/session-directory/reducer.d.ts +4 -0
- package/dist/core/session-directory/selectors.d.ts +2 -0
- package/dist/core/session-directory/state.d.ts +6 -0
- package/dist/index.d.ts +28 -16
- package/dist/interruptState.d.ts +2 -0
- package/dist/product-agent-runtime.cjs +1 -1
- package/dist/product-agent-runtime.js +384 -315
- package/dist/product-agent-sdk.js +7611 -3447
- package/dist/product-agent-widget.js +8794 -4769
- package/dist/public/operationRoutes.d.ts +1 -0
- package/dist/runtime/composition.d.ts +27 -7
- package/dist/runtime/modelSelection.d.ts +14 -0
- package/dist/runtimeClient.d.ts +10 -0
- package/dist/sessionRecoveryPolling.d.ts +3 -0
- package/dist/timelineReconciliation.d.ts +1 -0
- package/dist/uiInvariants.d.ts +6 -0
- package/dist/widget.d.ts +1 -0
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -10,6 +10,14 @@ npm install @pluno/product-agent-web
|
|
|
10
10
|
|
|
11
11
|
Keep your Product Agent `secret_key` on your server. Browser code should only receive a short-lived session `token`, or call your own authenticated token endpoint.
|
|
12
12
|
|
|
13
|
+
## Host-rendered chat notices
|
|
14
|
+
|
|
15
|
+
The default widget handle exposes `host`. Hosts may append presentation-only elements with
|
|
16
|
+
`slot="bottom-notices"` (account, authentication, connection or device notices above the composer) or
|
|
17
|
+
`slot="conversation-notices"` (conversation-local notices inline). Remove these elements when their
|
|
18
|
+
existing owner clears the notice; the slots do not store state or decide eligibility. The main-web React
|
|
19
|
+
shell uses portals into these slots. Do not use them as a second transcript or interaction owner.
|
|
20
|
+
|
|
13
21
|
## Headless SDK
|
|
14
22
|
|
|
15
23
|
```ts
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
type ActiveUsersCounterOptions = {
|
|
2
|
-
backendUrl?: string;
|
|
3
|
-
fetcher?: typeof fetch;
|
|
4
|
-
loader?: () => Promise<ActiveUsersCounterValue>;
|
|
5
|
-
};
|
|
6
1
|
export type ActiveUsersCounterValue = {
|
|
7
2
|
count: number;
|
|
8
3
|
refreshAfterMs: number;
|
|
9
4
|
};
|
|
10
|
-
export declare function startActiveUsersCounter(onUpdate: (value: number) => void, options?: ActiveUsersCounterOptions): () => void;
|
|
11
|
-
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PAEffectHandlers } from "../../core/kernel/effects";
|
|
2
|
+
import type { PAActiveUsersEffects } from "../../core/active-users/reducer";
|
|
3
|
+
export declare function createActiveUsersPorts(load: () => Promise<number>, random?: () => number, displayRandom?: () => number): PAEffectHandlers<PAActiveUsersEffects>;
|
|
4
|
+
export declare function fetchActiveUsersCount(backendUrl: string, fetcher?: (input: URL, init?: RequestInit) => Promise<Response>): Promise<number>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ProductAgentSocketAuth } from './socketIOTransport';
|
|
2
|
+
export declare class ProductAgentHttpTransport {
|
|
3
|
+
private readonly options;
|
|
4
|
+
private readonly requests;
|
|
5
|
+
readonly auth: ProductAgentSocketAuth;
|
|
6
|
+
constructor(options: {
|
|
7
|
+
backendUrl: string;
|
|
8
|
+
auth: ProductAgentSocketAuth;
|
|
9
|
+
});
|
|
10
|
+
dispose(): void;
|
|
11
|
+
request<T = unknown>(path: string, params?: Record<string, unknown>, body?: unknown, method?: string, namespace?: 'runtime' | 'extension' | 'embed'): Promise<T>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ProductAgentHttpTransport } from './backendHttp';
|
|
2
|
+
import { ProductAgentSocketIOTransport, type ProductAgentSocketAuth } from './socketIOTransport';
|
|
3
|
+
type WireEvent = Record<string, any> & {
|
|
4
|
+
type: string;
|
|
5
|
+
};
|
|
6
|
+
type Options = {
|
|
7
|
+
backendUrl: string;
|
|
8
|
+
auth: ProductAgentSocketAuth;
|
|
9
|
+
pageUrl: () => string;
|
|
10
|
+
currentSession: (page?: Record<string, any>) => string | null;
|
|
11
|
+
contextKey?: (event: WireEvent) => string;
|
|
12
|
+
sessionReferences: () => readonly string[];
|
|
13
|
+
};
|
|
14
|
+
export declare class ProductAgentBackendTransport extends EventTarget {
|
|
15
|
+
private readonly options;
|
|
16
|
+
readyState: number;
|
|
17
|
+
private readonly transport;
|
|
18
|
+
readonly httpTransport: ProductAgentHttpTransport;
|
|
19
|
+
private readonly contextRevisions;
|
|
20
|
+
private promptRevision;
|
|
21
|
+
private initialized;
|
|
22
|
+
private bootstrapped;
|
|
23
|
+
private credentialBootstrap;
|
|
24
|
+
private readonly beforeBootstrap;
|
|
25
|
+
private readonly memberships;
|
|
26
|
+
private readonly pendingMemberships;
|
|
27
|
+
private readonly toolReceipts;
|
|
28
|
+
private readonly acceptedMessages;
|
|
29
|
+
private hydration;
|
|
30
|
+
private hydrations;
|
|
31
|
+
constructor(options: Options);
|
|
32
|
+
get directoryRooms(): Pick<ProductAgentSocketIOTransport, 'retain' | 'release'>;
|
|
33
|
+
replaceCredentials(auth: ProductAgentSocketAuth, authorityChanged: boolean, bootstrap?: Record<string, any> | null): void;
|
|
34
|
+
pause(): void;
|
|
35
|
+
close(): void;
|
|
36
|
+
private finishClose;
|
|
37
|
+
send(data: string): void;
|
|
38
|
+
private receive;
|
|
39
|
+
acceptMessage(message: Event): void;
|
|
40
|
+
private rejectToolReceipts;
|
|
41
|
+
private deliver;
|
|
42
|
+
private buffer;
|
|
43
|
+
private fail;
|
|
44
|
+
private http;
|
|
45
|
+
private dispatch;
|
|
46
|
+
private isCurrent;
|
|
47
|
+
synchronizeReferences(): void;
|
|
48
|
+
private restoreReference;
|
|
49
|
+
private retain;
|
|
50
|
+
private hydrate;
|
|
51
|
+
}
|
|
52
|
+
export { ProductAgentHttpTransport } from './backendHttp';
|
|
53
|
+
export { createDirectoryPorts, ProductAgentDirectoryObservationAdapter } from './directoryAdapters';
|
|
54
|
+
export { ProductAgentDirectoryScopeAdapter, createWebDirectoryPersistence } from './directoryScope';
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { PARequestId, PASessionId } from '../../core/kernel/state';
|
|
2
|
+
import type { PAConversationMetadata, PADirectoryAuthority, PADirectoryPorts, PADirectoryQuery } from '../../core/session-directory/contracts';
|
|
3
|
+
import { ProductAgentSessionRecoveryPoller } from '../../sessionRecoveryPolling';
|
|
4
|
+
import type { PAClientRuntime } from '../../runtime/composition';
|
|
5
|
+
import { ProductAgentHttpTransport } from './backendHttp';
|
|
6
|
+
import type { ProductAgentSocketIOTransport } from './socketIOTransport';
|
|
7
|
+
export declare const DIRECTORY_POLL_INTERVALS: {
|
|
8
|
+
readonly activeIntervalMs: 3000;
|
|
9
|
+
readonly idleIntervalMs: 15000;
|
|
10
|
+
readonly maxFailureIntervalMs: 30000;
|
|
11
|
+
};
|
|
12
|
+
type AuthorityBoundary = {
|
|
13
|
+
authority: PADirectoryAuthority;
|
|
14
|
+
currentAuthority: () => {
|
|
15
|
+
authorityId: string | null;
|
|
16
|
+
generation: number;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export declare function normalizeDirectoryQuery(query: PADirectoryQuery): PADirectoryQuery;
|
|
20
|
+
export declare function readDirectoryMetadata(http: ProductAgentHttpTransport, sessionId: string): Promise<PAConversationMetadata>;
|
|
21
|
+
export declare function waitForDirectoryMutation(options: {
|
|
22
|
+
runtime: PAClientRuntime;
|
|
23
|
+
authority: PADirectoryAuthority;
|
|
24
|
+
sessionId: string;
|
|
25
|
+
field: "title" | "pinned";
|
|
26
|
+
requestId: PARequestId;
|
|
27
|
+
isDisposed: () => boolean;
|
|
28
|
+
failureMessage: string;
|
|
29
|
+
}): Promise<void>;
|
|
30
|
+
export declare function createDirectoryPorts(options: AuthorityBoundary & {
|
|
31
|
+
http: ProductAgentHttpTransport;
|
|
32
|
+
pageUrl: () => string;
|
|
33
|
+
now: () => number;
|
|
34
|
+
onError?: (error: unknown) => void;
|
|
35
|
+
}): PADirectoryPorts;
|
|
36
|
+
type RecoveryHandle = Pick<ProductAgentSessionRecoveryPoller<unknown>, 'start' | 'stop' | 'refresh'>;
|
|
37
|
+
export type PADirectoryRecoveryHandles = {
|
|
38
|
+
transcript: RecoveryHandle;
|
|
39
|
+
activity: RecoveryHandle;
|
|
40
|
+
};
|
|
41
|
+
export declare class ProductAgentDirectoryObservationAdapter {
|
|
42
|
+
private readonly options;
|
|
43
|
+
private readonly queryRequests;
|
|
44
|
+
private readonly queryWaiters;
|
|
45
|
+
private readonly refreshAfterRequest;
|
|
46
|
+
private readonly observations;
|
|
47
|
+
private readonly unsubscribe;
|
|
48
|
+
private readonly owner;
|
|
49
|
+
private disposed;
|
|
50
|
+
private readonly boundary;
|
|
51
|
+
constructor(options: {
|
|
52
|
+
runtime: PAClientRuntime;
|
|
53
|
+
authority: PADirectoryAuthority;
|
|
54
|
+
http: ProductAgentHttpTransport;
|
|
55
|
+
socket: Pick<ProductAgentSocketIOTransport, 'retain' | 'release'>;
|
|
56
|
+
recovery: (sessionId: string) => PADirectoryRecoveryHandles;
|
|
57
|
+
isActiveTurn: (sessionId: string) => boolean;
|
|
58
|
+
nextRequestId: () => string;
|
|
59
|
+
onError: (error: unknown) => void;
|
|
60
|
+
wakeup: {
|
|
61
|
+
start: () => void;
|
|
62
|
+
stop: () => void;
|
|
63
|
+
};
|
|
64
|
+
enabled?: () => boolean;
|
|
65
|
+
observedQueries: () => readonly PADirectoryQuery[];
|
|
66
|
+
});
|
|
67
|
+
reconcile(): void;
|
|
68
|
+
metadata(value: PAConversationMetadata): void;
|
|
69
|
+
open(query: PADirectoryQuery, mode?: 'replace' | 'append', cursor?: string | null): Promise<void>;
|
|
70
|
+
requestPage(query: PADirectoryQuery, mode?: 'replace' | 'append', cursor?: string | null): Promise<readonly PASessionId[]>;
|
|
71
|
+
private enqueueQuery;
|
|
72
|
+
private readPage;
|
|
73
|
+
refresh(query: PADirectoryQuery, loadAllPages?: boolean): Promise<void>;
|
|
74
|
+
private refreshObservedQuery;
|
|
75
|
+
private refreshPages;
|
|
76
|
+
private waitForQuery;
|
|
77
|
+
focus(): Promise<void>;
|
|
78
|
+
private observedQueryStates;
|
|
79
|
+
private isObserved;
|
|
80
|
+
refreshObservedQueries(): Promise<void>;
|
|
81
|
+
reconnect(): Promise<void>;
|
|
82
|
+
private report;
|
|
83
|
+
dispose(): void;
|
|
84
|
+
}
|
|
85
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { PAClientScopeId, PAConversationScopeId, PASessionId } from '../../core/kernel/state';
|
|
2
|
+
import type { PADirectoryAuthority } from '../../core/session-directory/contracts';
|
|
3
|
+
import type { PAClientRuntime } from '../../runtime/composition';
|
|
4
|
+
export type PADirectoryBindingCheckpoint = Readonly<{
|
|
5
|
+
version: 1;
|
|
6
|
+
authorityId: string;
|
|
7
|
+
browserSessionId: string;
|
|
8
|
+
bindings: readonly Readonly<{
|
|
9
|
+
clientScopeId: PAClientScopeId;
|
|
10
|
+
conversationScopeId: PAConversationScopeId;
|
|
11
|
+
sessionId: PASessionId | null;
|
|
12
|
+
provisionalId: string | null;
|
|
13
|
+
}>[];
|
|
14
|
+
mains: Readonly<Record<string, PAClientScopeId>>;
|
|
15
|
+
}>;
|
|
16
|
+
export type PADirectoryBindingPersistence = {
|
|
17
|
+
read: () => Promise<unknown>;
|
|
18
|
+
write: (value: PADirectoryBindingCheckpoint) => Promise<void>;
|
|
19
|
+
sessionId: () => string;
|
|
20
|
+
liveClients: () => Promise<readonly string[]>;
|
|
21
|
+
};
|
|
22
|
+
export declare class ProductAgentDirectoryScopeAdapter {
|
|
23
|
+
private readonly options;
|
|
24
|
+
constructor(options: {
|
|
25
|
+
runtime: PAClientRuntime;
|
|
26
|
+
authority: PADirectoryAuthority;
|
|
27
|
+
random: () => number;
|
|
28
|
+
persistence: PADirectoryBindingPersistence;
|
|
29
|
+
});
|
|
30
|
+
private state;
|
|
31
|
+
private current;
|
|
32
|
+
private replacement;
|
|
33
|
+
private choose;
|
|
34
|
+
bind(clientScopeId: PAClientScopeId, conversationScopeId: PAConversationScopeId, sessionId: PASessionId, reason?: 'user' | 'tool'): Promise<void>;
|
|
35
|
+
detach(clientScopeId: PAClientScopeId): Promise<void>;
|
|
36
|
+
provisional(clientScopeId: PAClientScopeId, conversationScopeId: PAConversationScopeId, provisionalId: string): Promise<void>;
|
|
37
|
+
accepted(conversationScopeId: PAConversationScopeId, provisionalId: string, sessionId: PASessionId): Promise<void>;
|
|
38
|
+
persist(): Promise<void>;
|
|
39
|
+
restore(expectedSessionId?: string | null): Promise<boolean>;
|
|
40
|
+
}
|
|
41
|
+
export declare function createWebDirectoryPersistence(storage: Pick<Storage, 'getItem' | 'setItem'>, clientScopeId: PAClientScopeId, authorityId: string, newId?: () => string): PADirectoryBindingPersistence;
|
|
42
|
+
export declare function createBrowserDirectoryPersistence(clientScopeId: PAClientScopeId, authorityId: string, newId?: () => string): PADirectoryBindingPersistence;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { PAClientScopeId } from "../../core/kernel/state";
|
|
2
|
+
export declare function getWebModelScopeId(storage: Pick<Storage, "getItem" | "setItem">, namespace: string, newId: () => string): PAClientScopeId;
|
|
3
|
+
export declare function getBrowserModelScopeId(namespace: string, newId: () => string): PAClientScopeId;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export type ProductAgentSocketAuth = {
|
|
2
|
+
protocol: 1;
|
|
3
|
+
token: string;
|
|
4
|
+
client_id: string;
|
|
5
|
+
client_kind: "web" | "embed" | "extension";
|
|
6
|
+
role: "session_surface" | "embedded_executor" | "browser_broker";
|
|
7
|
+
transport_id?: string;
|
|
8
|
+
community_id?: string;
|
|
9
|
+
automation_run_id?: string;
|
|
10
|
+
local_runtime_client_id?: string;
|
|
11
|
+
extension_id?: string;
|
|
12
|
+
extension_version?: string;
|
|
13
|
+
};
|
|
14
|
+
type Ready = {
|
|
15
|
+
protocol: number;
|
|
16
|
+
role: string;
|
|
17
|
+
metadata_ready: boolean;
|
|
18
|
+
display_projection_ready: boolean;
|
|
19
|
+
capabilities: string[];
|
|
20
|
+
};
|
|
21
|
+
type Options = {
|
|
22
|
+
backendUrl: string;
|
|
23
|
+
auth: ProductAgentSocketAuth;
|
|
24
|
+
onReady: (ready: Ready) => void;
|
|
25
|
+
onDisconnect: (intentional: boolean) => void;
|
|
26
|
+
onEvent: (name: string, event: unknown) => void;
|
|
27
|
+
onToolCall: (event: unknown) => boolean | Promise<boolean>;
|
|
28
|
+
onError: (error: ProductAgentSocketError) => void;
|
|
29
|
+
requestTimeoutMs?: number;
|
|
30
|
+
reconnect?: boolean;
|
|
31
|
+
};
|
|
32
|
+
export declare class ProductAgentSocketError extends Error {
|
|
33
|
+
readonly code: string;
|
|
34
|
+
readonly outcomeUnknown: boolean;
|
|
35
|
+
readonly detail?: unknown | undefined;
|
|
36
|
+
constructor(message: string, code: string, outcomeUnknown?: boolean, detail?: unknown | undefined);
|
|
37
|
+
}
|
|
38
|
+
export declare class ProductAgentSocketIOTransport {
|
|
39
|
+
private readonly options;
|
|
40
|
+
private readonly socket;
|
|
41
|
+
private generation;
|
|
42
|
+
private active;
|
|
43
|
+
private ready;
|
|
44
|
+
private admitted;
|
|
45
|
+
private activating;
|
|
46
|
+
private rejectedToken;
|
|
47
|
+
private retired;
|
|
48
|
+
private replacingCredentials;
|
|
49
|
+
private readonly bindings;
|
|
50
|
+
private readonly pending;
|
|
51
|
+
private operations;
|
|
52
|
+
private queuedOperations;
|
|
53
|
+
private uploadingResult;
|
|
54
|
+
constructor(options: Options);
|
|
55
|
+
connect(): void;
|
|
56
|
+
replaceCredentials(auth: ProductAgentSocketAuth, authorityChanged: boolean): void;
|
|
57
|
+
suspend(): void;
|
|
58
|
+
disconnect(): void;
|
|
59
|
+
dispose(): void;
|
|
60
|
+
retain(sessionId: string, owner: string): Promise<void>;
|
|
61
|
+
release(sessionId: string, owner: string): Promise<void>;
|
|
62
|
+
rpc(type: string, payload: Record<string, unknown>): Promise<unknown>;
|
|
63
|
+
private activate;
|
|
64
|
+
private activationFailed;
|
|
65
|
+
private synchronize;
|
|
66
|
+
private enqueue;
|
|
67
|
+
private assertReady;
|
|
68
|
+
private uploadResult;
|
|
69
|
+
private request;
|
|
70
|
+
private invalidate;
|
|
71
|
+
}
|
|
72
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type PAQueryState } from "../kernel/state";
|
|
2
|
+
import type { PAEffect, PAEffectResultEvent } from "../kernel/effects";
|
|
3
|
+
export declare const ACTIVE_USERS_POLL_MS = 10000;
|
|
4
|
+
export declare const ACTIVE_USERS_DISPLAY_MS = 1000;
|
|
5
|
+
export type PAActiveUsersState = Readonly<{
|
|
6
|
+
authenticated: boolean;
|
|
7
|
+
generation: number;
|
|
8
|
+
sequence: number;
|
|
9
|
+
displaySequence: number;
|
|
10
|
+
backendCount: number | null;
|
|
11
|
+
query: PAQueryState<"activeUsers", number>;
|
|
12
|
+
}>;
|
|
13
|
+
export type PAActiveUsersCommand = Readonly<{
|
|
14
|
+
type: "activeUsers.authenticate";
|
|
15
|
+
authenticated: boolean;
|
|
16
|
+
}>;
|
|
17
|
+
export type PAActiveUsersEffects = {
|
|
18
|
+
"activeUsers.load": {
|
|
19
|
+
input: {
|
|
20
|
+
generation: number;
|
|
21
|
+
};
|
|
22
|
+
output: {
|
|
23
|
+
count: number;
|
|
24
|
+
updatedAt: number;
|
|
25
|
+
offset: number;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
"activeUsers.displayWait": {
|
|
29
|
+
input: {
|
|
30
|
+
milliseconds: number;
|
|
31
|
+
};
|
|
32
|
+
output: {
|
|
33
|
+
offset: number;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
"activeUsers.wait": {
|
|
37
|
+
input: {
|
|
38
|
+
milliseconds: number;
|
|
39
|
+
};
|
|
40
|
+
output: null;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export declare function createActiveUsersState(): PAActiveUsersState;
|
|
44
|
+
export declare function reduceActiveUsers(state: PAActiveUsersState, event: PAActiveUsersCommand | PAEffectResultEvent<PAActiveUsersEffects>): {
|
|
45
|
+
state: PAActiveUsersState;
|
|
46
|
+
effects: PAEffect<PAActiveUsersEffects>[];
|
|
47
|
+
};
|
package/dist/core/index.d.ts
CHANGED
|
@@ -12,3 +12,8 @@ export * from "./model-selection/contracts";
|
|
|
12
12
|
export * from "./ports";
|
|
13
13
|
export * from "./protocol/errors";
|
|
14
14
|
export * from "./protocol/json";
|
|
15
|
+
export * from "./session-directory/contracts";
|
|
16
|
+
export * from "./session-directory/state";
|
|
17
|
+
export * from "./session-directory/reducer";
|
|
18
|
+
export * from "./session-directory/selectors";
|
|
19
|
+
export * from "./session-directory/membership";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { PAClientScopeId } from "../kernel/state";
|
|
2
|
+
import type { PAProductAgentModel } from "./contracts";
|
|
3
|
+
export type PAModelCommand = Readonly<{
|
|
4
|
+
clientScopeId: PAClientScopeId;
|
|
5
|
+
}> & (Readonly<{
|
|
6
|
+
type: "model.scope_open";
|
|
7
|
+
sessionId: string | null;
|
|
8
|
+
defaultModel: PAProductAgentModel | undefined;
|
|
9
|
+
selectedModel?: PAProductAgentModel;
|
|
10
|
+
}> | Readonly<{
|
|
11
|
+
type: "composer.select_model";
|
|
12
|
+
model: PAProductAgentModel;
|
|
13
|
+
}> | Readonly<{
|
|
14
|
+
type: "model.scope_navigate";
|
|
15
|
+
sessionId: string | null;
|
|
16
|
+
}> | Readonly<{
|
|
17
|
+
type: "model.submission_capture";
|
|
18
|
+
clientMessageId: string;
|
|
19
|
+
requestedModel?: PAProductAgentModel;
|
|
20
|
+
}> | Readonly<{
|
|
21
|
+
type: "model.scope_close";
|
|
22
|
+
}>);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { PAClientScopeId } from "../kernel/state";
|
|
2
|
-
export
|
|
2
|
+
export declare const PA_PRODUCT_AGENT_MODELS: readonly ["anthropic/claude-opus-5", "anthropic/claude-sonnet-5", "deepseek/deepseek-chat-v3.1", "deepseek/deepseek-v4-flash", "gpt-5.4-nano", "gpt-5.4-mini", "gpt-5.4", "gpt-5.6-luna", "gpt-5.6-terra", "gpt-5.6-sol"];
|
|
3
|
+
export type PAProductAgentModel = (typeof PA_PRODUCT_AGENT_MODELS)[number];
|
|
3
4
|
export type PAComposerModelSelection = Readonly<{
|
|
4
5
|
clientScopeId: PAClientScopeId;
|
|
5
6
|
requestedModel: PAProductAgentModel;
|
|
6
7
|
}>;
|
|
8
|
+
export declare const isPAProductAgentModel: (value: unknown) => value is PAProductAgentModel;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PAClientScopeId } from "../kernel/state";
|
|
2
|
+
import type { PAProductAgentModel } from "./contracts";
|
|
3
|
+
import type { PATurnModelRouting } from "./state";
|
|
4
|
+
export type PAModelEvent = Readonly<{
|
|
5
|
+
clientScopeId: PAClientScopeId;
|
|
6
|
+
sessionId: string;
|
|
7
|
+
}> & (Readonly<{
|
|
8
|
+
type: "model.history_received";
|
|
9
|
+
model?: PAProductAgentModel;
|
|
10
|
+
}> | Readonly<{
|
|
11
|
+
type: "model.routing_accepted";
|
|
12
|
+
clientMessageId: string;
|
|
13
|
+
routing: PATurnModelRouting;
|
|
14
|
+
updatedAt?: number;
|
|
15
|
+
}>);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PAModelCommand } from "./commands";
|
|
2
|
+
import type { PAModelEvent } from "./events";
|
|
3
|
+
import type { PAModelSelectionState } from "./state";
|
|
4
|
+
export declare function reduceModelSelection(state: PAModelSelectionState, input: PAModelCommand | PAModelEvent): PAModelSelectionState;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PAClientScopeId } from "../kernel/state";
|
|
2
|
+
import type { PAModelScope, PAModelSelectionState } from "./state";
|
|
3
|
+
export declare const selectNextTurnModel: (scope: PAModelScope) => "anthropic/claude-opus-5" | "anthropic/claude-sonnet-5" | "deepseek/deepseek-chat-v3.1" | "deepseek/deepseek-v4-flash" | "gpt-5.4-nano" | "gpt-5.4-mini" | "gpt-5.4" | "gpt-5.6-luna" | "gpt-5.6-terra" | "gpt-5.6-sol" | undefined;
|
|
4
|
+
export declare const selectModelScope: (state: PAModelSelectionState, clientScopeId: PAClientScopeId) => Readonly<{
|
|
5
|
+
sessionId: string | null;
|
|
6
|
+
defaultModel: import("./contracts").PAProductAgentModel | undefined;
|
|
7
|
+
historyModel?: import("./contracts").PAProductAgentModel;
|
|
8
|
+
selectedModel?: import("./contracts").PAProductAgentModel;
|
|
9
|
+
submissions: Readonly<Record<string, import("./state").PAModelSubmission>>;
|
|
10
|
+
}>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { PAProductAgentModel } from "./contracts";
|
|
2
|
+
export type PATurnModelRouting = Readonly<{
|
|
3
|
+
requestedModel: PAProductAgentModel;
|
|
4
|
+
effectiveModel: PAProductAgentModel;
|
|
5
|
+
provider: "openrouter" | "azure" | "openai";
|
|
6
|
+
}>;
|
|
7
|
+
export type PAModelSubmission = Readonly<{
|
|
8
|
+
requestedModel: PAProductAgentModel | undefined;
|
|
9
|
+
routing?: PATurnModelRouting;
|
|
10
|
+
routingUpdatedAt?: number;
|
|
11
|
+
}>;
|
|
12
|
+
export type PAModelScope = Readonly<{
|
|
13
|
+
sessionId: string | null;
|
|
14
|
+
defaultModel: PAProductAgentModel | undefined;
|
|
15
|
+
historyModel?: PAProductAgentModel;
|
|
16
|
+
selectedModel?: PAProductAgentModel;
|
|
17
|
+
submissions: Readonly<Record<string, PAModelSubmission>>;
|
|
18
|
+
}>;
|
|
19
|
+
export type PAModelSelectionState = Readonly<{
|
|
20
|
+
scopes: Readonly<Record<string, PAModelScope>>;
|
|
21
|
+
}>;
|
|
22
|
+
export declare const createModelSelectionState: () => PAModelSelectionState;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import type { PAEffectHandlers } from "../kernel/effects";
|
|
2
|
+
import type { PAAuthorityId, PAClientScopeId, PAConversationScopeId, PAQueryState, PARequestId, PASessionId, PAViewId } from "../kernel/state";
|
|
3
|
+
import type { PATransportedError } from "../protocol/errors";
|
|
4
|
+
import type { PAJsonValue } from "../protocol/json";
|
|
5
|
+
export type PAConversationMetadata = Readonly<{
|
|
6
|
+
conversation_id: PASessionId;
|
|
7
|
+
version: number;
|
|
8
|
+
conversation: Readonly<{
|
|
9
|
+
id: PASessionId;
|
|
10
|
+
user_id: string;
|
|
11
|
+
community_id: string | null;
|
|
12
|
+
product_variant: "personal" | "customer_embedded";
|
|
13
|
+
created_at: string;
|
|
14
|
+
last_activity_at: string;
|
|
15
|
+
pinned: boolean;
|
|
16
|
+
title: string | null;
|
|
17
|
+
title_source: "generated" | "user";
|
|
18
|
+
}>;
|
|
19
|
+
automation_id: string | null;
|
|
20
|
+
automation_run_id: string | null;
|
|
21
|
+
first_user_message?: string | null;
|
|
22
|
+
current_page?: PAJsonValue;
|
|
23
|
+
is_active?: boolean | null;
|
|
24
|
+
}>;
|
|
25
|
+
export type PADirectoryOptimisticEntry = Readonly<{
|
|
26
|
+
id: string;
|
|
27
|
+
clientMessageId: string;
|
|
28
|
+
sessionId: PASessionId | null;
|
|
29
|
+
firstUserMessage: string;
|
|
30
|
+
currentPage: PAJsonValue;
|
|
31
|
+
createdAt: string;
|
|
32
|
+
isActive: boolean;
|
|
33
|
+
}>;
|
|
34
|
+
export type PAConversationDirectoryPage = Readonly<{
|
|
35
|
+
entries: readonly PAConversationMetadata[];
|
|
36
|
+
next_cursor: string | null;
|
|
37
|
+
}>;
|
|
38
|
+
export type PADirectoryAuthority = Readonly<{
|
|
39
|
+
authorityId: PAAuthorityId;
|
|
40
|
+
generation: number;
|
|
41
|
+
}>;
|
|
42
|
+
export type PADirectoryQuery = Readonly<{
|
|
43
|
+
kind: "recent" | "pinned";
|
|
44
|
+
origin: string | null;
|
|
45
|
+
limit: number;
|
|
46
|
+
}>;
|
|
47
|
+
export type PADirectoryQueryState = PAQueryState<string, readonly PASessionId[]> & Readonly<{
|
|
48
|
+
query: PADirectoryQuery;
|
|
49
|
+
requestSequence: number;
|
|
50
|
+
mode: "replace" | "append";
|
|
51
|
+
invalidated: boolean;
|
|
52
|
+
startedAtMetadataRevision: number;
|
|
53
|
+
startedAtActivityRevisionBySessionId: Readonly<Record<string, number>>;
|
|
54
|
+
pageData: readonly PASessionId[];
|
|
55
|
+
}>;
|
|
56
|
+
export type PADirectoryPatch = Readonly<{
|
|
57
|
+
title?: string;
|
|
58
|
+
pinned?: boolean;
|
|
59
|
+
}>;
|
|
60
|
+
export type PADirectoryMutation = Readonly<{
|
|
61
|
+
requestId: PARequestId;
|
|
62
|
+
value: string | boolean;
|
|
63
|
+
status: "pending" | "failed";
|
|
64
|
+
error: PATransportedError | null;
|
|
65
|
+
}>;
|
|
66
|
+
export type PAMembership = Readonly<{
|
|
67
|
+
members: readonly PAClientScopeId[];
|
|
68
|
+
mainClientScopeId: PAClientScopeId | null;
|
|
69
|
+
}>;
|
|
70
|
+
export type PAMainReplacement = Readonly<{
|
|
71
|
+
sessionId: PASessionId;
|
|
72
|
+
membershipRevision: number;
|
|
73
|
+
clientScopeId: PAClientScopeId;
|
|
74
|
+
}>;
|
|
75
|
+
export type PAConversationSelection = Readonly<{
|
|
76
|
+
sessionId: PASessionId | null;
|
|
77
|
+
provisionalId: string | null;
|
|
78
|
+
}>;
|
|
79
|
+
export type PADirectoryState = Readonly<{
|
|
80
|
+
authorityId: PAAuthorityId | null;
|
|
81
|
+
generation: number;
|
|
82
|
+
entities: Readonly<Record<string, PAConversationMetadata>>;
|
|
83
|
+
optimisticEntries: Readonly<Record<string, PADirectoryOptimisticEntry>>;
|
|
84
|
+
durableActivityBySessionId: Readonly<Record<string, boolean>>;
|
|
85
|
+
activityBySessionId: Readonly<Record<string, boolean>>;
|
|
86
|
+
activityRevisionBySessionId: Readonly<Record<string, number>>;
|
|
87
|
+
activityRevision: number;
|
|
88
|
+
queries: Readonly<Record<string, PADirectoryQueryState>>;
|
|
89
|
+
mutations: Readonly<Record<string, Readonly<Partial<Record<"title" | "pinned", PADirectoryMutation>>>>>;
|
|
90
|
+
metadataRevision: number;
|
|
91
|
+
membershipRevision: number;
|
|
92
|
+
clients: Readonly<Record<string, PAConversationScopeId>>;
|
|
93
|
+
selections: Readonly<Record<string, PAConversationSelection>>;
|
|
94
|
+
memberships: Readonly<Record<string, PAMembership>>;
|
|
95
|
+
views: Readonly<Record<string, PAClientScopeId>>;
|
|
96
|
+
requestSequence: number;
|
|
97
|
+
requests: Readonly<Record<string, PADirectoryRequest>>;
|
|
98
|
+
}>;
|
|
99
|
+
export type PADirectoryQueryRequest = PADirectoryAuthority & Readonly<{
|
|
100
|
+
requestId: PARequestId;
|
|
101
|
+
query: PADirectoryQuery;
|
|
102
|
+
cursor: string | null;
|
|
103
|
+
}>;
|
|
104
|
+
export type PADirectoryMutationRequest = PADirectoryAuthority & Readonly<{
|
|
105
|
+
requestId: PARequestId;
|
|
106
|
+
sessionId: PASessionId;
|
|
107
|
+
patch: PADirectoryPatch;
|
|
108
|
+
}>;
|
|
109
|
+
export type PADirectoryRequest = Readonly<{
|
|
110
|
+
kind: "directory.query";
|
|
111
|
+
input: PADirectoryQueryRequest;
|
|
112
|
+
}> | Readonly<{
|
|
113
|
+
kind: "directory.mutate";
|
|
114
|
+
input: PADirectoryMutationRequest;
|
|
115
|
+
}>;
|
|
116
|
+
export type PADirectoryEffects = {
|
|
117
|
+
"directory.query": {
|
|
118
|
+
input: PADirectoryQueryRequest;
|
|
119
|
+
output: PAConversationDirectoryPage & Readonly<{
|
|
120
|
+
updatedAt: number;
|
|
121
|
+
}>;
|
|
122
|
+
};
|
|
123
|
+
"directory.mutate": {
|
|
124
|
+
input: PADirectoryMutationRequest;
|
|
125
|
+
output: PAConversationMetadata;
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
export type PADirectoryPorts = PAEffectHandlers<PADirectoryEffects>;
|
|
129
|
+
export type PADirectoryCommand = PADirectoryAuthority & (Readonly<{
|
|
130
|
+
type: "directory.authority_replace";
|
|
131
|
+
expectedGeneration: number;
|
|
132
|
+
}> | Readonly<{
|
|
133
|
+
type: "directory.query";
|
|
134
|
+
query: PADirectoryQuery;
|
|
135
|
+
requestId: PARequestId;
|
|
136
|
+
mode: "replace" | "append";
|
|
137
|
+
cursor?: string | null;
|
|
138
|
+
}> | Readonly<{
|
|
139
|
+
type: "directory.invalidate";
|
|
140
|
+
}> | Readonly<{
|
|
141
|
+
type: "directory.optimistic_upsert";
|
|
142
|
+
entry: PADirectoryOptimisticEntry;
|
|
143
|
+
}> | Readonly<{
|
|
144
|
+
type: "directory.optimistic_accept";
|
|
145
|
+
clientMessageId: string;
|
|
146
|
+
sessionId: PASessionId;
|
|
147
|
+
}> | Readonly<{
|
|
148
|
+
type: "directory.optimistic_remove";
|
|
149
|
+
clientMessageId: string;
|
|
150
|
+
}> | Readonly<{
|
|
151
|
+
type: "directory.activity_set";
|
|
152
|
+
sessionId: PASessionId;
|
|
153
|
+
active: boolean;
|
|
154
|
+
}> | Readonly<{
|
|
155
|
+
type: "directory.mutate";
|
|
156
|
+
sessionId: PASessionId;
|
|
157
|
+
requestId: PARequestId;
|
|
158
|
+
patch: PADirectoryPatch;
|
|
159
|
+
}> | Readonly<{
|
|
160
|
+
type: "directory.bind";
|
|
161
|
+
clientScopeId: PAClientScopeId;
|
|
162
|
+
conversationScopeId: PAConversationScopeId;
|
|
163
|
+
sessionId: PASessionId;
|
|
164
|
+
reason: "user" | "tool";
|
|
165
|
+
replacement: PAMainReplacement | null;
|
|
166
|
+
}> | Readonly<{
|
|
167
|
+
type: "directory.provisional";
|
|
168
|
+
clientScopeId: PAClientScopeId;
|
|
169
|
+
conversationScopeId: PAConversationScopeId;
|
|
170
|
+
provisionalId: string;
|
|
171
|
+
replacement: PAMainReplacement | null;
|
|
172
|
+
}> | Readonly<{
|
|
173
|
+
type: "directory.accepted";
|
|
174
|
+
conversationScopeId: PAConversationScopeId;
|
|
175
|
+
provisionalId: string;
|
|
176
|
+
sessionId: PASessionId;
|
|
177
|
+
}> | Readonly<{
|
|
178
|
+
type: "directory.detach";
|
|
179
|
+
clientScopeId: PAClientScopeId;
|
|
180
|
+
replacement: PAMainReplacement | null;
|
|
181
|
+
}> | Readonly<{
|
|
182
|
+
type: "directory.view_attach";
|
|
183
|
+
viewId: PAViewId;
|
|
184
|
+
clientScopeId: PAClientScopeId;
|
|
185
|
+
}> | Readonly<{
|
|
186
|
+
type: "directory.view_detach";
|
|
187
|
+
viewId: PAViewId;
|
|
188
|
+
}>);
|
|
189
|
+
export type PADirectoryEvent = PADirectoryAuthority & Readonly<{
|
|
190
|
+
type: "directory.metadata_received";
|
|
191
|
+
metadata: PAConversationMetadata;
|
|
192
|
+
}>;
|
|
193
|
+
export type PADirectoryIntent = Readonly<{
|
|
194
|
+
observe: boolean;
|
|
195
|
+
titleClientScopeId: PAClientScopeId | null;
|
|
196
|
+
title: string | null;
|
|
197
|
+
groupClientScopeIds: readonly PAClientScopeId[];
|
|
198
|
+
}>;
|
|
199
|
+
export type PADirectoryProjection = Omit<PADirectoryState, "views" | "durableActivityBySessionId" | "activityRevisionBySessionId" | "activityRevision"> & Readonly<{
|
|
200
|
+
intents: Readonly<Record<string, PADirectoryIntent>>;
|
|
201
|
+
views: Readonly<Record<string, PAConversationSelection | null>>;
|
|
202
|
+
}>;
|