@kumwe/studio-core 0.1.0-alpha.2

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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +27 -0
  3. package/dist/canonical.d.ts +20 -0
  4. package/dist/canonical.d.ts.map +1 -0
  5. package/dist/canonical.js +100 -0
  6. package/dist/canonical.js.map +1 -0
  7. package/dist/clone.d.ts +2 -0
  8. package/dist/clone.d.ts.map +1 -0
  9. package/dist/clone.js +4 -0
  10. package/dist/clone.js.map +1 -0
  11. package/dist/commands.d.ts +12 -0
  12. package/dist/commands.d.ts.map +1 -0
  13. package/dist/commands.js +679 -0
  14. package/dist/commands.js.map +1 -0
  15. package/dist/contributions.d.ts +65 -0
  16. package/dist/contributions.d.ts.map +1 -0
  17. package/dist/contributions.js +302 -0
  18. package/dist/contributions.js.map +1 -0
  19. package/dist/entry-commands.d.ts +3 -0
  20. package/dist/entry-commands.d.ts.map +1 -0
  21. package/dist/entry-commands.js +36 -0
  22. package/dist/entry-commands.js.map +1 -0
  23. package/dist/history.d.ts +13 -0
  24. package/dist/history.d.ts.map +1 -0
  25. package/dist/history.js +63 -0
  26. package/dist/history.js.map +1 -0
  27. package/dist/index.d.ts +15 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +15 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/migrations.d.ts +47 -0
  32. package/dist/migrations.d.ts.map +1 -0
  33. package/dist/migrations.js +83 -0
  34. package/dist/migrations.js.map +1 -0
  35. package/dist/model-commands.d.ts +3 -0
  36. package/dist/model-commands.d.ts.map +1 -0
  37. package/dist/model-commands.js +21 -0
  38. package/dist/model-commands.js.map +1 -0
  39. package/dist/negotiation.d.ts +23 -0
  40. package/dist/negotiation.d.ts.map +1 -0
  41. package/dist/negotiation.js +65 -0
  42. package/dist/negotiation.js.map +1 -0
  43. package/dist/recipes.d.ts +15 -0
  44. package/dist/recipes.d.ts.map +1 -0
  45. package/dist/recipes.js +34 -0
  46. package/dist/recipes.js.map +1 -0
  47. package/dist/registry.d.ts +17 -0
  48. package/dist/registry.d.ts.map +1 -0
  49. package/dist/registry.js +56 -0
  50. package/dist/registry.js.map +1 -0
  51. package/dist/schema-profile.d.ts +9 -0
  52. package/dist/schema-profile.d.ts.map +1 -0
  53. package/dist/schema-profile.js +387 -0
  54. package/dist/schema-profile.js.map +1 -0
  55. package/dist/semver.d.ts +20 -0
  56. package/dist/semver.d.ts.map +1 -0
  57. package/dist/semver.js +128 -0
  58. package/dist/semver.js.map +1 -0
  59. package/dist/session.d.ts +33 -0
  60. package/dist/session.d.ts.map +1 -0
  61. package/dist/session.js +113 -0
  62. package/dist/session.js.map +1 -0
  63. package/dist/validation.d.ts +13 -0
  64. package/dist/validation.d.ts.map +1 -0
  65. package/dist/validation.js +398 -0
  66. package/dist/validation.js.map +1 -0
  67. package/package.json +40 -0
@@ -0,0 +1,47 @@
1
+ import type { JsonValue, OwnerReference, QualifiedName, SemanticVersion, StudioDiagnostic } from '@kumwe/studio-protocol';
2
+ export type MigratableArtifactKind = 'block-definition' | 'blueprint' | 'content-model' | 'entry' | 'theme';
3
+ export interface MigratableDocument {
4
+ kind: string;
5
+ version: SemanticVersion;
6
+ [member: string]: JsonValue | undefined;
7
+ }
8
+ export interface MigrationDescriptor {
9
+ artifactKinds: readonly MigratableArtifactKind[];
10
+ description: string;
11
+ id: QualifiedName;
12
+ lossClassification: 'lossless' | 'lossy';
13
+ migrate(document: MigratableDocument): MigratableDocument;
14
+ owner: OwnerReference;
15
+ sourceVersions: string;
16
+ targetVersion: SemanticVersion;
17
+ }
18
+ export interface MigrationApplyOptions {
19
+ confirmLossy?: boolean;
20
+ validate?(document: MigratableDocument): StudioDiagnostic[];
21
+ }
22
+ export interface MigrationApplyResult {
23
+ diagnostics: StudioDiagnostic[];
24
+ document: MigratableDocument;
25
+ migrationId: QualifiedName;
26
+ }
27
+ export declare class StudioMigrationError extends Error {
28
+ readonly code: 'already-applied' | 'confirmation-required' | 'duplicate-migration' | 'invalid-result' | 'not-applicable' | 'unknown-migration';
29
+ readonly diagnostics: StudioDiagnostic[];
30
+ constructor(code: StudioMigrationError['code'], message: string, diagnostics?: StudioDiagnostic[]);
31
+ }
32
+ /**
33
+ * The deterministic migration runner the versioning contract defines.
34
+ * Migration operates on a copy, validates the complete result before
35
+ * acceptance, never mutates or replaces the original revision, refuses
36
+ * lossy transformations without explicit confirmation, and rejects
37
+ * reapplication once a document has left a migration's source range.
38
+ */
39
+ export declare class MigrationRunner {
40
+ #private;
41
+ register(migration: MigrationDescriptor): void;
42
+ migrations(): MigrationDescriptor[];
43
+ /** Ordered migrations whose source range and artifact kind match the document. */
44
+ plan(document: Readonly<MigratableDocument>): MigrationDescriptor[];
45
+ apply(document: Readonly<MigratableDocument>, migrationId: QualifiedName, options?: Readonly<MigrationApplyOptions>): MigrationApplyResult;
46
+ }
47
+ //# sourceMappingURL=migrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,aAAa,EACb,eAAe,EACf,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAIhC,MAAM,MAAM,sBAAsB,GAChC,kBAAkB,GAAG,WAAW,GAAG,eAAe,GAAG,OAAO,GAAG,OAAO,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,eAAe,CAAC;IACzB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;CACzC;AAED,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,aAAa,CAAC;IAClB,kBAAkB,EAAE,UAAU,GAAG,OAAO,CAAC;IACzC,OAAO,CAAC,QAAQ,EAAE,kBAAkB,GAAG,kBAAkB,CAAC;IAC1D,KAAK,EAAE,cAAc,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,eAAe,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,CAAC,QAAQ,EAAE,kBAAkB,GAAG,gBAAgB,EAAE,CAAC;CAC7D;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,WAAW,EAAE,aAAa,CAAC;CAC5B;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,SAAgB,IAAI,EAChB,iBAAiB,GACjB,uBAAuB,GACvB,qBAAqB,GACrB,gBAAgB,GAChB,gBAAgB,GAChB,mBAAmB,CAAC;IACxB,SAAgB,WAAW,EAAE,gBAAgB,EAAE,CAAC;gBAG9C,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,EAClC,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,gBAAgB,EAAO;CAOvC;AAED;;;;;;GAMG;AACH,qBAAa,eAAe;;IAGnB,QAAQ,CAAC,SAAS,EAAE,mBAAmB,GAAG,IAAI;IAwB9C,UAAU,IAAI,mBAAmB,EAAE;IAI1C,kFAAkF;IAC3E,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,kBAAkB,CAAC,GAAG,mBAAmB,EAAE;IAUnE,KAAK,CACV,QAAQ,EAAE,QAAQ,CAAC,kBAAkB,CAAC,EACtC,WAAW,EAAE,aAAa,EAC1B,OAAO,GAAE,QAAQ,CAAC,qBAAqB,CAAM,GAC5C,oBAAoB;CAiExB"}
@@ -0,0 +1,83 @@
1
+ import { cloneContractValue } from './clone.js';
2
+ import { normalizeVersionRange, parseSemanticVersion, satisfiesVersionRange } from './semver.js';
3
+ export class StudioMigrationError extends Error {
4
+ code;
5
+ diagnostics;
6
+ constructor(code, message, diagnostics = []) {
7
+ super(message);
8
+ this.name = 'StudioMigrationError';
9
+ this.code = code;
10
+ this.diagnostics = diagnostics;
11
+ }
12
+ }
13
+ /**
14
+ * The deterministic migration runner the versioning contract defines.
15
+ * Migration operates on a copy, validates the complete result before
16
+ * acceptance, never mutates or replaces the original revision, refuses
17
+ * lossy transformations without explicit confirmation, and rejects
18
+ * reapplication once a document has left a migration's source range.
19
+ */
20
+ export class MigrationRunner {
21
+ #migrations = new Map();
22
+ register(migration) {
23
+ if (this.#migrations.has(migration.id)) {
24
+ throw new StudioMigrationError('duplicate-migration', `Migration ${migration.id} is already registered.`);
25
+ }
26
+ if (migration.artifactKinds.length === 0) {
27
+ throw new StudioMigrationError('not-applicable', `Migration ${migration.id} declares no artifact kinds.`);
28
+ }
29
+ normalizeVersionRange(migration.sourceVersions);
30
+ parseSemanticVersion(migration.targetVersion);
31
+ if (satisfiesVersionRange(migration.targetVersion, migration.sourceVersions)) {
32
+ throw new StudioMigrationError('invalid-result', `Migration ${migration.id} targets a version inside its own source range, so reapplication could never be rejected.`);
33
+ }
34
+ this.#migrations.set(migration.id, migration);
35
+ }
36
+ migrations() {
37
+ return [...this.#migrations.values()];
38
+ }
39
+ /** Ordered migrations whose source range and artifact kind match the document. */
40
+ plan(document) {
41
+ return this.migrations()
42
+ .filter((migration) => migration.artifactKinds.includes(document.kind) &&
43
+ satisfiesVersionRange(document.version, migration.sourceVersions))
44
+ .sort((left, right) => (left.id < right.id ? -1 : 1));
45
+ }
46
+ apply(document, migrationId, options = {}) {
47
+ const migration = this.#migrations.get(migrationId);
48
+ if (migration === undefined) {
49
+ throw new StudioMigrationError('unknown-migration', `Migration ${migrationId} is not registered.`);
50
+ }
51
+ if (!migration.artifactKinds.includes(document.kind)) {
52
+ throw new StudioMigrationError('not-applicable', `Migration ${migrationId} does not cover ${document.kind} artifacts.`);
53
+ }
54
+ if (!satisfiesVersionRange(document.version, migration.sourceVersions)) {
55
+ const code = document.version === migration.targetVersion ? 'already-applied' : 'not-applicable';
56
+ throw new StudioMigrationError(code, `Document version ${document.version} is outside the source range of ${migrationId}.`);
57
+ }
58
+ if (migration.lossClassification === 'lossy' && options.confirmLossy !== true) {
59
+ throw new StudioMigrationError('confirmation-required', `Migration ${migrationId} is lossy and requires explicit confirmation.`);
60
+ }
61
+ const migrated = migration.migrate(cloneContractValue(document));
62
+ const diagnostics = [];
63
+ if (migrated.kind !== document.kind) {
64
+ throw new StudioMigrationError('invalid-result', `Migration ${migrationId} changed the artifact kind from ${document.kind} to ${migrated.kind}.`);
65
+ }
66
+ if (migrated.version !== migration.targetVersion) {
67
+ throw new StudioMigrationError('invalid-result', `Migration ${migrationId} produced version ${migrated.version}, not the declared target ${migration.targetVersion}.`);
68
+ }
69
+ if (options.validate !== undefined) {
70
+ const validationDiagnostics = options.validate(migrated);
71
+ diagnostics.push(...validationDiagnostics);
72
+ if (validationDiagnostics.some((entry) => entry.severity === 'blocking' || entry.severity === 'error')) {
73
+ throw new StudioMigrationError('invalid-result', `Migration ${migrationId} produced an invalid document.`, validationDiagnostics);
74
+ }
75
+ }
76
+ return {
77
+ diagnostics,
78
+ document: migrated,
79
+ migrationId,
80
+ };
81
+ }
82
+ }
83
+ //# sourceMappingURL=migrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AddModelFieldCommand, ContentModelDocument } from '@kumwe/studio-protocol';
2
+ export declare function applyModelCommand(model: ContentModelDocument, command: AddModelFieldCommand): ContentModelDocument;
3
+ //# sourceMappingURL=model-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-commands.d.ts","sourceRoot":"","sources":["../src/model-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAIzF,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,oBAAoB,EAC3B,OAAO,EAAE,oBAAoB,GAC5B,oBAAoB,CA8BtB"}
@@ -0,0 +1,21 @@
1
+ import { cloneContractValue } from './clone.js';
2
+ import { StudioCommandError } from './commands.js';
3
+ export function applyModelCommand(model, command) {
4
+ if (command.artifactId !== model.id) {
5
+ throw new StudioCommandError('node-not-found', `Command targets ${command.artifactId}, not content model ${model.id}.`);
6
+ }
7
+ if (model.status !== 'draft') {
8
+ throw new StudioCommandError('artifact-not-draft', `Content model ${model.id} is ${model.status}; fields are added through a new draft.`);
9
+ }
10
+ if (model.fields.some((field) => field.id === command.payload.field.id)) {
11
+ throw new StudioCommandError('duplicate-field', `Field ${command.payload.field.id} already exists on ${model.id}.`);
12
+ }
13
+ const position = command.payload.position ?? model.fields.length;
14
+ if (!Number.isInteger(position) || position < 0 || position > model.fields.length) {
15
+ throw new StudioCommandError('invalid-index', `Field position ${position} is outside the model's field list.`);
16
+ }
17
+ const next = cloneContractValue(model);
18
+ next.fields.splice(position, 0, cloneContractValue(command.payload.field));
19
+ return next;
20
+ }
21
+ //# sourceMappingURL=model-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-commands.js","sourceRoot":"","sources":["../src/model-commands.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,UAAU,iBAAiB,CAC/B,KAA2B,EAC3B,OAA6B;IAE7B,IAAI,OAAO,CAAC,UAAU,KAAK,KAAK,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,IAAI,kBAAkB,CAC1B,gBAAgB,EAChB,mBAAmB,OAAO,CAAC,UAAU,uBAAuB,KAAK,CAAC,EAAE,GAAG,CACxE,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,kBAAkB,CAC1B,oBAAoB,EACpB,iBAAiB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC,MAAM,yCAAyC,CACtF,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,kBAAkB,CAC1B,iBAAiB,EACjB,SAAS,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,sBAAsB,KAAK,CAAC,EAAE,GAAG,CACnE,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;IACjE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,IAAI,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAClF,MAAM,IAAI,kBAAkB,CAC1B,eAAe,EACf,kBAAkB,QAAQ,qCAAqC,CAChE,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3E,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { HostCapabilities, QualifiedName, StudioDiagnostic } from '@kumwe/studio-protocol';
2
+ export interface CapabilityNegotiationOptions {
3
+ optionalPorts?: readonly QualifiedName[];
4
+ requiredPorts?: readonly QualifiedName[];
5
+ supportedProtocolVersions?: readonly string[];
6
+ }
7
+ export interface CapabilityNegotiationResult {
8
+ availablePorts: QualifiedName[];
9
+ diagnostics: StudioDiagnostic[];
10
+ missingOptionalPorts: QualifiedName[];
11
+ missingRequiredPorts: QualifiedName[];
12
+ protocolVersion?: string;
13
+ sessionState: 'editable' | 'read-only';
14
+ }
15
+ /**
16
+ * Resolve one session posture from a host capability document. Capability
17
+ * negotiation fails closed: without a common wire protocol version or a
18
+ * required port there is no editable session, only a diagnosable read-only
19
+ * one. Optional ports degrade with informational diagnostics instead of
20
+ * being silently assumed.
21
+ */
22
+ export declare function negotiateCapabilities(capabilities: HostCapabilities, options?: Readonly<CapabilityNegotiationOptions>): CapabilityNegotiationResult;
23
+ //# sourceMappingURL=negotiation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"negotiation.d.ts","sourceRoot":"","sources":["../src/negotiation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAGhG,MAAM,WAAW,4BAA4B;IAC3C,aAAa,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,aAAa,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,yBAAyB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/C;AAED,MAAM,WAAW,2BAA2B;IAC1C,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,oBAAoB,EAAE,aAAa,EAAE,CAAC;IACtC,oBAAoB,EAAE,aAAa,EAAE,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,UAAU,GAAG,WAAW,CAAC;CACxC;AAID;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,gBAAgB,EAC9B,OAAO,GAAE,QAAQ,CAAC,4BAA4B,CAAM,GACnD,2BAA2B,CA6D7B"}
@@ -0,0 +1,65 @@
1
+ import { STUDIO_WIRE_PROTOCOL_VERSION } from '@kumwe/studio-protocol';
2
+ const DEFAULT_REQUIRED_PORTS = ['studio.port/artifact'];
3
+ /**
4
+ * Resolve one session posture from a host capability document. Capability
5
+ * negotiation fails closed: without a common wire protocol version or a
6
+ * required port there is no editable session, only a diagnosable read-only
7
+ * one. Optional ports degrade with informational diagnostics instead of
8
+ * being silently assumed.
9
+ */
10
+ export function negotiateCapabilities(capabilities, options = {}) {
11
+ const supportedVersions = options.supportedProtocolVersions ?? [STUDIO_WIRE_PROTOCOL_VERSION];
12
+ const requiredPorts = options.requiredPorts ?? DEFAULT_REQUIRED_PORTS;
13
+ const optionalPorts = options.optionalPorts ?? [];
14
+ const diagnostics = [];
15
+ const availablePorts = capabilities.ports.map((port) => port.id);
16
+ const available = new Set(availablePorts);
17
+ const protocolVersion = supportedVersions.find((version) => capabilities.protocolVersions.includes(version));
18
+ if (protocolVersion === undefined) {
19
+ diagnostics.push({
20
+ code: 'studio.host/no-common-protocol-version',
21
+ message: {
22
+ defaultMessage: 'Studio and the host share no wire protocol version.',
23
+ key: 'studio.host/no-common-protocol-version',
24
+ },
25
+ severity: 'blocking',
26
+ });
27
+ }
28
+ const missingRequiredPorts = requiredPorts.filter((port) => !available.has(port));
29
+ for (const port of missingRequiredPorts) {
30
+ diagnostics.push({
31
+ code: 'studio.host/missing-required-port',
32
+ message: {
33
+ defaultMessage: `The host does not provide the required ${port} port.`,
34
+ key: 'studio.host/missing-required-port',
35
+ },
36
+ parameters: { port },
37
+ severity: 'blocking',
38
+ });
39
+ }
40
+ const missingOptionalPorts = optionalPorts.filter((port) => !available.has(port));
41
+ for (const port of missingOptionalPorts) {
42
+ diagnostics.push({
43
+ code: 'studio.host/missing-optional-port',
44
+ message: {
45
+ defaultMessage: `The optional ${port} port is unavailable; its features are disabled.`,
46
+ key: 'studio.host/missing-optional-port',
47
+ },
48
+ parameters: { port },
49
+ severity: 'information',
50
+ });
51
+ }
52
+ const editable = protocolVersion !== undefined && missingRequiredPorts.length === 0;
53
+ const result = {
54
+ availablePorts,
55
+ diagnostics,
56
+ missingOptionalPorts,
57
+ missingRequiredPorts,
58
+ sessionState: editable ? 'editable' : 'read-only',
59
+ };
60
+ if (protocolVersion !== undefined) {
61
+ result.protocolVersion = protocolVersion;
62
+ }
63
+ return result;
64
+ }
65
+ //# sourceMappingURL=negotiation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"negotiation.js","sourceRoot":"","sources":["../src/negotiation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAiBtE,MAAM,sBAAsB,GAA6B,CAAC,sBAAsB,CAAC,CAAC;AAElF;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,YAA8B,EAC9B,UAAkD,EAAE;IAEpD,MAAM,iBAAiB,GAAG,OAAO,CAAC,yBAAyB,IAAI,CAAC,4BAA4B,CAAC,CAAC;IAC9F,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,sBAAsB,CAAC;IACtE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;IAElD,MAAM,WAAW,GAAuB,EAAE,CAAC;IAC3C,MAAM,cAAc,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAgB,cAAc,CAAC,CAAC;IAEzD,MAAM,eAAe,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CACzD,YAAY,CAAC,gBAAgB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAChD,CAAC;IACF,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;QAClC,WAAW,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,wCAAwC;YAC9C,OAAO,EAAE;gBACP,cAAc,EAAE,qDAAqD;gBACrE,GAAG,EAAE,wCAAwC;aAC9C;YACD,QAAQ,EAAE,UAAU;SACrB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,oBAAoB,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAClF,KAAK,MAAM,IAAI,IAAI,oBAAoB,EAAE,CAAC;QACxC,WAAW,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,mCAAmC;YACzC,OAAO,EAAE;gBACP,cAAc,EAAE,0CAA0C,IAAI,QAAQ;gBACtE,GAAG,EAAE,mCAAmC;aACzC;YACD,UAAU,EAAE,EAAE,IAAI,EAAE;YACpB,QAAQ,EAAE,UAAU;SACrB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,oBAAoB,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAClF,KAAK,MAAM,IAAI,IAAI,oBAAoB,EAAE,CAAC;QACxC,WAAW,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,mCAAmC;YACzC,OAAO,EAAE;gBACP,cAAc,EAAE,gBAAgB,IAAI,kDAAkD;gBACtF,GAAG,EAAE,mCAAmC;aACzC;YACD,UAAU,EAAE,EAAE,IAAI,EAAE;YACpB,QAAQ,EAAE,aAAa;SACxB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,eAAe,KAAK,SAAS,IAAI,oBAAoB,CAAC,MAAM,KAAK,CAAC,CAAC;IACpF,MAAM,MAAM,GAAgC;QAC1C,cAAc;QACd,WAAW;QACX,oBAAoB;QACpB,oBAAoB;QACpB,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW;KAClD,CAAC;IACF,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,CAAC,eAAe,GAAG,eAAe,CAAC;IAC3C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { BlueprintBatchOperation, BlueprintNode, LocalName, ThemeDocument } from '@kumwe/studio-protocol';
2
+ /**
3
+ * The reserved node property that records which theme recipe an author
4
+ * selected. Recipe selection is canonically an atomic batch of set-property
5
+ * operations, so it inherits batch atomicity and verified inverses from the
6
+ * command contract instead of introducing a new command type.
7
+ */
8
+ export declare const RECIPE_MARKER_PROPERTY = "studio.recipe";
9
+ /**
10
+ * Expand a theme recipe selection into the deterministic batch operations
11
+ * that apply it to one node: every design value of the recipe, in sorted
12
+ * member order, followed by the reserved recipe marker property.
13
+ */
14
+ export declare function recipeSelectionOperations(node: Readonly<BlueprintNode>, theme: Readonly<ThemeDocument>, recipeId: LocalName): BlueprintBatchOperation[];
15
+ //# sourceMappingURL=recipes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,aAAa,EACb,SAAS,EACT,aAAa,EACd,MAAM,wBAAwB,CAAC;AAGhC;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AAEtD;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC7B,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC9B,QAAQ,EAAE,SAAS,GAClB,uBAAuB,EAAE,CAsB3B"}
@@ -0,0 +1,34 @@
1
+ import { cloneContractValue } from './clone.js';
2
+ /**
3
+ * The reserved node property that records which theme recipe an author
4
+ * selected. Recipe selection is canonically an atomic batch of set-property
5
+ * operations, so it inherits batch atomicity and verified inverses from the
6
+ * command contract instead of introducing a new command type.
7
+ */
8
+ export const RECIPE_MARKER_PROPERTY = 'studio.recipe';
9
+ /**
10
+ * Expand a theme recipe selection into the deterministic batch operations
11
+ * that apply it to one node: every design value of the recipe, in sorted
12
+ * member order, followed by the reserved recipe marker property.
13
+ */
14
+ export function recipeSelectionOperations(node, theme, recipeId) {
15
+ const recipe = theme.recipes.find((candidate) => candidate.id === recipeId);
16
+ if (recipe === undefined) {
17
+ throw new Error(`Theme ${theme.id} does not declare a recipe ${recipeId}.`);
18
+ }
19
+ if (recipe.blockType !== node.type) {
20
+ throw new Error(`Recipe ${recipeId} targets ${recipe.blockType} blocks, not ${node.type} node ${node.id}.`);
21
+ }
22
+ const operations = Object.entries(recipe.designValues)
23
+ .sort(([left], [right]) => (left < right ? -1 : 1))
24
+ .map(([property, value]) => ({
25
+ payload: { nodeId: node.id, property, value: cloneContractValue(value) },
26
+ type: 'studio.command/set-property',
27
+ }));
28
+ operations.push({
29
+ payload: { nodeId: node.id, property: RECIPE_MARKER_PROPERTY, value: recipeId },
30
+ type: 'studio.command/set-property',
31
+ });
32
+ return operations;
33
+ }
34
+ //# sourceMappingURL=recipes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipes.js","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,eAAe,CAAC;AAEtD;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CACvC,IAA6B,EAC7B,KAA8B,EAC9B,QAAmB;IAEnB,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;IAC5E,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,SAAS,KAAK,CAAC,EAAE,8BAA8B,QAAQ,GAAG,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,UAAU,QAAQ,YAAY,MAAM,CAAC,SAAS,gBAAgB,IAAI,CAAC,IAAI,SAAS,IAAI,CAAC,EAAE,GAAG,CAC3F,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAA8B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC;SAC9E,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAClD,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3B,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE;QACxE,IAAI,EAAE,6BAAsC;KAC7C,CAAC,CAAC,CAAC;IACN,UAAU,CAAC,IAAI,CAAC;QACd,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,sBAAsB,EAAE,KAAK,EAAE,QAAQ,EAAE;QAC/E,IAAI,EAAE,6BAA6B;KACpC,CAAC,CAAC;IACH,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { BlockDefinition, BlockType } from '@kumwe/studio-protocol';
2
+ export interface BlockRegistrationOptions {
3
+ verifiedIntegrity?: string;
4
+ }
5
+ export interface ResolvedBlockRegistration {
6
+ definition: BlockDefinition;
7
+ verifiedIntegrity?: string;
8
+ }
9
+ export declare class BlockRegistry {
10
+ #private;
11
+ constructor(definitions?: readonly BlockDefinition[]);
12
+ register(definition: BlockDefinition, options?: Readonly<BlockRegistrationOptions>): void;
13
+ resolve(type: BlockType, version: string): BlockDefinition | undefined;
14
+ resolveRegistration(type: BlockType, version: string): ResolvedBlockRegistration | undefined;
15
+ definitions(): BlockDefinition[];
16
+ }
17
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAIzE,MAAM,WAAW,wBAAwB;IACvC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,eAAe,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAOD,qBAAa,aAAa;;gBAGL,WAAW,GAAE,SAAS,eAAe,EAAO;IAMxD,QAAQ,CACb,UAAU,EAAE,eAAe,EAC3B,OAAO,GAAE,QAAQ,CAAC,wBAAwB,CAAM,GAC/C,IAAI;IA2BA,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAItE,mBAAmB,CACxB,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,GACd,yBAAyB,GAAG,SAAS;IAcjC,WAAW,IAAI,eAAe,EAAE;CAKxC"}
@@ -0,0 +1,56 @@
1
+ import { cloneContractValue } from './clone.js';
2
+ import { assertStudioPropertySchema } from './schema-profile.js';
3
+ export class BlockRegistry {
4
+ #definitions = new Map();
5
+ constructor(definitions = []) {
6
+ for (const definition of definitions) {
7
+ this.register(definition);
8
+ }
9
+ }
10
+ register(definition, options = {}) {
11
+ assertStudioPropertySchema(definition.propertySchema);
12
+ if (options.verifiedIntegrity !== undefined && !isIntegrity(options.verifiedIntegrity)) {
13
+ throw new TypeError('Host-verified block integrity must be a canonical SRI sha256/384/512 value.');
14
+ }
15
+ let versions = this.#definitions.get(definition.type);
16
+ if (versions === undefined) {
17
+ versions = new Map();
18
+ this.#definitions.set(definition.type, versions);
19
+ }
20
+ if (versions.has(definition.version)) {
21
+ throw new Error(`Block ${definition.type}@${definition.version} is already registered.`);
22
+ }
23
+ const registration = {
24
+ definition: cloneContractValue(definition),
25
+ };
26
+ if (options.verifiedIntegrity !== undefined) {
27
+ registration.verifiedIntegrity = options.verifiedIntegrity;
28
+ }
29
+ versions.set(definition.version, registration);
30
+ }
31
+ resolve(type, version) {
32
+ return this.resolveRegistration(type, version)?.definition;
33
+ }
34
+ resolveRegistration(type, version) {
35
+ const registration = this.#definitions.get(type)?.get(version);
36
+ if (registration === undefined) {
37
+ return undefined;
38
+ }
39
+ const resolved = {
40
+ definition: cloneContractValue(registration.definition),
41
+ };
42
+ if (registration.verifiedIntegrity !== undefined) {
43
+ resolved.verifiedIntegrity = registration.verifiedIntegrity;
44
+ }
45
+ return resolved;
46
+ }
47
+ definitions() {
48
+ return [...this.#definitions.values()]
49
+ .flatMap((versions) => [...versions.values()])
50
+ .map((registration) => cloneContractValue(registration.definition));
51
+ }
52
+ }
53
+ function isIntegrity(value) {
54
+ return /^(?:sha256-[A-Za-z0-9+/]{42}[AEIMQUYcgkosw048]=|sha384-[A-Za-z0-9+/]{64}|sha512-[A-Za-z0-9+/]{85}[AQgw]==)(?![\s\S])/u.test(value);
55
+ }
56
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAgBjE,MAAM,OAAO,aAAa;IACf,YAAY,GAAG,IAAI,GAAG,EAAmD,CAAC;IAEnF,YAAmB,cAA0C,EAAE;QAC7D,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAEM,QAAQ,CACb,UAA2B,EAC3B,UAA8C,EAAE;QAEhD,0BAA0B,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QACtD,IAAI,OAAO,CAAC,iBAAiB,KAAK,SAAS,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACvF,MAAM,IAAI,SAAS,CACjB,6EAA6E,CAC9E,CAAC;QACJ,CAAC;QAED,IAAI,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACtD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,QAAQ,GAAG,IAAI,GAAG,EAAmC,CAAC;YACtD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnD,CAAC;QAED,IAAI,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,SAAS,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;QAC3F,CAAC;QAED,MAAM,YAAY,GAA4B;YAC5C,UAAU,EAAE,kBAAkB,CAAC,UAAU,CAAC;SAC3C,CAAC;QACF,IAAI,OAAO,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;YAC5C,YAAY,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;QAC7D,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACjD,CAAC;IAEM,OAAO,CAAC,IAAe,EAAE,OAAe;QAC7C,OAAO,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,UAAU,CAAC;IAC7D,CAAC;IAEM,mBAAmB,CACxB,IAAe,EACf,OAAe;QAEf,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAC/D,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,QAAQ,GAA8B;YAC1C,UAAU,EAAE,kBAAkB,CAAC,YAAY,CAAC,UAAU,CAAC;SACxD,CAAC;QACF,IAAI,YAAY,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;YACjD,QAAQ,CAAC,iBAAiB,GAAG,YAAY,CAAC,iBAAiB,CAAC;QAC9D,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEM,WAAW;QAChB,OAAO,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;aACnC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;aAC7C,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,kBAAkB,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC;IACxE,CAAC;CACF;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,uHAAuH,CAAC,IAAI,CACjI,KAAK,CACN,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { JsonSchema } from '@kumwe/studio-protocol';
2
+ /**
3
+ * The published complexity limits of the Studio Schema Profile. The
4
+ * machine-readable meta-schema (`schema-profile.schema.json`) carries the
5
+ * same values; a parity test keeps the two from drifting.
6
+ */
7
+ export declare const STUDIO_SCHEMA_PROFILE_LIMITS: Readonly<Record<string, number>>;
8
+ export declare function assertStudioPropertySchema(schema: JsonSchema): void;
9
+ //# sourceMappingURL=schema-profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-profile.d.ts","sourceRoot":"","sources":["../src/schema-profile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAezD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYxE,CAAC;AAiDH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAwBnE"}