@lunora/svelte 1.0.0-alpha.4 → 1.0.0-alpha.40
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.md +6 -0
- package/README.md +2 -0
- package/__assets__/package-og.svg +1 -1
- package/dist/index.d.mts +872 -168
- package/dist/index.d.ts +872 -168
- package/dist/index.mjs +17 -9
- package/dist/packem_shared/agent-KLsxO_Uw.mjs +48 -0
- package/dist/packem_shared/agentChat-BlwlNfDg.mjs +138 -0
- package/dist/packem_shared/agentState-DBXc_3RM.mjs +15 -0
- package/dist/packem_shared/agentToolEvents-qYM1CdTV.mjs +60 -0
- package/dist/packem_shared/{auth-DLPf_bK9.mjs → auth-BeYqYP9S.mjs} +1 -1
- package/dist/packem_shared/{connectionStatus-CRsOMeYl.mjs → connectionStatus-BrICpw9d.mjs} +1 -1
- package/dist/packem_shared/flag-CqMU07WH.mjs +56 -0
- package/dist/packem_shared/{getLunoraClient--bwSz7F6.mjs → getLunoraClient-Prczj1gU.mjs} +2 -1
- package/dist/packem_shared/{hydratePreloaded-D5rUJdXy.mjs → hydratePreloaded-Djsf_C8Q.mjs} +1 -1
- package/dist/packem_shared/{infiniteQuery-jPMQw8Vz.mjs → infiniteQuery-Bemu7Um1.mjs} +51 -20
- package/dist/packem_shared/{mutation-CnDkAaLH.mjs → mutation-BmkCZnTd.mjs} +1 -1
- package/dist/packem_shared/mutator-B5LchgMS.mjs +19 -0
- package/dist/packem_shared/{presence-BQWixJ2T.mjs → presence-BvChXqiB.mjs} +23 -6
- package/dist/packem_shared/{query-D8Pct9Qe.mjs → query-B-Gu6KQw.mjs} +8 -2
- package/dist/packem_shared/stream-BebZbIaD.mjs +68 -0
- package/dist/packem_shared/{subscription-twuBT_Wb.mjs → subscription-COqqiMPX.mjs} +1 -4
- package/dist/packem_shared/voiceAgent-Cxib7eCK.mjs +405 -0
- package/package.json +6 -5
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
1
|
+
export { agent } from './packem_shared/agent-KLsxO_Uw.mjs';
|
|
2
|
+
export { agentChat } from './packem_shared/agentChat-BlwlNfDg.mjs';
|
|
3
|
+
export { agentState } from './packem_shared/agentState-DBXc_3RM.mjs';
|
|
4
|
+
export { agentToolEvents } from './packem_shared/agentToolEvents-qYM1CdTV.mjs';
|
|
5
|
+
export { auth } from './packem_shared/auth-BeYqYP9S.mjs';
|
|
6
|
+
export { connectionStatus } from './packem_shared/connectionStatus-BrICpw9d.mjs';
|
|
7
|
+
export { getLunoraClient, setLunoraClient } from './packem_shared/getLunoraClient-Prczj1gU.mjs';
|
|
8
|
+
export { flag, flags } from './packem_shared/flag-CqMU07WH.mjs';
|
|
9
|
+
export { hydratePreloaded } from './packem_shared/hydratePreloaded-Djsf_C8Q.mjs';
|
|
10
|
+
export { mutation } from './packem_shared/mutation-BmkCZnTd.mjs';
|
|
11
|
+
export { mutator } from './packem_shared/mutator-B5LchgMS.mjs';
|
|
12
|
+
export { infiniteQuery, paginatedQuery } from './packem_shared/infiniteQuery-Bemu7Um1.mjs';
|
|
13
|
+
export { presence } from './packem_shared/presence-BvChXqiB.mjs';
|
|
14
|
+
export { query } from './packem_shared/query-B-Gu6KQw.mjs';
|
|
9
15
|
export { rateLimit } from './packem_shared/rateLimit-Cdw1kp8t.mjs';
|
|
10
|
-
export {
|
|
16
|
+
export { stream } from './packem_shared/stream-BebZbIaD.mjs';
|
|
17
|
+
export { subscription } from './packem_shared/subscription-COqqiMPX.mjs';
|
|
18
|
+
export { voiceAgent } from './packem_shared/voiceAgent-Cxib7eCK.mjs';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { writable } from 'svelte/store';
|
|
2
|
+
import { getLunoraClient } from './getLunoraClient-Prczj1gU.mjs';
|
|
3
|
+
import { mutation } from './mutation-BmkCZnTd.mjs';
|
|
4
|
+
|
|
5
|
+
const NO_MUTATION_REF = { __lunoraRef: "" };
|
|
6
|
+
const isClient = (value) => typeof value === "object" && value !== null && typeof value.subscribe === "function";
|
|
7
|
+
const createAgentHandle = (client, options) => {
|
|
8
|
+
const { api, cancel: cancelReference, run: runReference, runArgs, threadKey } = options;
|
|
9
|
+
const runMutation = mutation(client, runReference);
|
|
10
|
+
const cancelMutation = mutation(client, cancelReference ?? NO_MUTATION_REF);
|
|
11
|
+
let latestThread;
|
|
12
|
+
const threadStore = writable();
|
|
13
|
+
const statusStore = writable();
|
|
14
|
+
const unsubscribe = client.subscribe(api.agents.agentThread, { key: threadKey }, (value) => {
|
|
15
|
+
latestThread = value;
|
|
16
|
+
threadStore.set(latestThread);
|
|
17
|
+
statusStore.set(latestThread?.status);
|
|
18
|
+
});
|
|
19
|
+
const run = async (input, arguments_) => {
|
|
20
|
+
await runMutation.mutate({ input, threadKey, ...runArgs, ...arguments_ });
|
|
21
|
+
};
|
|
22
|
+
const cancel = async () => {
|
|
23
|
+
const instanceId = latestThread?.instanceId;
|
|
24
|
+
if (cancelReference === void 0 || instanceId === void 0) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
await cancelMutation.mutate({ instanceId, threadKey });
|
|
28
|
+
};
|
|
29
|
+
const teardown = () => {
|
|
30
|
+
unsubscribe();
|
|
31
|
+
};
|
|
32
|
+
return {
|
|
33
|
+
cancel,
|
|
34
|
+
pending: runMutation.pending,
|
|
35
|
+
run,
|
|
36
|
+
status: { subscribe: statusStore.subscribe },
|
|
37
|
+
teardown,
|
|
38
|
+
thread: { subscribe: threadStore.subscribe }
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
function agent(clientOrOptions, maybeOptions) {
|
|
42
|
+
const hasExplicitClient = isClient(clientOrOptions);
|
|
43
|
+
const client = hasExplicitClient ? clientOrOptions : getLunoraClient();
|
|
44
|
+
const options = hasExplicitClient ? maybeOptions : clientOrOptions;
|
|
45
|
+
return createAgentHandle(client, options);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { NO_MUTATION_REF, agent, isClient };
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { writable } from 'svelte/store';
|
|
2
|
+
import { isClient, NO_MUTATION_REF } from './agent-KLsxO_Uw.mjs';
|
|
3
|
+
import { getLunoraClient } from './getLunoraClient-Prczj1gU.mjs';
|
|
4
|
+
import { mutation } from './mutation-BmkCZnTd.mjs';
|
|
5
|
+
import { stream } from './stream-BebZbIaD.mjs';
|
|
6
|
+
|
|
7
|
+
const NO_STREAM_REF = { __lunoraRef: "" };
|
|
8
|
+
const reconcileOptimistic = (optimistic, durable) => {
|
|
9
|
+
const durableUserRows = durable.filter((message) => message.role === "user");
|
|
10
|
+
const consumed = /* @__PURE__ */ new Set();
|
|
11
|
+
return optimistic.filter((pending) => {
|
|
12
|
+
for (let index = pending.durableUserCountAtSend; index < durableUserRows.length; index += 1) {
|
|
13
|
+
const row = durableUserRows[index];
|
|
14
|
+
if (row !== void 0 && !consumed.has(index) && row.content === pending.content) {
|
|
15
|
+
consumed.add(index);
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return true;
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
const createAgentChatHandle = (client, options) => {
|
|
23
|
+
const { api, cancel: cancelReference, limit, send: sendReference, sendArgs, stream: streamReference, threadKey } = options;
|
|
24
|
+
const sendMutation = mutation(client, sendReference);
|
|
25
|
+
const cancelMutation = mutation(client, cancelReference ?? NO_MUTATION_REF);
|
|
26
|
+
const approvalMutation = mutation(client, api.agents.agentResolveApproval);
|
|
27
|
+
let latestThread;
|
|
28
|
+
let durable = [];
|
|
29
|
+
let optimistic = [];
|
|
30
|
+
let liveEvents = [];
|
|
31
|
+
let nextId = 0;
|
|
32
|
+
const messagesStore = writable([]);
|
|
33
|
+
const statusStore = writable();
|
|
34
|
+
const streamingTextStore = writable("");
|
|
35
|
+
const recompute = () => {
|
|
36
|
+
const visible = reconcileOptimistic(optimistic, durable);
|
|
37
|
+
if (visible.length === 0) {
|
|
38
|
+
messagesStore.set(durable);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
let maxDurableSeq = -1;
|
|
42
|
+
for (const message of durable) {
|
|
43
|
+
if (message.seq > maxDurableSeq) {
|
|
44
|
+
maxDurableSeq = message.seq;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
messagesStore.set([
|
|
48
|
+
...durable,
|
|
49
|
+
...visible.map((pending, index) => {
|
|
50
|
+
return {
|
|
51
|
+
content: pending.content,
|
|
52
|
+
optimistic: true,
|
|
53
|
+
role: "user",
|
|
54
|
+
seq: maxDurableSeq + 1 + index
|
|
55
|
+
};
|
|
56
|
+
})
|
|
57
|
+
]);
|
|
58
|
+
};
|
|
59
|
+
const recomputeStreamingText = () => {
|
|
60
|
+
const assistantCount = durable.filter((message) => message.role === "assistant").length;
|
|
61
|
+
const text = liveEvents.filter((event) => event.kind !== "progress" && event.threadKey === threadKey && event.turn >= assistantCount).map((delta) => delta.text).join("");
|
|
62
|
+
streamingTextStore.set(text);
|
|
63
|
+
};
|
|
64
|
+
const streamArguments = streamReference === void 0 ? "skip" : { key: threadKey };
|
|
65
|
+
const streamHandle = stream(client, streamReference ?? NO_STREAM_REF, streamArguments);
|
|
66
|
+
const unsubscribeStream = streamHandle.chunks.subscribe((value) => {
|
|
67
|
+
liveEvents = value;
|
|
68
|
+
recomputeStreamingText();
|
|
69
|
+
});
|
|
70
|
+
const historyArgs = limit === void 0 ? { key: threadKey } : { key: threadKey, limit };
|
|
71
|
+
const unsubscribeHistory = client.subscribe(api.agents.agentMessages, historyArgs, (value) => {
|
|
72
|
+
durable = value;
|
|
73
|
+
recompute();
|
|
74
|
+
recomputeStreamingText();
|
|
75
|
+
});
|
|
76
|
+
const unsubscribeThread = client.subscribe(api.agents.agentThread, { key: threadKey }, (value) => {
|
|
77
|
+
latestThread = value;
|
|
78
|
+
statusStore.set(latestThread?.status);
|
|
79
|
+
});
|
|
80
|
+
const send = async (input, arguments_) => {
|
|
81
|
+
const id = nextId;
|
|
82
|
+
nextId += 1;
|
|
83
|
+
const durableUserCountAtSend = durable.filter((message) => message.role === "user").length;
|
|
84
|
+
optimistic = [...reconcileOptimistic(optimistic, durable), { content: input, durableUserCountAtSend, id }];
|
|
85
|
+
recompute();
|
|
86
|
+
try {
|
|
87
|
+
await sendMutation.mutate({ input, threadKey, ...sendArgs, ...arguments_ });
|
|
88
|
+
} catch (error) {
|
|
89
|
+
optimistic = optimistic.filter((pending) => pending.id !== id);
|
|
90
|
+
recompute();
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const approve = async (toolCallId, note) => {
|
|
95
|
+
const instanceId = latestThread?.instanceId;
|
|
96
|
+
if (instanceId === void 0) {
|
|
97
|
+
throw new Error("agentChat: cannot approve — no in-flight run (thread has no instanceId)");
|
|
98
|
+
}
|
|
99
|
+
await approvalMutation.mutate({ decision: "approve", instanceId, threadKey, toolCallId, ...note === void 0 ? {} : { note } });
|
|
100
|
+
};
|
|
101
|
+
const reject = async (toolCallId, note) => {
|
|
102
|
+
const instanceId = latestThread?.instanceId;
|
|
103
|
+
if (instanceId === void 0) {
|
|
104
|
+
throw new Error("agentChat: cannot reject — no in-flight run (thread has no instanceId)");
|
|
105
|
+
}
|
|
106
|
+
await approvalMutation.mutate({ decision: "reject", instanceId, threadKey, toolCallId, ...note === void 0 ? {} : { note } });
|
|
107
|
+
};
|
|
108
|
+
const cancel = async () => {
|
|
109
|
+
const instanceId = latestThread?.instanceId;
|
|
110
|
+
if (cancelReference === void 0 || instanceId === void 0) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
await cancelMutation.mutate({ instanceId, threadKey });
|
|
114
|
+
};
|
|
115
|
+
const teardown = () => {
|
|
116
|
+
unsubscribeHistory();
|
|
117
|
+
unsubscribeThread();
|
|
118
|
+
unsubscribeStream();
|
|
119
|
+
};
|
|
120
|
+
return {
|
|
121
|
+
approve,
|
|
122
|
+
cancel,
|
|
123
|
+
messages: { subscribe: messagesStore.subscribe },
|
|
124
|
+
reject,
|
|
125
|
+
send,
|
|
126
|
+
status: { subscribe: statusStore.subscribe },
|
|
127
|
+
streamingText: { subscribe: streamingTextStore.subscribe },
|
|
128
|
+
teardown
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
function agentChat(clientOrOptions, maybeOptions) {
|
|
132
|
+
const hasExplicitClient = isClient(clientOrOptions);
|
|
133
|
+
const client = hasExplicitClient ? clientOrOptions : getLunoraClient();
|
|
134
|
+
const options = hasExplicitClient ? maybeOptions : clientOrOptions;
|
|
135
|
+
return createAgentChatHandle(client, options);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export { agentChat };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { derived } from 'svelte/store';
|
|
2
|
+
import { isClient } from './agent-KLsxO_Uw.mjs';
|
|
3
|
+
import { getLunoraClient } from './getLunoraClient-Prczj1gU.mjs';
|
|
4
|
+
import { subscription } from './subscription-COqqiMPX.mjs';
|
|
5
|
+
|
|
6
|
+
function agentState(clientOrOptions, maybeOptions) {
|
|
7
|
+
const hasExplicitClient = isClient(clientOrOptions);
|
|
8
|
+
const client = hasExplicitClient ? clientOrOptions : getLunoraClient();
|
|
9
|
+
const options = hasExplicitClient ? maybeOptions : clientOrOptions;
|
|
10
|
+
const { data, error } = subscription(client, options.api.agents.agentState, { key: options.threadKey });
|
|
11
|
+
const state = derived(data, (value) => value);
|
|
12
|
+
return { error, state };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { agentState };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { derived } from 'svelte/store';
|
|
2
|
+
import { isClient } from './agent-KLsxO_Uw.mjs';
|
|
3
|
+
import { getLunoraClient } from './getLunoraClient-Prczj1gU.mjs';
|
|
4
|
+
import { stream } from './stream-BebZbIaD.mjs';
|
|
5
|
+
import { subscription } from './subscription-COqqiMPX.mjs';
|
|
6
|
+
|
|
7
|
+
const NO_STREAM_REF = { __lunoraRef: "" };
|
|
8
|
+
const toDurableEvent = (message) => {
|
|
9
|
+
if (message.role === "assistant" && message.toolCalls) {
|
|
10
|
+
return message.toolCalls.map((call) => {
|
|
11
|
+
return { input: call.input, seq: message.seq, toolCallId: call.id, toolName: call.name, type: "call" };
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
if (message.role !== "tool") {
|
|
15
|
+
return void 0;
|
|
16
|
+
}
|
|
17
|
+
if (message.status === "awaiting_approval") {
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
seq: message.seq,
|
|
21
|
+
type: "awaiting-approval",
|
|
22
|
+
...message.toolCallId === void 0 ? {} : { toolCallId: message.toolCallId },
|
|
23
|
+
...message.toolName === void 0 ? {} : { toolName: message.toolName }
|
|
24
|
+
}
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
return [
|
|
28
|
+
{
|
|
29
|
+
output: message.content,
|
|
30
|
+
seq: message.seq,
|
|
31
|
+
type: "result",
|
|
32
|
+
...message.status === "approved" || message.status === "rejected" ? { status: message.status } : {},
|
|
33
|
+
...message.toolCallId === void 0 ? {} : { toolCallId: message.toolCallId },
|
|
34
|
+
...message.toolName === void 0 ? {} : { toolName: message.toolName }
|
|
35
|
+
}
|
|
36
|
+
];
|
|
37
|
+
};
|
|
38
|
+
function agentToolEvents(clientOrOptions, maybeOptions) {
|
|
39
|
+
const hasExplicitClient = isClient(clientOrOptions);
|
|
40
|
+
const client = hasExplicitClient ? clientOrOptions : getLunoraClient();
|
|
41
|
+
const options = hasExplicitClient ? maybeOptions : clientOrOptions;
|
|
42
|
+
const { api, limit, stream: streamReference, threadKey } = options;
|
|
43
|
+
const historyArgs = limit === void 0 ? { key: threadKey } : { key: threadKey, limit };
|
|
44
|
+
const { data } = subscription(client, api.agents.agentMessages, historyArgs);
|
|
45
|
+
const streamArguments = streamReference === void 0 ? "skip" : { key: threadKey };
|
|
46
|
+
const streamHandle = stream(client, streamReference ?? NO_STREAM_REF, streamArguments);
|
|
47
|
+
const events = derived([data, streamHandle.chunks], ([history, liveEvents]) => {
|
|
48
|
+
const durable = history ?? [];
|
|
49
|
+
const collected = durable.flatMap((message) => toDurableEvent(message) ?? []);
|
|
50
|
+
for (const event of liveEvents) {
|
|
51
|
+
if (event.kind === "progress" && event.threadKey === threadKey) {
|
|
52
|
+
collected.push({ data: event.data, toolCallId: event.toolCallId, type: "progress" });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return collected;
|
|
56
|
+
});
|
|
57
|
+
return { events };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { agentToolEvents };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getIdentityStore } from '@lunora/client/auth';
|
|
2
2
|
import { readable } from 'svelte/store';
|
|
3
|
-
import { getLunoraClient } from './getLunoraClient
|
|
3
|
+
import { getLunoraClient } from './getLunoraClient-Prczj1gU.mjs';
|
|
4
4
|
|
|
5
5
|
const auth = (explicitClient) => {
|
|
6
6
|
const client = explicitClient ?? getLunoraClient();
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { readable } from 'svelte/store';
|
|
2
|
+
import { getLunoraClient } from './getLunoraClient-Prczj1gU.mjs';
|
|
3
|
+
|
|
4
|
+
const FLAGS_EVAL_PATH = "__lunora_flags__:eval";
|
|
5
|
+
const flagKind = (value) => {
|
|
6
|
+
const kind = typeof value;
|
|
7
|
+
if (kind === "boolean" || kind === "number" || kind === "string") {
|
|
8
|
+
return kind;
|
|
9
|
+
}
|
|
10
|
+
return "object";
|
|
11
|
+
};
|
|
12
|
+
const flagsReference = { __lunoraRef: FLAGS_EVAL_PATH };
|
|
13
|
+
const isClient = (value) => typeof value === "object" && value !== null && typeof value.subscribe === "function";
|
|
14
|
+
const subscribeFlag = (client, key, defaultValue, context, set) => {
|
|
15
|
+
try {
|
|
16
|
+
return client.subscribe(flagsReference, { context, default: defaultValue, key, type: flagKind(defaultValue) }, (next) => {
|
|
17
|
+
set(next);
|
|
18
|
+
});
|
|
19
|
+
} catch {
|
|
20
|
+
return () => {
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
function flag(clientOrKey, keyOrDefault, defaultOrContext, maybeContext) {
|
|
25
|
+
const hasExplicitClient = isClient(clientOrKey);
|
|
26
|
+
const client = hasExplicitClient ? clientOrKey : getLunoraClient();
|
|
27
|
+
const key = hasExplicitClient ? keyOrDefault : clientOrKey;
|
|
28
|
+
const defaultValue = hasExplicitClient ? defaultOrContext : keyOrDefault;
|
|
29
|
+
const context = (hasExplicitClient ? maybeContext : defaultOrContext) ?? void 0;
|
|
30
|
+
return readable(defaultValue, (set) => subscribeFlag(client, key, defaultValue, context, set));
|
|
31
|
+
}
|
|
32
|
+
function flags(clientOrFlags, flagsOrContext, maybeContext) {
|
|
33
|
+
const hasExplicitClient = isClient(clientOrFlags);
|
|
34
|
+
const client = hasExplicitClient ? clientOrFlags : getLunoraClient();
|
|
35
|
+
const flagDefaults = hasExplicitClient ? flagsOrContext : clientOrFlags;
|
|
36
|
+
const context = (hasExplicitClient ? maybeContext : flagsOrContext) ?? void 0;
|
|
37
|
+
return readable(flagDefaults, (set) => {
|
|
38
|
+
let current = { ...flagDefaults };
|
|
39
|
+
const unsubscribes = [];
|
|
40
|
+
for (const [key, defaultValue] of Object.entries(flagDefaults)) {
|
|
41
|
+
unsubscribes.push(
|
|
42
|
+
subscribeFlag(client, key, defaultValue, context, (next) => {
|
|
43
|
+
current = { ...current, [key]: next };
|
|
44
|
+
set(current);
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return () => {
|
|
49
|
+
for (const unsubscribe of unsubscribes) {
|
|
50
|
+
unsubscribe();
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { flag, flags };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LunoraError } from '@lunora/errors';
|
|
1
2
|
import { setContext, getContext } from 'svelte';
|
|
2
3
|
|
|
3
4
|
const LUNORA_CONTEXT_KEY = /* @__PURE__ */ Symbol("lunora.client");
|
|
@@ -8,7 +9,7 @@ const setLunoraClient = (client) => {
|
|
|
8
9
|
const getLunoraClient = () => {
|
|
9
10
|
const client = getContext(LUNORA_CONTEXT_KEY);
|
|
10
11
|
if (!client) {
|
|
11
|
-
throw new
|
|
12
|
+
throw new LunoraError("INTERNAL", "getLunoraClient(): no LunoraClient in context — call setLunoraClient(client) in an ancestor component first.");
|
|
12
13
|
}
|
|
13
14
|
return client;
|
|
14
15
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readable } from 'svelte/store';
|
|
2
|
-
import { getLunoraClient } from './getLunoraClient
|
|
2
|
+
import { getLunoraClient } from './getLunoraClient-Prczj1gU.mjs';
|
|
3
3
|
|
|
4
4
|
const hydratePreloaded = (preloaded, client) => {
|
|
5
5
|
const resolvedClient = client ?? getLunoraClient();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { initialPages, derivePaginationStatus,
|
|
2
|
-
import { derived, writable, readable } from 'svelte/store';
|
|
3
|
-
import { getLunoraClient } from './getLunoraClient
|
|
1
|
+
import { initialPages, derivePaginationStatus, applyLoadMore, rebalance } from '@lunora/client/pagination';
|
|
2
|
+
import { derived, writable, readable, get } from 'svelte/store';
|
|
3
|
+
import { getLunoraClient } from './getLunoraClient-Prczj1gU.mjs';
|
|
4
4
|
import { i as isFunctionReference } from './is-function-reference-ycLAcI79.mjs';
|
|
5
5
|
|
|
6
6
|
const buildPageArgs = (page, baseArgs) => {
|
|
@@ -17,23 +17,38 @@ const createPaginatedEngine = (client, function_, baseArgs, options) => {
|
|
|
17
17
|
const resultsByKey = /* @__PURE__ */ new Map();
|
|
18
18
|
const activeSubs = /* @__PURE__ */ new Map();
|
|
19
19
|
const pendingPageKeys = /* @__PURE__ */ new Set();
|
|
20
|
-
let currentPages = initialPages(initialNumItems);
|
|
21
20
|
const currentBaseArgs = baseArgs;
|
|
22
|
-
pagesStore.subscribe((pages) => {
|
|
23
|
-
currentPages = pages;
|
|
24
|
-
});
|
|
25
21
|
const rebuildPageResults = () => {
|
|
26
22
|
if (currentBaseArgs === "skip") {
|
|
27
23
|
pageResultsInternal.set([]);
|
|
28
24
|
return;
|
|
29
25
|
}
|
|
30
|
-
const updated =
|
|
26
|
+
const updated = get(pagesStore).map((page) => {
|
|
31
27
|
const key = buildPageKey(function_["__lunoraRef"], buildPageArgs(page, currentBaseArgs));
|
|
32
28
|
return resultsByKey.get(key);
|
|
33
29
|
});
|
|
34
30
|
pageResultsInternal.set(updated);
|
|
35
31
|
};
|
|
36
|
-
const
|
|
32
|
+
const migrateResultsForRebalance = (oldPages, newPages) => {
|
|
33
|
+
if (currentBaseArgs === "skip") {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const keyOf = (page) => buildPageKey(function_["__lunoraRef"], buildPageArgs(page, currentBaseArgs));
|
|
37
|
+
for (const newPage of newPages) {
|
|
38
|
+
const newKey = keyOf(newPage);
|
|
39
|
+
if (resultsByKey.has(newKey)) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const donor = oldPages.find((op) => op.lower === newPage.lower);
|
|
43
|
+
if (donor) {
|
|
44
|
+
const carried = resultsByKey.get(keyOf(donor));
|
|
45
|
+
if (carried) {
|
|
46
|
+
resultsByKey.set(newKey, carried);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const syncPass = () => {
|
|
37
52
|
if (currentBaseArgs === "skip") {
|
|
38
53
|
for (const unsub of activeSubs.values()) {
|
|
39
54
|
unsub();
|
|
@@ -43,8 +58,9 @@ const createPaginatedEngine = (client, function_, baseArgs, options) => {
|
|
|
43
58
|
return;
|
|
44
59
|
}
|
|
45
60
|
const baseArgsRecord = currentBaseArgs;
|
|
61
|
+
const pages = get(pagesStore);
|
|
46
62
|
const wantedKeys = /* @__PURE__ */ new Set();
|
|
47
|
-
for (const page of
|
|
63
|
+
for (const page of pages) {
|
|
48
64
|
wantedKeys.add(buildPageKey(function_["__lunoraRef"], buildPageArgs(page, baseArgsRecord)));
|
|
49
65
|
}
|
|
50
66
|
for (const [key, unsub] of activeSubs) {
|
|
@@ -52,9 +68,10 @@ const createPaginatedEngine = (client, function_, baseArgs, options) => {
|
|
|
52
68
|
unsub();
|
|
53
69
|
activeSubs.delete(key);
|
|
54
70
|
pendingPageKeys.delete(key);
|
|
71
|
+
resultsByKey.delete(key);
|
|
55
72
|
}
|
|
56
73
|
}
|
|
57
|
-
for (const page of
|
|
74
|
+
for (const page of pages) {
|
|
58
75
|
const pageArgs = buildPageArgs(page, baseArgsRecord);
|
|
59
76
|
const key = buildPageKey(function_["__lunoraRef"], pageArgs);
|
|
60
77
|
if (activeSubs.has(key)) {
|
|
@@ -69,12 +86,10 @@ const createPaginatedEngine = (client, function_, baseArgs, options) => {
|
|
|
69
86
|
pendingPageKeys.delete(key);
|
|
70
87
|
rebuildPageResults();
|
|
71
88
|
if (pendingPageKeys.size === 0) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
updatedResults = results;
|
|
75
|
-
})();
|
|
76
|
-
const next = rebalance(currentPages, updatedResults);
|
|
89
|
+
const latestPages = get(pagesStore);
|
|
90
|
+
const next = rebalance(latestPages, get(pageResultsInternal));
|
|
77
91
|
if (next) {
|
|
92
|
+
migrateResultsForRebalance(latestPages, next);
|
|
78
93
|
pagesStore.set(next);
|
|
79
94
|
syncSubscriptions();
|
|
80
95
|
rebuildPageResults();
|
|
@@ -86,6 +101,23 @@ const createPaginatedEngine = (client, function_, baseArgs, options) => {
|
|
|
86
101
|
activeSubs.set(key, unsub);
|
|
87
102
|
}
|
|
88
103
|
};
|
|
104
|
+
let syncing = false;
|
|
105
|
+
let resyncRequested = false;
|
|
106
|
+
const syncSubscriptions = () => {
|
|
107
|
+
if (syncing) {
|
|
108
|
+
resyncRequested = true;
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
syncing = true;
|
|
112
|
+
try {
|
|
113
|
+
do {
|
|
114
|
+
resyncRequested = false;
|
|
115
|
+
syncPass();
|
|
116
|
+
} while (resyncRequested);
|
|
117
|
+
} finally {
|
|
118
|
+
syncing = false;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
89
121
|
const teardownAll = () => {
|
|
90
122
|
for (const unsub of activeSubs.values()) {
|
|
91
123
|
unsub();
|
|
@@ -115,14 +147,12 @@ const createPaginatedEngine = (client, function_, baseArgs, options) => {
|
|
|
115
147
|
if (currentBaseArgs === "skip") {
|
|
116
148
|
return;
|
|
117
149
|
}
|
|
118
|
-
|
|
119
|
-
pageResultsInternal.subscribe((results) => {
|
|
120
|
-
currentResults = results;
|
|
121
|
-
})();
|
|
150
|
+
const currentResults = get(pageResultsInternal);
|
|
122
151
|
const { nextCursor, status: currentStatus } = derivePaginationStatus(false, currentResults);
|
|
123
152
|
if (currentStatus !== "CanLoadMore") {
|
|
124
153
|
return;
|
|
125
154
|
}
|
|
155
|
+
const currentPages = get(pagesStore);
|
|
126
156
|
const next = applyLoadMore(currentPages, nextCursor, numberItems);
|
|
127
157
|
if (!next) {
|
|
128
158
|
return;
|
|
@@ -136,6 +166,7 @@ const createPaginatedEngine = (client, function_, baseArgs, options) => {
|
|
|
136
166
|
const carried = resultsByKey.get(oldKey);
|
|
137
167
|
if (carried) {
|
|
138
168
|
resultsByKey.set(newKey, carried);
|
|
169
|
+
resultsByKey.delete(oldKey);
|
|
139
170
|
}
|
|
140
171
|
}
|
|
141
172
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createMutationRunner } from '@lunora/client';
|
|
2
2
|
import { writable } from 'svelte/store';
|
|
3
|
-
import { getLunoraClient } from './getLunoraClient
|
|
3
|
+
import { getLunoraClient } from './getLunoraClient-Prczj1gU.mjs';
|
|
4
4
|
|
|
5
5
|
function mutation(clientOrFunction, maybeFunction) {
|
|
6
6
|
const hasExplicitClient = maybeFunction !== void 0;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createMutatorRunner } from '@lunora/client';
|
|
2
|
+
import { writable, derived } from 'svelte/store';
|
|
3
|
+
|
|
4
|
+
const mutator = (handle) => {
|
|
5
|
+
const error = writable();
|
|
6
|
+
const pending = writable(false);
|
|
7
|
+
const isError = derived(error, ($error) => $error !== void 0);
|
|
8
|
+
const { mutate, reset } = createMutatorRunner(handle, {
|
|
9
|
+
setError: (value) => {
|
|
10
|
+
error.set(value);
|
|
11
|
+
},
|
|
12
|
+
setPending: (value) => {
|
|
13
|
+
pending.set(value);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
return { error, isError, mutate, pending, reset };
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export { mutator };
|
|
@@ -1,16 +1,24 @@
|
|
|
1
|
+
import { onDestroy } from 'svelte';
|
|
1
2
|
import { readable } from 'svelte/store';
|
|
2
|
-
import { getLunoraClient } from './getLunoraClient
|
|
3
|
+
import { getLunoraClient } from './getLunoraClient-Prczj1gU.mjs';
|
|
3
4
|
|
|
4
|
-
const
|
|
5
|
-
if (typeof crypto !== "undefined"
|
|
6
|
-
|
|
5
|
+
const randomSessionId = (prefix = "sess") => {
|
|
6
|
+
if (typeof crypto !== "undefined") {
|
|
7
|
+
if (typeof crypto.randomUUID === "function") {
|
|
8
|
+
return crypto.randomUUID();
|
|
9
|
+
}
|
|
10
|
+
if (typeof crypto.getRandomValues === "function") {
|
|
11
|
+
const bytes = crypto.getRandomValues(new Uint8Array(16));
|
|
12
|
+
return `${prefix}-${Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("")}`;
|
|
13
|
+
}
|
|
7
14
|
}
|
|
8
|
-
return
|
|
15
|
+
return `${prefix}-${Date.now().toString(36)}`;
|
|
9
16
|
};
|
|
17
|
+
|
|
10
18
|
const DEFAULT_INTERVAL_MS = 1e4;
|
|
11
19
|
const createPresenceHandle = (client, roomId, options) => {
|
|
12
20
|
const { heartbeat, intervalMs = DEFAULT_INTERVAL_MS, listPresent, shardKey } = options;
|
|
13
|
-
const sessionId = options.sessionId ??
|
|
21
|
+
const sessionId = options.sessionId ?? randomSessionId();
|
|
14
22
|
let latestData = options.data;
|
|
15
23
|
const sendHeartbeat = () => {
|
|
16
24
|
const args = {
|
|
@@ -46,13 +54,22 @@ const createPresenceHandle = (client, roomId, options) => {
|
|
|
46
54
|
);
|
|
47
55
|
return unsubscribe;
|
|
48
56
|
});
|
|
57
|
+
let torndown = false;
|
|
49
58
|
const teardown = () => {
|
|
59
|
+
if (torndown) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
torndown = true;
|
|
50
63
|
clearInterval(intervalHandle);
|
|
51
64
|
if (typeof document !== "undefined") {
|
|
52
65
|
document.removeEventListener("visibilitychange", onVisible);
|
|
53
66
|
}
|
|
54
67
|
releaseConnectionContext();
|
|
55
68
|
};
|
|
69
|
+
try {
|
|
70
|
+
onDestroy(teardown);
|
|
71
|
+
} catch {
|
|
72
|
+
}
|
|
56
73
|
return { present, sessionId, setData, teardown };
|
|
57
74
|
};
|
|
58
75
|
function presence(clientOrRoomId, roomIdOrOptions, maybeOptions) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createQuerySubscription } from '@lunora/client/query';
|
|
2
2
|
import { readable } from 'svelte/store';
|
|
3
|
-
import { getLunoraClient } from './getLunoraClient
|
|
3
|
+
import { getLunoraClient } from './getLunoraClient-Prczj1gU.mjs';
|
|
4
4
|
import { i as isFunctionReference } from './is-function-reference-ycLAcI79.mjs';
|
|
5
5
|
|
|
6
6
|
function query(clientOrFunction, functionOrArguments, argumentsOrOptions, maybeOptions) {
|
|
@@ -25,7 +25,13 @@ function query(clientOrFunction, functionOrArguments, argumentsOrOptions, maybeO
|
|
|
25
25
|
onData: (value) => {
|
|
26
26
|
set(value);
|
|
27
27
|
},
|
|
28
|
-
onError: options.onError
|
|
28
|
+
onError: options.onError,
|
|
29
|
+
// `args === "skip"` short-circuits inside the shared helper and
|
|
30
|
+
// fires this reset — clear any prior value so a store that flips
|
|
31
|
+
// to `"skip"` does not retain stale data.
|
|
32
|
+
onReset: () => {
|
|
33
|
+
set(void 0);
|
|
34
|
+
}
|
|
29
35
|
},
|
|
30
36
|
{ shardKey: options.shardKey }
|
|
31
37
|
)
|