@aithos/sdk 0.1.0-alpha.26 → 0.1.0-alpha.27
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/src/ethos.d.ts +38 -0
- package/dist/src/ethos.js +92 -0
- package/package.json +1 -1
package/dist/src/ethos.d.ts
CHANGED
|
@@ -71,6 +71,44 @@ export declare class EthosClient {
|
|
|
71
71
|
* so the next read picks up the fresh edition.
|
|
72
72
|
*/
|
|
73
73
|
publish(): Promise<PublishResult>;
|
|
74
|
+
/**
|
|
75
|
+
* Idempotently ensure the subject's Ethos has at least one published
|
|
76
|
+
* edition. Required because a **delegate** cannot bootstrap a first
|
|
77
|
+
* edition (the first edition's manifest is signed with the owner's
|
|
78
|
+
* public-sphere key, which delegates do not have). Without an initial
|
|
79
|
+
* owner-published edition, subsequent delegate writes via
|
|
80
|
+
* {@link publish} fail with `not found: edition for did:…`.
|
|
81
|
+
*
|
|
82
|
+
* Semantics:
|
|
83
|
+
* - If an edition already exists (owner OR delegate OR anonymous mode),
|
|
84
|
+
* this is a NO-OP and returns `{ alreadyInitialized: true }`.
|
|
85
|
+
* - If no edition exists AND the actor is the owner, this stages and
|
|
86
|
+
* publishes a height=1 edition containing a single sentinel section
|
|
87
|
+
* `aithos-init` in the `public` zone, then returns
|
|
88
|
+
* `{ alreadyInitialized: false, editionHeight: 1 }`. Any previously
|
|
89
|
+
* staged mutations on this client are preserved and NOT auto-flushed.
|
|
90
|
+
* - If no edition exists AND the actor is NOT the owner (delegate or
|
|
91
|
+
* anonymous), throws `ethos_bootstrap_not_owner` — only the owner
|
|
92
|
+
* can sign a first edition.
|
|
93
|
+
*
|
|
94
|
+
* Call site: typically the owner's dashboard, right after sign-in and
|
|
95
|
+
* before any delegate-mode write (e.g. before triggering a backend
|
|
96
|
+
* worker that holds a mandate). Idempotent ⇒ safe to call on every
|
|
97
|
+
* mount.
|
|
98
|
+
*
|
|
99
|
+
* Implementation note: this routes through {@link #publishFirstEditionOwner}
|
|
100
|
+
* which the SDK already uses internally when {@link publish} detects a
|
|
101
|
+
* fresh Ethos with staged owner mutations. ensureInitialized() exposes
|
|
102
|
+
* the same code path as an explicit primitive, so the caller doesn't
|
|
103
|
+
* need to stage a mutation just to trigger first-edition logic.
|
|
104
|
+
*/
|
|
105
|
+
ensureInitialized(): Promise<{
|
|
106
|
+
alreadyInitialized: true;
|
|
107
|
+
} | {
|
|
108
|
+
alreadyInitialized: false;
|
|
109
|
+
editionHeight: number;
|
|
110
|
+
manifestHash: string;
|
|
111
|
+
}>;
|
|
74
112
|
_readZone(zone: ZoneName): Promise<readonly Section[]>;
|
|
75
113
|
_stageAdd(zone: ZoneName, input: AddSectionInput): void;
|
|
76
114
|
_stageUpdate(zone: ZoneName, sectionId: string, patch: UpdateSectionPatch): void;
|
package/dist/src/ethos.js
CHANGED
|
@@ -203,6 +203,98 @@ export class EthosClient {
|
|
|
203
203
|
throw new AithosSDKError("ethos_invalid_actor", "unsupported actor for publish()");
|
|
204
204
|
}
|
|
205
205
|
/* ------------------------------------------------------------------------ */
|
|
206
|
+
/* Bootstrap — first-edition init for fresh Ethos */
|
|
207
|
+
/* ------------------------------------------------------------------------ */
|
|
208
|
+
/**
|
|
209
|
+
* Idempotently ensure the subject's Ethos has at least one published
|
|
210
|
+
* edition. Required because a **delegate** cannot bootstrap a first
|
|
211
|
+
* edition (the first edition's manifest is signed with the owner's
|
|
212
|
+
* public-sphere key, which delegates do not have). Without an initial
|
|
213
|
+
* owner-published edition, subsequent delegate writes via
|
|
214
|
+
* {@link publish} fail with `not found: edition for did:…`.
|
|
215
|
+
*
|
|
216
|
+
* Semantics:
|
|
217
|
+
* - If an edition already exists (owner OR delegate OR anonymous mode),
|
|
218
|
+
* this is a NO-OP and returns `{ alreadyInitialized: true }`.
|
|
219
|
+
* - If no edition exists AND the actor is the owner, this stages and
|
|
220
|
+
* publishes a height=1 edition containing a single sentinel section
|
|
221
|
+
* `aithos-init` in the `public` zone, then returns
|
|
222
|
+
* `{ alreadyInitialized: false, editionHeight: 1 }`. Any previously
|
|
223
|
+
* staged mutations on this client are preserved and NOT auto-flushed.
|
|
224
|
+
* - If no edition exists AND the actor is NOT the owner (delegate or
|
|
225
|
+
* anonymous), throws `ethos_bootstrap_not_owner` — only the owner
|
|
226
|
+
* can sign a first edition.
|
|
227
|
+
*
|
|
228
|
+
* Call site: typically the owner's dashboard, right after sign-in and
|
|
229
|
+
* before any delegate-mode write (e.g. before triggering a backend
|
|
230
|
+
* worker that holds a mandate). Idempotent ⇒ safe to call on every
|
|
231
|
+
* mount.
|
|
232
|
+
*
|
|
233
|
+
* Implementation note: this routes through {@link #publishFirstEditionOwner}
|
|
234
|
+
* which the SDK already uses internally when {@link publish} detects a
|
|
235
|
+
* fresh Ethos with staged owner mutations. ensureInitialized() exposes
|
|
236
|
+
* the same code path as an explicit primitive, so the caller doesn't
|
|
237
|
+
* need to stage a mutation just to trigger first-edition logic.
|
|
238
|
+
*/
|
|
239
|
+
async ensureInitialized() {
|
|
240
|
+
// Read attempt — tolerant (returns null if no edition exists). Routes
|
|
241
|
+
// through the right snapshot method based on actor kind so the
|
|
242
|
+
// detection is correct in every mode.
|
|
243
|
+
let snap;
|
|
244
|
+
if (this.#actor.kind === "anonymous") {
|
|
245
|
+
snap = await this.#tryEnsureSnapshotAnonymous();
|
|
246
|
+
}
|
|
247
|
+
else if (this.#actor.kind === "owner") {
|
|
248
|
+
snap = await this.#tryEnsureSnapshotOwner();
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
snap = await this.#tryEnsureSnapshotDelegate();
|
|
252
|
+
}
|
|
253
|
+
if (snap !== null) {
|
|
254
|
+
return { alreadyInitialized: true };
|
|
255
|
+
}
|
|
256
|
+
// Bootstrap path — owner only.
|
|
257
|
+
if (this.#actor.kind !== "owner") {
|
|
258
|
+
throw new AithosSDKError("ethos_bootstrap_not_owner", `subject ${this.subjectDid} has no published edition yet, and only the owner can sign a first edition. Have the owner call ensureInitialized() once (typically from their dashboard at sign-in time).`, { data: { subjectDid: this.subjectDid, actorKind: this.#actor.kind } });
|
|
259
|
+
}
|
|
260
|
+
// Stage the sentinel init section. We don't disturb any pre-existing
|
|
261
|
+
// staged mutations — they'll be picked up by the same first-edition
|
|
262
|
+
// publish that runs underneath.
|
|
263
|
+
const prevMutations = this.#mutations.slice();
|
|
264
|
+
this.#mutations.push({
|
|
265
|
+
kind: "add",
|
|
266
|
+
zone: "public",
|
|
267
|
+
section: {
|
|
268
|
+
id: "sec_" + randomHex(12),
|
|
269
|
+
title: "aithos-init",
|
|
270
|
+
body: "Ethos initialized.\n\n" +
|
|
271
|
+
"This section is a sentinel created by `EthosClient.ensureInitialized()` " +
|
|
272
|
+
"to materialise the subject's first edition. It is safe to delete or " +
|
|
273
|
+
"edit later — its only purpose was to satisfy the protocol's " +
|
|
274
|
+
"requirement that an edition contain at least one section.",
|
|
275
|
+
gamma_ref: "gamma_none_" + randomHex(24),
|
|
276
|
+
},
|
|
277
|
+
});
|
|
278
|
+
try {
|
|
279
|
+
const result = await this.#publishFirstEditionOwner();
|
|
280
|
+
// Re-stage the caller's prior mutations (if any) so a subsequent
|
|
281
|
+
// publish() in the same call sequence picks them up. The init
|
|
282
|
+
// section we added has been consumed by the publish above.
|
|
283
|
+
this.#mutations = prevMutations;
|
|
284
|
+
return {
|
|
285
|
+
alreadyInitialized: false,
|
|
286
|
+
editionHeight: result.editionHeight,
|
|
287
|
+
manifestHash: result.manifestHash,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
catch (e) {
|
|
291
|
+
// On failure, restore the caller's mutations as they were before
|
|
292
|
+
// we touched the buffer so the client is left in a consistent state.
|
|
293
|
+
this.#mutations = prevMutations;
|
|
294
|
+
throw e;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/* ------------------------------------------------------------------------ */
|
|
206
298
|
/* Internal — snapshot management */
|
|
207
299
|
/* ------------------------------------------------------------------------ */
|
|
208
300
|
async _readZone(zone) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aithos/sdk",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.27",
|
|
4
4
|
"description": "Aithos SDK \u2014 high-level TypeScript developer kit for building agentic apps on the Aithos protocol. Wraps @aithos/protocol-client and exposes the Aithos compute proxy and wallet (Stripe top-up) endpoints.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"aithos",
|