@abraca/orchestrator 2.33.0 → 2.35.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abraca/orchestrator",
3
- "version": "2.33.0",
3
+ "version": "2.35.0",
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
- "@noble/ed25519": "^3.1.0",
32
- "@noble/hashes": "^2.2.0"
31
+ "@abraca/convert": "2.35.0"
33
32
  },
34
33
  "peerDependencies": {
35
34
  "@abraca/dabra": ">=1.0.0",
@@ -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 '../converters/markdownToYjs.ts'
9
+ import { populateYDocFromMarkdown } from '@abraca/convert'
10
10
  import { bodyStartIndex } from '../yjs-utils.ts'
11
11
 
12
12
  export async function executeWriteContent(
@@ -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 { AbracadabraProvider, AbracadabraClient } from '@abraca/dabra'
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 loadOrCreateKeypair(this.actor.keyFile)
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
- try {
55
- await this.client.loginWithKey(keypair.publicKeyB64, signFn)
56
- } catch (err: any) {
57
- const status = err?.status ?? err?.response?.status
58
- if (status === 404 || status === 422) {
59
- log(`${this.actor.name}: registering new account...`)
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 roots = await this.client.listChildren()
77
- const firstSpace = roots.find((d) => d.kind === 'space')
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 = new Y.Doc({ guid: rootDocId })
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}`)