@aithos/sdk 0.1.0-alpha.5 → 0.1.0-alpha.50
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 +245 -7
- package/dist/src/apps.d.ts +224 -0
- package/dist/src/apps.js +432 -0
- package/dist/src/assets.d.ts +208 -0
- package/dist/src/assets.js +534 -0
- package/dist/src/auth-api.d.ts +219 -0
- package/dist/src/auth-api.js +248 -0
- package/dist/src/auth.d.ts +543 -0
- package/dist/src/auth.js +937 -31
- package/dist/src/compute.d.ts +464 -6
- package/dist/src/compute.js +746 -20
- package/dist/src/data-schema-contacts-v1.d.ts +14 -0
- package/dist/src/data-schema-contacts-v1.js +28 -0
- package/dist/src/data.d.ts +342 -0
- package/dist/src/data.js +1002 -0
- package/dist/src/endpoints.d.ts +18 -0
- package/dist/src/endpoints.js +6 -0
- package/dist/src/ethos.d.ts +85 -0
- package/dist/src/ethos.js +463 -7
- package/dist/src/index.d.ts +17 -6
- package/dist/src/index.js +25 -3
- package/dist/src/internal/delegate-bundle.js +7 -2
- package/dist/src/internal/envelope.d.ts +93 -0
- package/dist/src/internal/envelope.js +59 -0
- package/dist/src/mandates.d.ts +111 -2
- package/dist/src/mandates.js +150 -7
- package/dist/src/react/AithosAsset.d.ts +66 -0
- package/dist/src/react/AithosAsset.js +67 -0
- package/dist/src/react/context.d.ts +29 -0
- package/dist/src/react/context.js +31 -0
- package/dist/src/react/index.d.ts +29 -0
- package/dist/src/react/index.js +31 -0
- package/dist/src/react/use-aithos-asset.d.ts +39 -0
- package/dist/src/react/use-aithos-asset.js +118 -0
- package/dist/src/react/use-transcribe-pending.d.ts +21 -0
- package/dist/src/react/use-transcribe-pending.js +47 -0
- package/dist/src/sdk.d.ts +10 -0
- package/dist/src/sdk.js +22 -0
- package/dist/src/transcribe-resilience.d.ts +57 -0
- package/dist/src/transcribe-resilience.js +203 -0
- package/dist/src/web.d.ts +279 -0
- package/dist/src/web.js +186 -0
- package/dist/test/auth-j3.test.js +32 -1
- package/dist/test/canonical-conformance.test.d.ts +2 -0
- package/dist/test/canonical-conformance.test.js +86 -0
- package/dist/test/compute-delegate-path.test.d.ts +2 -0
- package/dist/test/compute-delegate-path.test.js +183 -0
- package/dist/test/compute.test.js +4 -0
- package/dist/test/endpoints.test.js +25 -1
- package/dist/test/envelope-core-conformance.test.d.ts +2 -0
- package/dist/test/envelope-core-conformance.test.js +75 -0
- package/dist/test/envelope.test.d.ts +2 -0
- package/dist/test/envelope.test.js +318 -0
- package/dist/test/ethos-first-edition.test.d.ts +2 -0
- package/dist/test/ethos-first-edition.test.js +371 -0
- package/dist/test/mandates-compute.test.d.ts +2 -0
- package/dist/test/mandates-compute.test.js +256 -0
- package/dist/test/sdk.test.js +10 -2
- package/dist/test/signup-bootstrap.test.d.ts +2 -0
- package/dist/test/signup-bootstrap.test.js +311 -0
- package/dist/test/transcribe-invoke.test.d.ts +2 -0
- package/dist/test/transcribe-invoke.test.js +204 -0
- package/dist/test/transcribe.test.d.ts +2 -0
- package/dist/test/transcribe.test.js +186 -0
- package/dist/test/web.test.d.ts +2 -0
- package/dist/test/web.test.js +270 -0
- package/package.json +20 -3
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
// Copyright 2026 Mathieu Colla
|
|
4
|
+
/**
|
|
5
|
+
* React context for the Aithos assets client.
|
|
6
|
+
*
|
|
7
|
+
* App roots wrap their tree with `<AssetsClientProvider client={sdk.assets}>`
|
|
8
|
+
* once, then child components use `<AithosAsset urn="..." />` (or the
|
|
9
|
+
* `useAithosAsset` hook) without having to thread the client through
|
|
10
|
+
* props.
|
|
11
|
+
*/
|
|
12
|
+
import { createContext, useContext } from "react";
|
|
13
|
+
const AssetsClientContext = createContext(null);
|
|
14
|
+
/**
|
|
15
|
+
* Provider that exposes an {@link AssetsClient} to descendants.
|
|
16
|
+
*
|
|
17
|
+
* Typical placement: as high in the React tree as the authenticated
|
|
18
|
+
* session lives (e.g. inside the auth boundary).
|
|
19
|
+
*/
|
|
20
|
+
export function AssetsClientProvider(props) {
|
|
21
|
+
return (_jsx(AssetsClientContext.Provider, { value: props.client, children: props.children }));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Return the {@link AssetsClient} from the nearest provider, or `null`
|
|
25
|
+
* if no provider is present. Components SHOULD accept an override via
|
|
26
|
+
* an explicit `client` prop and fall back to this hook when omitted.
|
|
27
|
+
*/
|
|
28
|
+
export function useAssetsClient() {
|
|
29
|
+
return useContext(AssetsClientContext);
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@aithos/sdk/react` — React bindings for the Aithos SDK.
|
|
3
|
+
*
|
|
4
|
+
* Drop-in components and hooks for displaying Aithos-hosted assets in
|
|
5
|
+
* React applications. The package's only peer dependency beyond
|
|
6
|
+
* `@aithos/sdk` itself is `react` (^18 || ^19).
|
|
7
|
+
*
|
|
8
|
+
* Quick start:
|
|
9
|
+
*
|
|
10
|
+
* // 1. Wrap your tree once
|
|
11
|
+
* <AssetsClientProvider client={sdk.assets}>
|
|
12
|
+
* <App />
|
|
13
|
+
* </AssetsClientProvider>
|
|
14
|
+
*
|
|
15
|
+
* // 2. Use anywhere
|
|
16
|
+
* <AithosAsset urn={cv.urn} alt="CV" className="w-full" />
|
|
17
|
+
* <AithosAsset urn={video.urn} as="video" controls />
|
|
18
|
+
* <AithosAsset urn={pdf.urn} as="download" filename="cv.pdf">
|
|
19
|
+
* Download my CV
|
|
20
|
+
* </AithosAsset>
|
|
21
|
+
*
|
|
22
|
+
* // 3. Or use the hook directly for custom rendering
|
|
23
|
+
* const { url, bytes, loading, error } = useAithosAsset(urn);
|
|
24
|
+
*/
|
|
25
|
+
export { AssetsClientProvider, useAssetsClient, type AssetsClientProviderProps, } from "./context.js";
|
|
26
|
+
export { useAithosAsset, type UseAithosAssetState, type UseAithosAssetOptions, } from "./use-aithos-asset.js";
|
|
27
|
+
export { AithosAsset, type AithosAssetProps, type AithosImageProps, type AithosVideoProps, type AithosAudioProps, type AithosDownloadProps, } from "./AithosAsset.js";
|
|
28
|
+
export { useAithosTranscribePendingJobs, type UseAithosTranscribePendingJobs, } from "./use-transcribe-pending.js";
|
|
29
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Mathieu Colla
|
|
3
|
+
/**
|
|
4
|
+
* `@aithos/sdk/react` — React bindings for the Aithos SDK.
|
|
5
|
+
*
|
|
6
|
+
* Drop-in components and hooks for displaying Aithos-hosted assets in
|
|
7
|
+
* React applications. The package's only peer dependency beyond
|
|
8
|
+
* `@aithos/sdk` itself is `react` (^18 || ^19).
|
|
9
|
+
*
|
|
10
|
+
* Quick start:
|
|
11
|
+
*
|
|
12
|
+
* // 1. Wrap your tree once
|
|
13
|
+
* <AssetsClientProvider client={sdk.assets}>
|
|
14
|
+
* <App />
|
|
15
|
+
* </AssetsClientProvider>
|
|
16
|
+
*
|
|
17
|
+
* // 2. Use anywhere
|
|
18
|
+
* <AithosAsset urn={cv.urn} alt="CV" className="w-full" />
|
|
19
|
+
* <AithosAsset urn={video.urn} as="video" controls />
|
|
20
|
+
* <AithosAsset urn={pdf.urn} as="download" filename="cv.pdf">
|
|
21
|
+
* Download my CV
|
|
22
|
+
* </AithosAsset>
|
|
23
|
+
*
|
|
24
|
+
* // 3. Or use the hook directly for custom rendering
|
|
25
|
+
* const { url, bytes, loading, error } = useAithosAsset(urn);
|
|
26
|
+
*/
|
|
27
|
+
export { AssetsClientProvider, useAssetsClient, } from "./context.js";
|
|
28
|
+
export { useAithosAsset, } from "./use-aithos-asset.js";
|
|
29
|
+
export { AithosAsset, } from "./AithosAsset.js";
|
|
30
|
+
export { useAithosTranscribePendingJobs, } from "./use-transcribe-pending.js";
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AssetsClient } from "../assets.js";
|
|
2
|
+
export interface UseAithosAssetState {
|
|
3
|
+
/** A `blob:` URL pointing at the decrypted plaintext. Use in <img src=…> etc. */
|
|
4
|
+
readonly url: string | null;
|
|
5
|
+
/** Raw decrypted bytes. Use when you need the binary itself (e.g. PDF viewer). */
|
|
6
|
+
readonly bytes: Uint8Array | null;
|
|
7
|
+
/** IANA media type — useful for routing rendering. */
|
|
8
|
+
readonly mediaType: string | null;
|
|
9
|
+
/** Plaintext size in bytes. */
|
|
10
|
+
readonly sizeBytes: number | null;
|
|
11
|
+
/** True while the fetch+decrypt is in flight. */
|
|
12
|
+
readonly loading: boolean;
|
|
13
|
+
/** Non-null when the fetch/decrypt failed. */
|
|
14
|
+
readonly error: Error | null;
|
|
15
|
+
}
|
|
16
|
+
export interface UseAithosAssetOptions {
|
|
17
|
+
/** Override the client from context. Useful for tests. */
|
|
18
|
+
readonly client?: AssetsClient | null;
|
|
19
|
+
/**
|
|
20
|
+
* If `true`, the hook keeps the previous blob URL visible while a
|
|
21
|
+
* new URN is being fetched, instead of flashing `null`. Default
|
|
22
|
+
* `false` (more predictable, less visual stutter avoidance).
|
|
23
|
+
*/
|
|
24
|
+
readonly keepPreviousOnUrnChange?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Fetch + decrypt an Aithos asset and return a stable `blob:` URL.
|
|
28
|
+
*
|
|
29
|
+
* Lifecycle:
|
|
30
|
+
* - On mount or when `urn` changes, runs `client.fetch(urn)`.
|
|
31
|
+
* - On success, creates an object URL from the plaintext bytes.
|
|
32
|
+
* - On unmount or before refetching, revokes the URL to free memory.
|
|
33
|
+
* - Cancels in-flight fetches if the URN changes mid-flight.
|
|
34
|
+
*
|
|
35
|
+
* Throws (via `error`) when no client is available — supply one via
|
|
36
|
+
* `<AssetsClientProvider>` or the `client` option.
|
|
37
|
+
*/
|
|
38
|
+
export declare function useAithosAsset(urn: string | null | undefined, options?: UseAithosAssetOptions): UseAithosAssetState;
|
|
39
|
+
//# sourceMappingURL=use-aithos-asset.d.ts.map
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Mathieu Colla
|
|
3
|
+
/**
|
|
4
|
+
* `useAithosAsset(urn)` — React hook that fetches an asset and exposes
|
|
5
|
+
* it as a browser-consumable `blob:` URL, with full lifecycle
|
|
6
|
+
* management (revoke on unmount, race-cancel on URN change, error
|
|
7
|
+
* surfacing).
|
|
8
|
+
*
|
|
9
|
+
* For most UIs the higher-level `<AithosAsset>` component is enough.
|
|
10
|
+
* Reach for this hook directly when you want to feed the bytes or the
|
|
11
|
+
* blob URL to a non-`<img>`/`<video>`/`<audio>` consumer — e.g. an
|
|
12
|
+
* inline CSS `background-image`, a Canvas, a custom PDF viewer.
|
|
13
|
+
*/
|
|
14
|
+
import { useEffect, useState } from "react";
|
|
15
|
+
import { useAssetsClient } from "./context.js";
|
|
16
|
+
/**
|
|
17
|
+
* Fetch + decrypt an Aithos asset and return a stable `blob:` URL.
|
|
18
|
+
*
|
|
19
|
+
* Lifecycle:
|
|
20
|
+
* - On mount or when `urn` changes, runs `client.fetch(urn)`.
|
|
21
|
+
* - On success, creates an object URL from the plaintext bytes.
|
|
22
|
+
* - On unmount or before refetching, revokes the URL to free memory.
|
|
23
|
+
* - Cancels in-flight fetches if the URN changes mid-flight.
|
|
24
|
+
*
|
|
25
|
+
* Throws (via `error`) when no client is available — supply one via
|
|
26
|
+
* `<AssetsClientProvider>` or the `client` option.
|
|
27
|
+
*/
|
|
28
|
+
export function useAithosAsset(urn, options = {}) {
|
|
29
|
+
const contextClient = useAssetsClient();
|
|
30
|
+
const client = options.client ?? contextClient;
|
|
31
|
+
const [state, setState] = useState({
|
|
32
|
+
url: null,
|
|
33
|
+
bytes: null,
|
|
34
|
+
mediaType: null,
|
|
35
|
+
sizeBytes: null,
|
|
36
|
+
loading: !!urn,
|
|
37
|
+
error: null,
|
|
38
|
+
});
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (!urn) {
|
|
41
|
+
setState({
|
|
42
|
+
url: null,
|
|
43
|
+
bytes: null,
|
|
44
|
+
mediaType: null,
|
|
45
|
+
sizeBytes: null,
|
|
46
|
+
loading: false,
|
|
47
|
+
error: null,
|
|
48
|
+
});
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (!client) {
|
|
52
|
+
setState({
|
|
53
|
+
url: null,
|
|
54
|
+
bytes: null,
|
|
55
|
+
mediaType: null,
|
|
56
|
+
sizeBytes: null,
|
|
57
|
+
loading: false,
|
|
58
|
+
error: new Error("useAithosAsset: no AssetsClient available — wrap your tree with <AssetsClientProvider> or pass the `client` option"),
|
|
59
|
+
});
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
let cancelled = false;
|
|
63
|
+
let createdUrl = null;
|
|
64
|
+
setState((prev) => options.keepPreviousOnUrnChange
|
|
65
|
+
? { ...prev, loading: true, error: null }
|
|
66
|
+
: {
|
|
67
|
+
url: null,
|
|
68
|
+
bytes: null,
|
|
69
|
+
mediaType: null,
|
|
70
|
+
sizeBytes: null,
|
|
71
|
+
loading: true,
|
|
72
|
+
error: null,
|
|
73
|
+
});
|
|
74
|
+
(async () => {
|
|
75
|
+
try {
|
|
76
|
+
const result = await client.fetch(urn);
|
|
77
|
+
if (cancelled)
|
|
78
|
+
return;
|
|
79
|
+
// Construct the blob: URL the DOM can consume.
|
|
80
|
+
// The `as BlobPart` cast is needed because @types/node and
|
|
81
|
+
// lib.dom disagree on whether Uint8Array's backing buffer is
|
|
82
|
+
// always ArrayBuffer (vs SharedArrayBuffer). The runtime
|
|
83
|
+
// accepts our Uint8Array unconditionally.
|
|
84
|
+
const blob = new Blob([result.bytes], {
|
|
85
|
+
type: result.mediaType,
|
|
86
|
+
});
|
|
87
|
+
createdUrl = URL.createObjectURL(blob);
|
|
88
|
+
setState({
|
|
89
|
+
url: createdUrl,
|
|
90
|
+
bytes: result.bytes,
|
|
91
|
+
mediaType: result.mediaType,
|
|
92
|
+
sizeBytes: result.sizeBytes,
|
|
93
|
+
loading: false,
|
|
94
|
+
error: null,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
if (cancelled)
|
|
99
|
+
return;
|
|
100
|
+
setState({
|
|
101
|
+
url: null,
|
|
102
|
+
bytes: null,
|
|
103
|
+
mediaType: null,
|
|
104
|
+
sizeBytes: null,
|
|
105
|
+
loading: false,
|
|
106
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
})();
|
|
110
|
+
return () => {
|
|
111
|
+
cancelled = true;
|
|
112
|
+
if (createdUrl)
|
|
113
|
+
URL.revokeObjectURL(createdUrl);
|
|
114
|
+
};
|
|
115
|
+
}, [urn, client, options.keepPreviousOnUrnChange]);
|
|
116
|
+
return state;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=use-aithos-asset.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ComputeNamespace, InvokeTranscribeResult, TranscribeProgressState } from "../compute.js";
|
|
2
|
+
import type { LocalPendingEntry } from "../transcribe-resilience.js";
|
|
3
|
+
export interface UseAithosTranscribePendingJobs {
|
|
4
|
+
/** Locally-tracked in-flight jobs (survives reloads via localStorage). */
|
|
5
|
+
readonly pending: readonly LocalPendingEntry[];
|
|
6
|
+
/** Resume polling a job by id; resolves with the final transcript. */
|
|
7
|
+
readonly resume: (jobId: string, opts?: {
|
|
8
|
+
readonly mandateId?: string;
|
|
9
|
+
readonly onProgress?: (state: TranscribeProgressState) => void;
|
|
10
|
+
readonly signal?: AbortSignal;
|
|
11
|
+
readonly pollIntervalMs?: number;
|
|
12
|
+
}) => Promise<InvokeTranscribeResult>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Subscribe a React component to the SDK's local pending-transcription
|
|
16
|
+
* registry. Re-renders whenever a job is added, advances, or clears.
|
|
17
|
+
*
|
|
18
|
+
* @param compute the SDK compute namespace (`sdk.compute`).
|
|
19
|
+
*/
|
|
20
|
+
export declare function useAithosTranscribePendingJobs(compute: ComputeNamespace): UseAithosTranscribePendingJobs;
|
|
21
|
+
//# sourceMappingURL=use-transcribe-pending.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Mathieu Colla
|
|
3
|
+
/**
|
|
4
|
+
* `useAithosTranscribePendingJobs(sdk.compute)` — a thin React adapter over
|
|
5
|
+
* the framework-agnostic local pending-jobs tracker exposed by the compute
|
|
6
|
+
* namespace. The tracker itself (subscribe/getSnapshot) is plain vanilla JS
|
|
7
|
+
* and works with any framework; this hook just wires it into React's
|
|
8
|
+
* `useSyncExternalStore`. Vue/Svelte/vanilla users can call
|
|
9
|
+
* `sdk.compute.subscribeLocalPendingTranscribes` directly.
|
|
10
|
+
*
|
|
11
|
+
* function PendingBanner({ sdk }) {
|
|
12
|
+
* const { pending, resume } = useAithosTranscribePendingJobs(sdk.compute);
|
|
13
|
+
* if (pending.length === 0) return null;
|
|
14
|
+
* return (
|
|
15
|
+
* <div>
|
|
16
|
+
* {pending.map((p) => (
|
|
17
|
+
* <button key={p.jobId} onClick={() => resume(p.jobId)}>
|
|
18
|
+
* Resume {p.jobId} ({p.status})
|
|
19
|
+
* </button>
|
|
20
|
+
* ))}
|
|
21
|
+
* </div>
|
|
22
|
+
* );
|
|
23
|
+
* }
|
|
24
|
+
*/
|
|
25
|
+
import { useCallback, useEffect, useState } from "react";
|
|
26
|
+
/**
|
|
27
|
+
* Subscribe a React component to the SDK's local pending-transcription
|
|
28
|
+
* registry. Re-renders whenever a job is added, advances, or clears.
|
|
29
|
+
*
|
|
30
|
+
* @param compute the SDK compute namespace (`sdk.compute`).
|
|
31
|
+
*/
|
|
32
|
+
export function useAithosTranscribePendingJobs(compute) {
|
|
33
|
+
const [pending, setPending] = useState(() => compute.getLocalPendingTranscribesSnapshot());
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
// Sync immediately (the snapshot may have changed before mount) then
|
|
36
|
+
// subscribe. getSnapshot returns a stable reference between mutations,
|
|
37
|
+
// so identical states bail out of a re-render.
|
|
38
|
+
setPending(compute.getLocalPendingTranscribesSnapshot());
|
|
39
|
+
const unsubscribe = compute.subscribeLocalPendingTranscribes(() => {
|
|
40
|
+
setPending(compute.getLocalPendingTranscribesSnapshot());
|
|
41
|
+
});
|
|
42
|
+
return unsubscribe;
|
|
43
|
+
}, [compute]);
|
|
44
|
+
const resume = useCallback((jobId, opts) => compute.resumeTranscribe(jobId, opts), [compute]);
|
|
45
|
+
return { pending, resume };
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=use-transcribe-pending.js.map
|
package/dist/src/sdk.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { AithosAuth } from "./auth.js";
|
|
2
|
+
import { AppsNamespace } from "./apps.js";
|
|
2
3
|
import { ComputeNamespace } from "./compute.js";
|
|
3
4
|
import { type AithosSdkEndpoints } from "./endpoints.js";
|
|
4
5
|
import { EthosNamespace } from "./ethos.js";
|
|
5
6
|
import { MandatesNamespace } from "./mandates.js";
|
|
6
7
|
import { WalletNamespace } from "./wallet.js";
|
|
8
|
+
import { WebNamespace } from "./web.js";
|
|
7
9
|
export interface AithosSDKConfig {
|
|
8
10
|
/**
|
|
9
11
|
* The {@link AithosAuth} instance the SDK reads sign-in state from.
|
|
@@ -44,6 +46,14 @@ export declare class AithosSDK {
|
|
|
44
46
|
readonly ethos: EthosNamespace;
|
|
45
47
|
/** Mandate lifecycle namespace — create / list / revoke. */
|
|
46
48
|
readonly mandates: MandatesNamespace;
|
|
49
|
+
/** Web extraction namespace — aithos.web_extract through the web extractor proxy. */
|
|
50
|
+
readonly web: WebNamespace;
|
|
51
|
+
/**
|
|
52
|
+
* App lifecycle namespace — sponsorship mandates + app-credit top-ups.
|
|
53
|
+
* V0.1 (2026-05-27 — draft §13). Lets a developer pre-pay a pool that
|
|
54
|
+
* funds compute calls from their app's users within explicit caps.
|
|
55
|
+
*/
|
|
56
|
+
readonly apps: AppsNamespace;
|
|
47
57
|
constructor(config: AithosSDKConfig);
|
|
48
58
|
/** DID of the currently signed-in owner, or null if no owner is loaded. */
|
|
49
59
|
get userDid(): string | null;
|
package/dist/src/sdk.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright 2026 Mathieu Colla
|
|
3
|
+
import { AppsNamespace } from "./apps.js";
|
|
3
4
|
import { ComputeNamespace } from "./compute.js";
|
|
4
5
|
import { resolveEndpoints } from "./endpoints.js";
|
|
5
6
|
import { EthosNamespace } from "./ethos.js";
|
|
6
7
|
import { MandatesNamespace } from "./mandates.js";
|
|
7
8
|
import { WalletNamespace } from "./wallet.js";
|
|
9
|
+
import { WebNamespace } from "./web.js";
|
|
8
10
|
export class AithosSDK {
|
|
9
11
|
/** Resolved endpoint configuration (defaults + caller overrides). */
|
|
10
12
|
endpoints;
|
|
@@ -20,6 +22,14 @@ export class AithosSDK {
|
|
|
20
22
|
ethos;
|
|
21
23
|
/** Mandate lifecycle namespace — create / list / revoke. */
|
|
22
24
|
mandates;
|
|
25
|
+
/** Web extraction namespace — aithos.web_extract through the web extractor proxy. */
|
|
26
|
+
web;
|
|
27
|
+
/**
|
|
28
|
+
* App lifecycle namespace — sponsorship mandates + app-credit top-ups.
|
|
29
|
+
* V0.1 (2026-05-27 — draft §13). Lets a developer pre-pay a pool that
|
|
30
|
+
* funds compute calls from their app's users within explicit caps.
|
|
31
|
+
*/
|
|
32
|
+
apps;
|
|
23
33
|
constructor(config) {
|
|
24
34
|
if (!config.auth) {
|
|
25
35
|
throw new TypeError("AithosSDK: config.auth is required");
|
|
@@ -53,6 +63,18 @@ export class AithosSDK {
|
|
|
53
63
|
endpoints: this.endpoints,
|
|
54
64
|
fetch: fetchImpl,
|
|
55
65
|
});
|
|
66
|
+
this.web = new WebNamespace({
|
|
67
|
+
auth: config.auth,
|
|
68
|
+
appDid: config.appDid,
|
|
69
|
+
endpoints: this.endpoints,
|
|
70
|
+
fetch: fetchImpl,
|
|
71
|
+
});
|
|
72
|
+
this.apps = new AppsNamespace({
|
|
73
|
+
auth: config.auth,
|
|
74
|
+
appDid: config.appDid,
|
|
75
|
+
endpoints: this.endpoints,
|
|
76
|
+
fetch: fetchImpl,
|
|
77
|
+
});
|
|
56
78
|
}
|
|
57
79
|
/** DID of the currently signed-in owner, or null if no owner is loaded. */
|
|
58
80
|
get userDid() {
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export type LocalPendingStatus = "uploading" | "running" | "completed" | "failed";
|
|
2
|
+
export interface LocalPendingEntry {
|
|
3
|
+
readonly jobId: string;
|
|
4
|
+
readonly status: LocalPendingStatus;
|
|
5
|
+
readonly createdAt: number;
|
|
6
|
+
readonly updatedAt: number;
|
|
7
|
+
readonly meta?: Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Framework-agnostic observable registry of in-flight transcription jobs.
|
|
11
|
+
* Persisted to localStorage when available (so it survives reloads), with
|
|
12
|
+
* an in-memory fallback otherwise. Subscribe with `subscribe(listener)`;
|
|
13
|
+
* read with `getSnapshot()` (stable reference between mutations, so it
|
|
14
|
+
* plugs directly into React's `useSyncExternalStore`).
|
|
15
|
+
*/
|
|
16
|
+
export declare class LocalPendingTranscribeTracker {
|
|
17
|
+
#private;
|
|
18
|
+
constructor();
|
|
19
|
+
/** Current entries. Stable reference until the next mutation. */
|
|
20
|
+
getSnapshot(): readonly LocalPendingEntry[];
|
|
21
|
+
list(): readonly LocalPendingEntry[];
|
|
22
|
+
/** Subscribe to changes. Returns an unsubscribe function. */
|
|
23
|
+
subscribe(listener: () => void): () => void;
|
|
24
|
+
upsert(jobId: string, status: LocalPendingStatus, meta?: Record<string, unknown>): void;
|
|
25
|
+
remove(jobId: string): void;
|
|
26
|
+
clear(): void;
|
|
27
|
+
}
|
|
28
|
+
export interface TranscribeDraftMeta {
|
|
29
|
+
readonly title?: string;
|
|
30
|
+
readonly tag?: string;
|
|
31
|
+
readonly contentType?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface TranscribeDraftRecord {
|
|
34
|
+
readonly draftId: string;
|
|
35
|
+
readonly blob: Blob;
|
|
36
|
+
readonly metadata: TranscribeDraftMeta;
|
|
37
|
+
readonly createdAt: number;
|
|
38
|
+
}
|
|
39
|
+
export declare class TranscribeDraftUnavailableError extends Error {
|
|
40
|
+
constructor();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* IndexedDB-backed queue of recorded audio Blobs. Save a recording the
|
|
44
|
+
* instant it finishes (before any network), then `upload` it when the
|
|
45
|
+
* user confirms — so a flaky network or a closed tab never loses audio.
|
|
46
|
+
* Browser-only: methods reject with {@link TranscribeDraftUnavailableError}
|
|
47
|
+
* when IndexedDB is absent.
|
|
48
|
+
*/
|
|
49
|
+
export declare class TranscribeDraftStore {
|
|
50
|
+
save(blob: Blob, meta?: TranscribeDraftMeta): Promise<{
|
|
51
|
+
readonly draftId: string;
|
|
52
|
+
}>;
|
|
53
|
+
list(): Promise<readonly TranscribeDraftRecord[]>;
|
|
54
|
+
get(draftId: string): Promise<TranscribeDraftRecord | null>;
|
|
55
|
+
delete(draftId: string): Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=transcribe-resilience.d.ts.map
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2026 Mathieu Colla
|
|
3
|
+
const LS_KEY = "aithos:transcribe:pending";
|
|
4
|
+
/**
|
|
5
|
+
* Framework-agnostic observable registry of in-flight transcription jobs.
|
|
6
|
+
* Persisted to localStorage when available (so it survives reloads), with
|
|
7
|
+
* an in-memory fallback otherwise. Subscribe with `subscribe(listener)`;
|
|
8
|
+
* read with `getSnapshot()` (stable reference between mutations, so it
|
|
9
|
+
* plugs directly into React's `useSyncExternalStore`).
|
|
10
|
+
*/
|
|
11
|
+
export class LocalPendingTranscribeTracker {
|
|
12
|
+
#listeners = new Set();
|
|
13
|
+
#mem = [];
|
|
14
|
+
#snapshot = [];
|
|
15
|
+
constructor() {
|
|
16
|
+
this.#snapshot = this.#read();
|
|
17
|
+
// Cross-tab sync: when another tab updates the key, re-emit.
|
|
18
|
+
try {
|
|
19
|
+
if (typeof window !== "undefined" && typeof window.addEventListener === "function") {
|
|
20
|
+
window.addEventListener("storage", (e) => {
|
|
21
|
+
if (e.key === LS_KEY) {
|
|
22
|
+
this.#snapshot = this.#read();
|
|
23
|
+
this.#emit();
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
/* no window — fine */
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
#ls() {
|
|
33
|
+
try {
|
|
34
|
+
return typeof localStorage !== "undefined" ? localStorage : null;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
#read() {
|
|
41
|
+
const ls = this.#ls();
|
|
42
|
+
if (!ls)
|
|
43
|
+
return [...this.#mem];
|
|
44
|
+
try {
|
|
45
|
+
const raw = ls.getItem(LS_KEY);
|
|
46
|
+
return raw ? JSON.parse(raw) : [];
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
#write(list) {
|
|
53
|
+
const ls = this.#ls();
|
|
54
|
+
if (ls) {
|
|
55
|
+
try {
|
|
56
|
+
ls.setItem(LS_KEY, JSON.stringify(list));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
/* quota / private mode — keep in-memory copy authoritative */
|
|
60
|
+
this.#mem = list;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
this.#mem = list;
|
|
65
|
+
}
|
|
66
|
+
this.#snapshot = list;
|
|
67
|
+
this.#emit();
|
|
68
|
+
}
|
|
69
|
+
#emit() {
|
|
70
|
+
for (const l of this.#listeners)
|
|
71
|
+
l();
|
|
72
|
+
}
|
|
73
|
+
/** Current entries. Stable reference until the next mutation. */
|
|
74
|
+
getSnapshot() {
|
|
75
|
+
return this.#snapshot;
|
|
76
|
+
}
|
|
77
|
+
list() {
|
|
78
|
+
this.#snapshot = this.#read();
|
|
79
|
+
return this.#snapshot;
|
|
80
|
+
}
|
|
81
|
+
/** Subscribe to changes. Returns an unsubscribe function. */
|
|
82
|
+
subscribe(listener) {
|
|
83
|
+
this.#listeners.add(listener);
|
|
84
|
+
return () => {
|
|
85
|
+
this.#listeners.delete(listener);
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
upsert(jobId, status, meta) {
|
|
89
|
+
const now = Date.now();
|
|
90
|
+
const list = this.#read();
|
|
91
|
+
const idx = list.findIndex((e) => e.jobId === jobId);
|
|
92
|
+
if (idx >= 0) {
|
|
93
|
+
const prev = list[idx];
|
|
94
|
+
list[idx] = {
|
|
95
|
+
...prev,
|
|
96
|
+
status,
|
|
97
|
+
updatedAt: now,
|
|
98
|
+
...(meta ? { meta: { ...prev.meta, ...meta } } : {}),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
list.push({
|
|
103
|
+
jobId,
|
|
104
|
+
status,
|
|
105
|
+
createdAt: now,
|
|
106
|
+
updatedAt: now,
|
|
107
|
+
...(meta ? { meta } : {}),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
this.#write(list);
|
|
111
|
+
}
|
|
112
|
+
remove(jobId) {
|
|
113
|
+
const list = this.#read().filter((e) => e.jobId !== jobId);
|
|
114
|
+
this.#write(list);
|
|
115
|
+
}
|
|
116
|
+
clear() {
|
|
117
|
+
this.#write([]);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const DB_NAME = "aithos-transcribe";
|
|
121
|
+
const DB_VERSION = 1;
|
|
122
|
+
const STORE = "drafts";
|
|
123
|
+
export class TranscribeDraftUnavailableError extends Error {
|
|
124
|
+
constructor() {
|
|
125
|
+
super("IndexedDB is not available in this environment — the transcription draft queue is browser-only.");
|
|
126
|
+
this.name = "TranscribeDraftUnavailableError";
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function getIndexedDB() {
|
|
130
|
+
try {
|
|
131
|
+
if (typeof indexedDB !== "undefined")
|
|
132
|
+
return indexedDB;
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
/* fall through */
|
|
136
|
+
}
|
|
137
|
+
throw new TranscribeDraftUnavailableError();
|
|
138
|
+
}
|
|
139
|
+
function openDb() {
|
|
140
|
+
const idb = getIndexedDB();
|
|
141
|
+
return new Promise((resolve, reject) => {
|
|
142
|
+
const req = idb.open(DB_NAME, DB_VERSION);
|
|
143
|
+
req.onupgradeneeded = () => {
|
|
144
|
+
const db = req.result;
|
|
145
|
+
if (!db.objectStoreNames.contains(STORE)) {
|
|
146
|
+
db.createObjectStore(STORE, { keyPath: "draftId" });
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
req.onsuccess = () => resolve(req.result);
|
|
150
|
+
req.onerror = () => reject(req.error ?? new Error("indexedDB open failed"));
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
function tx(db, mode, fn) {
|
|
154
|
+
return new Promise((resolve, reject) => {
|
|
155
|
+
const t = db.transaction(STORE, mode);
|
|
156
|
+
const req = fn(t.objectStore(STORE));
|
|
157
|
+
req.onsuccess = () => resolve(req.result);
|
|
158
|
+
req.onerror = () => reject(req.error ?? new Error("indexedDB request failed"));
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* IndexedDB-backed queue of recorded audio Blobs. Save a recording the
|
|
163
|
+
* instant it finishes (before any network), then `upload` it when the
|
|
164
|
+
* user confirms — so a flaky network or a closed tab never loses audio.
|
|
165
|
+
* Browser-only: methods reject with {@link TranscribeDraftUnavailableError}
|
|
166
|
+
* when IndexedDB is absent.
|
|
167
|
+
*/
|
|
168
|
+
export class TranscribeDraftStore {
|
|
169
|
+
async save(blob, meta) {
|
|
170
|
+
const db = await openDb();
|
|
171
|
+
const draftId = `draft_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
172
|
+
const record = {
|
|
173
|
+
draftId,
|
|
174
|
+
blob,
|
|
175
|
+
metadata: {
|
|
176
|
+
...(meta ?? {}),
|
|
177
|
+
...(meta?.contentType ? {} : { contentType: blob.type || "audio/webm" }),
|
|
178
|
+
},
|
|
179
|
+
createdAt: Date.now(),
|
|
180
|
+
};
|
|
181
|
+
await tx(db, "readwrite", (s) => s.put(record));
|
|
182
|
+
db.close();
|
|
183
|
+
return { draftId };
|
|
184
|
+
}
|
|
185
|
+
async list() {
|
|
186
|
+
const db = await openDb();
|
|
187
|
+
const out = await tx(db, "readonly", (s) => s.getAll());
|
|
188
|
+
db.close();
|
|
189
|
+
return out.sort((a, b) => a.createdAt - b.createdAt);
|
|
190
|
+
}
|
|
191
|
+
async get(draftId) {
|
|
192
|
+
const db = await openDb();
|
|
193
|
+
const rec = await tx(db, "readonly", (s) => s.get(draftId));
|
|
194
|
+
db.close();
|
|
195
|
+
return rec ?? null;
|
|
196
|
+
}
|
|
197
|
+
async delete(draftId) {
|
|
198
|
+
const db = await openDb();
|
|
199
|
+
await tx(db, "readwrite", (s) => s.delete(draftId));
|
|
200
|
+
db.close();
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=transcribe-resilience.js.map
|