@holonograph/client 0.1.0 → 0.2.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +160 -144
  2. package/dist/index.js +106 -2
  3. package/package.json +2 -10
package/dist/index.js CHANGED
@@ -4008,6 +4008,8 @@ var ALL_VISIBILITIES = ["transparent", "announced", "opaque"];
4008
4008
  var VisibilityAttributeSchema = external_exports.enum(ALL_VISIBILITIES);
4009
4009
  var ALL_SUBSTRATE_COLUMN_SEMANTICS = ["deployment-state", "diagnostic"];
4010
4010
  var SubstrateColumnSemanticSchema = external_exports.enum(ALL_SUBSTRATE_COLUMN_SEMANTICS);
4011
+ var ALL_EMISSION_EXPECTATIONS = ["always", "conditional"];
4012
+ var EmissionExpectationSchema = external_exports.enum(ALL_EMISSION_EXPECTATIONS);
4011
4013
  var SubstrateColumnSchema = external_exports.object({
4012
4014
  id: external_exports.string().min(1).max(128),
4013
4015
  control: ControlAttributeSchema,
@@ -4016,7 +4018,9 @@ var SubstrateColumnSchema = external_exports.object({
4016
4018
 
4017
4019
  semantic: SubstrateColumnSemanticSchema.default("deployment-state"),
4018
4020
 
4019
- values: external_exports.array(external_exports.string().min(1)).min(1).optional()
4021
+ values: external_exports.array(external_exports.string().min(1)).min(1).optional(),
4022
+
4023
+ emissionExpectation: EmissionExpectationSchema.optional()
4020
4024
  });
4021
4025
  var SubstrateSnapshotSchema = external_exports.object({
4022
4026
  lensVersion: LensVersionIdSchema,
@@ -4585,7 +4589,9 @@ external_exports.object({
4585
4589
 
4586
4590
  tools: external_exports.array(CapabilityToolDefSchema).default([]),
4587
4591
 
4588
- proseRules: external_exports.array(external_exports.string().min(1)).default([])
4592
+ proseRules: external_exports.array(external_exports.string().min(1)).default([]),
4593
+
4594
+ availableColumns: external_exports.array(external_exports.string().min(1)).optional()
4589
4595
  });
4590
4596
  external_exports.object({
4591
4597
 
@@ -5366,6 +5372,9 @@ var HttpTransport = class {
5366
5372
  async postContract(contract) {
5367
5373
  return this.post("/holonograph/contract", contract);
5368
5374
  }
5375
+ async getContract() {
5376
+ return this.get("/holonograph/contract");
5377
+ }
5369
5378
  async markAvailability(req) {
5370
5379
  return this.post("/lens/availability/mark", req);
5371
5380
  }
@@ -5413,6 +5422,45 @@ var HttpTransport = class {
5413
5422
  }
5414
5423
  return parsed;
5415
5424
  }
5425
+
5426
+ async get(path) {
5427
+ const url = `${this.endpoint}${path}`;
5428
+ const headers = { "content-type": "application/json" };
5429
+ if (this.token !== void 0) headers.authorization = `Bearer ${this.token}`;
5430
+ if (this.runMode !== void 0) headers["x-holonograph-run-mode"] = this.runMode;
5431
+ let response;
5432
+ try {
5433
+ response = await this.fetchImpl(url, { method: "GET", headers });
5434
+ } catch (cause) {
5435
+ throw new HolonographHttpError(
5436
+ 0,
5437
+ "transport_error",
5438
+ `the lens fetch failed: ${cause.message}`,
5439
+ { cause: String(cause) }
5440
+ );
5441
+ }
5442
+ const text = await response.text();
5443
+ let parsed;
5444
+ try {
5445
+ parsed = text.length ? JSON.parse(text) : {};
5446
+ } catch {
5447
+ throw new HolonographHttpError(
5448
+ response.status,
5449
+ "parse_error",
5450
+ `the lens returned non-JSON (status ${String(response.status)}): ${text.slice(0, 200)}`
5451
+ );
5452
+ }
5453
+ if (!response.ok) {
5454
+ const envelope = parsed;
5455
+ throw new HolonographHttpError(
5456
+ response.status,
5457
+ envelope.code ?? "server_error",
5458
+ envelope.error ?? `the lens returned ${String(response.status)}`,
5459
+ envelope.details
5460
+ );
5461
+ }
5462
+ return parsed;
5463
+ }
5416
5464
  };
5417
5465
  function lightSnapshotFromResult(result) {
5418
5466
  const snapshot = {
@@ -5449,6 +5497,14 @@ var HolonographClient = class {
5449
5497
  lensVersion;
5450
5498
  substrate;
5451
5499
 
5500
+ onUnknownColumn;
5501
+
5502
+ declaredColumns;
5503
+
5504
+ warnedColumns = new Set();
5505
+
5506
+ refreshedColumnsOnce = false;
5507
+
5452
5508
  messages;
5453
5509
 
5454
5510
  contract;
@@ -5476,6 +5532,7 @@ var HolonographClient = class {
5476
5532
  }
5477
5533
  this.lensVersion = options.lensVersion;
5478
5534
  this.substrate = options.substrate;
5535
+ this.onUnknownColumn = isHttpOptions(options) ? options.onUnknownColumn ?? "warn" : "ignore";
5479
5536
  this.messages = { create: (req) => this.messagesCreate(req) };
5480
5537
  this.contract = { register: (c) => this.registerContract(c) };
5481
5538
  this.availability = { mark: (req, opts) => this.markAvailability(req, opts) };
@@ -5531,6 +5588,52 @@ var HolonographClient = class {
5531
5588
  return this.inProcessTransport ? this.inProcessTransport.topology : null;
5532
5589
  }
5533
5590
 
5591
+ fetchDeclaredColumns(force = false) {
5592
+ const getContract = this.transport.getContract?.bind(this.transport);
5593
+ if (getContract === void 0) return Promise.resolve(null);
5594
+ if (this.declaredColumns === void 0 || force) {
5595
+ this.declaredColumns = getContract().then(
5596
+ (c) => {
5597
+ const union = new Set();
5598
+ for (const surface of c.surfaces) {
5599
+ for (const id of surface.substrateColumnIds ?? []) union.add(id);
5600
+ }
5601
+ return union;
5602
+ },
5603
+ () => null
5604
+ );
5605
+ }
5606
+ return this.declaredColumns;
5607
+ }
5608
+
5609
+ async validateSubstrateColumns(columns) {
5610
+ if (columns === void 0 || this.onUnknownColumn === "ignore" || this.transport.getContract === void 0) {
5611
+ return;
5612
+ }
5613
+ const keys = Object.keys(columns);
5614
+ if (keys.length === 0) return;
5615
+ const declared = await this.fetchDeclaredColumns();
5616
+ if (declared === null || declared.size === 0) return;
5617
+ let unknown = keys.filter((k) => !declared.has(k));
5618
+ if (unknown.length > 0 && !this.refreshedColumnsOnce) {
5619
+ this.refreshedColumnsOnce = true;
5620
+ const refreshed = await this.fetchDeclaredColumns(true);
5621
+ if (refreshed === null || refreshed.size === 0) return;
5622
+ unknown = keys.filter((k) => !refreshed.has(k));
5623
+ }
5624
+ if (unknown.length === 0) return;
5625
+ if (this.onUnknownColumn === "throw") {
5626
+ throw new Error(
5627
+ `Holonograph: substrate column(s) declared in no surface contract: ${unknown.join(", ")}. Declare them on the surface contract or fix the typo. (onUnknownColumn: 'throw')`
5628
+ );
5629
+ }
5630
+ const toWarn = unknown.filter((k) => !this.warnedColumns.has(k));
5631
+ if (toWarn.length === 0) return;
5632
+ for (const k of toWarn) this.warnedColumns.add(k);
5633
+ console.warn(
5634
+ `Holonograph: substrate column(s) declared in no surface contract: ${toWarn.join(", ")}. They are still emitted, but the lens won't recognize them \u2014 declare them on the contract or fix the typo. (onUnknownColumn: 'throw' to block, 'ignore' to silence.)`
5635
+ );
5636
+ }
5534
5637
  async registerContract(contract) {
5535
5638
  if (typeof this.transport.postContract !== "function") {
5536
5639
  throw new Error(
@@ -5627,6 +5730,7 @@ var HolonographClient = class {
5627
5730
  substrate: { ...this.substrate, lightSourceIdentifier: callResult.record.lightSourceId },
5628
5731
  surface
5629
5732
  });
5733
+ await this.validateSubstrateColumns(event.substrate?.columns);
5630
5734
  await this.transport.appendEvent(event);
5631
5735
  if (callResult.observerRecords && callResult.observerRecords.length > 0) {
5632
5736
  const siblingCohortTags = baseCohortTags;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holonograph/client",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "TypeScript HTTP client for a Holonograph lens. Send messages through the lens and report scored outcomes back to it.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -18,15 +18,7 @@
18
18
  "engines": {
19
19
  "node": ">=18"
20
20
  },
21
- "keywords": [
22
- "holonograph",
23
- "llm",
24
- "evaluation",
25
- "observability",
26
- "sdk",
27
- "client",
28
- "typescript"
29
- ],
21
+ "keywords": ["holonograph", "llm", "evaluation", "observability", "sdk", "client", "typescript"],
30
22
  "repository": {
31
23
  "type": "git",
32
24
  "url": "git+https://github.com/holonograph/client.git"