@granular-software/sdk 0.4.66 → 0.4.68
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 +2 -2
- package/dist/agent-evals.d.ts +2 -2
- package/dist/agent-evals.js +279 -36
- package/dist/agent-evals.js.map +1 -1
- package/dist/agent-evals.mjs +279 -36
- package/dist/agent-evals.mjs.map +1 -1
- package/dist/agent-harness.js +6 -0
- package/dist/agent-harness.js.map +1 -1
- package/dist/agent-harness.mjs +6 -0
- package/dist/agent-harness.mjs.map +1 -1
- package/dist/cli/index.js +274 -36
- package/dist/{client-CTpRnXpT.d.ts → client-BNpPrX2X.d.mts} +27 -9
- package/dist/{client-B8Ahz5yo.d.mts → client-C-GYQSJC.d.ts} +27 -9
- package/dist/index.d.mts +52 -4
- package/dist/index.d.ts +52 -4
- package/dist/index.js +535 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +532 -37
- package/dist/index.mjs.map +1 -1
- package/dist/{spend-x-lpt8n1.d.mts → spend-BDGtgZtl.d.mts} +4 -2
- package/dist/{spend-x-lpt8n1.d.ts → spend-BDGtgZtl.d.ts} +4 -2
- package/dist/spend.d.mts +1 -1
- package/dist/spend.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -5281,7 +5281,6 @@ var DEFAULT_RPC_TIMEOUT_MS = 3e4;
|
|
|
5281
5281
|
var DOMAIN_PACKAGE_RPC_TIMEOUT_MS = 12e4;
|
|
5282
5282
|
var EFFECT_CONTROL_RPC_TIMEOUT_MS = 12e4;
|
|
5283
5283
|
var HARNESS_RUN_RPC_TIMEOUT_MS = 6e5;
|
|
5284
|
-
var HEARTBEAT_RPC_TIMEOUT_MS = 15e3;
|
|
5285
5284
|
var DEFAULT_CONNECT_TIMEOUT_MS = 1e4;
|
|
5286
5285
|
var DEFAULT_RECONNECT_DELAY_MS = 3e3;
|
|
5287
5286
|
var DEFAULT_MAX_RECONNECT_ATTEMPTS = 5;
|
|
@@ -5327,8 +5326,6 @@ function rpcTimeoutMsForMethod(method) {
|
|
|
5327
5326
|
case "domain.fetchPackagePart":
|
|
5328
5327
|
case "domain.getSummary":
|
|
5329
5328
|
return DOMAIN_PACKAGE_RPC_TIMEOUT_MS;
|
|
5330
|
-
case "client.heartbeat":
|
|
5331
|
-
return HEARTBEAT_RPC_TIMEOUT_MS;
|
|
5332
5329
|
case "effects.publishCatalog":
|
|
5333
5330
|
case "effects.resetCatalog":
|
|
5334
5331
|
case "effects.addCatalog":
|
|
@@ -5348,6 +5345,7 @@ var WSClient = class {
|
|
|
5348
5345
|
sessionId;
|
|
5349
5346
|
token;
|
|
5350
5347
|
messageQueue = [];
|
|
5348
|
+
pendingRpcPeriodStartedAt = null;
|
|
5351
5349
|
rpcHandlers = /* @__PURE__ */ new Map();
|
|
5352
5350
|
eventHandlers = /* @__PURE__ */ new Map();
|
|
5353
5351
|
canonicalDocumentQuarantineHandlers = /* @__PURE__ */ new Set();
|
|
@@ -5362,6 +5360,7 @@ var WSClient = class {
|
|
|
5362
5360
|
cancelConnectAttempt = null;
|
|
5363
5361
|
documentRepairRequired = false;
|
|
5364
5362
|
canonicalDocumentActivated = false;
|
|
5363
|
+
lastInboundActivityAt = null;
|
|
5365
5364
|
options;
|
|
5366
5365
|
constructor(options) {
|
|
5367
5366
|
this.options = options;
|
|
@@ -5375,6 +5374,29 @@ var WSClient = class {
|
|
|
5375
5374
|
get currentSessionId() {
|
|
5376
5375
|
return this.sessionId;
|
|
5377
5376
|
}
|
|
5377
|
+
isTransportOpen() {
|
|
5378
|
+
return this.ws?.readyState === READY_STATE_OPEN;
|
|
5379
|
+
}
|
|
5380
|
+
hasPendingRpcRequests() {
|
|
5381
|
+
return this.messageQueue.length > 0;
|
|
5382
|
+
}
|
|
5383
|
+
hasRecentlyPendingRpcPeriod(maxAgeMs, now = Date.now()) {
|
|
5384
|
+
return this.messageQueue.length > 0 && this.pendingRpcPeriodStartedAt !== null && now - this.pendingRpcPeriodStartedAt <= maxAgeMs;
|
|
5385
|
+
}
|
|
5386
|
+
removePendingRpc(id) {
|
|
5387
|
+
this.messageQueue = this.messageQueue.filter(
|
|
5388
|
+
(pending) => pending.id !== id
|
|
5389
|
+
);
|
|
5390
|
+
if (this.messageQueue.length === 0) this.pendingRpcPeriodStartedAt = null;
|
|
5391
|
+
}
|
|
5392
|
+
/**
|
|
5393
|
+
* Whether the current socket has delivered any frame recently. SessionDO
|
|
5394
|
+
* broadcasts a one-way heartbeat every five seconds, so this measures the
|
|
5395
|
+
* transport without adding an RPC that can be delayed by application work.
|
|
5396
|
+
*/
|
|
5397
|
+
hasRecentInboundActivity(maxAgeMs, now = Date.now()) {
|
|
5398
|
+
return this.ws?.readyState === READY_STATE_OPEN && this.lastInboundActivityAt !== null && now - this.lastInboundActivityAt <= maxAgeMs;
|
|
5399
|
+
}
|
|
5378
5400
|
seedDocumentSnapshot(document) {
|
|
5379
5401
|
if (!document || typeof document !== "object" || Array.isArray(document)) {
|
|
5380
5402
|
return;
|
|
@@ -5526,6 +5548,7 @@ var WSClient = class {
|
|
|
5526
5548
|
const socket = this.ws;
|
|
5527
5549
|
this.connectionEpoch += 1;
|
|
5528
5550
|
this.ws = null;
|
|
5551
|
+
this.lastInboundActivityAt = null;
|
|
5529
5552
|
try {
|
|
5530
5553
|
socket?.close(4001, "Transport failure");
|
|
5531
5554
|
} catch {
|
|
@@ -5608,12 +5631,14 @@ var WSClient = class {
|
|
|
5608
5631
|
closeStaleSocket();
|
|
5609
5632
|
return;
|
|
5610
5633
|
}
|
|
5634
|
+
this.lastInboundActivityAt = Date.now();
|
|
5611
5635
|
this.reconnectAttempts = 0;
|
|
5612
5636
|
this.emit("open", {});
|
|
5613
5637
|
finish();
|
|
5614
5638
|
};
|
|
5615
5639
|
const handleMessage = (data) => {
|
|
5616
5640
|
if (!isCurrent()) return;
|
|
5641
|
+
this.lastInboundActivityAt = Date.now();
|
|
5617
5642
|
try {
|
|
5618
5643
|
const text = typeof data === "string" ? data : data && typeof data === "object" && "toString" in data ? String(data.toString()) : "";
|
|
5619
5644
|
this.handleMessage(JSON.parse(text));
|
|
@@ -5648,9 +5673,7 @@ var WSClient = class {
|
|
|
5648
5673
|
this.ws = null;
|
|
5649
5674
|
closeStaleSocket();
|
|
5650
5675
|
finish(
|
|
5651
|
-
new Error(
|
|
5652
|
-
`WebSocket connect timed out after ${connectTimeoutMs}ms`
|
|
5653
|
-
)
|
|
5676
|
+
new Error(`WebSocket connect timed out after ${connectTimeoutMs}ms`)
|
|
5654
5677
|
);
|
|
5655
5678
|
}, connectTimeoutMs);
|
|
5656
5679
|
signal?.addEventListener("abort", handleAbort, { once: true });
|
|
@@ -5690,6 +5713,7 @@ var WSClient = class {
|
|
|
5690
5713
|
pending.reject(error);
|
|
5691
5714
|
});
|
|
5692
5715
|
this.messageQueue = [];
|
|
5716
|
+
this.pendingRpcPeriodStartedAt = null;
|
|
5693
5717
|
}
|
|
5694
5718
|
emitReconnectErrorMessage(error, terminal = false) {
|
|
5695
5719
|
const reconnectInfo = {
|
|
@@ -6093,9 +6117,7 @@ var WSClient = class {
|
|
|
6093
6117
|
} else {
|
|
6094
6118
|
pending.resolve(response.result);
|
|
6095
6119
|
}
|
|
6096
|
-
this.
|
|
6097
|
-
(q) => q.id !== response.id
|
|
6098
|
-
);
|
|
6120
|
+
this.removePendingRpc(response.id);
|
|
6099
6121
|
}
|
|
6100
6122
|
return;
|
|
6101
6123
|
}
|
|
@@ -6133,16 +6155,24 @@ var WSClient = class {
|
|
|
6133
6155
|
const timeout = setTimeout(() => {
|
|
6134
6156
|
const pending = this.messageQueue.find((q) => q.id === id);
|
|
6135
6157
|
if (pending) {
|
|
6136
|
-
this.
|
|
6158
|
+
this.removePendingRpc(id);
|
|
6137
6159
|
reject(new Error(`RPC timeout: ${method}`));
|
|
6138
6160
|
}
|
|
6139
6161
|
}, timeoutMs);
|
|
6140
|
-
this.messageQueue.
|
|
6162
|
+
if (this.messageQueue.length === 0) {
|
|
6163
|
+
this.pendingRpcPeriodStartedAt = Date.now();
|
|
6164
|
+
}
|
|
6165
|
+
this.messageQueue.push({
|
|
6166
|
+
resolve,
|
|
6167
|
+
reject,
|
|
6168
|
+
id,
|
|
6169
|
+
timeout
|
|
6170
|
+
});
|
|
6141
6171
|
try {
|
|
6142
6172
|
this.ws.send(JSON.stringify(request));
|
|
6143
6173
|
} catch (error) {
|
|
6144
6174
|
clearTimeout(timeout);
|
|
6145
|
-
this.
|
|
6175
|
+
this.removePendingRpc(id);
|
|
6146
6176
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
6147
6177
|
}
|
|
6148
6178
|
});
|
|
@@ -6247,6 +6277,7 @@ var WSClient = class {
|
|
|
6247
6277
|
this.cancelConnectAttempt?.();
|
|
6248
6278
|
this.cancelConnectAttempt = null;
|
|
6249
6279
|
this.connectionEpoch += 1;
|
|
6280
|
+
this.lastInboundActivityAt = null;
|
|
6250
6281
|
if (this.reconnectTimer) {
|
|
6251
6282
|
clearTimeout(this.reconnectTimer);
|
|
6252
6283
|
this.reconnectTimer = null;
|
|
@@ -12663,6 +12694,7 @@ function mergeClassSummaryPatch(target, patch) {
|
|
|
12663
12694
|
function mergePropertySummaryPatch(target, patch) {
|
|
12664
12695
|
pushUnique(target.notes, patch.notes || []);
|
|
12665
12696
|
if (patch.searchable !== void 0) target.searchable = patch.searchable;
|
|
12697
|
+
if (patch.format !== void 0) target.format = patch.format;
|
|
12666
12698
|
if (patch.searchablePhonetic !== void 0) {
|
|
12667
12699
|
target.searchablePhonetic = patch.searchablePhonetic;
|
|
12668
12700
|
}
|
|
@@ -15550,6 +15582,91 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15550
15582
|
}
|
|
15551
15583
|
});
|
|
15552
15584
|
|
|
15585
|
+
// ../metamodel-temporal/src/index.ts
|
|
15586
|
+
function normalizeTemporalFormat(format) {
|
|
15587
|
+
return format === "date" || format === "date-time" ? format : null;
|
|
15588
|
+
}
|
|
15589
|
+
function buildTemporalFieldMutations(fieldPath, format) {
|
|
15590
|
+
const normalized = normalizeTemporalFormat(format);
|
|
15591
|
+
if (!normalized) return [];
|
|
15592
|
+
return [
|
|
15593
|
+
{
|
|
15594
|
+
label: `set temporal format on ${fieldPath}`,
|
|
15595
|
+
query: `mutation { at(path: ${JSON.stringify(fieldPath)}) { set_temporal_format(format: ${JSON.stringify(normalized)}) { format } } }`
|
|
15596
|
+
}
|
|
15597
|
+
];
|
|
15598
|
+
}
|
|
15599
|
+
var temporalMetamodelPackage = defineMetamodelPackage({
|
|
15600
|
+
id: "temporal",
|
|
15601
|
+
docs: {
|
|
15602
|
+
fieldRows: [
|
|
15603
|
+
{
|
|
15604
|
+
key: "format",
|
|
15605
|
+
description: "Temporal representation for date fields. Use `date` for a civil calendar date and `date-time` when the instant and time matter."
|
|
15606
|
+
}
|
|
15607
|
+
]
|
|
15608
|
+
},
|
|
15609
|
+
graphql: {
|
|
15610
|
+
typeDefs: [
|
|
15611
|
+
`
|
|
15612
|
+
type TemporalFormatMetamodel {
|
|
15613
|
+
model: Model!
|
|
15614
|
+
format: String!
|
|
15615
|
+
}
|
|
15616
|
+
|
|
15617
|
+
extend type Model {
|
|
15618
|
+
temporal_format: TemporalFormatMetamodel
|
|
15619
|
+
}
|
|
15620
|
+
|
|
15621
|
+
extend type ModelMutation {
|
|
15622
|
+
set_temporal_format(format: String!): TemporalFormatMetamodel
|
|
15623
|
+
}
|
|
15624
|
+
`
|
|
15625
|
+
],
|
|
15626
|
+
createResolvers({ run }) {
|
|
15627
|
+
return {
|
|
15628
|
+
TemporalFormatMetamodel: {
|
|
15629
|
+
model: (value) => value.model,
|
|
15630
|
+
format: (value) => value.format
|
|
15631
|
+
},
|
|
15632
|
+
Model: {
|
|
15633
|
+
temporal_format: async (ant) => await run(ant.temporal_format())
|
|
15634
|
+
},
|
|
15635
|
+
ModelMutation: {
|
|
15636
|
+
set_temporal_format: async (ant, { format }) => {
|
|
15637
|
+
if (format !== "date" && format !== "date-time") {
|
|
15638
|
+
throw new Error(`Unsupported temporal format: ${format}`);
|
|
15639
|
+
}
|
|
15640
|
+
return {
|
|
15641
|
+
model: await run(ant.set_temporal_format(format)),
|
|
15642
|
+
format
|
|
15643
|
+
};
|
|
15644
|
+
}
|
|
15645
|
+
}
|
|
15646
|
+
};
|
|
15647
|
+
}
|
|
15648
|
+
},
|
|
15649
|
+
manifest: {
|
|
15650
|
+
buildFieldMutations(fieldPath, spec) {
|
|
15651
|
+
return buildTemporalFieldMutations(fieldPath, spec.format);
|
|
15652
|
+
}
|
|
15653
|
+
},
|
|
15654
|
+
summary: {
|
|
15655
|
+
selections: {
|
|
15656
|
+
propertyFields: ["temporal_format { format }"]
|
|
15657
|
+
},
|
|
15658
|
+
readPropertySummary(rawProperty) {
|
|
15659
|
+
const format = rawProperty.temporal_format?.format;
|
|
15660
|
+
return format === "date" || format === "date-time" ? { format } : {};
|
|
15661
|
+
}
|
|
15662
|
+
},
|
|
15663
|
+
domain: {
|
|
15664
|
+
applyToPropertyIR(propertyIR, _propertySummary) {
|
|
15665
|
+
return propertyIR;
|
|
15666
|
+
}
|
|
15667
|
+
}
|
|
15668
|
+
});
|
|
15669
|
+
|
|
15553
15670
|
// ../metamodel-validation-rule/src/index.ts
|
|
15554
15671
|
function describeRule(rule) {
|
|
15555
15672
|
if (rule.message) return rule.message;
|
|
@@ -15819,6 +15936,7 @@ var DEFAULT_METAMODEL_PACKAGES = [
|
|
|
15819
15936
|
searchableMetamodelPackage,
|
|
15820
15937
|
validationRuleMetamodelPackage,
|
|
15821
15938
|
stateMachineMetamodelPackage,
|
|
15939
|
+
temporalMetamodelPackage,
|
|
15822
15940
|
effectBehaviorsMetamodelPackage,
|
|
15823
15941
|
policyMetamodelPackage
|
|
15824
15942
|
];
|
|
@@ -16141,16 +16259,100 @@ function normalizeEnvironmentData(environment) {
|
|
|
16141
16259
|
setup: normalizeEnvironmentSetupSummary(environment.setup)
|
|
16142
16260
|
};
|
|
16143
16261
|
}
|
|
16262
|
+
function isGraphQLMutationDocument(query) {
|
|
16263
|
+
if (typeof query !== "string") return false;
|
|
16264
|
+
const tokens = [];
|
|
16265
|
+
for (let index = 0; index < query.length; ) {
|
|
16266
|
+
const character = query[index];
|
|
16267
|
+
if (/[,\s\ufeff]/.test(character)) {
|
|
16268
|
+
index += 1;
|
|
16269
|
+
continue;
|
|
16270
|
+
}
|
|
16271
|
+
if (character === "#") {
|
|
16272
|
+
while (index < query.length && !/[\r\n]/.test(query[index])) index += 1;
|
|
16273
|
+
continue;
|
|
16274
|
+
}
|
|
16275
|
+
if (character === '"') {
|
|
16276
|
+
const block = query.startsWith('"""', index);
|
|
16277
|
+
let closed = false;
|
|
16278
|
+
index += block ? 3 : 1;
|
|
16279
|
+
while (index < query.length) {
|
|
16280
|
+
if (block && query.startsWith('"""', index) && query[index - 1] !== "\\") {
|
|
16281
|
+
index += 3;
|
|
16282
|
+
closed = true;
|
|
16283
|
+
break;
|
|
16284
|
+
}
|
|
16285
|
+
if (!block && query[index] === '"') {
|
|
16286
|
+
index += 1;
|
|
16287
|
+
closed = true;
|
|
16288
|
+
break;
|
|
16289
|
+
}
|
|
16290
|
+
index += query[index] === "\\" && !block ? 2 : 1;
|
|
16291
|
+
}
|
|
16292
|
+
if (!closed) return true;
|
|
16293
|
+
continue;
|
|
16294
|
+
}
|
|
16295
|
+
const name = query.slice(index).match(/^[_A-Za-z][_0-9A-Za-z]*/)?.[0];
|
|
16296
|
+
if (name) {
|
|
16297
|
+
tokens.push(name);
|
|
16298
|
+
index += name.length;
|
|
16299
|
+
continue;
|
|
16300
|
+
}
|
|
16301
|
+
if ("{}()[]".includes(character)) tokens.push(character);
|
|
16302
|
+
index += 1;
|
|
16303
|
+
}
|
|
16304
|
+
const skipSelection = (start) => {
|
|
16305
|
+
let depth = 0;
|
|
16306
|
+
for (let index = start; index < tokens.length; index += 1) {
|
|
16307
|
+
if (tokens[index] === "{") depth += 1;
|
|
16308
|
+
if (tokens[index] === "}" && --depth === 0) return index + 1;
|
|
16309
|
+
}
|
|
16310
|
+
return null;
|
|
16311
|
+
};
|
|
16312
|
+
for (let index = 0; index < tokens.length; ) {
|
|
16313
|
+
const definition = tokens[index++];
|
|
16314
|
+
if (definition === "mutation") return true;
|
|
16315
|
+
if (definition === "{") {
|
|
16316
|
+
const nextDefinition2 = skipSelection(index - 1);
|
|
16317
|
+
if (nextDefinition2 === null) return true;
|
|
16318
|
+
index = nextDefinition2;
|
|
16319
|
+
continue;
|
|
16320
|
+
}
|
|
16321
|
+
if (!["query", "subscription", "fragment"].includes(definition || "")) {
|
|
16322
|
+
return true;
|
|
16323
|
+
}
|
|
16324
|
+
let parentheses = 0;
|
|
16325
|
+
let brackets = 0;
|
|
16326
|
+
while (index < tokens.length) {
|
|
16327
|
+
const token = tokens[index];
|
|
16328
|
+
if (token === "(") parentheses += 1;
|
|
16329
|
+
else if (token === ")") parentheses -= 1;
|
|
16330
|
+
else if (token === "[") brackets += 1;
|
|
16331
|
+
else if (token === "]") brackets -= 1;
|
|
16332
|
+
else if (token === "{" && parentheses === 0 && brackets === 0) break;
|
|
16333
|
+
index += 1;
|
|
16334
|
+
}
|
|
16335
|
+
if (index === tokens.length) return true;
|
|
16336
|
+
const nextDefinition = skipSelection(index);
|
|
16337
|
+
if (nextDefinition === null) return true;
|
|
16338
|
+
index = nextDefinition;
|
|
16339
|
+
}
|
|
16340
|
+
return false;
|
|
16341
|
+
}
|
|
16144
16342
|
var Environment = class _Environment {
|
|
16145
16343
|
granular;
|
|
16146
16344
|
envData;
|
|
16147
16345
|
_apiKey;
|
|
16148
16346
|
_apiEndpoint;
|
|
16149
|
-
|
|
16347
|
+
_tokenProvider;
|
|
16348
|
+
_beforeMutationSend;
|
|
16349
|
+
constructor(granular, envData, apiKey, apiEndpoint, tokenProvider, beforeMutationSend) {
|
|
16150
16350
|
this.granular = granular;
|
|
16151
16351
|
this.envData = envData;
|
|
16152
16352
|
this._apiKey = apiKey;
|
|
16153
16353
|
this._apiEndpoint = apiEndpoint;
|
|
16354
|
+
this._tokenProvider = tokenProvider;
|
|
16355
|
+
this._beforeMutationSend = beforeMutationSend;
|
|
16154
16356
|
}
|
|
16155
16357
|
/** The environment ID */
|
|
16156
16358
|
get environmentId() {
|
|
@@ -16216,6 +16418,15 @@ var Environment = class _Environment {
|
|
|
16216
16418
|
get authToken() {
|
|
16217
16419
|
return this._apiKey;
|
|
16218
16420
|
}
|
|
16421
|
+
resolveAuthToken() {
|
|
16422
|
+
if (!this._tokenProvider) return this._apiKey;
|
|
16423
|
+
return Promise.resolve(this._tokenProvider()).then((provided) => {
|
|
16424
|
+
if (typeof provided === "string" && provided.trim()) {
|
|
16425
|
+
this._apiKey = provided.trim();
|
|
16426
|
+
}
|
|
16427
|
+
return this._apiKey;
|
|
16428
|
+
});
|
|
16429
|
+
}
|
|
16219
16430
|
/** Base runtime URL derived from the GraphQL endpoint */
|
|
16220
16431
|
get runtimeBaseUrl() {
|
|
16221
16432
|
return this.getRuntimeBaseUrl();
|
|
@@ -16607,10 +16818,15 @@ var Environment = class _Environment {
|
|
|
16607
16818
|
async controlPlaneRequest(path, options = {}) {
|
|
16608
16819
|
const runtimeBase = this.getRuntimeBaseUrl();
|
|
16609
16820
|
const url = `${runtimeBase}${path}`;
|
|
16821
|
+
const authToken = await this.resolveAuthToken();
|
|
16822
|
+
const method = (options.method || "GET").toUpperCase();
|
|
16823
|
+
if (method !== "GET" && method !== "HEAD" && method !== "OPTIONS") {
|
|
16824
|
+
this._beforeMutationSend?.();
|
|
16825
|
+
}
|
|
16610
16826
|
const response = await fetch(url, {
|
|
16611
16827
|
...options,
|
|
16612
16828
|
headers: {
|
|
16613
|
-
Authorization: `Bearer ${
|
|
16829
|
+
Authorization: `Bearer ${authToken}`,
|
|
16614
16830
|
"Content-Type": "application/json",
|
|
16615
16831
|
...options.headers
|
|
16616
16832
|
}
|
|
@@ -16675,11 +16891,15 @@ var Environment = class _Environment {
|
|
|
16675
16891
|
* ```
|
|
16676
16892
|
*/
|
|
16677
16893
|
async graphql(query, variables) {
|
|
16894
|
+
const authToken = await this.resolveAuthToken();
|
|
16895
|
+
if (this._beforeMutationSend && isGraphQLMutationDocument(query)) {
|
|
16896
|
+
this._beforeMutationSend?.();
|
|
16897
|
+
}
|
|
16678
16898
|
const response = await fetch(this._apiEndpoint, {
|
|
16679
16899
|
method: "POST",
|
|
16680
16900
|
headers: {
|
|
16681
16901
|
"Content-Type": "application/json",
|
|
16682
|
-
Authorization: `Bearer ${
|
|
16902
|
+
Authorization: `Bearer ${authToken}`
|
|
16683
16903
|
},
|
|
16684
16904
|
body: JSON.stringify({
|
|
16685
16905
|
environmentId: this.environmentId,
|
|
@@ -17158,8 +17378,10 @@ var Environment = class _Environment {
|
|
|
17158
17378
|
eventType.payloadSchema.properties
|
|
17159
17379
|
)) {
|
|
17160
17380
|
const schema = propSchema;
|
|
17381
|
+
const format = schema.format === "date" || schema.format === "date-time" ? schema.format : void 0;
|
|
17161
17382
|
fieldSpecs[propName] = {
|
|
17162
17383
|
type: schema.type ?? "string",
|
|
17384
|
+
...format ? { format } : {},
|
|
17163
17385
|
description: schema.description
|
|
17164
17386
|
};
|
|
17165
17387
|
}
|
|
@@ -17581,40 +17803,36 @@ var EnvironmentSession = class extends Session {
|
|
|
17581
17803
|
environment;
|
|
17582
17804
|
sessionDataRoutePrefix;
|
|
17583
17805
|
sessionDataHeaders;
|
|
17806
|
+
beforeMutationSend;
|
|
17584
17807
|
heartbeatTimer = null;
|
|
17585
|
-
|
|
17586
|
-
/** The last known graph container status, updated by checkReadiness() or on heartbeat */
|
|
17808
|
+
/** The last known graph container status, updated by checkReadiness(). */
|
|
17587
17809
|
graphContainerStatus = null;
|
|
17588
17810
|
constructor(client, environment, clientId, options = {}) {
|
|
17589
17811
|
super(client, clientId, { initialQuota: options.initialQuota });
|
|
17590
17812
|
this.environment = environment;
|
|
17591
17813
|
this.sessionDataRoutePrefix = options.sessionDataRoutePrefix || "/orchestrator/ws/sessions";
|
|
17592
17814
|
this.sessionDataHeaders = options.sessionDataHeaders || {};
|
|
17815
|
+
this.beforeMutationSend = options.beforeMutationSend;
|
|
17593
17816
|
this.setFeedListTransport(
|
|
17594
17817
|
(feedOptions) => this.sessionDataRequest("/feed", feedOptions)
|
|
17595
17818
|
);
|
|
17596
17819
|
}
|
|
17597
17820
|
/**
|
|
17598
17821
|
* Keep the browser session transport observable from the client side.
|
|
17599
|
-
*
|
|
17600
|
-
*
|
|
17601
|
-
*
|
|
17602
|
-
*
|
|
17822
|
+
* SessionDO already broadcasts a heartbeat every five seconds. Treat that
|
|
17823
|
+
* and all other inbound frames as proof of life instead of issuing an RPC:
|
|
17824
|
+
* an application RPC may be delayed by Durable Object work even while the
|
|
17825
|
+
* underlying WebSocket is healthy.
|
|
17603
17826
|
*/
|
|
17604
17827
|
startHeartbeat() {
|
|
17605
17828
|
if (this.heartbeatTimer) return;
|
|
17606
17829
|
this.heartbeatTimer = setInterval(() => {
|
|
17607
|
-
if (this.
|
|
17608
|
-
this.
|
|
17609
|
-
|
|
17610
|
-
|
|
17611
|
-
|
|
17612
|
-
|
|
17613
|
-
}).catch((error) => {
|
|
17614
|
-
this.client.reportTransportFailure(error);
|
|
17615
|
-
}).finally(() => {
|
|
17616
|
-
this.heartbeatInFlight = false;
|
|
17617
|
-
});
|
|
17830
|
+
if (!this.client.isTransportOpen()) return;
|
|
17831
|
+
if (this.client.hasRecentInboundActivity(3e4)) return;
|
|
17832
|
+
if (this.client.hasRecentlyPendingRpcPeriod(6e4)) return;
|
|
17833
|
+
this.client.reportTransportFailure(
|
|
17834
|
+
new Error("No server activity received for 30 seconds")
|
|
17835
|
+
);
|
|
17618
17836
|
}, 5e3);
|
|
17619
17837
|
this.heartbeatTimer.unref?.();
|
|
17620
17838
|
}
|
|
@@ -17623,7 +17841,6 @@ var EnvironmentSession = class extends Session {
|
|
|
17623
17841
|
clearInterval(this.heartbeatTimer);
|
|
17624
17842
|
this.heartbeatTimer = null;
|
|
17625
17843
|
}
|
|
17626
|
-
this.heartbeatInFlight = false;
|
|
17627
17844
|
}
|
|
17628
17845
|
async hello() {
|
|
17629
17846
|
const result = await super.hello();
|
|
@@ -17684,7 +17901,13 @@ var EnvironmentSession = class extends Session {
|
|
|
17684
17901
|
for (let attempt = 1; attempt <= SESSION_DATA_REQUEST_RETRY_COUNT; attempt += 1) {
|
|
17685
17902
|
try {
|
|
17686
17903
|
const headers = new Headers(init2.headers);
|
|
17687
|
-
|
|
17904
|
+
const resolvedAuthToken = this.environment.resolveAuthToken();
|
|
17905
|
+
const authToken = typeof resolvedAuthToken === "string" ? resolvedAuthToken : await resolvedAuthToken;
|
|
17906
|
+
headers.set("Authorization", `Bearer ${authToken}`);
|
|
17907
|
+
const method = (init2.method || "GET").toUpperCase();
|
|
17908
|
+
if (method !== "GET" && method !== "HEAD" && method !== "OPTIONS") {
|
|
17909
|
+
this.beforeMutationSend?.();
|
|
17910
|
+
}
|
|
17688
17911
|
const response = await fetch(url, {
|
|
17689
17912
|
method: init2.method || "GET",
|
|
17690
17913
|
headers,
|
|
@@ -18143,7 +18366,7 @@ var EnvironmentSession = class extends Session {
|
|
|
18143
18366
|
method: "POST",
|
|
18144
18367
|
headers: {
|
|
18145
18368
|
"Content-Type": "application/json",
|
|
18146
|
-
Authorization: `Bearer ${this.environment.
|
|
18369
|
+
Authorization: `Bearer ${await this.environment.resolveAuthToken()}`
|
|
18147
18370
|
},
|
|
18148
18371
|
body: JSON.stringify({
|
|
18149
18372
|
reason: "sdk_disconnect_http_fallback",
|
|
@@ -19081,6 +19304,10 @@ var Granular = class _Granular {
|
|
|
19081
19304
|
});
|
|
19082
19305
|
}
|
|
19083
19306
|
async recordOpenAIUsageSpend(usage, context, options) {
|
|
19307
|
+
const providedToken = await this.tokenProvider?.();
|
|
19308
|
+
if (typeof providedToken === "string" && providedToken.trim()) {
|
|
19309
|
+
this.apiKey = providedToken.trim();
|
|
19310
|
+
}
|
|
19084
19311
|
return recordOpenAIUsageSpend({
|
|
19085
19312
|
apiUrl: this.apiUrl,
|
|
19086
19313
|
token: this.apiKey,
|
|
@@ -19253,7 +19480,13 @@ var Granular = class _Granular {
|
|
|
19253
19480
|
}
|
|
19254
19481
|
bindEnvironmentHandle(envData) {
|
|
19255
19482
|
const graphqlEndpoint = `${this.httpUrl}/orchestrator/graphql`;
|
|
19256
|
-
return new Environment(
|
|
19483
|
+
return new Environment(
|
|
19484
|
+
this,
|
|
19485
|
+
envData,
|
|
19486
|
+
this.apiKey,
|
|
19487
|
+
graphqlEndpoint,
|
|
19488
|
+
this.tokenProvider
|
|
19489
|
+
);
|
|
19257
19490
|
}
|
|
19258
19491
|
async bindWebSocketEnvironmentSession(environment, clientId, session, transportOptions = {}) {
|
|
19259
19492
|
const client = new WSClient({
|
|
@@ -20137,6 +20370,10 @@ var Granular = class _Granular {
|
|
|
20137
20370
|
console.log(`[SDK] Requesting: ${url}`);
|
|
20138
20371
|
}
|
|
20139
20372
|
for (let attempt = 1; attempt <= LOCAL_CONTROL_REQUEST_RETRY_COUNT; attempt += 1) {
|
|
20373
|
+
const providedToken = await this.tokenProvider?.();
|
|
20374
|
+
if (typeof providedToken === "string" && providedToken.trim()) {
|
|
20375
|
+
this.apiKey = providedToken.trim();
|
|
20376
|
+
}
|
|
20140
20377
|
const response = await fetch(url, {
|
|
20141
20378
|
...options,
|
|
20142
20379
|
headers: {
|
|
@@ -20172,6 +20409,258 @@ var Granular = class _Granular {
|
|
|
20172
20409
|
}
|
|
20173
20410
|
};
|
|
20174
20411
|
|
|
20412
|
+
// src/environment-setup.ts
|
|
20413
|
+
var EnvironmentSetupTerminalError = class extends Error {
|
|
20414
|
+
constructor(setup) {
|
|
20415
|
+
super(
|
|
20416
|
+
setup?.errorMessage?.trim() || "Environment setup failed before all records were imported."
|
|
20417
|
+
);
|
|
20418
|
+
this.name = "EnvironmentSetupTerminalError";
|
|
20419
|
+
}
|
|
20420
|
+
};
|
|
20421
|
+
function environmentSetupFailedError(setup) {
|
|
20422
|
+
return new EnvironmentSetupTerminalError(setup);
|
|
20423
|
+
}
|
|
20424
|
+
function environmentSetupAbortError() {
|
|
20425
|
+
const error = new Error("Environment setup polling was aborted.");
|
|
20426
|
+
error.name = "AbortError";
|
|
20427
|
+
return error;
|
|
20428
|
+
}
|
|
20429
|
+
function throwIfAborted(signal) {
|
|
20430
|
+
if (signal.aborted) {
|
|
20431
|
+
throw environmentSetupAbortError();
|
|
20432
|
+
}
|
|
20433
|
+
}
|
|
20434
|
+
function abortableSleep(ms, signal) {
|
|
20435
|
+
return new Promise((resolve, reject) => {
|
|
20436
|
+
if (signal.aborted) {
|
|
20437
|
+
reject(environmentSetupAbortError());
|
|
20438
|
+
return;
|
|
20439
|
+
}
|
|
20440
|
+
const timeout = setTimeout(() => {
|
|
20441
|
+
signal.removeEventListener("abort", abort);
|
|
20442
|
+
resolve();
|
|
20443
|
+
}, ms);
|
|
20444
|
+
const abort = () => {
|
|
20445
|
+
clearTimeout(timeout);
|
|
20446
|
+
signal.removeEventListener("abort", abort);
|
|
20447
|
+
reject(environmentSetupAbortError());
|
|
20448
|
+
};
|
|
20449
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
20450
|
+
});
|
|
20451
|
+
}
|
|
20452
|
+
function setupIsRunning(setup) {
|
|
20453
|
+
return setup?.lifecycleStatus === "running";
|
|
20454
|
+
}
|
|
20455
|
+
function setupHasFailed(setup) {
|
|
20456
|
+
return setup?.lifecycleStatus === "failed";
|
|
20457
|
+
}
|
|
20458
|
+
function hasRecordFailures(setup) {
|
|
20459
|
+
return Boolean(
|
|
20460
|
+
setup && (setup.failedRecords > 0 || setup.canceledRecords > 0)
|
|
20461
|
+
);
|
|
20462
|
+
}
|
|
20463
|
+
function setupHasTerminalLifecycleFailure(setup) {
|
|
20464
|
+
return setupHasFailed(setup);
|
|
20465
|
+
}
|
|
20466
|
+
function importsAreActive(summary) {
|
|
20467
|
+
return Boolean(
|
|
20468
|
+
summary && (summary.awaitingRecords > 0 || summary.activeImports > 0)
|
|
20469
|
+
);
|
|
20470
|
+
}
|
|
20471
|
+
function numericRetryAfter(value) {
|
|
20472
|
+
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.round(value)) : null;
|
|
20473
|
+
}
|
|
20474
|
+
function environmentSetupTimeoutError(maxDurationMs) {
|
|
20475
|
+
return new Error(`Environment setup timed out after ${maxDurationMs}ms.`);
|
|
20476
|
+
}
|
|
20477
|
+
function environmentSetupProgressFromResponse(environment, response, retryAfterMs) {
|
|
20478
|
+
const readiness = response.readiness;
|
|
20479
|
+
const nextEnvironment = {
|
|
20480
|
+
...environment,
|
|
20481
|
+
...response.environment || {}
|
|
20482
|
+
};
|
|
20483
|
+
const explicitReady = typeof readiness?.ready === "boolean" ? readiness.ready : typeof response.ready === "boolean" ? response.ready : void 0;
|
|
20484
|
+
const hasResponseSetup = Object.prototype.hasOwnProperty.call(
|
|
20485
|
+
response,
|
|
20486
|
+
"setup"
|
|
20487
|
+
);
|
|
20488
|
+
const hasReadinessSetup = readiness !== null && typeof readiness === "object" && Object.prototype.hasOwnProperty.call(readiness, "setup");
|
|
20489
|
+
const hasEnvironmentSetup = response.environment !== null && typeof response.environment === "object" && Object.prototype.hasOwnProperty.call(response.environment, "setup");
|
|
20490
|
+
const setup = hasResponseSetup ? response.setup ?? null : hasReadinessSetup ? readiness?.setup ?? null : hasEnvironmentSetup ? response.environment?.setup ?? null : explicitReady === true ? null : nextEnvironment.setup ?? null;
|
|
20491
|
+
nextEnvironment.setup = setup;
|
|
20492
|
+
const summary = response.summary ?? readiness?.summary ?? null;
|
|
20493
|
+
const retry = [
|
|
20494
|
+
retryAfterMs,
|
|
20495
|
+
response.retryAfterMs,
|
|
20496
|
+
readiness?.retryAfterMs
|
|
20497
|
+
].find((value) => typeof value === "number" && Number.isFinite(value));
|
|
20498
|
+
const recordFailures = hasRecordFailures(setup) || hasRecordFailures(summary);
|
|
20499
|
+
return {
|
|
20500
|
+
environment: nextEnvironment,
|
|
20501
|
+
setup,
|
|
20502
|
+
summary,
|
|
20503
|
+
ready: explicitReady !== false && !setupIsRunning(setup) && !setupHasFailed(setup) && (explicitReady === true || !recordFailures) && !importsAreActive(summary),
|
|
20504
|
+
retryAfterMs: numericRetryAfter(retry)
|
|
20505
|
+
};
|
|
20506
|
+
}
|
|
20507
|
+
function environmentSetupProgressFromError(environment, error) {
|
|
20508
|
+
if (!error || typeof error !== "object") return null;
|
|
20509
|
+
const candidate = error;
|
|
20510
|
+
if (candidate.status !== 503 && candidate.status !== 202 || typeof candidate.body !== "string") {
|
|
20511
|
+
return null;
|
|
20512
|
+
}
|
|
20513
|
+
try {
|
|
20514
|
+
const response = JSON.parse(candidate.body);
|
|
20515
|
+
const explicitReady = response?.readiness?.ready ?? (typeof response?.ready === "boolean" ? response.ready : void 0);
|
|
20516
|
+
if (candidate.status === 202) {
|
|
20517
|
+
const progress = environmentSetupProgressFromResponse(
|
|
20518
|
+
environment,
|
|
20519
|
+
response,
|
|
20520
|
+
numericRetryAfter(candidate.retryAfterMs)
|
|
20521
|
+
);
|
|
20522
|
+
return explicitReady === void 0 ? { ...progress, ready: false } : progress;
|
|
20523
|
+
}
|
|
20524
|
+
return explicitReady === false ? environmentSetupProgressFromResponse(
|
|
20525
|
+
environment,
|
|
20526
|
+
response,
|
|
20527
|
+
numericRetryAfter(candidate.retryAfterMs)
|
|
20528
|
+
) : null;
|
|
20529
|
+
} catch {
|
|
20530
|
+
return null;
|
|
20531
|
+
}
|
|
20532
|
+
}
|
|
20533
|
+
function defaultTransientError(error) {
|
|
20534
|
+
if (!error) return false;
|
|
20535
|
+
const status = typeof error === "object" ? error.status : void 0;
|
|
20536
|
+
if (typeof status === "number") {
|
|
20537
|
+
return status === 408 || status === 425 || status === 429 || status >= 500;
|
|
20538
|
+
}
|
|
20539
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
20540
|
+
return /failed to fetch|network error|network connection lost|connection (?:reset|closed|refused)|econnreset|socket hang up|socket connection was closed unexpectedly|dns|timed out/i.test(
|
|
20541
|
+
message
|
|
20542
|
+
);
|
|
20543
|
+
}
|
|
20544
|
+
async function pollEnvironmentSetup(input) {
|
|
20545
|
+
const maxAttempts = Math.max(1, input.maxAttempts ?? 3);
|
|
20546
|
+
const maxDurationMs = Math.max(1, input.maxDurationMs ?? 12e4);
|
|
20547
|
+
const sleep2 = input.sleep || ((ms, signal2) => abortableSleep(ms, signal2 || new AbortController().signal));
|
|
20548
|
+
const now = input.now || (() => Date.now());
|
|
20549
|
+
const isTransientError = input.isTransientError || defaultTransientError;
|
|
20550
|
+
const internalController = input.signal ? null : new AbortController();
|
|
20551
|
+
const signal = input.signal || internalController.signal;
|
|
20552
|
+
const startedAt = now();
|
|
20553
|
+
let currentEnvironment = input.environment;
|
|
20554
|
+
let transientFailures = 0;
|
|
20555
|
+
let attempt = 0;
|
|
20556
|
+
const waitForNextAttempt = async (requestedDelayMs) => {
|
|
20557
|
+
throwIfAborted(signal);
|
|
20558
|
+
const remainingMs = maxDurationMs - Math.max(0, now() - startedAt);
|
|
20559
|
+
if (remainingMs <= 0) {
|
|
20560
|
+
throw environmentSetupTimeoutError(maxDurationMs);
|
|
20561
|
+
}
|
|
20562
|
+
await sleep2(Math.min(Math.max(0, requestedDelayMs), remainingMs), signal);
|
|
20563
|
+
throwIfAborted(signal);
|
|
20564
|
+
};
|
|
20565
|
+
const requestWithinDeadline = async (requestAttempt) => {
|
|
20566
|
+
throwIfAborted(signal);
|
|
20567
|
+
const remainingMs = maxDurationMs - Math.max(0, now() - startedAt);
|
|
20568
|
+
if (remainingMs <= 0) {
|
|
20569
|
+
throw environmentSetupTimeoutError(maxDurationMs);
|
|
20570
|
+
}
|
|
20571
|
+
const requestController = new AbortController();
|
|
20572
|
+
let timeoutHandle = null;
|
|
20573
|
+
let abortHandler = null;
|
|
20574
|
+
const requestPromise = Promise.resolve().then(
|
|
20575
|
+
() => input.request(requestAttempt, requestController.signal)
|
|
20576
|
+
);
|
|
20577
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
20578
|
+
if (!Number.isFinite(remainingMs)) return;
|
|
20579
|
+
timeoutHandle = setTimeout(
|
|
20580
|
+
() => {
|
|
20581
|
+
reject(environmentSetupTimeoutError(maxDurationMs));
|
|
20582
|
+
requestController.abort();
|
|
20583
|
+
},
|
|
20584
|
+
Math.max(1, Math.ceil(remainingMs))
|
|
20585
|
+
);
|
|
20586
|
+
});
|
|
20587
|
+
const abortPromise = new Promise((_, reject) => {
|
|
20588
|
+
abortHandler = () => {
|
|
20589
|
+
requestController.abort();
|
|
20590
|
+
reject(environmentSetupAbortError());
|
|
20591
|
+
};
|
|
20592
|
+
signal.addEventListener("abort", abortHandler, { once: true });
|
|
20593
|
+
});
|
|
20594
|
+
try {
|
|
20595
|
+
return await Promise.race([requestPromise, timeoutPromise, abortPromise]);
|
|
20596
|
+
} finally {
|
|
20597
|
+
if (timeoutHandle !== null) {
|
|
20598
|
+
clearTimeout(timeoutHandle);
|
|
20599
|
+
}
|
|
20600
|
+
if (abortHandler !== null) {
|
|
20601
|
+
signal.removeEventListener("abort", abortHandler);
|
|
20602
|
+
}
|
|
20603
|
+
}
|
|
20604
|
+
};
|
|
20605
|
+
while (true) {
|
|
20606
|
+
throwIfAborted(signal);
|
|
20607
|
+
if (now() - startedAt >= maxDurationMs) {
|
|
20608
|
+
throw environmentSetupTimeoutError(maxDurationMs);
|
|
20609
|
+
}
|
|
20610
|
+
attempt += 1;
|
|
20611
|
+
try {
|
|
20612
|
+
const progress = environmentSetupProgressFromResponse(
|
|
20613
|
+
currentEnvironment,
|
|
20614
|
+
await requestWithinDeadline(attempt)
|
|
20615
|
+
);
|
|
20616
|
+
throwIfAborted(signal);
|
|
20617
|
+
currentEnvironment = progress.environment;
|
|
20618
|
+
input.onProgress?.(progress);
|
|
20619
|
+
if (setupHasTerminalLifecycleFailure(progress.setup) && !progress.ready) {
|
|
20620
|
+
throw environmentSetupFailedError(progress.setup);
|
|
20621
|
+
}
|
|
20622
|
+
if (progress.ready) return progress.environment;
|
|
20623
|
+
transientFailures = 0;
|
|
20624
|
+
await waitForNextAttempt(
|
|
20625
|
+
progress.retryAfterMs ?? input.pollIntervalMs ?? 1e3
|
|
20626
|
+
);
|
|
20627
|
+
} catch (error) {
|
|
20628
|
+
throwIfAborted(signal);
|
|
20629
|
+
if (error instanceof EnvironmentSetupTerminalError) {
|
|
20630
|
+
throw error;
|
|
20631
|
+
}
|
|
20632
|
+
const pending = environmentSetupProgressFromError(
|
|
20633
|
+
currentEnvironment,
|
|
20634
|
+
error
|
|
20635
|
+
);
|
|
20636
|
+
if (pending) {
|
|
20637
|
+
currentEnvironment = pending.environment;
|
|
20638
|
+
input.onProgress?.(pending);
|
|
20639
|
+
if (setupHasTerminalLifecycleFailure(pending.setup) && !pending.ready) {
|
|
20640
|
+
throw environmentSetupFailedError(pending.setup);
|
|
20641
|
+
}
|
|
20642
|
+
if (pending.ready) return pending.environment;
|
|
20643
|
+
transientFailures = 0;
|
|
20644
|
+
await waitForNextAttempt(
|
|
20645
|
+
pending.retryAfterMs ?? input.pollIntervalMs ?? 1e3
|
|
20646
|
+
);
|
|
20647
|
+
continue;
|
|
20648
|
+
}
|
|
20649
|
+
if (!isTransientError(error) || transientFailures + 1 >= maxAttempts) {
|
|
20650
|
+
throw error;
|
|
20651
|
+
}
|
|
20652
|
+
transientFailures += 1;
|
|
20653
|
+
input.onRetry?.({ attempt: transientFailures, error });
|
|
20654
|
+
const retryAfterMs = numericRetryAfter(
|
|
20655
|
+
error && typeof error === "object" ? error.retryAfterMs : null
|
|
20656
|
+
);
|
|
20657
|
+
await waitForNextAttempt(
|
|
20658
|
+
retryAfterMs ?? (input.retryDelayMs ?? 1500) * transientFailures
|
|
20659
|
+
);
|
|
20660
|
+
}
|
|
20661
|
+
}
|
|
20662
|
+
}
|
|
20663
|
+
|
|
20175
20664
|
// src/record-snapshot-projection.ts
|
|
20176
20665
|
function stableValue(value) {
|
|
20177
20666
|
if (Array.isArray(value)) return value.map(stableValue);
|
|
@@ -22348,6 +22837,10 @@ function jsonSchemaTypeName(schema) {
|
|
|
22348
22837
|
const record = normalizeJsonSchema(schema);
|
|
22349
22838
|
if (!record) return "unknown";
|
|
22350
22839
|
const type = record.type;
|
|
22840
|
+
if (record.format === "date-time") return "date-time";
|
|
22841
|
+
if (record.format === "date" || type === "date" || Array.isArray(type) && type.includes("date")) {
|
|
22842
|
+
return "date";
|
|
22843
|
+
}
|
|
22351
22844
|
if (typeof type === "string") {
|
|
22352
22845
|
if (type === "array") return "array";
|
|
22353
22846
|
if (type === "object") return "object";
|
|
@@ -22849,6 +23342,8 @@ ${actionIndex}
|
|
|
22849
23342
|
- A suggestion is a recommendation button: \`await stateHandle.suggest(message)\`. A prepared action is the editable form the user can review/run: \`const action = stateHandle.reach(); const prepared = await action.open()\`.
|
|
22850
23343
|
- Use suggestions when the user asks "what can I do next?", asks for options, or gives an unclear intent. Prefer 2 to 5 concrete suggestions and keep text short.
|
|
22851
23344
|
- Opening a prepared action does not execute the underlying mutation. Use \`.open()\` only when the user asks to prepare, review, show, or edit an action before running it, when a new record must be prepared, or when a reviewable form must collect missing editable inputs. Prefill only grounded values and leave unknown fields empty.
|
|
23345
|
+
- For creation inputs, use the declared action schema and its field descriptions as the mapping authority. Copy every compatible value explicitly present in the current request, conversation, selected/saved object, file, fresh read, or declared ontology default, including values for fields with arbitrary names. Omit only values for which that context provides no evidence.
|
|
23346
|
+
- Never fill an input because of its field name, a regular expression or other string pattern, its primitive type, a schema minimum, an example value, or the first enum option. If the evidence is ambiguous, leave the field unresolved or ask the user.
|
|
22852
23347
|
- When the user explicitly commands an existing-record mutation such as approve, reject, block, route, send, or update, and one visible domain action uniquely matches, call that domain action directly. Do not substitute a state-handle \`.open()\` artifact for execution. If runtime policy requires confirmation, invoke the action once and let the runtime pause and resume that same invocation.
|
|
22853
23348
|
- When a grounded related/context record can satisfy the prepared action through declared relationships, use those relationships to fill required relationship inputs before opening or updating the action. If a required relationship remains empty, continue through declared relationship chains from the grounded object when the next hop can fill that slot. Do not only save the context record in memory while leaving derivable relationship slots blank.
|
|
22854
23349
|
- A derived intermediate relationship is not enough when another required relationship is still reachable from it. For example, if a team gives a cost center and the action also requires a budget, traverse the cost center's declared budget relationship before opening the action.
|
|
@@ -23449,6 +23944,6 @@ function calculateOpenAITokenSpend(model, rawUsage) {
|
|
|
23449
23944
|
};
|
|
23450
23945
|
}
|
|
23451
23946
|
|
|
23452
|
-
export { Environment, EnvironmentSession, GRANULAR_FEED_DIAGNOSTIC_EVENT, Granular, OPENAI_MODEL_PRICING_USD_PER_MILLION, OntologyHandle, Session, SessionFeedController, WSClient, buildContinuationInstruction, buildContinuationInstructionFromTemplate, buildGranularAgentCheckpointBlock, buildGranularAgentDomainBlock, buildGranularAgentFileBlock, buildGranularAgentHeapBlock, buildGranularAgentLoopBlock, buildGranularAgentManualActionBlock, buildGranularAgentManualActionMemorySummary, buildGranularAgentReferentBlock, buildGranularAgentRuntimeImportsBlock, buildGranularAgentSessionBlock, buildGranularAgentSystemPrompt, buildGranularAgentSystemPromptFromTemplate, buildGranularAgentToolBlock, buildGranularAgentWorkflowBlock, buildOpenAISpendEventId, buildSessionTranscript, buildSessionTranscriptFromFeedItems, calculateOpenAITokenSpend, canonicalizeCommitValue, changedRecordSnapshots, consumeGranularReasoningOnlyChunk, consumeGranularReasoningTraceChunk, createFeedPublisher, createHarnessVerifierSnapshot, defineEffect, defineProjection, defineStateMachine, emitFeedDiagnostic, emitFeedDiagnosticToDefaultSink, emptyFeedSnapshot, evaluateContinuation, evaluateValidationRule, extractPromptTokens, getCurrentClosureId, getDefaultHarnessTemplateId, getExclusivePromptTarget, getOpenAIModelPricing, hasCanonicalSessionFeedActivation, hasOpenPrompt, hashHarnessTemplateValue, invokeRegisteredEffect, isCanonicalSessionFeedDocument, isLocalApiUrl, listHarnessTemplates, mergeFeedItemsBySequence, normalizeEffectBehaviors, normalizeFeedDiagnostic, normalizeFeedDiagnosticKind, normalizeFeedPage, normalizeOpenAIUsage, normalizePrompt, normalizePromptChoiceOption, normalizePromptText, normalizePromptType, orderTransientFeedItems, projectConversationReferentFocus, projectConversationReferentSummary, projectHeapSummary, projectLoopSummary, projectRecordSnapshotMutation, projectSessionFileSummary, projectWorkflowFocus, projectWorkflowSummary, readSessionFeedSnapshot, recordOpenAIUsageSpend, renderContinuationInstructionFromTemplate, renderGranularAgentSystemPromptFromTemplate, resolveApiUrl, resolveAuthTokenForApiUrl, resolveHarnessTemplate, resolveJobPresentation, resolvePromptAnswer, reviewGeneratedJobCode, scorePromptChoiceMatch, stripGranularReasoningTrace, toGranularHttpBase, validateHarnessTemplateManifest, validateProjectionResult, validationRuleFailureMessage };
|
|
23947
|
+
export { Environment, EnvironmentSession, GRANULAR_FEED_DIAGNOSTIC_EVENT, Granular, OPENAI_MODEL_PRICING_USD_PER_MILLION, OntologyHandle, Session, SessionFeedController, WSClient, buildContinuationInstruction, buildContinuationInstructionFromTemplate, buildGranularAgentCheckpointBlock, buildGranularAgentDomainBlock, buildGranularAgentFileBlock, buildGranularAgentHeapBlock, buildGranularAgentLoopBlock, buildGranularAgentManualActionBlock, buildGranularAgentManualActionMemorySummary, buildGranularAgentReferentBlock, buildGranularAgentRuntimeImportsBlock, buildGranularAgentSessionBlock, buildGranularAgentSystemPrompt, buildGranularAgentSystemPromptFromTemplate, buildGranularAgentToolBlock, buildGranularAgentWorkflowBlock, buildOpenAISpendEventId, buildSessionTranscript, buildSessionTranscriptFromFeedItems, calculateOpenAITokenSpend, canonicalizeCommitValue, changedRecordSnapshots, consumeGranularReasoningOnlyChunk, consumeGranularReasoningTraceChunk, createFeedPublisher, createHarnessVerifierSnapshot, defineEffect, defineProjection, defineStateMachine, emitFeedDiagnostic, emitFeedDiagnosticToDefaultSink, emptyFeedSnapshot, environmentSetupProgressFromError, environmentSetupProgressFromResponse, evaluateContinuation, evaluateValidationRule, extractPromptTokens, getCurrentClosureId, getDefaultHarnessTemplateId, getExclusivePromptTarget, getOpenAIModelPricing, hasCanonicalSessionFeedActivation, hasOpenPrompt, hashHarnessTemplateValue, invokeRegisteredEffect, isCanonicalSessionFeedDocument, isGraphQLMutationDocument, isLocalApiUrl, listHarnessTemplates, mergeFeedItemsBySequence, normalizeEffectBehaviors, normalizeFeedDiagnostic, normalizeFeedDiagnosticKind, normalizeFeedPage, normalizeOpenAIUsage, normalizePrompt, normalizePromptChoiceOption, normalizePromptText, normalizePromptType, orderTransientFeedItems, pollEnvironmentSetup, projectConversationReferentFocus, projectConversationReferentSummary, projectHeapSummary, projectLoopSummary, projectRecordSnapshotMutation, projectSessionFileSummary, projectWorkflowFocus, projectWorkflowSummary, readSessionFeedSnapshot, recordOpenAIUsageSpend, renderContinuationInstructionFromTemplate, renderGranularAgentSystemPromptFromTemplate, resolveApiUrl, resolveAuthTokenForApiUrl, resolveHarnessTemplate, resolveJobPresentation, resolvePromptAnswer, reviewGeneratedJobCode, scorePromptChoiceMatch, stripGranularReasoningTrace, toGranularHttpBase, validateHarnessTemplateManifest, validateProjectionResult, validationRuleFailureMessage };
|
|
23453
23948
|
//# sourceMappingURL=index.mjs.map
|
|
23454
23949
|
//# sourceMappingURL=index.mjs.map
|