pi-meta-oauth 0.2.0 → 0.2.1
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/package.json +6 -1
- package/preview.png +0 -0
- package/tests/meta.test.ts +0 -118
- package/tests/voice.test.ts +0 -55
- package/tsconfig.json +0 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-meta-oauth",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Meta Model API OAuth provider and Muse-style voice dictation for pi",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
],
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"type": "module",
|
|
16
|
+
"files": [
|
|
17
|
+
"LICENSE",
|
|
18
|
+
"README.md",
|
|
19
|
+
"extensions/"
|
|
20
|
+
],
|
|
16
21
|
"repository": {
|
|
17
22
|
"type": "git",
|
|
18
23
|
"url": "https://github.com/BlockedPath/pi-meta-oauth"
|
package/preview.png
DELETED
|
Binary file
|
package/tests/meta.test.ts
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
/// <reference types="bun-types" />
|
|
2
|
-
import { describe, expect, test } from "bun:test";
|
|
3
|
-
import {
|
|
4
|
-
loginMeta,
|
|
5
|
-
mintMetaApiKey,
|
|
6
|
-
toProviderModels,
|
|
7
|
-
} from "../extensions/meta.ts";
|
|
8
|
-
|
|
9
|
-
function jsonResponse(body: unknown, status = 200): Response {
|
|
10
|
-
return new Response(JSON.stringify(body), {
|
|
11
|
-
status,
|
|
12
|
-
headers: { "Content-Type": "application/json" },
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
describe("Meta OAuth provider", () => {
|
|
17
|
-
test("maps the Muse catalog into Pi model metadata", () => {
|
|
18
|
-
const models = toProviderModels({
|
|
19
|
-
data: [
|
|
20
|
-
{
|
|
21
|
-
id: "muse-spark-test",
|
|
22
|
-
metadata: {
|
|
23
|
-
"muse-code": {
|
|
24
|
-
name: "Muse Spark Test",
|
|
25
|
-
reasoning: true,
|
|
26
|
-
modalities: { input: ["text", "image"] },
|
|
27
|
-
limit: { context: 123_000, output: 45_000 },
|
|
28
|
-
variants: { high: { reasoningEffort: "deep" } },
|
|
29
|
-
cost: { input: "1.25", output: "4.25", cached: "0.15" },
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
{ id: "hidden", metadata: { "muse-code": { is_hidden: true } } },
|
|
34
|
-
],
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
expect(models).toHaveLength(1);
|
|
38
|
-
expect(models[0]).toMatchObject({
|
|
39
|
-
id: "muse-spark-test",
|
|
40
|
-
name: "Muse Spark Test",
|
|
41
|
-
input: ["text", "image"],
|
|
42
|
-
contextWindow: 123_000,
|
|
43
|
-
maxTokens: 45_000,
|
|
44
|
-
cost: { input: 1.25, output: 4.25, cacheRead: 0.15, cacheWrite: 0 },
|
|
45
|
-
thinkingLevelMap: { off: null, high: "deep", max: null },
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test("runs device login, polls, and mints a Model API key", async () => {
|
|
50
|
-
const requests: Array<{ url: string; authorization?: string }> = [];
|
|
51
|
-
const responses = [
|
|
52
|
-
jsonResponse({
|
|
53
|
-
device_code: "device-token",
|
|
54
|
-
user_code: "ABCD-1234",
|
|
55
|
-
verification_uri: "https://auth.meta.com/device",
|
|
56
|
-
verification_uri_complete:
|
|
57
|
-
"https://auth.meta.com/device?code=ABCD-1234",
|
|
58
|
-
expires_in: 900,
|
|
59
|
-
interval: 1,
|
|
60
|
-
}),
|
|
61
|
-
jsonResponse({ error: "authorization_pending" }, 400),
|
|
62
|
-
jsonResponse({ access_token: "identity-token" }),
|
|
63
|
-
jsonResponse({
|
|
64
|
-
api_key: "model-api-key",
|
|
65
|
-
base_url: "https://api.meta.ai/v1",
|
|
66
|
-
}),
|
|
67
|
-
];
|
|
68
|
-
const fetchMock = (async (
|
|
69
|
-
input: string | URL | Request,
|
|
70
|
-
init?: RequestInit,
|
|
71
|
-
) => {
|
|
72
|
-
const headers = new Headers(init?.headers);
|
|
73
|
-
requests.push({
|
|
74
|
-
url: String(input),
|
|
75
|
-
authorization: headers.get("Authorization") ?? undefined,
|
|
76
|
-
});
|
|
77
|
-
const response = responses.shift();
|
|
78
|
-
if (!response) throw new Error("Unexpected request");
|
|
79
|
-
return response;
|
|
80
|
-
}) as unknown as typeof fetch;
|
|
81
|
-
const deviceCodes: unknown[] = [];
|
|
82
|
-
const credentials = await loginMeta(
|
|
83
|
-
{
|
|
84
|
-
onAuth() {},
|
|
85
|
-
onDeviceCode(value: unknown) {
|
|
86
|
-
deviceCodes.push(value);
|
|
87
|
-
},
|
|
88
|
-
onPrompt: async () => "",
|
|
89
|
-
onSelect: async () => undefined,
|
|
90
|
-
},
|
|
91
|
-
fetchMock,
|
|
92
|
-
async () => {},
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
expect(deviceCodes).toEqual([
|
|
96
|
-
{
|
|
97
|
-
userCode: "ABCD-1234",
|
|
98
|
-
verificationUri: "https://auth.meta.com/device?code=ABCD-1234",
|
|
99
|
-
intervalSeconds: 1,
|
|
100
|
-
expiresInSeconds: 900,
|
|
101
|
-
},
|
|
102
|
-
]);
|
|
103
|
-
expect(credentials.refresh).toBe("identity-token");
|
|
104
|
-
expect(credentials.access).toBe("model-api-key");
|
|
105
|
-
expect(requests.at(-1)?.authorization).toBe("Bearer identity-token");
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
test("reports account setup when minting yields no API key", async () => {
|
|
109
|
-
const fetchMock = (async () =>
|
|
110
|
-
jsonResponse({
|
|
111
|
-
require_payment: true,
|
|
112
|
-
action_url: "https://dev.meta.ai/billing",
|
|
113
|
-
})) as unknown as typeof fetch;
|
|
114
|
-
await expect(mintMetaApiKey("identity-token", fetchMock)).rejects.toThrow(
|
|
115
|
-
"Complete setup at https://dev.meta.ai/billing",
|
|
116
|
-
);
|
|
117
|
-
});
|
|
118
|
-
});
|
package/tests/voice.test.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/// <reference types="bun-types" />
|
|
2
|
-
import { describe, expect, test } from "bun:test";
|
|
3
|
-
import { existsSync } from "node:fs";
|
|
4
|
-
import { dirname, join } from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
import {
|
|
7
|
-
asrEndpoint,
|
|
8
|
-
formatAuthorization,
|
|
9
|
-
pcmAudioLevel,
|
|
10
|
-
} from "../extensions/voice.ts";
|
|
11
|
-
|
|
12
|
-
describe("Meta voice mode", () => {
|
|
13
|
-
test("maps silent and audible PCM into meter levels", () => {
|
|
14
|
-
const silent = Buffer.alloc(3_200);
|
|
15
|
-
const audible = Buffer.alloc(3_200);
|
|
16
|
-
for (let offset = 0; offset < audible.length; offset += 2) {
|
|
17
|
-
audible.writeInt16LE(offset % 4 === 0 ? 8_000 : -8_000, offset);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
expect(pcmAudioLevel(silent)).toBe(0);
|
|
21
|
-
expect(pcmAudioLevel(audible)).toBeGreaterThan(0.5);
|
|
22
|
-
expect(pcmAudioLevel(audible)).toBeLessThanOrEqual(1);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test("formats the Meta ASR authorization value exactly once", () => {
|
|
26
|
-
expect(formatAuthorization("LLM|example")).toBe("OAuth LLM|example");
|
|
27
|
-
expect(formatAuthorization("OAuth LLM|example")).toBe("OAuth LLM|example");
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test("builds a secure ASR URL with a session id", () => {
|
|
31
|
-
let url: URL;
|
|
32
|
-
try {
|
|
33
|
-
url = new URL(asrEndpoint("session-123"));
|
|
34
|
-
} catch (error) {
|
|
35
|
-
throw new Error("ASR endpoint was not a valid URL", { cause: error });
|
|
36
|
-
}
|
|
37
|
-
expect(url.protocol).toBe("wss:");
|
|
38
|
-
expect(url.hostname).toBe("shortwave.facebook.com");
|
|
39
|
-
expect(url.searchParams.get("sessionId")).toBe("session-123");
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test("ships the macOS helper resources", () => {
|
|
43
|
-
const root = join(
|
|
44
|
-
dirname(fileURLToPath(import.meta.url)),
|
|
45
|
-
"../extensions/voice",
|
|
46
|
-
);
|
|
47
|
-
for (const file of [
|
|
48
|
-
"macos-audio.swift",
|
|
49
|
-
"Info.plist",
|
|
50
|
-
"Entitlements.plist",
|
|
51
|
-
]) {
|
|
52
|
-
expect(existsSync(join(root, file))).toBe(true);
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
});
|
package/tsconfig.json
DELETED