@granular-software/sdk 0.4.70 → 0.4.71
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 +286 -27
- package/dist/agent-evals.js.map +1 -1
- package/dist/agent-evals.mjs +286 -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/index.mjs
CHANGED
|
@@ -4278,8 +4278,8 @@ function normalizeFeedItems(values) {
|
|
|
4278
4278
|
return { items: Object.freeze(items), error };
|
|
4279
4279
|
}
|
|
4280
4280
|
function normalizeTransients(values) {
|
|
4281
|
-
const
|
|
4282
|
-
if (!
|
|
4281
|
+
const record2 = asRecord(values);
|
|
4282
|
+
if (!record2) {
|
|
4283
4283
|
return {
|
|
4284
4284
|
items: [],
|
|
4285
4285
|
error: new Error("Canonical feed transientById is not an object.")
|
|
@@ -4288,7 +4288,7 @@ function normalizeTransients(values) {
|
|
|
4288
4288
|
let error = null;
|
|
4289
4289
|
const byId = /* @__PURE__ */ new Map();
|
|
4290
4290
|
const idByOrdinal = /* @__PURE__ */ new Map();
|
|
4291
|
-
for (const [key, value] of Object.entries(
|
|
4291
|
+
for (const [key, value] of Object.entries(record2)) {
|
|
4292
4292
|
const item = normalizeTransientFeedItem(value);
|
|
4293
4293
|
if (!item || item.id !== key) {
|
|
4294
4294
|
error ||= new Error("Canonical feed contains an invalid transient item.");
|
|
@@ -5161,11 +5161,11 @@ function operationId(prefix) {
|
|
|
5161
5161
|
return randomUuid ? `${prefix}_${randomUuid}` : `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
5162
5162
|
}
|
|
5163
5163
|
function unwrapPublishedItem(value) {
|
|
5164
|
-
const
|
|
5165
|
-
const directItems = Array.isArray(
|
|
5166
|
-
const durable = asRecord(
|
|
5164
|
+
const record2 = asRecord(value);
|
|
5165
|
+
const directItems = Array.isArray(record2?.items) ? record2.items : [];
|
|
5166
|
+
const durable = asRecord(record2?.durable);
|
|
5167
5167
|
const durableItems = Array.isArray(durable?.items) ? durable.items : [];
|
|
5168
|
-
return
|
|
5168
|
+
return record2?.item || directItems[0] || durableItems[0] || value;
|
|
5169
5169
|
}
|
|
5170
5170
|
function requireFeedbackItem(value) {
|
|
5171
5171
|
const item = normalizeFeedItem(unwrapPublishedItem(value));
|
|
@@ -5205,14 +5205,14 @@ function createFeedPublisher(publish) {
|
|
|
5205
5205
|
get revision() {
|
|
5206
5206
|
return current.revision;
|
|
5207
5207
|
},
|
|
5208
|
-
update(
|
|
5208
|
+
update(text2, options = {}) {
|
|
5209
5209
|
const reservedOperationId = options.operationId || operationId("feed_transient_update");
|
|
5210
5210
|
const reservedOptions = { ...options };
|
|
5211
5211
|
return enqueueMutation(async () => {
|
|
5212
5212
|
const response = await publish("feed.transient.update", {
|
|
5213
5213
|
transientId: current.id,
|
|
5214
5214
|
expectedRevision: current.revision,
|
|
5215
|
-
text,
|
|
5215
|
+
text: text2,
|
|
5216
5216
|
...reservedOptions,
|
|
5217
5217
|
operationId: reservedOperationId
|
|
5218
5218
|
});
|
|
@@ -5220,14 +5220,14 @@ function createFeedPublisher(publish) {
|
|
|
5220
5220
|
return handle;
|
|
5221
5221
|
});
|
|
5222
5222
|
},
|
|
5223
|
-
settle(
|
|
5223
|
+
settle(text2, options = {}) {
|
|
5224
5224
|
const reservedOperationId = options.operationId || operationId("feed_transient_settle");
|
|
5225
5225
|
const reservedOptions = { ...options };
|
|
5226
5226
|
return enqueueMutation(async () => {
|
|
5227
5227
|
const response = await publish("feed.transient.settle", {
|
|
5228
5228
|
transientId: current.id,
|
|
5229
5229
|
expectedRevision: current.revision,
|
|
5230
|
-
...
|
|
5230
|
+
...text2 === void 0 ? {} : { text: text2 },
|
|
5231
5231
|
...reservedOptions,
|
|
5232
5232
|
operationId: reservedOperationId
|
|
5233
5233
|
});
|
|
@@ -5245,19 +5245,19 @@ function createFeedPublisher(publish) {
|
|
|
5245
5245
|
return handle;
|
|
5246
5246
|
};
|
|
5247
5247
|
return {
|
|
5248
|
-
async feedback(
|
|
5248
|
+
async feedback(text2, options = {}) {
|
|
5249
5249
|
return requireFeedbackItem(
|
|
5250
5250
|
await publish("feed.feedback", {
|
|
5251
|
-
text,
|
|
5251
|
+
text: text2,
|
|
5252
5252
|
...options,
|
|
5253
5253
|
operationId: options.operationId || operationId("feed_feedback")
|
|
5254
5254
|
})
|
|
5255
5255
|
);
|
|
5256
5256
|
},
|
|
5257
|
-
async transientFeedback(
|
|
5257
|
+
async transientFeedback(text2, options = {}) {
|
|
5258
5258
|
const item = requireTransientFeedbackItem(
|
|
5259
5259
|
await publish("feed.transient.create", {
|
|
5260
|
-
text,
|
|
5260
|
+
text: text2,
|
|
5261
5261
|
...options,
|
|
5262
5262
|
operationId: options.operationId || operationId("feed_transient_create")
|
|
5263
5263
|
})
|
|
@@ -5287,9 +5287,9 @@ var DEFAULT_MAX_RECONNECT_ATTEMPTS = 5;
|
|
|
5287
5287
|
var DOCUMENT_RESYNC_CLOSE_CODE = 4e3;
|
|
5288
5288
|
var DOCUMENT_RESYNC_CLOSE_REASON = "Document resync required";
|
|
5289
5289
|
function documentVersion(document) {
|
|
5290
|
-
const
|
|
5291
|
-
const epochValue =
|
|
5292
|
-
const revisionValue =
|
|
5290
|
+
const record2 = document;
|
|
5291
|
+
const epochValue = record2.documentEpoch;
|
|
5292
|
+
const revisionValue = record2.documentRevision;
|
|
5293
5293
|
const epoch = epochValue === void 0 ? 0 : epochValue;
|
|
5294
5294
|
const revision = revisionValue === void 0 ? 0 : revisionValue;
|
|
5295
5295
|
if (!Number.isSafeInteger(epoch) || Number(epoch) < 0 || !Number.isSafeInteger(revision) || Number(revision) < 0) {
|
|
@@ -5311,11 +5311,43 @@ function stableDocumentFingerprint(value) {
|
|
|
5311
5311
|
if (Array.isArray(value)) {
|
|
5312
5312
|
return `[${value.map(stableDocumentFingerprint).join(",")}]`;
|
|
5313
5313
|
}
|
|
5314
|
-
const
|
|
5315
|
-
return `{${Object.keys(
|
|
5316
|
-
(key) => `${JSON.stringify(key)}:${stableDocumentFingerprint(
|
|
5314
|
+
const record2 = value;
|
|
5315
|
+
return `{${Object.keys(record2).sort().map(
|
|
5316
|
+
(key) => `${JSON.stringify(key)}:${stableDocumentFingerprint(record2[key])}`
|
|
5317
5317
|
).join(",")}}`;
|
|
5318
5318
|
}
|
|
5319
|
+
function canonicalDocumentFingerprint(value) {
|
|
5320
|
+
const stripPresentation = (input, path) => {
|
|
5321
|
+
if (input === null || typeof input !== "object") return input;
|
|
5322
|
+
if (input instanceof Date || input instanceof Uint8Array) return input;
|
|
5323
|
+
if (Array.isArray(input)) {
|
|
5324
|
+
return input.map((entry) => stripPresentation(entry, path));
|
|
5325
|
+
}
|
|
5326
|
+
const record2 = input;
|
|
5327
|
+
const output = {};
|
|
5328
|
+
for (const [key, entry] of Object.entries(record2)) {
|
|
5329
|
+
if (path.length === 1 && path[0] === "feed" && [
|
|
5330
|
+
"transientById",
|
|
5331
|
+
"feedbackUsageByJob",
|
|
5332
|
+
"revision",
|
|
5333
|
+
"lastTransientOrdinal"
|
|
5334
|
+
].includes(key)) {
|
|
5335
|
+
continue;
|
|
5336
|
+
}
|
|
5337
|
+
if (path.length === 3 && path[0] === "jobs" && path[1] === "byId" && [
|
|
5338
|
+
"actionTrace",
|
|
5339
|
+
"actionSummary",
|
|
5340
|
+
"actionSummaryText",
|
|
5341
|
+
"lastActionAt"
|
|
5342
|
+
].includes(key)) {
|
|
5343
|
+
continue;
|
|
5344
|
+
}
|
|
5345
|
+
output[key] = stripPresentation(entry, [...path, key]);
|
|
5346
|
+
}
|
|
5347
|
+
return output;
|
|
5348
|
+
};
|
|
5349
|
+
return stableDocumentFingerprint(stripPresentation(value, []));
|
|
5350
|
+
}
|
|
5319
5351
|
function debugWs(...args) {
|
|
5320
5352
|
if (DEBUG_WS) {
|
|
5321
5353
|
console.log(...args);
|
|
@@ -5633,6 +5665,7 @@ var WSClient = class {
|
|
|
5633
5665
|
}
|
|
5634
5666
|
this.lastInboundActivityAt = Date.now();
|
|
5635
5667
|
this.reconnectAttempts = 0;
|
|
5668
|
+
this.connectPromise = null;
|
|
5636
5669
|
this.emit("open", {});
|
|
5637
5670
|
finish();
|
|
5638
5671
|
};
|
|
@@ -5640,8 +5673,8 @@ var WSClient = class {
|
|
|
5640
5673
|
if (!isCurrent()) return;
|
|
5641
5674
|
this.lastInboundActivityAt = Date.now();
|
|
5642
5675
|
try {
|
|
5643
|
-
const
|
|
5644
|
-
this.handleMessage(JSON.parse(
|
|
5676
|
+
const text2 = typeof data === "string" ? data : data && typeof data === "object" && "toString" in data ? String(data.toString()) : "";
|
|
5677
|
+
this.handleMessage(JSON.parse(text2));
|
|
5645
5678
|
} catch (error) {
|
|
5646
5679
|
console.error("[Granular] Failed to parse message:", error);
|
|
5647
5680
|
}
|
|
@@ -5699,8 +5732,8 @@ var WSClient = class {
|
|
|
5699
5732
|
if (typeof reason === "string") return reason;
|
|
5700
5733
|
if (typeof reason === "object" && reason && "toString" in reason) {
|
|
5701
5734
|
try {
|
|
5702
|
-
const
|
|
5703
|
-
return
|
|
5735
|
+
const text2 = String(reason.toString());
|
|
5736
|
+
return text2 || void 0;
|
|
5704
5737
|
} catch {
|
|
5705
5738
|
return void 0;
|
|
5706
5739
|
}
|
|
@@ -5795,7 +5828,7 @@ var WSClient = class {
|
|
|
5795
5828
|
this.canonicalDocumentActivated = true;
|
|
5796
5829
|
}
|
|
5797
5830
|
}
|
|
5798
|
-
canAcceptDocumentReplacement(replacement, strictlyNewer) {
|
|
5831
|
+
canAcceptDocumentReplacement(replacement, strictlyNewer, options = {}) {
|
|
5799
5832
|
const replacementCanonical = isCanonicalSessionFeedDocument(replacement);
|
|
5800
5833
|
const currentCanonical = isCanonicalSessionFeedDocument(this.doc);
|
|
5801
5834
|
if (replacementCanonical) {
|
|
@@ -5844,7 +5877,7 @@ var WSClient = class {
|
|
|
5844
5877
|
debugWs(`[Granular DEBUG] Rejected session snapshot: ${canonicalError}`);
|
|
5845
5878
|
return false;
|
|
5846
5879
|
}
|
|
5847
|
-
if (this.canonicalDocumentActivated && incoming.epoch === current.epoch && incoming.revision === current.revision && !readSessionFeedSnapshot(this.doc).error && stableDocumentFingerprint(Automerge.toJS(replacement)) !== stableDocumentFingerprint(Automerge.toJS(this.doc))) {
|
|
5880
|
+
if (this.canonicalDocumentActivated && incoming.epoch === current.epoch && incoming.revision === current.revision && !readSessionFeedSnapshot(this.doc).error && (options.allowEqualRevisionPresentation ? canonicalDocumentFingerprint(Automerge.toJS(replacement)) : stableDocumentFingerprint(Automerge.toJS(replacement))) !== (options.allowEqualRevisionPresentation ? canonicalDocumentFingerprint(Automerge.toJS(this.doc)) : stableDocumentFingerprint(Automerge.toJS(this.doc)))) {
|
|
5848
5881
|
debugWs(
|
|
5849
5882
|
"[Granular DEBUG] Rejected divergent canonical snapshot at the accepted document version."
|
|
5850
5883
|
);
|
|
@@ -5966,6 +5999,7 @@ var WSClient = class {
|
|
|
5966
5999
|
reconnectScheduled: false
|
|
5967
6000
|
};
|
|
5968
6001
|
this.ws = null;
|
|
6002
|
+
this.connectPromise = null;
|
|
5969
6003
|
this.emit("close", info);
|
|
5970
6004
|
if (this.reconnectTimer) {
|
|
5971
6005
|
clearTimeout(this.reconnectTimer);
|
|
@@ -6003,13 +6037,89 @@ var WSClient = class {
|
|
|
6003
6037
|
);
|
|
6004
6038
|
return;
|
|
6005
6039
|
}
|
|
6040
|
+
if ("type" in message && message.type === "job_action_trace") {
|
|
6041
|
+
const update = message;
|
|
6042
|
+
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(
|
|
6043
|
+
(event) => event && typeof event === "object" && typeof event.id === "string" && typeof event.timestamp === "number" && Number.isFinite(event.timestamp)
|
|
6044
|
+
) || !Array.isArray(update.actionSummary) || update.actionSummary.length > 16 || !update.actionSummary.every((line) => typeof line === "string") || typeof update.actionSummaryText !== "string" || update.actionSummaryText.length > 8e3) {
|
|
6045
|
+
console.warn("[Granular] Ignoring invalid job_action_trace message");
|
|
6046
|
+
return;
|
|
6047
|
+
}
|
|
6048
|
+
const currentVersion = documentVersion(this.doc);
|
|
6049
|
+
if (update.documentEpoch < currentVersion.epoch || update.documentEpoch === currentVersion.epoch && update.documentRevision < currentVersion.revision) {
|
|
6050
|
+
return;
|
|
6051
|
+
}
|
|
6052
|
+
if (update.documentEpoch > currentVersion.epoch || update.documentEpoch === currentVersion.epoch && update.documentRevision > currentVersion.revision) {
|
|
6053
|
+
return;
|
|
6054
|
+
}
|
|
6055
|
+
const current = Automerge.toJS(this.doc);
|
|
6056
|
+
const job = current.jobs?.byId?.[update.jobId];
|
|
6057
|
+
if (job && typeof job === "object" && !Array.isArray(job)) {
|
|
6058
|
+
job.actionTrace = update.actionTrace;
|
|
6059
|
+
job.actionSummary = update.actionSummary;
|
|
6060
|
+
job.actionSummaryText = update.actionSummaryText;
|
|
6061
|
+
const lastEvent = update.actionTrace[update.actionTrace.length - 1];
|
|
6062
|
+
if (lastEvent && typeof lastEvent.timestamp === "number") {
|
|
6063
|
+
job.lastActionAt = lastEvent.timestamp;
|
|
6064
|
+
}
|
|
6065
|
+
this.doc = Automerge.from(current);
|
|
6066
|
+
this.emit("job_action_trace", update);
|
|
6067
|
+
this.emit("sync", this.doc);
|
|
6068
|
+
}
|
|
6069
|
+
return;
|
|
6070
|
+
}
|
|
6071
|
+
if ("type" in message && message.type === "feed_transient_patch") {
|
|
6072
|
+
const update = message;
|
|
6073
|
+
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) => {
|
|
6074
|
+
if (!change || typeof change !== "object" || typeof change.transientId !== "string" || change.transientId.length === 0) {
|
|
6075
|
+
return false;
|
|
6076
|
+
}
|
|
6077
|
+
if (change.removed === true) return change.item === void 0;
|
|
6078
|
+
const item = change.item;
|
|
6079
|
+
return Boolean(
|
|
6080
|
+
item && typeof item === "object" && !Array.isArray(item) && item.id === change.transientId
|
|
6081
|
+
);
|
|
6082
|
+
})) {
|
|
6083
|
+
console.warn("[Granular] Ignoring invalid feed_transient_patch");
|
|
6084
|
+
return;
|
|
6085
|
+
}
|
|
6086
|
+
const currentVersion = documentVersion(this.doc);
|
|
6087
|
+
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) {
|
|
6088
|
+
return;
|
|
6089
|
+
}
|
|
6090
|
+
const current = Automerge.toJS(this.doc);
|
|
6091
|
+
const feed = current.feed;
|
|
6092
|
+
if (!feed || typeof feed !== "object" || Array.isArray(feed)) return;
|
|
6093
|
+
if (Number.isSafeInteger(feed.revision) && feed.revision > update.feedRevision) {
|
|
6094
|
+
return;
|
|
6095
|
+
}
|
|
6096
|
+
if (Number.isSafeInteger(feed.lastTransientOrdinal) && feed.lastTransientOrdinal > update.lastTransientOrdinal) {
|
|
6097
|
+
return;
|
|
6098
|
+
}
|
|
6099
|
+
if (!feed.transientById || typeof feed.transientById !== "object") {
|
|
6100
|
+
feed.transientById = {};
|
|
6101
|
+
}
|
|
6102
|
+
for (const change of update.changes) {
|
|
6103
|
+
if (change.removed === true) {
|
|
6104
|
+
delete feed.transientById[change.transientId];
|
|
6105
|
+
} else {
|
|
6106
|
+
feed.transientById[change.transientId] = change.item;
|
|
6107
|
+
}
|
|
6108
|
+
}
|
|
6109
|
+
feed.revision = update.feedRevision;
|
|
6110
|
+
feed.lastTransientOrdinal = update.lastTransientOrdinal;
|
|
6111
|
+
this.doc = Automerge.from(current);
|
|
6112
|
+
this.emit("feed_transient_patch", update);
|
|
6113
|
+
this.emit("sync", this.doc);
|
|
6114
|
+
return;
|
|
6115
|
+
}
|
|
6006
6116
|
if ("type" in message && message.type === "snapshot_reset") {
|
|
6007
6117
|
const resetMessage = message;
|
|
6008
6118
|
try {
|
|
6009
|
-
if (!Number.isSafeInteger(resetMessage.documentEpoch) || resetMessage.documentEpoch <= 0 || !Number.isSafeInteger(resetMessage.documentRevision) || resetMessage.documentRevision < 0 || !Array.isArray(resetMessage.data)) {
|
|
6119
|
+
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))) {
|
|
6010
6120
|
throw new Error("snapshot_reset metadata is invalid");
|
|
6011
6121
|
}
|
|
6012
|
-
const replacement = Automerge.load(
|
|
6122
|
+
const replacement = resetMessage.document ? Automerge.from(resetMessage.document) : Automerge.load(
|
|
6013
6123
|
this.decodeDocumentBytes(
|
|
6014
6124
|
resetMessage.data,
|
|
6015
6125
|
"Automerge snapshot_reset"
|
|
@@ -6023,7 +6133,10 @@ var WSClient = class {
|
|
|
6023
6133
|
"snapshot_reset metadata does not match the saved document"
|
|
6024
6134
|
);
|
|
6025
6135
|
}
|
|
6026
|
-
|
|
6136
|
+
const isJsonReplacement = Boolean(resetMessage.document);
|
|
6137
|
+
if (!this.canAcceptDocumentReplacement(replacement, !isJsonReplacement, {
|
|
6138
|
+
allowEqualRevisionPresentation: isJsonReplacement
|
|
6139
|
+
})) {
|
|
6027
6140
|
if (this.documentRepairRequired) {
|
|
6028
6141
|
this.requireDocumentResync(
|
|
6029
6142
|
"Stale Automerge snapshot_reset during document repair",
|
|
@@ -6316,30 +6429,30 @@ function parseJsonPromptChoiceOption(option) {
|
|
|
6316
6429
|
}
|
|
6317
6430
|
function normalizePromptChoiceOption(option) {
|
|
6318
6431
|
if (typeof option === "string") {
|
|
6319
|
-
const
|
|
6320
|
-
if (!
|
|
6432
|
+
const record3 = parseJsonPromptChoiceOption(option);
|
|
6433
|
+
if (!record3) {
|
|
6321
6434
|
return { value: option, label: option };
|
|
6322
6435
|
}
|
|
6323
|
-
const value2 = typeof
|
|
6436
|
+
const value2 = typeof record3.value === "string" ? record3.value : typeof record3.id === "string" ? record3.id : typeof record3.label === "string" ? record3.label : JSON.stringify(record3);
|
|
6324
6437
|
return {
|
|
6325
6438
|
value: value2,
|
|
6326
|
-
label: typeof
|
|
6327
|
-
description: typeof
|
|
6439
|
+
label: typeof record3.label === "string" ? record3.label : value2,
|
|
6440
|
+
description: typeof record3.description === "string" ? record3.description : void 0
|
|
6328
6441
|
};
|
|
6329
6442
|
}
|
|
6330
|
-
const
|
|
6331
|
-
if (!
|
|
6443
|
+
const record2 = option;
|
|
6444
|
+
if (!record2) {
|
|
6332
6445
|
return { value: "", label: "" };
|
|
6333
6446
|
}
|
|
6334
|
-
const nestedJson = (typeof
|
|
6447
|
+
const nestedJson = (typeof record2.value === "string" ? parseJsonPromptChoiceOption(record2.value) : null) || (typeof record2.label === "string" ? parseJsonPromptChoiceOption(record2.label) : null);
|
|
6335
6448
|
if (nestedJson) {
|
|
6336
6449
|
return normalizePromptChoiceOption(nestedJson);
|
|
6337
6450
|
}
|
|
6338
|
-
const value = typeof
|
|
6451
|
+
const value = typeof record2.value === "string" ? record2.value : typeof record2.label === "string" ? record2.label : JSON.stringify(record2);
|
|
6339
6452
|
return {
|
|
6340
6453
|
value,
|
|
6341
|
-
label: typeof
|
|
6342
|
-
description: typeof
|
|
6454
|
+
label: typeof record2.label === "string" ? record2.label : value,
|
|
6455
|
+
description: typeof record2.description === "string" ? record2.description : void 0
|
|
6343
6456
|
};
|
|
6344
6457
|
}
|
|
6345
6458
|
function scorePromptChoiceMatch(answer, answerTokens, option) {
|
|
@@ -6631,18 +6744,18 @@ var Session = class {
|
|
|
6631
6744
|
get revision() {
|
|
6632
6745
|
return current.revision;
|
|
6633
6746
|
},
|
|
6634
|
-
async update(
|
|
6747
|
+
async update(text2, options = {}) {
|
|
6635
6748
|
current = await track(
|
|
6636
|
-
current.update(
|
|
6749
|
+
current.update(text2, {
|
|
6637
6750
|
...options,
|
|
6638
6751
|
operationId: options.operationId || nextOperationId("transient-update")
|
|
6639
6752
|
})
|
|
6640
6753
|
);
|
|
6641
6754
|
return wrapped;
|
|
6642
6755
|
},
|
|
6643
|
-
settle(
|
|
6756
|
+
settle(text2, options = {}) {
|
|
6644
6757
|
return track(
|
|
6645
|
-
current.settle(
|
|
6758
|
+
current.settle(text2, {
|
|
6646
6759
|
...options,
|
|
6647
6760
|
operationId: options.operationId || nextOperationId("transient-settle")
|
|
6648
6761
|
})
|
|
@@ -6652,14 +6765,14 @@ var Session = class {
|
|
|
6652
6765
|
return wrapped;
|
|
6653
6766
|
};
|
|
6654
6767
|
return {
|
|
6655
|
-
feedback: (
|
|
6656
|
-
publisher.feedback(
|
|
6768
|
+
feedback: (text2, options = {}) => track(
|
|
6769
|
+
publisher.feedback(text2, {
|
|
6657
6770
|
...options,
|
|
6658
6771
|
operationId: options.operationId || nextOperationId("feedback")
|
|
6659
6772
|
})
|
|
6660
6773
|
),
|
|
6661
|
-
transientFeedback: (
|
|
6662
|
-
publisher.transientFeedback(
|
|
6774
|
+
transientFeedback: (text2, options = {}) => track(
|
|
6775
|
+
publisher.transientFeedback(text2, {
|
|
6663
6776
|
...options,
|
|
6664
6777
|
operationId: options.operationId || nextOperationId("transient-create")
|
|
6665
6778
|
}).then(wrapTransientHandle)
|
|
@@ -7847,8 +7960,8 @@ function artifactRecordsById(liveDoc) {
|
|
|
7847
7960
|
const byId = asRecord3(artifacts?.byId) || {};
|
|
7848
7961
|
return Object.fromEntries(
|
|
7849
7962
|
Object.entries(byId).map(([artifactId, value]) => {
|
|
7850
|
-
const
|
|
7851
|
-
return
|
|
7963
|
+
const record2 = asRecord3(value);
|
|
7964
|
+
return record2 ? [artifactId, record2] : null;
|
|
7852
7965
|
}).filter((entry) => Boolean(entry))
|
|
7853
7966
|
);
|
|
7854
7967
|
}
|
|
@@ -7881,8 +7994,8 @@ function latestInputEditSummary(metadata) {
|
|
|
7881
7994
|
].filter(Boolean);
|
|
7882
7995
|
return `lastEdit=${source}${actor ? ` by ${actor}` : ""}${changed.length ? ` (${changed.join("; ")})` : ""}`;
|
|
7883
7996
|
}
|
|
7884
|
-
function artifactIssueSummary(
|
|
7885
|
-
const validation = asRecord3(
|
|
7997
|
+
function artifactIssueSummary(record2) {
|
|
7998
|
+
const validation = asRecord3(record2.validation);
|
|
7886
7999
|
if (!validation) return null;
|
|
7887
8000
|
const issues = Array.isArray(validation.issues) ? validation.issues.map((issue) => asRecord3(issue)).filter((issue) => Boolean(issue)).slice(0, 3) : [];
|
|
7888
8001
|
if (issues.length > 0) {
|
|
@@ -7929,18 +8042,18 @@ function artifactStatePathSummary(metadata) {
|
|
|
7929
8042
|
].filter(Boolean);
|
|
7930
8043
|
return pieces.length ? pieces.join("; ") : null;
|
|
7931
8044
|
}
|
|
7932
|
-
function artifactSummaryLine(artifactId,
|
|
7933
|
-
if (!
|
|
7934
|
-
const label = trimString(
|
|
7935
|
-
const kind = asString(
|
|
7936
|
-
const status = asString(
|
|
7937
|
-
const createdByJobId = asString(
|
|
7938
|
-
const target = asRecord3(
|
|
7939
|
-
const metadata = asRecord3(
|
|
7940
|
-
const subArtifactIds = Array.isArray(
|
|
8045
|
+
function artifactSummaryLine(artifactId, record2) {
|
|
8046
|
+
if (!record2) return `- ${artifactId}: unavailable in session artifact store`;
|
|
8047
|
+
const label = trimString(record2.label) || artifactId;
|
|
8048
|
+
const kind = asString(record2.kind) || "artifact";
|
|
8049
|
+
const status = asString(record2.status) || "unknown";
|
|
8050
|
+
const createdByJobId = asString(record2.createdByJobId);
|
|
8051
|
+
const target = asRecord3(record2.target);
|
|
8052
|
+
const metadata = asRecord3(record2.metadata) || {};
|
|
8053
|
+
const subArtifactIds = Array.isArray(record2.subArtifactIds) ? record2.subArtifactIds.filter(
|
|
7941
8054
|
(id) => typeof id === "string" && id.trim().length > 0
|
|
7942
8055
|
).slice(0, 8) : [];
|
|
7943
|
-
const relationships = compactJson(
|
|
8056
|
+
const relationships = compactJson(record2.relationships, 220);
|
|
7944
8057
|
const pieces = [
|
|
7945
8058
|
`kind=${kind}`,
|
|
7946
8059
|
`status=${status}`,
|
|
@@ -7948,7 +8061,7 @@ function artifactSummaryLine(artifactId, record) {
|
|
|
7948
8061
|
target ? `target=${asString(target.className) || "record"}:${asString(target.id) || "unknown"}${asString(target.label) ? ` (${asString(target.label)})` : ""}` : null,
|
|
7949
8062
|
artifactStatePathSummary(metadata),
|
|
7950
8063
|
artifactExecutionSummary(metadata),
|
|
7951
|
-
artifactIssueSummary(
|
|
8064
|
+
artifactIssueSummary(record2),
|
|
7952
8065
|
latestInputEditSummary(metadata),
|
|
7953
8066
|
subArtifactIds.length ? `subArtifacts=${subArtifactIds.join(",")}` : null,
|
|
7954
8067
|
relationships ? `relationships=${relationships}` : null
|
|
@@ -12368,6 +12481,7 @@ var StateMachineTransitionSchema = external_exports.object({
|
|
|
12368
12481
|
to: external_exports.string().min(1),
|
|
12369
12482
|
label: external_exports.string().optional(),
|
|
12370
12483
|
description: external_exports.string().optional(),
|
|
12484
|
+
userVisible: external_exports.boolean().optional(),
|
|
12371
12485
|
action: StateTransitionActionSchema.optional(),
|
|
12372
12486
|
assignee: StateTransitionAssigneeSchema.optional(),
|
|
12373
12487
|
requirements: StateTransitionRequirementsSchema.optional(),
|
|
@@ -12452,6 +12566,7 @@ var CreatesSchema = external_exports.union([
|
|
|
12452
12566
|
idPath: external_exports.string().min(1).optional(),
|
|
12453
12567
|
pathPath: external_exports.string().min(1).optional(),
|
|
12454
12568
|
statePath: external_exports.string().min(1).optional(),
|
|
12569
|
+
completionState: external_exports.string().min(1).optional(),
|
|
12455
12570
|
classStateHandle: external_exports.boolean().optional()
|
|
12456
12571
|
}).strict()
|
|
12457
12572
|
]);
|
|
@@ -12801,6 +12916,7 @@ function normalizeCreationSummary(metamodels) {
|
|
|
12801
12916
|
...typeof raw.idPath === "string" && raw.idPath.trim() ? { idPath: raw.idPath.trim() } : {},
|
|
12802
12917
|
...typeof raw.pathPath === "string" && raw.pathPath.trim() ? { pathPath: raw.pathPath.trim() } : {},
|
|
12803
12918
|
...typeof raw.statePath === "string" && raw.statePath.trim() ? { statePath: raw.statePath.trim() } : {},
|
|
12919
|
+
...typeof raw.completionState === "string" && raw.completionState.trim() ? { completionState: raw.completionState.trim() } : {},
|
|
12804
12920
|
...typeof raw.classStateHandle === "boolean" ? { classStateHandle: raw.classStateHandle } : {}
|
|
12805
12921
|
};
|
|
12806
12922
|
}
|
|
@@ -12926,7 +13042,7 @@ var effectBehaviorsMetamodelPackage = defineMetamodelPackage({
|
|
|
12926
13042
|
},
|
|
12927
13043
|
{
|
|
12928
13044
|
key: "creates",
|
|
12929
|
-
description: 'Marks a static method as an allowed creator for a class. Use `creates: "class_name"` or `{ className, idPath, pathPath, statePath, classStateHandle }`.'
|
|
13045
|
+
description: 'Marks a static method as an allowed creator for a class. Use `creates: "class_name"` or `{ className, idPath, pathPath, statePath, completionState, classStateHandle }`.'
|
|
12930
13046
|
}
|
|
12931
13047
|
]
|
|
12932
13048
|
},
|
|
@@ -13149,18 +13265,18 @@ function validateScalarRecord(value, path) {
|
|
|
13149
13265
|
}
|
|
13150
13266
|
function validateProjectedRecord(value, path) {
|
|
13151
13267
|
validateObjectReference(value, path);
|
|
13152
|
-
const
|
|
13153
|
-
if (
|
|
13154
|
-
if (typeof
|
|
13268
|
+
const record2 = value;
|
|
13269
|
+
if (record2.label !== void 0) {
|
|
13270
|
+
if (typeof record2.label !== "string") {
|
|
13155
13271
|
throw new Error(`${path}.label must be a string`);
|
|
13156
13272
|
}
|
|
13157
|
-
if (
|
|
13273
|
+
if (record2.label.length > MAX_SAFE_TEXT_LENGTH) {
|
|
13158
13274
|
throw new Error(
|
|
13159
13275
|
`${path}.label exceeds ${MAX_SAFE_TEXT_LENGTH} characters`
|
|
13160
13276
|
);
|
|
13161
13277
|
}
|
|
13162
13278
|
}
|
|
13163
|
-
validateScalarRecord(
|
|
13279
|
+
validateScalarRecord(record2.fields, `${path}.fields`);
|
|
13164
13280
|
}
|
|
13165
13281
|
function validateBoundedJson(value, path, depth = 0) {
|
|
13166
13282
|
if (depth > 12) throw new Error(`${path} is nested too deeply`);
|
|
@@ -13210,6 +13326,11 @@ function validateProjectionResult(declaration, projection) {
|
|
|
13210
13326
|
"projection.source.version"
|
|
13211
13327
|
);
|
|
13212
13328
|
}
|
|
13329
|
+
if (projection.source.versionScope !== void 0 && projection.source.versionScope !== "global" && projection.source.versionScope !== "target") {
|
|
13330
|
+
throw new Error(
|
|
13331
|
+
"projection.source.versionScope must be 'global' or 'target'"
|
|
13332
|
+
);
|
|
13333
|
+
}
|
|
13213
13334
|
if (!Array.isArray(projection.changes)) {
|
|
13214
13335
|
throw new Error("projection.changes must be an array");
|
|
13215
13336
|
}
|
|
@@ -13573,18 +13694,18 @@ function createInvocationFeedbackContext(bridge) {
|
|
|
13573
13694
|
get revision() {
|
|
13574
13695
|
return current.revision;
|
|
13575
13696
|
},
|
|
13576
|
-
async update(
|
|
13697
|
+
async update(text2, options = {}) {
|
|
13577
13698
|
current = await track(
|
|
13578
|
-
current.update(
|
|
13699
|
+
current.update(text2, {
|
|
13579
13700
|
...options,
|
|
13580
13701
|
operationId: options.operationId || nextOperationId("transient-update")
|
|
13581
13702
|
})
|
|
13582
13703
|
);
|
|
13583
13704
|
return wrapped;
|
|
13584
13705
|
},
|
|
13585
|
-
settle(
|
|
13706
|
+
settle(text2, options = {}) {
|
|
13586
13707
|
return track(
|
|
13587
|
-
current.settle(
|
|
13708
|
+
current.settle(text2, {
|
|
13588
13709
|
...options,
|
|
13589
13710
|
operationId: options.operationId || nextOperationId("transient-settle")
|
|
13590
13711
|
})
|
|
@@ -13594,17 +13715,17 @@ function createInvocationFeedbackContext(bridge) {
|
|
|
13594
13715
|
return wrapped;
|
|
13595
13716
|
};
|
|
13596
13717
|
return {
|
|
13597
|
-
feedback(
|
|
13718
|
+
feedback(text2, options = {}) {
|
|
13598
13719
|
return track(
|
|
13599
|
-
publisher.feedback(
|
|
13720
|
+
publisher.feedback(text2, {
|
|
13600
13721
|
...options,
|
|
13601
13722
|
operationId: options.operationId || nextOperationId("feedback")
|
|
13602
13723
|
})
|
|
13603
13724
|
);
|
|
13604
13725
|
},
|
|
13605
|
-
transientFeedback(
|
|
13726
|
+
transientFeedback(text2, options = {}) {
|
|
13606
13727
|
return track(
|
|
13607
|
-
publisher.transientFeedback(
|
|
13728
|
+
publisher.transientFeedback(text2, {
|
|
13608
13729
|
...options,
|
|
13609
13730
|
operationId: options.operationId || nextOperationId("transient-create")
|
|
13610
13731
|
}).then(wrapTransientHandle)
|
|
@@ -14452,9 +14573,9 @@ var noteMetamodelPackage = defineMetamodelPackage({
|
|
|
14452
14573
|
notes: async (ant) => await run(ant.notes())
|
|
14453
14574
|
},
|
|
14454
14575
|
ModelMutation: {
|
|
14455
|
-
add_note: async (ant, { text }) => {
|
|
14456
|
-
const model = await run(ant.add_note(
|
|
14457
|
-
return { model, text };
|
|
14576
|
+
add_note: async (ant, { text: text2 }) => {
|
|
14577
|
+
const model = await run(ant.add_note(text2));
|
|
14578
|
+
return { model, text: text2 };
|
|
14458
14579
|
}
|
|
14459
14580
|
}
|
|
14460
14581
|
};
|
|
@@ -14867,6 +14988,7 @@ function normalizeStateMachines(values) {
|
|
|
14867
14988
|
to: String(transition?.to?.name || ""),
|
|
14868
14989
|
label: typeof transition?.label === "string" ? transition.label : null,
|
|
14869
14990
|
description: typeof transition?.description === "string" ? transition.description : null,
|
|
14991
|
+
userVisible: typeof transition?.user_visible === "boolean" ? transition.user_visible : typeof transition?.userVisible === "boolean" ? transition.userVisible : null,
|
|
14870
14992
|
action: parseJsonRecord(transition?.action) || parseJsonRecord(transition?.action_json),
|
|
14871
14993
|
assignee: parseJsonRecord(transition?.assignee) || parseJsonRecord(transition?.assignee_json),
|
|
14872
14994
|
requirements: parseJsonRecord(transition?.requirements) || parseJsonRecord(transition?.requirements_json),
|
|
@@ -14938,6 +15060,9 @@ function transitionMetadataGraphqlArgs(transition) {
|
|
|
14938
15060
|
if (typeof transition.description === "string") {
|
|
14939
15061
|
args.push(`description: ${JSON.stringify(transition.description)}`);
|
|
14940
15062
|
}
|
|
15063
|
+
if (typeof transition.userVisible === "boolean") {
|
|
15064
|
+
args.push(`user_visible: ${transition.userVisible}`);
|
|
15065
|
+
}
|
|
14941
15066
|
if (transition.action) {
|
|
14942
15067
|
args.push(
|
|
14943
15068
|
`action_json: ${JSON.stringify(JSON.stringify(transition.action))}`
|
|
@@ -15249,7 +15374,7 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15249
15374
|
name: String!
|
|
15250
15375
|
state_machine: StateMachine!
|
|
15251
15376
|
add_state(name: String!, is_final: Boolean, label: String, description: String): StateMachineMutation!
|
|
15252
|
-
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!
|
|
15377
|
+
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!
|
|
15253
15378
|
activate_transition(name: String!): StateMachineMutation!
|
|
15254
15379
|
}
|
|
15255
15380
|
|
|
@@ -15307,6 +15432,7 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15307
15432
|
to: StateMachineState!
|
|
15308
15433
|
label: String
|
|
15309
15434
|
description: String
|
|
15435
|
+
user_visible: Boolean
|
|
15310
15436
|
action_json: String
|
|
15311
15437
|
assignee_json: String
|
|
15312
15438
|
requirements_json: String
|
|
@@ -15388,6 +15514,7 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15388
15514
|
to,
|
|
15389
15515
|
label,
|
|
15390
15516
|
description,
|
|
15517
|
+
user_visible,
|
|
15391
15518
|
action_json,
|
|
15392
15519
|
assignee_json,
|
|
15393
15520
|
requirements_json,
|
|
@@ -15405,6 +15532,7 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15405
15532
|
{
|
|
15406
15533
|
label,
|
|
15407
15534
|
description,
|
|
15535
|
+
userVisible: user_visible,
|
|
15408
15536
|
actionJson: action_json,
|
|
15409
15537
|
assigneeJson: assignee_json,
|
|
15410
15538
|
requirementsJson: requirements_json,
|
|
@@ -15469,6 +15597,7 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15469
15597
|
to: (value) => value.to_state || { name: value.to, is_final: false },
|
|
15470
15598
|
label: (value) => value.label || null,
|
|
15471
15599
|
description: (value) => value.description || null,
|
|
15600
|
+
user_visible: (value) => value.user_visible ?? null,
|
|
15472
15601
|
action_json: (value) => value.action_json || null,
|
|
15473
15602
|
assignee_json: (value) => value.assignee_json || null,
|
|
15474
15603
|
requirements_json: (value) => value.requirements_json || null,
|
|
@@ -15555,6 +15684,7 @@ var stateMachineMetamodelPackage = defineMetamodelPackage({
|
|
|
15555
15684
|
to { name }
|
|
15556
15685
|
label
|
|
15557
15686
|
description
|
|
15687
|
+
user_visible
|
|
15558
15688
|
action_json
|
|
15559
15689
|
assignee_json
|
|
15560
15690
|
requirements_json
|
|
@@ -15962,6 +16092,786 @@ function buildEffectMetamodelMutations(toolPath, spec) {
|
|
|
15962
16092
|
);
|
|
15963
16093
|
}
|
|
15964
16094
|
|
|
16095
|
+
// src/artifact-workflow.ts
|
|
16096
|
+
var TERMINAL_ARTIFACT_STATUSES = /* @__PURE__ */ new Set([
|
|
16097
|
+
"completed",
|
|
16098
|
+
"partially_completed",
|
|
16099
|
+
"failed",
|
|
16100
|
+
"canceled"
|
|
16101
|
+
]);
|
|
16102
|
+
function record(value) {
|
|
16103
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
16104
|
+
}
|
|
16105
|
+
function text(value) {
|
|
16106
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
16107
|
+
}
|
|
16108
|
+
function humanize(value) {
|
|
16109
|
+
const words = value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
|
|
16110
|
+
return words ? words[0].toUpperCase() + words.slice(1) : "Details";
|
|
16111
|
+
}
|
|
16112
|
+
function stableToken(value) {
|
|
16113
|
+
return encodeURIComponent(value.trim().toLowerCase());
|
|
16114
|
+
}
|
|
16115
|
+
function isMissing(value) {
|
|
16116
|
+
return value === null || value === void 0 || typeof value === "string" && !value.trim() || Array.isArray(value) && value.length === 0;
|
|
16117
|
+
}
|
|
16118
|
+
function displayValue(value) {
|
|
16119
|
+
if (typeof value === "string") return value;
|
|
16120
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
16121
|
+
return String(value);
|
|
16122
|
+
}
|
|
16123
|
+
if (Array.isArray(value)) {
|
|
16124
|
+
return value.map(displayValue).filter(Boolean).join(", ");
|
|
16125
|
+
}
|
|
16126
|
+
return "Provided";
|
|
16127
|
+
}
|
|
16128
|
+
function artifactFields(artifact) {
|
|
16129
|
+
return Array.isArray(artifact.inputSchema?.fields) ? artifact.inputSchema.fields.filter(
|
|
16130
|
+
(field) => Boolean(record(field))
|
|
16131
|
+
) : [];
|
|
16132
|
+
}
|
|
16133
|
+
function declaredSections(artifact) {
|
|
16134
|
+
const fields = artifactFields(artifact);
|
|
16135
|
+
if (!fields.length) return [];
|
|
16136
|
+
const knownNames = new Set(
|
|
16137
|
+
fields.map((field) => text(field.name)).filter((name) => Boolean(name))
|
|
16138
|
+
);
|
|
16139
|
+
const ui = record(artifact.inputSchema?.ui);
|
|
16140
|
+
const workflow = record(ui?.workflow);
|
|
16141
|
+
const rawSections = Array.isArray(workflow?.steps) ? workflow.steps : Array.isArray(ui?.sections) ? ui.sections : [];
|
|
16142
|
+
const used = /* @__PURE__ */ new Set();
|
|
16143
|
+
const sections = rawSections.flatMap((value) => {
|
|
16144
|
+
const section = record(value);
|
|
16145
|
+
const id = text(section?.id);
|
|
16146
|
+
const label = text(section?.label);
|
|
16147
|
+
const fieldNames = Array.isArray(section?.fieldNames) ? section.fieldNames.map(text).filter(
|
|
16148
|
+
(name) => name !== null && knownNames.has(name) && !used.has(name)
|
|
16149
|
+
) : [];
|
|
16150
|
+
if (!id || !label || !fieldNames.length) return [];
|
|
16151
|
+
fieldNames.forEach((name) => used.add(name));
|
|
16152
|
+
return [{ id, label, description: text(section?.description), fieldNames }];
|
|
16153
|
+
});
|
|
16154
|
+
const remaining = [...knownNames].filter((name) => !used.has(name));
|
|
16155
|
+
const chunkSize = 5;
|
|
16156
|
+
const chunkCount = Math.ceil(remaining.length / chunkSize);
|
|
16157
|
+
const hasDeclaredSections = sections.length > 0;
|
|
16158
|
+
for (let index = 0; index < chunkCount; index += 1) {
|
|
16159
|
+
const baseLabel = hasDeclaredSections ? "Other details" : "Details";
|
|
16160
|
+
sections.push({
|
|
16161
|
+
id: chunkCount === 1 ? hasDeclaredSections ? "other-details" : "details" : `${hasDeclaredSections ? "other-details" : "details"}-${index + 1}`,
|
|
16162
|
+
label: chunkCount === 1 ? baseLabel : `${baseLabel} ${index + 1}`,
|
|
16163
|
+
description: null,
|
|
16164
|
+
fieldNames: remaining.slice(index * chunkSize, (index + 1) * chunkSize)
|
|
16165
|
+
});
|
|
16166
|
+
}
|
|
16167
|
+
return sections;
|
|
16168
|
+
}
|
|
16169
|
+
function fieldValue(artifact, fieldName) {
|
|
16170
|
+
const field = artifactFields(artifact).find(
|
|
16171
|
+
(candidate) => text(candidate.name) === fieldName
|
|
16172
|
+
);
|
|
16173
|
+
const kind = text(field?.kind);
|
|
16174
|
+
return kind === "relationshipOne" || kind === "relationshipMany" ? artifact.relationships?.[fieldName] : artifact.inputValues?.[fieldName];
|
|
16175
|
+
}
|
|
16176
|
+
function conditionallyRequired(artifact, field) {
|
|
16177
|
+
const raw = field.requiredWhen ?? field.required_when;
|
|
16178
|
+
const conditions = Array.isArray(raw) ? raw : raw ? [raw] : [];
|
|
16179
|
+
return conditions.length > 0 && conditions.every((value) => {
|
|
16180
|
+
const condition = record(value);
|
|
16181
|
+
const dependency = text(condition?.field);
|
|
16182
|
+
return Boolean(dependency) && Object.prototype.hasOwnProperty.call(condition || {}, "equals") && Object.is(fieldValue(artifact, dependency), condition.equals);
|
|
16183
|
+
});
|
|
16184
|
+
}
|
|
16185
|
+
function fieldValidationRules(field) {
|
|
16186
|
+
const raw = Array.isArray(field.validationRules) ? field.validationRules : Array.isArray(field.validation_rules) ? field.validation_rules : Array.isArray(field.validate) ? field.validate : [];
|
|
16187
|
+
return raw.filter(
|
|
16188
|
+
(rule) => Boolean(record(rule)) && typeof record(rule)?.operator === "string"
|
|
16189
|
+
);
|
|
16190
|
+
}
|
|
16191
|
+
function fieldProvenanceNeedsReview(artifact, field) {
|
|
16192
|
+
const fieldName = text(field.name);
|
|
16193
|
+
if (!fieldName) return false;
|
|
16194
|
+
const namespace = text(field.kind)?.startsWith("relationship") ? "relationships" : "inputValues";
|
|
16195
|
+
const provenance = artifact.fieldProvenance?.[`${namespace}.${fieldName}`];
|
|
16196
|
+
if (!provenance) return false;
|
|
16197
|
+
const confirmedAt = typeof provenance.confirmedAt === "number" ? provenance.confirmedAt : null;
|
|
16198
|
+
const updatedAt = typeof provenance.updatedAt === "number" ? provenance.updatedAt : null;
|
|
16199
|
+
const invalidatedAt = typeof provenance.invalidatedAt === "number" ? provenance.invalidatedAt : null;
|
|
16200
|
+
const explicitlyConfirmed = confirmedAt !== null && (updatedAt === null || confirmedAt >= updatedAt) && (invalidatedAt === null || confirmedAt >= invalidatedAt);
|
|
16201
|
+
if (explicitlyConfirmed) return false;
|
|
16202
|
+
const invalidated = invalidatedAt !== null && (confirmedAt === null || confirmedAt < invalidatedAt);
|
|
16203
|
+
const assistantSource = [
|
|
16204
|
+
"user_statement",
|
|
16205
|
+
"agent_extraction",
|
|
16206
|
+
"agent_inference",
|
|
16207
|
+
"provider_lookup",
|
|
16208
|
+
"ontology_default"
|
|
16209
|
+
].includes(provenance.source);
|
|
16210
|
+
return invalidated || assistantSource && provenance.confidence === "ambiguous";
|
|
16211
|
+
}
|
|
16212
|
+
function sectionComplete(artifact, fieldNames) {
|
|
16213
|
+
const schema = record(artifact.inputSchema);
|
|
16214
|
+
const declaredRequiredNames = new Set(
|
|
16215
|
+
[
|
|
16216
|
+
...Array.isArray(schema?.required) ? schema.required : [],
|
|
16217
|
+
...Array.isArray(schema?.["x-granular-artifact-required"]) ? schema["x-granular-artifact-required"] : []
|
|
16218
|
+
].map(text).filter((name) => Boolean(name))
|
|
16219
|
+
);
|
|
16220
|
+
const validation = record(artifact.validation);
|
|
16221
|
+
const invalidFieldNames = new Set(
|
|
16222
|
+
(Array.isArray(validation?.issues) ? validation.issues : []).map(record).filter((issue) => Boolean(issue)).map((issue) => text(issue.path) || text(issue.field)).filter((path) => Boolean(path)).map((path) => path.replace(/^(inputValues|relationships)\./, ""))
|
|
16223
|
+
);
|
|
16224
|
+
const fieldsByName = new Map(
|
|
16225
|
+
artifactFields(artifact).map((field) => [text(field.name), field])
|
|
16226
|
+
);
|
|
16227
|
+
return fieldNames.every((fieldName) => {
|
|
16228
|
+
if (invalidFieldNames.has(fieldName)) return false;
|
|
16229
|
+
const field = fieldsByName.get(fieldName);
|
|
16230
|
+
if (!field) return true;
|
|
16231
|
+
if (fieldProvenanceNeedsReview(artifact, field)) return false;
|
|
16232
|
+
const required = declaredRequiredNames.has(fieldName) || field.required === true || conditionallyRequired(artifact, field);
|
|
16233
|
+
const value = fieldValue(artifact, fieldName);
|
|
16234
|
+
const provenance = artifact.fieldProvenance?.[`${text(field.kind)?.startsWith("relationship") ? "relationships" : "inputValues"}.${fieldName}`];
|
|
16235
|
+
if (provenance?.invalidatedAt) return false;
|
|
16236
|
+
if (text(field.kind)?.startsWith("relationship")) {
|
|
16237
|
+
const resolvers = record(
|
|
16238
|
+
record(artifact.metadata)?.relationshipResolvers
|
|
16239
|
+
);
|
|
16240
|
+
const resolverStatus = text(record(resolvers?.[fieldName])?.status);
|
|
16241
|
+
if (resolverStatus === "missing") return false;
|
|
16242
|
+
if (resolverStatus === "choice" && isMissing(value)) return false;
|
|
16243
|
+
}
|
|
16244
|
+
if (required && isMissing(value)) return false;
|
|
16245
|
+
if (isMissing(value)) return true;
|
|
16246
|
+
return fieldValidationRules(field).every(
|
|
16247
|
+
(rule) => evaluateValidationRule(value, rule).passed
|
|
16248
|
+
);
|
|
16249
|
+
});
|
|
16250
|
+
}
|
|
16251
|
+
function sectionRecap(artifact, fieldNames) {
|
|
16252
|
+
const fields = artifactFields(artifact);
|
|
16253
|
+
const fieldsByName = new Map(
|
|
16254
|
+
fields.map((field) => [text(field.name), field])
|
|
16255
|
+
);
|
|
16256
|
+
const labels = new Map(
|
|
16257
|
+
fields.map((field) => [
|
|
16258
|
+
text(field.name),
|
|
16259
|
+
text(field.label) || humanize(text(field.name) || "detail")
|
|
16260
|
+
])
|
|
16261
|
+
);
|
|
16262
|
+
const items = fieldNames.flatMap((fieldName) => {
|
|
16263
|
+
const value = fieldValue(artifact, fieldName);
|
|
16264
|
+
if (isMissing(value)) return [];
|
|
16265
|
+
const field = fieldsByName.get(fieldName);
|
|
16266
|
+
const relationshipLabels = record(
|
|
16267
|
+
record(artifact.metadata)?.relationshipLabels
|
|
16268
|
+
);
|
|
16269
|
+
const fieldLabels = record(relationshipLabels?.[fieldName]);
|
|
16270
|
+
const resolvers = record(record(artifact.metadata)?.relationshipResolvers);
|
|
16271
|
+
const candidates = Array.isArray(record(resolvers?.[fieldName])?.candidates) ? record(resolvers?.[fieldName])?.candidates : [];
|
|
16272
|
+
const candidateLabel = candidates.map(record).find((candidate) => text(candidate?.id) === value)?.label;
|
|
16273
|
+
const rawOptions = Array.isArray(field?.enumOptions) ? field.enumOptions : Array.isArray(field?.options) ? field.options : [];
|
|
16274
|
+
const enumLabel = rawOptions.map(
|
|
16275
|
+
(option) => typeof option === "string" ? { value: option, label: humanize(option) } : record(option)
|
|
16276
|
+
).find((option) => text(option?.value) === value)?.label;
|
|
16277
|
+
const rendered = typeof value === "string" && text(fieldLabels?.[value]) ? text(fieldLabels?.[value]) : typeof value === "string" && text(candidateLabel) ? text(candidateLabel) : typeof value === "string" && text(enumLabel) ? text(enumLabel) : typeof value === "string" && (text(field?.kind) === "enum" || text(field?.kind)?.startsWith("relationship")) ? humanize(value) : displayValue(value);
|
|
16278
|
+
return [
|
|
16279
|
+
{ label: labels.get(fieldName) || humanize(fieldName), value: rendered }
|
|
16280
|
+
];
|
|
16281
|
+
});
|
|
16282
|
+
return {
|
|
16283
|
+
summary: items.length ? items.map((item) => `${item.label}: ${item.value}`).join(" \xB7 ") : "Completed",
|
|
16284
|
+
items
|
|
16285
|
+
};
|
|
16286
|
+
}
|
|
16287
|
+
function operationPhase(artifact) {
|
|
16288
|
+
const execution = record(record(artifact.metadata)?.execution);
|
|
16289
|
+
const phase = text(execution?.phase);
|
|
16290
|
+
if (artifact.status === "completed") return "completed";
|
|
16291
|
+
if (artifact.status === "failed") return "failed";
|
|
16292
|
+
if (artifact.status === "awaiting_human") return "waiting_for_approval";
|
|
16293
|
+
if (phase === "preparing") return "reviewing";
|
|
16294
|
+
if (phase === "syncing_record") return "synchronizing";
|
|
16295
|
+
if (phase === "verifying_target") return "verifying";
|
|
16296
|
+
if (artifact.status === "running") return "sending";
|
|
16297
|
+
return null;
|
|
16298
|
+
}
|
|
16299
|
+
function operationLabel(artifact) {
|
|
16300
|
+
const ui = record(artifact.inputSchema?.ui);
|
|
16301
|
+
const workflow = record(ui?.workflow);
|
|
16302
|
+
const effect = record(record(artifact.metadata)?.effect);
|
|
16303
|
+
return text(workflow?.operationLabel) || text(ui?.submitLabel) || text(effect?.activityLabel) || text(effect?.label) || artifact.label;
|
|
16304
|
+
}
|
|
16305
|
+
function relationshipValueContainsRecordId(value, recordId) {
|
|
16306
|
+
return Array.isArray(value) ? value.some((item) => item === recordId) : value === recordId;
|
|
16307
|
+
}
|
|
16308
|
+
function relationshipChildLinkPending(parent, fieldName, child) {
|
|
16309
|
+
if (child.status !== "completed") return false;
|
|
16310
|
+
const parentMetadata = record(parent.metadata);
|
|
16311
|
+
const linkMarker = record(
|
|
16312
|
+
record(parentMetadata?.relationshipLinkProvenance)?.[fieldName]
|
|
16313
|
+
);
|
|
16314
|
+
const relationshipValue = parent.relationships?.[fieldName];
|
|
16315
|
+
const childExecution = record(record(child.metadata)?.execution);
|
|
16316
|
+
const childResult = record(childExecution?.result);
|
|
16317
|
+
const childCommit = record(childResult?.commit);
|
|
16318
|
+
const primaryTarget2 = record(childCommit?.primaryTarget);
|
|
16319
|
+
const committedRecordId = text(primaryTarget2?.id);
|
|
16320
|
+
const markerRecordId = text(linkMarker?.recordId);
|
|
16321
|
+
const exactRecordId = markerRecordId || committedRecordId;
|
|
16322
|
+
if (exactRecordId) {
|
|
16323
|
+
return !relationshipValueContainsRecordId(relationshipValue, exactRecordId);
|
|
16324
|
+
}
|
|
16325
|
+
return isMissing(relationshipValue);
|
|
16326
|
+
}
|
|
16327
|
+
function stateTransitionSteps(artifact) {
|
|
16328
|
+
if (artifact.kind !== "state_path") return [];
|
|
16329
|
+
const statePlan = record(record(artifact.metadata)?.statePlan);
|
|
16330
|
+
const plan = record(statePlan?.plan);
|
|
16331
|
+
const transitionMetadata = record(statePlan?.transitionMetadata);
|
|
16332
|
+
const rawSteps = Array.isArray(statePlan?.steps) ? statePlan.steps : Array.isArray(plan?.steps) ? plan.steps : [];
|
|
16333
|
+
return Array.from(rawSteps).flatMap((value, fallbackIndex) => {
|
|
16334
|
+
const step = record(value);
|
|
16335
|
+
const transition = text(step?.transition);
|
|
16336
|
+
if (!step || !transition) return [];
|
|
16337
|
+
const transitionDescription = record(transitionMetadata?.[transition]);
|
|
16338
|
+
const userVisible = typeof step.userVisible === "boolean" ? step.userVisible : typeof transitionDescription?.userVisible === "boolean" ? transitionDescription.userVisible : true;
|
|
16339
|
+
const blockers = Array.isArray(step.blockers) ? step.blockers.filter(
|
|
16340
|
+
(blocker) => Boolean(record(blocker))
|
|
16341
|
+
) : [];
|
|
16342
|
+
return [
|
|
16343
|
+
{
|
|
16344
|
+
index: typeof step.index === "number" ? step.index : fallbackIndex,
|
|
16345
|
+
transition,
|
|
16346
|
+
label: text(step.label) || humanize(transition),
|
|
16347
|
+
description: text(step.description) || text(record(step.expectedOutcome)?.summary) || null,
|
|
16348
|
+
status: text(step.status) || "pending",
|
|
16349
|
+
// State plans may contain bookkeeping transitions that are necessary
|
|
16350
|
+
// for execution/audit but are already represented by an actionable
|
|
16351
|
+
// form or by the single final operation. Producers must opt those
|
|
16352
|
+
// transitions out explicitly; the client never infers this from a
|
|
16353
|
+
// label or transition name.
|
|
16354
|
+
userVisible,
|
|
16355
|
+
blockers
|
|
16356
|
+
}
|
|
16357
|
+
];
|
|
16358
|
+
});
|
|
16359
|
+
}
|
|
16360
|
+
function stateTransitionGroupLabel(artifact) {
|
|
16361
|
+
if (artifact.kind !== "state_path") return null;
|
|
16362
|
+
const statePlan = record(record(artifact.metadata)?.statePlan);
|
|
16363
|
+
const classLabel = text(statePlan?.classLabel);
|
|
16364
|
+
return classLabel ? `${classLabel} workflow` : null;
|
|
16365
|
+
}
|
|
16366
|
+
function workflowGroupStatus(nodes) {
|
|
16367
|
+
const active = nodes.find(
|
|
16368
|
+
(node) => ["current", "needs_input", "working", "blocked", "failed"].includes(
|
|
16369
|
+
node.status
|
|
16370
|
+
)
|
|
16371
|
+
);
|
|
16372
|
+
if (active) return active.status;
|
|
16373
|
+
if (nodes.some((node) => node.status === "upcoming")) return "upcoming";
|
|
16374
|
+
const lastTerminal = [...nodes].reverse().find((node) => isTerminalWorkflowStepStatus(node.status));
|
|
16375
|
+
return lastTerminal?.status || nodes[0]?.status || "upcoming";
|
|
16376
|
+
}
|
|
16377
|
+
function transitionNodeStatus(artifact, step) {
|
|
16378
|
+
const statePlan = record(record(artifact.metadata)?.statePlan);
|
|
16379
|
+
const currentStep = record(statePlan?.currentStep);
|
|
16380
|
+
const execution = record(record(artifact.metadata)?.execution);
|
|
16381
|
+
const currentTransition = text(execution?.currentTransition);
|
|
16382
|
+
const completedTransitions = new Set(
|
|
16383
|
+
Array.isArray(execution?.completedTransitions) ? execution.completedTransitions.map(text).filter((value) => Boolean(value)) : []
|
|
16384
|
+
);
|
|
16385
|
+
const isCurrent = currentTransition === step.transition || currentStep?.index === step.index;
|
|
16386
|
+
if (completedTransitions.has(step.transition) || step.status === "completed") {
|
|
16387
|
+
return "completed";
|
|
16388
|
+
}
|
|
16389
|
+
if (isCurrent && artifact.status === "failed") return "failed";
|
|
16390
|
+
if (isCurrent && artifact.status === "canceled") return "canceled";
|
|
16391
|
+
if (isCurrent && artifact.status === "running") return "working";
|
|
16392
|
+
if (step.status === "failed") return "failed";
|
|
16393
|
+
if (artifact.status === "canceled") return "canceled";
|
|
16394
|
+
if (step.status === "blocked") return "blocked";
|
|
16395
|
+
if (step.status === "needs_other_user" || step.status === "needs_input") {
|
|
16396
|
+
return "needs_input";
|
|
16397
|
+
}
|
|
16398
|
+
if (isCurrent || step.status === "ready" || step.status === "current") {
|
|
16399
|
+
return "current";
|
|
16400
|
+
}
|
|
16401
|
+
if (step.status === "skipped") return "skipped";
|
|
16402
|
+
if (step.status === "canceled") return "canceled";
|
|
16403
|
+
return "upcoming";
|
|
16404
|
+
}
|
|
16405
|
+
var TERMINAL_WORKFLOW_STEP_STATUSES = /* @__PURE__ */ new Set([
|
|
16406
|
+
"completed",
|
|
16407
|
+
"skipped",
|
|
16408
|
+
"canceled"
|
|
16409
|
+
]);
|
|
16410
|
+
function isArtifactWorkflowNodeTerminal(nodeOrStatus) {
|
|
16411
|
+
const status = typeof nodeOrStatus === "string" ? nodeOrStatus : nodeOrStatus.status;
|
|
16412
|
+
return TERMINAL_WORKFLOW_STEP_STATUSES.has(status);
|
|
16413
|
+
}
|
|
16414
|
+
function isTerminalWorkflowStepStatus(status) {
|
|
16415
|
+
return isArtifactWorkflowNodeTerminal(status);
|
|
16416
|
+
}
|
|
16417
|
+
function firstTransitionStatus(artifact, status) {
|
|
16418
|
+
if (status !== "upcoming") return status;
|
|
16419
|
+
if (artifact.status === "canceled") return "canceled";
|
|
16420
|
+
if (artifact.status === "failed") return "failed";
|
|
16421
|
+
if (artifact.status === "blocked" || artifact.status === "stale" || artifact.status === "partially_completed") {
|
|
16422
|
+
return "blocked";
|
|
16423
|
+
}
|
|
16424
|
+
if (artifact.status === "running") return "working";
|
|
16425
|
+
if (artifact.status === "awaiting_human") return "needs_input";
|
|
16426
|
+
return "current";
|
|
16427
|
+
}
|
|
16428
|
+
function operationStatus(artifact, transitionStatuses = []) {
|
|
16429
|
+
if (artifact.status === "completed") {
|
|
16430
|
+
if (transitionStatuses.some(
|
|
16431
|
+
(status) => !TERMINAL_WORKFLOW_STEP_STATUSES.has(status)
|
|
16432
|
+
)) {
|
|
16433
|
+
if (transitionStatuses.includes("failed")) return "failed";
|
|
16434
|
+
if (transitionStatuses.includes("needs_input")) return "needs_input";
|
|
16435
|
+
if (transitionStatuses.includes("working")) return "working";
|
|
16436
|
+
if (transitionStatuses.includes("current")) return "current";
|
|
16437
|
+
return "blocked";
|
|
16438
|
+
}
|
|
16439
|
+
return "completed";
|
|
16440
|
+
}
|
|
16441
|
+
if (artifact.status === "failed") return "failed";
|
|
16442
|
+
if (artifact.status === "canceled") return "canceled";
|
|
16443
|
+
if (artifact.status === "partially_completed") return "blocked";
|
|
16444
|
+
if (artifact.status === "blocked" || artifact.status === "stale")
|
|
16445
|
+
return "blocked";
|
|
16446
|
+
if (artifact.status === "running") return "working";
|
|
16447
|
+
if (artifact.status === "awaiting_human") return "needs_input";
|
|
16448
|
+
if (artifact.status === "ready") return "current";
|
|
16449
|
+
return "upcoming";
|
|
16450
|
+
}
|
|
16451
|
+
function semanticWorkflow(workflow) {
|
|
16452
|
+
const { revision: _revision, updatedAt: _updatedAt, ...semantic } = workflow;
|
|
16453
|
+
return semantic;
|
|
16454
|
+
}
|
|
16455
|
+
function isNavigationOnlyOperation(workflow, node) {
|
|
16456
|
+
const hasExplicitTransitionLeaf = getArtifactWorkflowNodes(workflow).some(
|
|
16457
|
+
(candidate) => candidate.childIds.length === 0 && candidate.kind === "transition"
|
|
16458
|
+
);
|
|
16459
|
+
return hasExplicitTransitionLeaf && node.childIds.length === 0 && node.kind === "operation" && // A terminal operation is redundant once authored state-path leaves are
|
|
16460
|
+
// available. While it is still delivering/synchronizing, however, it is
|
|
16461
|
+
// the only honest representation of the work still in progress.
|
|
16462
|
+
isArtifactWorkflowNodeTerminal(node);
|
|
16463
|
+
}
|
|
16464
|
+
function getArtifactWorkflowNavigationLeaves(workflow) {
|
|
16465
|
+
return getArtifactWorkflowNodes(workflow).filter(
|
|
16466
|
+
(node) => isArtifactWorkflowNodeNavigableLeaf(workflow, node)
|
|
16467
|
+
);
|
|
16468
|
+
}
|
|
16469
|
+
function isArtifactWorkflowNodeNavigableLeaf(workflow, node) {
|
|
16470
|
+
return node.childIds.length === 0 && !isNavigationOnlyOperation(workflow, node);
|
|
16471
|
+
}
|
|
16472
|
+
function isArtifactWorkflowNodeActionable(node) {
|
|
16473
|
+
return node.availability === "available" && ["current", "needs_input", "working", "blocked", "failed"].includes(
|
|
16474
|
+
node.status
|
|
16475
|
+
);
|
|
16476
|
+
}
|
|
16477
|
+
function getArtifactWorkflowNavigationTarget(workflow) {
|
|
16478
|
+
const leaves = getArtifactWorkflowNavigationLeaves(workflow);
|
|
16479
|
+
return leaves.find(
|
|
16480
|
+
(node) => !isArtifactWorkflowNodeTerminal(node) && isArtifactWorkflowNodeActionable(node)
|
|
16481
|
+
) || leaves.at(-1) || null;
|
|
16482
|
+
}
|
|
16483
|
+
function projectArtifactWorkflow(artifact, allArtifacts = [artifact], now = artifact.updatedAt) {
|
|
16484
|
+
const nodesById = {};
|
|
16485
|
+
const rootNodeIds = [];
|
|
16486
|
+
const sections = declaredSections(artifact);
|
|
16487
|
+
const children = new Map(
|
|
16488
|
+
allArtifacts.filter((candidate2) => candidate2.parentArtifactId === artifact.artifactId).map((candidate2) => [candidate2.artifactId, candidate2])
|
|
16489
|
+
);
|
|
16490
|
+
const relationshipChildren = record(
|
|
16491
|
+
record(artifact.metadata)?.relationshipChildren
|
|
16492
|
+
);
|
|
16493
|
+
const operationId2 = `${artifact.artifactId}:operation`;
|
|
16494
|
+
const validationId = `${artifact.artifactId}:validation`;
|
|
16495
|
+
const sectionNodeIds = [];
|
|
16496
|
+
let currentNodeId = null;
|
|
16497
|
+
let foundIncompleteSection = false;
|
|
16498
|
+
let foundActiveLeaf = false;
|
|
16499
|
+
let transitionHasActiveStep = false;
|
|
16500
|
+
let hasVisibleTransition = false;
|
|
16501
|
+
const projectedTransitionStatuses = [];
|
|
16502
|
+
const transitionNodeIds = [];
|
|
16503
|
+
const transitionGroupLabel = stateTransitionGroupLabel(artifact);
|
|
16504
|
+
const transitionGroupId = `${artifact.artifactId}:transition-group`;
|
|
16505
|
+
for (const section of sections) {
|
|
16506
|
+
const id = `${artifact.artifactId}:section:${stableToken(section.id)}`;
|
|
16507
|
+
const complete = sectionComplete(artifact, section.fieldNames);
|
|
16508
|
+
const blockedByEarlierSection = foundIncompleteSection;
|
|
16509
|
+
const blockedByEarlierAction = foundIncompleteSection || foundActiveLeaf;
|
|
16510
|
+
const relationshipFields = artifactFields(artifact).filter(
|
|
16511
|
+
(field) => section.fieldNames.includes(text(field.name) || "") && ["relationshipOne", "relationshipMany"].includes(
|
|
16512
|
+
text(field.kind) || ""
|
|
16513
|
+
)
|
|
16514
|
+
);
|
|
16515
|
+
const relationshipField = relationshipFields[0];
|
|
16516
|
+
const relationshipChildrenInSection = relationshipFields.flatMap(
|
|
16517
|
+
(field) => {
|
|
16518
|
+
const relationshipName = text(field.name);
|
|
16519
|
+
const childArtifactId = relationshipName ? text(relationshipChildren?.[relationshipName]) : null;
|
|
16520
|
+
const child = childArtifactId ? children.get(childArtifactId) : null;
|
|
16521
|
+
if (!relationshipName || !child) return [];
|
|
16522
|
+
return [
|
|
16523
|
+
{
|
|
16524
|
+
relationshipName,
|
|
16525
|
+
child,
|
|
16526
|
+
childLinkPending: relationshipChildLinkPending(
|
|
16527
|
+
artifact,
|
|
16528
|
+
relationshipName,
|
|
16529
|
+
child
|
|
16530
|
+
),
|
|
16531
|
+
childId: `${artifact.artifactId}:child:${stableToken(child.artifactId)}`
|
|
16532
|
+
}
|
|
16533
|
+
];
|
|
16534
|
+
}
|
|
16535
|
+
);
|
|
16536
|
+
const relationshipChildFieldNames = new Set(
|
|
16537
|
+
relationshipChildrenInSection.map(
|
|
16538
|
+
({ relationshipName }) => relationshipName
|
|
16539
|
+
)
|
|
16540
|
+
);
|
|
16541
|
+
const residualFieldNames = section.fieldNames.filter(
|
|
16542
|
+
(fieldName) => !relationshipChildFieldNames.has(fieldName)
|
|
16543
|
+
);
|
|
16544
|
+
const residualComplete = sectionComplete(artifact, residualFieldNames);
|
|
16545
|
+
const residualId = `${id}:details`;
|
|
16546
|
+
const childActive = relationshipChildrenInSection.some(
|
|
16547
|
+
({ child, childLinkPending }) => childLinkPending || !TERMINAL_ARTIFACT_STATUSES.has(child.status)
|
|
16548
|
+
);
|
|
16549
|
+
const childIsWorking = relationshipChildrenInSection.some(
|
|
16550
|
+
({ child, childLinkPending }) => childLinkPending || child.status === "running"
|
|
16551
|
+
);
|
|
16552
|
+
const sectionStatus = complete && !blockedByEarlierSection ? "completed" : blockedByEarlierAction ? "upcoming" : childActive ? childIsWorking ? "working" : "needs_input" : !TERMINAL_ARTIFACT_STATUSES.has(artifact.status) ? "needs_input" : "upcoming";
|
|
16553
|
+
if (!complete) foundIncompleteSection = true;
|
|
16554
|
+
nodesById[id] = {
|
|
16555
|
+
id,
|
|
16556
|
+
artifactId: artifact.artifactId,
|
|
16557
|
+
parentId: operationId2,
|
|
16558
|
+
childIds: [
|
|
16559
|
+
...relationshipChildrenInSection.map(({ childId }) => childId),
|
|
16560
|
+
...relationshipChildrenInSection.length > 0 && residualFieldNames.length > 0 && !residualComplete ? [residualId] : []
|
|
16561
|
+
],
|
|
16562
|
+
kind: relationshipChildrenInSection.length > 0 ? "group" : relationshipField ? "relationship" : "input",
|
|
16563
|
+
label: section.label,
|
|
16564
|
+
description: section.description,
|
|
16565
|
+
status: sectionStatus,
|
|
16566
|
+
availability: sectionStatus === "completed" ? "readonly" : sectionStatus === "upcoming" ? "unavailable" : "available",
|
|
16567
|
+
fieldNames: relationshipChildrenInSection.length > 0 ? void 0 : section.fieldNames,
|
|
16568
|
+
recap: sectionStatus === "completed" ? sectionRecap(artifact, section.fieldNames) : null,
|
|
16569
|
+
completedAt: sectionStatus === "completed" ? artifact.updatedAt : null
|
|
16570
|
+
};
|
|
16571
|
+
sectionNodeIds.push(id);
|
|
16572
|
+
const childStatuses = [];
|
|
16573
|
+
for (const {
|
|
16574
|
+
child,
|
|
16575
|
+
childId,
|
|
16576
|
+
childLinkPending
|
|
16577
|
+
} of relationshipChildrenInSection) {
|
|
16578
|
+
const authoritativeChildStatus = childLinkPending ? "working" : child.status === "completed" ? "completed" : child.status === "failed" ? "failed" : child.status === "canceled" ? "canceled" : child.status === "running" ? "working" : child.status === "blocked" || child.status === "stale" ? "blocked" : child.status === "ready" ? "current" : "needs_input";
|
|
16579
|
+
const childStatus = blockedByEarlierSection ? "upcoming" : foundActiveLeaf && !isTerminalWorkflowStepStatus(authoritativeChildStatus) ? "upcoming" : authoritativeChildStatus;
|
|
16580
|
+
childStatuses.push(childStatus);
|
|
16581
|
+
nodesById[childId] = {
|
|
16582
|
+
id: childId,
|
|
16583
|
+
artifactId: artifact.artifactId,
|
|
16584
|
+
parentId: id,
|
|
16585
|
+
childIds: [],
|
|
16586
|
+
kind: "child_artifact",
|
|
16587
|
+
label: child.label,
|
|
16588
|
+
description: child.description,
|
|
16589
|
+
status: childStatus,
|
|
16590
|
+
availability: childStatus === "completed" ? "readonly" : childStatus === "upcoming" ? "unavailable" : "available",
|
|
16591
|
+
childArtifactId: child.artifactId,
|
|
16592
|
+
recap: childStatus === "completed" ? { summary: `${child.label} completed`, items: [] } : null,
|
|
16593
|
+
attention: childStatus === "failed" ? { title: `${child.label} failed`, retryable: true } : null,
|
|
16594
|
+
startedAt: child.executedAt || null,
|
|
16595
|
+
completedAt: childLinkPending ? null : child.completedAt || null
|
|
16596
|
+
};
|
|
16597
|
+
if (!blockedByEarlierSection && !isArtifactWorkflowNodeTerminal(childStatus)) {
|
|
16598
|
+
if (!foundActiveLeaf) {
|
|
16599
|
+
currentNodeId = childId;
|
|
16600
|
+
foundActiveLeaf = true;
|
|
16601
|
+
}
|
|
16602
|
+
}
|
|
16603
|
+
}
|
|
16604
|
+
if (relationshipChildrenInSection.length > 0 && residualFieldNames.length > 0 && !residualComplete) {
|
|
16605
|
+
const residualStatus = residualComplete ? "completed" : blockedByEarlierSection || foundActiveLeaf ? "upcoming" : !TERMINAL_ARTIFACT_STATUSES.has(artifact.status) ? "needs_input" : "upcoming";
|
|
16606
|
+
const residualFields = artifactFields(artifact).filter(
|
|
16607
|
+
(field) => residualFieldNames.includes(text(field.name) || "")
|
|
16608
|
+
);
|
|
16609
|
+
const residualLabel = residualFields.length === 1 ? text(residualFields[0]?.label) || section.label : "Details";
|
|
16610
|
+
childStatuses.push(residualStatus);
|
|
16611
|
+
nodesById[residualId] = {
|
|
16612
|
+
id: residualId,
|
|
16613
|
+
artifactId: artifact.artifactId,
|
|
16614
|
+
parentId: id,
|
|
16615
|
+
childIds: [],
|
|
16616
|
+
kind: residualFields.some(
|
|
16617
|
+
(field) => ["relationshipOne", "relationshipMany"].includes(
|
|
16618
|
+
text(field.kind) || ""
|
|
16619
|
+
)
|
|
16620
|
+
) ? "relationship" : "input",
|
|
16621
|
+
label: residualLabel,
|
|
16622
|
+
description: section.description,
|
|
16623
|
+
status: residualStatus,
|
|
16624
|
+
availability: residualStatus === "completed" ? "readonly" : residualStatus === "upcoming" ? "unavailable" : "available",
|
|
16625
|
+
fieldNames: residualFieldNames,
|
|
16626
|
+
recap: residualComplete ? sectionRecap(artifact, residualFieldNames) : null,
|
|
16627
|
+
completedAt: residualComplete ? artifact.updatedAt : null
|
|
16628
|
+
};
|
|
16629
|
+
if (!foundActiveLeaf && ["needs_input", "working", "blocked", "failed"].includes(residualStatus)) {
|
|
16630
|
+
currentNodeId = residualId;
|
|
16631
|
+
foundActiveLeaf = true;
|
|
16632
|
+
}
|
|
16633
|
+
}
|
|
16634
|
+
if (childStatuses.length > 0) {
|
|
16635
|
+
const representativeChildStatus = childStatuses.find(
|
|
16636
|
+
(status) => !isArtifactWorkflowNodeTerminal(status)
|
|
16637
|
+
) ?? (complete ? childStatuses.at(-1) : null);
|
|
16638
|
+
if (representativeChildStatus) {
|
|
16639
|
+
nodesById[id].status = representativeChildStatus;
|
|
16640
|
+
}
|
|
16641
|
+
nodesById[id].availability = "readonly";
|
|
16642
|
+
}
|
|
16643
|
+
if (!foundActiveLeaf && relationshipChildrenInSection.length === 0 && ["needs_input", "working", "blocked", "failed"].includes(sectionStatus)) {
|
|
16644
|
+
currentNodeId = id;
|
|
16645
|
+
foundActiveLeaf = true;
|
|
16646
|
+
}
|
|
16647
|
+
}
|
|
16648
|
+
const transitionsAreGatedByForm = (foundIncompleteSection || foundActiveLeaf) && !TERMINAL_ARTIFACT_STATUSES.has(artifact.status);
|
|
16649
|
+
for (const step of stateTransitionSteps(artifact)) {
|
|
16650
|
+
if (!step.userVisible) continue;
|
|
16651
|
+
hasVisibleTransition = true;
|
|
16652
|
+
const id = `${artifact.artifactId}:transition:${stableToken(step.transition)}`;
|
|
16653
|
+
const rawStatus = transitionNodeStatus(artifact, step);
|
|
16654
|
+
const status = isTerminalWorkflowStepStatus(rawStatus) ? rawStatus : transitionsAreGatedByForm || transitionHasActiveStep ? "upcoming" : firstTransitionStatus(artifact, rawStatus);
|
|
16655
|
+
projectedTransitionStatuses.push(status);
|
|
16656
|
+
if (!isTerminalWorkflowStepStatus(status)) {
|
|
16657
|
+
transitionHasActiveStep = true;
|
|
16658
|
+
}
|
|
16659
|
+
const blocker = step.blockers[0];
|
|
16660
|
+
nodesById[id] = {
|
|
16661
|
+
id,
|
|
16662
|
+
artifactId: artifact.artifactId,
|
|
16663
|
+
parentId: transitionGroupLabel ? transitionGroupId : operationId2,
|
|
16664
|
+
childIds: [],
|
|
16665
|
+
kind: "transition",
|
|
16666
|
+
label: step.label,
|
|
16667
|
+
description: step.description,
|
|
16668
|
+
status,
|
|
16669
|
+
availability: status === "completed" ? "readonly" : status === "upcoming" ? "unavailable" : "available",
|
|
16670
|
+
operationPhase: step.status === "needs_other_user" ? "waiting_for_approval" : status === "working" ? operationPhase(artifact) : null,
|
|
16671
|
+
operationDetail: text(record(record(artifact.metadata)?.execution)?.message) || null,
|
|
16672
|
+
recap: status === "completed" ? { summary: `${step.label} completed`, items: [] } : null,
|
|
16673
|
+
attention: status === "failed" || status === "blocked" ? {
|
|
16674
|
+
title: text(blocker?.label) || `${step.label} needs attention`,
|
|
16675
|
+
detail: text(blocker?.detail) || text(blocker?.description) || null,
|
|
16676
|
+
retryable: status === "failed"
|
|
16677
|
+
} : null,
|
|
16678
|
+
startedAt: status === "working" ? artifact.executedAt || artifact.updatedAt : null,
|
|
16679
|
+
completedAt: status === "completed" ? artifact.updatedAt : null
|
|
16680
|
+
};
|
|
16681
|
+
transitionNodeIds.push(id);
|
|
16682
|
+
if (!currentNodeId && !["completed", "upcoming", "skipped", "canceled"].includes(status)) {
|
|
16683
|
+
currentNodeId = id;
|
|
16684
|
+
}
|
|
16685
|
+
}
|
|
16686
|
+
if (transitionNodeIds.length) {
|
|
16687
|
+
const transitionNodes = transitionNodeIds.map((id) => nodesById[id]).filter((node) => Boolean(node));
|
|
16688
|
+
if (transitionGroupLabel) {
|
|
16689
|
+
const groupStatus = workflowGroupStatus(transitionNodes);
|
|
16690
|
+
const activeTransition = transitionNodes.find(
|
|
16691
|
+
(node) => ["current", "needs_input", "working", "blocked", "failed"].includes(
|
|
16692
|
+
node.status
|
|
16693
|
+
)
|
|
16694
|
+
);
|
|
16695
|
+
nodesById[transitionGroupId] = {
|
|
16696
|
+
id: transitionGroupId,
|
|
16697
|
+
artifactId: artifact.artifactId,
|
|
16698
|
+
parentId: operationId2,
|
|
16699
|
+
childIds: transitionNodeIds,
|
|
16700
|
+
kind: "group",
|
|
16701
|
+
label: transitionGroupLabel,
|
|
16702
|
+
description: null,
|
|
16703
|
+
status: groupStatus,
|
|
16704
|
+
availability: groupStatus === "upcoming" ? "unavailable" : groupStatus === "completed" ? "readonly" : "available",
|
|
16705
|
+
operationPhase: activeTransition?.operationPhase || null,
|
|
16706
|
+
startedAt: activeTransition?.startedAt || null,
|
|
16707
|
+
completedAt: groupStatus === "completed" ? transitionNodes.at(-1)?.completedAt || artifact.updatedAt : null
|
|
16708
|
+
};
|
|
16709
|
+
sectionNodeIds.push(transitionGroupId);
|
|
16710
|
+
} else {
|
|
16711
|
+
sectionNodeIds.push(...transitionNodeIds);
|
|
16712
|
+
}
|
|
16713
|
+
}
|
|
16714
|
+
const projectedOperationStatus = operationStatus(
|
|
16715
|
+
artifact,
|
|
16716
|
+
projectedTransitionStatuses
|
|
16717
|
+
);
|
|
16718
|
+
if (projectedOperationStatus === "completed") {
|
|
16719
|
+
for (const transitionNodeId of transitionNodeIds) {
|
|
16720
|
+
const transition = nodesById[transitionNodeId];
|
|
16721
|
+
if (transition?.kind === "transition" && transition.status === "completed") {
|
|
16722
|
+
transition.completionState = "graph_propagated";
|
|
16723
|
+
}
|
|
16724
|
+
}
|
|
16725
|
+
}
|
|
16726
|
+
const phase = operationPhase(artifact);
|
|
16727
|
+
const activeDescendantStatus = currentNodeId ? nodesById[currentNodeId]?.status : null;
|
|
16728
|
+
const finalStatus = activeDescendantStatus && !isTerminalWorkflowStepStatus(activeDescendantStatus) ? activeDescendantStatus : projectedOperationStatus;
|
|
16729
|
+
const validationStatus = currentNodeId ? "upcoming" : projectedOperationStatus === "upcoming" ? "current" : projectedOperationStatus;
|
|
16730
|
+
nodesById[validationId] = {
|
|
16731
|
+
id: validationId,
|
|
16732
|
+
artifactId: artifact.artifactId,
|
|
16733
|
+
parentId: operationId2,
|
|
16734
|
+
childIds: [],
|
|
16735
|
+
kind: "operation",
|
|
16736
|
+
label: operationLabel(artifact),
|
|
16737
|
+
description: artifact.description || null,
|
|
16738
|
+
status: validationStatus,
|
|
16739
|
+
availability: validationStatus === "upcoming" ? "unavailable" : validationStatus === "completed" ? "readonly" : "available",
|
|
16740
|
+
operationPhase: phase,
|
|
16741
|
+
completionState: projectedOperationStatus === "completed" ? "graph_propagated" : phase === "synchronizing" || phase === "verifying" ? "effect_applied" : null,
|
|
16742
|
+
operationDetail: text(
|
|
16743
|
+
record(record(artifact.metadata)?.execution)?.message
|
|
16744
|
+
),
|
|
16745
|
+
recap: validationStatus === "completed" ? { summary: `${artifact.label} completed`, items: [] } : null,
|
|
16746
|
+
attention: validationStatus === "failed" ? { title: `${artifact.label} failed`, retryable: true } : validationStatus === "blocked" ? {
|
|
16747
|
+
title: `${artifact.label} needs attention`,
|
|
16748
|
+
retryable: artifact.status === "stale"
|
|
16749
|
+
} : null,
|
|
16750
|
+
startedAt: artifact.executedAt || null,
|
|
16751
|
+
completedAt: artifact.completedAt || null
|
|
16752
|
+
};
|
|
16753
|
+
sectionNodeIds.push(validationId);
|
|
16754
|
+
if (!currentNodeId && !hasVisibleTransition && !["completed", "canceled"].includes(finalStatus)) {
|
|
16755
|
+
currentNodeId = validationId;
|
|
16756
|
+
}
|
|
16757
|
+
const rootStatus = currentNodeId === validationId ? nodesById[validationId].status : finalStatus;
|
|
16758
|
+
nodesById[operationId2] = {
|
|
16759
|
+
id: operationId2,
|
|
16760
|
+
artifactId: artifact.artifactId,
|
|
16761
|
+
parentId: null,
|
|
16762
|
+
childIds: sectionNodeIds,
|
|
16763
|
+
kind: "group",
|
|
16764
|
+
label: artifact.label,
|
|
16765
|
+
description: artifact.description || null,
|
|
16766
|
+
status: rootStatus,
|
|
16767
|
+
availability: rootStatus === "upcoming" ? "unavailable" : rootStatus === "completed" ? "readonly" : "available",
|
|
16768
|
+
operationPhase: null,
|
|
16769
|
+
startedAt: artifact.executedAt || null,
|
|
16770
|
+
completedAt: artifact.completedAt || null
|
|
16771
|
+
};
|
|
16772
|
+
rootNodeIds.push(operationId2);
|
|
16773
|
+
const candidateBeforeTarget = {
|
|
16774
|
+
schemaVersion: 1,
|
|
16775
|
+
revision: artifact.workflow?.revision || 1,
|
|
16776
|
+
artifactId: artifact.artifactId,
|
|
16777
|
+
rootNodeIds,
|
|
16778
|
+
nodesById,
|
|
16779
|
+
currentNodeId: null,
|
|
16780
|
+
updatedAt: now
|
|
16781
|
+
};
|
|
16782
|
+
currentNodeId = getArtifactWorkflowNavigationTarget(candidateBeforeTarget)?.id || null;
|
|
16783
|
+
const automaticTarget = currentNodeId ? nodesById[currentNodeId] || null : null;
|
|
16784
|
+
const canonicalRootStatus = automaticTarget && !isArtifactWorkflowNodeTerminal(automaticTarget) ? automaticTarget.status : projectedOperationStatus;
|
|
16785
|
+
nodesById[operationId2].status = canonicalRootStatus;
|
|
16786
|
+
nodesById[operationId2].availability = canonicalRootStatus === "upcoming" ? "unavailable" : canonicalRootStatus === "completed" ? "readonly" : "available";
|
|
16787
|
+
const candidate = {
|
|
16788
|
+
...candidateBeforeTarget,
|
|
16789
|
+
currentNodeId
|
|
16790
|
+
};
|
|
16791
|
+
if (artifact.workflow && JSON.stringify(semanticWorkflow(artifact.workflow)) !== JSON.stringify(semanticWorkflow(candidate))) {
|
|
16792
|
+
candidate.revision = artifact.workflow.revision + 1;
|
|
16793
|
+
} else if (artifact.workflow) {
|
|
16794
|
+
candidate.updatedAt = artifact.workflow.updatedAt;
|
|
16795
|
+
}
|
|
16796
|
+
return candidate;
|
|
16797
|
+
}
|
|
16798
|
+
function getCurrentArtifactWorkflowNode(workflow) {
|
|
16799
|
+
return workflow.currentNodeId ? workflow.nodesById[workflow.currentNodeId] || null : null;
|
|
16800
|
+
}
|
|
16801
|
+
function getArtifactWorkflowNodes(workflow) {
|
|
16802
|
+
const visit = (id) => {
|
|
16803
|
+
const node = workflow.nodesById[id];
|
|
16804
|
+
return node ? [node, ...node.childIds.flatMap(visit)] : [];
|
|
16805
|
+
};
|
|
16806
|
+
return workflow.rootNodeIds.flatMap(visit);
|
|
16807
|
+
}
|
|
16808
|
+
function canInspectArtifactWorkflowNode(node) {
|
|
16809
|
+
return node.childIds.length === 0 && node.availability !== "unavailable";
|
|
16810
|
+
}
|
|
16811
|
+
function assertArtifactWorkflow(workflow) {
|
|
16812
|
+
if (workflow.schemaVersion !== 1)
|
|
16813
|
+
throw new Error("Unsupported artifact workflow schema");
|
|
16814
|
+
if (!Number.isSafeInteger(workflow.revision) || workflow.revision < 1) {
|
|
16815
|
+
throw new Error("Artifact workflow revision must be a positive integer");
|
|
16816
|
+
}
|
|
16817
|
+
const visited = /* @__PURE__ */ new Set();
|
|
16818
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
16819
|
+
const nodes = [];
|
|
16820
|
+
const visit = (id, expectedParentId) => {
|
|
16821
|
+
const node = workflow.nodesById[id];
|
|
16822
|
+
if (!node) throw new Error(`Artifact workflow node ${id} does not exist`);
|
|
16823
|
+
if (visiting.has(id)) throw new Error("Artifact workflow contains a cycle");
|
|
16824
|
+
if (visited.has(id))
|
|
16825
|
+
throw new Error("Artifact workflow contains a duplicate node reference");
|
|
16826
|
+
if (node.parentId !== expectedParentId) {
|
|
16827
|
+
throw new Error(`Artifact workflow node ${id} has an invalid parent`);
|
|
16828
|
+
}
|
|
16829
|
+
visiting.add(id);
|
|
16830
|
+
nodes.push(node);
|
|
16831
|
+
node.childIds.forEach((childId) => visit(childId, id));
|
|
16832
|
+
visiting.delete(id);
|
|
16833
|
+
visited.add(id);
|
|
16834
|
+
};
|
|
16835
|
+
workflow.rootNodeIds.forEach((id) => visit(id, null));
|
|
16836
|
+
if (visited.size !== Object.keys(workflow.nodesById).length) {
|
|
16837
|
+
throw new Error("Artifact workflow contains unreachable nodes");
|
|
16838
|
+
}
|
|
16839
|
+
if (workflow.currentNodeId && !workflow.nodesById[workflow.currentNodeId]) {
|
|
16840
|
+
throw new Error("Artifact workflow current node does not exist");
|
|
16841
|
+
}
|
|
16842
|
+
const currentNode = workflow.currentNodeId ? workflow.nodesById[workflow.currentNodeId] : null;
|
|
16843
|
+
if (currentNode && currentNode.childIds.length > 0) {
|
|
16844
|
+
throw new Error("Artifact workflow current node must be actionable leaf");
|
|
16845
|
+
}
|
|
16846
|
+
const actionable = nodes.filter(
|
|
16847
|
+
(node) => isArtifactWorkflowNodeNavigableLeaf(workflow, node) && isArtifactWorkflowNodeActionable(node)
|
|
16848
|
+
);
|
|
16849
|
+
if (actionable.length > 1)
|
|
16850
|
+
throw new Error("Artifact workflow has multiple current nodes");
|
|
16851
|
+
if (actionable.length === 1 && actionable[0].id !== workflow.currentNodeId) {
|
|
16852
|
+
throw new Error("Artifact workflow current node does not own its action");
|
|
16853
|
+
}
|
|
16854
|
+
if (workflow.currentNodeId && !actionable.length && !isArtifactWorkflowNodeTerminal(currentNode)) {
|
|
16855
|
+
throw new Error("Artifact workflow current node is not actionable");
|
|
16856
|
+
}
|
|
16857
|
+
}
|
|
16858
|
+
function requireArtifactWorkflow(artifact) {
|
|
16859
|
+
if (!artifact.workflow) {
|
|
16860
|
+
throw new Error(
|
|
16861
|
+
`Artifact ${artifact.artifactId} has no canonical workflow`
|
|
16862
|
+
);
|
|
16863
|
+
}
|
|
16864
|
+
assertArtifactWorkflow(artifact.workflow);
|
|
16865
|
+
if (artifact.workflow.artifactId !== artifact.artifactId) {
|
|
16866
|
+
throw new Error("Artifact workflow belongs to a different artifact");
|
|
16867
|
+
}
|
|
16868
|
+
return artifact;
|
|
16869
|
+
}
|
|
16870
|
+
function requireArtifactWorkflowResult(result) {
|
|
16871
|
+
requireArtifactWorkflow(result.artifact);
|
|
16872
|
+
return result;
|
|
16873
|
+
}
|
|
16874
|
+
|
|
15965
16875
|
// src/client.ts
|
|
15966
16876
|
var DEFAULT_CONVERSATION_SESSION_LIST_LIMIT = 100;
|
|
15967
16877
|
var MAX_CONVERSATION_SESSION_LIST_LIMIT = 500;
|
|
@@ -16115,17 +17025,17 @@ function planRecordObjectsChunks(records, batchSize) {
|
|
|
16115
17025
|
}
|
|
16116
17026
|
return plans;
|
|
16117
17027
|
}
|
|
16118
|
-
function preserveRecordObjectRealId(
|
|
16119
|
-
const realId =
|
|
17028
|
+
function preserveRecordObjectRealId(record2) {
|
|
17029
|
+
const realId = record2.id.trim();
|
|
16120
17030
|
if (!realId) {
|
|
16121
|
-
return
|
|
17031
|
+
return record2;
|
|
16122
17032
|
}
|
|
16123
|
-
const fields =
|
|
17033
|
+
const fields = record2.fields || {};
|
|
16124
17034
|
if (typeof fields.real_id === "string" && fields.real_id.trim()) {
|
|
16125
|
-
return
|
|
17035
|
+
return record2;
|
|
16126
17036
|
}
|
|
16127
17037
|
return {
|
|
16128
|
-
...
|
|
17038
|
+
...record2,
|
|
16129
17039
|
fields: {
|
|
16130
17040
|
...fields,
|
|
16131
17041
|
real_id: realId
|
|
@@ -16457,7 +17367,7 @@ var Environment = class _Environment {
|
|
|
16457
17367
|
}
|
|
16458
17368
|
get data() {
|
|
16459
17369
|
return {
|
|
16460
|
-
record: async (
|
|
17370
|
+
record: async (record2) => this.recordObject(record2),
|
|
16461
17371
|
recordMany: async (records, options) => this.recordObjects(records, options),
|
|
16462
17372
|
import: async (records, options) => this.enqueueRecordImport(records, options),
|
|
16463
17373
|
listImports: async (status) => this.listRecordImports(status),
|
|
@@ -17805,6 +18715,7 @@ var EnvironmentSession = class extends Session {
|
|
|
17805
18715
|
sessionDataHeaders;
|
|
17806
18716
|
beforeMutationSend;
|
|
17807
18717
|
heartbeatTimer = null;
|
|
18718
|
+
heartbeatProbeInFlight = false;
|
|
17808
18719
|
/** The last known graph container status, updated by checkReadiness(). */
|
|
17809
18720
|
graphContainerStatus = null;
|
|
17810
18721
|
constructor(client, environment, clientId, options = {}) {
|
|
@@ -17824,16 +18735,34 @@ var EnvironmentSession = class extends Session {
|
|
|
17824
18735
|
* an application RPC may be delayed by Durable Object work even while the
|
|
17825
18736
|
* underlying WebSocket is healthy.
|
|
17826
18737
|
*/
|
|
17827
|
-
startHeartbeat() {
|
|
18738
|
+
startHeartbeat(options = {}) {
|
|
17828
18739
|
if (this.heartbeatTimer) return;
|
|
17829
|
-
|
|
17830
|
-
|
|
17831
|
-
|
|
17832
|
-
|
|
17833
|
-
|
|
17834
|
-
|
|
17835
|
-
|
|
17836
|
-
|
|
18740
|
+
const probeServer = options.probeServer === true;
|
|
18741
|
+
this.heartbeatTimer = setInterval(
|
|
18742
|
+
() => {
|
|
18743
|
+
if (!this.client.isTransportOpen()) return;
|
|
18744
|
+
if (probeServer) {
|
|
18745
|
+
if (this.heartbeatProbeInFlight) return;
|
|
18746
|
+
if (this.client.hasPendingRpcRequests()) return;
|
|
18747
|
+
if (this.client.hasRecentInboundActivity(1e4)) return;
|
|
18748
|
+
this.heartbeatProbeInFlight = true;
|
|
18749
|
+
void this.client.call("client.heartbeat", {}).catch((error) => {
|
|
18750
|
+
if (this.client.isTransportOpen()) {
|
|
18751
|
+
this.client.reportTransportFailure(error);
|
|
18752
|
+
}
|
|
18753
|
+
}).finally(() => {
|
|
18754
|
+
this.heartbeatProbeInFlight = false;
|
|
18755
|
+
});
|
|
18756
|
+
return;
|
|
18757
|
+
}
|
|
18758
|
+
if (this.client.hasRecentInboundActivity(3e4)) return;
|
|
18759
|
+
if (this.client.hasRecentlyPendingRpcPeriod(6e4)) return;
|
|
18760
|
+
this.client.reportTransportFailure(
|
|
18761
|
+
new Error("No server activity received for 30 seconds")
|
|
18762
|
+
);
|
|
18763
|
+
},
|
|
18764
|
+
probeServer ? 1e4 : 5e3
|
|
18765
|
+
);
|
|
17837
18766
|
this.heartbeatTimer.unref?.();
|
|
17838
18767
|
}
|
|
17839
18768
|
stopHeartbeat() {
|
|
@@ -17841,10 +18770,15 @@ var EnvironmentSession = class extends Session {
|
|
|
17841
18770
|
clearInterval(this.heartbeatTimer);
|
|
17842
18771
|
this.heartbeatTimer = null;
|
|
17843
18772
|
}
|
|
18773
|
+
this.heartbeatProbeInFlight = false;
|
|
17844
18774
|
}
|
|
17845
18775
|
async hello() {
|
|
17846
18776
|
const result = await super.hello();
|
|
17847
|
-
|
|
18777
|
+
if (result.features?.serverHeartbeat === false) {
|
|
18778
|
+
this.startHeartbeat({ probeServer: true });
|
|
18779
|
+
} else {
|
|
18780
|
+
this.startHeartbeat();
|
|
18781
|
+
}
|
|
17848
18782
|
return result;
|
|
17849
18783
|
}
|
|
17850
18784
|
get environmentId() {
|
|
@@ -17979,13 +18913,13 @@ var EnvironmentSession = class extends Session {
|
|
|
17979
18913
|
input.operationId,
|
|
17980
18914
|
"operationId"
|
|
17981
18915
|
);
|
|
17982
|
-
const
|
|
18916
|
+
const text2 = requiredAssistantReplyString(input.text, "text");
|
|
17983
18917
|
return this.sessionDataRequest(
|
|
17984
18918
|
"/assistant-replies",
|
|
17985
18919
|
void 0,
|
|
17986
18920
|
{
|
|
17987
18921
|
method: "POST",
|
|
17988
|
-
body: { id, operationId: operationId2, text }
|
|
18922
|
+
body: { id, operationId: operationId2, text: text2 }
|
|
17989
18923
|
}
|
|
17990
18924
|
);
|
|
17991
18925
|
}
|
|
@@ -18030,7 +18964,10 @@ var EnvironmentSession = class extends Session {
|
|
|
18030
18964
|
queryOptions.targetId = options.target.id;
|
|
18031
18965
|
delete queryOptions.target;
|
|
18032
18966
|
}
|
|
18033
|
-
return this.sessionDataRequest("/artifacts", queryOptions)
|
|
18967
|
+
return this.sessionDataRequest("/artifacts", queryOptions).then((page) => ({
|
|
18968
|
+
...page,
|
|
18969
|
+
items: page.items.map(requireArtifactWorkflow)
|
|
18970
|
+
}));
|
|
18034
18971
|
},
|
|
18035
18972
|
listForLatestJob: (options = {}) => this.artifacts.list({
|
|
18036
18973
|
...options,
|
|
@@ -18043,7 +18980,7 @@ var EnvironmentSession = class extends Session {
|
|
|
18043
18980
|
// `cache: no-store`; this also bypasses intermediaries that ignore
|
|
18044
18981
|
// the Fetch cache directive for an otherwise identical GET URL.
|
|
18045
18982
|
{ _granularLiveRead: Date.now() }
|
|
18046
|
-
),
|
|
18983
|
+
).then(requireArtifactWorkflow),
|
|
18047
18984
|
create: (artifact) => this.sessionDataRequest(
|
|
18048
18985
|
"/artifacts",
|
|
18049
18986
|
void 0,
|
|
@@ -18051,7 +18988,7 @@ var EnvironmentSession = class extends Session {
|
|
|
18051
18988
|
method: "POST",
|
|
18052
18989
|
body: artifact
|
|
18053
18990
|
}
|
|
18054
|
-
),
|
|
18991
|
+
).then(requireArtifactWorkflow),
|
|
18055
18992
|
acceptSuggestion: (sequence) => this.sessionDataRequest(
|
|
18056
18993
|
"/artifacts/suggestions/accept",
|
|
18057
18994
|
void 0,
|
|
@@ -18059,7 +18996,7 @@ var EnvironmentSession = class extends Session {
|
|
|
18059
18996
|
method: "POST",
|
|
18060
18997
|
body: { sequence }
|
|
18061
18998
|
}
|
|
18062
|
-
),
|
|
18999
|
+
).then(requireArtifactWorkflow),
|
|
18063
19000
|
updateInputs: (artifactId, patch) => this.sessionDataRequest(
|
|
18064
19001
|
`/artifacts/${encodeURIComponent(artifactId)}`,
|
|
18065
19002
|
void 0,
|
|
@@ -18067,7 +19004,7 @@ var EnvironmentSession = class extends Session {
|
|
|
18067
19004
|
method: "PATCH",
|
|
18068
19005
|
body: patch
|
|
18069
19006
|
}
|
|
18070
|
-
),
|
|
19007
|
+
).then(requireArtifactWorkflow),
|
|
18071
19008
|
relationshipOptions: (artifactId, input) => this.sessionDataRequest(
|
|
18072
19009
|
`/artifacts/${encodeURIComponent(artifactId)}/relationship-options`,
|
|
18073
19010
|
void 0,
|
|
@@ -18077,27 +19014,27 @@ var EnvironmentSession = class extends Session {
|
|
|
18077
19014
|
`/artifacts/${encodeURIComponent(artifactId)}/relationship-create`,
|
|
18078
19015
|
void 0,
|
|
18079
19016
|
{ method: "POST", body: input }
|
|
18080
|
-
),
|
|
19017
|
+
).then(requireArtifactWorkflow),
|
|
18081
19018
|
validate: (artifactId) => this.sessionDataRequest(
|
|
18082
19019
|
`/artifacts/${encodeURIComponent(artifactId)}/validate`,
|
|
18083
19020
|
void 0,
|
|
18084
19021
|
{ method: "POST" }
|
|
18085
|
-
),
|
|
19022
|
+
).then(requireArtifactWorkflowResult),
|
|
18086
19023
|
execute: (artifactId, options) => this.sessionDataRequest(
|
|
18087
19024
|
`/artifacts/${encodeURIComponent(artifactId)}/execute`,
|
|
18088
19025
|
void 0,
|
|
18089
19026
|
{ method: "POST", body: options }
|
|
18090
|
-
),
|
|
19027
|
+
).then(requireArtifactWorkflowResult),
|
|
18091
19028
|
approve: (artifactId, options) => this.sessionDataRequest(
|
|
18092
19029
|
`/artifacts/${encodeURIComponent(artifactId)}/approve`,
|
|
18093
19030
|
void 0,
|
|
18094
19031
|
{ method: "POST", body: options }
|
|
18095
|
-
),
|
|
19032
|
+
).then(requireArtifactWorkflowResult),
|
|
18096
19033
|
cancel: (artifactId) => this.sessionDataRequest(
|
|
18097
19034
|
`/artifacts/${encodeURIComponent(artifactId)}/cancel`,
|
|
18098
19035
|
void 0,
|
|
18099
19036
|
{ method: "POST" }
|
|
18100
|
-
)
|
|
19037
|
+
).then(requireArtifactWorkflow)
|
|
18101
19038
|
};
|
|
18102
19039
|
}
|
|
18103
19040
|
get manualActions() {
|
|
@@ -20085,13 +21022,13 @@ var Granular = class _Granular {
|
|
|
20085
21022
|
* Permission Profile management for sandboxes
|
|
20086
21023
|
*/
|
|
20087
21024
|
get permissionProfiles() {
|
|
20088
|
-
const profileSourceFromRecord = (
|
|
20089
|
-
const profile =
|
|
21025
|
+
const profileSourceFromRecord = (record2) => {
|
|
21026
|
+
const profile = record2.profile || record2.rules || {};
|
|
20090
21027
|
return {
|
|
20091
21028
|
...profile,
|
|
20092
21029
|
schemaVersion: profile.schemaVersion || 1,
|
|
20093
|
-
name: profile.name ||
|
|
20094
|
-
description: profile.description ||
|
|
21030
|
+
name: profile.name || record2.name,
|
|
21031
|
+
description: profile.description || record2.description
|
|
20095
21032
|
};
|
|
20096
21033
|
};
|
|
20097
21034
|
return {
|
|
@@ -20674,18 +21611,18 @@ function stableValue(value) {
|
|
|
20674
21611
|
function stableJson(value) {
|
|
20675
21612
|
return JSON.stringify(stableValue(value));
|
|
20676
21613
|
}
|
|
20677
|
-
function recordKey(
|
|
20678
|
-
return `${
|
|
21614
|
+
function recordKey(record2) {
|
|
21615
|
+
return `${record2.className}\0${record2.id}`;
|
|
20679
21616
|
}
|
|
20680
21617
|
function recordReference(className, id) {
|
|
20681
21618
|
return { className, id };
|
|
20682
21619
|
}
|
|
20683
21620
|
function changedRecordSnapshots(beforeRecords, afterRecords) {
|
|
20684
21621
|
const before = new Map(
|
|
20685
|
-
beforeRecords.map((
|
|
21622
|
+
beforeRecords.map((record2) => [recordKey(record2), record2])
|
|
20686
21623
|
);
|
|
20687
21624
|
const after = new Map(
|
|
20688
|
-
afterRecords.map((
|
|
21625
|
+
afterRecords.map((record2) => [recordKey(record2), record2])
|
|
20689
21626
|
);
|
|
20690
21627
|
const changedKeys = /* @__PURE__ */ new Set();
|
|
20691
21628
|
for (const key of /* @__PURE__ */ new Set([...before.keys(), ...after.keys()])) {
|
|
@@ -20695,10 +21632,10 @@ function changedRecordSnapshots(beforeRecords, afterRecords) {
|
|
|
20695
21632
|
}
|
|
20696
21633
|
return {
|
|
20697
21634
|
beforeRecords: beforeRecords.filter(
|
|
20698
|
-
(
|
|
21635
|
+
(record2) => changedKeys.has(recordKey(record2))
|
|
20699
21636
|
),
|
|
20700
21637
|
afterRecords: afterRecords.filter(
|
|
20701
|
-
(
|
|
21638
|
+
(record2) => changedKeys.has(recordKey(record2))
|
|
20702
21639
|
)
|
|
20703
21640
|
};
|
|
20704
21641
|
}
|
|
@@ -20747,35 +21684,35 @@ function changedObjectProjection(before, after) {
|
|
|
20747
21684
|
}
|
|
20748
21685
|
function projectionChanges(input) {
|
|
20749
21686
|
const before = new Map(
|
|
20750
|
-
input.beforeRecords.map((
|
|
21687
|
+
input.beforeRecords.map((record2) => [recordKey(record2), record2])
|
|
20751
21688
|
);
|
|
20752
21689
|
const after = new Map(
|
|
20753
|
-
input.afterRecords.map((
|
|
21690
|
+
input.afterRecords.map((record2) => [recordKey(record2), record2])
|
|
20754
21691
|
);
|
|
20755
21692
|
const targets = relationshipTargets(input.manifest);
|
|
20756
21693
|
const changes = [];
|
|
20757
|
-
for (const
|
|
20758
|
-
const previous = before.get(recordKey(
|
|
20759
|
-
const objectChange = changedObjectProjection(previous,
|
|
21694
|
+
for (const record2 of input.afterRecords) {
|
|
21695
|
+
const previous = before.get(recordKey(record2));
|
|
21696
|
+
const objectChange = changedObjectProjection(previous, record2);
|
|
20760
21697
|
if (objectChange) changes.push(objectChange);
|
|
20761
21698
|
const relationshipNames = /* @__PURE__ */ new Set([
|
|
20762
21699
|
...Object.keys(previous?.relationships || {}),
|
|
20763
|
-
...Object.keys(
|
|
21700
|
+
...Object.keys(record2.relationships || {})
|
|
20764
21701
|
]);
|
|
20765
21702
|
for (const relationshipName of [...relationshipNames].sort()) {
|
|
20766
21703
|
const target = targets.get(
|
|
20767
|
-
`${
|
|
21704
|
+
`${record2.className}\0${relationshipName}`
|
|
20768
21705
|
);
|
|
20769
21706
|
if (!target) {
|
|
20770
21707
|
throw new Error(
|
|
20771
|
-
`No ontology relationship target is declared for ${
|
|
21708
|
+
`No ontology relationship target is declared for ${record2.className}.${relationshipName}`
|
|
20772
21709
|
);
|
|
20773
21710
|
}
|
|
20774
21711
|
const previousIds = new Set(
|
|
20775
21712
|
asIds(previous?.relationships?.[relationshipName])
|
|
20776
21713
|
);
|
|
20777
21714
|
const currentIds = new Set(
|
|
20778
|
-
asIds(
|
|
21715
|
+
asIds(record2.relationships?.[relationshipName])
|
|
20779
21716
|
);
|
|
20780
21717
|
for (const id of [...previousIds].sort()) {
|
|
20781
21718
|
if (currentIds.has(id)) continue;
|
|
@@ -20783,7 +21720,7 @@ function projectionChanges(input) {
|
|
|
20783
21720
|
kind: "relationship",
|
|
20784
21721
|
operation: "disconnected",
|
|
20785
21722
|
relationship: relationshipName,
|
|
20786
|
-
from: recordReference(
|
|
21723
|
+
from: recordReference(record2.className, record2.id),
|
|
20787
21724
|
to: recordReference(target.className, id)
|
|
20788
21725
|
});
|
|
20789
21726
|
}
|
|
@@ -20793,37 +21730,37 @@ function projectionChanges(input) {
|
|
|
20793
21730
|
kind: "relationship",
|
|
20794
21731
|
operation: "connected",
|
|
20795
21732
|
relationship: relationshipName,
|
|
20796
|
-
from: recordReference(
|
|
21733
|
+
from: recordReference(record2.className, record2.id),
|
|
20797
21734
|
to: recordReference(target.className, id)
|
|
20798
21735
|
});
|
|
20799
21736
|
}
|
|
20800
21737
|
}
|
|
20801
21738
|
const machines = /* @__PURE__ */ new Set([
|
|
20802
21739
|
...Object.keys(previous?.states || {}),
|
|
20803
|
-
...Object.keys(
|
|
21740
|
+
...Object.keys(record2.states || {})
|
|
20804
21741
|
]);
|
|
20805
21742
|
for (const machine of [...machines].sort()) {
|
|
20806
|
-
const next =
|
|
21743
|
+
const next = record2.states?.[machine];
|
|
20807
21744
|
if (next === void 0) continue;
|
|
20808
21745
|
const prior = previous?.states?.[machine];
|
|
20809
21746
|
if (prior !== void 0 && stateName(prior) === stateName(next)) continue;
|
|
20810
|
-
if (input.transition && input.transition.className ===
|
|
21747
|
+
if (input.transition && input.transition.className === record2.className && input.transition.objectId === record2.id && input.transition.machine === machine) {
|
|
20811
21748
|
continue;
|
|
20812
21749
|
}
|
|
20813
21750
|
changes.push({
|
|
20814
21751
|
kind: "state_observation",
|
|
20815
|
-
target: recordReference(
|
|
21752
|
+
target: recordReference(record2.className, record2.id),
|
|
20816
21753
|
machine,
|
|
20817
21754
|
state: stateName(next)
|
|
20818
21755
|
});
|
|
20819
21756
|
}
|
|
20820
21757
|
}
|
|
20821
|
-
for (const
|
|
20822
|
-
if (after.has(recordKey(
|
|
21758
|
+
for (const record2 of input.beforeRecords) {
|
|
21759
|
+
if (after.has(recordKey(record2))) continue;
|
|
20823
21760
|
changes.push({
|
|
20824
21761
|
kind: "object",
|
|
20825
21762
|
operation: "deleted",
|
|
20826
|
-
target: recordReference(
|
|
21763
|
+
target: recordReference(record2.className, record2.id)
|
|
20827
21764
|
});
|
|
20828
21765
|
}
|
|
20829
21766
|
return changes;
|
|
@@ -20868,7 +21805,7 @@ function transitionOutcome(transition, afterRecords) {
|
|
|
20868
21805
|
throw new Error("A transition commit has no authored transition context.");
|
|
20869
21806
|
}
|
|
20870
21807
|
const target = afterRecords.find(
|
|
20871
|
-
(
|
|
21808
|
+
(record2) => record2.className === transition.className && record2.id === transition.objectId
|
|
20872
21809
|
);
|
|
20873
21810
|
const observed = target?.states?.[transition.machine];
|
|
20874
21811
|
if (!observed) {
|
|
@@ -20914,7 +21851,8 @@ function projectRecordSnapshotMutation(input) {
|
|
|
20914
21851
|
const base = {
|
|
20915
21852
|
source: {
|
|
20916
21853
|
reference: input.source.reference,
|
|
20917
|
-
...input.source.version ? { version: input.source.version } : {}
|
|
21854
|
+
...input.source.version ? { version: input.source.version } : {},
|
|
21855
|
+
...input.source.versionScope ? { versionScope: input.source.versionScope } : {}
|
|
20918
21856
|
},
|
|
20919
21857
|
...target ? { primaryTarget: target } : {},
|
|
20920
21858
|
changes,
|
|
@@ -21085,29 +22023,29 @@ function requireRecord(value, context) {
|
|
|
21085
22023
|
}
|
|
21086
22024
|
return value;
|
|
21087
22025
|
}
|
|
21088
|
-
function requiredString(
|
|
21089
|
-
const value =
|
|
22026
|
+
function requiredString(record2, key, context) {
|
|
22027
|
+
const value = record2[key];
|
|
21090
22028
|
if (typeof value !== "string" || !value.trim()) {
|
|
21091
22029
|
throw new Error(`${context}.${key} must be a non-empty string.`);
|
|
21092
22030
|
}
|
|
21093
22031
|
return value;
|
|
21094
22032
|
}
|
|
21095
|
-
function requiredNumber(
|
|
21096
|
-
const value =
|
|
22033
|
+
function requiredNumber(record2, key, context) {
|
|
22034
|
+
const value = record2[key];
|
|
21097
22035
|
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
21098
22036
|
throw new Error(`${context}.${key} must be a finite number.`);
|
|
21099
22037
|
}
|
|
21100
22038
|
return value;
|
|
21101
22039
|
}
|
|
21102
|
-
function requiredStringArray(
|
|
21103
|
-
const value =
|
|
22040
|
+
function requiredStringArray(record2, key, context) {
|
|
22041
|
+
const value = record2[key];
|
|
21104
22042
|
if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !item.trim())) {
|
|
21105
22043
|
throw new Error(`${context}.${key} must be an array of non-empty strings.`);
|
|
21106
22044
|
}
|
|
21107
22045
|
return [...value];
|
|
21108
22046
|
}
|
|
21109
|
-
function requiredNumberRecord(
|
|
21110
|
-
const value = requireRecord(
|
|
22047
|
+
function requiredNumberRecord(record2, key, context) {
|
|
22048
|
+
const value = requireRecord(record2[key], `${context}.${key}`);
|
|
21111
22049
|
const output = {};
|
|
21112
22050
|
for (const [entryKey, entryValue] of Object.entries(value)) {
|
|
21113
22051
|
if (typeof entryValue !== "number" || !Number.isFinite(entryValue) || entryValue < 0 || entryValue > 1) {
|
|
@@ -21120,22 +22058,22 @@ function requiredNumberRecord(record, key, context) {
|
|
|
21120
22058
|
return output;
|
|
21121
22059
|
}
|
|
21122
22060
|
function validateHarnessTemplateManifest(value, context = "HarnessTemplateManifest") {
|
|
21123
|
-
const
|
|
21124
|
-
const status = requiredString(
|
|
22061
|
+
const record2 = requireRecord(value, context);
|
|
22062
|
+
const status = requiredString(record2, "status", context);
|
|
21125
22063
|
if (!HARNESS_TEMPLATE_STATUSES.includes(status)) {
|
|
21126
22064
|
throw new Error(
|
|
21127
22065
|
`${context}.status must be one of ${HARNESS_TEMPLATE_STATUSES.join(", ")}.`
|
|
21128
22066
|
);
|
|
21129
22067
|
}
|
|
21130
|
-
const createdAt = requiredString(
|
|
22068
|
+
const createdAt = requiredString(record2, "createdAt", context);
|
|
21131
22069
|
if (Number.isNaN(Date.parse(createdAt))) {
|
|
21132
22070
|
throw new Error(`${context}.createdAt must be an ISO timestamp.`);
|
|
21133
22071
|
}
|
|
21134
22072
|
const compatibility = requireRecord(
|
|
21135
|
-
|
|
22073
|
+
record2.compatibility,
|
|
21136
22074
|
`${context}.compatibility`
|
|
21137
22075
|
);
|
|
21138
|
-
const evalGates = requireRecord(
|
|
22076
|
+
const evalGates = requireRecord(record2.evalGates, `${context}.evalGates`);
|
|
21139
22077
|
const maxRegressionPct = requiredNumber(
|
|
21140
22078
|
evalGates,
|
|
21141
22079
|
"maxRegressionPct",
|
|
@@ -21147,23 +22085,23 @@ function validateHarnessTemplateManifest(value, context = "HarnessTemplateManife
|
|
|
21147
22085
|
);
|
|
21148
22086
|
}
|
|
21149
22087
|
return {
|
|
21150
|
-
id: requiredString(
|
|
21151
|
-
version: requiredString(
|
|
22088
|
+
id: requiredString(record2, "id", context),
|
|
22089
|
+
version: requiredString(record2, "version", context),
|
|
21152
22090
|
status,
|
|
21153
|
-
owner: requiredString(
|
|
22091
|
+
owner: requiredString(record2, "owner", context),
|
|
21154
22092
|
createdAt,
|
|
21155
|
-
changelog: requiredString(
|
|
21156
|
-
promptBuilder: requiredString(
|
|
21157
|
-
continuationBuilder: requiredString(
|
|
22093
|
+
changelog: requiredString(record2, "changelog", context),
|
|
22094
|
+
promptBuilder: requiredString(record2, "promptBuilder", context),
|
|
22095
|
+
continuationBuilder: requiredString(record2, "continuationBuilder", context),
|
|
21158
22096
|
modelOutputInstruction: requiredString(
|
|
21159
|
-
|
|
22097
|
+
record2,
|
|
21160
22098
|
"modelOutputInstruction",
|
|
21161
22099
|
context
|
|
21162
22100
|
),
|
|
21163
|
-
codeReviewPolicy: requiredString(
|
|
21164
|
-
defaultModel: requiredString(
|
|
21165
|
-
modelMatrix: requiredStringArray(
|
|
21166
|
-
temperature: requiredNumber(
|
|
22101
|
+
codeReviewPolicy: requiredString(record2, "codeReviewPolicy", context),
|
|
22102
|
+
defaultModel: requiredString(record2, "defaultModel", context),
|
|
22103
|
+
modelMatrix: requiredStringArray(record2, "modelMatrix", context),
|
|
22104
|
+
temperature: requiredNumber(record2, "temperature", context),
|
|
21167
22105
|
compatibility: {
|
|
21168
22106
|
minSdkVersion: requiredString(
|
|
21169
22107
|
compatibility,
|
|
@@ -21217,27 +22155,27 @@ var DEFAULT_LOW_SIGNAL_REASONING_LINES = [
|
|
|
21217
22155
|
function parseReasoningCommentLine(line, options = {}) {
|
|
21218
22156
|
const trimmed = line.trimStart();
|
|
21219
22157
|
if (!trimmed.startsWith("//")) return null;
|
|
21220
|
-
const
|
|
21221
|
-
if (!
|
|
22158
|
+
const text2 = trimmed.replace(/^\/\/\s?/, "").trim();
|
|
22159
|
+
if (!text2) return { kind: "ignored" };
|
|
21222
22160
|
const ignoredDirectives = options.ignoredCommentDirectives || DEFAULT_IGNORED_REASONING_COMMENT_DIRECTIVES;
|
|
21223
|
-
if (ignoredDirectives.some((pattern) => pattern.test(
|
|
22161
|
+
if (ignoredDirectives.some((pattern) => pattern.test(text2))) {
|
|
21224
22162
|
return { kind: "ignored" };
|
|
21225
22163
|
}
|
|
21226
22164
|
const lowSignalLines = options.lowSignalReasoningLines || DEFAULT_LOW_SIGNAL_REASONING_LINES;
|
|
21227
|
-
if (lowSignalLines.some((pattern) => pattern.test(
|
|
22165
|
+
if (lowSignalLines.some((pattern) => pattern.test(text2))) {
|
|
21228
22166
|
return { kind: "ignored" };
|
|
21229
22167
|
}
|
|
21230
|
-
return { kind: "reasoning", text };
|
|
22168
|
+
return { kind: "reasoning", text: text2 };
|
|
21231
22169
|
}
|
|
21232
22170
|
function consumeGranularReasoningTraceChunk(buffer, chunk, options = {}) {
|
|
21233
|
-
let
|
|
22171
|
+
let text2 = buffer + chunk;
|
|
21234
22172
|
let visibleText = "";
|
|
21235
22173
|
const reasoningLines = [];
|
|
21236
22174
|
while (true) {
|
|
21237
|
-
const newlineIndex =
|
|
22175
|
+
const newlineIndex = text2.indexOf("\n");
|
|
21238
22176
|
if (newlineIndex === -1) break;
|
|
21239
|
-
const rawLine =
|
|
21240
|
-
|
|
22177
|
+
const rawLine = text2.slice(0, newlineIndex);
|
|
22178
|
+
text2 = text2.slice(newlineIndex + 1);
|
|
21241
22179
|
const comment = parseReasoningCommentLine(
|
|
21242
22180
|
rawLine.replace(/\r$/, ""),
|
|
21243
22181
|
options
|
|
@@ -21251,19 +22189,19 @@ function consumeGranularReasoningTraceChunk(buffer, chunk, options = {}) {
|
|
|
21251
22189
|
`;
|
|
21252
22190
|
}
|
|
21253
22191
|
}
|
|
21254
|
-
if (options.final &&
|
|
21255
|
-
const comment = parseReasoningCommentLine(
|
|
22192
|
+
if (options.final && text2.length > 0) {
|
|
22193
|
+
const comment = parseReasoningCommentLine(text2.replace(/\r$/, ""), options);
|
|
21256
22194
|
if (comment?.kind === "reasoning") {
|
|
21257
22195
|
reasoningLines.push(comment.text);
|
|
21258
|
-
|
|
22196
|
+
text2 = "";
|
|
21259
22197
|
} else if (comment?.kind === "ignored") {
|
|
21260
|
-
|
|
22198
|
+
text2 = "";
|
|
21261
22199
|
} else {
|
|
21262
|
-
visibleText +=
|
|
21263
|
-
|
|
22200
|
+
visibleText += text2;
|
|
22201
|
+
text2 = "";
|
|
21264
22202
|
}
|
|
21265
22203
|
}
|
|
21266
|
-
return { buffer:
|
|
22204
|
+
return { buffer: text2, visibleText, reasoningLines };
|
|
21267
22205
|
}
|
|
21268
22206
|
function consumeGranularReasoningOnlyChunk(buffer, chunk, options = {}) {
|
|
21269
22207
|
const result = consumeGranularReasoningTraceChunk(buffer, chunk, options);
|
|
@@ -21272,8 +22210,8 @@ function consumeGranularReasoningOnlyChunk(buffer, chunk, options = {}) {
|
|
|
21272
22210
|
reasoningLines: result.reasoningLines
|
|
21273
22211
|
};
|
|
21274
22212
|
}
|
|
21275
|
-
function stripGranularReasoningTrace(
|
|
21276
|
-
return consumeGranularReasoningTraceChunk("",
|
|
22213
|
+
function stripGranularReasoningTrace(text2, options = {}) {
|
|
22214
|
+
return consumeGranularReasoningTraceChunk("", text2, {
|
|
21277
22215
|
...options,
|
|
21278
22216
|
final: true
|
|
21279
22217
|
}).visibleText.trim();
|
|
@@ -21308,8 +22246,8 @@ function stableStringify(value) {
|
|
|
21308
22246
|
if (Array.isArray(value)) {
|
|
21309
22247
|
return `[${value.map((entry) => stableStringify(entry)).join(",")}]`;
|
|
21310
22248
|
}
|
|
21311
|
-
const
|
|
21312
|
-
return `{${Object.keys(
|
|
22249
|
+
const record2 = value;
|
|
22250
|
+
return `{${Object.keys(record2).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(record2[key])}`).join(",")}}`;
|
|
21313
22251
|
}
|
|
21314
22252
|
function renderConstBlock(name, value) {
|
|
21315
22253
|
return `const ${name} = ${JSON.stringify(value, null, 2)} as const;`;
|
|
@@ -21905,9 +22843,9 @@ function getLatestClosure(liveDoc) {
|
|
|
21905
22843
|
}
|
|
21906
22844
|
const closures = [];
|
|
21907
22845
|
for (const [closureId, value] of Object.entries(closuresById)) {
|
|
21908
|
-
const
|
|
21909
|
-
if (!
|
|
21910
|
-
closures.push({ ...
|
|
22846
|
+
const record2 = asRecord4(value);
|
|
22847
|
+
if (!record2) continue;
|
|
22848
|
+
closures.push({ ...record2, closureId });
|
|
21911
22849
|
}
|
|
21912
22850
|
closures.sort(
|
|
21913
22851
|
(left, right) => (Number(right.createdAt) || 0) - (Number(left.createdAt) || 0)
|
|
@@ -21945,9 +22883,9 @@ function getJobRecords(liveDoc) {
|
|
|
21945
22883
|
const jobsById = asRecord4(asRecord4(liveDoc?.jobs)?.byId) || {};
|
|
21946
22884
|
const jobs = [];
|
|
21947
22885
|
for (const [jobId, value] of Object.entries(jobsById)) {
|
|
21948
|
-
const
|
|
21949
|
-
if (!
|
|
21950
|
-
jobs.push({ ...
|
|
22886
|
+
const record2 = asRecord4(value);
|
|
22887
|
+
if (!record2) continue;
|
|
22888
|
+
jobs.push({ ...record2, jobId });
|
|
21951
22889
|
}
|
|
21952
22890
|
jobs.sort(
|
|
21953
22891
|
(left, right) => getJobTimestamp(right) - getJobTimestamp(left)
|
|
@@ -22133,8 +23071,8 @@ function hasOpenPrompt(liveDoc, pendingPrompts) {
|
|
|
22133
23071
|
const prompts = asRecord4(asRecord4(job)?.prompts);
|
|
22134
23072
|
if (!prompts) continue;
|
|
22135
23073
|
for (const prompt of Object.values(prompts)) {
|
|
22136
|
-
const
|
|
22137
|
-
if (
|
|
23074
|
+
const record2 = asRecord4(prompt);
|
|
23075
|
+
if (record2?.status === "open") return true;
|
|
22138
23076
|
}
|
|
22139
23077
|
}
|
|
22140
23078
|
return false;
|
|
@@ -22193,13 +23131,13 @@ function projectLoopSummary(liveDoc, pendingPrompts = [], options) {
|
|
|
22193
23131
|
title: typeof decision.title === "string" && decision.title.trim() ? decision.title.trim() : "Decision",
|
|
22194
23132
|
status,
|
|
22195
23133
|
candidates: status === "open" ? asArray(decision.candidates).slice(0, 5).map((candidate) => {
|
|
22196
|
-
const
|
|
22197
|
-
if (!
|
|
23134
|
+
const record2 = asRecord4(candidate);
|
|
23135
|
+
if (!record2) return null;
|
|
22198
23136
|
return {
|
|
22199
|
-
id: typeof
|
|
22200
|
-
label: typeof
|
|
22201
|
-
description: typeof
|
|
22202
|
-
metadata: asRecord4(
|
|
23137
|
+
id: typeof record2.id === "string" ? record2.id : "unknown",
|
|
23138
|
+
label: typeof record2.label === "string" && record2.label.trim() ? record2.label.trim() : null,
|
|
23139
|
+
description: typeof record2.description === "string" && record2.description.trim() ? record2.description.trim() : null,
|
|
23140
|
+
metadata: asRecord4(record2.metadata)
|
|
22203
23141
|
};
|
|
22204
23142
|
}).filter(Boolean) : [],
|
|
22205
23143
|
selected: status === "open" ? null : {
|
|
@@ -22834,11 +23772,11 @@ function normalizeJsonSchema(value) {
|
|
|
22834
23772
|
return asRecord4(value);
|
|
22835
23773
|
}
|
|
22836
23774
|
function jsonSchemaTypeName(schema) {
|
|
22837
|
-
const
|
|
22838
|
-
if (!
|
|
22839
|
-
const type =
|
|
22840
|
-
if (
|
|
22841
|
-
if (
|
|
23775
|
+
const record2 = normalizeJsonSchema(schema);
|
|
23776
|
+
if (!record2) return "unknown";
|
|
23777
|
+
const type = record2.type;
|
|
23778
|
+
if (record2.format === "date-time") return "date-time";
|
|
23779
|
+
if (record2.format === "date" || type === "date" || Array.isArray(type) && type.includes("date")) {
|
|
22842
23780
|
return "date";
|
|
22843
23781
|
}
|
|
22844
23782
|
if (typeof type === "string") {
|
|
@@ -22849,12 +23787,12 @@ function jsonSchemaTypeName(schema) {
|
|
|
22849
23787
|
return "unknown";
|
|
22850
23788
|
}
|
|
22851
23789
|
function summarizeObjectSchema(schema) {
|
|
22852
|
-
const
|
|
22853
|
-
const properties = asRecord4(
|
|
23790
|
+
const record2 = normalizeJsonSchema(schema);
|
|
23791
|
+
const properties = asRecord4(record2?.properties);
|
|
22854
23792
|
if (!properties || Object.keys(properties).length === 0) {
|
|
22855
|
-
return
|
|
23793
|
+
return record2 ? "{}" : null;
|
|
22856
23794
|
}
|
|
22857
|
-
const required = new Set(asArray(
|
|
23795
|
+
const required = new Set(asArray(record2?.required));
|
|
22858
23796
|
const fields = Object.entries(properties).slice(0, 8).map(([name, property]) => {
|
|
22859
23797
|
const marker = required.has(name) ? "*" : "?";
|
|
22860
23798
|
return `${name}${marker}: ${jsonSchemaTypeName(property)}`;
|
|
@@ -23343,6 +24281,10 @@ ${actionIndex}
|
|
|
23343
24281
|
- 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.
|
|
23344
24282
|
- Opening a prepared action does not execute the underlying mutation. Use \`.open()\` only when the user asks to prepare, review, show, or edit an action before running it, when a new record must be prepared, or when a reviewable form must collect missing editable inputs. Prefill only grounded values and leave unknown fields empty.
|
|
23345
24283
|
- 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.
|
|
24284
|
+
- 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.
|
|
24285
|
+
- 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.
|
|
24286
|
+
- 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.
|
|
24287
|
+
- 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.
|
|
23346
24288
|
- 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.
|
|
23347
24289
|
- 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.
|
|
23348
24290
|
- 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.
|
|
@@ -23596,10 +24538,10 @@ function responseTextFromFeedItems(feedItems, jobId) {
|
|
|
23596
24538
|
if (item.kind !== "message" || item.payload.role !== "assistant" || item.source?.jobId !== jobId || item.sequence <= latestSequence) {
|
|
23597
24539
|
continue;
|
|
23598
24540
|
}
|
|
23599
|
-
const
|
|
23600
|
-
if (!
|
|
24541
|
+
const text2 = item.payload.text.trim();
|
|
24542
|
+
if (!text2) continue;
|
|
23601
24543
|
latestSequence = item.sequence;
|
|
23602
|
-
latestText =
|
|
24544
|
+
latestText = text2;
|
|
23603
24545
|
}
|
|
23604
24546
|
return latestText;
|
|
23605
24547
|
}
|
|
@@ -23614,39 +24556,39 @@ function pushStringArray(target, value) {
|
|
|
23614
24556
|
pushString(target, item);
|
|
23615
24557
|
}
|
|
23616
24558
|
}
|
|
23617
|
-
function collectReferencesFromRecord(
|
|
24559
|
+
function collectReferencesFromRecord(record2, refs) {
|
|
23618
24560
|
for (const key of ENTRY_KEY_CANDIDATES)
|
|
23619
|
-
pushString(refs.entryPaths,
|
|
24561
|
+
pushString(refs.entryPaths, record2[key]);
|
|
23620
24562
|
for (const key of ENTRY_ARRAY_KEY_CANDIDATES)
|
|
23621
|
-
pushStringArray(refs.entryPaths,
|
|
24563
|
+
pushStringArray(refs.entryPaths, record2[key]);
|
|
23622
24564
|
for (const key of LIST_KEY_CANDIDATES)
|
|
23623
|
-
pushString(refs.listNames,
|
|
24565
|
+
pushString(refs.listNames, record2[key]);
|
|
23624
24566
|
for (const key of LIST_ARRAY_KEY_CANDIDATES)
|
|
23625
|
-
pushStringArray(refs.listNames,
|
|
24567
|
+
pushStringArray(refs.listNames, record2[key]);
|
|
23626
24568
|
for (const key of VARIABLE_KEY_CANDIDATES)
|
|
23627
|
-
pushString(refs.variableNames,
|
|
24569
|
+
pushString(refs.variableNames, record2[key]);
|
|
23628
24570
|
for (const key of VARIABLE_ARRAY_KEY_CANDIDATES)
|
|
23629
|
-
pushStringArray(refs.variableNames,
|
|
24571
|
+
pushStringArray(refs.variableNames, record2[key]);
|
|
23630
24572
|
}
|
|
23631
|
-
function stringValue(
|
|
24573
|
+
function stringValue(record2, keys) {
|
|
23632
24574
|
for (const key of keys) {
|
|
23633
|
-
const value =
|
|
24575
|
+
const value = record2[key];
|
|
23634
24576
|
if (typeof value === "string" && value.trim()) {
|
|
23635
24577
|
return value.trim();
|
|
23636
24578
|
}
|
|
23637
24579
|
}
|
|
23638
24580
|
return null;
|
|
23639
24581
|
}
|
|
23640
|
-
function findEntryPathForRecord(
|
|
23641
|
-
const directPath = stringValue(
|
|
24582
|
+
function findEntryPathForRecord(record2, heap) {
|
|
24583
|
+
const directPath = stringValue(record2, ["entryPath", "path"]);
|
|
23642
24584
|
if (directPath && heap.entriesByPath?.[directPath]) {
|
|
23643
24585
|
return directPath;
|
|
23644
24586
|
}
|
|
23645
|
-
const id = stringValue(
|
|
24587
|
+
const id = stringValue(record2, ["id", "_id", "recordId", "objectId"]);
|
|
23646
24588
|
if (!id) {
|
|
23647
24589
|
return null;
|
|
23648
24590
|
}
|
|
23649
|
-
const className = stringValue(
|
|
24591
|
+
const className = stringValue(record2, [
|
|
23650
24592
|
"className",
|
|
23651
24593
|
"_className",
|
|
23652
24594
|
"__className",
|
|
@@ -23680,17 +24622,17 @@ function scanForHeapReferences(value, heap, refs, depth = 0, seen = /* @__PURE__
|
|
|
23680
24622
|
}
|
|
23681
24623
|
return;
|
|
23682
24624
|
}
|
|
23683
|
-
const
|
|
23684
|
-
if (!
|
|
24625
|
+
const record2 = asRecord5(value);
|
|
24626
|
+
if (!record2) return;
|
|
23685
24627
|
seen.add(value);
|
|
23686
|
-
const entryPath = findEntryPathForRecord(
|
|
24628
|
+
const entryPath = findEntryPathForRecord(record2, heap);
|
|
23687
24629
|
if (entryPath) refs.entryPaths.add(entryPath);
|
|
23688
|
-
collectReferencesFromRecord(
|
|
24630
|
+
collectReferencesFromRecord(record2, refs);
|
|
23689
24631
|
for (const key of UI_CONTAINER_KEYS) {
|
|
23690
|
-
const nested = asRecord5(
|
|
24632
|
+
const nested = asRecord5(record2[key]);
|
|
23691
24633
|
if (nested) collectReferencesFromRecord(nested, refs);
|
|
23692
24634
|
}
|
|
23693
|
-
for (const nested of Object.values(
|
|
24635
|
+
for (const nested of Object.values(record2).slice(0, 24)) {
|
|
23694
24636
|
scanForHeapReferences(nested, heap, refs, depth + 1, seen);
|
|
23695
24637
|
}
|
|
23696
24638
|
}
|
|
@@ -23839,8 +24781,8 @@ var OPENAI_MODEL_PRICING_USD_PER_MILLION = {
|
|
|
23839
24781
|
function asRecord6(value) {
|
|
23840
24782
|
return value && typeof value === "object" ? value : null;
|
|
23841
24783
|
}
|
|
23842
|
-
function numberField(
|
|
23843
|
-
const value =
|
|
24784
|
+
function numberField(record2, key) {
|
|
24785
|
+
const value = record2?.[key];
|
|
23844
24786
|
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
23845
24787
|
}
|
|
23846
24788
|
function microsPerMillion(usdPerMillion) {
|
|
@@ -23944,6 +24886,216 @@ function calculateOpenAITokenSpend(model, rawUsage) {
|
|
|
23944
24886
|
};
|
|
23945
24887
|
}
|
|
23946
24888
|
|
|
23947
|
-
|
|
24889
|
+
// src/artifact-surface.ts
|
|
24890
|
+
function operationNode(workflow) {
|
|
24891
|
+
return getArtifactWorkflowNodes(workflow).find(
|
|
24892
|
+
(node) => node.kind === "operation"
|
|
24893
|
+
) || null;
|
|
24894
|
+
}
|
|
24895
|
+
function operationStatusLabel(phase) {
|
|
24896
|
+
if (phase === "reviewing") return "Preparing";
|
|
24897
|
+
if (phase === "sending") return "In progress";
|
|
24898
|
+
if (phase === "synchronizing") return "Saving";
|
|
24899
|
+
if (phase === "verifying") return "Verifying";
|
|
24900
|
+
if (phase === "waiting_for_approval") return "Awaiting approval";
|
|
24901
|
+
if (phase === "completed") return "Completed";
|
|
24902
|
+
if (phase === "failed") return "Failed";
|
|
24903
|
+
return null;
|
|
24904
|
+
}
|
|
24905
|
+
function action(id, label, tone, disabled, disabledReason = null) {
|
|
24906
|
+
return { id, label, tone, disabled, disabledReason };
|
|
24907
|
+
}
|
|
24908
|
+
function navigationIsUseful(workflow) {
|
|
24909
|
+
const nodes = getArtifactWorkflowNodes(workflow).filter(
|
|
24910
|
+
(node) => node.kind !== "operation" && node.kind !== "group"
|
|
24911
|
+
);
|
|
24912
|
+
return nodes.length > 1 || nodes.some((node) => node.kind === "child_artifact");
|
|
24913
|
+
}
|
|
24914
|
+
function inputNode(workflow, activeEditorNodeId) {
|
|
24915
|
+
if (activeEditorNodeId) {
|
|
24916
|
+
const active = workflow.nodesById[activeEditorNodeId];
|
|
24917
|
+
if (active && (active.kind === "input" || active.kind === "relationship")) {
|
|
24918
|
+
return active;
|
|
24919
|
+
}
|
|
24920
|
+
}
|
|
24921
|
+
const current = getCurrentArtifactWorkflowNode(workflow);
|
|
24922
|
+
return current?.kind === "input" || current?.kind === "relationship" ? current : null;
|
|
24923
|
+
}
|
|
24924
|
+
function selectArtifactSurface(artifact, context = {}) {
|
|
24925
|
+
const workflow = artifact.workflow || projectArtifactWorkflow(artifact);
|
|
24926
|
+
const operation = operationNode(workflow);
|
|
24927
|
+
const workflowStatus = operation?.status || null;
|
|
24928
|
+
const terminal = workflowStatus === "completed" || workflowStatus === "canceled";
|
|
24929
|
+
const requestedEditorNodeId = terminal ? null : context.activeEditorNodeId || null;
|
|
24930
|
+
const current = getCurrentArtifactWorkflowNode(workflow);
|
|
24931
|
+
const activeInput = inputNode(workflow, requestedEditorNodeId);
|
|
24932
|
+
const mutationsDisabled = context.mutationsDisabled === true;
|
|
24933
|
+
const busy = Boolean(context.busyAction);
|
|
24934
|
+
const disabledReason = mutationsDisabled ? "Reconnect to continue." : busy ? "This action is already in progress." : null;
|
|
24935
|
+
const actionDisabled = Boolean(disabledReason);
|
|
24936
|
+
const transportStatus = context.transportStatus || "connected";
|
|
24937
|
+
let kind;
|
|
24938
|
+
if (artifact.status === "completed" && workflowStatus === "completed") {
|
|
24939
|
+
kind = "result";
|
|
24940
|
+
} else if (artifact.status === "completed" && workflowStatus === "failed") {
|
|
24941
|
+
kind = "failure";
|
|
24942
|
+
} else if (artifact.status === "completed" && workflowStatus === "working") {
|
|
24943
|
+
kind = "executing";
|
|
24944
|
+
} else if (artifact.status === "completed" && workflowStatus && workflowStatus !== "canceled") {
|
|
24945
|
+
kind = "blocked";
|
|
24946
|
+
} else if (artifact.status === "completed") kind = "result";
|
|
24947
|
+
else if (artifact.status === "canceled") kind = "canceled";
|
|
24948
|
+
else if (artifact.status === "stale") kind = "stale";
|
|
24949
|
+
else if (artifact.status === "partially_completed") kind = "partial";
|
|
24950
|
+
else if (artifact.status === "failed" || context.directError)
|
|
24951
|
+
kind = "failure";
|
|
24952
|
+
else if (artifact.status === "blocked") kind = "blocked";
|
|
24953
|
+
else if (artifact.status === "awaiting_human") kind = "approval";
|
|
24954
|
+
else if (artifact.status === "running" || busy) kind = "executing";
|
|
24955
|
+
else if (requestedEditorNodeId || artifact.status === "draft" || artifact.status === "needs_edit") {
|
|
24956
|
+
kind = "input";
|
|
24957
|
+
} else {
|
|
24958
|
+
kind = "review";
|
|
24959
|
+
}
|
|
24960
|
+
let title = artifact.label;
|
|
24961
|
+
let description = artifact.description || null;
|
|
24962
|
+
let statusLabel = null;
|
|
24963
|
+
let primaryAction = null;
|
|
24964
|
+
let secondaryActions = [];
|
|
24965
|
+
if (kind === "input") {
|
|
24966
|
+
title = activeInput?.label || artifact.label;
|
|
24967
|
+
description = activeInput?.description || artifact.description || null;
|
|
24968
|
+
statusLabel = activeInput?.status === "needs_input" ? "Needs input" : null;
|
|
24969
|
+
primaryAction = action(
|
|
24970
|
+
"continue",
|
|
24971
|
+
"Continue",
|
|
24972
|
+
"primary",
|
|
24973
|
+
actionDisabled,
|
|
24974
|
+
disabledReason
|
|
24975
|
+
);
|
|
24976
|
+
} else if (kind === "review") {
|
|
24977
|
+
title = artifact.label;
|
|
24978
|
+
description = artifact.description || operation?.description || null;
|
|
24979
|
+
primaryAction = action(
|
|
24980
|
+
"execute",
|
|
24981
|
+
operation?.label || "Continue",
|
|
24982
|
+
"primary",
|
|
24983
|
+
actionDisabled || context.canExecute === false,
|
|
24984
|
+
disabledReason
|
|
24985
|
+
);
|
|
24986
|
+
if (context.canEdit) {
|
|
24987
|
+
secondaryActions = [
|
|
24988
|
+
action(
|
|
24989
|
+
"edit",
|
|
24990
|
+
"Edit details",
|
|
24991
|
+
"secondary",
|
|
24992
|
+
actionDisabled,
|
|
24993
|
+
disabledReason
|
|
24994
|
+
)
|
|
24995
|
+
];
|
|
24996
|
+
}
|
|
24997
|
+
} else if (kind === "executing") {
|
|
24998
|
+
title = operation?.operationDetail || operation?.label || artifact.label;
|
|
24999
|
+
description = operation?.operationDetail ? artifact.label : null;
|
|
25000
|
+
statusLabel = operationStatusLabel(operation?.operationPhase) || "In progress";
|
|
25001
|
+
} else if (kind === "approval") {
|
|
25002
|
+
title = operation?.attention?.title || operation?.label || artifact.label;
|
|
25003
|
+
description = operation?.attention?.detail || operation?.description || null;
|
|
25004
|
+
statusLabel = "Awaiting approval";
|
|
25005
|
+
if (context.canApprove) {
|
|
25006
|
+
primaryAction = action(
|
|
25007
|
+
"approve",
|
|
25008
|
+
"Approve",
|
|
25009
|
+
"primary",
|
|
25010
|
+
actionDisabled,
|
|
25011
|
+
disabledReason
|
|
25012
|
+
);
|
|
25013
|
+
secondaryActions = [
|
|
25014
|
+
action(
|
|
25015
|
+
"decline",
|
|
25016
|
+
"Decline",
|
|
25017
|
+
"secondary",
|
|
25018
|
+
actionDisabled,
|
|
25019
|
+
disabledReason
|
|
25020
|
+
)
|
|
25021
|
+
];
|
|
25022
|
+
}
|
|
25023
|
+
} else if (kind === "failure" || kind === "blocked") {
|
|
25024
|
+
const attention = current?.attention || operation?.attention;
|
|
25025
|
+
title = attention?.title || artifact.label;
|
|
25026
|
+
description = context.directError || attention?.detail || operation?.description || null;
|
|
25027
|
+
statusLabel = kind === "failure" ? "Failed" : "Needs attention";
|
|
25028
|
+
if (attention?.retryable) {
|
|
25029
|
+
primaryAction = action(
|
|
25030
|
+
"retry",
|
|
25031
|
+
"Retry",
|
|
25032
|
+
"primary",
|
|
25033
|
+
actionDisabled,
|
|
25034
|
+
disabledReason
|
|
25035
|
+
);
|
|
25036
|
+
} else if (context.canEdit) {
|
|
25037
|
+
primaryAction = action(
|
|
25038
|
+
"edit",
|
|
25039
|
+
"Edit details",
|
|
25040
|
+
"primary",
|
|
25041
|
+
actionDisabled,
|
|
25042
|
+
disabledReason
|
|
25043
|
+
);
|
|
25044
|
+
}
|
|
25045
|
+
} else if (kind === "partial") {
|
|
25046
|
+
title = operation?.attention?.title || artifact.label;
|
|
25047
|
+
description = operation?.attention?.detail || operation?.description || null;
|
|
25048
|
+
statusLabel = "Partially completed";
|
|
25049
|
+
primaryAction = action(
|
|
25050
|
+
"retry",
|
|
25051
|
+
"Retry unfinished work",
|
|
25052
|
+
"primary",
|
|
25053
|
+
actionDisabled,
|
|
25054
|
+
disabledReason
|
|
25055
|
+
);
|
|
25056
|
+
} else if (kind === "stale") {
|
|
25057
|
+
title = operation?.attention?.title || artifact.label;
|
|
25058
|
+
description = operation?.attention?.detail || operation?.description || null;
|
|
25059
|
+
statusLabel = "Details changed";
|
|
25060
|
+
primaryAction = action(
|
|
25061
|
+
"refresh",
|
|
25062
|
+
"Review latest details",
|
|
25063
|
+
"primary",
|
|
25064
|
+
actionDisabled,
|
|
25065
|
+
disabledReason
|
|
25066
|
+
);
|
|
25067
|
+
} else if (kind === "result") {
|
|
25068
|
+
title = artifact.label;
|
|
25069
|
+
description = operation?.recap?.summary || artifact.description || null;
|
|
25070
|
+
statusLabel = "Completed";
|
|
25071
|
+
primaryAction = action("close", "Done", "primary", false);
|
|
25072
|
+
} else {
|
|
25073
|
+
title = artifact.label;
|
|
25074
|
+
description = operation?.attention?.detail || "Nothing else will run.";
|
|
25075
|
+
statusLabel = "Canceled";
|
|
25076
|
+
primaryAction = action("close", "Done", "primary", false);
|
|
25077
|
+
}
|
|
25078
|
+
const activeNodeId = kind === "input" ? activeInput?.id || workflow.currentNodeId : workflow.currentNodeId;
|
|
25079
|
+
const announcement = [statusLabel, title, description].filter((value) => Boolean(value)).join(". ");
|
|
25080
|
+
return {
|
|
25081
|
+
artifactId: artifact.artifactId,
|
|
25082
|
+
revision: workflow.revision,
|
|
25083
|
+
updatedAt: artifact.updatedAt,
|
|
25084
|
+
kind,
|
|
25085
|
+
title,
|
|
25086
|
+
description,
|
|
25087
|
+
statusLabel,
|
|
25088
|
+
announcement,
|
|
25089
|
+
workflow,
|
|
25090
|
+
activeNodeId,
|
|
25091
|
+
operationNodeId: operation?.id || null,
|
|
25092
|
+
showNavigation: navigationIsUseful(workflow),
|
|
25093
|
+
primaryAction,
|
|
25094
|
+
secondaryActions,
|
|
25095
|
+
transportStatus
|
|
25096
|
+
};
|
|
25097
|
+
}
|
|
25098
|
+
|
|
25099
|
+
export { Environment, EnvironmentSession, GRANULAR_FEED_DIAGNOSTIC_EVENT, Granular, OPENAI_MODEL_PRICING_USD_PER_MILLION, OntologyHandle, Session, SessionFeedController, WSClient, assertArtifactWorkflow, buildContinuationInstruction, buildContinuationInstructionFromTemplate, buildGranularAgentCheckpointBlock, buildGranularAgentDomainBlock, buildGranularAgentFileBlock, buildGranularAgentHeapBlock, buildGranularAgentLoopBlock, buildGranularAgentManualActionBlock, buildGranularAgentManualActionMemorySummary, buildGranularAgentReferentBlock, buildGranularAgentRuntimeImportsBlock, buildGranularAgentSessionBlock, buildGranularAgentSystemPrompt, buildGranularAgentSystemPromptFromTemplate, buildGranularAgentToolBlock, buildGranularAgentWorkflowBlock, buildOpenAISpendEventId, buildSessionTranscript, buildSessionTranscriptFromFeedItems, calculateOpenAITokenSpend, canInspectArtifactWorkflowNode, canonicalizeCommitValue, changedRecordSnapshots, consumeGranularReasoningOnlyChunk, consumeGranularReasoningTraceChunk, createFeedPublisher, createHarnessVerifierSnapshot, defineEffect, defineProjection, defineStateMachine, emitFeedDiagnostic, emitFeedDiagnosticToDefaultSink, emptyFeedSnapshot, environmentSetupProgressFromError, environmentSetupProgressFromResponse, evaluateContinuation, evaluateValidationRule, extractPromptTokens, getArtifactWorkflowNavigationLeaves, getArtifactWorkflowNavigationTarget, getArtifactWorkflowNodes, getCurrentArtifactWorkflowNode, getCurrentClosureId, getDefaultHarnessTemplateId, getExclusivePromptTarget, getOpenAIModelPricing, hasCanonicalSessionFeedActivation, hasOpenPrompt, hashHarnessTemplateValue, invokeRegisteredEffect, isArtifactWorkflowNodeNavigableLeaf, isArtifactWorkflowNodeTerminal, isCanonicalSessionFeedDocument, isGraphQLMutationDocument, isLocalApiUrl, listHarnessTemplates, mergeFeedItemsBySequence, normalizeEffectBehaviors, normalizeFeedDiagnostic, normalizeFeedDiagnosticKind, normalizeFeedPage, normalizeOpenAIUsage, normalizePrompt, normalizePromptChoiceOption, normalizePromptText, normalizePromptType, orderTransientFeedItems, pollEnvironmentSetup, projectArtifactWorkflow, projectConversationReferentFocus, projectConversationReferentSummary, projectHeapSummary, projectLoopSummary, projectRecordSnapshotMutation, projectSessionFileSummary, projectWorkflowFocus, projectWorkflowSummary, readSessionFeedSnapshot, recordOpenAIUsageSpend, renderContinuationInstructionFromTemplate, renderGranularAgentSystemPromptFromTemplate, requireArtifactWorkflow, requireArtifactWorkflowResult, resolveApiUrl, resolveAuthTokenForApiUrl, resolveHarnessTemplate, resolveJobPresentation, resolvePromptAnswer, reviewGeneratedJobCode, scorePromptChoiceMatch, selectArtifactSurface, stripGranularReasoningTrace, toGranularHttpBase, validateHarnessTemplateManifest, validateProjectionResult, validationRuleFailureMessage };
|
|
23948
25100
|
//# sourceMappingURL=index.mjs.map
|
|
23949
25101
|
//# sourceMappingURL=index.mjs.map
|