@granular-software/sdk 0.4.66 → 0.4.67
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-B8Ahz5yo.d.mts → client-BT1DJddL.d.ts} +27 -9
- package/dist/{client-CTpRnXpT.d.ts → client-BkX2cb20.d.mts} +27 -9
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +280 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +280 -37
- package/dist/index.mjs.map +1 -1
- package/dist/{spend-x-lpt8n1.d.mts → spend-D4r0SA-H.d.mts} +3 -1
- package/dist/{spend-x-lpt8n1.d.ts → spend-D4r0SA-H.d.ts} +3 -1
- package/dist/spend.d.mts +1 -1
- package/dist/spend.d.ts +1 -1
- package/package.json +1 -1
package/dist/agent-evals.mjs
CHANGED
|
@@ -5256,7 +5256,6 @@ var DEFAULT_RPC_TIMEOUT_MS = 3e4;
|
|
|
5256
5256
|
var DOMAIN_PACKAGE_RPC_TIMEOUT_MS = 12e4;
|
|
5257
5257
|
var EFFECT_CONTROL_RPC_TIMEOUT_MS = 12e4;
|
|
5258
5258
|
var HARNESS_RUN_RPC_TIMEOUT_MS = 6e5;
|
|
5259
|
-
var HEARTBEAT_RPC_TIMEOUT_MS = 15e3;
|
|
5260
5259
|
var DEFAULT_CONNECT_TIMEOUT_MS = 1e4;
|
|
5261
5260
|
var DEFAULT_RECONNECT_DELAY_MS = 3e3;
|
|
5262
5261
|
var DEFAULT_MAX_RECONNECT_ATTEMPTS = 5;
|
|
@@ -5302,8 +5301,6 @@ function rpcTimeoutMsForMethod(method) {
|
|
|
5302
5301
|
case "domain.fetchPackagePart":
|
|
5303
5302
|
case "domain.getSummary":
|
|
5304
5303
|
return DOMAIN_PACKAGE_RPC_TIMEOUT_MS;
|
|
5305
|
-
case "client.heartbeat":
|
|
5306
|
-
return HEARTBEAT_RPC_TIMEOUT_MS;
|
|
5307
5304
|
case "effects.publishCatalog":
|
|
5308
5305
|
case "effects.resetCatalog":
|
|
5309
5306
|
case "effects.addCatalog":
|
|
@@ -5323,6 +5320,7 @@ var WSClient = class {
|
|
|
5323
5320
|
sessionId;
|
|
5324
5321
|
token;
|
|
5325
5322
|
messageQueue = [];
|
|
5323
|
+
pendingRpcPeriodStartedAt = null;
|
|
5326
5324
|
rpcHandlers = /* @__PURE__ */ new Map();
|
|
5327
5325
|
eventHandlers = /* @__PURE__ */ new Map();
|
|
5328
5326
|
canonicalDocumentQuarantineHandlers = /* @__PURE__ */ new Set();
|
|
@@ -5337,6 +5335,7 @@ var WSClient = class {
|
|
|
5337
5335
|
cancelConnectAttempt = null;
|
|
5338
5336
|
documentRepairRequired = false;
|
|
5339
5337
|
canonicalDocumentActivated = false;
|
|
5338
|
+
lastInboundActivityAt = null;
|
|
5340
5339
|
options;
|
|
5341
5340
|
constructor(options) {
|
|
5342
5341
|
this.options = options;
|
|
@@ -5350,6 +5349,29 @@ var WSClient = class {
|
|
|
5350
5349
|
get currentSessionId() {
|
|
5351
5350
|
return this.sessionId;
|
|
5352
5351
|
}
|
|
5352
|
+
isTransportOpen() {
|
|
5353
|
+
return this.ws?.readyState === READY_STATE_OPEN;
|
|
5354
|
+
}
|
|
5355
|
+
hasPendingRpcRequests() {
|
|
5356
|
+
return this.messageQueue.length > 0;
|
|
5357
|
+
}
|
|
5358
|
+
hasRecentlyPendingRpcPeriod(maxAgeMs, now = Date.now()) {
|
|
5359
|
+
return this.messageQueue.length > 0 && this.pendingRpcPeriodStartedAt !== null && now - this.pendingRpcPeriodStartedAt <= maxAgeMs;
|
|
5360
|
+
}
|
|
5361
|
+
removePendingRpc(id) {
|
|
5362
|
+
this.messageQueue = this.messageQueue.filter(
|
|
5363
|
+
(pending) => pending.id !== id
|
|
5364
|
+
);
|
|
5365
|
+
if (this.messageQueue.length === 0) this.pendingRpcPeriodStartedAt = null;
|
|
5366
|
+
}
|
|
5367
|
+
/**
|
|
5368
|
+
* Whether the current socket has delivered any frame recently. SessionDO
|
|
5369
|
+
* broadcasts a one-way heartbeat every five seconds, so this measures the
|
|
5370
|
+
* transport without adding an RPC that can be delayed by application work.
|
|
5371
|
+
*/
|
|
5372
|
+
hasRecentInboundActivity(maxAgeMs, now = Date.now()) {
|
|
5373
|
+
return this.ws?.readyState === READY_STATE_OPEN && this.lastInboundActivityAt !== null && now - this.lastInboundActivityAt <= maxAgeMs;
|
|
5374
|
+
}
|
|
5353
5375
|
seedDocumentSnapshot(document) {
|
|
5354
5376
|
if (!document || typeof document !== "object" || Array.isArray(document)) {
|
|
5355
5377
|
return;
|
|
@@ -5501,6 +5523,7 @@ var WSClient = class {
|
|
|
5501
5523
|
const socket = this.ws;
|
|
5502
5524
|
this.connectionEpoch += 1;
|
|
5503
5525
|
this.ws = null;
|
|
5526
|
+
this.lastInboundActivityAt = null;
|
|
5504
5527
|
try {
|
|
5505
5528
|
socket?.close(4001, "Transport failure");
|
|
5506
5529
|
} catch {
|
|
@@ -5583,12 +5606,14 @@ var WSClient = class {
|
|
|
5583
5606
|
closeStaleSocket();
|
|
5584
5607
|
return;
|
|
5585
5608
|
}
|
|
5609
|
+
this.lastInboundActivityAt = Date.now();
|
|
5586
5610
|
this.reconnectAttempts = 0;
|
|
5587
5611
|
this.emit("open", {});
|
|
5588
5612
|
finish();
|
|
5589
5613
|
};
|
|
5590
5614
|
const handleMessage = (data) => {
|
|
5591
5615
|
if (!isCurrent()) return;
|
|
5616
|
+
this.lastInboundActivityAt = Date.now();
|
|
5592
5617
|
try {
|
|
5593
5618
|
const text = typeof data === "string" ? data : data && typeof data === "object" && "toString" in data ? String(data.toString()) : "";
|
|
5594
5619
|
this.handleMessage(JSON.parse(text));
|
|
@@ -5623,9 +5648,7 @@ var WSClient = class {
|
|
|
5623
5648
|
this.ws = null;
|
|
5624
5649
|
closeStaleSocket();
|
|
5625
5650
|
finish(
|
|
5626
|
-
new Error(
|
|
5627
|
-
`WebSocket connect timed out after ${connectTimeoutMs}ms`
|
|
5628
|
-
)
|
|
5651
|
+
new Error(`WebSocket connect timed out after ${connectTimeoutMs}ms`)
|
|
5629
5652
|
);
|
|
5630
5653
|
}, connectTimeoutMs);
|
|
5631
5654
|
signal?.addEventListener("abort", handleAbort, { once: true });
|
|
@@ -5665,6 +5688,7 @@ var WSClient = class {
|
|
|
5665
5688
|
pending.reject(error);
|
|
5666
5689
|
});
|
|
5667
5690
|
this.messageQueue = [];
|
|
5691
|
+
this.pendingRpcPeriodStartedAt = null;
|
|
5668
5692
|
}
|
|
5669
5693
|
emitReconnectErrorMessage(error, terminal = false) {
|
|
5670
5694
|
const reconnectInfo = {
|
|
@@ -6068,9 +6092,7 @@ var WSClient = class {
|
|
|
6068
6092
|
} else {
|
|
6069
6093
|
pending.resolve(response.result);
|
|
6070
6094
|
}
|
|
6071
|
-
this.
|
|
6072
|
-
(q) => q.id !== response.id
|
|
6073
|
-
);
|
|
6095
|
+
this.removePendingRpc(response.id);
|
|
6074
6096
|
}
|
|
6075
6097
|
return;
|
|
6076
6098
|
}
|
|
@@ -6108,16 +6130,24 @@ var WSClient = class {
|
|
|
6108
6130
|
const timeout = setTimeout(() => {
|
|
6109
6131
|
const pending = this.messageQueue.find((q) => q.id === id);
|
|
6110
6132
|
if (pending) {
|
|
6111
|
-
this.
|
|
6133
|
+
this.removePendingRpc(id);
|
|
6112
6134
|
reject(new Error(`RPC timeout: ${method}`));
|
|
6113
6135
|
}
|
|
6114
6136
|
}, timeoutMs);
|
|
6115
|
-
this.messageQueue.
|
|
6137
|
+
if (this.messageQueue.length === 0) {
|
|
6138
|
+
this.pendingRpcPeriodStartedAt = Date.now();
|
|
6139
|
+
}
|
|
6140
|
+
this.messageQueue.push({
|
|
6141
|
+
resolve,
|
|
6142
|
+
reject,
|
|
6143
|
+
id,
|
|
6144
|
+
timeout
|
|
6145
|
+
});
|
|
6116
6146
|
try {
|
|
6117
6147
|
this.ws.send(JSON.stringify(request));
|
|
6118
6148
|
} catch (error) {
|
|
6119
6149
|
clearTimeout(timeout);
|
|
6120
|
-
this.
|
|
6150
|
+
this.removePendingRpc(id);
|
|
6121
6151
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
6122
6152
|
}
|
|
6123
6153
|
});
|
|
@@ -6222,6 +6252,7 @@ var WSClient = class {
|
|
|
6222
6252
|
this.cancelConnectAttempt?.();
|
|
6223
6253
|
this.cancelConnectAttempt = null;
|
|
6224
6254
|
this.connectionEpoch += 1;
|
|
6255
|
+
this.lastInboundActivityAt = null;
|
|
6225
6256
|
if (this.reconnectTimer) {
|
|
6226
6257
|
clearTimeout(this.reconnectTimer);
|
|
6227
6258
|
this.reconnectTimer = null;
|
|
@@ -12638,6 +12669,7 @@ function mergeClassSummaryPatch(target, patch) {
|
|
|
12638
12669
|
function mergePropertySummaryPatch(target, patch) {
|
|
12639
12670
|
pushUnique(target.notes, patch.notes || []);
|
|
12640
12671
|
if (patch.searchable !== void 0) target.searchable = patch.searchable;
|
|
12672
|
+
if (patch.format !== void 0) target.format = patch.format;
|
|
12641
12673
|
if (patch.searchablePhonetic !== void 0) {
|
|
12642
12674
|
target.searchablePhonetic = patch.searchablePhonetic;
|
|
12643
12675
|
}
|
|
@@ -15474,6 +15506,91 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15474
15506
|
}
|
|
15475
15507
|
});
|
|
15476
15508
|
|
|
15509
|
+
// ../metamodel-temporal/src/index.ts
|
|
15510
|
+
function normalizeTemporalFormat(format) {
|
|
15511
|
+
return format === "date" || format === "date-time" ? format : null;
|
|
15512
|
+
}
|
|
15513
|
+
function buildTemporalFieldMutations(fieldPath, format) {
|
|
15514
|
+
const normalized = normalizeTemporalFormat(format);
|
|
15515
|
+
if (!normalized) return [];
|
|
15516
|
+
return [
|
|
15517
|
+
{
|
|
15518
|
+
label: `set temporal format on ${fieldPath}`,
|
|
15519
|
+
query: `mutation { at(path: ${JSON.stringify(fieldPath)}) { set_temporal_format(format: ${JSON.stringify(normalized)}) { format } } }`
|
|
15520
|
+
}
|
|
15521
|
+
];
|
|
15522
|
+
}
|
|
15523
|
+
var temporalMetamodelPackage = defineMetamodelPackage({
|
|
15524
|
+
id: "temporal",
|
|
15525
|
+
docs: {
|
|
15526
|
+
fieldRows: [
|
|
15527
|
+
{
|
|
15528
|
+
key: "format",
|
|
15529
|
+
description: "Temporal representation for date fields. Use `date` for a civil calendar date and `date-time` when the instant and time matter."
|
|
15530
|
+
}
|
|
15531
|
+
]
|
|
15532
|
+
},
|
|
15533
|
+
graphql: {
|
|
15534
|
+
typeDefs: [
|
|
15535
|
+
`
|
|
15536
|
+
type TemporalFormatMetamodel {
|
|
15537
|
+
model: Model!
|
|
15538
|
+
format: String!
|
|
15539
|
+
}
|
|
15540
|
+
|
|
15541
|
+
extend type Model {
|
|
15542
|
+
temporal_format: TemporalFormatMetamodel
|
|
15543
|
+
}
|
|
15544
|
+
|
|
15545
|
+
extend type ModelMutation {
|
|
15546
|
+
set_temporal_format(format: String!): TemporalFormatMetamodel
|
|
15547
|
+
}
|
|
15548
|
+
`
|
|
15549
|
+
],
|
|
15550
|
+
createResolvers({ run }) {
|
|
15551
|
+
return {
|
|
15552
|
+
TemporalFormatMetamodel: {
|
|
15553
|
+
model: (value) => value.model,
|
|
15554
|
+
format: (value) => value.format
|
|
15555
|
+
},
|
|
15556
|
+
Model: {
|
|
15557
|
+
temporal_format: async (ant) => await run(ant.temporal_format())
|
|
15558
|
+
},
|
|
15559
|
+
ModelMutation: {
|
|
15560
|
+
set_temporal_format: async (ant, { format }) => {
|
|
15561
|
+
if (format !== "date" && format !== "date-time") {
|
|
15562
|
+
throw new Error(`Unsupported temporal format: ${format}`);
|
|
15563
|
+
}
|
|
15564
|
+
return {
|
|
15565
|
+
model: await run(ant.set_temporal_format(format)),
|
|
15566
|
+
format
|
|
15567
|
+
};
|
|
15568
|
+
}
|
|
15569
|
+
}
|
|
15570
|
+
};
|
|
15571
|
+
}
|
|
15572
|
+
},
|
|
15573
|
+
manifest: {
|
|
15574
|
+
buildFieldMutations(fieldPath, spec) {
|
|
15575
|
+
return buildTemporalFieldMutations(fieldPath, spec.format);
|
|
15576
|
+
}
|
|
15577
|
+
},
|
|
15578
|
+
summary: {
|
|
15579
|
+
selections: {
|
|
15580
|
+
propertyFields: ["temporal_format { format }"]
|
|
15581
|
+
},
|
|
15582
|
+
readPropertySummary(rawProperty) {
|
|
15583
|
+
const format = rawProperty.temporal_format?.format;
|
|
15584
|
+
return format === "date" || format === "date-time" ? { format } : {};
|
|
15585
|
+
}
|
|
15586
|
+
},
|
|
15587
|
+
domain: {
|
|
15588
|
+
applyToPropertyIR(propertyIR, _propertySummary) {
|
|
15589
|
+
return propertyIR;
|
|
15590
|
+
}
|
|
15591
|
+
}
|
|
15592
|
+
});
|
|
15593
|
+
|
|
15477
15594
|
// ../metamodel-validation-rule/src/index.ts
|
|
15478
15595
|
function describeRule(rule) {
|
|
15479
15596
|
if (rule.message) return rule.message;
|
|
@@ -15645,6 +15762,7 @@ var DEFAULT_METAMODEL_PACKAGES = [
|
|
|
15645
15762
|
searchableMetamodelPackage,
|
|
15646
15763
|
validationRuleMetamodelPackage,
|
|
15647
15764
|
stateMachineMetamodelPackage,
|
|
15765
|
+
temporalMetamodelPackage,
|
|
15648
15766
|
effectBehaviorsMetamodelPackage,
|
|
15649
15767
|
policyMetamodelPackage
|
|
15650
15768
|
];
|
|
@@ -15967,16 +16085,100 @@ function normalizeEnvironmentData(environment) {
|
|
|
15967
16085
|
setup: normalizeEnvironmentSetupSummary(environment.setup)
|
|
15968
16086
|
};
|
|
15969
16087
|
}
|
|
16088
|
+
function isGraphQLMutationDocument(query) {
|
|
16089
|
+
if (typeof query !== "string") return false;
|
|
16090
|
+
const tokens = [];
|
|
16091
|
+
for (let index = 0; index < query.length; ) {
|
|
16092
|
+
const character = query[index];
|
|
16093
|
+
if (/[,\s\ufeff]/.test(character)) {
|
|
16094
|
+
index += 1;
|
|
16095
|
+
continue;
|
|
16096
|
+
}
|
|
16097
|
+
if (character === "#") {
|
|
16098
|
+
while (index < query.length && !/[\r\n]/.test(query[index])) index += 1;
|
|
16099
|
+
continue;
|
|
16100
|
+
}
|
|
16101
|
+
if (character === '"') {
|
|
16102
|
+
const block = query.startsWith('"""', index);
|
|
16103
|
+
let closed = false;
|
|
16104
|
+
index += block ? 3 : 1;
|
|
16105
|
+
while (index < query.length) {
|
|
16106
|
+
if (block && query.startsWith('"""', index) && query[index - 1] !== "\\") {
|
|
16107
|
+
index += 3;
|
|
16108
|
+
closed = true;
|
|
16109
|
+
break;
|
|
16110
|
+
}
|
|
16111
|
+
if (!block && query[index] === '"') {
|
|
16112
|
+
index += 1;
|
|
16113
|
+
closed = true;
|
|
16114
|
+
break;
|
|
16115
|
+
}
|
|
16116
|
+
index += query[index] === "\\" && !block ? 2 : 1;
|
|
16117
|
+
}
|
|
16118
|
+
if (!closed) return true;
|
|
16119
|
+
continue;
|
|
16120
|
+
}
|
|
16121
|
+
const name = query.slice(index).match(/^[_A-Za-z][_0-9A-Za-z]*/)?.[0];
|
|
16122
|
+
if (name) {
|
|
16123
|
+
tokens.push(name);
|
|
16124
|
+
index += name.length;
|
|
16125
|
+
continue;
|
|
16126
|
+
}
|
|
16127
|
+
if ("{}()[]".includes(character)) tokens.push(character);
|
|
16128
|
+
index += 1;
|
|
16129
|
+
}
|
|
16130
|
+
const skipSelection = (start) => {
|
|
16131
|
+
let depth = 0;
|
|
16132
|
+
for (let index = start; index < tokens.length; index += 1) {
|
|
16133
|
+
if (tokens[index] === "{") depth += 1;
|
|
16134
|
+
if (tokens[index] === "}" && --depth === 0) return index + 1;
|
|
16135
|
+
}
|
|
16136
|
+
return null;
|
|
16137
|
+
};
|
|
16138
|
+
for (let index = 0; index < tokens.length; ) {
|
|
16139
|
+
const definition = tokens[index++];
|
|
16140
|
+
if (definition === "mutation") return true;
|
|
16141
|
+
if (definition === "{") {
|
|
16142
|
+
const nextDefinition2 = skipSelection(index - 1);
|
|
16143
|
+
if (nextDefinition2 === null) return true;
|
|
16144
|
+
index = nextDefinition2;
|
|
16145
|
+
continue;
|
|
16146
|
+
}
|
|
16147
|
+
if (!["query", "subscription", "fragment"].includes(definition || "")) {
|
|
16148
|
+
return true;
|
|
16149
|
+
}
|
|
16150
|
+
let parentheses = 0;
|
|
16151
|
+
let brackets = 0;
|
|
16152
|
+
while (index < tokens.length) {
|
|
16153
|
+
const token = tokens[index];
|
|
16154
|
+
if (token === "(") parentheses += 1;
|
|
16155
|
+
else if (token === ")") parentheses -= 1;
|
|
16156
|
+
else if (token === "[") brackets += 1;
|
|
16157
|
+
else if (token === "]") brackets -= 1;
|
|
16158
|
+
else if (token === "{" && parentheses === 0 && brackets === 0) break;
|
|
16159
|
+
index += 1;
|
|
16160
|
+
}
|
|
16161
|
+
if (index === tokens.length) return true;
|
|
16162
|
+
const nextDefinition = skipSelection(index);
|
|
16163
|
+
if (nextDefinition === null) return true;
|
|
16164
|
+
index = nextDefinition;
|
|
16165
|
+
}
|
|
16166
|
+
return false;
|
|
16167
|
+
}
|
|
15970
16168
|
var Environment = class _Environment {
|
|
15971
16169
|
granular;
|
|
15972
16170
|
envData;
|
|
15973
16171
|
_apiKey;
|
|
15974
16172
|
_apiEndpoint;
|
|
15975
|
-
|
|
16173
|
+
_tokenProvider;
|
|
16174
|
+
_beforeMutationSend;
|
|
16175
|
+
constructor(granular, envData, apiKey, apiEndpoint, tokenProvider, beforeMutationSend) {
|
|
15976
16176
|
this.granular = granular;
|
|
15977
16177
|
this.envData = envData;
|
|
15978
16178
|
this._apiKey = apiKey;
|
|
15979
16179
|
this._apiEndpoint = apiEndpoint;
|
|
16180
|
+
this._tokenProvider = tokenProvider;
|
|
16181
|
+
this._beforeMutationSend = beforeMutationSend;
|
|
15980
16182
|
}
|
|
15981
16183
|
/** The environment ID */
|
|
15982
16184
|
get environmentId() {
|
|
@@ -16042,6 +16244,15 @@ var Environment = class _Environment {
|
|
|
16042
16244
|
get authToken() {
|
|
16043
16245
|
return this._apiKey;
|
|
16044
16246
|
}
|
|
16247
|
+
resolveAuthToken() {
|
|
16248
|
+
if (!this._tokenProvider) return this._apiKey;
|
|
16249
|
+
return Promise.resolve(this._tokenProvider()).then((provided) => {
|
|
16250
|
+
if (typeof provided === "string" && provided.trim()) {
|
|
16251
|
+
this._apiKey = provided.trim();
|
|
16252
|
+
}
|
|
16253
|
+
return this._apiKey;
|
|
16254
|
+
});
|
|
16255
|
+
}
|
|
16045
16256
|
/** Base runtime URL derived from the GraphQL endpoint */
|
|
16046
16257
|
get runtimeBaseUrl() {
|
|
16047
16258
|
return this.getRuntimeBaseUrl();
|
|
@@ -16433,10 +16644,15 @@ var Environment = class _Environment {
|
|
|
16433
16644
|
async controlPlaneRequest(path2, options = {}) {
|
|
16434
16645
|
const runtimeBase = this.getRuntimeBaseUrl();
|
|
16435
16646
|
const url = `${runtimeBase}${path2}`;
|
|
16647
|
+
const authToken = await this.resolveAuthToken();
|
|
16648
|
+
const method = (options.method || "GET").toUpperCase();
|
|
16649
|
+
if (method !== "GET" && method !== "HEAD" && method !== "OPTIONS") {
|
|
16650
|
+
this._beforeMutationSend?.();
|
|
16651
|
+
}
|
|
16436
16652
|
const response = await fetch(url, {
|
|
16437
16653
|
...options,
|
|
16438
16654
|
headers: {
|
|
16439
|
-
Authorization: `Bearer ${
|
|
16655
|
+
Authorization: `Bearer ${authToken}`,
|
|
16440
16656
|
"Content-Type": "application/json",
|
|
16441
16657
|
...options.headers
|
|
16442
16658
|
}
|
|
@@ -16501,11 +16717,15 @@ var Environment = class _Environment {
|
|
|
16501
16717
|
* ```
|
|
16502
16718
|
*/
|
|
16503
16719
|
async graphql(query, variables) {
|
|
16720
|
+
const authToken = await this.resolveAuthToken();
|
|
16721
|
+
if (this._beforeMutationSend && isGraphQLMutationDocument(query)) {
|
|
16722
|
+
this._beforeMutationSend?.();
|
|
16723
|
+
}
|
|
16504
16724
|
const response = await fetch(this._apiEndpoint, {
|
|
16505
16725
|
method: "POST",
|
|
16506
16726
|
headers: {
|
|
16507
16727
|
"Content-Type": "application/json",
|
|
16508
|
-
Authorization: `Bearer ${
|
|
16728
|
+
Authorization: `Bearer ${authToken}`
|
|
16509
16729
|
},
|
|
16510
16730
|
body: JSON.stringify({
|
|
16511
16731
|
environmentId: this.environmentId,
|
|
@@ -16984,8 +17204,10 @@ var Environment = class _Environment {
|
|
|
16984
17204
|
eventType.payloadSchema.properties
|
|
16985
17205
|
)) {
|
|
16986
17206
|
const schema = propSchema;
|
|
17207
|
+
const format = schema.format === "date" || schema.format === "date-time" ? schema.format : void 0;
|
|
16987
17208
|
fieldSpecs[propName] = {
|
|
16988
17209
|
type: schema.type ?? "string",
|
|
17210
|
+
...format ? { format } : {},
|
|
16989
17211
|
description: schema.description
|
|
16990
17212
|
};
|
|
16991
17213
|
}
|
|
@@ -17407,40 +17629,36 @@ var EnvironmentSession = class extends Session {
|
|
|
17407
17629
|
environment;
|
|
17408
17630
|
sessionDataRoutePrefix;
|
|
17409
17631
|
sessionDataHeaders;
|
|
17632
|
+
beforeMutationSend;
|
|
17410
17633
|
heartbeatTimer = null;
|
|
17411
|
-
|
|
17412
|
-
/** The last known graph container status, updated by checkReadiness() or on heartbeat */
|
|
17634
|
+
/** The last known graph container status, updated by checkReadiness(). */
|
|
17413
17635
|
graphContainerStatus = null;
|
|
17414
17636
|
constructor(client, environment, clientId, options = {}) {
|
|
17415
17637
|
super(client, clientId, { initialQuota: options.initialQuota });
|
|
17416
17638
|
this.environment = environment;
|
|
17417
17639
|
this.sessionDataRoutePrefix = options.sessionDataRoutePrefix || "/orchestrator/ws/sessions";
|
|
17418
17640
|
this.sessionDataHeaders = options.sessionDataHeaders || {};
|
|
17641
|
+
this.beforeMutationSend = options.beforeMutationSend;
|
|
17419
17642
|
this.setFeedListTransport(
|
|
17420
17643
|
(feedOptions) => this.sessionDataRequest("/feed", feedOptions)
|
|
17421
17644
|
);
|
|
17422
17645
|
}
|
|
17423
17646
|
/**
|
|
17424
17647
|
* Keep the browser session transport observable from the client side.
|
|
17425
|
-
*
|
|
17426
|
-
*
|
|
17427
|
-
*
|
|
17428
|
-
*
|
|
17648
|
+
* SessionDO already broadcasts a heartbeat every five seconds. Treat that
|
|
17649
|
+
* and all other inbound frames as proof of life instead of issuing an RPC:
|
|
17650
|
+
* an application RPC may be delayed by Durable Object work even while the
|
|
17651
|
+
* underlying WebSocket is healthy.
|
|
17429
17652
|
*/
|
|
17430
17653
|
startHeartbeat() {
|
|
17431
17654
|
if (this.heartbeatTimer) return;
|
|
17432
17655
|
this.heartbeatTimer = setInterval(() => {
|
|
17433
|
-
if (this.
|
|
17434
|
-
this.
|
|
17435
|
-
|
|
17436
|
-
|
|
17437
|
-
|
|
17438
|
-
|
|
17439
|
-
}).catch((error) => {
|
|
17440
|
-
this.client.reportTransportFailure(error);
|
|
17441
|
-
}).finally(() => {
|
|
17442
|
-
this.heartbeatInFlight = false;
|
|
17443
|
-
});
|
|
17656
|
+
if (!this.client.isTransportOpen()) return;
|
|
17657
|
+
if (this.client.hasRecentInboundActivity(3e4)) return;
|
|
17658
|
+
if (this.client.hasRecentlyPendingRpcPeriod(6e4)) return;
|
|
17659
|
+
this.client.reportTransportFailure(
|
|
17660
|
+
new Error("No server activity received for 30 seconds")
|
|
17661
|
+
);
|
|
17444
17662
|
}, 5e3);
|
|
17445
17663
|
this.heartbeatTimer.unref?.();
|
|
17446
17664
|
}
|
|
@@ -17449,7 +17667,6 @@ var EnvironmentSession = class extends Session {
|
|
|
17449
17667
|
clearInterval(this.heartbeatTimer);
|
|
17450
17668
|
this.heartbeatTimer = null;
|
|
17451
17669
|
}
|
|
17452
|
-
this.heartbeatInFlight = false;
|
|
17453
17670
|
}
|
|
17454
17671
|
async hello() {
|
|
17455
17672
|
const result = await super.hello();
|
|
@@ -17510,7 +17727,13 @@ var EnvironmentSession = class extends Session {
|
|
|
17510
17727
|
for (let attempt = 1; attempt <= SESSION_DATA_REQUEST_RETRY_COUNT; attempt += 1) {
|
|
17511
17728
|
try {
|
|
17512
17729
|
const headers = new Headers(init2.headers);
|
|
17513
|
-
|
|
17730
|
+
const resolvedAuthToken = this.environment.resolveAuthToken();
|
|
17731
|
+
const authToken = typeof resolvedAuthToken === "string" ? resolvedAuthToken : await resolvedAuthToken;
|
|
17732
|
+
headers.set("Authorization", `Bearer ${authToken}`);
|
|
17733
|
+
const method = (init2.method || "GET").toUpperCase();
|
|
17734
|
+
if (method !== "GET" && method !== "HEAD" && method !== "OPTIONS") {
|
|
17735
|
+
this.beforeMutationSend?.();
|
|
17736
|
+
}
|
|
17514
17737
|
const response = await fetch(url, {
|
|
17515
17738
|
method: init2.method || "GET",
|
|
17516
17739
|
headers,
|
|
@@ -17969,7 +18192,7 @@ var EnvironmentSession = class extends Session {
|
|
|
17969
18192
|
method: "POST",
|
|
17970
18193
|
headers: {
|
|
17971
18194
|
"Content-Type": "application/json",
|
|
17972
|
-
Authorization: `Bearer ${this.environment.
|
|
18195
|
+
Authorization: `Bearer ${await this.environment.resolveAuthToken()}`
|
|
17973
18196
|
},
|
|
17974
18197
|
body: JSON.stringify({
|
|
17975
18198
|
reason: "sdk_disconnect_http_fallback",
|
|
@@ -18907,6 +19130,10 @@ var Granular = class _Granular {
|
|
|
18907
19130
|
});
|
|
18908
19131
|
}
|
|
18909
19132
|
async recordOpenAIUsageSpend(usage, context, options) {
|
|
19133
|
+
const providedToken = await this.tokenProvider?.();
|
|
19134
|
+
if (typeof providedToken === "string" && providedToken.trim()) {
|
|
19135
|
+
this.apiKey = providedToken.trim();
|
|
19136
|
+
}
|
|
18910
19137
|
return recordOpenAIUsageSpend({
|
|
18911
19138
|
apiUrl: this.apiUrl,
|
|
18912
19139
|
token: this.apiKey,
|
|
@@ -19079,7 +19306,13 @@ var Granular = class _Granular {
|
|
|
19079
19306
|
}
|
|
19080
19307
|
bindEnvironmentHandle(envData) {
|
|
19081
19308
|
const graphqlEndpoint = `${this.httpUrl}/orchestrator/graphql`;
|
|
19082
|
-
return new Environment(
|
|
19309
|
+
return new Environment(
|
|
19310
|
+
this,
|
|
19311
|
+
envData,
|
|
19312
|
+
this.apiKey,
|
|
19313
|
+
graphqlEndpoint,
|
|
19314
|
+
this.tokenProvider
|
|
19315
|
+
);
|
|
19083
19316
|
}
|
|
19084
19317
|
async bindWebSocketEnvironmentSession(environment, clientId, session, transportOptions = {}) {
|
|
19085
19318
|
const client = new WSClient({
|
|
@@ -19963,6 +20196,10 @@ var Granular = class _Granular {
|
|
|
19963
20196
|
console.log(`[SDK] Requesting: ${url}`);
|
|
19964
20197
|
}
|
|
19965
20198
|
for (let attempt = 1; attempt <= LOCAL_CONTROL_REQUEST_RETRY_COUNT; attempt += 1) {
|
|
20199
|
+
const providedToken = await this.tokenProvider?.();
|
|
20200
|
+
if (typeof providedToken === "string" && providedToken.trim()) {
|
|
20201
|
+
this.apiKey = providedToken.trim();
|
|
20202
|
+
}
|
|
19966
20203
|
const response = await fetch(url, {
|
|
19967
20204
|
...options,
|
|
19968
20205
|
headers: {
|
|
@@ -21894,6 +22131,10 @@ function jsonSchemaTypeName(schema) {
|
|
|
21894
22131
|
const record = normalizeJsonSchema(schema);
|
|
21895
22132
|
if (!record) return "unknown";
|
|
21896
22133
|
const type = record.type;
|
|
22134
|
+
if (record.format === "date-time") return "date-time";
|
|
22135
|
+
if (record.format === "date" || type === "date" || Array.isArray(type) && type.includes("date")) {
|
|
22136
|
+
return "date";
|
|
22137
|
+
}
|
|
21897
22138
|
if (typeof type === "string") {
|
|
21898
22139
|
if (type === "array") return "array";
|
|
21899
22140
|
if (type === "object") return "object";
|
|
@@ -22395,6 +22636,8 @@ ${actionIndex}
|
|
|
22395
22636
|
- 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()\`.
|
|
22396
22637
|
- 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.
|
|
22397
22638
|
- 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.
|
|
22639
|
+
- 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.
|
|
22640
|
+
- 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.
|
|
22398
22641
|
- 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.
|
|
22399
22642
|
- 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.
|
|
22400
22643
|
- 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.
|