@granular-software/sdk 0.4.11 → 0.4.13
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/cli/index.js +124 -0
- package/dist/index.d.mts +130 -3
- package/dist/index.d.ts +130 -3
- package/dist/index.js +354 -68
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +353 -69
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var Automerge = require('@automerge/automerge');
|
|
4
|
+
var metamodelEffectBehaviors = require('@granular-software/metamodel-effect-behaviors');
|
|
5
|
+
var metamodelPresetDefault = require('@granular-software/metamodel-preset-default');
|
|
4
6
|
|
|
5
7
|
function _interopNamespace(e) {
|
|
6
8
|
if (e && e.__esModule) return e;
|
|
@@ -4650,7 +4652,7 @@ var Session = class {
|
|
|
4650
4652
|
* Respond to a prompt request from the sandbox
|
|
4651
4653
|
*/
|
|
4652
4654
|
async answerPrompt(promptId, answer) {
|
|
4653
|
-
await this.client.call("prompt.answer", { promptId, value: answer });
|
|
4655
|
+
await this.client.call("prompt.answer", { promptId, answer, value: answer });
|
|
4654
4656
|
}
|
|
4655
4657
|
/**
|
|
4656
4658
|
* Get the current list of available effects.
|
|
@@ -4967,13 +4969,31 @@ import { ${allImports} } from "./sandbox-tools";
|
|
|
4967
4969
|
});
|
|
4968
4970
|
}
|
|
4969
4971
|
setupEventHandlers() {
|
|
4972
|
+
this.client.on("open", (payload) => this.emit("open", payload || {}));
|
|
4970
4973
|
this.client.on("sync", (doc) => {
|
|
4971
4974
|
this.currentDomainRevision = this.extractDomainRevisionFromDoc(doc);
|
|
4972
4975
|
this.emit("sync", doc);
|
|
4973
4976
|
this.checkForToolChanges();
|
|
4974
4977
|
});
|
|
4975
|
-
|
|
4978
|
+
const emitPrompt = (payload) => {
|
|
4979
|
+
const raw = payload;
|
|
4980
|
+
const prompt = raw.prompt || {
|
|
4981
|
+
id: typeof raw.id === "string" ? raw.id : String(raw.promptId || ""),
|
|
4982
|
+
type: raw.type === "confirm" || raw.type === "choice" || raw.type === "input" ? raw.type : raw.promptType === "confirm" || raw.promptType === "choice" ? raw.promptType : "input",
|
|
4983
|
+
title: typeof raw.title === "string" ? raw.title : "Input required",
|
|
4984
|
+
message: typeof raw.message === "string" ? raw.message : "",
|
|
4985
|
+
options: raw.options,
|
|
4986
|
+
defaultValue: raw.defaultValue,
|
|
4987
|
+
placeholder: raw.placeholder,
|
|
4988
|
+
allowEmpty: raw.allowEmpty,
|
|
4989
|
+
metadata: raw.metadata
|
|
4990
|
+
};
|
|
4991
|
+
this.emit("prompt", prompt);
|
|
4992
|
+
};
|
|
4993
|
+
this.client.on("prompt", emitPrompt);
|
|
4994
|
+
this.client.on("prompt.request", emitPrompt);
|
|
4976
4995
|
this.client.on("disconnect", (payload) => this.emit("disconnect", payload || {}));
|
|
4996
|
+
this.client.on("reconnect_error", (payload) => this.emit("reconnect_error", payload || {}));
|
|
4977
4997
|
this.client.on("job.status", (data) => {
|
|
4978
4998
|
this.emit("job:status", data);
|
|
4979
4999
|
});
|
|
@@ -5045,6 +5065,8 @@ function normalizeJobStatus(status) {
|
|
|
5045
5065
|
case "failed":
|
|
5046
5066
|
case "running":
|
|
5047
5067
|
case "queued":
|
|
5068
|
+
case "awaitingTool":
|
|
5069
|
+
case "awaitingHuman":
|
|
5048
5070
|
case "succeeded":
|
|
5049
5071
|
case "timeout":
|
|
5050
5072
|
case "canceled":
|
|
@@ -5179,6 +5201,19 @@ var JobImplementation = class {
|
|
|
5179
5201
|
this.client.on(`job.${id}.error`, (error) => {
|
|
5180
5202
|
this.finalize("failed", void 0, error);
|
|
5181
5203
|
});
|
|
5204
|
+
this.client.on("job.status", (data) => {
|
|
5205
|
+
const jobData = data;
|
|
5206
|
+
if (jobData.jobId !== id) {
|
|
5207
|
+
return;
|
|
5208
|
+
}
|
|
5209
|
+
const normalizedStatus = normalizeJobStatus(jobData.status);
|
|
5210
|
+
this.status = normalizedStatus;
|
|
5211
|
+
this.metadata.status = normalizedStatus;
|
|
5212
|
+
if (normalizedStatus === "running") {
|
|
5213
|
+
this.markStarted();
|
|
5214
|
+
}
|
|
5215
|
+
this.emit("status", normalizedStatus);
|
|
5216
|
+
});
|
|
5182
5217
|
this.client.on("job.completed", (data) => {
|
|
5183
5218
|
const jobData = data;
|
|
5184
5219
|
if (jobData.jobId === id) {
|
|
@@ -5372,6 +5407,123 @@ function resolveApiUrl(explicitApiUrl, mode) {
|
|
|
5372
5407
|
}
|
|
5373
5408
|
return resolveEndpointMode(mode) === "local" ? LOCAL_API_URL : PRODUCTION_API_URL;
|
|
5374
5409
|
}
|
|
5410
|
+
function computeEffectKey(effect) {
|
|
5411
|
+
const attachedClass = effect.className?.trim();
|
|
5412
|
+
if (!attachedClass) {
|
|
5413
|
+
return `global:${effect.name}`;
|
|
5414
|
+
}
|
|
5415
|
+
return effect.static ? `class:${attachedClass}:static:${effect.name}` : `class:${attachedClass}:instance:${effect.name}`;
|
|
5416
|
+
}
|
|
5417
|
+
function normalizeEffectBehaviors(value) {
|
|
5418
|
+
return metamodelEffectBehaviors.normalizeEffectBehaviorSummary(
|
|
5419
|
+
value
|
|
5420
|
+
) || {};
|
|
5421
|
+
}
|
|
5422
|
+
function resolveInvocationMode(context) {
|
|
5423
|
+
const mode = context?.invocation?.mode;
|
|
5424
|
+
if (mode === "dryRun" || mode === "reverse") {
|
|
5425
|
+
return mode;
|
|
5426
|
+
}
|
|
5427
|
+
return "execute";
|
|
5428
|
+
}
|
|
5429
|
+
function resolveReverseEffect(effectMap, currentEffect, request, behaviors) {
|
|
5430
|
+
const explicitReverseHandler = request.context?.invocation?.reverseHandler?.trim();
|
|
5431
|
+
const configuredReverseHandler = behaviors.reverse?.handler?.trim();
|
|
5432
|
+
const reverseHandler = explicitReverseHandler || configuredReverseHandler;
|
|
5433
|
+
if (!reverseHandler) {
|
|
5434
|
+
return void 0;
|
|
5435
|
+
}
|
|
5436
|
+
if (reverseHandler.includes(":")) {
|
|
5437
|
+
return effectMap.get(reverseHandler);
|
|
5438
|
+
}
|
|
5439
|
+
const directMatch = effectMap.get(reverseHandler);
|
|
5440
|
+
if (directMatch) {
|
|
5441
|
+
return directMatch;
|
|
5442
|
+
}
|
|
5443
|
+
const candidateKeys = [
|
|
5444
|
+
computeEffectKey({
|
|
5445
|
+
name: reverseHandler,
|
|
5446
|
+
className: currentEffect.className,
|
|
5447
|
+
static: currentEffect.static
|
|
5448
|
+
}),
|
|
5449
|
+
computeEffectKey({
|
|
5450
|
+
name: reverseHandler
|
|
5451
|
+
})
|
|
5452
|
+
];
|
|
5453
|
+
for (const candidateKey of candidateKeys) {
|
|
5454
|
+
const candidate = effectMap.get(candidateKey);
|
|
5455
|
+
if (candidate) {
|
|
5456
|
+
return candidate;
|
|
5457
|
+
}
|
|
5458
|
+
}
|
|
5459
|
+
return void 0;
|
|
5460
|
+
}
|
|
5461
|
+
function resolveHandlerForMode(effectMap, effect, request) {
|
|
5462
|
+
const behaviors = normalizeEffectBehaviors(request.context?.behaviors || effect.metamodels || void 0);
|
|
5463
|
+
const mode = resolveInvocationMode(request.context);
|
|
5464
|
+
if (mode === "dryRun") {
|
|
5465
|
+
if (effect.dryRunHandler) {
|
|
5466
|
+
return { effect, mode, handler: effect.dryRunHandler };
|
|
5467
|
+
}
|
|
5468
|
+
if (behaviors.dryRun?.enabled) {
|
|
5469
|
+
return { effect, mode, handler: effect.handler };
|
|
5470
|
+
}
|
|
5471
|
+
throw new Error(`Dry run is not supported for ${request.effectKey}`);
|
|
5472
|
+
}
|
|
5473
|
+
if (mode === "reverse") {
|
|
5474
|
+
if (effect.reverseHandler) {
|
|
5475
|
+
return { effect, mode, handler: effect.reverseHandler };
|
|
5476
|
+
}
|
|
5477
|
+
const reverseEffect = resolveReverseEffect(effectMap, effect, request, behaviors);
|
|
5478
|
+
if (reverseEffect) {
|
|
5479
|
+
return {
|
|
5480
|
+
effect: reverseEffect,
|
|
5481
|
+
mode,
|
|
5482
|
+
handler: reverseEffect.reverseHandler || reverseEffect.handler
|
|
5483
|
+
};
|
|
5484
|
+
}
|
|
5485
|
+
throw new Error(`Reverse execution is not supported for ${request.effectKey}`);
|
|
5486
|
+
}
|
|
5487
|
+
return { effect, mode, handler: effect.handler };
|
|
5488
|
+
}
|
|
5489
|
+
async function invokeRegisteredEffect(effectMap, request) {
|
|
5490
|
+
const effect = effectMap.get(request.effectKey);
|
|
5491
|
+
if (!effect) {
|
|
5492
|
+
throw new Error(`Effect handler not found: ${request.effectKey}`);
|
|
5493
|
+
}
|
|
5494
|
+
const resolved = resolveHandlerForMode(effectMap, effect, request);
|
|
5495
|
+
const context = {
|
|
5496
|
+
...request.context || {},
|
|
5497
|
+
behaviors: normalizeEffectBehaviors(request.context?.behaviors || effect.metamodels || void 0),
|
|
5498
|
+
invocation: {
|
|
5499
|
+
mode: resolved.mode,
|
|
5500
|
+
sourceEffectKey: request.effectKey,
|
|
5501
|
+
sourceEffectName: request.effectName,
|
|
5502
|
+
...request.context?.invocation?.reverseHandler ? { reverseHandler: request.context.invocation.reverseHandler } : {}
|
|
5503
|
+
}
|
|
5504
|
+
};
|
|
5505
|
+
if (resolved.effect.className && !resolved.effect.static && request.input && typeof request.input === "object" && "_objectId" in request.input) {
|
|
5506
|
+
const { _objectId, ...rest } = request.input;
|
|
5507
|
+
return resolved.handler(_objectId, rest, context);
|
|
5508
|
+
}
|
|
5509
|
+
return resolved.handler(request.input, context);
|
|
5510
|
+
}
|
|
5511
|
+
function buildFieldMetamodelMutations(fieldPath, spec) {
|
|
5512
|
+
return metamodelPresetDefault.DEFAULT_METAMODEL_PACKAGES.flatMap(
|
|
5513
|
+
(pkg) => pkg.manifest?.buildFieldMutations?.(fieldPath, spec) || []
|
|
5514
|
+
);
|
|
5515
|
+
}
|
|
5516
|
+
function buildModelMetamodelMutations(modelPath, spec) {
|
|
5517
|
+
return metamodelPresetDefault.DEFAULT_METAMODEL_PACKAGES.flatMap(
|
|
5518
|
+
(pkg) => pkg.manifest?.buildModelMutations?.(modelPath, spec) || []
|
|
5519
|
+
);
|
|
5520
|
+
}
|
|
5521
|
+
function buildEffectMetamodelMutations(toolPath, spec) {
|
|
5522
|
+
if (!spec) return [];
|
|
5523
|
+
return metamodelPresetDefault.DEFAULT_METAMODEL_PACKAGES.flatMap(
|
|
5524
|
+
(pkg) => pkg.manifest?.buildEffectMutations?.(toolPath, spec) || []
|
|
5525
|
+
);
|
|
5526
|
+
}
|
|
5375
5527
|
|
|
5376
5528
|
// src/client.ts
|
|
5377
5529
|
var STANDARD_MODULES_OPERATIONS = [
|
|
@@ -5387,7 +5539,7 @@ var STANDARD_MODULES_OPERATIONS = [
|
|
|
5387
5539
|
var BUILTIN_MODULES = {
|
|
5388
5540
|
"standard_modules": STANDARD_MODULES_OPERATIONS
|
|
5389
5541
|
};
|
|
5390
|
-
function
|
|
5542
|
+
function computeEffectKey2(effect) {
|
|
5391
5543
|
const attachedClass = effect.className?.trim();
|
|
5392
5544
|
if (!attachedClass) {
|
|
5393
5545
|
return `global:${effect.name}`;
|
|
@@ -5964,6 +6116,87 @@ var Environment = class extends Session {
|
|
|
5964
6116
|
}
|
|
5965
6117
|
return ref;
|
|
5966
6118
|
}
|
|
6119
|
+
async _runGraphql(query, label) {
|
|
6120
|
+
const result = await this.graphql(query);
|
|
6121
|
+
if (result.errors?.length) {
|
|
6122
|
+
throw new Error(`${label}: ${result.errors[0].message}`);
|
|
6123
|
+
}
|
|
6124
|
+
return result.data;
|
|
6125
|
+
}
|
|
6126
|
+
async _applyFieldMetamodels(fieldPath, spec) {
|
|
6127
|
+
for (const mutation of buildFieldMetamodelMutations(fieldPath, spec)) {
|
|
6128
|
+
await this._runGraphql(mutation.query, mutation.label);
|
|
6129
|
+
}
|
|
6130
|
+
}
|
|
6131
|
+
async _applyModelMetamodels(modelPath, op) {
|
|
6132
|
+
for (const mutation of buildModelMetamodelMutations(modelPath, op)) {
|
|
6133
|
+
await this._runGraphql(mutation.query, mutation.label);
|
|
6134
|
+
}
|
|
6135
|
+
}
|
|
6136
|
+
async _ensureWorkspaceToolsRoot() {
|
|
6137
|
+
await this._runGraphql(
|
|
6138
|
+
`mutation { create_model(path: "workspace", label: "workspace") { model { path } } }`,
|
|
6139
|
+
"ensure workspace"
|
|
6140
|
+
).catch((error) => {
|
|
6141
|
+
if (!error.message.includes("already exists")) throw error;
|
|
6142
|
+
});
|
|
6143
|
+
await this._runGraphql(
|
|
6144
|
+
`mutation { at(path: "workspace") { create_submodel(subpath: "tools", label: "Tools") { model { path } } } }`,
|
|
6145
|
+
"ensure workspace:tools"
|
|
6146
|
+
).catch((error) => {
|
|
6147
|
+
if (!error.message.includes("already exists")) throw error;
|
|
6148
|
+
});
|
|
6149
|
+
await this._runGraphql(
|
|
6150
|
+
`mutation { at(path: "workspace:tools") { create_submodel(subpath: "declared", label: "Declared") { model { path } } } }`,
|
|
6151
|
+
"ensure workspace:tools:declared"
|
|
6152
|
+
).catch((error) => {
|
|
6153
|
+
if (!error.message.includes("already exists")) throw error;
|
|
6154
|
+
});
|
|
6155
|
+
}
|
|
6156
|
+
async _storeEffectSchemas(toolPath, effect) {
|
|
6157
|
+
await this._runGraphql(
|
|
6158
|
+
`mutation { at(path: ${JSON.stringify(toolPath)}) { create_submodel(subpath: "inputSchema", label: "inputSchema") { set_string_value(value: ${JSON.stringify(JSON.stringify(effect.inputSchema))}) { done } } } }`,
|
|
6159
|
+
`store inputSchema on ${toolPath}`
|
|
6160
|
+
).catch((error) => {
|
|
6161
|
+
if (!error.message.includes("already exists")) throw error;
|
|
6162
|
+
});
|
|
6163
|
+
if (effect.outputSchema) {
|
|
6164
|
+
await this._runGraphql(
|
|
6165
|
+
`mutation { at(path: ${JSON.stringify(toolPath)}) { create_submodel(subpath: "outputSchema", label: "outputSchema") { set_string_value(value: ${JSON.stringify(JSON.stringify(effect.outputSchema))}) { done } } } }`,
|
|
6166
|
+
`store outputSchema on ${toolPath}`
|
|
6167
|
+
).catch((error) => {
|
|
6168
|
+
if (!error.message.includes("already exists")) throw error;
|
|
6169
|
+
});
|
|
6170
|
+
}
|
|
6171
|
+
}
|
|
6172
|
+
async _applyEffectMetamodels(toolPath, metamodels) {
|
|
6173
|
+
for (const mutation of buildEffectMetamodelMutations(toolPath, metamodels)) {
|
|
6174
|
+
await this._runGraphql(mutation.query, mutation.label);
|
|
6175
|
+
}
|
|
6176
|
+
}
|
|
6177
|
+
async _applyEffectDeclaration(effect, aliasMap) {
|
|
6178
|
+
let containerPath = "workspace:tools:declared";
|
|
6179
|
+
if (effect.attachedClass) {
|
|
6180
|
+
containerPath = this._resolveAlias(effect.attachedClass, aliasMap);
|
|
6181
|
+
} else {
|
|
6182
|
+
await this._ensureWorkspaceToolsRoot();
|
|
6183
|
+
}
|
|
6184
|
+
await this._runGraphql(
|
|
6185
|
+
`mutation { at(path: ${JSON.stringify(containerPath)}) { create_submodel(subpath: ${JSON.stringify(effect.name)}, label: ${JSON.stringify(effect.name)}) { model { path } } } }`,
|
|
6186
|
+
`create effect model ${containerPath}:${effect.name}`
|
|
6187
|
+
).catch((error) => {
|
|
6188
|
+
if (!error.message.includes("already exists")) throw error;
|
|
6189
|
+
});
|
|
6190
|
+
const toolPath = `${containerPath}:${effect.name}`;
|
|
6191
|
+
if (effect.description) {
|
|
6192
|
+
await this._runGraphql(
|
|
6193
|
+
`mutation { at(path: ${JSON.stringify(toolPath)}) { set_description(description: ${JSON.stringify(effect.description)}) { done } } }`,
|
|
6194
|
+
`set effect description on ${toolPath}`
|
|
6195
|
+
);
|
|
6196
|
+
}
|
|
6197
|
+
await this._storeEffectSchemas(toolPath, effect);
|
|
6198
|
+
await this._applyEffectMetamodels(toolPath, effect.metamodels);
|
|
6199
|
+
}
|
|
5967
6200
|
/**
|
|
5968
6201
|
* Apply a single manifest operation via GraphQL
|
|
5969
6202
|
*/
|
|
@@ -5986,24 +6219,32 @@ var Environment = class extends Session {
|
|
|
5986
6219
|
const extendsRef = op.extends ? this._resolveAlias(op.extends, aliasMap) : void 0;
|
|
5987
6220
|
const instanceOfRef = op.instanceOf ? this._resolveAlias(op.instanceOf, aliasMap) : void 0;
|
|
5988
6221
|
if (extendsRef) {
|
|
5989
|
-
await this.
|
|
5990
|
-
`mutation { create_model(path: "${op.create}", label: "${label}") { model { path } } }
|
|
6222
|
+
await this._runGraphql(
|
|
6223
|
+
`mutation { create_model(path: "${op.create}", label: "${label}") { model { path } } }`,
|
|
6224
|
+
`create model ${op.create}`
|
|
5991
6225
|
);
|
|
5992
|
-
await this.
|
|
5993
|
-
`mutation { at(path: "${op.create}") { add_superclass(superclass: "${extendsRef}") { model { path } } } }
|
|
6226
|
+
await this._runGraphql(
|
|
6227
|
+
`mutation { at(path: "${op.create}") { add_superclass(superclass: "${extendsRef}") { model { path } } } }`,
|
|
6228
|
+
`add superclass ${extendsRef} to ${op.create}`
|
|
5994
6229
|
);
|
|
5995
6230
|
} else if (instanceOfRef) {
|
|
5996
|
-
await this.
|
|
5997
|
-
`mutation { at(path: "${instanceOfRef}") { instantiate(path: "${op.create}", label: "${label}") { model { path } } } }
|
|
6231
|
+
await this._runGraphql(
|
|
6232
|
+
`mutation { at(path: "${instanceOfRef}") { instantiate(path: "${op.create}", label: "${label}") { model { path } } } }`,
|
|
6233
|
+
`instantiate ${op.create} from ${instanceOfRef}`
|
|
5998
6234
|
);
|
|
5999
6235
|
} else {
|
|
6000
|
-
await this.
|
|
6001
|
-
`mutation { create_model(path: "${op.create}", label: "${label}") { model { path } } }
|
|
6236
|
+
await this._runGraphql(
|
|
6237
|
+
`mutation { create_model(path: "${op.create}", label: "${label}") { model { path } } }`,
|
|
6238
|
+
`create model ${op.create}`
|
|
6002
6239
|
);
|
|
6003
6240
|
}
|
|
6004
6241
|
if (op.has) {
|
|
6005
6242
|
await this._applyFields(op.create, op.has);
|
|
6006
6243
|
}
|
|
6244
|
+
await this._applyModelMetamodels(op.create, op);
|
|
6245
|
+
if (op.withEffect) {
|
|
6246
|
+
await this._applyEffectDeclaration(op.withEffect, aliasMap);
|
|
6247
|
+
}
|
|
6007
6248
|
return;
|
|
6008
6249
|
}
|
|
6009
6250
|
if (op.on) {
|
|
@@ -6011,8 +6252,15 @@ var Environment = class extends Session {
|
|
|
6011
6252
|
if (op.has) {
|
|
6012
6253
|
await this._applyFields(target, op.has);
|
|
6013
6254
|
}
|
|
6255
|
+
await this._applyModelMetamodels(target, op);
|
|
6256
|
+
if (op.withEffect) {
|
|
6257
|
+
await this._applyEffectDeclaration(op.withEffect, aliasMap);
|
|
6258
|
+
}
|
|
6014
6259
|
return;
|
|
6015
6260
|
}
|
|
6261
|
+
if (op.withEffect) {
|
|
6262
|
+
await this._applyEffectDeclaration(op.withEffect, aliasMap);
|
|
6263
|
+
}
|
|
6016
6264
|
}
|
|
6017
6265
|
/**
|
|
6018
6266
|
* Apply field definitions (has) to a model via GraphQL
|
|
@@ -6020,81 +6268,91 @@ var Environment = class extends Session {
|
|
|
6020
6268
|
async _applyFields(modelPath, fields) {
|
|
6021
6269
|
for (const [fieldName, spec] of Object.entries(fields)) {
|
|
6022
6270
|
const fieldLabel = fieldName.charAt(0).toUpperCase() + fieldName.slice(1);
|
|
6023
|
-
await this.
|
|
6271
|
+
await this._runGraphql(
|
|
6024
6272
|
`mutation {
|
|
6025
|
-
at(path:
|
|
6026
|
-
create_submodel(subpath:
|
|
6273
|
+
at(path: ${JSON.stringify(modelPath)}) {
|
|
6274
|
+
create_submodel(subpath: ${JSON.stringify(fieldName)}, label: ${JSON.stringify(fieldLabel)}) {
|
|
6027
6275
|
model { path }
|
|
6028
6276
|
}
|
|
6029
6277
|
}
|
|
6030
|
-
}
|
|
6031
|
-
|
|
6278
|
+
}`,
|
|
6279
|
+
`create field ${modelPath}.${fieldName}`
|
|
6280
|
+
).catch((error) => {
|
|
6281
|
+
if (!error.message.includes("already exists")) throw error;
|
|
6282
|
+
});
|
|
6032
6283
|
if (spec.type) {
|
|
6033
|
-
await this.
|
|
6284
|
+
await this._runGraphql(
|
|
6034
6285
|
`mutation {
|
|
6035
|
-
at(path:
|
|
6036
|
-
at(submodel:
|
|
6037
|
-
add_prototype(prototype:
|
|
6286
|
+
at(path: ${JSON.stringify(modelPath)}) {
|
|
6287
|
+
at(submodel: ${JSON.stringify(fieldName)}) {
|
|
6288
|
+
add_prototype(prototype: ${JSON.stringify(spec.type)}) { done }
|
|
6038
6289
|
}
|
|
6039
6290
|
}
|
|
6040
|
-
}
|
|
6291
|
+
}`,
|
|
6292
|
+
`set prototype on ${modelPath}:${fieldName}`
|
|
6041
6293
|
);
|
|
6042
6294
|
}
|
|
6043
6295
|
if (spec.description) {
|
|
6044
|
-
await this.
|
|
6296
|
+
await this._runGraphql(
|
|
6045
6297
|
`mutation {
|
|
6046
|
-
at(path:
|
|
6047
|
-
at(submodel:
|
|
6048
|
-
set_description(description:
|
|
6298
|
+
at(path: ${JSON.stringify(modelPath)}) {
|
|
6299
|
+
at(submodel: ${JSON.stringify(fieldName)}) {
|
|
6300
|
+
set_description(description: ${JSON.stringify(spec.description)}) { done }
|
|
6049
6301
|
}
|
|
6050
6302
|
}
|
|
6051
|
-
}
|
|
6303
|
+
}`,
|
|
6304
|
+
`set description on ${modelPath}:${fieldName}`
|
|
6052
6305
|
);
|
|
6053
6306
|
}
|
|
6054
6307
|
if (spec.value !== void 0 && spec.value !== null) {
|
|
6055
6308
|
if (typeof spec.value === "string") {
|
|
6056
|
-
await this.
|
|
6309
|
+
await this._runGraphql(
|
|
6057
6310
|
`mutation {
|
|
6058
|
-
at(path:
|
|
6059
|
-
at(submodel:
|
|
6060
|
-
set_string_value(value:
|
|
6311
|
+
at(path: ${JSON.stringify(modelPath)}) {
|
|
6312
|
+
at(submodel: ${JSON.stringify(fieldName)}) {
|
|
6313
|
+
set_string_value(value: ${JSON.stringify(spec.value)}) { done }
|
|
6061
6314
|
}
|
|
6062
6315
|
}
|
|
6063
|
-
}
|
|
6316
|
+
}`,
|
|
6317
|
+
`set string value on ${modelPath}:${fieldName}`
|
|
6064
6318
|
);
|
|
6065
6319
|
} else if (typeof spec.value === "number") {
|
|
6066
|
-
await this.
|
|
6320
|
+
await this._runGraphql(
|
|
6067
6321
|
`mutation {
|
|
6068
|
-
at(path:
|
|
6069
|
-
at(submodel:
|
|
6322
|
+
at(path: ${JSON.stringify(modelPath)}) {
|
|
6323
|
+
at(submodel: ${JSON.stringify(fieldName)}) {
|
|
6070
6324
|
set_number_value(value: ${spec.value}) { done }
|
|
6071
6325
|
}
|
|
6072
6326
|
}
|
|
6073
|
-
}
|
|
6327
|
+
}`,
|
|
6328
|
+
`set number value on ${modelPath}:${fieldName}`
|
|
6074
6329
|
);
|
|
6075
6330
|
} else if (typeof spec.value === "boolean") {
|
|
6076
|
-
await this.
|
|
6331
|
+
await this._runGraphql(
|
|
6077
6332
|
`mutation {
|
|
6078
|
-
at(path:
|
|
6079
|
-
at(submodel:
|
|
6333
|
+
at(path: ${JSON.stringify(modelPath)}) {
|
|
6334
|
+
at(submodel: ${JSON.stringify(fieldName)}) {
|
|
6080
6335
|
set_boolean_value(value: ${spec.value}) { done }
|
|
6081
6336
|
}
|
|
6082
6337
|
}
|
|
6083
|
-
}
|
|
6338
|
+
}`,
|
|
6339
|
+
`set boolean value on ${modelPath}:${fieldName}`
|
|
6084
6340
|
);
|
|
6085
6341
|
}
|
|
6086
6342
|
}
|
|
6087
6343
|
if (spec.ref) {
|
|
6088
|
-
await this.
|
|
6344
|
+
await this._runGraphql(
|
|
6089
6345
|
`mutation {
|
|
6090
|
-
at(path:
|
|
6091
|
-
at(submodel:
|
|
6092
|
-
set_reference(reference:
|
|
6346
|
+
at(path: ${JSON.stringify(modelPath)}) {
|
|
6347
|
+
at(submodel: ${JSON.stringify(fieldName)}) {
|
|
6348
|
+
set_reference(reference: ${JSON.stringify(spec.ref)}) { done }
|
|
6093
6349
|
}
|
|
6094
6350
|
}
|
|
6095
|
-
}
|
|
6351
|
+
}`,
|
|
6352
|
+
`set reference on ${modelPath}:${fieldName}`
|
|
6096
6353
|
);
|
|
6097
6354
|
}
|
|
6355
|
+
await this._applyFieldMetamodels(`${modelPath}:${fieldName}`, spec);
|
|
6098
6356
|
if (spec.has) {
|
|
6099
6357
|
await this._applyFields(`${modelPath}:${fieldName}`, spec.has);
|
|
6100
6358
|
}
|
|
@@ -6434,7 +6692,7 @@ var Granular = class {
|
|
|
6434
6692
|
}
|
|
6435
6693
|
serializeEffect(effect) {
|
|
6436
6694
|
return {
|
|
6437
|
-
effectKey:
|
|
6695
|
+
effectKey: computeEffectKey2(effect),
|
|
6438
6696
|
name: effect.name,
|
|
6439
6697
|
description: effect.description,
|
|
6440
6698
|
inputSchema: effect.inputSchema,
|
|
@@ -6470,23 +6728,54 @@ var Granular = class {
|
|
|
6470
6728
|
const host = await this.ensureSandboxEffectHost(sandboxId);
|
|
6471
6729
|
await this.publishSandboxEffectCatalog(host);
|
|
6472
6730
|
}
|
|
6473
|
-
|
|
6474
|
-
if (host.
|
|
6475
|
-
|
|
6731
|
+
recoverEffectHost(host, error) {
|
|
6732
|
+
if (host.recovering) {
|
|
6733
|
+
return;
|
|
6734
|
+
}
|
|
6735
|
+
if (this.sandboxEffectHosts.get(host.sandboxId) !== host) {
|
|
6736
|
+
return;
|
|
6476
6737
|
}
|
|
6477
|
-
host.
|
|
6738
|
+
host.recovering = true;
|
|
6739
|
+
this.stopEffectHostHeartbeat(host);
|
|
6740
|
+
this.sandboxEffectHosts.delete(host.sandboxId);
|
|
6741
|
+
try {
|
|
6742
|
+
host.wsClient.disconnect();
|
|
6743
|
+
} catch (disconnectError) {
|
|
6478
6744
|
console.warn(
|
|
6479
|
-
`[Granular]
|
|
6480
|
-
|
|
6745
|
+
`[Granular] Failed to disconnect stale effect host for sandbox ${host.sandboxId}:`,
|
|
6746
|
+
disconnectError
|
|
6747
|
+
);
|
|
6748
|
+
}
|
|
6749
|
+
void this.ensureSandboxEffectHost(host.sandboxId).catch((reconnectError) => {
|
|
6750
|
+
console.error(
|
|
6751
|
+
`[Granular] Failed to recover effect host for sandbox ${host.sandboxId} after heartbeat failure:`,
|
|
6752
|
+
reconnectError
|
|
6481
6753
|
);
|
|
6754
|
+
console.error("[Granular] Original heartbeat failure:", error);
|
|
6482
6755
|
});
|
|
6483
|
-
|
|
6756
|
+
}
|
|
6757
|
+
startEffectHostHeartbeat(host) {
|
|
6758
|
+
if (host.heartbeatTimer) {
|
|
6759
|
+
clearInterval(host.heartbeatTimer);
|
|
6760
|
+
}
|
|
6761
|
+
host.heartbeatInFlight = false;
|
|
6762
|
+
const sendHeartbeat = (failureLabel, recoverOnFailure) => {
|
|
6763
|
+
if (host.heartbeatInFlight || host.recovering) {
|
|
6764
|
+
return;
|
|
6765
|
+
}
|
|
6766
|
+
host.heartbeatInFlight = true;
|
|
6484
6767
|
host.wsClient.call("client.heartbeat", {}).catch((error) => {
|
|
6485
|
-
console.warn(
|
|
6486
|
-
|
|
6487
|
-
error
|
|
6488
|
-
|
|
6768
|
+
console.warn(`${failureLabel} ${host.sandboxId}:`, error);
|
|
6769
|
+
if (recoverOnFailure) {
|
|
6770
|
+
this.recoverEffectHost(host, error);
|
|
6771
|
+
}
|
|
6772
|
+
}).finally(() => {
|
|
6773
|
+
host.heartbeatInFlight = false;
|
|
6489
6774
|
});
|
|
6775
|
+
};
|
|
6776
|
+
sendHeartbeat("[Granular] Initial effect host heartbeat failed for sandbox", false);
|
|
6777
|
+
host.heartbeatTimer = setInterval(() => {
|
|
6778
|
+
sendHeartbeat("[Granular] Effect host heartbeat failed for sandbox", true);
|
|
6490
6779
|
}, 1e4);
|
|
6491
6780
|
}
|
|
6492
6781
|
stopEffectHostHeartbeat(host) {
|
|
@@ -6495,6 +6784,7 @@ var Granular = class {
|
|
|
6495
6784
|
}
|
|
6496
6785
|
clearInterval(host.heartbeatTimer);
|
|
6497
6786
|
host.heartbeatTimer = null;
|
|
6787
|
+
host.heartbeatInFlight = false;
|
|
6498
6788
|
}
|
|
6499
6789
|
async synchronizeEffectHost(host) {
|
|
6500
6790
|
await host.wsClient.call("client.hello", {
|
|
@@ -6530,19 +6820,13 @@ var Granular = class {
|
|
|
6530
6820
|
effectClientId,
|
|
6531
6821
|
clientId,
|
|
6532
6822
|
wsClient,
|
|
6533
|
-
heartbeatTimer: null
|
|
6823
|
+
heartbeatTimer: null,
|
|
6824
|
+
heartbeatInFlight: false,
|
|
6825
|
+
recovering: false
|
|
6534
6826
|
};
|
|
6535
6827
|
wsClient.registerRpcHandler("effect.invoke", async (params) => {
|
|
6536
6828
|
const request = params;
|
|
6537
|
-
|
|
6538
|
-
if (!effect) {
|
|
6539
|
-
throw new Error(`Effect handler not found: ${request.effectKey}`);
|
|
6540
|
-
}
|
|
6541
|
-
if (effect.className && !effect.static && request.input && typeof request.input === "object" && "_objectId" in request.input) {
|
|
6542
|
-
const { _objectId, ...rest } = request.input;
|
|
6543
|
-
return effect.handler(_objectId, rest, request.context);
|
|
6544
|
-
}
|
|
6545
|
-
return effect.handler(request.input, request.context);
|
|
6829
|
+
return invokeRegisteredEffect(this.getSandboxEffectMap(sandboxId), request);
|
|
6546
6830
|
});
|
|
6547
6831
|
wsClient.on("open", () => {
|
|
6548
6832
|
void this.synchronizeEffectHost(host).catch((error) => {
|
|
@@ -6585,7 +6869,7 @@ var Granular = class {
|
|
|
6585
6869
|
async registerEffect(sandboxNameOrId, effect) {
|
|
6586
6870
|
const sandbox = await this.findOrCreateSandbox(sandboxNameOrId);
|
|
6587
6871
|
const sandboxId = sandbox.sandboxId;
|
|
6588
|
-
this.getSandboxEffectMap(sandboxId).set(
|
|
6872
|
+
this.getSandboxEffectMap(sandboxId).set(computeEffectKey2(effect), effect);
|
|
6589
6873
|
await this.syncSandboxEffectCatalog(sandboxId);
|
|
6590
6874
|
}
|
|
6591
6875
|
/**
|
|
@@ -6598,7 +6882,7 @@ var Granular = class {
|
|
|
6598
6882
|
const sandboxId = sandbox.sandboxId;
|
|
6599
6883
|
const map = this.getSandboxEffectMap(sandboxId);
|
|
6600
6884
|
for (const effect of effects) {
|
|
6601
|
-
map.set(
|
|
6885
|
+
map.set(computeEffectKey2(effect), effect);
|
|
6602
6886
|
}
|
|
6603
6887
|
await this.syncSandboxEffectCatalog(sandboxId);
|
|
6604
6888
|
}
|
|
@@ -6879,5 +7163,7 @@ exports.Environment = Environment;
|
|
|
6879
7163
|
exports.Granular = Granular;
|
|
6880
7164
|
exports.Session = Session;
|
|
6881
7165
|
exports.WSClient = WSClient;
|
|
7166
|
+
exports.invokeRegisteredEffect = invokeRegisteredEffect;
|
|
7167
|
+
exports.normalizeEffectBehaviors = normalizeEffectBehaviors;
|
|
6882
7168
|
//# sourceMappingURL=index.js.map
|
|
6883
7169
|
//# sourceMappingURL=index.js.map
|