@abraca/orchestrator 2.34.0 → 2.35.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/dist/abracadabra-orchestrator.cjs +14 -1505
- package/dist/abracadabra-orchestrator.cjs.map +1 -1
- package/dist/abracadabra-orchestrator.esm.js +13 -1503
- package/dist/abracadabra-orchestrator.esm.js.map +1 -1
- package/package.json +2 -3
- package/src/actions/content.ts +1 -1
- package/src/actor-connection.ts +19 -35
- package/src/utils.ts +5 -37
- package/src/converters/markdownToYjs.ts +0 -932
- package/src/converters/types.ts +0 -179
- package/src/crypto.ts +0 -71
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abraca/orchestrator",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.35.1",
|
|
4
4
|
"description": "CouShell commercial director — orchestrate simulated actors on Abracadabra for screen recording",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -28,8 +28,7 @@
|
|
|
28
28
|
"dist"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@
|
|
32
|
-
"@noble/hashes": "^2.2.0"
|
|
31
|
+
"@abraca/convert": "2.35.1"
|
|
33
32
|
},
|
|
34
33
|
"peerDependencies": {
|
|
35
34
|
"@abraca/dabra": ">=1.0.0",
|
package/src/actions/content.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { ActorConnection } from '../actor-connection.ts'
|
|
8
8
|
import type { WriteContentAction, DeleteContentAction } from '../types.ts'
|
|
9
|
-
import { populateYDocFromMarkdown } from '
|
|
9
|
+
import { populateYDocFromMarkdown } from '@abraca/convert'
|
|
10
10
|
import { bodyStartIndex } from '../yjs-utils.ts'
|
|
11
11
|
|
|
12
12
|
export async function executeWriteContent(
|
package/src/actor-connection.ts
CHANGED
|
@@ -3,9 +3,16 @@
|
|
|
3
3
|
* One instance per actor. Handles auth, providers, child caching, awareness, and cursors.
|
|
4
4
|
*/
|
|
5
5
|
import * as Y from 'yjs'
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
AbracadabraProvider,
|
|
8
|
+
AbracadabraClient,
|
|
9
|
+
loadOrCreateKeyFile,
|
|
10
|
+
deterministicKeypair,
|
|
11
|
+
loginOrRegisterWithKey,
|
|
12
|
+
openSyncedProvider,
|
|
13
|
+
pickEntrySpace,
|
|
14
|
+
} from '@abraca/dabra'
|
|
7
15
|
import type { ActorDef, ServerConfig } from './types.ts'
|
|
8
|
-
import { loadOrCreateKeypair, deterministicKeypair, signChallenge } from './crypto.ts'
|
|
9
16
|
import { waitForSync, sleep, log } from './utils.ts'
|
|
10
17
|
import { findTextPosition, fragmentTextLength } from './yjs-utils.ts'
|
|
11
18
|
|
|
@@ -44,38 +51,23 @@ export class ActorConnection {
|
|
|
44
51
|
async connect(serverConfig: ServerConfig): Promise<void> {
|
|
45
52
|
// Step 1: Get keypair (from file or deterministic from name)
|
|
46
53
|
const keypair = this.actor.keyFile
|
|
47
|
-
? await
|
|
54
|
+
? await loadOrCreateKeyFile(this.actor.keyFile)
|
|
48
55
|
: deterministicKeypair(this.actor.name)
|
|
49
56
|
this._publicKey = keypair.publicKeyB64
|
|
50
|
-
const signFn = (challenge: string) =>
|
|
51
|
-
Promise.resolve(signChallenge(challenge, keypair.privateKey))
|
|
52
57
|
|
|
53
58
|
// Step 2: Auth (auto-register on first run)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
await this.client.registerWithKey({
|
|
61
|
-
publicKey: keypair.publicKeyB64,
|
|
62
|
-
username: this.actor.name.replace(/\s+/g, '-').toLowerCase(),
|
|
63
|
-
displayName: this.actor.name,
|
|
64
|
-
deviceName: 'Orchestrator Actor',
|
|
65
|
-
inviteCode: serverConfig.inviteCode,
|
|
66
|
-
})
|
|
67
|
-
await this.client.loginWithKey(keypair.publicKeyB64, signFn)
|
|
68
|
-
} else {
|
|
69
|
-
throw err
|
|
70
|
-
}
|
|
71
|
-
}
|
|
59
|
+
await loginOrRegisterWithKey(this.client, keypair, {
|
|
60
|
+
displayName: this.actor.name,
|
|
61
|
+
deviceName: 'Orchestrator Actor',
|
|
62
|
+
inviteCode: serverConfig.inviteCode,
|
|
63
|
+
onRegister: () => log(`${this.actor.name}: registering new account...`),
|
|
64
|
+
})
|
|
72
65
|
log(`${this.actor.name}: authenticated (${keypair.publicKeyB64.slice(0, 12)}...)`)
|
|
73
66
|
|
|
74
67
|
// Step 3: Pick an entry-point doc — first Space under the server root,
|
|
75
68
|
// falling back to the first top-level doc of any kind.
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
const rootDocId = (firstSpace ?? roots[0])?.id ?? null
|
|
69
|
+
const { entry } = pickEntrySpace(await this.client.listChildren())
|
|
70
|
+
const rootDocId = entry?.id ?? null
|
|
79
71
|
|
|
80
72
|
if (!rootDocId) {
|
|
81
73
|
throw new Error(`${this.actor.name}: no root document found`)
|
|
@@ -83,15 +75,7 @@ export class ActorConnection {
|
|
|
83
75
|
this._rootDocId = rootDocId
|
|
84
76
|
|
|
85
77
|
// Step 4: Connect provider
|
|
86
|
-
const doc =
|
|
87
|
-
const provider = new AbracadabraProvider({
|
|
88
|
-
name: rootDocId,
|
|
89
|
-
document: doc,
|
|
90
|
-
client: this.client,
|
|
91
|
-
disableOfflineStore: true,
|
|
92
|
-
subdocLoading: 'lazy',
|
|
93
|
-
})
|
|
94
|
-
await waitForSync(provider)
|
|
78
|
+
const { doc, provider } = await openSyncedProvider({ client: this.client, docId: rootDocId })
|
|
95
79
|
|
|
96
80
|
this._rootDoc = doc
|
|
97
81
|
this._rootProvider = provider
|
package/src/utils.ts
CHANGED
|
@@ -1,49 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Utility functions for the orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* `waitForSync` / `withTimeout` are the shared provider implementations from
|
|
5
|
+
* `@abraca/dabra` (`DocUtils`), re-exported here so existing `./utils.ts`
|
|
6
|
+
* importers keep working. `sleep` / `log` are orchestrator-local.
|
|
3
7
|
*/
|
|
4
|
-
|
|
5
|
-
/** Wait for a provider's `synced` event with a timeout. Resolves immediately if already synced. */
|
|
6
|
-
export function waitForSync(
|
|
7
|
-
provider: { on(event: string, cb: () => void): void; off(event: string, cb: () => void): void; synced?: boolean },
|
|
8
|
-
timeoutMs = 15000
|
|
9
|
-
): Promise<void> {
|
|
10
|
-
// If already synced, resolve immediately
|
|
11
|
-
if (provider.synced) return Promise.resolve()
|
|
12
|
-
|
|
13
|
-
return new Promise<void>((resolve, reject) => {
|
|
14
|
-
const timer = setTimeout(() => {
|
|
15
|
-
provider.off('synced', handler)
|
|
16
|
-
reject(new Error(`Sync timed out after ${timeoutMs}ms`))
|
|
17
|
-
}, timeoutMs)
|
|
18
|
-
|
|
19
|
-
function handler() {
|
|
20
|
-
clearTimeout(timer)
|
|
21
|
-
resolve()
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
provider.on('synced', handler)
|
|
25
|
-
})
|
|
26
|
-
}
|
|
8
|
+
export { waitForSync, withTimeout } from '@abraca/dabra'
|
|
27
9
|
|
|
28
10
|
/** Sleep for a given number of milliseconds. */
|
|
29
11
|
export function sleep(ms: number): Promise<void> {
|
|
30
12
|
return new Promise(resolve => setTimeout(resolve, ms))
|
|
31
13
|
}
|
|
32
14
|
|
|
33
|
-
/** Wraps a promise with a timeout. */
|
|
34
|
-
export function withTimeout<T>(promise: Promise<T>, timeoutMs: number, message?: string): Promise<T> {
|
|
35
|
-
return new Promise<T>((resolve, reject) => {
|
|
36
|
-
const timer = setTimeout(
|
|
37
|
-
() => reject(new Error(message ?? `Operation timed out after ${timeoutMs}ms`)),
|
|
38
|
-
timeoutMs
|
|
39
|
-
)
|
|
40
|
-
promise.then(
|
|
41
|
-
(val) => { clearTimeout(timer); resolve(val) },
|
|
42
|
-
(err) => { clearTimeout(timer); reject(err) }
|
|
43
|
-
)
|
|
44
|
-
})
|
|
45
|
-
}
|
|
46
|
-
|
|
47
15
|
/** Log to stderr with [orchestrator] prefix. */
|
|
48
16
|
export function log(msg: string): void {
|
|
49
17
|
console.error(`[orchestrator] ${msg}`)
|