memeloop 0.0.1 → 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/README.md +63 -0
- package/dist/browser.cjs +1413 -0
- package/dist/browser.cjs.map +1 -0
- package/dist/browser.d.cts +3066 -0
- package/dist/browser.d.ts +3066 -0
- package/dist/browser.js +43 -0
- package/dist/chunk-426CJUZP.js +630 -0
- package/dist/chunk-426CJUZP.js.map +1 -0
- package/dist/chunk-44YHBKDL.js +382 -0
- package/dist/chunk-44YHBKDL.js.map +1 -0
- package/dist/chunk-7ZDTB4VZ.js +63 -0
- package/dist/chunk-7ZDTB4VZ.js.map +1 -0
- package/dist/chunk-AZFYDWIN.js +98 -0
- package/dist/chunk-AZFYDWIN.js.map +1 -0
- package/dist/chunk-BGPU4RR7.js +367 -0
- package/dist/chunk-BGPU4RR7.js.map +1 -0
- package/dist/chunk-CCEFAOSH.js +496 -0
- package/dist/chunk-CCEFAOSH.js.map +1 -0
- package/dist/chunk-FWSY5HOA.js +63 -0
- package/dist/chunk-FWSY5HOA.js.map +1 -0
- package/dist/chunk-GYIOMQMY.js +8726 -0
- package/dist/chunk-GYIOMQMY.js.map +1 -0
- package/dist/chunk-HVB2BR3H.js +42 -0
- package/dist/chunk-HVB2BR3H.js.map +1 -0
- package/dist/chunk-K6P63KD4.js +68 -0
- package/dist/chunk-K6P63KD4.js.map +1 -0
- package/dist/chunk-MRKY4HGF.js +205 -0
- package/dist/chunk-MRKY4HGF.js.map +1 -0
- package/dist/chunk-QFHAAIIM.js +2657 -0
- package/dist/chunk-QFHAAIIM.js.map +1 -0
- package/dist/chunk-VZKQX5PP.js +1 -0
- package/dist/chunk-VZKQX5PP.js.map +1 -0
- package/dist/chunk-WAI6BODI.js +175 -0
- package/dist/chunk-WAI6BODI.js.map +1 -0
- package/dist/chunk-XHRBV6I3.js +3637 -0
- package/dist/chunk-XHRBV6I3.js.map +1 -0
- package/dist/chunk-YMNXDNDW.js +798 -0
- package/dist/chunk-YMNXDNDW.js.map +1 -0
- package/dist/conversation.cjs +208 -0
- package/dist/conversation.cjs.map +1 -0
- package/dist/conversation.d.cts +100 -0
- package/dist/conversation.d.ts +100 -0
- package/dist/conversation.js +21 -0
- package/dist/conversation.js.map +1 -0
- package/dist/device-network-portable.cjs +702 -0
- package/dist/device-network-portable.cjs.map +1 -0
- package/dist/device-network-portable.d.cts +110 -0
- package/dist/device-network-portable.d.ts +110 -0
- package/dist/device-network-portable.js +53 -0
- package/dist/device-network-portable.js.map +1 -0
- package/dist/device-network.cjs +906 -0
- package/dist/device-network.cjs.map +1 -0
- package/dist/device-network.d.cts +6 -0
- package/dist/device-network.d.ts +6 -0
- package/dist/device-network.js +59 -0
- package/dist/device-network.js.map +1 -0
- package/dist/fetchProvider-BpcGVSOG.d.cts +91 -0
- package/dist/fetchProvider-Cm0sO4Tl.d.ts +91 -0
- package/dist/index.cjs +27957 -5459
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +94 -1320
- package/dist/index.d.ts +94 -1320
- package/dist/index.js +10576 -2386
- package/dist/index.js.map +1 -1
- package/dist/interface-IrKBFtL1.d.cts +493 -0
- package/dist/interface-IrKBFtL1.d.ts +493 -0
- package/dist/llm-providers.cjs +43 -8
- package/dist/llm-providers.cjs.map +1 -1
- package/dist/llm-providers.d.cts +2 -1
- package/dist/llm-providers.d.ts +2 -1
- package/dist/llm-providers.js +4 -2
- package/dist/llm-providers.js.map +1 -1
- package/dist/loop-api.cjs +5177 -2050
- package/dist/loop-api.cjs.map +1 -1
- package/dist/loop-api.d.cts +11 -5
- package/dist/loop-api.d.ts +11 -5
- package/dist/loop-api.js +84 -49
- package/dist/mobile.cjs +2625 -0
- package/dist/mobile.cjs.map +1 -0
- package/dist/mobile.d.cts +6 -0
- package/dist/mobile.d.ts +6 -0
- package/dist/mobile.js +22 -0
- package/dist/mobile.js.map +1 -0
- package/dist/orchestration-portable-Bsf8YRfp.d.cts +2192 -0
- package/dist/orchestration-portable-Zw0g5tbj.d.ts +2192 -0
- package/dist/orchestration-portable.cjs +9553 -0
- package/dist/orchestration-portable.cjs.map +1 -0
- package/dist/orchestration-portable.d.cts +5 -0
- package/dist/orchestration-portable.d.ts +5 -0
- package/dist/orchestration-portable.js +290 -0
- package/dist/orchestration-portable.js.map +1 -0
- package/dist/pairingInvite-BXPWY3aM.d.cts +149 -0
- package/dist/pairingInvite-Cuz0wuq9.d.ts +149 -0
- package/dist/promptConcat-WTN-uHcz.d.cts +516 -0
- package/dist/promptConcat-deDSWZE3.d.ts +516 -0
- package/dist/providerRegistry-9trr5aoK.d.ts +86 -0
- package/dist/providerRegistry-xk_B1Ekv.d.cts +86 -0
- package/dist/registry-8eztoD_r.d.cts +393 -0
- package/dist/registry-DV24sI-3.d.ts +393 -0
- package/dist/remoteClient-B_spK019.d.ts +87 -0
- package/dist/remoteClient-CBggnRy3.d.cts +87 -0
- package/dist/runtime-SKSXVYIM.js +18 -0
- package/dist/runtime-SKSXVYIM.js.map +1 -0
- package/dist/scriptDeploymentPipeline-BAeo1dPb.d.cts +2463 -0
- package/dist/scriptDeploymentPipeline-DsnT0AG6.d.ts +2463 -0
- package/dist/syncCloudDevices-BEqwgrhD.d.ts +49 -0
- package/dist/syncCloudDevices-Ds_Kcgrv.d.cts +49 -0
- package/dist/types-7pYti-k9.d.cts +255 -0
- package/dist/types-CdFVSntj.d.ts +255 -0
- package/package.json +110 -35
- package/dist/anthropic.cjs +0 -72
- package/dist/anthropic.cjs.map +0 -1
- package/dist/anthropic.d.cts +0 -21
- package/dist/anthropic.d.ts +0 -21
- package/dist/anthropic.js +0 -21
- package/dist/anthropic.js.map +0 -1
- package/dist/azure.cjs +0 -72
- package/dist/azure.cjs.map +0 -1
- package/dist/azure.d.cts +0 -21
- package/dist/azure.d.ts +0 -21
- package/dist/azure.js +0 -21
- package/dist/azure.js.map +0 -1
- package/dist/chunk-3CN7DFBL.js +0 -4894
- package/dist/chunk-3CN7DFBL.js.map +0 -1
- package/dist/chunk-4AZ4D7U5.js +0 -32
- package/dist/chunk-4AZ4D7U5.js.map +0 -1
- package/dist/chunk-6ON4XSOV.js +0 -63
- package/dist/chunk-6ON4XSOV.js.map +0 -1
- package/dist/chunk-DJQNGIXX.js +0 -4793
- package/dist/chunk-DJQNGIXX.js.map +0 -1
- package/dist/chunk-FKQP6AOQ.js +0 -32
- package/dist/chunk-FKQP6AOQ.js.map +0 -1
- package/dist/chunk-OVJ7JJBA.js +0 -35
- package/dist/chunk-OVJ7JJBA.js.map +0 -1
- package/dist/chunk-P4UZ7IXC.js +0 -42
- package/dist/chunk-YHJ2AEFR.js +0 -4933
- package/dist/chunk-YHJ2AEFR.js.map +0 -1
- package/dist/chunk-YVK7RYRO.js +0 -4973
- package/dist/chunk-YVK7RYRO.js.map +0 -1
- package/dist/code-assistant.json +0 -114
- package/dist/cohere.cjs +0 -72
- package/dist/cohere.cjs.map +0 -1
- package/dist/cohere.d.cts +0 -21
- package/dist/cohere.d.ts +0 -21
- package/dist/cohere.js +0 -21
- package/dist/cohere.js.map +0 -1
- package/dist/deepseek.cjs +0 -72
- package/dist/deepseek.cjs.map +0 -1
- package/dist/deepseek.d.cts +0 -21
- package/dist/deepseek.d.ts +0 -21
- package/dist/deepseek.js +0 -21
- package/dist/deepseek.js.map +0 -1
- package/dist/dist-65U7OYRG.js +0 -1257
- package/dist/dist-65U7OYRG.js.map +0 -1
- package/dist/fetchProvider-Cu4WkU5O.d.cts +0 -819
- package/dist/fetchProvider-Cu4WkU5O.d.ts +0 -819
- package/dist/frontend-ui-ux.json +0 -105
- package/dist/general-assistant.json +0 -95
- package/dist/git-master.json +0 -51
- package/dist/google-vertex.cjs +0 -72
- package/dist/google-vertex.cjs.map +0 -1
- package/dist/google-vertex.d.cts +0 -21
- package/dist/google-vertex.d.ts +0 -21
- package/dist/google-vertex.js +0 -21
- package/dist/google-vertex.js.map +0 -1
- package/dist/google.cjs +0 -72
- package/dist/google.cjs.map +0 -1
- package/dist/google.d.cts +0 -21
- package/dist/google.d.ts +0 -21
- package/dist/google.js +0 -21
- package/dist/google.js.map +0 -1
- package/dist/groq.cjs +0 -72
- package/dist/groq.cjs.map +0 -1
- package/dist/groq.d.cts +0 -21
- package/dist/groq.d.ts +0 -21
- package/dist/groq.js +0 -21
- package/dist/groq.js.map +0 -1
- package/dist/index.d.mts +0 -3203
- package/dist/index.mjs +0 -7064
- package/dist/index.mjs.map +0 -1
- package/dist/mistral.cjs +0 -72
- package/dist/mistral.cjs.map +0 -1
- package/dist/mistral.d.cts +0 -21
- package/dist/mistral.d.ts +0 -21
- package/dist/mistral.js +0 -21
- package/dist/mistral.js.map +0 -1
- package/dist/multipart-parser-EJCXIUHC.js +0 -372
- package/dist/multipart-parser-EJCXIUHC.js.map +0 -1
- package/dist/openai.cjs +0 -72
- package/dist/openai.cjs.map +0 -1
- package/dist/openai.d.cts +0 -21
- package/dist/openai.d.ts +0 -21
- package/dist/openai.js +0 -21
- package/dist/openai.js.map +0 -1
- package/dist/perplexity.cjs +0 -72
- package/dist/perplexity.cjs.map +0 -1
- package/dist/perplexity.d.cts +0 -21
- package/dist/perplexity.d.ts +0 -21
- package/dist/perplexity.js +0 -21
- package/dist/perplexity.js.map +0 -1
- package/dist/playwright.json +0 -52
- package/dist/promptConcat-BJdazTg5.d.cts +0 -1832
- package/dist/promptConcat-BJdazTg5.d.ts +0 -1832
- package/dist/promptConcat-CAkpni_8.d.cts +0 -1834
- package/dist/promptConcat-CAkpni_8.d.ts +0 -1834
- package/dist/promptConcat-CfH5-GAE.d.cts +0 -1036
- package/dist/promptConcat-ChcAZOOL.d.ts +0 -1036
- package/dist/promptConcat-G5TnJVRy.d.cts +0 -1800
- package/dist/promptConcat-G5TnJVRy.d.ts +0 -1800
- package/dist/promptConcat-L72eowzp.d.ts +0 -1090
- package/dist/promptConcat-eLHdN7K8.d.cts +0 -1090
- package/dist/src-VTSXKG72.js +0 -1409
- package/dist/src-VTSXKG72.js.map +0 -1
- package/dist/togetherai.cjs +0 -72
- package/dist/togetherai.cjs.map +0 -1
- package/dist/togetherai.d.cts +0 -21
- package/dist/togetherai.d.ts +0 -21
- package/dist/togetherai.js +0 -21
- package/dist/togetherai.js.map +0 -1
- package/dist/types-B0Jm2l38.d.cts +0 -767
- package/dist/types-B0Jm2l38.d.ts +0 -767
- package/dist/xai.cjs +0 -72
- package/dist/xai.cjs.map +0 -1
- package/dist/xai.d.cts +0 -21
- package/dist/xai.d.ts +0 -21
- package/dist/xai.js +0 -21
- package/dist/xai.js.map +0 -1
- /package/dist/{chunk-P4UZ7IXC.js.map → browser.js.map} +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAgentToolLoopRunner
|
|
3
|
+
} from "./chunk-QFHAAIIM.js";
|
|
4
|
+
|
|
5
|
+
// src/loopAPI/agent-tool-loop/runner.ts
|
|
6
|
+
function resolveAgentToolLoopTerminalState(step, current) {
|
|
7
|
+
if (step.type !== "thinking") return current;
|
|
8
|
+
const data = step.data;
|
|
9
|
+
if (data.status === "input-required") return "input-required";
|
|
10
|
+
if (data.status === "cancelled") return "canceled";
|
|
11
|
+
if (data.status === "max-iterations") return "completed";
|
|
12
|
+
if (data.status === "blocked") return "failed";
|
|
13
|
+
if (data.status === "calling-llm") return "working";
|
|
14
|
+
return current;
|
|
15
|
+
}
|
|
16
|
+
async function runAgentToolLoopTurn(context, input, callbacks = {}) {
|
|
17
|
+
const agentToolLoop = callbacks.agentToolLoop ?? createAgentToolLoopRunner(context);
|
|
18
|
+
let terminalState = "completed";
|
|
19
|
+
let stepCount = 0;
|
|
20
|
+
for await (const step of agentToolLoop(input)) {
|
|
21
|
+
stepCount += 1;
|
|
22
|
+
terminalState = resolveAgentToolLoopTerminalState(step, terminalState);
|
|
23
|
+
await callbacks.onStep?.(step);
|
|
24
|
+
if (step.type === "thinking" && step.data && typeof step.data === "object") {
|
|
25
|
+
const data = step.data;
|
|
26
|
+
const status = data.status;
|
|
27
|
+
if (typeof status === "string") {
|
|
28
|
+
await callbacks.onProgress?.(status, data, step);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
state: terminalState === "working" || terminalState === "submitted" ? "completed" : terminalState,
|
|
34
|
+
stepCount
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export {
|
|
39
|
+
resolveAgentToolLoopTerminalState,
|
|
40
|
+
runAgentToolLoopTurn
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=chunk-HVB2BR3H.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/loopAPI/agent-tool-loop/runner.ts"],"sourcesContent":["/**\n * AgentToolLoop runner — convenience API for driving a full loop turn.\n */\n\nimport type { AgentFrameworkContext, AgentInstanceState } from '../../types.js';\nimport type { AgentLoopGenerator, AgentLoopInput, AgentLoopStep } from '../types.js';\nimport { createAgentToolLoopRunner } from './directRunner.js';\n\nexport interface RunAgentToolLoopTurnCallbacks {\n onStep?: (step: AgentLoopStep) => void | Promise<void>;\n onProgress?: (\n status: string,\n data: Record<string, unknown>,\n step: AgentLoopStep,\n ) => void | Promise<void>;\n agentToolLoop?: (input: AgentLoopInput) => AgentLoopGenerator;\n}\n\nexport interface RunAgentToolLoopTurnResult {\n state: AgentInstanceState;\n stepCount: number;\n}\n\nexport function resolveAgentToolLoopTerminalState(\n step: AgentLoopStep,\n current: AgentInstanceState,\n): AgentInstanceState {\n if (step.type !== 'thinking') return current;\n const data = step.data as { status?: string };\n if (data.status === 'input-required') return 'input-required';\n if (data.status === 'cancelled') return 'canceled';\n if (data.status === 'max-iterations') return 'completed';\n if (data.status === 'blocked') return 'failed';\n if (data.status === 'calling-llm') return 'working';\n return current;\n}\n\nexport async function runAgentToolLoopTurn(\n context: AgentFrameworkContext,\n input: AgentLoopInput,\n callbacks: RunAgentToolLoopTurnCallbacks = {},\n): Promise<RunAgentToolLoopTurnResult> {\n const agentToolLoop = callbacks.agentToolLoop ?? createAgentToolLoopRunner(context);\n let terminalState: AgentInstanceState = 'completed';\n let stepCount = 0;\n\n for await (const step of agentToolLoop(input)) {\n stepCount += 1;\n terminalState = resolveAgentToolLoopTerminalState(step, terminalState);\n await callbacks.onStep?.(step);\n\n if (step.type === 'thinking' && step.data && typeof step.data === 'object') {\n const data = step.data as Record<string, unknown>;\n const status = data.status;\n if (typeof status === 'string') {\n await callbacks.onProgress?.(status, data, step);\n }\n }\n }\n\n return {\n state: terminalState === 'working' || terminalState === 'submitted' ? 'completed' : terminalState,\n stepCount,\n };\n}\n"],"mappings":";;;;;AAuBO,SAAS,kCACd,MACA,SACoB;AACpB,MAAI,KAAK,SAAS,WAAY,QAAO;AACrC,QAAM,OAAO,KAAK;AAClB,MAAI,KAAK,WAAW,iBAAkB,QAAO;AAC7C,MAAI,KAAK,WAAW,YAAa,QAAO;AACxC,MAAI,KAAK,WAAW,iBAAkB,QAAO;AAC7C,MAAI,KAAK,WAAW,UAAW,QAAO;AACtC,MAAI,KAAK,WAAW,cAAe,QAAO;AAC1C,SAAO;AACT;AAEA,eAAsB,qBACpB,SACA,OACA,YAA2C,CAAC,GACP;AACrC,QAAM,gBAAgB,UAAU,iBAAiB,0BAA0B,OAAO;AAClF,MAAI,gBAAoC;AACxC,MAAI,YAAY;AAEhB,mBAAiB,QAAQ,cAAc,KAAK,GAAG;AAC7C,iBAAa;AACb,oBAAgB,kCAAkC,MAAM,aAAa;AACrE,UAAM,UAAU,SAAS,IAAI;AAE7B,QAAI,KAAK,SAAS,cAAc,KAAK,QAAQ,OAAO,KAAK,SAAS,UAAU;AAC1E,YAAM,OAAO,KAAK;AAClB,YAAM,SAAS,KAAK;AACpB,UAAI,OAAO,WAAW,UAAU;AAC9B,cAAM,UAAU,aAAa,QAAQ,MAAM,IAAI;AAAA,MACjD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,kBAAkB,aAAa,kBAAkB,cAAc,cAAc;AAAA,IACpF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// src/llm/fetchProvider.ts
|
|
2
|
+
import { generateText, streamText } from "ai";
|
|
3
|
+
function createFetchLLMProvider(config) {
|
|
4
|
+
return {
|
|
5
|
+
name: config.name,
|
|
6
|
+
...config.modelId !== void 0 ? { modelId: config.modelId } : {},
|
|
7
|
+
// Store the factory so hosts can introspect or extend
|
|
8
|
+
model: config.createModel,
|
|
9
|
+
async chat(request) {
|
|
10
|
+
const body = typeof request === "object" && request !== null ? request : {};
|
|
11
|
+
const model = config.createModel(body.model);
|
|
12
|
+
const specificationVersion = model?.specificationVersion;
|
|
13
|
+
if (model === null || typeof model !== "object" || !["v2", "v3", "v4"].includes(String(specificationVersion))) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
`LLM provider '${config.name}' returned an incompatible AI SDK model for '${typeof body.model === "string" ? body.model : config.modelId ?? "default"}' (expected specificationVersion v2, v3, or v4; received ${String(specificationVersion)})`
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
const systemMessages = (body.messages ?? []).filter((message) => message.role === "system").map((message) => message.content);
|
|
19
|
+
const messages = (body.messages ?? []).filter((message) => message.role !== "system").map((message) => {
|
|
20
|
+
const role = message.role === "tool" ? "user" : message.role;
|
|
21
|
+
return {
|
|
22
|
+
role,
|
|
23
|
+
content: message.content
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
const system = body.system ?? (systemMessages.length > 0 ? systemMessages.join("\n\n") : void 0);
|
|
27
|
+
const temperature = body.temperature;
|
|
28
|
+
const abortSignal = body.abortSignal;
|
|
29
|
+
const maxOutputTokens = body.max_tokens;
|
|
30
|
+
if (body.stream !== false) {
|
|
31
|
+
let streamingError;
|
|
32
|
+
const result2 = streamText({
|
|
33
|
+
model,
|
|
34
|
+
instructions: system,
|
|
35
|
+
messages,
|
|
36
|
+
maxOutputTokens,
|
|
37
|
+
temperature,
|
|
38
|
+
abortSignal,
|
|
39
|
+
onError: ({ error }) => {
|
|
40
|
+
streamingError = error;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return (async function* () {
|
|
44
|
+
for await (const chunk of result2.textStream) {
|
|
45
|
+
yield chunk;
|
|
46
|
+
}
|
|
47
|
+
if (streamingError !== void 0) {
|
|
48
|
+
throw streamingError instanceof Error ? streamingError : new Error("The model stream failed", { cause: streamingError });
|
|
49
|
+
}
|
|
50
|
+
})();
|
|
51
|
+
}
|
|
52
|
+
const result = await generateText({
|
|
53
|
+
model,
|
|
54
|
+
instructions: system,
|
|
55
|
+
messages,
|
|
56
|
+
maxOutputTokens,
|
|
57
|
+
temperature,
|
|
58
|
+
abortSignal
|
|
59
|
+
});
|
|
60
|
+
return result.text;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export {
|
|
66
|
+
createFetchLLMProvider
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=chunk-K6P63KD4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/llm/fetchProvider.ts"],"sourcesContent":["/**\n * Provider-agnostic LLM provider — wraps a current Vercel AI SDK LanguageModel.\n *\n * The core does NOT depend on @ai-sdk/openai or any specific provider.\n * Hosts inject their own `createModel` factory:\n *\n * import { createOpenAI } from '@ai-sdk/openai';\n * const openai = createOpenAI({ baseURL: '...', apiKey: '...' });\n * const provider = createFetchLLMProvider({\n * name: 'openai',\n * createModel: (id) => openai(id ?? 'gpt-4o-mini'),\n * });\n *\n * Or for Anthropic:\n * import { createAnthropic } from '@ai-sdk/anthropic';\n * const anthropic = createAnthropic({ apiKey: '...' });\n * const provider = createFetchLLMProvider({\n * name: 'claude',\n * createModel: (id) => anthropic(id ?? 'claude-3-5-sonnet-20241022'),\n * });\n *\n * Works with every @ai-sdk/* provider: openai, anthropic, google, deepseek,\n * cohere, mistral, azure, bedrock, groq, ollama, openrouter, together, etc.\n */\n\nimport type { LanguageModel } from 'ai';\nimport { generateText, streamText } from 'ai';\n\nimport type { ILLMProvider } from '../types.js';\n\n// ─── Config ────────────────────────────────────────────────────────────\n\nexport interface FetchLLMProviderConfig {\n /** Display name. */\n name: string;\n /** Serializable default model identity for scheduling and audit records. */\n modelId?: string;\n /**\n * Factory: given an optional model id, return a LanguageModel from any @ai-sdk/* provider.\n * The factory is responsible for picking a default model when `modelId` is omitted.\n */\n createModel: (modelId?: string) => LanguageModel;\n}\n\n// ─── Factory ───────────────────────────────────────────────────────────\n\n/**\n * Create an `ILLMProvider` that delegates to the Vercel AI SDK.\n *\n * Provider-agnostic — hosts supply their own `createModel` factory.\n * Supports every @ai-sdk/* provider (OpenAI, Anthropic, Google, DeepSeek,\n * Groq, Ollama, OpenRouter, Together, Bedrock, Azure, Mistral, Cohere…).\n *\n * @example\n * ```ts\n * import { createOpenAI } from '@ai-sdk/openai';\n * const openai = createOpenAI({ baseURL: 'https://api.openai.com/v1', apiKey });\n * const provider = createFetchLLMProvider({\n * name: 'openai',\n * createModel: (modelId) => openai(modelId ?? 'gpt-4o-mini'),\n * });\n * ```\n */\nexport function createFetchLLMProvider(config: FetchLLMProviderConfig): ILLMProvider {\n return {\n name: config.name,\n ...(config.modelId !== undefined ? { modelId: config.modelId } : {}),\n // Store the factory so hosts can introspect or extend\n model: config.createModel as unknown as LanguageModel,\n async chat(request: unknown) {\n const body = (typeof request === 'object' && request !== null ? request : {}) as {\n messages?: Array<{ role: string; content: string }>;\n model?: string;\n stream?: boolean;\n max_tokens?: number;\n temperature?: number;\n system?: string;\n abortSignal?: AbortSignal;\n };\n\n const model = config.createModel(body.model);\n const specificationVersion = (\n model as { specificationVersion?: unknown } | null\n )?.specificationVersion;\n if (\n model === null ||\n typeof model !== 'object' ||\n !['v2', 'v3', 'v4'].includes(String(specificationVersion))\n ) {\n throw new Error(\n `LLM provider '${config.name}' returned an incompatible AI SDK model for '${\n typeof body.model === 'string' ? body.model : (config.modelId ?? 'default')\n }' (expected specificationVersion v2, v3, or v4; received ${String(specificationVersion)})`,\n );\n }\n\n const systemMessages = (body.messages ?? [])\n .filter((message) => message.role === 'system')\n .map((message) => message.content);\n const messages = (body.messages ?? [])\n .filter((message) => message.role !== 'system')\n .map((message) => {\n // AI SDK model messages do not accept a bare textual tool role.\n // MemeLoop stores tool results as role='tool'; promote them to user\n // messages while preserving the result text in conversation history.\n const role = message.role === 'tool' ? 'user' : (message.role as 'user' | 'assistant');\n return {\n role,\n content: message.content,\n };\n });\n\n const system = body.system ?? (\n systemMessages.length > 0 ? systemMessages.join('\\n\\n') : undefined\n );\n const temperature = body.temperature;\n const abortSignal = body.abortSignal;\n const maxOutputTokens = body.max_tokens;\n\n if (body.stream !== false) {\n let streamingError: unknown;\n const result = streamText({\n model,\n instructions: system,\n messages,\n maxOutputTokens,\n temperature,\n abortSignal,\n onError: ({ error }) => {\n streamingError = error;\n },\n });\n return (async function*() {\n for await (const chunk of result.textStream) {\n yield chunk;\n }\n if (streamingError !== undefined) {\n throw streamingError instanceof Error\n ? streamingError\n : new Error('The model stream failed', { cause: streamingError });\n }\n })();\n }\n\n const result = await generateText({\n model,\n instructions: system,\n messages,\n maxOutputTokens,\n temperature,\n abortSignal,\n });\n return result.text;\n },\n };\n}\n"],"mappings":";AA0BA,SAAS,cAAc,kBAAkB;AAqClC,SAAS,uBAAuB,QAA8C;AACnF,SAAO;AAAA,IACL,MAAM,OAAO;AAAA,IACb,GAAI,OAAO,YAAY,SAAY,EAAE,SAAS,OAAO,QAAQ,IAAI,CAAC;AAAA;AAAA,IAElE,OAAO,OAAO;AAAA,IACd,MAAM,KAAK,SAAkB;AAC3B,YAAM,OAAQ,OAAO,YAAY,YAAY,YAAY,OAAO,UAAU,CAAC;AAU3E,YAAM,QAAQ,OAAO,YAAY,KAAK,KAAK;AAC3C,YAAM,uBACJ,OACC;AACH,UACE,UAAU,QACV,OAAO,UAAU,YACjB,CAAC,CAAC,MAAM,MAAM,IAAI,EAAE,SAAS,OAAO,oBAAoB,CAAC,GACzD;AACA,cAAM,IAAI;AAAA,UACR,iBAAiB,OAAO,IAAI,gDAC1B,OAAO,KAAK,UAAU,WAAW,KAAK,QAAS,OAAO,WAAW,SACnE,4DAA4D,OAAO,oBAAoB,CAAC;AAAA,QAC1F;AAAA,MACF;AAEA,YAAM,kBAAkB,KAAK,YAAY,CAAC,GACvC,OAAO,CAAC,YAAY,QAAQ,SAAS,QAAQ,EAC7C,IAAI,CAAC,YAAY,QAAQ,OAAO;AACnC,YAAM,YAAY,KAAK,YAAY,CAAC,GACjC,OAAO,CAAC,YAAY,QAAQ,SAAS,QAAQ,EAC7C,IAAI,CAAC,YAAY;AAIhB,cAAM,OAAO,QAAQ,SAAS,SAAS,SAAU,QAAQ;AACzD,eAAO;AAAA,UACL;AAAA,UACA,SAAS,QAAQ;AAAA,QACnB;AAAA,MACF,CAAC;AAEH,YAAM,SAAS,KAAK,WAClB,eAAe,SAAS,IAAI,eAAe,KAAK,MAAM,IAAI;AAE5D,YAAM,cAAc,KAAK;AACzB,YAAM,cAAc,KAAK;AACzB,YAAM,kBAAkB,KAAK;AAE7B,UAAI,KAAK,WAAW,OAAO;AACzB,YAAI;AACJ,cAAMA,UAAS,WAAW;AAAA,UACxB;AAAA,UACA,cAAc;AAAA,UACd;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,SAAS,CAAC,EAAE,MAAM,MAAM;AACtB,6BAAiB;AAAA,UACnB;AAAA,QACF,CAAC;AACD,gBAAQ,mBAAkB;AACxB,2BAAiB,SAASA,QAAO,YAAY;AAC3C,kBAAM;AAAA,UACR;AACA,cAAI,mBAAmB,QAAW;AAChC,kBAAM,0BAA0B,QAC5B,iBACA,IAAI,MAAM,2BAA2B,EAAE,OAAO,eAAe,CAAC;AAAA,UACpE;AAAA,QACF,GAAG;AAAA,MACL;AAEA,YAAM,SAAS,MAAM,aAAa;AAAA,QAChC;AAAA,QACA,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,OAAO;AAAA,IAChB;AAAA,EACF;AACF;","names":["result"]}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
// src/device-network/memoryDeviceNetworkService.ts
|
|
2
|
+
var emptyCapabilities = {
|
|
3
|
+
tools: [],
|
|
4
|
+
mcpServers: [],
|
|
5
|
+
hasWiki: false,
|
|
6
|
+
agentLoop: false,
|
|
7
|
+
imChannels: [],
|
|
8
|
+
wikis: []
|
|
9
|
+
};
|
|
10
|
+
function toDevice(record, capabilities) {
|
|
11
|
+
return {
|
|
12
|
+
peerId: record.peerId,
|
|
13
|
+
displayName: record.deviceName,
|
|
14
|
+
platform: record.platform,
|
|
15
|
+
trustMode: record.trustMode,
|
|
16
|
+
trusted: !record.revokedAt,
|
|
17
|
+
reachability: {
|
|
18
|
+
state: record.revokedAt ? "offline" : "nearby",
|
|
19
|
+
paths: record.revokedAt ? [] : ["lan"]
|
|
20
|
+
},
|
|
21
|
+
capabilities,
|
|
22
|
+
lastSeen: record.lastSeen
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
var MemoryDeviceNetworkService = class {
|
|
26
|
+
constructor(options) {
|
|
27
|
+
this.options = options;
|
|
28
|
+
this.capabilities = options.capabilities ?? emptyCapabilities;
|
|
29
|
+
for (const record of options.trustedDevices ?? []) {
|
|
30
|
+
this.trustedDevices.set(record.peerId, record);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
started = false;
|
|
34
|
+
capabilities;
|
|
35
|
+
trustedDevices = /* @__PURE__ */ new Map();
|
|
36
|
+
pairingSessions = /* @__PURE__ */ new Map();
|
|
37
|
+
listeners = /* @__PURE__ */ new Set();
|
|
38
|
+
pairingListeners = /* @__PURE__ */ new Set();
|
|
39
|
+
async start() {
|
|
40
|
+
this.started = true;
|
|
41
|
+
this.emitDevices();
|
|
42
|
+
}
|
|
43
|
+
async stop() {
|
|
44
|
+
this.started = false;
|
|
45
|
+
this.emitDevices();
|
|
46
|
+
}
|
|
47
|
+
async getLocalDevice() {
|
|
48
|
+
return {
|
|
49
|
+
peerId: this.options.identity.peerId,
|
|
50
|
+
displayName: this.options.identity.deviceName,
|
|
51
|
+
platform: this.options.identity.platform,
|
|
52
|
+
trustMode: "local-pairing",
|
|
53
|
+
reachability: {
|
|
54
|
+
state: this.started ? "online" : "offline",
|
|
55
|
+
paths: this.started ? ["lan"] : []
|
|
56
|
+
},
|
|
57
|
+
capabilities: this.capabilities,
|
|
58
|
+
lastSeen: Date.now()
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
async listDevices() {
|
|
62
|
+
return [...this.trustedDevices.values()].map((record) => toDevice(record, emptyCapabilities));
|
|
63
|
+
}
|
|
64
|
+
observeDevices(listener) {
|
|
65
|
+
this.listeners.add(listener);
|
|
66
|
+
void this.listDevices().then(listener);
|
|
67
|
+
return () => {
|
|
68
|
+
this.listeners.delete(listener);
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
async listPairingSessions() {
|
|
72
|
+
return [...this.pairingSessions.values()];
|
|
73
|
+
}
|
|
74
|
+
observePairingSessions(listener) {
|
|
75
|
+
this.pairingListeners.add(listener);
|
|
76
|
+
void this.listPairingSessions().then(listener);
|
|
77
|
+
return () => {
|
|
78
|
+
this.pairingListeners.delete(listener);
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
async requestLocalPairing(peerId, _options = {}) {
|
|
82
|
+
const createdAt = Date.now();
|
|
83
|
+
const session = {
|
|
84
|
+
sessionId: `pairing-${this.options.identity.peerId}-${peerId}-${createdAt}`,
|
|
85
|
+
localPeerId: this.options.identity.peerId,
|
|
86
|
+
remotePeerId: peerId,
|
|
87
|
+
remotePublicKeyMultibase: "",
|
|
88
|
+
remoteDeviceName: peerId,
|
|
89
|
+
remotePlatform: "cli",
|
|
90
|
+
remoteCapabilities: emptyCapabilities,
|
|
91
|
+
remoteMultiaddrs: [],
|
|
92
|
+
direction: "outbound",
|
|
93
|
+
status: "pending",
|
|
94
|
+
confirmCode: this.confirmCode(peerId),
|
|
95
|
+
createdAt,
|
|
96
|
+
expiresAt: createdAt + 5 * 6e4
|
|
97
|
+
};
|
|
98
|
+
this.pairingSessions.set(session.sessionId, session);
|
|
99
|
+
this.emitPairingSessions();
|
|
100
|
+
return session;
|
|
101
|
+
}
|
|
102
|
+
async acceptPairing(sessionId) {
|
|
103
|
+
const session = this.pairingSessions.get(sessionId);
|
|
104
|
+
if (!session) throw new Error("pairing_session_not_found");
|
|
105
|
+
if (session.expiresAt < Date.now()) throw new Error("pairing_session_expired");
|
|
106
|
+
if (session.status !== "pending") throw new Error("pairing_session_not_pending");
|
|
107
|
+
this.trustedDevices.set(session.remotePeerId, {
|
|
108
|
+
peerId: session.remotePeerId,
|
|
109
|
+
publicKeyMultibase: session.remotePublicKeyMultibase,
|
|
110
|
+
deviceName: session.remoteDeviceName,
|
|
111
|
+
platform: session.remotePlatform,
|
|
112
|
+
trustMode: "local-pairing",
|
|
113
|
+
createdAt: Date.now(),
|
|
114
|
+
lastSeen: Date.now()
|
|
115
|
+
});
|
|
116
|
+
session.status = "accepted";
|
|
117
|
+
this.emitPairingSessions();
|
|
118
|
+
this.emitDevices();
|
|
119
|
+
}
|
|
120
|
+
async rejectPairing(sessionId) {
|
|
121
|
+
const session = this.pairingSessions.get(sessionId);
|
|
122
|
+
if (!session) return;
|
|
123
|
+
session.status = "rejected";
|
|
124
|
+
this.emitPairingSessions();
|
|
125
|
+
}
|
|
126
|
+
async removeTrustedDevice(peerId) {
|
|
127
|
+
this.trustedDevices.delete(peerId);
|
|
128
|
+
this.emitDevices();
|
|
129
|
+
}
|
|
130
|
+
async openStream(peerId, _protocol, _presentedGrant) {
|
|
131
|
+
if (!this.trustedDevices.has(peerId)) throw new Error("device_not_trusted");
|
|
132
|
+
return {
|
|
133
|
+
source: (async function* emptySource() {
|
|
134
|
+
})(),
|
|
135
|
+
async sink() {
|
|
136
|
+
},
|
|
137
|
+
async close() {
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
async sendRpc(peerId, _method, _parameters, _presentedGrant) {
|
|
142
|
+
if (!this.trustedDevices.has(peerId)) throw new Error("device_not_trusted");
|
|
143
|
+
throw new Error("rpc_handler_not_registered");
|
|
144
|
+
}
|
|
145
|
+
async syncWithDevice(peerId, _presentedGrant) {
|
|
146
|
+
if (!this.trustedDevices.has(peerId)) throw new Error("device_not_trusted");
|
|
147
|
+
return { ok: true, peerId, syncedAt: Date.now() };
|
|
148
|
+
}
|
|
149
|
+
confirmCode(peerId) {
|
|
150
|
+
const input = `${this.options.identity.peerId}:${peerId}`;
|
|
151
|
+
let hash = 0;
|
|
152
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
153
|
+
hash = hash * 31 + input.charCodeAt(index) >>> 0;
|
|
154
|
+
}
|
|
155
|
+
return (hash % 1e6).toString().padStart(6, "0");
|
|
156
|
+
}
|
|
157
|
+
emitDevices() {
|
|
158
|
+
void this.listDevices().then((devices) => {
|
|
159
|
+
for (const listener of this.listeners) listener(devices);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
emitPairingSessions() {
|
|
163
|
+
void this.listPairingSessions().then((sessions) => {
|
|
164
|
+
for (const listener of this.pairingListeners) listener(sessions);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// src/device-network/syncCloudDevices.ts
|
|
170
|
+
async function syncCloudDevices(input) {
|
|
171
|
+
const cloudDevices = await input.cloudClient.listDevices();
|
|
172
|
+
if (cloudDevices.length === 0) return [];
|
|
173
|
+
const existingRecords = await input.trustStore.loadTrustedDevices();
|
|
174
|
+
const existingByPeerId = new Map(existingRecords.map((r) => [r.peerId, r]));
|
|
175
|
+
for (const cloudDevice of cloudDevices) {
|
|
176
|
+
const existing = existingByPeerId.get(cloudDevice.peerId);
|
|
177
|
+
const record = {
|
|
178
|
+
peerId: cloudDevice.peerId,
|
|
179
|
+
publicKeyMultibase: cloudDevice.publicKeyMultibase,
|
|
180
|
+
deviceName: cloudDevice.deviceName,
|
|
181
|
+
platform: cloudDevice.platform,
|
|
182
|
+
trustMode: "cloud-account",
|
|
183
|
+
accountId: cloudDevice.accountId,
|
|
184
|
+
createdAt: existing?.createdAt ?? Date.now(),
|
|
185
|
+
lastSeen: cloudDevice.lastSeen,
|
|
186
|
+
revokedAt: cloudDevice.revokedAt
|
|
187
|
+
};
|
|
188
|
+
if (existing) {
|
|
189
|
+
existing.lastSeen = cloudDevice.lastSeen;
|
|
190
|
+
existing.revokedAt = cloudDevice.revokedAt;
|
|
191
|
+
if (existing.publicKeyMultibase !== record.publicKeyMultibase || existing.deviceName !== record.deviceName || existing.platform !== record.platform) {
|
|
192
|
+
await input.trustStore.saveTrustedDevice(record);
|
|
193
|
+
}
|
|
194
|
+
} else {
|
|
195
|
+
await input.trustStore.saveTrustedDevice(record);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return cloudDevices;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export {
|
|
202
|
+
MemoryDeviceNetworkService,
|
|
203
|
+
syncCloudDevices
|
|
204
|
+
};
|
|
205
|
+
//# sourceMappingURL=chunk-MRKY4HGF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/device-network/memoryDeviceNetworkService.ts","../src/device-network/syncCloudDevices.ts"],"sourcesContent":["import type {\n Device,\n DeviceCapabilities,\n DeviceConnectionGrant,\n DeviceNetworkService,\n LocalDeviceIdentity,\n LocalPairingRequestOptions,\n MemeLoopDuplexStream,\n MemeLoopProtocol,\n PairingSession,\n SyncResult,\n TrustedDeviceRecord,\n} from './types.js';\n\nexport interface MemoryDeviceNetworkServiceOptions {\n identity: LocalDeviceIdentity;\n capabilities?: DeviceCapabilities;\n trustedDevices?: TrustedDeviceRecord[];\n}\n\nconst emptyCapabilities: DeviceCapabilities = {\n tools: [],\n mcpServers: [],\n hasWiki: false,\n agentLoop: false,\n imChannels: [],\n wikis: [],\n};\n\nfunction toDevice(record: TrustedDeviceRecord, capabilities: DeviceCapabilities): Device {\n return {\n peerId: record.peerId,\n displayName: record.deviceName,\n platform: record.platform,\n trustMode: record.trustMode,\n trusted: !record.revokedAt,\n reachability: {\n state: record.revokedAt ? 'offline' : 'nearby',\n paths: record.revokedAt ? [] : ['lan'],\n },\n capabilities,\n lastSeen: record.lastSeen,\n };\n}\n\nexport class MemoryDeviceNetworkService implements DeviceNetworkService {\n private started = false;\n private readonly capabilities: DeviceCapabilities;\n private readonly trustedDevices = new Map<string, TrustedDeviceRecord>();\n private readonly pairingSessions = new Map<string, PairingSession>();\n private readonly listeners = new Set<(devices: Device[]) => void>();\n private readonly pairingListeners = new Set<(sessions: PairingSession[]) => void>();\n\n constructor(private readonly options: MemoryDeviceNetworkServiceOptions) {\n this.capabilities = options.capabilities ?? emptyCapabilities;\n for (const record of options.trustedDevices ?? []) {\n this.trustedDevices.set(record.peerId, record);\n }\n }\n\n public async start(): Promise<void> {\n this.started = true;\n this.emitDevices();\n }\n\n public async stop(): Promise<void> {\n this.started = false;\n this.emitDevices();\n }\n\n public async getLocalDevice(): Promise<Device> {\n return {\n peerId: this.options.identity.peerId,\n displayName: this.options.identity.deviceName,\n platform: this.options.identity.platform,\n trustMode: 'local-pairing',\n reachability: {\n state: this.started ? 'online' : 'offline',\n paths: this.started ? ['lan'] : [],\n },\n capabilities: this.capabilities,\n lastSeen: Date.now(),\n };\n }\n\n public async listDevices(): Promise<Device[]> {\n return [...this.trustedDevices.values()].map((record) => toDevice(record, emptyCapabilities));\n }\n\n public observeDevices(listener: (devices: Device[]) => void): () => void {\n this.listeners.add(listener);\n void this.listDevices().then(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n public async listPairingSessions(): Promise<PairingSession[]> {\n return [...this.pairingSessions.values()];\n }\n\n public observePairingSessions(listener: (sessions: PairingSession[]) => void): () => void {\n this.pairingListeners.add(listener);\n void this.listPairingSessions().then(listener);\n return () => {\n this.pairingListeners.delete(listener);\n };\n }\n\n public async requestLocalPairing(peerId: string, _options: LocalPairingRequestOptions = {}): Promise<PairingSession> {\n const createdAt = Date.now();\n const session: PairingSession = {\n sessionId: `pairing-${this.options.identity.peerId}-${peerId}-${createdAt}`,\n localPeerId: this.options.identity.peerId,\n remotePeerId: peerId,\n remotePublicKeyMultibase: '',\n remoteDeviceName: peerId,\n remotePlatform: 'cli',\n remoteCapabilities: emptyCapabilities,\n remoteMultiaddrs: [],\n direction: 'outbound',\n status: 'pending',\n confirmCode: this.confirmCode(peerId),\n createdAt,\n expiresAt: createdAt + 5 * 60_000,\n };\n this.pairingSessions.set(session.sessionId, session);\n this.emitPairingSessions();\n return session;\n }\n\n public async acceptPairing(sessionId: string): Promise<void> {\n const session = this.pairingSessions.get(sessionId);\n if (!session) throw new Error('pairing_session_not_found');\n if (session.expiresAt < Date.now()) throw new Error('pairing_session_expired');\n if (session.status !== 'pending') throw new Error('pairing_session_not_pending');\n this.trustedDevices.set(session.remotePeerId, {\n peerId: session.remotePeerId,\n publicKeyMultibase: session.remotePublicKeyMultibase,\n deviceName: session.remoteDeviceName,\n platform: session.remotePlatform,\n trustMode: 'local-pairing',\n createdAt: Date.now(),\n lastSeen: Date.now(),\n });\n session.status = 'accepted';\n this.emitPairingSessions();\n this.emitDevices();\n }\n\n public async rejectPairing(sessionId: string): Promise<void> {\n const session = this.pairingSessions.get(sessionId);\n if (!session) return;\n session.status = 'rejected';\n this.emitPairingSessions();\n }\n\n public async removeTrustedDevice(peerId: string): Promise<void> {\n this.trustedDevices.delete(peerId);\n this.emitDevices();\n }\n\n public async openStream(\n peerId: string,\n _protocol: MemeLoopProtocol,\n _presentedGrant?: DeviceConnectionGrant,\n ): Promise<MemeLoopDuplexStream> {\n if (!this.trustedDevices.has(peerId)) throw new Error('device_not_trusted');\n return {\n source: (async function* emptySource() {})(),\n async sink() {},\n async close() {},\n };\n }\n\n public async sendRpc<T>(\n peerId: string,\n _method: string,\n _parameters: unknown,\n _presentedGrant?: DeviceConnectionGrant,\n ): Promise<T> {\n if (!this.trustedDevices.has(peerId)) throw new Error('device_not_trusted');\n throw new Error('rpc_handler_not_registered');\n }\n\n public async syncWithDevice(peerId: string, _presentedGrant?: DeviceConnectionGrant): Promise<SyncResult> {\n if (!this.trustedDevices.has(peerId)) throw new Error('device_not_trusted');\n return { ok: true, peerId, syncedAt: Date.now() };\n }\n\n private confirmCode(peerId: string): string {\n const input = `${this.options.identity.peerId}:${peerId}`;\n let hash = 0;\n for (let index = 0; index < input.length; index += 1) {\n hash = (hash * 31 + input.charCodeAt(index)) >>> 0;\n }\n return (hash % 1_000_000).toString().padStart(6, '0');\n }\n\n private emitDevices(): void {\n void this.listDevices().then((devices) => {\n for (const listener of this.listeners) listener(devices);\n });\n }\n\n private emitPairingSessions(): void {\n void this.listPairingSessions().then((sessions) => {\n for (const listener of this.pairingListeners) listener(sessions);\n });\n }\n}\n","import type { CloudDeviceClient, CloudDeviceRecord, DeviceTrustStore, TrustedDeviceRecord } from './types.js';\n\n/**\n * Fetch visible cloud devices and merge them into the local trust store.\n * - Cloud devices become trusted with trustMode = \"cloud-account\".\n * - Already-trusted devices are updated (capabilities, lastSeen, multiaddrs).\n * - Revoked cloud devices are NOT removed from local trust store here\n * (revocation should be handled via heartbeat/grant failure).\n * - Returns the synced cloud device records for caller to emit as discovered devices.\n */\nexport async function syncCloudDevices(input: {\n cloudClient: CloudDeviceClient;\n trustStore: DeviceTrustStore;\n}): Promise<CloudDeviceRecord[]> {\n const cloudDevices = await input.cloudClient.listDevices();\n\n if (cloudDevices.length === 0) return [];\n\n const existingRecords = await input.trustStore.loadTrustedDevices();\n const existingByPeerId = new Map(existingRecords.map((r) => [r.peerId, r]));\n\n for (const cloudDevice of cloudDevices) {\n const existing = existingByPeerId.get(cloudDevice.peerId);\n\n const record: TrustedDeviceRecord = {\n peerId: cloudDevice.peerId,\n publicKeyMultibase: cloudDevice.publicKeyMultibase,\n deviceName: cloudDevice.deviceName,\n platform: cloudDevice.platform,\n trustMode: 'cloud-account',\n accountId: cloudDevice.accountId,\n createdAt: existing?.createdAt ?? Date.now(),\n lastSeen: cloudDevice.lastSeen,\n revokedAt: cloudDevice.revokedAt,\n };\n\n if (existing) {\n // Update mutable fields while preserving trust mode\n existing.lastSeen = cloudDevice.lastSeen;\n existing.revokedAt = cloudDevice.revokedAt;\n // If the device is already trusted via cloud-account, skip persisting again\n // unless key fields changed\n if (\n existing.publicKeyMultibase !== record.publicKeyMultibase ||\n existing.deviceName !== record.deviceName ||\n existing.platform !== record.platform\n ) {\n await input.trustStore.saveTrustedDevice(record);\n }\n } else {\n await input.trustStore.saveTrustedDevice(record);\n }\n }\n\n return cloudDevices;\n}\n"],"mappings":"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","names":[]}
|