@granular-software/sdk 0.4.16 → 0.4.18

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/index.d.mts CHANGED
@@ -359,7 +359,7 @@ interface BuildListResponse {
359
359
  }
360
360
  interface SemanticVersionDiffEntry {
361
361
  operationId: string;
362
- kind: 'create' | 'update' | 'relationship' | 'effect' | 'unknown';
362
+ kind: 'create' | 'update' | 'relationship' | 'effect' | 'eventStream' | 'unknown';
363
363
  changeType: 'added' | 'removed' | 'changed';
364
364
  label: string;
365
365
  additive: boolean;
@@ -1024,6 +1024,22 @@ interface ManifestEffectDeclaration {
1024
1024
  tags?: string[];
1025
1025
  metamodels?: ManifestEffectMetamodelSpec;
1026
1026
  }
1027
+ /**
1028
+ * An event type within an event stream definition
1029
+ */
1030
+ interface ManifestEventTypeDef {
1031
+ name: string;
1032
+ description?: string;
1033
+ payloadSchema: ManifestEffectSchema;
1034
+ }
1035
+ /**
1036
+ * Event stream definition for outgoing typed events
1037
+ */
1038
+ interface ManifestEventStreamDef {
1039
+ name: string;
1040
+ description?: string;
1041
+ eventTypes: ManifestEventTypeDef[];
1042
+ }
1027
1043
  /**
1028
1044
  * A single operation in a manifest volume
1029
1045
  */
@@ -1046,6 +1062,8 @@ interface ManifestOperation {
1046
1062
  defineRelationship?: ManifestRelationshipDef;
1047
1063
  /** Declare a build-owned effect */
1048
1064
  withEffect?: ManifestEffectDeclaration;
1065
+ /** Define an outgoing event stream with typed events */
1066
+ defineEventStream?: ManifestEventStreamDef;
1049
1067
  }
1050
1068
  /**
1051
1069
  * A volume in a manifest
@@ -1098,6 +1116,29 @@ interface APIError {
1098
1116
  interface DeleteResponse {
1099
1117
  deleted: boolean;
1100
1118
  }
1119
+ interface StreamEvent {
1120
+ eventId: string;
1121
+ streamName: string;
1122
+ eventType: string;
1123
+ payload: Record<string, unknown>;
1124
+ environmentId: string;
1125
+ sessionId?: string;
1126
+ subjectId?: string;
1127
+ source: 'sandbox' | 'api';
1128
+ isAcked: boolean;
1129
+ createdAt: number;
1130
+ }
1131
+ interface StreamSubscription {
1132
+ unsubscribe(): void;
1133
+ }
1134
+ interface StreamStats {
1135
+ streamName: string;
1136
+ eventType: string;
1137
+ total: number;
1138
+ last1h: number;
1139
+ last24h: number;
1140
+ unacked: number;
1141
+ }
1101
1142
 
1102
1143
  declare class WSClient {
1103
1144
  private ws;
@@ -1593,6 +1634,8 @@ declare class Environment extends Session {
1593
1634
  private _ensureWorkspaceToolsRoot;
1594
1635
  private _storeEffectSchemas;
1595
1636
  private _applyEffectMetamodels;
1637
+ private _ensureWorkspaceStreamsRoot;
1638
+ private _applyEventStreamDeclaration;
1596
1639
  private _applyEffectDeclaration;
1597
1640
  /**
1598
1641
  * Apply a single manifest operation via GraphQL
@@ -1696,6 +1739,7 @@ declare class Granular {
1696
1739
  private WebSocketCtor?;
1697
1740
  private onUnexpectedClose?;
1698
1741
  private onReconnectError?;
1742
+ private debugHttp;
1699
1743
  /** Sandbox-level effect registry: sandboxId → (effectKey → ToolWithHandler) */
1700
1744
  private sandboxEffects;
1701
1745
  /** Live sandbox-scoped effect hosts keyed by sandboxId */
@@ -1887,6 +1931,40 @@ declare class Granular {
1887
1931
  create: (sandboxId: string, data: CreateEnvironmentData) => Promise<EnvironmentData>;
1888
1932
  delete: (environmentId: string) => Promise<DeleteResponse>;
1889
1933
  };
1934
+ /**
1935
+ * Event stream operations: query, subscribe, and acknowledge stream events
1936
+ */
1937
+ get streams(): {
1938
+ getEvents: (params: {
1939
+ ontology: string;
1940
+ stream: string;
1941
+ environment?: string;
1942
+ session?: string;
1943
+ eventTypes?: string[];
1944
+ since?: Date;
1945
+ until?: Date;
1946
+ isAcked?: boolean;
1947
+ limit?: number;
1948
+ offset?: number;
1949
+ }) => Promise<StreamEvent[]>;
1950
+ subscribe: (params: {
1951
+ ontology: string;
1952
+ stream: string;
1953
+ environment?: string;
1954
+ session?: string;
1955
+ eventTypes?: string[];
1956
+ since?: Date;
1957
+ onEvent: (event: StreamEvent) => void;
1958
+ onError?: (err: Error) => void;
1959
+ pollIntervalMs?: number;
1960
+ }) => StreamSubscription;
1961
+ ack: (eventId: string) => Promise<void>;
1962
+ ackBatch: (eventIds: string[]) => Promise<void>;
1963
+ getStats: (params: {
1964
+ ontology: string;
1965
+ environment?: string;
1966
+ }) => Promise<StreamStats[]>;
1967
+ };
1890
1968
  /**
1891
1969
  * Subject management
1892
1970
  */
@@ -1905,6 +1983,7 @@ declare class Granular {
1905
1983
  }) => Promise<Subject>;
1906
1984
  get: (id: string) => Promise<Subject>;
1907
1985
  };
1986
+ private _resolveSandboxId;
1908
1987
  /**
1909
1988
  * Make an authenticated API request
1910
1989
  */
@@ -1920,4 +1999,4 @@ type EffectRuntimeRequest = {
1920
1999
  declare function normalizeEffectBehaviors(value?: ManifestEffectMetamodelSpec | ResolvedEffectBehaviors | null): ResolvedEffectBehaviors;
1921
2000
  declare function invokeRegisteredEffect(effectMap: Map<string, ToolWithHandler>, request: EffectRuntimeRequest): Promise<unknown>;
1922
2001
 
1923
- export { type APIError, type AccessTokenProvider, type Assignment, type AssignmentListResponse, type Build, type BuildListResponse, type BuildPolicy, type BuildStatus, type ConnectOptions, type ConversationSessionInfo, type CreateEnvironmentData, type CreatePermissionProfileData, type CreateSandboxData, type DefineRelationshipOptions, type DeleteResponse, type DomainState, type EffectHandler, type EffectHandlerContext, type EffectInfo, type EffectInvocationMetadata, type EffectInvocationMode, type EffectSchema, type EffectWithHandler, type EffectsChangedEvent, type EndpointMode, Environment, type EnvironmentData, type EnvironmentListResponse, type EnvironmentRecordImportSummary, Granular, type GranularAuth, type GranularOptions, type GraphQLResult, type InstanceEffectHandler, type InstanceToolHandler, type Job, type JobFeedbackInput, type JobFeedbackMetadata, type JobFeedbackRecord, type JobFeedbackSentiment, type JobFeedbackToolCall, type JobStatus, type JobSubmitResult, type Manifest, type ManifestApprovalRequiredSpec, type ManifestContent, type ManifestDryRunSpec, type ManifestEffectDeclaration, type ManifestEffectMetamodelSpec, type ManifestEffectSchema, type ManifestEnumRuleSpec, type ManifestFilterBySpec, type ManifestImport, type ManifestListResponse, type ManifestOperation, type ManifestPostConditionSpec, type ManifestPropertySpec, type ManifestRelationshipDef, type ManifestReverseSpec, type ManifestStateMachineSpec, type ManifestStateMachineStateSpec, type ManifestStateMachineTransitionSpec, type ManifestValidationOperator, type ManifestValidationRuleSpec, type ManifestVolume, type ModelRef, type PermissionProfile, type PermissionProfileListResponse, type PermissionRules, type Prompt, type PublishEffectsResult, type PublishToolsResult, type RPCRequest, type RPCRequestFromServer, type RPCResponse, type RecordImport, type RecordImportItem, type RecordImportItemStatus, type RecordImportStats, type RecordImportStatus, type RecordObjectOptions, type RecordObjectResult, type RecordUserOptions, type RelationshipInfo, type ResolvedEffectApprovalRequired, type ResolvedEffectBehaviors, type ResolvedEffectDryRun, type ResolvedEffectPostCondition, type ResolvedEffectReverse, type Sandbox, type SandboxListResponse, type SemanticVersionDiff, type SemanticVersionDiffEntry, Session, type SessionHeapEntry, type SessionHeapFieldType, type SessionHeapFieldValue, type SessionHeapList, type SessionHeapSnapshot, type SessionHeapVariable, type Subject, type SyncMessage, type ToolHandler, type ToolInfo, type ToolInvokeParams, type ToolResultParams, type ToolSchema, type ToolWithHandler, type ToolsChangedEvent, type User, type Version, type VersionTag, type VersionTracking, WSClient, type WSClientOptions, type WSDisconnectInfo, type WSReconnectErrorInfo, invokeRegisteredEffect, normalizeEffectBehaviors };
2002
+ export { type APIError, type AccessTokenProvider, type Assignment, type AssignmentListResponse, type Build, type BuildListResponse, type BuildPolicy, type BuildStatus, type ConnectOptions, type ConversationSessionInfo, type CreateEnvironmentData, type CreatePermissionProfileData, type CreateSandboxData, type DefineRelationshipOptions, type DeleteResponse, type DomainState, type EffectHandler, type EffectHandlerContext, type EffectInfo, type EffectInvocationMetadata, type EffectInvocationMode, type EffectSchema, type EffectWithHandler, type EffectsChangedEvent, type EndpointMode, Environment, type EnvironmentData, type EnvironmentListResponse, type EnvironmentRecordImportSummary, Granular, type GranularAuth, type GranularOptions, type GraphQLResult, type InstanceEffectHandler, type InstanceToolHandler, type Job, type JobFeedbackInput, type JobFeedbackMetadata, type JobFeedbackRecord, type JobFeedbackSentiment, type JobFeedbackToolCall, type JobStatus, type JobSubmitResult, type Manifest, type ManifestApprovalRequiredSpec, type ManifestContent, type ManifestDryRunSpec, type ManifestEffectDeclaration, type ManifestEffectMetamodelSpec, type ManifestEffectSchema, type ManifestEnumRuleSpec, type ManifestEventStreamDef, type ManifestEventTypeDef, type ManifestFilterBySpec, type ManifestImport, type ManifestListResponse, type ManifestOperation, type ManifestPostConditionSpec, type ManifestPropertySpec, type ManifestRelationshipDef, type ManifestReverseSpec, type ManifestStateMachineSpec, type ManifestStateMachineStateSpec, type ManifestStateMachineTransitionSpec, type ManifestValidationOperator, type ManifestValidationRuleSpec, type ManifestVolume, type ModelRef, type PermissionProfile, type PermissionProfileListResponse, type PermissionRules, type Prompt, type PublishEffectsResult, type PublishToolsResult, type RPCRequest, type RPCRequestFromServer, type RPCResponse, type RecordImport, type RecordImportItem, type RecordImportItemStatus, type RecordImportStats, type RecordImportStatus, type RecordObjectOptions, type RecordObjectResult, type RecordUserOptions, type RelationshipInfo, type ResolvedEffectApprovalRequired, type ResolvedEffectBehaviors, type ResolvedEffectDryRun, type ResolvedEffectPostCondition, type ResolvedEffectReverse, type Sandbox, type SandboxListResponse, type SemanticVersionDiff, type SemanticVersionDiffEntry, Session, type SessionHeapEntry, type SessionHeapFieldType, type SessionHeapFieldValue, type SessionHeapList, type SessionHeapSnapshot, type SessionHeapVariable, type StreamEvent, type StreamStats, type StreamSubscription, type Subject, type SyncMessage, type ToolHandler, type ToolInfo, type ToolInvokeParams, type ToolResultParams, type ToolSchema, type ToolWithHandler, type ToolsChangedEvent, type User, type Version, type VersionTag, type VersionTracking, WSClient, type WSClientOptions, type WSDisconnectInfo, type WSReconnectErrorInfo, invokeRegisteredEffect, normalizeEffectBehaviors };
package/dist/index.d.ts CHANGED
@@ -359,7 +359,7 @@ interface BuildListResponse {
359
359
  }
360
360
  interface SemanticVersionDiffEntry {
361
361
  operationId: string;
362
- kind: 'create' | 'update' | 'relationship' | 'effect' | 'unknown';
362
+ kind: 'create' | 'update' | 'relationship' | 'effect' | 'eventStream' | 'unknown';
363
363
  changeType: 'added' | 'removed' | 'changed';
364
364
  label: string;
365
365
  additive: boolean;
@@ -1024,6 +1024,22 @@ interface ManifestEffectDeclaration {
1024
1024
  tags?: string[];
1025
1025
  metamodels?: ManifestEffectMetamodelSpec;
1026
1026
  }
1027
+ /**
1028
+ * An event type within an event stream definition
1029
+ */
1030
+ interface ManifestEventTypeDef {
1031
+ name: string;
1032
+ description?: string;
1033
+ payloadSchema: ManifestEffectSchema;
1034
+ }
1035
+ /**
1036
+ * Event stream definition for outgoing typed events
1037
+ */
1038
+ interface ManifestEventStreamDef {
1039
+ name: string;
1040
+ description?: string;
1041
+ eventTypes: ManifestEventTypeDef[];
1042
+ }
1027
1043
  /**
1028
1044
  * A single operation in a manifest volume
1029
1045
  */
@@ -1046,6 +1062,8 @@ interface ManifestOperation {
1046
1062
  defineRelationship?: ManifestRelationshipDef;
1047
1063
  /** Declare a build-owned effect */
1048
1064
  withEffect?: ManifestEffectDeclaration;
1065
+ /** Define an outgoing event stream with typed events */
1066
+ defineEventStream?: ManifestEventStreamDef;
1049
1067
  }
1050
1068
  /**
1051
1069
  * A volume in a manifest
@@ -1098,6 +1116,29 @@ interface APIError {
1098
1116
  interface DeleteResponse {
1099
1117
  deleted: boolean;
1100
1118
  }
1119
+ interface StreamEvent {
1120
+ eventId: string;
1121
+ streamName: string;
1122
+ eventType: string;
1123
+ payload: Record<string, unknown>;
1124
+ environmentId: string;
1125
+ sessionId?: string;
1126
+ subjectId?: string;
1127
+ source: 'sandbox' | 'api';
1128
+ isAcked: boolean;
1129
+ createdAt: number;
1130
+ }
1131
+ interface StreamSubscription {
1132
+ unsubscribe(): void;
1133
+ }
1134
+ interface StreamStats {
1135
+ streamName: string;
1136
+ eventType: string;
1137
+ total: number;
1138
+ last1h: number;
1139
+ last24h: number;
1140
+ unacked: number;
1141
+ }
1101
1142
 
1102
1143
  declare class WSClient {
1103
1144
  private ws;
@@ -1593,6 +1634,8 @@ declare class Environment extends Session {
1593
1634
  private _ensureWorkspaceToolsRoot;
1594
1635
  private _storeEffectSchemas;
1595
1636
  private _applyEffectMetamodels;
1637
+ private _ensureWorkspaceStreamsRoot;
1638
+ private _applyEventStreamDeclaration;
1596
1639
  private _applyEffectDeclaration;
1597
1640
  /**
1598
1641
  * Apply a single manifest operation via GraphQL
@@ -1696,6 +1739,7 @@ declare class Granular {
1696
1739
  private WebSocketCtor?;
1697
1740
  private onUnexpectedClose?;
1698
1741
  private onReconnectError?;
1742
+ private debugHttp;
1699
1743
  /** Sandbox-level effect registry: sandboxId → (effectKey → ToolWithHandler) */
1700
1744
  private sandboxEffects;
1701
1745
  /** Live sandbox-scoped effect hosts keyed by sandboxId */
@@ -1887,6 +1931,40 @@ declare class Granular {
1887
1931
  create: (sandboxId: string, data: CreateEnvironmentData) => Promise<EnvironmentData>;
1888
1932
  delete: (environmentId: string) => Promise<DeleteResponse>;
1889
1933
  };
1934
+ /**
1935
+ * Event stream operations: query, subscribe, and acknowledge stream events
1936
+ */
1937
+ get streams(): {
1938
+ getEvents: (params: {
1939
+ ontology: string;
1940
+ stream: string;
1941
+ environment?: string;
1942
+ session?: string;
1943
+ eventTypes?: string[];
1944
+ since?: Date;
1945
+ until?: Date;
1946
+ isAcked?: boolean;
1947
+ limit?: number;
1948
+ offset?: number;
1949
+ }) => Promise<StreamEvent[]>;
1950
+ subscribe: (params: {
1951
+ ontology: string;
1952
+ stream: string;
1953
+ environment?: string;
1954
+ session?: string;
1955
+ eventTypes?: string[];
1956
+ since?: Date;
1957
+ onEvent: (event: StreamEvent) => void;
1958
+ onError?: (err: Error) => void;
1959
+ pollIntervalMs?: number;
1960
+ }) => StreamSubscription;
1961
+ ack: (eventId: string) => Promise<void>;
1962
+ ackBatch: (eventIds: string[]) => Promise<void>;
1963
+ getStats: (params: {
1964
+ ontology: string;
1965
+ environment?: string;
1966
+ }) => Promise<StreamStats[]>;
1967
+ };
1890
1968
  /**
1891
1969
  * Subject management
1892
1970
  */
@@ -1905,6 +1983,7 @@ declare class Granular {
1905
1983
  }) => Promise<Subject>;
1906
1984
  get: (id: string) => Promise<Subject>;
1907
1985
  };
1986
+ private _resolveSandboxId;
1908
1987
  /**
1909
1988
  * Make an authenticated API request
1910
1989
  */
@@ -1920,4 +1999,4 @@ type EffectRuntimeRequest = {
1920
1999
  declare function normalizeEffectBehaviors(value?: ManifestEffectMetamodelSpec | ResolvedEffectBehaviors | null): ResolvedEffectBehaviors;
1921
2000
  declare function invokeRegisteredEffect(effectMap: Map<string, ToolWithHandler>, request: EffectRuntimeRequest): Promise<unknown>;
1922
2001
 
1923
- export { type APIError, type AccessTokenProvider, type Assignment, type AssignmentListResponse, type Build, type BuildListResponse, type BuildPolicy, type BuildStatus, type ConnectOptions, type ConversationSessionInfo, type CreateEnvironmentData, type CreatePermissionProfileData, type CreateSandboxData, type DefineRelationshipOptions, type DeleteResponse, type DomainState, type EffectHandler, type EffectHandlerContext, type EffectInfo, type EffectInvocationMetadata, type EffectInvocationMode, type EffectSchema, type EffectWithHandler, type EffectsChangedEvent, type EndpointMode, Environment, type EnvironmentData, type EnvironmentListResponse, type EnvironmentRecordImportSummary, Granular, type GranularAuth, type GranularOptions, type GraphQLResult, type InstanceEffectHandler, type InstanceToolHandler, type Job, type JobFeedbackInput, type JobFeedbackMetadata, type JobFeedbackRecord, type JobFeedbackSentiment, type JobFeedbackToolCall, type JobStatus, type JobSubmitResult, type Manifest, type ManifestApprovalRequiredSpec, type ManifestContent, type ManifestDryRunSpec, type ManifestEffectDeclaration, type ManifestEffectMetamodelSpec, type ManifestEffectSchema, type ManifestEnumRuleSpec, type ManifestFilterBySpec, type ManifestImport, type ManifestListResponse, type ManifestOperation, type ManifestPostConditionSpec, type ManifestPropertySpec, type ManifestRelationshipDef, type ManifestReverseSpec, type ManifestStateMachineSpec, type ManifestStateMachineStateSpec, type ManifestStateMachineTransitionSpec, type ManifestValidationOperator, type ManifestValidationRuleSpec, type ManifestVolume, type ModelRef, type PermissionProfile, type PermissionProfileListResponse, type PermissionRules, type Prompt, type PublishEffectsResult, type PublishToolsResult, type RPCRequest, type RPCRequestFromServer, type RPCResponse, type RecordImport, type RecordImportItem, type RecordImportItemStatus, type RecordImportStats, type RecordImportStatus, type RecordObjectOptions, type RecordObjectResult, type RecordUserOptions, type RelationshipInfo, type ResolvedEffectApprovalRequired, type ResolvedEffectBehaviors, type ResolvedEffectDryRun, type ResolvedEffectPostCondition, type ResolvedEffectReverse, type Sandbox, type SandboxListResponse, type SemanticVersionDiff, type SemanticVersionDiffEntry, Session, type SessionHeapEntry, type SessionHeapFieldType, type SessionHeapFieldValue, type SessionHeapList, type SessionHeapSnapshot, type SessionHeapVariable, type Subject, type SyncMessage, type ToolHandler, type ToolInfo, type ToolInvokeParams, type ToolResultParams, type ToolSchema, type ToolWithHandler, type ToolsChangedEvent, type User, type Version, type VersionTag, type VersionTracking, WSClient, type WSClientOptions, type WSDisconnectInfo, type WSReconnectErrorInfo, invokeRegisteredEffect, normalizeEffectBehaviors };
2002
+ export { type APIError, type AccessTokenProvider, type Assignment, type AssignmentListResponse, type Build, type BuildListResponse, type BuildPolicy, type BuildStatus, type ConnectOptions, type ConversationSessionInfo, type CreateEnvironmentData, type CreatePermissionProfileData, type CreateSandboxData, type DefineRelationshipOptions, type DeleteResponse, type DomainState, type EffectHandler, type EffectHandlerContext, type EffectInfo, type EffectInvocationMetadata, type EffectInvocationMode, type EffectSchema, type EffectWithHandler, type EffectsChangedEvent, type EndpointMode, Environment, type EnvironmentData, type EnvironmentListResponse, type EnvironmentRecordImportSummary, Granular, type GranularAuth, type GranularOptions, type GraphQLResult, type InstanceEffectHandler, type InstanceToolHandler, type Job, type JobFeedbackInput, type JobFeedbackMetadata, type JobFeedbackRecord, type JobFeedbackSentiment, type JobFeedbackToolCall, type JobStatus, type JobSubmitResult, type Manifest, type ManifestApprovalRequiredSpec, type ManifestContent, type ManifestDryRunSpec, type ManifestEffectDeclaration, type ManifestEffectMetamodelSpec, type ManifestEffectSchema, type ManifestEnumRuleSpec, type ManifestEventStreamDef, type ManifestEventTypeDef, type ManifestFilterBySpec, type ManifestImport, type ManifestListResponse, type ManifestOperation, type ManifestPostConditionSpec, type ManifestPropertySpec, type ManifestRelationshipDef, type ManifestReverseSpec, type ManifestStateMachineSpec, type ManifestStateMachineStateSpec, type ManifestStateMachineTransitionSpec, type ManifestValidationOperator, type ManifestValidationRuleSpec, type ManifestVolume, type ModelRef, type PermissionProfile, type PermissionProfileListResponse, type PermissionRules, type Prompt, type PublishEffectsResult, type PublishToolsResult, type RPCRequest, type RPCRequestFromServer, type RPCResponse, type RecordImport, type RecordImportItem, type RecordImportItemStatus, type RecordImportStats, type RecordImportStatus, type RecordObjectOptions, type RecordObjectResult, type RecordUserOptions, type RelationshipInfo, type ResolvedEffectApprovalRequired, type ResolvedEffectBehaviors, type ResolvedEffectDryRun, type ResolvedEffectPostCondition, type ResolvedEffectReverse, type Sandbox, type SandboxListResponse, type SemanticVersionDiff, type SemanticVersionDiffEntry, Session, type SessionHeapEntry, type SessionHeapFieldType, type SessionHeapFieldValue, type SessionHeapList, type SessionHeapSnapshot, type SessionHeapVariable, type StreamEvent, type StreamStats, type StreamSubscription, type Subject, type SyncMessage, type ToolHandler, type ToolInfo, type ToolInvokeParams, type ToolResultParams, type ToolSchema, type ToolWithHandler, type ToolsChangedEvent, type User, type Version, type VersionTag, type VersionTracking, WSClient, type WSClientOptions, type WSDisconnectInfo, type WSReconnectErrorInfo, invokeRegisteredEffect, normalizeEffectBehaviors };
package/dist/index.js CHANGED
@@ -3950,6 +3950,12 @@ var READY_STATE_OPEN = 1;
3950
3950
  var TOKEN_REFRESH_LEEWAY_MS = 2 * 60 * 1e3;
3951
3951
  var TOKEN_REFRESH_RETRY_MS = 30 * 1e3;
3952
3952
  var MAX_TIMER_DELAY_MS = 2147483647;
3953
+ var DEBUG_WS = process.env.GRANULAR_DEBUG_WS === "1";
3954
+ function debugWs(...args) {
3955
+ if (DEBUG_WS) {
3956
+ console.log(...args);
3957
+ }
3958
+ }
3953
3959
  var WSClient = class {
3954
3960
  ws = null;
3955
3961
  url;
@@ -4249,7 +4255,7 @@ var WSClient = class {
4249
4255
  }
4250
4256
  handleMessage(message) {
4251
4257
  if (typeof message !== "object" || message === null) return;
4252
- console.log("[Granular DEBUG] Received message:", JSON.stringify(message).slice(0, 500));
4258
+ debugWs("[Granular DEBUG] Received message:", JSON.stringify(message).slice(0, 500));
4253
4259
  if ("type" in message && message.type === "sync") {
4254
4260
  const syncMessage = message;
4255
4261
  let bytes;
@@ -4269,7 +4275,7 @@ var WSClient = class {
4269
4275
  } else {
4270
4276
  return;
4271
4277
  }
4272
- console.log("[Granular DEBUG] Applying sync bytes:", bytes.length);
4278
+ debugWs("[Granular DEBUG] Applying sync bytes:", bytes.length);
4273
4279
  const [newDoc, newSyncState] = Automerge__namespace.receiveSyncMessage(
4274
4280
  this.doc,
4275
4281
  this.syncState,
@@ -4279,19 +4285,19 @@ var WSClient = class {
4279
4285
  this.syncState = newSyncState;
4280
4286
  const docAny = this.doc;
4281
4287
  if (docAny.catalog) {
4282
- console.log("[Granular DEBUG] Doc catalog sync applied. Keys in catalog:", Object.keys(docAny.catalog || {}));
4283
- console.log("[Granular DEBUG] RawToolCatalogs:", Object.keys(docAny.catalog.rawToolCatalogs || {}));
4288
+ debugWs("[Granular DEBUG] Doc catalog sync applied. Keys in catalog:", Object.keys(docAny.catalog || {}));
4289
+ debugWs("[Granular DEBUG] RawToolCatalogs:", Object.keys(docAny.catalog.rawToolCatalogs || {}));
4284
4290
  } else {
4285
- console.log("[Granular DEBUG] Doc synced but no catalog yet. Keys in doc:", Object.keys(docAny));
4291
+ debugWs("[Granular DEBUG] Doc synced but no catalog yet. Keys in doc:", Object.keys(docAny));
4286
4292
  }
4287
4293
  this.emit("sync", this.doc);
4288
4294
  } catch (e) {
4289
4295
  try {
4290
- console.log("[Granular DEBUG] receiveSyncMessage failed, trying applyChanges...");
4296
+ debugWs("[Granular DEBUG] receiveSyncMessage failed, trying applyChanges...");
4291
4297
  const [newDoc] = Automerge__namespace.applyChanges(this.doc, [bytes]);
4292
4298
  this.doc = newDoc;
4293
4299
  this.emit("sync", this.doc);
4294
- console.log("[Granular DEBUG] applyChanges succeeded. Doc:", JSON.stringify(Automerge__namespace.toJS(this.doc)));
4300
+ debugWs("[Granular DEBUG] applyChanges succeeded. Doc:", JSON.stringify(Automerge__namespace.toJS(this.doc)));
4295
4301
  } catch (applyError) {
4296
4302
  console.warn("[Granular] Failed to apply sync message (both sync & applyChanges)", e, applyError);
4297
4303
  }
@@ -4302,10 +4308,10 @@ var WSClient = class {
4302
4308
  const snapshotMessage = message;
4303
4309
  try {
4304
4310
  const bytes = new Uint8Array(snapshotMessage.data);
4305
- console.log("[Granular DEBUG] Loading Automerge session snapshot bytes:", bytes.length);
4311
+ debugWs("[Granular DEBUG] Loading Automerge session snapshot bytes:", bytes.length);
4306
4312
  this.doc = Automerge__namespace.load(bytes);
4307
4313
  this.emit("sync", this.doc);
4308
- console.log("[Granular DEBUG] Automerge session snapshot loaded. Doc:", JSON.stringify(Automerge__namespace.toJS(this.doc)));
4314
+ debugWs("[Granular DEBUG] Automerge session snapshot loaded. Doc:", JSON.stringify(Automerge__namespace.toJS(this.doc)));
4309
4315
  } catch (e) {
4310
4316
  console.warn("[Granular] Failed to load snapshot message", e);
4311
4317
  }
@@ -11343,6 +11349,7 @@ var Environment = class extends Session {
11343
11349
  headers: {
11344
11350
  "Authorization": `Bearer ${this._apiKey}`,
11345
11351
  "Content-Type": "application/json",
11352
+ "Connection": "close",
11346
11353
  ...options.headers
11347
11354
  }
11348
11355
  });
@@ -11377,7 +11384,8 @@ var Environment = class extends Session {
11377
11384
  method: "POST",
11378
11385
  headers: {
11379
11386
  "Content-Type": "application/json",
11380
- "Authorization": `Bearer ${this._apiKey}`
11387
+ "Authorization": `Bearer ${this._apiKey}`,
11388
+ "Connection": "close"
11381
11389
  },
11382
11390
  body: JSON.stringify({
11383
11391
  reason: "sdk_disconnect_http_fallback",
@@ -11837,6 +11845,70 @@ var Environment = class extends Session {
11837
11845
  await this._runGraphql(mutation.query, mutation.label);
11838
11846
  }
11839
11847
  }
11848
+ async _ensureWorkspaceStreamsRoot() {
11849
+ await this._runGraphql(
11850
+ `mutation { create_model(path: "workspace", label: "workspace") { model { path } } }`,
11851
+ "ensure workspace"
11852
+ ).catch((error) => {
11853
+ if (!error.message.includes("already exists")) throw error;
11854
+ });
11855
+ await this._runGraphql(
11856
+ `mutation { at(path: "workspace") { create_submodel(subpath: "streams", label: "Streams") { model { path } } } }`,
11857
+ "ensure workspace:streams"
11858
+ ).catch((error) => {
11859
+ if (!error.message.includes("already exists")) throw error;
11860
+ });
11861
+ }
11862
+ async _applyEventStreamDeclaration(stream) {
11863
+ await this._ensureWorkspaceStreamsRoot();
11864
+ const streamPath = `workspace:streams:${stream.name}`;
11865
+ await this._runGraphql(
11866
+ `mutation { at(path: "workspace:streams") { create_submodel(subpath: ${JSON.stringify(stream.name)}, label: ${JSON.stringify(stream.name)}) { model { path } } } }`,
11867
+ `create stream ${stream.name}`
11868
+ ).catch((error) => {
11869
+ if (!error.message.includes("already exists")) throw error;
11870
+ });
11871
+ if (stream.description) {
11872
+ await this._runGraphql(
11873
+ `mutation { at(path: ${JSON.stringify(streamPath)}) { set_description(description: ${JSON.stringify(stream.description)}) { done } } }`,
11874
+ `set stream description on ${streamPath}`
11875
+ );
11876
+ }
11877
+ for (const eventType of stream.eventTypes) {
11878
+ const typePath = `${streamPath}:${eventType.name}`;
11879
+ await this._runGraphql(
11880
+ `mutation { at(path: ${JSON.stringify(streamPath)}) { create_submodel(subpath: ${JSON.stringify(eventType.name)}, label: ${JSON.stringify(eventType.name)}) { model { path } } } }`,
11881
+ `create event type ${eventType.name} on ${streamPath}`
11882
+ ).catch((error) => {
11883
+ if (!error.message.includes("already exists")) throw error;
11884
+ });
11885
+ if (eventType.description) {
11886
+ await this._runGraphql(
11887
+ `mutation { at(path: ${JSON.stringify(typePath)}) { set_description(description: ${JSON.stringify(eventType.description)}) { done } } }`,
11888
+ `set event type description on ${typePath}`
11889
+ );
11890
+ }
11891
+ if (eventType.payloadSchema?.properties) {
11892
+ const fieldSpecs = {};
11893
+ for (const [propName, propSchema] of Object.entries(eventType.payloadSchema.properties)) {
11894
+ const schema = propSchema;
11895
+ fieldSpecs[propName] = {
11896
+ type: schema.type ?? "string",
11897
+ description: schema.description
11898
+ };
11899
+ }
11900
+ await this._applyFields(typePath, fieldSpecs);
11901
+ }
11902
+ if (eventType.payloadSchema?.required?.length) {
11903
+ await this._runGraphql(
11904
+ `mutation { at(path: ${JSON.stringify(typePath)}) { create_submodel(subpath: "required", label: "required") { set_string_value(value: ${JSON.stringify(JSON.stringify(eventType.payloadSchema.required))}) { done } } } }`,
11905
+ `store required fields on ${typePath}`
11906
+ ).catch((error) => {
11907
+ if (!error.message.includes("already exists")) throw error;
11908
+ });
11909
+ }
11910
+ }
11911
+ }
11840
11912
  async _applyEffectDeclaration(effect, aliasMap) {
11841
11913
  let containerPath = "workspace:tools:declared";
11842
11914
  if (effect.attachedClass) {
@@ -11924,6 +11996,9 @@ var Environment = class extends Session {
11924
11996
  if (op.withEffect) {
11925
11997
  await this._applyEffectDeclaration(op.withEffect, aliasMap);
11926
11998
  }
11999
+ if (op.defineEventStream) {
12000
+ await this._applyEventStreamDeclaration(op.defineEventStream);
12001
+ }
11927
12002
  }
11928
12003
  /**
11929
12004
  * Apply field definitions (has) to a model via GraphQL
@@ -12173,6 +12248,7 @@ var Granular = class _Granular {
12173
12248
  WebSocketCtor;
12174
12249
  onUnexpectedClose;
12175
12250
  onReconnectError;
12251
+ debugHttp = process.env.GRANULAR_DEBUG_HTTP === "1";
12176
12252
  /** Sandbox-level effect registry: sandboxId → (effectKey → ToolWithHandler) */
12177
12253
  sandboxEffects = /* @__PURE__ */ new Map();
12178
12254
  /** Live sandbox-scoped effect hosts keyed by sandboxId */
@@ -12896,6 +12972,107 @@ var Granular = class _Granular {
12896
12972
  }
12897
12973
  };
12898
12974
  }
12975
+ /**
12976
+ * Event stream operations: query, subscribe, and acknowledge stream events
12977
+ */
12978
+ get streams() {
12979
+ return {
12980
+ getEvents: async (params) => {
12981
+ const sandbox = await this._resolveSandboxId(params.ontology);
12982
+ const query = new URLSearchParams({ sandboxId: sandbox });
12983
+ if (params.environment) query.set("environmentId", params.environment);
12984
+ if (params.session) query.set("sessionId", params.session);
12985
+ if (params.stream) query.set("streamName", params.stream);
12986
+ if (params.eventTypes && params.eventTypes.length > 0) {
12987
+ query.set("eventTypes", params.eventTypes.join(","));
12988
+ }
12989
+ if (params.since) query.set("since", params.since.toISOString());
12990
+ if (params.until) query.set("until", params.until.toISOString());
12991
+ if (params.isAcked !== void 0) query.set("isAcked", params.isAcked ? "1" : "0");
12992
+ if (params.limit) query.set("limit", String(params.limit));
12993
+ if (params.offset) query.set("offset", String(params.offset));
12994
+ const result = await this.request(`/control/stream-events?${query.toString()}`);
12995
+ return (result.items || []).map((row) => ({
12996
+ eventId: row.event_id,
12997
+ streamName: row.stream_name,
12998
+ eventType: row.event_type,
12999
+ payload: typeof row.payload === "string" ? JSON.parse(row.payload) : row.payload,
13000
+ environmentId: row.environment_id,
13001
+ sessionId: row.session_id,
13002
+ subjectId: row.subject_id,
13003
+ source: row.source,
13004
+ isAcked: Boolean(row.is_acked),
13005
+ createdAt: row.created_at
13006
+ }));
13007
+ },
13008
+ subscribe: (params) => {
13009
+ const interval = params.pollIntervalMs ?? 5e3;
13010
+ let cursor = params.since || /* @__PURE__ */ new Date();
13011
+ let running = true;
13012
+ const seenEventIds = /* @__PURE__ */ new Set();
13013
+ const poll = async () => {
13014
+ while (running) {
13015
+ try {
13016
+ const events = await this.streams.getEvents({
13017
+ ontology: params.ontology,
13018
+ stream: params.stream,
13019
+ environment: params.environment,
13020
+ session: params.session,
13021
+ eventTypes: params.eventTypes,
13022
+ since: cursor,
13023
+ limit: 100
13024
+ });
13025
+ const orderedEvents = [...events].sort((a, b) => a.createdAt - b.createdAt);
13026
+ for (const event of orderedEvents) {
13027
+ if (seenEventIds.has(event.eventId)) {
13028
+ continue;
13029
+ }
13030
+ seenEventIds.add(event.eventId);
13031
+ const eventTime = new Date(event.createdAt * 1e3);
13032
+ if (eventTime > cursor) {
13033
+ cursor = eventTime;
13034
+ }
13035
+ params.onEvent(event);
13036
+ }
13037
+ } catch (err) {
13038
+ params.onError?.(err instanceof Error ? err : new Error(String(err)));
13039
+ }
13040
+ await new Promise((resolve) => setTimeout(resolve, interval));
13041
+ }
13042
+ };
13043
+ poll();
13044
+ return { unsubscribe: () => {
13045
+ running = false;
13046
+ } };
13047
+ },
13048
+ ack: async (eventId) => {
13049
+ await this.request("/control/stream-events/ack", {
13050
+ method: "POST",
13051
+ body: JSON.stringify({ eventIds: [eventId] })
13052
+ });
13053
+ },
13054
+ ackBatch: async (eventIds) => {
13055
+ await this.request("/control/stream-events/ack", {
13056
+ method: "POST",
13057
+ body: JSON.stringify({ eventIds })
13058
+ });
13059
+ },
13060
+ getStats: async (params) => {
13061
+ const sandbox = await this._resolveSandboxId(params.ontology);
13062
+ const query = new URLSearchParams({ sandboxId: sandbox });
13063
+ if (params.environment) query.set("environmentId", params.environment);
13064
+ const result = await this.request(`/control/stream-events/stats?${query.toString()}`);
13065
+ return (result.items || []).map((row) => ({
13066
+ streamName: row.stream_name,
13067
+ eventType: row.event_type,
13068
+ total: Number(row.total),
13069
+ last1h: Number(row.last_1h),
13070
+ last24h: Number(row.last_24h),
13071
+ unacked: Number(row.unacked)
13072
+ }));
13073
+ }
13074
+ };
13075
+ }
12899
13076
  /**
12900
13077
  * Subject management
12901
13078
  */
@@ -12929,17 +13106,26 @@ var Granular = class _Granular {
12929
13106
  }
12930
13107
  };
12931
13108
  }
13109
+ async _resolveSandboxId(ontologyNameOrId) {
13110
+ if (ontologyNameOrId.startsWith("sbx_")) return ontologyNameOrId;
13111
+ const result = await this.request(`/control/sandboxes?name=${encodeURIComponent(ontologyNameOrId)}`);
13112
+ if (result.items.length === 0) throw new Error(`Ontology not found: ${ontologyNameOrId}`);
13113
+ return result.items[0].sandboxId;
13114
+ }
12932
13115
  /**
12933
13116
  * Make an authenticated API request
12934
13117
  */
12935
13118
  async request(path, options = {}) {
12936
13119
  const url = `${this.httpUrl}${path}`;
12937
- console.log(`[SDK] Requesting: ${url}`);
13120
+ if (this.debugHttp) {
13121
+ console.log(`[SDK] Requesting: ${url}`);
13122
+ }
12938
13123
  const response = await fetch(url, {
12939
13124
  ...options,
12940
13125
  headers: {
12941
13126
  "Authorization": `Bearer ${this.apiKey}`,
12942
13127
  "Content-Type": "application/json",
13128
+ "Connection": "close",
12943
13129
  ...options.headers
12944
13130
  }
12945
13131
  });