@ziprack/sdk 0.1.0
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/dist/activity/index.d.ts +37 -0
- package/dist/ai/index.d.ts +41 -0
- package/dist/attempt/index.d.ts +27 -0
- package/dist/auth/index.d.ts +14 -0
- package/dist/broadcast/index.d.ts +81 -0
- package/dist/core/bridge.d.ts +39 -0
- package/dist/core/link.d.ts +14 -0
- package/dist/core/mock/MockRack.d.ts +141 -0
- package/dist/core/mock/MockTransport.d.ts +14 -0
- package/dist/core/mock/store.d.ts +23 -0
- package/dist/core/protocol.d.ts +15 -0
- package/dist/core/rack.d.ts +68 -0
- package/dist/core/types.d.ts +155 -0
- package/dist/db/index.d.ts +62 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +517 -0
- package/dist/index.js.map +1 -0
- package/dist/media/index.d.ts +14 -0
- package/dist/storage/index.d.ts +41 -0
- package/dist/store-DSV5q7C7.js +504 -0
- package/dist/store-DSV5q7C7.js.map +1 -0
- package/dist/testing.d.ts +30 -0
- package/dist/testing.js +42 -0
- package/dist/testing.js.map +1 -0
- package/dist/ziprack-sdk.iife.js +2 -0
- package/dist/ziprack-sdk.iife.js.map +1 -0
- package/package.json +30 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Link } from '../core/link';
|
|
2
|
+
import type { AckResult, JsonObject, LaunchActivity } from '../core/types';
|
|
3
|
+
export interface StatementInput {
|
|
4
|
+
verb: string;
|
|
5
|
+
activity: {
|
|
6
|
+
id: string;
|
|
7
|
+
type?: string;
|
|
8
|
+
};
|
|
9
|
+
result?: JsonObject;
|
|
10
|
+
context?: JsonObject;
|
|
11
|
+
occurred_at?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface AnswerOptions {
|
|
14
|
+
type?: string;
|
|
15
|
+
context?: JsonObject;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* activity@1 — append-only statements. Answers are statements, not state.
|
|
19
|
+
*/
|
|
20
|
+
export declare class ActivityApi {
|
|
21
|
+
private readonly link;
|
|
22
|
+
constructor(link: Link);
|
|
23
|
+
/** The manifest's declared activities for this version. */
|
|
24
|
+
activities(): LaunchActivity[];
|
|
25
|
+
activity(id: string): LaunchActivity | null;
|
|
26
|
+
statement(input: StatementInput): Promise<AckResult<{
|
|
27
|
+
id: string;
|
|
28
|
+
}>>;
|
|
29
|
+
/** `answered` statement with the value in result.response — the only field reporting reads. */
|
|
30
|
+
answer(activityId: string, response: unknown, options?: AnswerOptions): Promise<AckResult<{
|
|
31
|
+
id: string;
|
|
32
|
+
}>>;
|
|
33
|
+
/** `progressed` statement with activity.type = 'step'. */
|
|
34
|
+
progress(stepId: string, context?: JsonObject): Promise<AckResult<{
|
|
35
|
+
id: string;
|
|
36
|
+
}>>;
|
|
37
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Link } from '../core/link';
|
|
2
|
+
import type { AckResult, JsonObject } from '../core/types';
|
|
3
|
+
export interface Usage {
|
|
4
|
+
input_tokens: number;
|
|
5
|
+
output_tokens: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ChatReply {
|
|
8
|
+
message_id: string;
|
|
9
|
+
text: string;
|
|
10
|
+
usage: Usage;
|
|
11
|
+
}
|
|
12
|
+
export declare class Chat {
|
|
13
|
+
private readonly link;
|
|
14
|
+
readonly promptId: string;
|
|
15
|
+
constructor(link: Link, promptId: string);
|
|
16
|
+
/**
|
|
17
|
+
* Send a participant message. onDelta receives text as it streams; the
|
|
18
|
+
* resolved result carries the full text.
|
|
19
|
+
*/
|
|
20
|
+
send(message: string, onDelta?: (delta: string, soFar: string) => void): Promise<AckResult<ChatReply>>;
|
|
21
|
+
reset(): Promise<AckResult>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* ai@1 — declared prompt templates. The applet supplies variables, never
|
|
25
|
+
* instructions; model, prompt and budget are Rack-owned.
|
|
26
|
+
*/
|
|
27
|
+
export declare class AiApi {
|
|
28
|
+
private readonly link;
|
|
29
|
+
constructor(link: Link);
|
|
30
|
+
prompts(): Array<{
|
|
31
|
+
id: string;
|
|
32
|
+
mode: 'analysis' | 'chat';
|
|
33
|
+
}>;
|
|
34
|
+
/** Analysis prompt: structured JSON conforming to the declared output_schema. */
|
|
35
|
+
ask<T extends object = JsonObject>(promptId: string, vars?: JsonObject): Promise<AckResult<{
|
|
36
|
+
output: T;
|
|
37
|
+
usage: Usage;
|
|
38
|
+
}>>;
|
|
39
|
+
/** Chat prompt: conversation history is held by the Rack. */
|
|
40
|
+
chat(promptId: string): Chat;
|
|
41
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Link } from '../core/link';
|
|
2
|
+
import type { AckResult, AttemptStatus, JsonObject, LaunchAttempt } from '../core/types';
|
|
3
|
+
/**
|
|
4
|
+
* attempt@1 — lifecycle, resume state, completion. Declaring it also pins
|
|
5
|
+
* every participant to the version they started on.
|
|
6
|
+
*/
|
|
7
|
+
export declare class AttemptApi {
|
|
8
|
+
private readonly link;
|
|
9
|
+
private local;
|
|
10
|
+
constructor(link: Link);
|
|
11
|
+
/** The attempt as launched, with local updates applied. */
|
|
12
|
+
current(): LaunchAttempt | null;
|
|
13
|
+
get status(): AttemptStatus | null;
|
|
14
|
+
get id(): number | null;
|
|
15
|
+
/** Resume state exactly as last saved. */
|
|
16
|
+
state<T extends object = JsonObject>(): T | null;
|
|
17
|
+
segment(): Record<string, string> | null;
|
|
18
|
+
/** Save resume state (max 64 KB). Send after every transition; the shell coalesces bursts. */
|
|
19
|
+
setState(state: JsonObject): Promise<AckResult>;
|
|
20
|
+
/** Set segment dimensions (max 20 keys, string values). */
|
|
21
|
+
setSegment(segment: Record<string, string>): Promise<AckResult>;
|
|
22
|
+
/** Mark the attempt completed. Idempotent. */
|
|
23
|
+
complete(summary?: JsonObject): Promise<AckResult<{
|
|
24
|
+
status: AttemptStatus;
|
|
25
|
+
completed_at: string | null;
|
|
26
|
+
}>>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Link } from '../core/link';
|
|
2
|
+
import type { LaunchUser } from '../core/types';
|
|
3
|
+
/**
|
|
4
|
+
* auth@1 — who the participant is and the profile attributes the Rack chose to
|
|
5
|
+
* release. Attributes the manifest requested but the Rack withheld are simply
|
|
6
|
+
* absent; degrade gracefully.
|
|
7
|
+
*/
|
|
8
|
+
export declare class AuthApi {
|
|
9
|
+
private readonly link;
|
|
10
|
+
constructor(link: Link);
|
|
11
|
+
user(): LaunchUser | null;
|
|
12
|
+
/** A released profile attribute, or the fallback when withheld. */
|
|
13
|
+
attribute<T = unknown>(key: string, fallback?: T | null): T | null;
|
|
14
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { Link } from '../core/link';
|
|
2
|
+
import type { AckResult, JsonObject, LaunchRoom, RackEvent, RoomMember, RoomRole, RoomStatus } from '../core/types';
|
|
3
|
+
export declare const ROOM_CHANNEL = "$room";
|
|
4
|
+
export type RoomEventName = 'presence' | 'state' | 'role' | 'status';
|
|
5
|
+
export interface RoomEvents {
|
|
6
|
+
presence: {
|
|
7
|
+
members: RoomMember[];
|
|
8
|
+
};
|
|
9
|
+
state: {
|
|
10
|
+
key: string;
|
|
11
|
+
value: unknown;
|
|
12
|
+
version: number;
|
|
13
|
+
};
|
|
14
|
+
role: {
|
|
15
|
+
role: RoomRole;
|
|
16
|
+
participant_id: number;
|
|
17
|
+
};
|
|
18
|
+
status: {
|
|
19
|
+
status: RoomStatus;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export declare class Channel {
|
|
23
|
+
private readonly link;
|
|
24
|
+
readonly name: string;
|
|
25
|
+
private readonly listeners;
|
|
26
|
+
private unsubscribe;
|
|
27
|
+
constructor(link: Link, name: string);
|
|
28
|
+
/** @internal */
|
|
29
|
+
attach(): void;
|
|
30
|
+
/** Listen for an event on this channel ('*' for all). Returns an unsubscribe function. */
|
|
31
|
+
listen<T = unknown>(event: string, callback: (payload: T, from: RackEvent['from']) => void): () => void;
|
|
32
|
+
/** Publish to everyone in the room. Facilitator-only events are enforced by the Rack. */
|
|
33
|
+
publish(event: string, payload?: unknown): Promise<AckResult>;
|
|
34
|
+
leave(): Promise<AckResult>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* broadcast@1 — rooms, presence, facilitator control and shared state. The
|
|
38
|
+
* Rack holds the WebSocket; the applet only ever sees postMessage.
|
|
39
|
+
*/
|
|
40
|
+
export declare class BroadcastApi {
|
|
41
|
+
private readonly link;
|
|
42
|
+
private readonly channels;
|
|
43
|
+
private readonly roomListeners;
|
|
44
|
+
private localRole;
|
|
45
|
+
private localMembers;
|
|
46
|
+
private localState;
|
|
47
|
+
private detach;
|
|
48
|
+
constructor(link: Link);
|
|
49
|
+
get room(): LaunchRoom | null;
|
|
50
|
+
get role(): RoomRole | null;
|
|
51
|
+
get isFacilitator(): boolean;
|
|
52
|
+
members(): RoomMember[];
|
|
53
|
+
/** Join a named channel within the room (default "main"). */
|
|
54
|
+
join(channel?: string): Promise<Channel>;
|
|
55
|
+
/** Who is in the room, by role. */
|
|
56
|
+
presence(): Promise<AckResult<{
|
|
57
|
+
members: RoomMember[];
|
|
58
|
+
}>>;
|
|
59
|
+
readonly state: {
|
|
60
|
+
/** Server-arbitrated shared state. */
|
|
61
|
+
get: (keys?: string[]) => Promise<AckResult<{
|
|
62
|
+
state: JsonObject;
|
|
63
|
+
}>>;
|
|
64
|
+
/** Last write wins at the key; the Rack stamps the version. */
|
|
65
|
+
set: (key: string, value: unknown) => Promise<AckResult<{
|
|
66
|
+
version: number;
|
|
67
|
+
}>>;
|
|
68
|
+
/** Locally known state (launch snapshot plus pushed updates). */
|
|
69
|
+
snapshot: () => JsonObject;
|
|
70
|
+
};
|
|
71
|
+
/** Claim the facilitator role (opt_in rooms). */
|
|
72
|
+
claim(): Promise<AckResult<{
|
|
73
|
+
role: RoomRole;
|
|
74
|
+
}>>;
|
|
75
|
+
/** Hand the facilitator role to another member. */
|
|
76
|
+
transfer(participantId: number): Promise<AckResult>;
|
|
77
|
+
/** Room-level events: presence, state, role, status. */
|
|
78
|
+
on<K extends RoomEventName>(event: K, callback: (payload: RoomEvents[K]) => void): () => void;
|
|
79
|
+
private launch;
|
|
80
|
+
private ensureRoomListener;
|
|
81
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AckResult, JsonObject, LaunchData, RackEvent, SendOptions, Transport } from './types';
|
|
2
|
+
export interface BridgeOptions {
|
|
3
|
+
ackTimeoutMs: number;
|
|
4
|
+
/** Window-like object to post to. Defaults to window.parent. */
|
|
5
|
+
target?: Pick<Window, 'postMessage'>;
|
|
6
|
+
/** Whether a MessageEvent came from the host. Defaults to event.source === window.parent. */
|
|
7
|
+
isHost?: (source: MessageEventSource | null) => boolean;
|
|
8
|
+
/** Where to listen for messages. Defaults to window. */
|
|
9
|
+
listenOn?: Pick<Window, 'addEventListener' | 'removeEventListener'>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* postMessage transport used inside the Rack's iframe.
|
|
13
|
+
*
|
|
14
|
+
* Only messages whose source is the parent window are honoured; the applet
|
|
15
|
+
* never inspects event.origin because its own origin is opaque by design.
|
|
16
|
+
*/
|
|
17
|
+
export declare class HostBridge implements Transport {
|
|
18
|
+
private readonly options;
|
|
19
|
+
readonly kind: "host";
|
|
20
|
+
private readonly pending;
|
|
21
|
+
private readonly eventListeners;
|
|
22
|
+
private launchResolvers;
|
|
23
|
+
private launchData;
|
|
24
|
+
private readonly target;
|
|
25
|
+
private readonly isHost;
|
|
26
|
+
private readonly listenOn;
|
|
27
|
+
private readonly listener;
|
|
28
|
+
constructor(options: BridgeOptions);
|
|
29
|
+
announceReady(): void;
|
|
30
|
+
waitForLaunch(timeoutMs: number): Promise<LaunchData | null>;
|
|
31
|
+
send<T = JsonObject>(type: string, payload: unknown, options?: SendOptions): Promise<AckResult<T>>;
|
|
32
|
+
fire(type: string, payload?: unknown): void;
|
|
33
|
+
onEvent(listener: (event: RackEvent) => void): () => void;
|
|
34
|
+
dispose(): void;
|
|
35
|
+
private expire;
|
|
36
|
+
private post;
|
|
37
|
+
private onMessage;
|
|
38
|
+
private onAck;
|
|
39
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AckResult, JsonObject, LaunchData, RackEvent, SendOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* What a capability module needs from the client: send/fire, the launch data,
|
|
4
|
+
* event subscription and the declared-capability check.
|
|
5
|
+
*/
|
|
6
|
+
export interface Link {
|
|
7
|
+
send<T = JsonObject>(type: string, payload: unknown, options?: SendOptions): Promise<AckResult<T>>;
|
|
8
|
+
fire(type: string, payload?: unknown): void;
|
|
9
|
+
launch(): LaunchData | null;
|
|
10
|
+
declares(capability: string): boolean;
|
|
11
|
+
onEvent(listener: (event: RackEvent) => void): () => void;
|
|
12
|
+
mode(): 'host' | 'mock' | 'pending';
|
|
13
|
+
}
|
|
14
|
+
export declare function notDeclared<T = JsonObject>(capability: string): AckResult<T>;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { AckResult, JsonObject, LaunchData, RackEvent, RoomMember, RoomRole } from '../types';
|
|
2
|
+
import type { RecordRow } from '../../db';
|
|
3
|
+
import type { StoredFile } from '../../storage';
|
|
4
|
+
import type { Store } from './store';
|
|
5
|
+
export interface MockManifest {
|
|
6
|
+
schema?: string;
|
|
7
|
+
slug: string;
|
|
8
|
+
name: string;
|
|
9
|
+
version: string;
|
|
10
|
+
requires?: {
|
|
11
|
+
capabilities?: string[];
|
|
12
|
+
profile?: string[];
|
|
13
|
+
};
|
|
14
|
+
media?: Array<{
|
|
15
|
+
id: string;
|
|
16
|
+
provider: string;
|
|
17
|
+
key: string;
|
|
18
|
+
}>;
|
|
19
|
+
activities?: Array<{
|
|
20
|
+
id: string;
|
|
21
|
+
type: string;
|
|
22
|
+
label: string;
|
|
23
|
+
scale?: unknown;
|
|
24
|
+
segment?: string | null;
|
|
25
|
+
sequence?: number;
|
|
26
|
+
}>;
|
|
27
|
+
collections?: Array<{
|
|
28
|
+
name: string;
|
|
29
|
+
scope: string;
|
|
30
|
+
schema?: JsonObject;
|
|
31
|
+
}>;
|
|
32
|
+
uploads?: Array<{
|
|
33
|
+
name: string;
|
|
34
|
+
scope: string;
|
|
35
|
+
mime?: string[];
|
|
36
|
+
max_bytes?: number;
|
|
37
|
+
}>;
|
|
38
|
+
prompts?: Array<{
|
|
39
|
+
id: string;
|
|
40
|
+
mode: 'analysis' | 'chat';
|
|
41
|
+
output_schema?: JsonObject;
|
|
42
|
+
}>;
|
|
43
|
+
broadcast?: {
|
|
44
|
+
facilitator_events?: string[];
|
|
45
|
+
channels?: string[];
|
|
46
|
+
mock_mode?: 'first_in' | 'opt_in';
|
|
47
|
+
};
|
|
48
|
+
[key: string]: unknown;
|
|
49
|
+
}
|
|
50
|
+
export type AiMockHandler = (vars: JsonObject, mode: 'analysis' | 'chat', message?: string) => unknown | Promise<unknown>;
|
|
51
|
+
export interface MockRackOptions {
|
|
52
|
+
/** Whether undeclared capabilities are refused, as a real Rack would. Default true when a manifest is present. */
|
|
53
|
+
strict?: boolean;
|
|
54
|
+
log?: (type: string, payload: unknown) => void;
|
|
55
|
+
participantId?: number;
|
|
56
|
+
participantName?: string;
|
|
57
|
+
/** Force the mock room role instead of deriving it from the assignment mode. */
|
|
58
|
+
role?: RoomRole;
|
|
59
|
+
}
|
|
60
|
+
export type MockOutcome = AckResult | {
|
|
61
|
+
stream: AsyncIterable<JsonObject>;
|
|
62
|
+
final: () => JsonObject;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* An in-memory Rack that services every capability so an applet can be built
|
|
66
|
+
* and QA'd standalone. Shared by the browser mock transport (localStorage) and
|
|
67
|
+
* the testing FakeHost (memory).
|
|
68
|
+
*/
|
|
69
|
+
export declare class MockRack {
|
|
70
|
+
readonly manifest: MockManifest | null;
|
|
71
|
+
private readonly store;
|
|
72
|
+
private readonly options;
|
|
73
|
+
readonly participantId: number;
|
|
74
|
+
readonly participantName: string;
|
|
75
|
+
readonly statements: Array<JsonObject & {
|
|
76
|
+
id: string;
|
|
77
|
+
}>;
|
|
78
|
+
readonly events: RackEvent[];
|
|
79
|
+
private readonly aiHandlers;
|
|
80
|
+
private readonly chatHistory;
|
|
81
|
+
private readonly blobs;
|
|
82
|
+
private readonly eventListeners;
|
|
83
|
+
private readonly roomMembers;
|
|
84
|
+
private roomState;
|
|
85
|
+
private role;
|
|
86
|
+
private readonly joinedAt;
|
|
87
|
+
private channel;
|
|
88
|
+
private heartbeat;
|
|
89
|
+
constructor(manifest: MockManifest | null, store: Store, options?: MockRackOptions);
|
|
90
|
+
get slug(): string;
|
|
91
|
+
private key;
|
|
92
|
+
declares(capability: string): boolean;
|
|
93
|
+
onEvent(listener: (event: RackEvent) => void): () => void;
|
|
94
|
+
pushEvent(event: RackEvent): void;
|
|
95
|
+
launchData(nameHint?: string): LaunchData;
|
|
96
|
+
mockAi(promptId: string, handler: AiMockHandler): void;
|
|
97
|
+
dispose(): void;
|
|
98
|
+
handle(type: string, payload: JsonObject): Promise<MockOutcome>;
|
|
99
|
+
attempt(): NonNullable<LaunchData['attempt']>;
|
|
100
|
+
private saveAttempt;
|
|
101
|
+
private attemptState;
|
|
102
|
+
private attemptSegment;
|
|
103
|
+
private attemptComplete;
|
|
104
|
+
/** Clear a completed mock attempt so the experience can be run again. */
|
|
105
|
+
resetAttempt(): void;
|
|
106
|
+
private statement;
|
|
107
|
+
private collectionKey;
|
|
108
|
+
records(collection: string): RecordRow[];
|
|
109
|
+
private saveRecords;
|
|
110
|
+
private collectionDeclared;
|
|
111
|
+
private dbCreate;
|
|
112
|
+
private dbGet;
|
|
113
|
+
private dbUpdate;
|
|
114
|
+
private dbDelete;
|
|
115
|
+
private filter;
|
|
116
|
+
private dbList;
|
|
117
|
+
private dbCount;
|
|
118
|
+
files(): StoredFile[];
|
|
119
|
+
private storagePut;
|
|
120
|
+
private storageUrl;
|
|
121
|
+
private storageList;
|
|
122
|
+
private storageDelete;
|
|
123
|
+
private prompt;
|
|
124
|
+
private aiAsk;
|
|
125
|
+
private aiChat;
|
|
126
|
+
private member;
|
|
127
|
+
members(): RoomMember[];
|
|
128
|
+
private stateSnapshot;
|
|
129
|
+
private send;
|
|
130
|
+
private joinRoom;
|
|
131
|
+
/** An earlier facilitator wins; a later optimistic one steps down. */
|
|
132
|
+
private reconcileFacilitator;
|
|
133
|
+
private onRoomMessage;
|
|
134
|
+
private setRole;
|
|
135
|
+
private publish;
|
|
136
|
+
private stateSet;
|
|
137
|
+
private claim;
|
|
138
|
+
private transfer;
|
|
139
|
+
}
|
|
140
|
+
/** A plausible object for an analysis prompt's output_schema, so UIs render in mock mode. */
|
|
141
|
+
export declare function stubFromSchema(schema: JsonObject | undefined, vars: JsonObject): unknown;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AckResult, JsonObject, RackEvent, SendOptions, Transport } from '../types';
|
|
2
|
+
import type { MockRack } from './MockRack';
|
|
3
|
+
/**
|
|
4
|
+
* Transport that fulfils every message locally through a MockRack.
|
|
5
|
+
*/
|
|
6
|
+
export declare class MockTransport implements Transport {
|
|
7
|
+
readonly rack: MockRack;
|
|
8
|
+
readonly kind: "mock";
|
|
9
|
+
constructor(rack: MockRack);
|
|
10
|
+
send<T = JsonObject>(type: string, payload: unknown, options?: SendOptions): Promise<AckResult<T>>;
|
|
11
|
+
fire(type: string, payload?: unknown): void;
|
|
12
|
+
onEvent(listener: (event: RackEvent) => void): () => void;
|
|
13
|
+
dispose(): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key/value persistence for the mock Rack. localStorage in the browser so a
|
|
3
|
+
* standalone session survives a refresh; memory in tests.
|
|
4
|
+
*/
|
|
5
|
+
export interface Store {
|
|
6
|
+
get<T>(key: string): T | null;
|
|
7
|
+
set(key: string, value: unknown): void;
|
|
8
|
+
remove(key: string): void;
|
|
9
|
+
keys(prefix: string): string[];
|
|
10
|
+
}
|
|
11
|
+
export declare class MemoryStore implements Store {
|
|
12
|
+
private readonly data;
|
|
13
|
+
get<T>(key: string): T | null;
|
|
14
|
+
set(key: string, value: unknown): void;
|
|
15
|
+
remove(key: string): void;
|
|
16
|
+
keys(prefix: string): string[];
|
|
17
|
+
}
|
|
18
|
+
export declare class LocalStore implements Store {
|
|
19
|
+
get<T>(key: string): T | null;
|
|
20
|
+
set(key: string, value: unknown): void;
|
|
21
|
+
remove(key: string): void;
|
|
22
|
+
keys(prefix: string): string[];
|
|
23
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const PROTOCOL_NAMESPACE: "ziprack";
|
|
2
|
+
export declare const PROTOCOL_VERSION: 1;
|
|
3
|
+
export declare const FORMAT: "ziprack/1";
|
|
4
|
+
export interface Envelope<T = unknown> {
|
|
5
|
+
ns: typeof PROTOCOL_NAMESPACE;
|
|
6
|
+
v: typeof PROTOCOL_VERSION;
|
|
7
|
+
type: string;
|
|
8
|
+
requestId?: string;
|
|
9
|
+
payload?: T;
|
|
10
|
+
}
|
|
11
|
+
export declare function newRequestId(): string;
|
|
12
|
+
export declare function createEnvelope<T>(type: string, payload?: T, requestId?: string): Envelope<T>;
|
|
13
|
+
export declare function isEnvelope(data: unknown): data is Envelope;
|
|
14
|
+
/** Capability id from a message type ("db:create" -> "db"). */
|
|
15
|
+
export declare function capabilityOf(type: string): string;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ActivityApi } from '../activity';
|
|
2
|
+
import { AiApi } from '../ai';
|
|
3
|
+
import { AttemptApi } from '../attempt';
|
|
4
|
+
import { AuthApi } from '../auth';
|
|
5
|
+
import { BroadcastApi } from '../broadcast';
|
|
6
|
+
import { DbApi } from '../db';
|
|
7
|
+
import { MediaApi } from '../media';
|
|
8
|
+
import { StorageApi } from '../storage';
|
|
9
|
+
import { MockRack, type AiMockHandler } from './mock/MockRack';
|
|
10
|
+
import type { AckResult, InitOptions, JsonObject, LaunchData, LaunchListener, RackEvent, SendOptions } from './types';
|
|
11
|
+
/**
|
|
12
|
+
* The SDK entry point. One instance per applet; `Rack` is the default singleton.
|
|
13
|
+
*
|
|
14
|
+
* Every capability is a message the Rack services. The applet asks; the Rack
|
|
15
|
+
* decides, enforces and persists. Nothing here ever throws on a Rack error:
|
|
16
|
+
* calls resolve to { ok: false, error }.
|
|
17
|
+
*/
|
|
18
|
+
export declare class RackClient {
|
|
19
|
+
readonly auth: AuthApi;
|
|
20
|
+
readonly attempt: AttemptApi;
|
|
21
|
+
readonly activity: ActivityApi;
|
|
22
|
+
readonly db: DbApi;
|
|
23
|
+
readonly storage: StorageApi;
|
|
24
|
+
readonly ai: AiApi;
|
|
25
|
+
readonly broadcast: BroadcastApi;
|
|
26
|
+
readonly media: MediaApi;
|
|
27
|
+
/** Dev-only hooks that only take effect in mock mode. */
|
|
28
|
+
readonly mock: {
|
|
29
|
+
/** Answer an ai prompt yourself instead of the schema stub. */
|
|
30
|
+
ai: (promptId: string, handler: AiMockHandler) => void;
|
|
31
|
+
/** Clear a completed mock attempt so the experience can be replayed. */
|
|
32
|
+
resetAttempt: () => void;
|
|
33
|
+
/** The MockRack when running standalone, else null. */
|
|
34
|
+
rack: () => MockRack | null;
|
|
35
|
+
};
|
|
36
|
+
private transport;
|
|
37
|
+
private initPromise;
|
|
38
|
+
private launchData;
|
|
39
|
+
private readonly queue;
|
|
40
|
+
private readonly launchListeners;
|
|
41
|
+
private readonly eventListeners;
|
|
42
|
+
private pendingAiMocks;
|
|
43
|
+
constructor();
|
|
44
|
+
/**
|
|
45
|
+
* Handshake with the Rack. Resolves with launch data once the Rack answers,
|
|
46
|
+
* or with mock launch data when running standalone. Safe to call repeatedly.
|
|
47
|
+
*/
|
|
48
|
+
init(options?: InitOptions): Promise<LaunchData>;
|
|
49
|
+
get launched(): boolean;
|
|
50
|
+
get mode(): 'host' | 'mock' | 'pending';
|
|
51
|
+
getLaunchData(): LaunchData | null;
|
|
52
|
+
/** Whether the manifest declared a capability (any version). */
|
|
53
|
+
declares(capability: string): boolean;
|
|
54
|
+
on(event: 'launch', listener: LaunchListener): () => void;
|
|
55
|
+
on(event: 'event', listener: (event: RackEvent) => void): () => void;
|
|
56
|
+
/** Ask the Rack to leave the applet. Needs no capability. */
|
|
57
|
+
eject(): void;
|
|
58
|
+
/** Low-level: send any message and await its ack. Capability calls go through the typed APIs. */
|
|
59
|
+
send<T = JsonObject>(type: string, payload: unknown, options?: SendOptions): Promise<AckResult<T>>;
|
|
60
|
+
fire(type: string, payload?: unknown): void;
|
|
61
|
+
/** Tear down (tests). */
|
|
62
|
+
dispose(): void;
|
|
63
|
+
private performInit;
|
|
64
|
+
private activateMock;
|
|
65
|
+
private activate;
|
|
66
|
+
private flushQueue;
|
|
67
|
+
private mockRack;
|
|
68
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
export type JsonObject = Record<string, unknown>;
|
|
2
|
+
export type AckErrorCode = 'timeout' | 'disposed' | 'persist_failed' | 'undeclared_capability' | 'unknown_type' | 'validation' | 'forbidden' | 'completed' | 'quota_exceeded' | 'budget_exceeded' | 'not_found' | 'conflict';
|
|
3
|
+
/** Every SDK call resolves to one of these and never throws. */
|
|
4
|
+
export interface AckResult<T = JsonObject> {
|
|
5
|
+
ok: boolean;
|
|
6
|
+
data?: T;
|
|
7
|
+
error?: AckErrorCode | string;
|
|
8
|
+
message?: string;
|
|
9
|
+
details?: JsonObject;
|
|
10
|
+
}
|
|
11
|
+
export interface AckPayload extends AckResult {
|
|
12
|
+
requestId: string;
|
|
13
|
+
partial?: boolean;
|
|
14
|
+
done?: boolean;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
}
|
|
17
|
+
export interface LaunchActor {
|
|
18
|
+
id: number;
|
|
19
|
+
name: string;
|
|
20
|
+
}
|
|
21
|
+
export interface LaunchApplet {
|
|
22
|
+
slug: string;
|
|
23
|
+
name: string;
|
|
24
|
+
version: string;
|
|
25
|
+
}
|
|
26
|
+
export interface MediaEmbed {
|
|
27
|
+
provider: 'vimeo' | 'youtube' | string;
|
|
28
|
+
embedUrl: string;
|
|
29
|
+
meta: {
|
|
30
|
+
title?: string;
|
|
31
|
+
thumbnail_url?: string;
|
|
32
|
+
duration?: number;
|
|
33
|
+
width?: number;
|
|
34
|
+
height?: number;
|
|
35
|
+
} | null;
|
|
36
|
+
}
|
|
37
|
+
export type AttemptStatus = 'in_progress' | 'completed';
|
|
38
|
+
export interface LaunchAttempt {
|
|
39
|
+
id: number;
|
|
40
|
+
status: AttemptStatus;
|
|
41
|
+
state: JsonObject | null;
|
|
42
|
+
segment: Record<string, string> | null;
|
|
43
|
+
}
|
|
44
|
+
export interface LaunchActivity {
|
|
45
|
+
id: string;
|
|
46
|
+
type: string;
|
|
47
|
+
label: string;
|
|
48
|
+
scale?: unknown;
|
|
49
|
+
segment?: string | null;
|
|
50
|
+
sequence?: number;
|
|
51
|
+
}
|
|
52
|
+
export interface LaunchUser {
|
|
53
|
+
id: number;
|
|
54
|
+
display_name: string;
|
|
55
|
+
[attribute: string]: unknown;
|
|
56
|
+
}
|
|
57
|
+
export type RoomStatus = 'open' | 'locked' | 'closed';
|
|
58
|
+
export type RoomRole = 'participant' | 'facilitator';
|
|
59
|
+
export interface RoomMember {
|
|
60
|
+
id: number;
|
|
61
|
+
name: string;
|
|
62
|
+
role: RoomRole;
|
|
63
|
+
present: boolean;
|
|
64
|
+
}
|
|
65
|
+
export interface LaunchRoom {
|
|
66
|
+
id: number;
|
|
67
|
+
code: string;
|
|
68
|
+
name: string;
|
|
69
|
+
status: RoomStatus;
|
|
70
|
+
mode: 'opt_in' | 'first_in' | 'roster';
|
|
71
|
+
}
|
|
72
|
+
export interface LaunchBroadcast {
|
|
73
|
+
room: LaunchRoom;
|
|
74
|
+
role: RoomRole;
|
|
75
|
+
members: RoomMember[];
|
|
76
|
+
state: JsonObject;
|
|
77
|
+
channels: string[];
|
|
78
|
+
}
|
|
79
|
+
export interface LaunchData {
|
|
80
|
+
schema: 'ziprack/1';
|
|
81
|
+
actor: LaunchActor;
|
|
82
|
+
applet: LaunchApplet;
|
|
83
|
+
capabilities: string[];
|
|
84
|
+
media: Record<string, MediaEmbed>;
|
|
85
|
+
auth?: {
|
|
86
|
+
user: LaunchUser;
|
|
87
|
+
};
|
|
88
|
+
attempt?: LaunchAttempt;
|
|
89
|
+
activity?: {
|
|
90
|
+
activities: LaunchActivity[];
|
|
91
|
+
};
|
|
92
|
+
db?: {
|
|
93
|
+
collections: Array<{
|
|
94
|
+
name: string;
|
|
95
|
+
scope: string;
|
|
96
|
+
}>;
|
|
97
|
+
};
|
|
98
|
+
storage?: {
|
|
99
|
+
uploads: Array<{
|
|
100
|
+
name: string;
|
|
101
|
+
scope: string;
|
|
102
|
+
mime: string[];
|
|
103
|
+
max_bytes: number;
|
|
104
|
+
}>;
|
|
105
|
+
};
|
|
106
|
+
ai?: {
|
|
107
|
+
prompts: Array<{
|
|
108
|
+
id: string;
|
|
109
|
+
mode: 'analysis' | 'chat';
|
|
110
|
+
}>;
|
|
111
|
+
};
|
|
112
|
+
broadcast?: LaunchBroadcast;
|
|
113
|
+
[capability: string]: unknown;
|
|
114
|
+
}
|
|
115
|
+
export interface RackEvent<T = unknown> {
|
|
116
|
+
event: string;
|
|
117
|
+
payload: T;
|
|
118
|
+
channel?: string;
|
|
119
|
+
from?: {
|
|
120
|
+
participant_id: number;
|
|
121
|
+
role?: RoomRole;
|
|
122
|
+
} | null;
|
|
123
|
+
}
|
|
124
|
+
export interface SendOptions {
|
|
125
|
+
/** Receives each partial chunk of a streamed ack. */
|
|
126
|
+
onPartial?: (chunk: JsonObject) => void;
|
|
127
|
+
/** Override the ack timeout for this call (streamed calls reset it per chunk). */
|
|
128
|
+
timeoutMs?: number;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Transport abstraction shared by the real host bridge, the standalone mock
|
|
132
|
+
* and the testing FakeHost.
|
|
133
|
+
*/
|
|
134
|
+
export interface Transport {
|
|
135
|
+
readonly kind: 'host' | 'mock';
|
|
136
|
+
send<T = JsonObject>(type: string, payload: unknown, options?: SendOptions): Promise<AckResult<T>>;
|
|
137
|
+
fire(type: string, payload?: unknown): void;
|
|
138
|
+
onEvent(listener: (event: RackEvent) => void): () => void;
|
|
139
|
+
dispose(): void;
|
|
140
|
+
}
|
|
141
|
+
export interface InitOptions {
|
|
142
|
+
/** Labels the mock session and locates ./manifest.json when running standalone. */
|
|
143
|
+
slug?: string;
|
|
144
|
+
/** Milliseconds to wait for rack:launch before falling back to mock mode. */
|
|
145
|
+
launchTimeoutMs?: number;
|
|
146
|
+
/** Milliseconds to wait for each rack:ack. */
|
|
147
|
+
ackTimeoutMs?: number;
|
|
148
|
+
/** Where the mock loads the manifest from. Default "./manifest.json". */
|
|
149
|
+
manifestUrl?: string;
|
|
150
|
+
/** Inject a transport (tests). Skips the host handshake and mock detection. */
|
|
151
|
+
transport?: Transport;
|
|
152
|
+
/** Launch data to use with an injected transport. */
|
|
153
|
+
launch?: LaunchData;
|
|
154
|
+
}
|
|
155
|
+
export type LaunchListener = (data: LaunchData) => void;
|