@granular-software/sdk 0.4.70 → 0.4.72
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 +4 -2
- package/dist/agent-evals.d.ts +4 -2
- package/dist/agent-evals.js +290 -27
- package/dist/agent-evals.js.map +1 -1
- package/dist/agent-evals.mjs +290 -27
- package/dist/agent-evals.mjs.map +1 -1
- package/dist/agent-harness.js +4 -0
- package/dist/agent-harness.js.map +1 -1
- package/dist/agent-harness.mjs +4 -0
- package/dist/agent-harness.mjs.map +1 -1
- package/dist/cli/index.js +282 -27
- package/dist/{client-D1gq4TO4.d.ts → client-JCISbded.d.ts} +23 -3
- package/dist/{client-qgWZ495o.d.mts → client-p5EhOwpP.d.mts} +23 -3
- package/dist/index.d.mts +67 -4
- package/dist/index.d.ts +67 -4
- package/dist/index.js +1396 -232
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1385 -233
- package/dist/index.mjs.map +1 -1
- package/dist/{spend-B-IQmp7F.d.mts → spend-lJDtuAr6.d.mts} +109 -2
- package/dist/{spend-B-IQmp7F.d.ts → spend-lJDtuAr6.d.ts} +109 -2
- 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 {
|
|
1
|
+
import { a as EnvironmentSession, G as Granular } from './client-p5EhOwpP.mjs';
|
|
2
|
+
import { aI as GranularSpendContext, aD as OpenAITokenSpend, n as Prompt, h as RecordObjectOptions, i as ManifestContent, m as SessionHeapSnapshot, T as ToolWithHandler, b2 as ConnectOptions, bs as CreateEnvironmentData, aX as GranularOptions } from './spend-lJDtuAr6.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';
|
|
@@ -415,6 +415,7 @@ declare function createOpenAIChatTurnGenerator(options: {
|
|
|
415
415
|
model?: string;
|
|
416
416
|
baseUrl?: string;
|
|
417
417
|
temperature?: number;
|
|
418
|
+
reasoningEffort?: "low" | "medium" | "high";
|
|
418
419
|
headers?: Record<string, string>;
|
|
419
420
|
usageContext?: GranularSpendContext;
|
|
420
421
|
onUsage?: (usage: AgentEvalOpenAIUsageEvent) => void | Promise<void>;
|
|
@@ -470,6 +471,7 @@ interface AgentTesterOptions {
|
|
|
470
471
|
model?: string;
|
|
471
472
|
baseUrl?: string;
|
|
472
473
|
temperature?: number;
|
|
474
|
+
reasoningEffort?: "low" | "medium" | "high";
|
|
473
475
|
headers?: Record<string, string>;
|
|
474
476
|
};
|
|
475
477
|
model?: string;
|
package/dist/agent-evals.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as EnvironmentSession, G as Granular } from './client-
|
|
2
|
-
import {
|
|
1
|
+
import { a as EnvironmentSession, G as Granular } from './client-JCISbded.js';
|
|
2
|
+
import { aI as GranularSpendContext, aD as OpenAITokenSpend, n as Prompt, h as RecordObjectOptions, i as ManifestContent, m as SessionHeapSnapshot, T as ToolWithHandler, b2 as ConnectOptions, bs as CreateEnvironmentData, aX as GranularOptions } from './spend-lJDtuAr6.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';
|
|
@@ -415,6 +415,7 @@ declare function createOpenAIChatTurnGenerator(options: {
|
|
|
415
415
|
model?: string;
|
|
416
416
|
baseUrl?: string;
|
|
417
417
|
temperature?: number;
|
|
418
|
+
reasoningEffort?: "low" | "medium" | "high";
|
|
418
419
|
headers?: Record<string, string>;
|
|
419
420
|
usageContext?: GranularSpendContext;
|
|
420
421
|
onUsage?: (usage: AgentEvalOpenAIUsageEvent) => void | Promise<void>;
|
|
@@ -470,6 +471,7 @@ interface AgentTesterOptions {
|
|
|
470
471
|
model?: string;
|
|
471
472
|
baseUrl?: string;
|
|
472
473
|
temperature?: number;
|
|
474
|
+
reasoningEffort?: "low" | "medium" | "high";
|
|
473
475
|
headers?: Record<string, string>;
|
|
474
476
|
};
|
|
475
477
|
model?: string;
|
package/dist/agent-evals.js
CHANGED
|
@@ -5317,6 +5317,38 @@ function stableDocumentFingerprint(value) {
|
|
|
5317
5317
|
(key) => `${JSON.stringify(key)}:${stableDocumentFingerprint(record[key])}`
|
|
5318
5318
|
).join(",")}}`;
|
|
5319
5319
|
}
|
|
5320
|
+
function canonicalDocumentFingerprint(value) {
|
|
5321
|
+
const stripPresentation = (input, path2) => {
|
|
5322
|
+
if (input === null || typeof input !== "object") return input;
|
|
5323
|
+
if (input instanceof Date || input instanceof Uint8Array) return input;
|
|
5324
|
+
if (Array.isArray(input)) {
|
|
5325
|
+
return input.map((entry) => stripPresentation(entry, path2));
|
|
5326
|
+
}
|
|
5327
|
+
const record = input;
|
|
5328
|
+
const output = {};
|
|
5329
|
+
for (const [key, entry] of Object.entries(record)) {
|
|
5330
|
+
if (path2.length === 1 && path2[0] === "feed" && [
|
|
5331
|
+
"transientById",
|
|
5332
|
+
"feedbackUsageByJob",
|
|
5333
|
+
"revision",
|
|
5334
|
+
"lastTransientOrdinal"
|
|
5335
|
+
].includes(key)) {
|
|
5336
|
+
continue;
|
|
5337
|
+
}
|
|
5338
|
+
if (path2.length === 3 && path2[0] === "jobs" && path2[1] === "byId" && [
|
|
5339
|
+
"actionTrace",
|
|
5340
|
+
"actionSummary",
|
|
5341
|
+
"actionSummaryText",
|
|
5342
|
+
"lastActionAt"
|
|
5343
|
+
].includes(key)) {
|
|
5344
|
+
continue;
|
|
5345
|
+
}
|
|
5346
|
+
output[key] = stripPresentation(entry, [...path2, key]);
|
|
5347
|
+
}
|
|
5348
|
+
return output;
|
|
5349
|
+
};
|
|
5350
|
+
return stableDocumentFingerprint(stripPresentation(value, []));
|
|
5351
|
+
}
|
|
5320
5352
|
function debugWs(...args) {
|
|
5321
5353
|
if (DEBUG_WS) {
|
|
5322
5354
|
console.log(...args);
|
|
@@ -5634,6 +5666,7 @@ var WSClient = class {
|
|
|
5634
5666
|
}
|
|
5635
5667
|
this.lastInboundActivityAt = Date.now();
|
|
5636
5668
|
this.reconnectAttempts = 0;
|
|
5669
|
+
this.connectPromise = null;
|
|
5637
5670
|
this.emit("open", {});
|
|
5638
5671
|
finish();
|
|
5639
5672
|
};
|
|
@@ -5796,7 +5829,7 @@ var WSClient = class {
|
|
|
5796
5829
|
this.canonicalDocumentActivated = true;
|
|
5797
5830
|
}
|
|
5798
5831
|
}
|
|
5799
|
-
canAcceptDocumentReplacement(replacement, strictlyNewer) {
|
|
5832
|
+
canAcceptDocumentReplacement(replacement, strictlyNewer, options = {}) {
|
|
5800
5833
|
const replacementCanonical = isCanonicalSessionFeedDocument(replacement);
|
|
5801
5834
|
const currentCanonical = isCanonicalSessionFeedDocument(this.doc);
|
|
5802
5835
|
if (replacementCanonical) {
|
|
@@ -5845,7 +5878,7 @@ var WSClient = class {
|
|
|
5845
5878
|
debugWs(`[Granular DEBUG] Rejected session snapshot: ${canonicalError}`);
|
|
5846
5879
|
return false;
|
|
5847
5880
|
}
|
|
5848
|
-
if (this.canonicalDocumentActivated && incoming.epoch === current.epoch && incoming.revision === current.revision && !readSessionFeedSnapshot(this.doc).error && stableDocumentFingerprint(Automerge__namespace.toJS(replacement)) !== stableDocumentFingerprint(Automerge__namespace.toJS(this.doc))) {
|
|
5881
|
+
if (this.canonicalDocumentActivated && incoming.epoch === current.epoch && incoming.revision === current.revision && !readSessionFeedSnapshot(this.doc).error && (options.allowEqualRevisionPresentation ? canonicalDocumentFingerprint(Automerge__namespace.toJS(replacement)) : stableDocumentFingerprint(Automerge__namespace.toJS(replacement))) !== (options.allowEqualRevisionPresentation ? canonicalDocumentFingerprint(Automerge__namespace.toJS(this.doc)) : stableDocumentFingerprint(Automerge__namespace.toJS(this.doc)))) {
|
|
5849
5882
|
debugWs(
|
|
5850
5883
|
"[Granular DEBUG] Rejected divergent canonical snapshot at the accepted document version."
|
|
5851
5884
|
);
|
|
@@ -5967,6 +6000,7 @@ var WSClient = class {
|
|
|
5967
6000
|
reconnectScheduled: false
|
|
5968
6001
|
};
|
|
5969
6002
|
this.ws = null;
|
|
6003
|
+
this.connectPromise = null;
|
|
5970
6004
|
this.emit("close", info);
|
|
5971
6005
|
if (this.reconnectTimer) {
|
|
5972
6006
|
clearTimeout(this.reconnectTimer);
|
|
@@ -6004,13 +6038,89 @@ var WSClient = class {
|
|
|
6004
6038
|
);
|
|
6005
6039
|
return;
|
|
6006
6040
|
}
|
|
6041
|
+
if ("type" in message && message.type === "job_action_trace") {
|
|
6042
|
+
const update = message;
|
|
6043
|
+
if (typeof update.jobId !== "string" || update.jobId.length === 0 || !Number.isSafeInteger(update.documentEpoch) || update.documentEpoch < 0 || !Number.isSafeInteger(update.documentRevision) || update.documentRevision < 0 || !Array.isArray(update.actionTrace) || update.actionTrace.length > 128 || !update.actionTrace.every(
|
|
6044
|
+
(event) => event && typeof event === "object" && typeof event.id === "string" && typeof event.timestamp === "number" && Number.isFinite(event.timestamp)
|
|
6045
|
+
) || !Array.isArray(update.actionSummary) || update.actionSummary.length > 16 || !update.actionSummary.every((line) => typeof line === "string") || typeof update.actionSummaryText !== "string" || update.actionSummaryText.length > 8e3) {
|
|
6046
|
+
console.warn("[Granular] Ignoring invalid job_action_trace message");
|
|
6047
|
+
return;
|
|
6048
|
+
}
|
|
6049
|
+
const currentVersion = documentVersion(this.doc);
|
|
6050
|
+
if (update.documentEpoch < currentVersion.epoch || update.documentEpoch === currentVersion.epoch && update.documentRevision < currentVersion.revision) {
|
|
6051
|
+
return;
|
|
6052
|
+
}
|
|
6053
|
+
if (update.documentEpoch > currentVersion.epoch || update.documentEpoch === currentVersion.epoch && update.documentRevision > currentVersion.revision) {
|
|
6054
|
+
return;
|
|
6055
|
+
}
|
|
6056
|
+
const current = Automerge__namespace.toJS(this.doc);
|
|
6057
|
+
const job = current.jobs?.byId?.[update.jobId];
|
|
6058
|
+
if (job && typeof job === "object" && !Array.isArray(job)) {
|
|
6059
|
+
job.actionTrace = update.actionTrace;
|
|
6060
|
+
job.actionSummary = update.actionSummary;
|
|
6061
|
+
job.actionSummaryText = update.actionSummaryText;
|
|
6062
|
+
const lastEvent = update.actionTrace[update.actionTrace.length - 1];
|
|
6063
|
+
if (lastEvent && typeof lastEvent.timestamp === "number") {
|
|
6064
|
+
job.lastActionAt = lastEvent.timestamp;
|
|
6065
|
+
}
|
|
6066
|
+
this.doc = Automerge__namespace.from(current);
|
|
6067
|
+
this.emit("job_action_trace", update);
|
|
6068
|
+
this.emit("sync", this.doc);
|
|
6069
|
+
}
|
|
6070
|
+
return;
|
|
6071
|
+
}
|
|
6072
|
+
if ("type" in message && message.type === "feed_transient_patch") {
|
|
6073
|
+
const update = message;
|
|
6074
|
+
if (!Number.isSafeInteger(update.documentEpoch) || update.documentEpoch < 0 || !Number.isSafeInteger(update.documentRevision) || update.documentRevision < 0 || !Number.isSafeInteger(update.feedRevision) || update.feedRevision < 0 || !Number.isSafeInteger(update.lastTransientOrdinal) || update.lastTransientOrdinal < 0 || !Array.isArray(update.changes) || update.changes.length > 128 || !update.changes.every((change) => {
|
|
6075
|
+
if (!change || typeof change !== "object" || typeof change.transientId !== "string" || change.transientId.length === 0) {
|
|
6076
|
+
return false;
|
|
6077
|
+
}
|
|
6078
|
+
if (change.removed === true) return change.item === void 0;
|
|
6079
|
+
const item = change.item;
|
|
6080
|
+
return Boolean(
|
|
6081
|
+
item && typeof item === "object" && !Array.isArray(item) && item.id === change.transientId
|
|
6082
|
+
);
|
|
6083
|
+
})) {
|
|
6084
|
+
console.warn("[Granular] Ignoring invalid feed_transient_patch");
|
|
6085
|
+
return;
|
|
6086
|
+
}
|
|
6087
|
+
const currentVersion = documentVersion(this.doc);
|
|
6088
|
+
if (update.documentEpoch > currentVersion.epoch || update.documentEpoch === currentVersion.epoch && update.documentRevision > currentVersion.revision || update.documentEpoch < currentVersion.epoch || update.documentEpoch === currentVersion.epoch && update.documentRevision < currentVersion.revision) {
|
|
6089
|
+
return;
|
|
6090
|
+
}
|
|
6091
|
+
const current = Automerge__namespace.toJS(this.doc);
|
|
6092
|
+
const feed = current.feed;
|
|
6093
|
+
if (!feed || typeof feed !== "object" || Array.isArray(feed)) return;
|
|
6094
|
+
if (Number.isSafeInteger(feed.revision) && feed.revision > update.feedRevision) {
|
|
6095
|
+
return;
|
|
6096
|
+
}
|
|
6097
|
+
if (Number.isSafeInteger(feed.lastTransientOrdinal) && feed.lastTransientOrdinal > update.lastTransientOrdinal) {
|
|
6098
|
+
return;
|
|
6099
|
+
}
|
|
6100
|
+
if (!feed.transientById || typeof feed.transientById !== "object") {
|
|
6101
|
+
feed.transientById = {};
|
|
6102
|
+
}
|
|
6103
|
+
for (const change of update.changes) {
|
|
6104
|
+
if (change.removed === true) {
|
|
6105
|
+
delete feed.transientById[change.transientId];
|
|
6106
|
+
} else {
|
|
6107
|
+
feed.transientById[change.transientId] = change.item;
|
|
6108
|
+
}
|
|
6109
|
+
}
|
|
6110
|
+
feed.revision = update.feedRevision;
|
|
6111
|
+
feed.lastTransientOrdinal = update.lastTransientOrdinal;
|
|
6112
|
+
this.doc = Automerge__namespace.from(current);
|
|
6113
|
+
this.emit("feed_transient_patch", update);
|
|
6114
|
+
this.emit("sync", this.doc);
|
|
6115
|
+
return;
|
|
6116
|
+
}
|
|
6007
6117
|
if ("type" in message && message.type === "snapshot_reset") {
|
|
6008
6118
|
const resetMessage = message;
|
|
6009
6119
|
try {
|
|
6010
|
-
if (!Number.isSafeInteger(resetMessage.documentEpoch) || resetMessage.documentEpoch <= 0 || !Number.isSafeInteger(resetMessage.documentRevision) || resetMessage.documentRevision < 0 || !Array.isArray(resetMessage.data)) {
|
|
6120
|
+
if (!Number.isSafeInteger(resetMessage.documentEpoch) || resetMessage.documentEpoch <= 0 || !Number.isSafeInteger(resetMessage.documentRevision) || resetMessage.documentRevision < 0 || !Array.isArray(resetMessage.data) && (!resetMessage.document || typeof resetMessage.document !== "object" || Array.isArray(resetMessage.document))) {
|
|
6011
6121
|
throw new Error("snapshot_reset metadata is invalid");
|
|
6012
6122
|
}
|
|
6013
|
-
const replacement = Automerge__namespace.load(
|
|
6123
|
+
const replacement = resetMessage.document ? Automerge__namespace.from(resetMessage.document) : Automerge__namespace.load(
|
|
6014
6124
|
this.decodeDocumentBytes(
|
|
6015
6125
|
resetMessage.data,
|
|
6016
6126
|
"Automerge snapshot_reset"
|
|
@@ -6024,7 +6134,10 @@ var WSClient = class {
|
|
|
6024
6134
|
"snapshot_reset metadata does not match the saved document"
|
|
6025
6135
|
);
|
|
6026
6136
|
}
|
|
6027
|
-
|
|
6137
|
+
const isJsonReplacement = Boolean(resetMessage.document);
|
|
6138
|
+
if (!this.canAcceptDocumentReplacement(replacement, !isJsonReplacement, {
|
|
6139
|
+
allowEqualRevisionPresentation: isJsonReplacement
|
|
6140
|
+
})) {
|
|
6028
6141
|
if (this.documentRepairRequired) {
|
|
6029
6142
|
this.requireDocumentResync(
|
|
6030
6143
|
"Stale Automerge snapshot_reset during document repair",
|
|
@@ -12369,6 +12482,7 @@ var StateMachineTransitionSchema = external_exports.object({
|
|
|
12369
12482
|
to: external_exports.string().min(1),
|
|
12370
12483
|
label: external_exports.string().optional(),
|
|
12371
12484
|
description: external_exports.string().optional(),
|
|
12485
|
+
userVisible: external_exports.boolean().optional(),
|
|
12372
12486
|
action: StateTransitionActionSchema.optional(),
|
|
12373
12487
|
assignee: StateTransitionAssigneeSchema.optional(),
|
|
12374
12488
|
requirements: StateTransitionRequirementsSchema.optional(),
|
|
@@ -12453,6 +12567,7 @@ var CreatesSchema = external_exports.union([
|
|
|
12453
12567
|
idPath: external_exports.string().min(1).optional(),
|
|
12454
12568
|
pathPath: external_exports.string().min(1).optional(),
|
|
12455
12569
|
statePath: external_exports.string().min(1).optional(),
|
|
12570
|
+
completionState: external_exports.string().min(1).optional(),
|
|
12456
12571
|
classStateHandle: external_exports.boolean().optional()
|
|
12457
12572
|
}).strict()
|
|
12458
12573
|
]);
|
|
@@ -12802,6 +12917,7 @@ function normalizeCreationSummary(metamodels) {
|
|
|
12802
12917
|
...typeof raw.idPath === "string" && raw.idPath.trim() ? { idPath: raw.idPath.trim() } : {},
|
|
12803
12918
|
...typeof raw.pathPath === "string" && raw.pathPath.trim() ? { pathPath: raw.pathPath.trim() } : {},
|
|
12804
12919
|
...typeof raw.statePath === "string" && raw.statePath.trim() ? { statePath: raw.statePath.trim() } : {},
|
|
12920
|
+
...typeof raw.completionState === "string" && raw.completionState.trim() ? { completionState: raw.completionState.trim() } : {},
|
|
12805
12921
|
...typeof raw.classStateHandle === "boolean" ? { classStateHandle: raw.classStateHandle } : {}
|
|
12806
12922
|
};
|
|
12807
12923
|
}
|
|
@@ -12927,7 +13043,7 @@ var effectBehaviorsMetamodelPackage = defineMetamodelPackage({
|
|
|
12927
13043
|
},
|
|
12928
13044
|
{
|
|
12929
13045
|
key: "creates",
|
|
12930
|
-
description: 'Marks a static method as an allowed creator for a class. Use `creates: "class_name"` or `{ className, idPath, pathPath, statePath, classStateHandle }`.'
|
|
13046
|
+
description: 'Marks a static method as an allowed creator for a class. Use `creates: "class_name"` or `{ className, idPath, pathPath, statePath, completionState, classStateHandle }`.'
|
|
12931
13047
|
}
|
|
12932
13048
|
]
|
|
12933
13049
|
},
|
|
@@ -13160,6 +13276,11 @@ function validateProjectionResult(declaration, projection) {
|
|
|
13160
13276
|
"projection.source.version"
|
|
13161
13277
|
);
|
|
13162
13278
|
}
|
|
13279
|
+
if (projection.source.versionScope !== void 0 && projection.source.versionScope !== "global" && projection.source.versionScope !== "target") {
|
|
13280
|
+
throw new Error(
|
|
13281
|
+
"projection.source.versionScope must be 'global' or 'target'"
|
|
13282
|
+
);
|
|
13283
|
+
}
|
|
13163
13284
|
if (!Array.isArray(projection.changes)) {
|
|
13164
13285
|
throw new Error("projection.changes must be an array");
|
|
13165
13286
|
}
|
|
@@ -14817,6 +14938,7 @@ function normalizeStateMachines(values) {
|
|
|
14817
14938
|
to: String(transition?.to?.name || ""),
|
|
14818
14939
|
label: typeof transition?.label === "string" ? transition.label : null,
|
|
14819
14940
|
description: typeof transition?.description === "string" ? transition.description : null,
|
|
14941
|
+
userVisible: typeof transition?.user_visible === "boolean" ? transition.user_visible : typeof transition?.userVisible === "boolean" ? transition.userVisible : null,
|
|
14820
14942
|
action: parseJsonRecord(transition?.action) || parseJsonRecord(transition?.action_json),
|
|
14821
14943
|
assignee: parseJsonRecord(transition?.assignee) || parseJsonRecord(transition?.assignee_json),
|
|
14822
14944
|
requirements: parseJsonRecord(transition?.requirements) || parseJsonRecord(transition?.requirements_json),
|
|
@@ -14888,6 +15010,9 @@ function transitionMetadataGraphqlArgs(transition) {
|
|
|
14888
15010
|
if (typeof transition.description === "string") {
|
|
14889
15011
|
args.push(`description: ${JSON.stringify(transition.description)}`);
|
|
14890
15012
|
}
|
|
15013
|
+
if (typeof transition.userVisible === "boolean") {
|
|
15014
|
+
args.push(`user_visible: ${transition.userVisible}`);
|
|
15015
|
+
}
|
|
14891
15016
|
if (transition.action) {
|
|
14892
15017
|
args.push(
|
|
14893
15018
|
`action_json: ${JSON.stringify(JSON.stringify(transition.action))}`
|
|
@@ -15199,7 +15324,7 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15199
15324
|
name: String!
|
|
15200
15325
|
state_machine: StateMachine!
|
|
15201
15326
|
add_state(name: String!, is_final: Boolean, label: String, description: String): StateMachineMutation!
|
|
15202
|
-
add_transition(name: String!, from: String!, to: String!, label: String, description: String, action_json: String, assignee_json: String, requirements_json: String, permission_json: String, risk: String, expected_outcome_json: String, outcomes_json: String): StateMachineMutation!
|
|
15327
|
+
add_transition(name: String!, from: String!, to: String!, label: String, description: String, user_visible: Boolean, action_json: String, assignee_json: String, requirements_json: String, permission_json: String, risk: String, expected_outcome_json: String, outcomes_json: String): StateMachineMutation!
|
|
15203
15328
|
activate_transition(name: String!): StateMachineMutation!
|
|
15204
15329
|
}
|
|
15205
15330
|
|
|
@@ -15257,6 +15382,7 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15257
15382
|
to: StateMachineState!
|
|
15258
15383
|
label: String
|
|
15259
15384
|
description: String
|
|
15385
|
+
user_visible: Boolean
|
|
15260
15386
|
action_json: String
|
|
15261
15387
|
assignee_json: String
|
|
15262
15388
|
requirements_json: String
|
|
@@ -15338,6 +15464,7 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15338
15464
|
to,
|
|
15339
15465
|
label,
|
|
15340
15466
|
description,
|
|
15467
|
+
user_visible,
|
|
15341
15468
|
action_json,
|
|
15342
15469
|
assignee_json,
|
|
15343
15470
|
requirements_json,
|
|
@@ -15355,6 +15482,7 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15355
15482
|
{
|
|
15356
15483
|
label,
|
|
15357
15484
|
description,
|
|
15485
|
+
userVisible: user_visible,
|
|
15358
15486
|
actionJson: action_json,
|
|
15359
15487
|
assigneeJson: assignee_json,
|
|
15360
15488
|
requirementsJson: requirements_json,
|
|
@@ -15419,6 +15547,7 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15419
15547
|
to: (value) => value.to_state || { name: value.to, is_final: false },
|
|
15420
15548
|
label: (value) => value.label || null,
|
|
15421
15549
|
description: (value) => value.description || null,
|
|
15550
|
+
user_visible: (value) => value.user_visible ?? null,
|
|
15422
15551
|
action_json: (value) => value.action_json || null,
|
|
15423
15552
|
assignee_json: (value) => value.assignee_json || null,
|
|
15424
15553
|
requirements_json: (value) => value.requirements_json || null,
|
|
@@ -15505,6 +15634,7 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15505
15634
|
to { name }
|
|
15506
15635
|
label
|
|
15507
15636
|
description
|
|
15637
|
+
user_visible
|
|
15508
15638
|
action_json
|
|
15509
15639
|
assignee_json
|
|
15510
15640
|
requirements_json
|
|
@@ -15814,6 +15944,104 @@ function buildEffectMetamodelMutations(toolPath, spec) {
|
|
|
15814
15944
|
);
|
|
15815
15945
|
}
|
|
15816
15946
|
|
|
15947
|
+
// src/artifact-workflow.ts
|
|
15948
|
+
var TERMINAL_WORKFLOW_STEP_STATUSES = /* @__PURE__ */ new Set([
|
|
15949
|
+
"completed",
|
|
15950
|
+
"skipped",
|
|
15951
|
+
"canceled"
|
|
15952
|
+
]);
|
|
15953
|
+
function isArtifactWorkflowNodeTerminal(nodeOrStatus) {
|
|
15954
|
+
const status = typeof nodeOrStatus === "string" ? nodeOrStatus : nodeOrStatus.status;
|
|
15955
|
+
return TERMINAL_WORKFLOW_STEP_STATUSES.has(status);
|
|
15956
|
+
}
|
|
15957
|
+
function isNavigationOnlyOperation(workflow, node) {
|
|
15958
|
+
const hasExplicitTransitionLeaf = getArtifactWorkflowNodes(workflow).some(
|
|
15959
|
+
(candidate) => candidate.childIds.length === 0 && candidate.kind === "transition"
|
|
15960
|
+
);
|
|
15961
|
+
return hasExplicitTransitionLeaf && node.childIds.length === 0 && node.kind === "operation" && // A terminal operation is redundant once authored state-path leaves are
|
|
15962
|
+
// available. While it is still delivering/synchronizing, however, it is
|
|
15963
|
+
// the only honest representation of the work still in progress.
|
|
15964
|
+
isArtifactWorkflowNodeTerminal(node);
|
|
15965
|
+
}
|
|
15966
|
+
function isArtifactWorkflowNodeNavigableLeaf(workflow, node) {
|
|
15967
|
+
return node.childIds.length === 0 && !isNavigationOnlyOperation(workflow, node);
|
|
15968
|
+
}
|
|
15969
|
+
function isArtifactWorkflowNodeActionable(node) {
|
|
15970
|
+
return node.availability === "available" && ["current", "needs_input", "working", "blocked", "failed"].includes(
|
|
15971
|
+
node.status
|
|
15972
|
+
);
|
|
15973
|
+
}
|
|
15974
|
+
function getArtifactWorkflowNodes(workflow) {
|
|
15975
|
+
const visit = (id) => {
|
|
15976
|
+
const node = workflow.nodesById[id];
|
|
15977
|
+
return node ? [node, ...node.childIds.flatMap(visit)] : [];
|
|
15978
|
+
};
|
|
15979
|
+
return workflow.rootNodeIds.flatMap(visit);
|
|
15980
|
+
}
|
|
15981
|
+
function assertArtifactWorkflow(workflow) {
|
|
15982
|
+
if (workflow.schemaVersion !== 1)
|
|
15983
|
+
throw new Error("Unsupported artifact workflow schema");
|
|
15984
|
+
if (!Number.isSafeInteger(workflow.revision) || workflow.revision < 1) {
|
|
15985
|
+
throw new Error("Artifact workflow revision must be a positive integer");
|
|
15986
|
+
}
|
|
15987
|
+
const visited = /* @__PURE__ */ new Set();
|
|
15988
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
15989
|
+
const nodes = [];
|
|
15990
|
+
const visit = (id, expectedParentId) => {
|
|
15991
|
+
const node = workflow.nodesById[id];
|
|
15992
|
+
if (!node) throw new Error(`Artifact workflow node ${id} does not exist`);
|
|
15993
|
+
if (visiting.has(id)) throw new Error("Artifact workflow contains a cycle");
|
|
15994
|
+
if (visited.has(id))
|
|
15995
|
+
throw new Error("Artifact workflow contains a duplicate node reference");
|
|
15996
|
+
if (node.parentId !== expectedParentId) {
|
|
15997
|
+
throw new Error(`Artifact workflow node ${id} has an invalid parent`);
|
|
15998
|
+
}
|
|
15999
|
+
visiting.add(id);
|
|
16000
|
+
nodes.push(node);
|
|
16001
|
+
node.childIds.forEach((childId) => visit(childId, id));
|
|
16002
|
+
visiting.delete(id);
|
|
16003
|
+
visited.add(id);
|
|
16004
|
+
};
|
|
16005
|
+
workflow.rootNodeIds.forEach((id) => visit(id, null));
|
|
16006
|
+
if (visited.size !== Object.keys(workflow.nodesById).length) {
|
|
16007
|
+
throw new Error("Artifact workflow contains unreachable nodes");
|
|
16008
|
+
}
|
|
16009
|
+
if (workflow.currentNodeId && !workflow.nodesById[workflow.currentNodeId]) {
|
|
16010
|
+
throw new Error("Artifact workflow current node does not exist");
|
|
16011
|
+
}
|
|
16012
|
+
const currentNode = workflow.currentNodeId ? workflow.nodesById[workflow.currentNodeId] : null;
|
|
16013
|
+
if (currentNode && currentNode.childIds.length > 0) {
|
|
16014
|
+
throw new Error("Artifact workflow current node must be actionable leaf");
|
|
16015
|
+
}
|
|
16016
|
+
const actionable = nodes.filter(
|
|
16017
|
+
(node) => isArtifactWorkflowNodeNavigableLeaf(workflow, node) && isArtifactWorkflowNodeActionable(node)
|
|
16018
|
+
);
|
|
16019
|
+
if (actionable.length > 1)
|
|
16020
|
+
throw new Error("Artifact workflow has multiple current nodes");
|
|
16021
|
+
if (actionable.length === 1 && actionable[0].id !== workflow.currentNodeId) {
|
|
16022
|
+
throw new Error("Artifact workflow current node does not own its action");
|
|
16023
|
+
}
|
|
16024
|
+
if (workflow.currentNodeId && !actionable.length && !isArtifactWorkflowNodeTerminal(currentNode)) {
|
|
16025
|
+
throw new Error("Artifact workflow current node is not actionable");
|
|
16026
|
+
}
|
|
16027
|
+
}
|
|
16028
|
+
function requireArtifactWorkflow(artifact) {
|
|
16029
|
+
if (!artifact.workflow) {
|
|
16030
|
+
throw new Error(
|
|
16031
|
+
`Artifact ${artifact.artifactId} has no canonical workflow`
|
|
16032
|
+
);
|
|
16033
|
+
}
|
|
16034
|
+
assertArtifactWorkflow(artifact.workflow);
|
|
16035
|
+
if (artifact.workflow.artifactId !== artifact.artifactId) {
|
|
16036
|
+
throw new Error("Artifact workflow belongs to a different artifact");
|
|
16037
|
+
}
|
|
16038
|
+
return artifact;
|
|
16039
|
+
}
|
|
16040
|
+
function requireArtifactWorkflowResult(result) {
|
|
16041
|
+
requireArtifactWorkflow(result.artifact);
|
|
16042
|
+
return result;
|
|
16043
|
+
}
|
|
16044
|
+
|
|
15817
16045
|
// src/client.ts
|
|
15818
16046
|
var DEFAULT_CONVERSATION_SESSION_LIST_LIMIT = 100;
|
|
15819
16047
|
var MAX_CONVERSATION_SESSION_LIST_LIMIT = 500;
|
|
@@ -17657,6 +17885,7 @@ var EnvironmentSession = class extends Session {
|
|
|
17657
17885
|
sessionDataHeaders;
|
|
17658
17886
|
beforeMutationSend;
|
|
17659
17887
|
heartbeatTimer = null;
|
|
17888
|
+
heartbeatProbeInFlight = false;
|
|
17660
17889
|
/** The last known graph container status, updated by checkReadiness(). */
|
|
17661
17890
|
graphContainerStatus = null;
|
|
17662
17891
|
constructor(client, environment, clientId, options = {}) {
|
|
@@ -17676,16 +17905,34 @@ var EnvironmentSession = class extends Session {
|
|
|
17676
17905
|
* an application RPC may be delayed by Durable Object work even while the
|
|
17677
17906
|
* underlying WebSocket is healthy.
|
|
17678
17907
|
*/
|
|
17679
|
-
startHeartbeat() {
|
|
17908
|
+
startHeartbeat(options = {}) {
|
|
17680
17909
|
if (this.heartbeatTimer) return;
|
|
17681
|
-
|
|
17682
|
-
|
|
17683
|
-
|
|
17684
|
-
|
|
17685
|
-
|
|
17686
|
-
|
|
17687
|
-
|
|
17688
|
-
|
|
17910
|
+
const probeServer = options.probeServer === true;
|
|
17911
|
+
this.heartbeatTimer = setInterval(
|
|
17912
|
+
() => {
|
|
17913
|
+
if (!this.client.isTransportOpen()) return;
|
|
17914
|
+
if (probeServer) {
|
|
17915
|
+
if (this.heartbeatProbeInFlight) return;
|
|
17916
|
+
if (this.client.hasPendingRpcRequests()) return;
|
|
17917
|
+
if (this.client.hasRecentInboundActivity(1e4)) return;
|
|
17918
|
+
this.heartbeatProbeInFlight = true;
|
|
17919
|
+
void this.client.call("client.heartbeat", {}).catch((error) => {
|
|
17920
|
+
if (this.client.isTransportOpen()) {
|
|
17921
|
+
this.client.reportTransportFailure(error);
|
|
17922
|
+
}
|
|
17923
|
+
}).finally(() => {
|
|
17924
|
+
this.heartbeatProbeInFlight = false;
|
|
17925
|
+
});
|
|
17926
|
+
return;
|
|
17927
|
+
}
|
|
17928
|
+
if (this.client.hasRecentInboundActivity(3e4)) return;
|
|
17929
|
+
if (this.client.hasRecentlyPendingRpcPeriod(6e4)) return;
|
|
17930
|
+
this.client.reportTransportFailure(
|
|
17931
|
+
new Error("No server activity received for 30 seconds")
|
|
17932
|
+
);
|
|
17933
|
+
},
|
|
17934
|
+
probeServer ? 1e4 : 5e3
|
|
17935
|
+
);
|
|
17689
17936
|
this.heartbeatTimer.unref?.();
|
|
17690
17937
|
}
|
|
17691
17938
|
stopHeartbeat() {
|
|
@@ -17693,10 +17940,15 @@ var EnvironmentSession = class extends Session {
|
|
|
17693
17940
|
clearInterval(this.heartbeatTimer);
|
|
17694
17941
|
this.heartbeatTimer = null;
|
|
17695
17942
|
}
|
|
17943
|
+
this.heartbeatProbeInFlight = false;
|
|
17696
17944
|
}
|
|
17697
17945
|
async hello() {
|
|
17698
17946
|
const result = await super.hello();
|
|
17699
|
-
|
|
17947
|
+
if (result.features?.serverHeartbeat === false) {
|
|
17948
|
+
this.startHeartbeat({ probeServer: true });
|
|
17949
|
+
} else {
|
|
17950
|
+
this.startHeartbeat();
|
|
17951
|
+
}
|
|
17700
17952
|
return result;
|
|
17701
17953
|
}
|
|
17702
17954
|
get environmentId() {
|
|
@@ -17882,7 +18134,10 @@ var EnvironmentSession = class extends Session {
|
|
|
17882
18134
|
queryOptions.targetId = options.target.id;
|
|
17883
18135
|
delete queryOptions.target;
|
|
17884
18136
|
}
|
|
17885
|
-
return this.sessionDataRequest("/artifacts", queryOptions)
|
|
18137
|
+
return this.sessionDataRequest("/artifacts", queryOptions).then((page) => ({
|
|
18138
|
+
...page,
|
|
18139
|
+
items: page.items.map(requireArtifactWorkflow)
|
|
18140
|
+
}));
|
|
17886
18141
|
},
|
|
17887
18142
|
listForLatestJob: (options = {}) => this.artifacts.list({
|
|
17888
18143
|
...options,
|
|
@@ -17895,7 +18150,7 @@ var EnvironmentSession = class extends Session {
|
|
|
17895
18150
|
// `cache: no-store`; this also bypasses intermediaries that ignore
|
|
17896
18151
|
// the Fetch cache directive for an otherwise identical GET URL.
|
|
17897
18152
|
{ _granularLiveRead: Date.now() }
|
|
17898
|
-
),
|
|
18153
|
+
).then(requireArtifactWorkflow),
|
|
17899
18154
|
create: (artifact) => this.sessionDataRequest(
|
|
17900
18155
|
"/artifacts",
|
|
17901
18156
|
void 0,
|
|
@@ -17903,7 +18158,7 @@ var EnvironmentSession = class extends Session {
|
|
|
17903
18158
|
method: "POST",
|
|
17904
18159
|
body: artifact
|
|
17905
18160
|
}
|
|
17906
|
-
),
|
|
18161
|
+
).then(requireArtifactWorkflow),
|
|
17907
18162
|
acceptSuggestion: (sequence) => this.sessionDataRequest(
|
|
17908
18163
|
"/artifacts/suggestions/accept",
|
|
17909
18164
|
void 0,
|
|
@@ -17911,7 +18166,7 @@ var EnvironmentSession = class extends Session {
|
|
|
17911
18166
|
method: "POST",
|
|
17912
18167
|
body: { sequence }
|
|
17913
18168
|
}
|
|
17914
|
-
),
|
|
18169
|
+
).then(requireArtifactWorkflow),
|
|
17915
18170
|
updateInputs: (artifactId, patch) => this.sessionDataRequest(
|
|
17916
18171
|
`/artifacts/${encodeURIComponent(artifactId)}`,
|
|
17917
18172
|
void 0,
|
|
@@ -17919,7 +18174,7 @@ var EnvironmentSession = class extends Session {
|
|
|
17919
18174
|
method: "PATCH",
|
|
17920
18175
|
body: patch
|
|
17921
18176
|
}
|
|
17922
|
-
),
|
|
18177
|
+
).then(requireArtifactWorkflow),
|
|
17923
18178
|
relationshipOptions: (artifactId, input) => this.sessionDataRequest(
|
|
17924
18179
|
`/artifacts/${encodeURIComponent(artifactId)}/relationship-options`,
|
|
17925
18180
|
void 0,
|
|
@@ -17929,27 +18184,27 @@ var EnvironmentSession = class extends Session {
|
|
|
17929
18184
|
`/artifacts/${encodeURIComponent(artifactId)}/relationship-create`,
|
|
17930
18185
|
void 0,
|
|
17931
18186
|
{ method: "POST", body: input }
|
|
17932
|
-
),
|
|
18187
|
+
).then(requireArtifactWorkflow),
|
|
17933
18188
|
validate: (artifactId) => this.sessionDataRequest(
|
|
17934
18189
|
`/artifacts/${encodeURIComponent(artifactId)}/validate`,
|
|
17935
18190
|
void 0,
|
|
17936
18191
|
{ method: "POST" }
|
|
17937
|
-
),
|
|
18192
|
+
).then(requireArtifactWorkflowResult),
|
|
17938
18193
|
execute: (artifactId, options) => this.sessionDataRequest(
|
|
17939
18194
|
`/artifacts/${encodeURIComponent(artifactId)}/execute`,
|
|
17940
18195
|
void 0,
|
|
17941
18196
|
{ method: "POST", body: options }
|
|
17942
|
-
),
|
|
18197
|
+
).then(requireArtifactWorkflowResult),
|
|
17943
18198
|
approve: (artifactId, options) => this.sessionDataRequest(
|
|
17944
18199
|
`/artifacts/${encodeURIComponent(artifactId)}/approve`,
|
|
17945
18200
|
void 0,
|
|
17946
18201
|
{ method: "POST", body: options }
|
|
17947
|
-
),
|
|
18202
|
+
).then(requireArtifactWorkflowResult),
|
|
17948
18203
|
cancel: (artifactId) => this.sessionDataRequest(
|
|
17949
18204
|
`/artifacts/${encodeURIComponent(artifactId)}/cancel`,
|
|
17950
18205
|
void 0,
|
|
17951
18206
|
{ method: "POST" }
|
|
17952
|
-
)
|
|
18207
|
+
).then(requireArtifactWorkflow)
|
|
17953
18208
|
};
|
|
17954
18209
|
}
|
|
17955
18210
|
get manualActions() {
|
|
@@ -22663,6 +22918,10 @@ ${actionIndex}
|
|
|
22663
22918
|
- 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.
|
|
22664
22919
|
- 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
22920
|
- 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.
|
|
22921
|
+
- Preserve explicit qualifiers from the user's requested object identity, including quantities, product names, and named organizational scope. Do not shorten a title in a way that drops those qualifiers when they distinguish what is being created.
|
|
22922
|
+
- A contextual or ontology default may fill a value only when the user supplied no conflicting intent for that semantic role. If the user names a team, owner, account, location, or other scope that cannot be grounded, leave that relationship unresolved; never substitute the current actor's default or another convenient visible record.
|
|
22923
|
+
- A missing or inaccessible required relationship is not a reason to replace a reviewable action with a lookup-failure reply. Call the reviewable action with every grounded non-relationship value, omit the unresolved relationship, and let the artifact collect it from the user. This applies even when the user explicitly named the unavailable relationship.
|
|
22924
|
+
- Choose enum values from the request's meaning and the ontology-authored option semantics. Do not choose an enum merely because it makes an available default relationship, budget, policy, or downstream option compatible. If no enum is semantically supported, leave it unresolved or ask.
|
|
22666
22925
|
- 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.
|
|
22667
22926
|
- 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.
|
|
22668
22927
|
- 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.
|
|
@@ -23838,6 +24097,9 @@ ${modelOutputInstruction()}`
|
|
|
23838
24097
|
if (typeof options.temperature === "number") {
|
|
23839
24098
|
payload.temperature = options.temperature;
|
|
23840
24099
|
}
|
|
24100
|
+
if (options.reasoningEffort) {
|
|
24101
|
+
payload.reasoning_effort = options.reasoningEffort;
|
|
24102
|
+
}
|
|
23841
24103
|
let lastError = null;
|
|
23842
24104
|
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
23843
24105
|
try {
|
|
@@ -26163,6 +26425,7 @@ function createAgentTester(options) {
|
|
|
26163
26425
|
model: options.openai?.model || options.model,
|
|
26164
26426
|
baseUrl: options.openai?.baseUrl,
|
|
26165
26427
|
temperature: options.openai?.temperature,
|
|
26428
|
+
reasoningEffort: options.openai?.reasoningEffort,
|
|
26166
26429
|
headers: options.openai?.headers,
|
|
26167
26430
|
onUsage: async (usage) => {
|
|
26168
26431
|
await granular.recordOpenAIUsageSpend(usage, usage.usageContext);
|