@granular-software/sdk 0.4.65 → 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 +282 -36
- package/dist/agent-evals.js.map +1 -1
- package/dist/agent-evals.mjs +282 -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 +277 -36
- package/dist/{client-S-z8bri1.d.mts → client-BT1DJddL.d.ts} +27 -9
- package/dist/{client-z6shQivt.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 +283 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +283 -37
- package/dist/index.mjs.map +1 -1
- package/dist/{spend-CESUvrZC.d.mts → spend-D4r0SA-H.d.mts} +9 -1
- package/dist/{spend-CESUvrZC.d.ts → spend-D4r0SA-H.d.ts} +9 -1
- package/dist/spend.d.mts +1 -1
- package/dist/spend.d.ts +1 -1
- package/package.json +1 -1
package/dist/agent-evals.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as EnvironmentSession, G as Granular } from './client-
|
|
2
|
-
import { aC as GranularSpendContext, ax as OpenAITokenSpend, l as Prompt, f as RecordObjectOptions, g as ManifestContent, k as SessionHeapSnapshot, T as ToolWithHandler, aY as ConnectOptions, bn as CreateEnvironmentData, aR as GranularOptions } from './spend-
|
|
1
|
+
import { a as EnvironmentSession, G as Granular } from './client-BkX2cb20.mjs';
|
|
2
|
+
import { aC as GranularSpendContext, ax as OpenAITokenSpend, l as Prompt, f as RecordObjectOptions, g as ManifestContent, k as SessionHeapSnapshot, T as ToolWithHandler, aY as ConnectOptions, bn as CreateEnvironmentData, aR as GranularOptions } from './spend-D4r0SA-H.mjs';
|
|
3
3
|
import { GranularAgentToolInfo, GeneratedJobCodeIssue, BuildGranularAgentSystemPromptInput, HarnessRenderedPrompt, HarnessRenderedContinuation, HarnessControllerBudgets } from './agent-harness.mjs';
|
|
4
4
|
import '@automerge/automerge';
|
|
5
5
|
import '@automerge/automerge/slim';
|
package/dist/agent-evals.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as EnvironmentSession, G as Granular } from './client-
|
|
2
|
-
import { aC as GranularSpendContext, ax as OpenAITokenSpend, l as Prompt, f as RecordObjectOptions, g as ManifestContent, k as SessionHeapSnapshot, T as ToolWithHandler, aY as ConnectOptions, bn as CreateEnvironmentData, aR as GranularOptions } from './spend-
|
|
1
|
+
import { a as EnvironmentSession, G as Granular } from './client-BT1DJddL.js';
|
|
2
|
+
import { aC as GranularSpendContext, ax as OpenAITokenSpend, l as Prompt, f as RecordObjectOptions, g as ManifestContent, k as SessionHeapSnapshot, T as ToolWithHandler, aY as ConnectOptions, bn as CreateEnvironmentData, aR as GranularOptions } from './spend-D4r0SA-H.js';
|
|
3
3
|
import { GranularAgentToolInfo, GeneratedJobCodeIssue, BuildGranularAgentSystemPromptInput, HarnessRenderedPrompt, HarnessRenderedContinuation, HarnessControllerBudgets } from './agent-harness.js';
|
|
4
4
|
import '@automerge/automerge';
|
|
5
5
|
import '@automerge/automerge/slim';
|
package/dist/agent-evals.js
CHANGED
|
@@ -5282,7 +5282,6 @@ var DEFAULT_RPC_TIMEOUT_MS = 3e4;
|
|
|
5282
5282
|
var DOMAIN_PACKAGE_RPC_TIMEOUT_MS = 12e4;
|
|
5283
5283
|
var EFFECT_CONTROL_RPC_TIMEOUT_MS = 12e4;
|
|
5284
5284
|
var HARNESS_RUN_RPC_TIMEOUT_MS = 6e5;
|
|
5285
|
-
var HEARTBEAT_RPC_TIMEOUT_MS = 15e3;
|
|
5286
5285
|
var DEFAULT_CONNECT_TIMEOUT_MS = 1e4;
|
|
5287
5286
|
var DEFAULT_RECONNECT_DELAY_MS = 3e3;
|
|
5288
5287
|
var DEFAULT_MAX_RECONNECT_ATTEMPTS = 5;
|
|
@@ -5328,8 +5327,6 @@ function rpcTimeoutMsForMethod(method) {
|
|
|
5328
5327
|
case "domain.fetchPackagePart":
|
|
5329
5328
|
case "domain.getSummary":
|
|
5330
5329
|
return DOMAIN_PACKAGE_RPC_TIMEOUT_MS;
|
|
5331
|
-
case "client.heartbeat":
|
|
5332
|
-
return HEARTBEAT_RPC_TIMEOUT_MS;
|
|
5333
5330
|
case "effects.publishCatalog":
|
|
5334
5331
|
case "effects.resetCatalog":
|
|
5335
5332
|
case "effects.addCatalog":
|
|
@@ -5349,6 +5346,7 @@ var WSClient = class {
|
|
|
5349
5346
|
sessionId;
|
|
5350
5347
|
token;
|
|
5351
5348
|
messageQueue = [];
|
|
5349
|
+
pendingRpcPeriodStartedAt = null;
|
|
5352
5350
|
rpcHandlers = /* @__PURE__ */ new Map();
|
|
5353
5351
|
eventHandlers = /* @__PURE__ */ new Map();
|
|
5354
5352
|
canonicalDocumentQuarantineHandlers = /* @__PURE__ */ new Set();
|
|
@@ -5363,6 +5361,7 @@ var WSClient = class {
|
|
|
5363
5361
|
cancelConnectAttempt = null;
|
|
5364
5362
|
documentRepairRequired = false;
|
|
5365
5363
|
canonicalDocumentActivated = false;
|
|
5364
|
+
lastInboundActivityAt = null;
|
|
5366
5365
|
options;
|
|
5367
5366
|
constructor(options) {
|
|
5368
5367
|
this.options = options;
|
|
@@ -5376,6 +5375,29 @@ var WSClient = class {
|
|
|
5376
5375
|
get currentSessionId() {
|
|
5377
5376
|
return this.sessionId;
|
|
5378
5377
|
}
|
|
5378
|
+
isTransportOpen() {
|
|
5379
|
+
return this.ws?.readyState === READY_STATE_OPEN;
|
|
5380
|
+
}
|
|
5381
|
+
hasPendingRpcRequests() {
|
|
5382
|
+
return this.messageQueue.length > 0;
|
|
5383
|
+
}
|
|
5384
|
+
hasRecentlyPendingRpcPeriod(maxAgeMs, now = Date.now()) {
|
|
5385
|
+
return this.messageQueue.length > 0 && this.pendingRpcPeriodStartedAt !== null && now - this.pendingRpcPeriodStartedAt <= maxAgeMs;
|
|
5386
|
+
}
|
|
5387
|
+
removePendingRpc(id) {
|
|
5388
|
+
this.messageQueue = this.messageQueue.filter(
|
|
5389
|
+
(pending) => pending.id !== id
|
|
5390
|
+
);
|
|
5391
|
+
if (this.messageQueue.length === 0) this.pendingRpcPeriodStartedAt = null;
|
|
5392
|
+
}
|
|
5393
|
+
/**
|
|
5394
|
+
* Whether the current socket has delivered any frame recently. SessionDO
|
|
5395
|
+
* broadcasts a one-way heartbeat every five seconds, so this measures the
|
|
5396
|
+
* transport without adding an RPC that can be delayed by application work.
|
|
5397
|
+
*/
|
|
5398
|
+
hasRecentInboundActivity(maxAgeMs, now = Date.now()) {
|
|
5399
|
+
return this.ws?.readyState === READY_STATE_OPEN && this.lastInboundActivityAt !== null && now - this.lastInboundActivityAt <= maxAgeMs;
|
|
5400
|
+
}
|
|
5379
5401
|
seedDocumentSnapshot(document) {
|
|
5380
5402
|
if (!document || typeof document !== "object" || Array.isArray(document)) {
|
|
5381
5403
|
return;
|
|
@@ -5527,6 +5549,7 @@ var WSClient = class {
|
|
|
5527
5549
|
const socket = this.ws;
|
|
5528
5550
|
this.connectionEpoch += 1;
|
|
5529
5551
|
this.ws = null;
|
|
5552
|
+
this.lastInboundActivityAt = null;
|
|
5530
5553
|
try {
|
|
5531
5554
|
socket?.close(4001, "Transport failure");
|
|
5532
5555
|
} catch {
|
|
@@ -5609,12 +5632,14 @@ var WSClient = class {
|
|
|
5609
5632
|
closeStaleSocket();
|
|
5610
5633
|
return;
|
|
5611
5634
|
}
|
|
5635
|
+
this.lastInboundActivityAt = Date.now();
|
|
5612
5636
|
this.reconnectAttempts = 0;
|
|
5613
5637
|
this.emit("open", {});
|
|
5614
5638
|
finish();
|
|
5615
5639
|
};
|
|
5616
5640
|
const handleMessage = (data) => {
|
|
5617
5641
|
if (!isCurrent()) return;
|
|
5642
|
+
this.lastInboundActivityAt = Date.now();
|
|
5618
5643
|
try {
|
|
5619
5644
|
const text = typeof data === "string" ? data : data && typeof data === "object" && "toString" in data ? String(data.toString()) : "";
|
|
5620
5645
|
this.handleMessage(JSON.parse(text));
|
|
@@ -5649,9 +5674,7 @@ var WSClient = class {
|
|
|
5649
5674
|
this.ws = null;
|
|
5650
5675
|
closeStaleSocket();
|
|
5651
5676
|
finish(
|
|
5652
|
-
new Error(
|
|
5653
|
-
`WebSocket connect timed out after ${connectTimeoutMs}ms`
|
|
5654
|
-
)
|
|
5677
|
+
new Error(`WebSocket connect timed out after ${connectTimeoutMs}ms`)
|
|
5655
5678
|
);
|
|
5656
5679
|
}, connectTimeoutMs);
|
|
5657
5680
|
signal?.addEventListener("abort", handleAbort, { once: true });
|
|
@@ -5691,6 +5714,7 @@ var WSClient = class {
|
|
|
5691
5714
|
pending.reject(error);
|
|
5692
5715
|
});
|
|
5693
5716
|
this.messageQueue = [];
|
|
5717
|
+
this.pendingRpcPeriodStartedAt = null;
|
|
5694
5718
|
}
|
|
5695
5719
|
emitReconnectErrorMessage(error, terminal = false) {
|
|
5696
5720
|
const reconnectInfo = {
|
|
@@ -6094,9 +6118,7 @@ var WSClient = class {
|
|
|
6094
6118
|
} else {
|
|
6095
6119
|
pending.resolve(response.result);
|
|
6096
6120
|
}
|
|
6097
|
-
this.
|
|
6098
|
-
(q) => q.id !== response.id
|
|
6099
|
-
);
|
|
6121
|
+
this.removePendingRpc(response.id);
|
|
6100
6122
|
}
|
|
6101
6123
|
return;
|
|
6102
6124
|
}
|
|
@@ -6134,16 +6156,24 @@ var WSClient = class {
|
|
|
6134
6156
|
const timeout = setTimeout(() => {
|
|
6135
6157
|
const pending = this.messageQueue.find((q) => q.id === id);
|
|
6136
6158
|
if (pending) {
|
|
6137
|
-
this.
|
|
6159
|
+
this.removePendingRpc(id);
|
|
6138
6160
|
reject(new Error(`RPC timeout: ${method}`));
|
|
6139
6161
|
}
|
|
6140
6162
|
}, timeoutMs);
|
|
6141
|
-
this.messageQueue.
|
|
6163
|
+
if (this.messageQueue.length === 0) {
|
|
6164
|
+
this.pendingRpcPeriodStartedAt = Date.now();
|
|
6165
|
+
}
|
|
6166
|
+
this.messageQueue.push({
|
|
6167
|
+
resolve,
|
|
6168
|
+
reject,
|
|
6169
|
+
id,
|
|
6170
|
+
timeout
|
|
6171
|
+
});
|
|
6142
6172
|
try {
|
|
6143
6173
|
this.ws.send(JSON.stringify(request));
|
|
6144
6174
|
} catch (error) {
|
|
6145
6175
|
clearTimeout(timeout);
|
|
6146
|
-
this.
|
|
6176
|
+
this.removePendingRpc(id);
|
|
6147
6177
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
6148
6178
|
}
|
|
6149
6179
|
});
|
|
@@ -6248,6 +6278,7 @@ var WSClient = class {
|
|
|
6248
6278
|
this.cancelConnectAttempt?.();
|
|
6249
6279
|
this.cancelConnectAttempt = null;
|
|
6250
6280
|
this.connectionEpoch += 1;
|
|
6281
|
+
this.lastInboundActivityAt = null;
|
|
6251
6282
|
if (this.reconnectTimer) {
|
|
6252
6283
|
clearTimeout(this.reconnectTimer);
|
|
6253
6284
|
this.reconnectTimer = null;
|
|
@@ -12664,6 +12695,7 @@ function mergeClassSummaryPatch(target, patch) {
|
|
|
12664
12695
|
function mergePropertySummaryPatch(target, patch) {
|
|
12665
12696
|
pushUnique(target.notes, patch.notes || []);
|
|
12666
12697
|
if (patch.searchable !== void 0) target.searchable = patch.searchable;
|
|
12698
|
+
if (patch.format !== void 0) target.format = patch.format;
|
|
12667
12699
|
if (patch.searchablePhonetic !== void 0) {
|
|
12668
12700
|
target.searchablePhonetic = patch.searchablePhonetic;
|
|
12669
12701
|
}
|
|
@@ -15500,6 +15532,91 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15500
15532
|
}
|
|
15501
15533
|
});
|
|
15502
15534
|
|
|
15535
|
+
// ../metamodel-temporal/src/index.ts
|
|
15536
|
+
function normalizeTemporalFormat(format) {
|
|
15537
|
+
return format === "date" || format === "date-time" ? format : null;
|
|
15538
|
+
}
|
|
15539
|
+
function buildTemporalFieldMutations(fieldPath, format) {
|
|
15540
|
+
const normalized = normalizeTemporalFormat(format);
|
|
15541
|
+
if (!normalized) return [];
|
|
15542
|
+
return [
|
|
15543
|
+
{
|
|
15544
|
+
label: `set temporal format on ${fieldPath}`,
|
|
15545
|
+
query: `mutation { at(path: ${JSON.stringify(fieldPath)}) { set_temporal_format(format: ${JSON.stringify(normalized)}) { format } } }`
|
|
15546
|
+
}
|
|
15547
|
+
];
|
|
15548
|
+
}
|
|
15549
|
+
var temporalMetamodelPackage = defineMetamodelPackage({
|
|
15550
|
+
id: "temporal",
|
|
15551
|
+
docs: {
|
|
15552
|
+
fieldRows: [
|
|
15553
|
+
{
|
|
15554
|
+
key: "format",
|
|
15555
|
+
description: "Temporal representation for date fields. Use `date` for a civil calendar date and `date-time` when the instant and time matter."
|
|
15556
|
+
}
|
|
15557
|
+
]
|
|
15558
|
+
},
|
|
15559
|
+
graphql: {
|
|
15560
|
+
typeDefs: [
|
|
15561
|
+
`
|
|
15562
|
+
type TemporalFormatMetamodel {
|
|
15563
|
+
model: Model!
|
|
15564
|
+
format: String!
|
|
15565
|
+
}
|
|
15566
|
+
|
|
15567
|
+
extend type Model {
|
|
15568
|
+
temporal_format: TemporalFormatMetamodel
|
|
15569
|
+
}
|
|
15570
|
+
|
|
15571
|
+
extend type ModelMutation {
|
|
15572
|
+
set_temporal_format(format: String!): TemporalFormatMetamodel
|
|
15573
|
+
}
|
|
15574
|
+
`
|
|
15575
|
+
],
|
|
15576
|
+
createResolvers({ run }) {
|
|
15577
|
+
return {
|
|
15578
|
+
TemporalFormatMetamodel: {
|
|
15579
|
+
model: (value) => value.model,
|
|
15580
|
+
format: (value) => value.format
|
|
15581
|
+
},
|
|
15582
|
+
Model: {
|
|
15583
|
+
temporal_format: async (ant) => await run(ant.temporal_format())
|
|
15584
|
+
},
|
|
15585
|
+
ModelMutation: {
|
|
15586
|
+
set_temporal_format: async (ant, { format }) => {
|
|
15587
|
+
if (format !== "date" && format !== "date-time") {
|
|
15588
|
+
throw new Error(`Unsupported temporal format: ${format}`);
|
|
15589
|
+
}
|
|
15590
|
+
return {
|
|
15591
|
+
model: await run(ant.set_temporal_format(format)),
|
|
15592
|
+
format
|
|
15593
|
+
};
|
|
15594
|
+
}
|
|
15595
|
+
}
|
|
15596
|
+
};
|
|
15597
|
+
}
|
|
15598
|
+
},
|
|
15599
|
+
manifest: {
|
|
15600
|
+
buildFieldMutations(fieldPath, spec) {
|
|
15601
|
+
return buildTemporalFieldMutations(fieldPath, spec.format);
|
|
15602
|
+
}
|
|
15603
|
+
},
|
|
15604
|
+
summary: {
|
|
15605
|
+
selections: {
|
|
15606
|
+
propertyFields: ["temporal_format { format }"]
|
|
15607
|
+
},
|
|
15608
|
+
readPropertySummary(rawProperty) {
|
|
15609
|
+
const format = rawProperty.temporal_format?.format;
|
|
15610
|
+
return format === "date" || format === "date-time" ? { format } : {};
|
|
15611
|
+
}
|
|
15612
|
+
},
|
|
15613
|
+
domain: {
|
|
15614
|
+
applyToPropertyIR(propertyIR, _propertySummary) {
|
|
15615
|
+
return propertyIR;
|
|
15616
|
+
}
|
|
15617
|
+
}
|
|
15618
|
+
});
|
|
15619
|
+
|
|
15503
15620
|
// ../metamodel-validation-rule/src/index.ts
|
|
15504
15621
|
function describeRule(rule) {
|
|
15505
15622
|
if (rule.message) return rule.message;
|
|
@@ -15671,6 +15788,7 @@ var DEFAULT_METAMODEL_PACKAGES = [
|
|
|
15671
15788
|
searchableMetamodelPackage,
|
|
15672
15789
|
validationRuleMetamodelPackage,
|
|
15673
15790
|
stateMachineMetamodelPackage,
|
|
15791
|
+
temporalMetamodelPackage,
|
|
15674
15792
|
effectBehaviorsMetamodelPackage,
|
|
15675
15793
|
policyMetamodelPackage
|
|
15676
15794
|
];
|
|
@@ -15993,16 +16111,100 @@ function normalizeEnvironmentData(environment) {
|
|
|
15993
16111
|
setup: normalizeEnvironmentSetupSummary(environment.setup)
|
|
15994
16112
|
};
|
|
15995
16113
|
}
|
|
16114
|
+
function isGraphQLMutationDocument(query) {
|
|
16115
|
+
if (typeof query !== "string") return false;
|
|
16116
|
+
const tokens = [];
|
|
16117
|
+
for (let index = 0; index < query.length; ) {
|
|
16118
|
+
const character = query[index];
|
|
16119
|
+
if (/[,\s\ufeff]/.test(character)) {
|
|
16120
|
+
index += 1;
|
|
16121
|
+
continue;
|
|
16122
|
+
}
|
|
16123
|
+
if (character === "#") {
|
|
16124
|
+
while (index < query.length && !/[\r\n]/.test(query[index])) index += 1;
|
|
16125
|
+
continue;
|
|
16126
|
+
}
|
|
16127
|
+
if (character === '"') {
|
|
16128
|
+
const block = query.startsWith('"""', index);
|
|
16129
|
+
let closed = false;
|
|
16130
|
+
index += block ? 3 : 1;
|
|
16131
|
+
while (index < query.length) {
|
|
16132
|
+
if (block && query.startsWith('"""', index) && query[index - 1] !== "\\") {
|
|
16133
|
+
index += 3;
|
|
16134
|
+
closed = true;
|
|
16135
|
+
break;
|
|
16136
|
+
}
|
|
16137
|
+
if (!block && query[index] === '"') {
|
|
16138
|
+
index += 1;
|
|
16139
|
+
closed = true;
|
|
16140
|
+
break;
|
|
16141
|
+
}
|
|
16142
|
+
index += query[index] === "\\" && !block ? 2 : 1;
|
|
16143
|
+
}
|
|
16144
|
+
if (!closed) return true;
|
|
16145
|
+
continue;
|
|
16146
|
+
}
|
|
16147
|
+
const name = query.slice(index).match(/^[_A-Za-z][_0-9A-Za-z]*/)?.[0];
|
|
16148
|
+
if (name) {
|
|
16149
|
+
tokens.push(name);
|
|
16150
|
+
index += name.length;
|
|
16151
|
+
continue;
|
|
16152
|
+
}
|
|
16153
|
+
if ("{}()[]".includes(character)) tokens.push(character);
|
|
16154
|
+
index += 1;
|
|
16155
|
+
}
|
|
16156
|
+
const skipSelection = (start) => {
|
|
16157
|
+
let depth = 0;
|
|
16158
|
+
for (let index = start; index < tokens.length; index += 1) {
|
|
16159
|
+
if (tokens[index] === "{") depth += 1;
|
|
16160
|
+
if (tokens[index] === "}" && --depth === 0) return index + 1;
|
|
16161
|
+
}
|
|
16162
|
+
return null;
|
|
16163
|
+
};
|
|
16164
|
+
for (let index = 0; index < tokens.length; ) {
|
|
16165
|
+
const definition = tokens[index++];
|
|
16166
|
+
if (definition === "mutation") return true;
|
|
16167
|
+
if (definition === "{") {
|
|
16168
|
+
const nextDefinition2 = skipSelection(index - 1);
|
|
16169
|
+
if (nextDefinition2 === null) return true;
|
|
16170
|
+
index = nextDefinition2;
|
|
16171
|
+
continue;
|
|
16172
|
+
}
|
|
16173
|
+
if (!["query", "subscription", "fragment"].includes(definition || "")) {
|
|
16174
|
+
return true;
|
|
16175
|
+
}
|
|
16176
|
+
let parentheses = 0;
|
|
16177
|
+
let brackets = 0;
|
|
16178
|
+
while (index < tokens.length) {
|
|
16179
|
+
const token = tokens[index];
|
|
16180
|
+
if (token === "(") parentheses += 1;
|
|
16181
|
+
else if (token === ")") parentheses -= 1;
|
|
16182
|
+
else if (token === "[") brackets += 1;
|
|
16183
|
+
else if (token === "]") brackets -= 1;
|
|
16184
|
+
else if (token === "{" && parentheses === 0 && brackets === 0) break;
|
|
16185
|
+
index += 1;
|
|
16186
|
+
}
|
|
16187
|
+
if (index === tokens.length) return true;
|
|
16188
|
+
const nextDefinition = skipSelection(index);
|
|
16189
|
+
if (nextDefinition === null) return true;
|
|
16190
|
+
index = nextDefinition;
|
|
16191
|
+
}
|
|
16192
|
+
return false;
|
|
16193
|
+
}
|
|
15996
16194
|
var Environment = class _Environment {
|
|
15997
16195
|
granular;
|
|
15998
16196
|
envData;
|
|
15999
16197
|
_apiKey;
|
|
16000
16198
|
_apiEndpoint;
|
|
16001
|
-
|
|
16199
|
+
_tokenProvider;
|
|
16200
|
+
_beforeMutationSend;
|
|
16201
|
+
constructor(granular, envData, apiKey, apiEndpoint, tokenProvider, beforeMutationSend) {
|
|
16002
16202
|
this.granular = granular;
|
|
16003
16203
|
this.envData = envData;
|
|
16004
16204
|
this._apiKey = apiKey;
|
|
16005
16205
|
this._apiEndpoint = apiEndpoint;
|
|
16206
|
+
this._tokenProvider = tokenProvider;
|
|
16207
|
+
this._beforeMutationSend = beforeMutationSend;
|
|
16006
16208
|
}
|
|
16007
16209
|
/** The environment ID */
|
|
16008
16210
|
get environmentId() {
|
|
@@ -16068,6 +16270,15 @@ var Environment = class _Environment {
|
|
|
16068
16270
|
get authToken() {
|
|
16069
16271
|
return this._apiKey;
|
|
16070
16272
|
}
|
|
16273
|
+
resolveAuthToken() {
|
|
16274
|
+
if (!this._tokenProvider) return this._apiKey;
|
|
16275
|
+
return Promise.resolve(this._tokenProvider()).then((provided) => {
|
|
16276
|
+
if (typeof provided === "string" && provided.trim()) {
|
|
16277
|
+
this._apiKey = provided.trim();
|
|
16278
|
+
}
|
|
16279
|
+
return this._apiKey;
|
|
16280
|
+
});
|
|
16281
|
+
}
|
|
16071
16282
|
/** Base runtime URL derived from the GraphQL endpoint */
|
|
16072
16283
|
get runtimeBaseUrl() {
|
|
16073
16284
|
return this.getRuntimeBaseUrl();
|
|
@@ -16459,10 +16670,15 @@ var Environment = class _Environment {
|
|
|
16459
16670
|
async controlPlaneRequest(path2, options = {}) {
|
|
16460
16671
|
const runtimeBase = this.getRuntimeBaseUrl();
|
|
16461
16672
|
const url = `${runtimeBase}${path2}`;
|
|
16673
|
+
const authToken = await this.resolveAuthToken();
|
|
16674
|
+
const method = (options.method || "GET").toUpperCase();
|
|
16675
|
+
if (method !== "GET" && method !== "HEAD" && method !== "OPTIONS") {
|
|
16676
|
+
this._beforeMutationSend?.();
|
|
16677
|
+
}
|
|
16462
16678
|
const response = await fetch(url, {
|
|
16463
16679
|
...options,
|
|
16464
16680
|
headers: {
|
|
16465
|
-
Authorization: `Bearer ${
|
|
16681
|
+
Authorization: `Bearer ${authToken}`,
|
|
16466
16682
|
"Content-Type": "application/json",
|
|
16467
16683
|
...options.headers
|
|
16468
16684
|
}
|
|
@@ -16527,11 +16743,15 @@ var Environment = class _Environment {
|
|
|
16527
16743
|
* ```
|
|
16528
16744
|
*/
|
|
16529
16745
|
async graphql(query, variables) {
|
|
16746
|
+
const authToken = await this.resolveAuthToken();
|
|
16747
|
+
if (this._beforeMutationSend && isGraphQLMutationDocument(query)) {
|
|
16748
|
+
this._beforeMutationSend?.();
|
|
16749
|
+
}
|
|
16530
16750
|
const response = await fetch(this._apiEndpoint, {
|
|
16531
16751
|
method: "POST",
|
|
16532
16752
|
headers: {
|
|
16533
16753
|
"Content-Type": "application/json",
|
|
16534
|
-
Authorization: `Bearer ${
|
|
16754
|
+
Authorization: `Bearer ${authToken}`
|
|
16535
16755
|
},
|
|
16536
16756
|
body: JSON.stringify({
|
|
16537
16757
|
environmentId: this.environmentId,
|
|
@@ -17010,8 +17230,10 @@ var Environment = class _Environment {
|
|
|
17010
17230
|
eventType.payloadSchema.properties
|
|
17011
17231
|
)) {
|
|
17012
17232
|
const schema = propSchema;
|
|
17233
|
+
const format = schema.format === "date" || schema.format === "date-time" ? schema.format : void 0;
|
|
17013
17234
|
fieldSpecs[propName] = {
|
|
17014
17235
|
type: schema.type ?? "string",
|
|
17236
|
+
...format ? { format } : {},
|
|
17015
17237
|
description: schema.description
|
|
17016
17238
|
};
|
|
17017
17239
|
}
|
|
@@ -17433,40 +17655,36 @@ var EnvironmentSession = class extends Session {
|
|
|
17433
17655
|
environment;
|
|
17434
17656
|
sessionDataRoutePrefix;
|
|
17435
17657
|
sessionDataHeaders;
|
|
17658
|
+
beforeMutationSend;
|
|
17436
17659
|
heartbeatTimer = null;
|
|
17437
|
-
|
|
17438
|
-
/** The last known graph container status, updated by checkReadiness() or on heartbeat */
|
|
17660
|
+
/** The last known graph container status, updated by checkReadiness(). */
|
|
17439
17661
|
graphContainerStatus = null;
|
|
17440
17662
|
constructor(client, environment, clientId, options = {}) {
|
|
17441
17663
|
super(client, clientId, { initialQuota: options.initialQuota });
|
|
17442
17664
|
this.environment = environment;
|
|
17443
17665
|
this.sessionDataRoutePrefix = options.sessionDataRoutePrefix || "/orchestrator/ws/sessions";
|
|
17444
17666
|
this.sessionDataHeaders = options.sessionDataHeaders || {};
|
|
17667
|
+
this.beforeMutationSend = options.beforeMutationSend;
|
|
17445
17668
|
this.setFeedListTransport(
|
|
17446
17669
|
(feedOptions) => this.sessionDataRequest("/feed", feedOptions)
|
|
17447
17670
|
);
|
|
17448
17671
|
}
|
|
17449
17672
|
/**
|
|
17450
17673
|
* Keep the browser session transport observable from the client side.
|
|
17451
|
-
*
|
|
17452
|
-
*
|
|
17453
|
-
*
|
|
17454
|
-
*
|
|
17674
|
+
* SessionDO already broadcasts a heartbeat every five seconds. Treat that
|
|
17675
|
+
* and all other inbound frames as proof of life instead of issuing an RPC:
|
|
17676
|
+
* an application RPC may be delayed by Durable Object work even while the
|
|
17677
|
+
* underlying WebSocket is healthy.
|
|
17455
17678
|
*/
|
|
17456
17679
|
startHeartbeat() {
|
|
17457
17680
|
if (this.heartbeatTimer) return;
|
|
17458
17681
|
this.heartbeatTimer = setInterval(() => {
|
|
17459
|
-
if (this.
|
|
17460
|
-
this.
|
|
17461
|
-
|
|
17462
|
-
|
|
17463
|
-
|
|
17464
|
-
|
|
17465
|
-
}).catch((error) => {
|
|
17466
|
-
this.client.reportTransportFailure(error);
|
|
17467
|
-
}).finally(() => {
|
|
17468
|
-
this.heartbeatInFlight = false;
|
|
17469
|
-
});
|
|
17682
|
+
if (!this.client.isTransportOpen()) return;
|
|
17683
|
+
if (this.client.hasRecentInboundActivity(3e4)) return;
|
|
17684
|
+
if (this.client.hasRecentlyPendingRpcPeriod(6e4)) return;
|
|
17685
|
+
this.client.reportTransportFailure(
|
|
17686
|
+
new Error("No server activity received for 30 seconds")
|
|
17687
|
+
);
|
|
17470
17688
|
}, 5e3);
|
|
17471
17689
|
this.heartbeatTimer.unref?.();
|
|
17472
17690
|
}
|
|
@@ -17475,7 +17693,6 @@ var EnvironmentSession = class extends Session {
|
|
|
17475
17693
|
clearInterval(this.heartbeatTimer);
|
|
17476
17694
|
this.heartbeatTimer = null;
|
|
17477
17695
|
}
|
|
17478
|
-
this.heartbeatInFlight = false;
|
|
17479
17696
|
}
|
|
17480
17697
|
async hello() {
|
|
17481
17698
|
const result = await super.hello();
|
|
@@ -17536,7 +17753,13 @@ var EnvironmentSession = class extends Session {
|
|
|
17536
17753
|
for (let attempt = 1; attempt <= SESSION_DATA_REQUEST_RETRY_COUNT; attempt += 1) {
|
|
17537
17754
|
try {
|
|
17538
17755
|
const headers = new Headers(init2.headers);
|
|
17539
|
-
|
|
17756
|
+
const resolvedAuthToken = this.environment.resolveAuthToken();
|
|
17757
|
+
const authToken = typeof resolvedAuthToken === "string" ? resolvedAuthToken : await resolvedAuthToken;
|
|
17758
|
+
headers.set("Authorization", `Bearer ${authToken}`);
|
|
17759
|
+
const method = (init2.method || "GET").toUpperCase();
|
|
17760
|
+
if (method !== "GET" && method !== "HEAD" && method !== "OPTIONS") {
|
|
17761
|
+
this.beforeMutationSend?.();
|
|
17762
|
+
}
|
|
17540
17763
|
const response = await fetch(url, {
|
|
17541
17764
|
method: init2.method || "GET",
|
|
17542
17765
|
headers,
|
|
@@ -17995,7 +18218,7 @@ var EnvironmentSession = class extends Session {
|
|
|
17995
18218
|
method: "POST",
|
|
17996
18219
|
headers: {
|
|
17997
18220
|
"Content-Type": "application/json",
|
|
17998
|
-
Authorization: `Bearer ${this.environment.
|
|
18221
|
+
Authorization: `Bearer ${await this.environment.resolveAuthToken()}`
|
|
17999
18222
|
},
|
|
18000
18223
|
body: JSON.stringify({
|
|
18001
18224
|
reason: "sdk_disconnect_http_fallback",
|
|
@@ -18787,6 +19010,9 @@ var Granular = class _Granular {
|
|
|
18787
19010
|
if (typeof options.limit === "number") {
|
|
18788
19011
|
query.set("limit", String(options.limit));
|
|
18789
19012
|
}
|
|
19013
|
+
if (options.consistency === "refresh") {
|
|
19014
|
+
query.set("consistency", "refresh");
|
|
19015
|
+
}
|
|
18790
19016
|
const state = await this.request(
|
|
18791
19017
|
`/sdk/user-environment-state?${query.toString()}`
|
|
18792
19018
|
);
|
|
@@ -18930,6 +19156,10 @@ var Granular = class _Granular {
|
|
|
18930
19156
|
});
|
|
18931
19157
|
}
|
|
18932
19158
|
async recordOpenAIUsageSpend(usage, context, options) {
|
|
19159
|
+
const providedToken = await this.tokenProvider?.();
|
|
19160
|
+
if (typeof providedToken === "string" && providedToken.trim()) {
|
|
19161
|
+
this.apiKey = providedToken.trim();
|
|
19162
|
+
}
|
|
18933
19163
|
return recordOpenAIUsageSpend({
|
|
18934
19164
|
apiUrl: this.apiUrl,
|
|
18935
19165
|
token: this.apiKey,
|
|
@@ -19102,7 +19332,13 @@ var Granular = class _Granular {
|
|
|
19102
19332
|
}
|
|
19103
19333
|
bindEnvironmentHandle(envData) {
|
|
19104
19334
|
const graphqlEndpoint = `${this.httpUrl}/orchestrator/graphql`;
|
|
19105
|
-
return new Environment(
|
|
19335
|
+
return new Environment(
|
|
19336
|
+
this,
|
|
19337
|
+
envData,
|
|
19338
|
+
this.apiKey,
|
|
19339
|
+
graphqlEndpoint,
|
|
19340
|
+
this.tokenProvider
|
|
19341
|
+
);
|
|
19106
19342
|
}
|
|
19107
19343
|
async bindWebSocketEnvironmentSession(environment, clientId, session, transportOptions = {}) {
|
|
19108
19344
|
const client = new WSClient({
|
|
@@ -19986,6 +20222,10 @@ var Granular = class _Granular {
|
|
|
19986
20222
|
console.log(`[SDK] Requesting: ${url}`);
|
|
19987
20223
|
}
|
|
19988
20224
|
for (let attempt = 1; attempt <= LOCAL_CONTROL_REQUEST_RETRY_COUNT; attempt += 1) {
|
|
20225
|
+
const providedToken = await this.tokenProvider?.();
|
|
20226
|
+
if (typeof providedToken === "string" && providedToken.trim()) {
|
|
20227
|
+
this.apiKey = providedToken.trim();
|
|
20228
|
+
}
|
|
19989
20229
|
const response = await fetch(url, {
|
|
19990
20230
|
...options,
|
|
19991
20231
|
headers: {
|
|
@@ -21917,6 +22157,10 @@ function jsonSchemaTypeName(schema) {
|
|
|
21917
22157
|
const record = normalizeJsonSchema(schema);
|
|
21918
22158
|
if (!record) return "unknown";
|
|
21919
22159
|
const type = record.type;
|
|
22160
|
+
if (record.format === "date-time") return "date-time";
|
|
22161
|
+
if (record.format === "date" || type === "date" || Array.isArray(type) && type.includes("date")) {
|
|
22162
|
+
return "date";
|
|
22163
|
+
}
|
|
21920
22164
|
if (typeof type === "string") {
|
|
21921
22165
|
if (type === "array") return "array";
|
|
21922
22166
|
if (type === "object") return "object";
|
|
@@ -22418,6 +22662,8 @@ ${actionIndex}
|
|
|
22418
22662
|
- 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()\`.
|
|
22419
22663
|
- 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.
|
|
22420
22664
|
- 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.
|
|
22665
|
+
- 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.
|
|
22666
|
+
- 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.
|
|
22421
22667
|
- 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.
|
|
22422
22668
|
- 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.
|
|
22423
22669
|
- 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.
|