@granular-software/sdk 0.4.33 → 0.4.35
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/agent-evals.d.mts +1 -1
- package/dist/agent-evals.d.ts +1 -1
- package/dist/agent-evals.js +272 -42
- package/dist/agent-evals.js.map +1 -1
- package/dist/agent-evals.mjs +272 -42
- package/dist/agent-evals.mjs.map +1 -1
- package/dist/agent-harness.js +15 -6
- package/dist/agent-harness.js.map +1 -1
- package/dist/agent-harness.mjs +15 -6
- package/dist/agent-harness.mjs.map +1 -1
- package/dist/cli/index.js +257 -36
- package/dist/{client-DTvI5MUG.d.mts → client-Cq8onk2D.d.mts} +75 -2
- package/dist/{client-DTvI5MUG.d.ts → client-Cq8onk2D.d.ts} +75 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +272 -42
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +272 -42
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/agent-evals.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as Prompt, f as EnvironmentSession, c as SessionHeapSnapshot,
|
|
1
|
+
import { P as Prompt, f as EnvironmentSession, c as SessionHeapSnapshot, bl as ManifestContent, aO as RecordObjectOptions, T as ToolWithHandler, G as Granular, C as ConnectOptions, J as CreateEnvironmentData, k as GranularOptions } from './client-Cq8onk2D.mjs';
|
|
2
2
|
import { GeneratedJobCodeIssue, HarnessControllerBudgets } from './agent-harness.mjs';
|
|
3
3
|
import '@automerge/automerge';
|
|
4
4
|
import '@automerge/automerge/slim';
|
package/dist/agent-evals.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as Prompt, f as EnvironmentSession, c as SessionHeapSnapshot,
|
|
1
|
+
import { P as Prompt, f as EnvironmentSession, c as SessionHeapSnapshot, bl as ManifestContent, aO as RecordObjectOptions, T as ToolWithHandler, G as Granular, C as ConnectOptions, J as CreateEnvironmentData, k as GranularOptions } from './client-Cq8onk2D.js';
|
|
2
2
|
import { GeneratedJobCodeIssue, HarnessControllerBudgets } from './agent-harness.js';
|
|
3
3
|
import '@automerge/automerge';
|
|
4
4
|
import '@automerge/automerge/slim';
|
package/dist/agent-evals.js
CHANGED
|
@@ -10891,6 +10891,50 @@ function computeEffectKey(effect) {
|
|
|
10891
10891
|
}
|
|
10892
10892
|
return effect.static ? `class:${attachedClass}:static:${effect.name}` : `class:${attachedClass}:instance:${effect.name}`;
|
|
10893
10893
|
}
|
|
10894
|
+
function computeEffectVersionSelectorSpecificity(selector) {
|
|
10895
|
+
if (!selector || selector.mode === "all") {
|
|
10896
|
+
return 0;
|
|
10897
|
+
}
|
|
10898
|
+
if (selector.mode === "exact") {
|
|
10899
|
+
return 2;
|
|
10900
|
+
}
|
|
10901
|
+
return 1;
|
|
10902
|
+
}
|
|
10903
|
+
function matchesEffectVersionSelector(selector, buildVersionNumber) {
|
|
10904
|
+
if (!selector || selector.mode === "all") {
|
|
10905
|
+
return true;
|
|
10906
|
+
}
|
|
10907
|
+
if (typeof buildVersionNumber !== "number" || !Number.isFinite(buildVersionNumber)) {
|
|
10908
|
+
return false;
|
|
10909
|
+
}
|
|
10910
|
+
if (selector.mode === "exact") {
|
|
10911
|
+
return buildVersionNumber === selector.versionNumber;
|
|
10912
|
+
}
|
|
10913
|
+
if (selector.mode === "before") {
|
|
10914
|
+
return buildVersionNumber < selector.versionNumber;
|
|
10915
|
+
}
|
|
10916
|
+
return buildVersionNumber > selector.versionNumber;
|
|
10917
|
+
}
|
|
10918
|
+
function selectRegisteredEffect(effectMap, effectKey, buildVersionNumber) {
|
|
10919
|
+
let bestEffect;
|
|
10920
|
+
let bestSpecificity = Number.NEGATIVE_INFINITY;
|
|
10921
|
+
for (const effect of effectMap.values()) {
|
|
10922
|
+
if (computeEffectKey(effect) !== effectKey) {
|
|
10923
|
+
continue;
|
|
10924
|
+
}
|
|
10925
|
+
if (!matchesEffectVersionSelector(effect.versionSelector, buildVersionNumber)) {
|
|
10926
|
+
continue;
|
|
10927
|
+
}
|
|
10928
|
+
const specificity = computeEffectVersionSelectorSpecificity(
|
|
10929
|
+
effect.versionSelector
|
|
10930
|
+
);
|
|
10931
|
+
if (!bestEffect || specificity > bestSpecificity) {
|
|
10932
|
+
bestEffect = effect;
|
|
10933
|
+
bestSpecificity = specificity;
|
|
10934
|
+
}
|
|
10935
|
+
}
|
|
10936
|
+
return bestEffect;
|
|
10937
|
+
}
|
|
10894
10938
|
function normalizeEffectBehaviors(value) {
|
|
10895
10939
|
return normalizeEffectBehaviorSummary(
|
|
10896
10940
|
value
|
|
@@ -10911,9 +10955,17 @@ function resolveReverseEffect(effectMap, currentEffect, request, behaviors) {
|
|
|
10911
10955
|
return void 0;
|
|
10912
10956
|
}
|
|
10913
10957
|
if (reverseHandler.includes(":")) {
|
|
10914
|
-
return
|
|
10958
|
+
return selectRegisteredEffect(
|
|
10959
|
+
effectMap,
|
|
10960
|
+
reverseHandler,
|
|
10961
|
+
request.context?.buildVersionNumber
|
|
10962
|
+
);
|
|
10915
10963
|
}
|
|
10916
|
-
const directMatch =
|
|
10964
|
+
const directMatch = selectRegisteredEffect(
|
|
10965
|
+
effectMap,
|
|
10966
|
+
reverseHandler,
|
|
10967
|
+
request.context?.buildVersionNumber
|
|
10968
|
+
);
|
|
10917
10969
|
if (directMatch) {
|
|
10918
10970
|
return directMatch;
|
|
10919
10971
|
}
|
|
@@ -10928,7 +10980,11 @@ function resolveReverseEffect(effectMap, currentEffect, request, behaviors) {
|
|
|
10928
10980
|
})
|
|
10929
10981
|
];
|
|
10930
10982
|
for (const candidateKey of candidateKeys) {
|
|
10931
|
-
const candidate =
|
|
10983
|
+
const candidate = selectRegisteredEffect(
|
|
10984
|
+
effectMap,
|
|
10985
|
+
candidateKey,
|
|
10986
|
+
request.context?.buildVersionNumber
|
|
10987
|
+
);
|
|
10932
10988
|
if (candidate) {
|
|
10933
10989
|
return candidate;
|
|
10934
10990
|
}
|
|
@@ -10964,7 +11020,11 @@ function resolveHandlerForMode(effectMap, effect, request) {
|
|
|
10964
11020
|
return { effect, mode, handler: effect.handler };
|
|
10965
11021
|
}
|
|
10966
11022
|
async function invokeRegisteredEffect(effectMap, request) {
|
|
10967
|
-
const effect =
|
|
11023
|
+
const effect = selectRegisteredEffect(
|
|
11024
|
+
effectMap,
|
|
11025
|
+
request.effectKey,
|
|
11026
|
+
request.context?.buildVersionNumber
|
|
11027
|
+
);
|
|
10968
11028
|
if (!effect) {
|
|
10969
11029
|
throw new Error(`Effect handler not found: ${request.effectKey}`);
|
|
10970
11030
|
}
|
|
@@ -12223,6 +12283,17 @@ function computeEffectKey2(effect) {
|
|
|
12223
12283
|
}
|
|
12224
12284
|
return effect.static ? `class:${attachedClass}:static:${effect.name}` : `class:${attachedClass}:instance:${effect.name}`;
|
|
12225
12285
|
}
|
|
12286
|
+
function computeEffectVersionSelectorKey(selector) {
|
|
12287
|
+
if (!selector || selector.mode === "all") {
|
|
12288
|
+
return "all";
|
|
12289
|
+
}
|
|
12290
|
+
return `${selector.mode}:${selector.versionNumber}`;
|
|
12291
|
+
}
|
|
12292
|
+
function computeEffectRegistrationKey(effect) {
|
|
12293
|
+
return `${computeEffectKey2(effect)}@${computeEffectVersionSelectorKey(
|
|
12294
|
+
effect.versionSelector
|
|
12295
|
+
)}`;
|
|
12296
|
+
}
|
|
12226
12297
|
function buildEffectHostUrl(apiUrl, sandboxId, effectClientId, clientId) {
|
|
12227
12298
|
const url = new URL(apiUrl);
|
|
12228
12299
|
if (url.pathname.endsWith("/granular/ws/connect")) {
|
|
@@ -12306,6 +12377,38 @@ function normalizeUser(user) {
|
|
|
12306
12377
|
permissions: Array.isArray(user.permissions) ? user.permissions : []
|
|
12307
12378
|
};
|
|
12308
12379
|
}
|
|
12380
|
+
function normalizeEnvironmentSetupSummary(setup) {
|
|
12381
|
+
if (!setup) {
|
|
12382
|
+
return null;
|
|
12383
|
+
}
|
|
12384
|
+
const queuedRecords = Number(setup.queuedRecords || 0);
|
|
12385
|
+
const processingRecords = Number(setup.processingRecords || 0);
|
|
12386
|
+
return {
|
|
12387
|
+
...setup,
|
|
12388
|
+
setupRunId: String(setup.setupRunId || ""),
|
|
12389
|
+
environmentId: String(setup.environmentId || ""),
|
|
12390
|
+
sandboxId: String(setup.sandboxId || ""),
|
|
12391
|
+
subjectId: String(setup.subjectId || ""),
|
|
12392
|
+
triggerReason: setup.triggerReason === "fresh_after_version_update" ? "fresh_after_version_update" : "new_environment",
|
|
12393
|
+
lifecycleStatus: setup.lifecycleStatus === "completed" || setup.lifecycleStatus === "failed" ? setup.lifecycleStatus : "running",
|
|
12394
|
+
stage: typeof setup.stage === "string" ? setup.stage : null,
|
|
12395
|
+
totalObjectsToImport: Number(setup.totalObjectsToImport || 0),
|
|
12396
|
+
totalImports: Number(setup.totalImports || 0),
|
|
12397
|
+
activeImports: Number(setup.activeImports || 0),
|
|
12398
|
+
totalRecords: Number(setup.totalRecords || 0),
|
|
12399
|
+
queuedRecords,
|
|
12400
|
+
processingRecords,
|
|
12401
|
+
completedRecords: Number(setup.completedRecords || 0),
|
|
12402
|
+
failedRecords: Number(setup.failedRecords || 0),
|
|
12403
|
+
canceledRecords: Number(setup.canceledRecords || 0),
|
|
12404
|
+
awaitingRecords: Number(setup.awaitingRecords || 0) || queuedRecords + processingRecords,
|
|
12405
|
+
errorMessage: typeof setup.errorMessage === "string" ? setup.errorMessage : null,
|
|
12406
|
+
startedAt: Number(setup.startedAt || Date.now()),
|
|
12407
|
+
hookCompletedAt: setup.hookCompletedAt == null ? null : Number(setup.hookCompletedAt),
|
|
12408
|
+
finishedAt: setup.finishedAt == null ? null : Number(setup.finishedAt),
|
|
12409
|
+
updatedAt: Number(setup.updatedAt || Date.now())
|
|
12410
|
+
};
|
|
12411
|
+
}
|
|
12309
12412
|
function normalizeEnvironmentData(environment) {
|
|
12310
12413
|
const buildPolicy = environment.buildPolicy || environment.tracking || (environment.tagId ? { mode: "tag", tagId: environment.tagId } : {
|
|
12311
12414
|
mode: "pinned",
|
|
@@ -12319,7 +12422,8 @@ function normalizeEnvironmentData(environment) {
|
|
|
12319
12422
|
envName: environmentName,
|
|
12320
12423
|
environment: environmentName,
|
|
12321
12424
|
buildPolicy,
|
|
12322
|
-
tracking: environment.tracking || buildPolicy
|
|
12425
|
+
tracking: environment.tracking || buildPolicy,
|
|
12426
|
+
setup: normalizeEnvironmentSetupSummary(environment.setup)
|
|
12323
12427
|
};
|
|
12324
12428
|
}
|
|
12325
12429
|
var Environment = class {
|
|
@@ -12377,6 +12481,10 @@ var Environment = class {
|
|
|
12377
12481
|
get updateState() {
|
|
12378
12482
|
return this.envData.updateState;
|
|
12379
12483
|
}
|
|
12484
|
+
/** The latest setup/import run summary for this environment, when available. */
|
|
12485
|
+
get setup() {
|
|
12486
|
+
return this.envData.setup || null;
|
|
12487
|
+
}
|
|
12380
12488
|
/** Convenience flag for whether this environment trails the current tag target */
|
|
12381
12489
|
get isOutdated() {
|
|
12382
12490
|
return this.envData.updateState === "update_available";
|
|
@@ -12397,6 +12505,9 @@ var Environment = class {
|
|
|
12397
12505
|
get runtimeBaseUrl() {
|
|
12398
12506
|
return this.getRuntimeBaseUrl();
|
|
12399
12507
|
}
|
|
12508
|
+
syncEnvironmentData(envData) {
|
|
12509
|
+
this.envData = normalizeEnvironmentData(envData);
|
|
12510
|
+
}
|
|
12400
12511
|
get sessions() {
|
|
12401
12512
|
return {
|
|
12402
12513
|
list: async (options) => this.listSessions(options?.status || "active"),
|
|
@@ -13342,7 +13453,8 @@ var Environment = class {
|
|
|
13342
13453
|
method: "POST",
|
|
13343
13454
|
body: JSON.stringify({
|
|
13344
13455
|
records,
|
|
13345
|
-
batchSize: options.batchSize
|
|
13456
|
+
batchSize: options.batchSize,
|
|
13457
|
+
setupRunId: options.setupRunId
|
|
13346
13458
|
})
|
|
13347
13459
|
}
|
|
13348
13460
|
);
|
|
@@ -13490,18 +13602,12 @@ var EnvironmentSession = class extends Session {
|
|
|
13490
13602
|
}
|
|
13491
13603
|
get messages() {
|
|
13492
13604
|
return {
|
|
13493
|
-
list: (options = {}) => this.sessionDataRequest(
|
|
13494
|
-
"/messages",
|
|
13495
|
-
options
|
|
13496
|
-
)
|
|
13605
|
+
list: (options = {}) => this.sessionDataRequest("/messages", options)
|
|
13497
13606
|
};
|
|
13498
13607
|
}
|
|
13499
13608
|
get timeline() {
|
|
13500
13609
|
return {
|
|
13501
|
-
list: (options = {}) => this.sessionDataRequest(
|
|
13502
|
-
"/timeline",
|
|
13503
|
-
options
|
|
13504
|
-
)
|
|
13610
|
+
list: (options = {}) => this.sessionDataRequest("/timeline", options)
|
|
13505
13611
|
};
|
|
13506
13612
|
}
|
|
13507
13613
|
get jobs() {
|
|
@@ -13518,10 +13624,7 @@ var EnvironmentSession = class extends Session {
|
|
|
13518
13624
|
get heap() {
|
|
13519
13625
|
return {
|
|
13520
13626
|
entries: {
|
|
13521
|
-
list: (options = {}) => this.sessionDataRequest(
|
|
13522
|
-
"/heap/entries",
|
|
13523
|
-
options
|
|
13524
|
-
),
|
|
13627
|
+
list: (options = {}) => this.sessionDataRequest("/heap/entries", options),
|
|
13525
13628
|
get: (path2) => this.sessionDataRequest(
|
|
13526
13629
|
`/heap/entries/${encodeURIComponent(path2)}`
|
|
13527
13630
|
)
|
|
@@ -13565,10 +13668,7 @@ var EnvironmentSession = class extends Session {
|
|
|
13565
13668
|
const heap = normalizeHeapSnapshot({
|
|
13566
13669
|
entriesByPath: Object.fromEntries(
|
|
13567
13670
|
entries.map((entry) => {
|
|
13568
|
-
return entry?.path ? [
|
|
13569
|
-
entry.path,
|
|
13570
|
-
entry
|
|
13571
|
-
] : null;
|
|
13671
|
+
return entry?.path ? [entry.path, entry] : null;
|
|
13572
13672
|
}).filter(
|
|
13573
13673
|
(entry) => Boolean(entry)
|
|
13574
13674
|
)
|
|
@@ -13734,6 +13834,15 @@ var OntologyHandle = class {
|
|
|
13734
13834
|
disconnect: async () => this.granular.disconnectEffects(this.ontologyNameOrId)
|
|
13735
13835
|
};
|
|
13736
13836
|
}
|
|
13837
|
+
get importer() {
|
|
13838
|
+
return {
|
|
13839
|
+
onEnvironmentCreate: (handler) => this.granular.registerEnvironmentImporter(
|
|
13840
|
+
this.ontologyNameOrId,
|
|
13841
|
+
handler
|
|
13842
|
+
),
|
|
13843
|
+
clear: () => this.granular.clearEnvironmentImporter(this.ontologyNameOrId)
|
|
13844
|
+
};
|
|
13845
|
+
}
|
|
13737
13846
|
};
|
|
13738
13847
|
var Granular = class _Granular {
|
|
13739
13848
|
apiKey;
|
|
@@ -13744,12 +13853,16 @@ var Granular = class _Granular {
|
|
|
13744
13853
|
onUnexpectedClose;
|
|
13745
13854
|
onReconnectError;
|
|
13746
13855
|
debugHttp = process.env.GRANULAR_DEBUG_HTTP === "1";
|
|
13747
|
-
/** Sandbox-level effect registry: sandboxId → (effectKey → ToolWithHandler) */
|
|
13856
|
+
/** Sandbox-level effect registry: sandboxId → (effectKey@selector → ToolWithHandler) */
|
|
13748
13857
|
sandboxEffects = /* @__PURE__ */ new Map();
|
|
13749
13858
|
/** Live sandbox-scoped effect hosts keyed by sandboxId */
|
|
13750
13859
|
sandboxEffectHosts = /* @__PURE__ */ new Map();
|
|
13751
13860
|
/** In-flight host connection promises to avoid duplicate concurrent connects */
|
|
13752
13861
|
sandboxEffectHostPromises = /* @__PURE__ */ new Map();
|
|
13862
|
+
/** Ontology-bound environment importer hooks keyed by the caller's ontology identifier. */
|
|
13863
|
+
ontologyImporters = /* @__PURE__ */ new Map();
|
|
13864
|
+
/** Resolved importer hooks keyed by sandboxId for fast lookups during openEnvironment(). */
|
|
13865
|
+
sandboxImporters = /* @__PURE__ */ new Map();
|
|
13753
13866
|
/**
|
|
13754
13867
|
* Create a new Granular client
|
|
13755
13868
|
* @param options - Client configuration
|
|
@@ -13775,6 +13888,18 @@ var Granular = class _Granular {
|
|
|
13775
13888
|
ontology(ontologyNameOrId) {
|
|
13776
13889
|
return new OntologyHandle(this, ontologyNameOrId);
|
|
13777
13890
|
}
|
|
13891
|
+
registerEnvironmentImporter(ontologyNameOrId, handler) {
|
|
13892
|
+
this.ontologyImporters.set(ontologyNameOrId, handler);
|
|
13893
|
+
if (ontologyNameOrId.startsWith("sbx_")) {
|
|
13894
|
+
this.sandboxImporters.set(ontologyNameOrId, handler);
|
|
13895
|
+
}
|
|
13896
|
+
}
|
|
13897
|
+
clearEnvironmentImporter(ontologyNameOrId) {
|
|
13898
|
+
this.ontologyImporters.delete(ontologyNameOrId);
|
|
13899
|
+
if (ontologyNameOrId.startsWith("sbx_")) {
|
|
13900
|
+
this.sandboxImporters.delete(ontologyNameOrId);
|
|
13901
|
+
}
|
|
13902
|
+
}
|
|
13778
13903
|
/**
|
|
13779
13904
|
* Records/upserts a user and prepares them for sandbox connections
|
|
13780
13905
|
*
|
|
@@ -13891,11 +14016,13 @@ var Granular = class _Granular {
|
|
|
13891
14016
|
* ```
|
|
13892
14017
|
*/
|
|
13893
14018
|
async openEnvironment(options) {
|
|
13894
|
-
const
|
|
14019
|
+
const resolved = await this.resolveOpenEnvironmentData(
|
|
13895
14020
|
options,
|
|
13896
14021
|
"openEnvironment"
|
|
13897
14022
|
);
|
|
13898
|
-
|
|
14023
|
+
const environment = this.bindEnvironmentHandle(resolved.environment);
|
|
14024
|
+
await this.maybeRunEnvironmentImporter(resolved, environment);
|
|
14025
|
+
return environment;
|
|
13899
14026
|
}
|
|
13900
14027
|
/**
|
|
13901
14028
|
* Deprecated compatibility alias for `openEnvironment()`.
|
|
@@ -13982,7 +14109,12 @@ var Granular = class _Granular {
|
|
|
13982
14109
|
)
|
|
13983
14110
|
);
|
|
13984
14111
|
if (currentMatches.length > 0) {
|
|
13985
|
-
return
|
|
14112
|
+
return {
|
|
14113
|
+
environment: currentMatches[0],
|
|
14114
|
+
requestedOntology: ontology,
|
|
14115
|
+
sandboxId: sandbox.sandboxId,
|
|
14116
|
+
subjectId: user.granularId
|
|
14117
|
+
};
|
|
13986
14118
|
}
|
|
13987
14119
|
const outdatedMatches = this.sortEnvironmentsByRecency(
|
|
13988
14120
|
userEnvironments.filter(
|
|
@@ -13990,14 +14122,25 @@ var Granular = class _Granular {
|
|
|
13990
14122
|
)
|
|
13991
14123
|
);
|
|
13992
14124
|
if (outdatedMatches.length > 0 && options.createFreshIfOutdated !== true) {
|
|
13993
|
-
return
|
|
14125
|
+
return {
|
|
14126
|
+
environment: outdatedMatches[0],
|
|
14127
|
+
requestedOntology: ontology,
|
|
14128
|
+
sandboxId: sandbox.sandboxId,
|
|
14129
|
+
subjectId: user.granularId
|
|
14130
|
+
};
|
|
13994
14131
|
}
|
|
13995
|
-
return
|
|
14132
|
+
return {
|
|
14133
|
+
environment: await this.environments.create(sandbox.sandboxId, {
|
|
14134
|
+
subjectId: user.granularId,
|
|
14135
|
+
environment: this.buildManagedEnvironmentName(tagName, targetVersionId),
|
|
14136
|
+
tagId: tag.tagId,
|
|
14137
|
+
permissionProfileId: null
|
|
14138
|
+
}),
|
|
14139
|
+
requestedOntology: ontology,
|
|
14140
|
+
sandboxId: sandbox.sandboxId,
|
|
13996
14141
|
subjectId: user.granularId,
|
|
13997
|
-
|
|
13998
|
-
|
|
13999
|
-
permissionProfileId: null
|
|
14000
|
-
});
|
|
14142
|
+
setupTriggerReason: outdatedMatches.length > 0 ? "fresh_after_version_update" : "new_environment"
|
|
14143
|
+
};
|
|
14001
14144
|
}
|
|
14002
14145
|
/**
|
|
14003
14146
|
* List active (open) sessions for an environment — each session is one agent conversation thread.
|
|
@@ -14114,6 +14257,80 @@ var Granular = class _Granular {
|
|
|
14114
14257
|
});
|
|
14115
14258
|
return this.connectSession({ sessionId, clientId: options?.clientId });
|
|
14116
14259
|
}
|
|
14260
|
+
resolveEnvironmentImporter(requestedOntology, sandboxId) {
|
|
14261
|
+
const resolved = this.sandboxImporters.get(sandboxId) || this.ontologyImporters.get(requestedOntology);
|
|
14262
|
+
if (resolved && !this.sandboxImporters.has(sandboxId) && this.ontologyImporters.get(requestedOntology) === resolved) {
|
|
14263
|
+
this.sandboxImporters.set(sandboxId, resolved);
|
|
14264
|
+
}
|
|
14265
|
+
return resolved;
|
|
14266
|
+
}
|
|
14267
|
+
async maybeRunEnvironmentImporter(resolved, environment) {
|
|
14268
|
+
if (!resolved.setupTriggerReason) {
|
|
14269
|
+
return;
|
|
14270
|
+
}
|
|
14271
|
+
const importer = this.resolveEnvironmentImporter(
|
|
14272
|
+
resolved.requestedOntology,
|
|
14273
|
+
resolved.sandboxId
|
|
14274
|
+
);
|
|
14275
|
+
if (!importer) {
|
|
14276
|
+
return;
|
|
14277
|
+
}
|
|
14278
|
+
const setupRun = await this.request(
|
|
14279
|
+
`/control/environments/${environment.environmentId}/setup-runs`,
|
|
14280
|
+
{
|
|
14281
|
+
method: "POST",
|
|
14282
|
+
body: JSON.stringify({
|
|
14283
|
+
triggerReason: resolved.setupTriggerReason
|
|
14284
|
+
})
|
|
14285
|
+
}
|
|
14286
|
+
);
|
|
14287
|
+
const setupRunId = setupRun.setupRunId;
|
|
14288
|
+
const updateSetupRun = async (patch) => {
|
|
14289
|
+
await this.request(
|
|
14290
|
+
`/control/environment-setup-runs/${setupRunId}`,
|
|
14291
|
+
{
|
|
14292
|
+
method: "PATCH",
|
|
14293
|
+
body: JSON.stringify(patch)
|
|
14294
|
+
}
|
|
14295
|
+
);
|
|
14296
|
+
};
|
|
14297
|
+
const importerContext = {
|
|
14298
|
+
environmentId: environment.environmentId,
|
|
14299
|
+
sandboxId: environment.sandboxId,
|
|
14300
|
+
subjectId: environment.subjectId,
|
|
14301
|
+
reason: resolved.setupTriggerReason,
|
|
14302
|
+
incrementTotalObjectsToImportCount: async (n) => {
|
|
14303
|
+
const safeIncrement = Math.max(0, Math.trunc(n));
|
|
14304
|
+
if (safeIncrement <= 0) {
|
|
14305
|
+
return;
|
|
14306
|
+
}
|
|
14307
|
+
await updateSetupRun({
|
|
14308
|
+
incrementTotalObjectsToImportCount: safeIncrement
|
|
14309
|
+
});
|
|
14310
|
+
},
|
|
14311
|
+
setStage: async (stage) => {
|
|
14312
|
+
await updateSetupRun({ stage });
|
|
14313
|
+
},
|
|
14314
|
+
importRecords: async (records, options) => environment.enqueueRecordImport(records, {
|
|
14315
|
+
batchSize: options?.batchSize,
|
|
14316
|
+
setupRunId
|
|
14317
|
+
})
|
|
14318
|
+
};
|
|
14319
|
+
try {
|
|
14320
|
+
await importer(importerContext);
|
|
14321
|
+
await updateSetupRun({ markHookCompleted: true });
|
|
14322
|
+
const refreshedEnvironment = await this.environments.get(
|
|
14323
|
+
environment.environmentId
|
|
14324
|
+
);
|
|
14325
|
+
environment.syncEnvironmentData(refreshedEnvironment);
|
|
14326
|
+
} catch (error) {
|
|
14327
|
+
await updateSetupRun({
|
|
14328
|
+
status: "failed",
|
|
14329
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
14330
|
+
}).catch(() => void 0);
|
|
14331
|
+
throw error;
|
|
14332
|
+
}
|
|
14333
|
+
}
|
|
14117
14334
|
bindEnvironmentHandle(envData) {
|
|
14118
14335
|
const graphqlEndpoint = `${this.httpUrl}/orchestrator/graphql`;
|
|
14119
14336
|
return new Environment(this, envData, this.apiKey, graphqlEndpoint);
|
|
@@ -14163,7 +14380,8 @@ var Granular = class _Granular {
|
|
|
14163
14380
|
provenance: effect.provenance || { source: "custom" },
|
|
14164
14381
|
tags: effect.tags,
|
|
14165
14382
|
className: effect.className,
|
|
14166
|
-
static: effect.static
|
|
14383
|
+
static: effect.static,
|
|
14384
|
+
versionSelector: effect.versionSelector
|
|
14167
14385
|
};
|
|
14168
14386
|
}
|
|
14169
14387
|
async publishSandboxEffectCatalog(host) {
|
|
@@ -14351,7 +14569,10 @@ var Granular = class _Granular {
|
|
|
14351
14569
|
async registerEffect(sandboxNameOrId, effect) {
|
|
14352
14570
|
const sandbox = await this.findOrCreateSandbox(sandboxNameOrId);
|
|
14353
14571
|
const sandboxId = sandbox.sandboxId;
|
|
14354
|
-
this.getSandboxEffectMap(sandboxId).set(
|
|
14572
|
+
this.getSandboxEffectMap(sandboxId).set(
|
|
14573
|
+
computeEffectRegistrationKey(effect),
|
|
14574
|
+
effect
|
|
14575
|
+
);
|
|
14355
14576
|
await this.syncSandboxEffectCatalog(sandboxId);
|
|
14356
14577
|
}
|
|
14357
14578
|
/**
|
|
@@ -14364,7 +14585,7 @@ var Granular = class _Granular {
|
|
|
14364
14585
|
const sandboxId = sandbox.sandboxId;
|
|
14365
14586
|
const map = this.getSandboxEffectMap(sandboxId);
|
|
14366
14587
|
for (const effect of effects) {
|
|
14367
|
-
map.set(
|
|
14588
|
+
map.set(computeEffectRegistrationKey(effect), effect);
|
|
14368
14589
|
}
|
|
14369
14590
|
await this.syncSandboxEffectCatalog(sandboxId);
|
|
14370
14591
|
}
|
|
@@ -14382,7 +14603,7 @@ var Granular = class _Granular {
|
|
|
14382
14603
|
return;
|
|
14383
14604
|
}
|
|
14384
14605
|
const nextEntries = Array.from(currentMap.entries()).filter(
|
|
14385
|
-
([
|
|
14606
|
+
([, effect]) => computeEffectKey2(effect) !== name && effect.name !== name
|
|
14386
14607
|
);
|
|
14387
14608
|
if (nextEntries.length === currentMap.size) {
|
|
14388
14609
|
return;
|
|
@@ -15571,12 +15792,11 @@ function buildContinuationInstruction(resultPreview) {
|
|
|
15571
15792
|
"Continue the same user request using the latest structured session state.",
|
|
15572
15793
|
"Take only the minimum next step that directly helps the user.",
|
|
15573
15794
|
"Use the active tasks, decisions, prompts, and heap references as the source of truth instead of replaying old work.",
|
|
15574
|
-
"If the user names a concrete record that is not already in the heap,
|
|
15795
|
+
"If the user names a concrete record that is not already in the heap, resolve it from the graph before saying it is missing: try a broad search, then a small set of normalized/fuzzy variants or a paged scan when the domain supports it.",
|
|
15796
|
+
"If the request needs all matching records, use iterate(...) or page until hasMore is false. A single list(...) or page(...) call is only one page.",
|
|
15575
15797
|
"If this request clearly spans multiple steps and there are no active tasks yet, create 2-4 short user-visible tasks now.",
|
|
15576
15798
|
"Reuse any existing taskId and decisionId values exactly as they appear in AGENT LOOP STATE.",
|
|
15577
|
-
"
|
|
15578
|
-
"Do not ask for confirmation in plain text. Use loop.confirm(...) when approval is needed.",
|
|
15579
|
-
"Await loop.ask_user(...) and loop.confirm(...). Those helpers pause the current job and resume it after the user answers.",
|
|
15799
|
+
"When progress depends on the user's choice, missing detail, or approval, use loop.ask_user(...) or loop.confirm(...) so the job pauses and resumes through the live workflow.",
|
|
15580
15800
|
"After a resumed ask_user or confirm call, continue the same job and perform the newly authorized action when the answer is sufficient. Do not stop with placeholder text like 'I'm ready to do it next.'",
|
|
15581
15801
|
"If you ask the user a new question in this job, do not also close the loop in the same job.",
|
|
15582
15802
|
"Write the smallest straightforward code for the current step. Avoid defensive fallback branches for hypothetical states that are not currently true.",
|
|
@@ -15764,12 +15984,13 @@ ${loopBlock}
|
|
|
15764
15984
|
- Continue from the latest structured state. Treat WORKFLOW SNAPSHOT, EXECUTION CHECKPOINT, RECENT REFERENTS, SESSION HEAP, and AGENT LOOP STATE as the working memory for this request.
|
|
15765
15985
|
- Use CAPABILITY SNAPSHOT to choose the next step, then use DOMAIN REFERENCE for exact signatures and query shapes.
|
|
15766
15986
|
- Take the minimum next step that directly helps the user. Avoid duplicate work, speculative cleanup, or extra fetching that is not needed yet.
|
|
15767
|
-
- If the user names a record that is not already in the heap, fetch it from the graph instead of saying it is not in context.
|
|
15768
|
-
- Treat user-provided names as human references, not exact keys. If one strong partial match exists, use it. If several plausible matches exist, ask the user to choose.
|
|
15769
15987
|
- Use RECENT REFERENTS to resolve follow-up references across turns, such as "that invoice", "that customer", "those products", or "the other one".
|
|
15988
|
+
- Treat user-provided names, numbers, and labels as human references, not exact keys. Resolve them with code: check recent referents/heap first, then query the graph with the broadest supported \`search\` or \`filter\`, then retry with a few normalized/fuzzy/prefix variants when the first pass is empty or ambiguous. Only say a record does not exist after a reasonable lookup across the relevant class.
|
|
15989
|
+
- If one strong match exists, use it. If several plausible matches remain, use \`loop.ask_user({ type: 'choice', ... })\` with the grounded candidates instead of guessing.
|
|
15770
15990
|
- If the request has more than one reasonable interpretation, ask the user to clarify instead of guessing.
|
|
15771
15991
|
- For comparisons, rankings, selections, or summaries, first identify the rule you are using. If that rule is not clear from the user request and DOMAIN REFERENCE, ask the user before choosing anything.
|
|
15772
15992
|
- When the ranking, comparison, or selection rule is unclear, the minimum next step is the clarification itself. Do not run a placeholder query for a provisional winner before asking.
|
|
15993
|
+
- If a user request matches both a domain type/effect and a loop helper, prioritize the domain type/effect. For example, if DOMAIN REFERENCE contains a \`Task\` class and the user asks to create a task, create the domain task record; do not call \`loop.create_task(...)\` unless you are only tracking your own workflow.
|
|
15773
15994
|
- Reuse exact \`taskId\`, \`decisionId\`, and \`closureId\` values from AGENT LOOP STATE. Never invent or rewrite them.
|
|
15774
15995
|
- If the request is ambiguous or clearly multi-step, create 2-4 short user-visible tasks and keep them updated as the workflow advances.
|
|
15775
15996
|
- Use \`loop.ask_user({ type: 'choice', options: [...] })\` when you have a short, grounded shortlist the user can choose from. Otherwise use \`type: 'input'\`.
|
|
@@ -15780,6 +16001,14 @@ ${loopBlock}
|
|
|
15780
16001
|
- Use \`loop.open_decision(...)\` to persist grounded candidates, \`loop.close_decision(...)\` to resolve one, and \`loop.close_loop(...)\` when the workflow is completed, canceled, or blocked.
|
|
15781
16002
|
- If you ask a new question in the current job, do not also close the loop in that same job.
|
|
15782
16003
|
|
|
16004
|
+
\u2500\u2500\u2500 LOOP HELPER REFERENCE \u2500\u2500\u2500
|
|
16005
|
+
- \`loop.ask_user(...)\`: pause the current job for missing input; use \`type: 'choice'\` only for a short grounded shortlist.
|
|
16006
|
+
- \`loop.confirm(...)\`: pause for yes/no approval before a consequential action, then branch on the returned boolean.
|
|
16007
|
+
- \`loop.open_decision(...)\`: save explicit candidates that later jobs can revisit; each candidate needs an \`id\`.
|
|
16008
|
+
- \`loop.close_decision(...)\`: resolve an open decision with a stored \`selectedId\` and optional rationale.
|
|
16009
|
+
- \`loop.create_task(...)\`, \`loop.update_task(...)\`, \`loop.complete_task(...)\`: keep a short resumable task list for the agent's workflow; these are not domain \`Task\` records.
|
|
16010
|
+
- \`loop.close_loop(...)\`: record the workflow outcome when it is completed, canceled, or blocked.
|
|
16011
|
+
|
|
15783
16012
|
\u2500\u2500\u2500 CODE RULES \u2500\u2500\u2500
|
|
15784
16013
|
- Import from \`./sandbox-tools\`.
|
|
15785
16014
|
- If you use \`heap\`, \`loop\`, \`agent_text_message\`, or \`agent_heap_objects\`, import them explicitly from \`./sandbox-tools\`.
|
|
@@ -15789,6 +16018,7 @@ ${loopBlock}
|
|
|
15789
16018
|
- Use \`ClassName.get({ path })\` only for known graph paths when you want a direct graph fetch.
|
|
15790
16019
|
- Use \`ClassName.count()\` for totals, \`ClassName.page({ page, perPage, saveAs })\` when you need \`items\` plus \`totalCount\` or \`hasMore\`, \`ClassName.list({ page, perPage, saveAs })\` for one page of records, and \`ClassName.iterate({ perPage, maxItems })\` for large scans.
|
|
15791
16020
|
- \`perPage\` defaults to \`100\` and is capped at \`100\`.
|
|
16021
|
+
- A single \`list(...)\` or \`page(...)\` call never proves there are no more records. For "all", "every", exports, broad scans, or exhaustive searches, use \`iterate(...)\` when available or loop \`page(...)\` until \`hasMore\` is false.
|
|
15792
16022
|
- Push \`filter\`, \`search\`, and \`sort\` into graph queries instead of fetching a page and processing it locally.
|
|
15793
16023
|
- A property appearing on a record does not make it valid in \`filter\` or \`sort\`; only use fields and operators that are explicitly exposed in DOMAIN REFERENCE.
|
|
15794
16024
|
- Choose \`sort.field\` verbatim from the sortable fields listed in DOMAIN REFERENCE. Do not sort by relationship names, related-record collections, counts, totals, or other derived metrics unless they are explicitly listed as sortable.
|