@everfir/az8-cli 0.3.0-preview.1 → 0.3.0-preview.2
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/CHANGELOG.md +23 -0
- package/README.md +1 -1
- package/RELEASE.md +1 -1
- package/dist/main.js +489 -45
- package/package.json +1 -1
- package/skills/az8-cli/SKILL.md +30 -4
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,29 @@ it does not inherit the Web application or monorepo root version.
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## 0.3.0-preview.2 - 2026-07-23
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Cursor-only Awareness acknowledgement after a remote Canvas Watch delivery has been flushed and
|
|
13
|
+
internally acknowledged.
|
|
14
|
+
- Advisory `data.createdByCli` provenance on every View Node created through the CLI.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- CLI-created Notes retain the authenticated Actor id and display the current client suffix in
|
|
19
|
+
their visible creator label.
|
|
20
|
+
- Ordinary Resource View Nodes no longer receive invented generic creator metadata.
|
|
21
|
+
- The built-in agent Skill recommends early visible generation targets and empty Text Resources
|
|
22
|
+
when artifact type and placement are already unambiguous.
|
|
23
|
+
|
|
24
|
+
### Safety and compatibility
|
|
25
|
+
|
|
26
|
+
- Delivery Awareness never responds to the CLI's own changes, never publishes Selection, and does
|
|
27
|
+
not represent understanding or completion.
|
|
28
|
+
- Editing an existing View Node preserves its creation provenance; duplicating stamps the new node
|
|
29
|
+
with the current client suffix.
|
|
30
|
+
|
|
8
31
|
## 0.3.0-preview.1 - 2026-07-23
|
|
9
32
|
|
|
10
33
|
### Added
|
package/README.md
CHANGED
package/RELEASE.md
CHANGED
|
@@ -60,7 +60,7 @@ authorization:
|
|
|
60
60
|
For a preview candidate, publish the exact retained artifact to the preview channel:
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
npm publish ./tmp/az8-cli-release/everfir-az8-cli-0.3.0-preview.
|
|
63
|
+
npm publish ./tmp/az8-cli-release/everfir-az8-cli-0.3.0-preview.2.tgz --tag preview
|
|
64
64
|
npm view @everfir/az8-cli dist-tags versions --json
|
|
65
65
|
```
|
|
66
66
|
|
package/dist/main.js
CHANGED
|
@@ -14175,11 +14175,26 @@ var CANVAS_OPERATION_REGISTRY = [
|
|
|
14175
14175
|
},
|
|
14176
14176
|
required: ["referenceViewNodeId", "viewNodeId"]
|
|
14177
14177
|
}),
|
|
14178
|
+
write2("insertPromptReference", "Bind one visible image, text, or video View Node and place its platform At token in the Prompt", "silent", {
|
|
14179
|
+
properties: {
|
|
14180
|
+
placement: { enum: ["start", "end"], type: "string" },
|
|
14181
|
+
referenceViewNodeId: stringSchema(),
|
|
14182
|
+
viewNodeId: stringSchema()
|
|
14183
|
+
},
|
|
14184
|
+
required: ["referenceViewNodeId", "viewNodeId"]
|
|
14185
|
+
}),
|
|
14178
14186
|
write2("removeVisualReference", "Remove one Canvas View Node reference from a generation Draft", "silent", {
|
|
14179
14187
|
properties: { referenceId: stringSchema(), viewNodeId: stringSchema() },
|
|
14180
14188
|
required: ["referenceId", "viewNodeId"]
|
|
14181
14189
|
}),
|
|
14182
14190
|
write2("startGeneration", "Estimate current Draft inputs, start a Workflow Run, and acknowledge immediate Canvas writes", "barrier", { properties: { viewNodeId: stringSchema() }, required: ["viewNodeId"] }, "workflow-accepted"),
|
|
14191
|
+
write2("reconcileGenerationStart", "Reconcile one known Workflow Run with its target without starting another Run", "barrier", {
|
|
14192
|
+
properties: {
|
|
14193
|
+
viewNodeId: stringSchema(),
|
|
14194
|
+
workflowRunId: stringSchema()
|
|
14195
|
+
},
|
|
14196
|
+
required: ["viewNodeId", "workflowRunId"]
|
|
14197
|
+
}),
|
|
14183
14198
|
read("getWorkflowRun", "Read one Workflow Run", {
|
|
14184
14199
|
properties: { workflowRunId: stringSchema() },
|
|
14185
14200
|
required: ["workflowRunId"]
|
|
@@ -14246,10 +14261,25 @@ function sizeSchema() {
|
|
|
14246
14261
|
}
|
|
14247
14262
|
|
|
14248
14263
|
// ../../packages/project-canvas-runtime/dist/operation-usage.js
|
|
14264
|
+
function attachCanvasOperationIndeterminateResult(value, result3) {
|
|
14265
|
+
const cause = value instanceof Error ? value : new Error("Unexpected Canvas Operation failure.");
|
|
14266
|
+
const error51 = new Error(cause.message, { cause });
|
|
14267
|
+
return Object.assign(error51, {
|
|
14268
|
+
indeterminate: true,
|
|
14269
|
+
operationResult: structuredClone(result3),
|
|
14270
|
+
..."timedOut" in cause && cause.timedOut === true ? { timedOut: true } : {}
|
|
14271
|
+
});
|
|
14272
|
+
}
|
|
14249
14273
|
function attachCanvasOperationUsage(value, usage) {
|
|
14250
14274
|
const error51 = value instanceof Error ? value : new Error("Unexpected Canvas Operation failure.");
|
|
14251
14275
|
return Object.assign(error51, { operationUsage: usage });
|
|
14252
14276
|
}
|
|
14277
|
+
function readCanvasOperationIndeterminateResult(value) {
|
|
14278
|
+
if (typeof value !== "object" || value === null || !("operationResult" in value))
|
|
14279
|
+
return void 0;
|
|
14280
|
+
const result3 = value.operationResult;
|
|
14281
|
+
return typeof result3 === "object" && result3 !== null && !Array.isArray(result3) ? result3 : void 0;
|
|
14282
|
+
}
|
|
14253
14283
|
function readCanvasOperationUsage(value) {
|
|
14254
14284
|
if (typeof value !== "object" || value === null || !("operationUsage" in value))
|
|
14255
14285
|
return void 0;
|
|
@@ -15022,6 +15052,37 @@ function addVisualReferenceToDraft(draft, definition, reference, sourceDataType,
|
|
|
15022
15052
|
}
|
|
15023
15053
|
return appendPromptReferenceToken(nextDraft, slot.name, reference.id, reference.viewNodeId, now);
|
|
15024
15054
|
}
|
|
15055
|
+
function insertPromptReferenceIntoDraft(draft, definition, reference, sourceDataType, placement, now) {
|
|
15056
|
+
const withReference = addVisualReferenceToDraft(draft, definition, reference, sourceDataType, now);
|
|
15057
|
+
const binding = Object.entries(withReference.inputs.slots).flatMap(([slotName, values]) => values.flatMap((value, index) => value.kind === "view-node" && value.id === reference.id ? [{ index, slotName, value }] : []))[0];
|
|
15058
|
+
if (!binding)
|
|
15059
|
+
throw new Error(`Generation Reference ${reference.id} does not exist in the Draft.`);
|
|
15060
|
+
if (binding.value.sourceDataType !== "image" && binding.value.sourceDataType !== "text" && binding.value.sourceDataType !== "video") {
|
|
15061
|
+
throw new Error("Prompt References must resolve to image, text, or video content.");
|
|
15062
|
+
}
|
|
15063
|
+
const promptSlot = requirePromptSlot(definition);
|
|
15064
|
+
const withoutExistingToken = removePromptReferenceToken(withReference, reference.id);
|
|
15065
|
+
const promptValues = withoutExistingToken.inputs.slots[promptSlot.name] ?? [];
|
|
15066
|
+
const existingLiteral = promptValues.find((value) => value.kind === "literal" && value.assetType === "text");
|
|
15067
|
+
const promptInput = existingLiteral ?? literal(withoutExistingToken, promptSlot.name, "text", "");
|
|
15068
|
+
const prompt = promptInput.content;
|
|
15069
|
+
const token = `{{@${binding.value.sourceDataType}:${binding.slotName}:${binding.index}:${reference.id}|view-node|${encodeURIComponent(reference.viewNodeId)}}}`;
|
|
15070
|
+
const content = placement === "start" ? prompt.trim() ? `${token}
|
|
15071
|
+
${prompt}` : token : prompt.trim() ? `${prompt}${prompt.endsWith("\n") ? "" : "\n"}${token}` : token;
|
|
15072
|
+
return {
|
|
15073
|
+
...structuredClone(withoutExistingToken),
|
|
15074
|
+
inputs: {
|
|
15075
|
+
slots: {
|
|
15076
|
+
...structuredClone(withoutExistingToken.inputs.slots),
|
|
15077
|
+
[promptSlot.name]: [
|
|
15078
|
+
{ ...promptInput, content },
|
|
15079
|
+
...promptValues.filter((value) => value.id !== promptInput.id)
|
|
15080
|
+
]
|
|
15081
|
+
}
|
|
15082
|
+
},
|
|
15083
|
+
updatedAt: now
|
|
15084
|
+
};
|
|
15085
|
+
}
|
|
15025
15086
|
function removeVisualReferenceFromDraft(draft, referenceId, now) {
|
|
15026
15087
|
let removed = false;
|
|
15027
15088
|
let removedTextReference = false;
|
|
@@ -15322,7 +15383,8 @@ function createGenerationExecutionOperations(input) {
|
|
|
15322
15383
|
if (definitionChanges || Object.keys(editInput).length > 2) {
|
|
15323
15384
|
operations.push({ input: editInput, name: "editGenerationDraft" });
|
|
15324
15385
|
}
|
|
15325
|
-
const
|
|
15386
|
+
const promptSlotName = resolvePromptSlot(input.definition)?.name;
|
|
15387
|
+
const currentReferences = (definitionChanges ? [] : readGenerationDraftReferences(input.currentDraft)).filter((reference) => editInput.prompt === void 0 || reference.sourceSlotName !== promptSlotName);
|
|
15326
15388
|
const desiredKeys = new Set(input.assignments.map((item) => referenceKey(item.reference)));
|
|
15327
15389
|
for (const current of currentReferences) {
|
|
15328
15390
|
if (!current.draftInputId || desiredKeys.has(referenceKey(current)))
|
|
@@ -15823,7 +15885,14 @@ async function resolveEffectiveTextInputContent(input) {
|
|
|
15823
15885
|
if (!literal3)
|
|
15824
15886
|
return null;
|
|
15825
15887
|
const fragmentsByBindingId = /* @__PURE__ */ new Map();
|
|
15826
|
-
|
|
15888
|
+
const bindingsById = /* @__PURE__ */ new Map();
|
|
15889
|
+
for (const [slotName, references] of Object.entries(input.allReferencesBySlot)) {
|
|
15890
|
+
for (const reference of references) {
|
|
15891
|
+
if (reference.kind !== "literal")
|
|
15892
|
+
bindingsById.set(reference.id, { reference, slotName });
|
|
15893
|
+
}
|
|
15894
|
+
}
|
|
15895
|
+
for (const reference of Object.values(input.allReferencesBySlot).flat()) {
|
|
15827
15896
|
if (reference.kind !== "view-node" || reference.sourceDataType !== "text")
|
|
15828
15897
|
continue;
|
|
15829
15898
|
const content = await input.resolveViewNodeTextContent(reference.viewNodeId);
|
|
@@ -15831,8 +15900,17 @@ async function resolveEffectiveTextInputContent(input) {
|
|
|
15831
15900
|
fragmentsByBindingId.set(reference.id, content.trim());
|
|
15832
15901
|
}
|
|
15833
15902
|
const positionedBindingIds = /* @__PURE__ */ new Set();
|
|
15834
|
-
const positionedContent = literal3.content.replace(new RegExp(PROMPT_REFERENCE_TOKEN_PATTERN2, "g"), (token,
|
|
15903
|
+
const positionedContent = literal3.content.replace(new RegExp(PROMPT_REFERENCE_TOKEN_PATTERN2, "g"), (token, contentType, slotName, _rawIndex, bindingId, encodedViewNodeId) => {
|
|
15835
15904
|
if (!bindingId)
|
|
15905
|
+
throw new Error("Prompt contains an At token without a binding identity.");
|
|
15906
|
+
const binding = bindingsById.get(bindingId);
|
|
15907
|
+
if (!binding || binding.slotName !== slotName || binding.reference.sourceDataType !== contentType) {
|
|
15908
|
+
throw new Error(`Prompt At token ${bindingId} does not match its Generation binding.`);
|
|
15909
|
+
}
|
|
15910
|
+
if (encodedViewNodeId && (binding.reference.kind !== "view-node" || binding.reference.viewNodeId !== decodePromptViewNodeId(encodedViewNodeId))) {
|
|
15911
|
+
throw new Error(`Prompt At token ${bindingId} does not match its View Node.`);
|
|
15912
|
+
}
|
|
15913
|
+
if (contentType !== "text")
|
|
15836
15914
|
return token;
|
|
15837
15915
|
const content = fragmentsByBindingId.get(bindingId);
|
|
15838
15916
|
if (content === void 0)
|
|
@@ -15841,11 +15919,21 @@ async function resolveEffectiveTextInputContent(input) {
|
|
|
15841
15919
|
return content;
|
|
15842
15920
|
});
|
|
15843
15921
|
const trailingFragments = [...fragmentsByBindingId.entries()].flatMap(([bindingId, content]) => positionedBindingIds.has(bindingId) ? [] : [content]);
|
|
15844
|
-
|
|
15922
|
+
const unresolvedTextToken = [
|
|
15923
|
+
...positionedContent.matchAll(new RegExp(PROMPT_REFERENCE_TOKEN_PATTERN2, "g"))
|
|
15924
|
+
].some((match) => match[1] === "text");
|
|
15925
|
+
if (unresolvedTextToken) {
|
|
15845
15926
|
throw new Error("Prompt contains an unresolved Text View Node reference.");
|
|
15846
15927
|
}
|
|
15847
15928
|
return appendUniqueTextFragments(positionedContent, trailingFragments);
|
|
15848
15929
|
}
|
|
15930
|
+
function decodePromptViewNodeId(value) {
|
|
15931
|
+
try {
|
|
15932
|
+
return decodeURIComponent(value);
|
|
15933
|
+
} catch {
|
|
15934
|
+
throw new Error("Prompt At token contains an invalid View Node identity.");
|
|
15935
|
+
}
|
|
15936
|
+
}
|
|
15849
15937
|
function appendUniqueTextFragments(base, fragments) {
|
|
15850
15938
|
let result3 = base;
|
|
15851
15939
|
for (const fragment of fragments) {
|
|
@@ -15865,6 +15953,7 @@ async function prepareGenerationInput(input) {
|
|
|
15865
15953
|
for (const slot of input.definition.inputSchema) {
|
|
15866
15954
|
const references = input.draft.inputs.slots[slot.name] ?? [];
|
|
15867
15955
|
const effectiveText = slot.name === promptSlot?.name ? await resolveEffectiveTextInputContent({
|
|
15956
|
+
allReferencesBySlot: input.draft.inputs.slots,
|
|
15868
15957
|
references,
|
|
15869
15958
|
resolveViewNodeTextContent: input.resolveViewNodeTextContent
|
|
15870
15959
|
}) : null;
|
|
@@ -15981,10 +16070,15 @@ var CoreNodeCreativeLoop = class {
|
|
|
15981
16070
|
return this.editDraft(input, timeoutMs);
|
|
15982
16071
|
if (name === "addVisualReference")
|
|
15983
16072
|
return this.addVisualReference(input, timeoutMs);
|
|
16073
|
+
if (name === "insertPromptReference")
|
|
16074
|
+
return this.insertPromptReference(input, timeoutMs);
|
|
15984
16075
|
if (name === "removeVisualReference")
|
|
15985
16076
|
return this.removeVisualReference(input, timeoutMs);
|
|
15986
16077
|
if (name === "startGeneration")
|
|
15987
16078
|
return this.startGeneration(input, timeoutMs);
|
|
16079
|
+
if (name === "reconcileGenerationStart") {
|
|
16080
|
+
return this.reconcileGenerationStart(input, timeoutMs);
|
|
16081
|
+
}
|
|
15988
16082
|
if (name === "getWorkflowRun")
|
|
15989
16083
|
return this.getWorkflowRun(input);
|
|
15990
16084
|
if (name === "waitWorkflowRun")
|
|
@@ -16160,23 +16254,28 @@ var CoreNodeCreativeLoop = class {
|
|
|
16160
16254
|
const draft = requireDraft(target);
|
|
16161
16255
|
const definition = await this.requireDefinition(draft.definitionId);
|
|
16162
16256
|
const referenceViewNodeId = requireString3(input.referenceViewNodeId, "referenceViewNodeId");
|
|
16163
|
-
const
|
|
16164
|
-
if (referenceViewNode.type !== "resource") {
|
|
16165
|
-
throw new Error("Generation References require a resource View Node.");
|
|
16166
|
-
}
|
|
16167
|
-
let sourceDataType = referenceViewNode.contentType ?? "";
|
|
16168
|
-
const referenceCoreNodeId = this.resolveViewNodeCoreNodeId(referenceViewNode);
|
|
16169
|
-
if (sourceDataType !== "text" || asRecord3(referenceViewNode.data).mode === "content") {
|
|
16170
|
-
if (!referenceCoreNodeId)
|
|
16171
|
-
throw new Error("Referenced View Node has no current Core Node.");
|
|
16172
|
-
const coreNode = await this.requireCoreNode(referenceCoreNodeId);
|
|
16173
|
-
sourceDataType = readCoreNodeDataType2(coreNode);
|
|
16174
|
-
}
|
|
16257
|
+
const sourceDataType = await this.resolveReferenceDataType(referenceViewNodeId);
|
|
16175
16258
|
const referenceId = `input_ref_${crypto.randomUUID().replaceAll("-", "")}`;
|
|
16176
16259
|
const nextDraft = addVisualReferenceToDraft(draft, definition, { id: referenceId, kind: "view-node", viewNodeId: referenceViewNodeId }, sourceDataType, this.context.now());
|
|
16177
16260
|
await this.replaceDraft(target, nextDraft, "Add Visual Reference", timeoutMs);
|
|
16178
16261
|
return attention(target.id, { referenceId, viewNodeId: target.id });
|
|
16179
16262
|
}
|
|
16263
|
+
async insertPromptReference(input, timeoutMs) {
|
|
16264
|
+
assertOnlyKeys3(input, ["placement", "referenceViewNodeId", "viewNodeId"]);
|
|
16265
|
+
const target = this.requireTarget(requireString3(input.viewNodeId, "viewNodeId"));
|
|
16266
|
+
const draft = requireDraft(target);
|
|
16267
|
+
const definition = await this.requireDefinition(draft.definitionId);
|
|
16268
|
+
const referenceViewNodeId = requireString3(input.referenceViewNodeId, "referenceViewNodeId");
|
|
16269
|
+
const sourceDataType = await this.resolveReferenceDataType(referenceViewNodeId);
|
|
16270
|
+
const existing = Object.values(draft.inputs.slots).flat().find((reference) => reference.kind === "view-node" && reference.viewNodeId === referenceViewNodeId);
|
|
16271
|
+
const referenceId = existing?.id ?? `input_ref_${crypto.randomUUID().replaceAll("-", "")}`;
|
|
16272
|
+
const placement = input.placement === void 0 ? "end" : input.placement === "start" || input.placement === "end" ? input.placement : null;
|
|
16273
|
+
if (!placement)
|
|
16274
|
+
throw new Error("placement must be start or end.");
|
|
16275
|
+
const nextDraft = insertPromptReferenceIntoDraft(draft, definition, { id: referenceId, kind: "view-node", viewNodeId: referenceViewNodeId }, sourceDataType, placement, this.context.now());
|
|
16276
|
+
await this.replaceDraft(target, nextDraft, "Insert Prompt Reference", timeoutMs);
|
|
16277
|
+
return attention(target.id, { placement, referenceId, viewNodeId: target.id });
|
|
16278
|
+
}
|
|
16180
16279
|
async removeVisualReference(input, timeoutMs) {
|
|
16181
16280
|
assertOnlyKeys3(input, ["referenceId", "viewNodeId"]);
|
|
16182
16281
|
const target = this.requireTarget(requireString3(input.viewNodeId, "viewNodeId"));
|
|
@@ -16187,7 +16286,8 @@ var CoreNodeCreativeLoop = class {
|
|
|
16187
16286
|
}
|
|
16188
16287
|
async startGeneration(input, timeoutMs) {
|
|
16189
16288
|
let estimate;
|
|
16190
|
-
let
|
|
16289
|
+
let acceptedRun;
|
|
16290
|
+
let acceptedTargetId;
|
|
16191
16291
|
try {
|
|
16192
16292
|
assertOnlyKeys3(input, ["viewNodeId"]);
|
|
16193
16293
|
const target = this.requireTarget(requireString3(input.viewNodeId, "viewNodeId"));
|
|
@@ -16200,6 +16300,10 @@ var CoreNodeCreativeLoop = class {
|
|
|
16200
16300
|
resolveViewNodeCoreNodeId: (id2) => this.resolveViewNodeCoreNodeId(this.requireViewNode(id2)),
|
|
16201
16301
|
resolveViewNodeTextContent: (id2) => this.resolveViewNodeTextContent(this.requireViewNode(id2))
|
|
16202
16302
|
});
|
|
16303
|
+
const targetSnapshot = structuredClone(target);
|
|
16304
|
+
const targetData = normalizeOptionalRecord(target.data, "View Node data");
|
|
16305
|
+
const targetHistory = readGenerationHistory(target.history);
|
|
16306
|
+
const effectivePrompt = readPrompt(prepared.effectiveDraft);
|
|
16203
16307
|
estimate = await this.systems.workflowRuntime.estimateRun({ definitionId: definition.id, inputs: prepared.estimateInputs }, { timeoutMs });
|
|
16204
16308
|
if (!estimate.canAfford)
|
|
16205
16309
|
throw new Error("Insufficient credits to start this generation.");
|
|
@@ -16218,7 +16322,8 @@ var CoreNodeCreativeLoop = class {
|
|
|
16218
16322
|
{ slotName: output.slotName, targetId: target.id, targetSlot: draft.id }
|
|
16219
16323
|
]
|
|
16220
16324
|
}, { timeoutMs });
|
|
16221
|
-
|
|
16325
|
+
acceptedRun = run;
|
|
16326
|
+
acceptedTargetId = target.id;
|
|
16222
16327
|
this.runs.set(run.id, run);
|
|
16223
16328
|
const timestamp = this.context.now();
|
|
16224
16329
|
const historyEntry = {
|
|
@@ -16234,15 +16339,15 @@ var CoreNodeCreativeLoop = class {
|
|
|
16234
16339
|
},
|
|
16235
16340
|
updatedAt: timestamp
|
|
16236
16341
|
};
|
|
16237
|
-
const { creationIntent: _creationIntent, ...data } =
|
|
16342
|
+
const { creationIntent: _creationIntent, ...data } = targetData;
|
|
16238
16343
|
const after = {
|
|
16239
|
-
...
|
|
16344
|
+
...targetSnapshot,
|
|
16240
16345
|
data: {
|
|
16241
16346
|
...data,
|
|
16242
|
-
...
|
|
16347
|
+
...effectivePrompt === null ? {} : { prompt: effectivePrompt }
|
|
16243
16348
|
},
|
|
16244
16349
|
draft: null,
|
|
16245
|
-
history: toDocumentJson([...
|
|
16350
|
+
history: toDocumentJson([...targetHistory, historyEntry]),
|
|
16246
16351
|
updatedAt: timestamp
|
|
16247
16352
|
};
|
|
16248
16353
|
await this.context.commit({
|
|
@@ -16264,8 +16369,15 @@ var CoreNodeCreativeLoop = class {
|
|
|
16264
16369
|
usage: estimatedUsage(estimate)
|
|
16265
16370
|
};
|
|
16266
16371
|
} catch (error51) {
|
|
16267
|
-
const
|
|
16268
|
-
|
|
16372
|
+
const failure = acceptedRun && acceptedTargetId ? attachCanvasOperationIndeterminateResult(error51, {
|
|
16373
|
+
canvasAcknowledged: false,
|
|
16374
|
+
reconciliationRequired: true,
|
|
16375
|
+
status: acceptedRun.status,
|
|
16376
|
+
viewNodeId: acceptedTargetId,
|
|
16377
|
+
workflowRunId: acceptedRun.id
|
|
16378
|
+
}) : error51;
|
|
16379
|
+
const usage = acceptedRun && estimate ? estimatedUsage(estimate) : isIndeterminateWrite(error51) ? unknownUsage(estimate) : notConsumedUsage(estimate);
|
|
16380
|
+
throw attachCanvasOperationUsage(failure, usage);
|
|
16269
16381
|
}
|
|
16270
16382
|
}
|
|
16271
16383
|
async getWorkflowRun(input) {
|
|
@@ -16273,6 +16385,133 @@ var CoreNodeCreativeLoop = class {
|
|
|
16273
16385
|
const run = await this.refreshRun(requireString3(input.workflowRunId, "workflowRunId"), 15e3);
|
|
16274
16386
|
return { result: { workflowRun: run } };
|
|
16275
16387
|
}
|
|
16388
|
+
async reconcileGenerationStart(input, timeoutMs) {
|
|
16389
|
+
assertOnlyKeys3(input, ["viewNodeId", "workflowRunId"]);
|
|
16390
|
+
const target = this.requireTarget(requireString3(input.viewNodeId, "viewNodeId"));
|
|
16391
|
+
const workflowRunId = requireString3(input.workflowRunId, "workflowRunId");
|
|
16392
|
+
const run = await this.systems.workflowRuntime.getRun(workflowRunId);
|
|
16393
|
+
if (!run)
|
|
16394
|
+
throw new Error(`Workflow Run ${workflowRunId} does not exist.`);
|
|
16395
|
+
this.recordRun(run);
|
|
16396
|
+
const sync = await this.systems.projectContent.syncProject(this.context.projectId, 0, {
|
|
16397
|
+
timeoutMs
|
|
16398
|
+
});
|
|
16399
|
+
this.projection.merge(sync.contents);
|
|
16400
|
+
const history = readGenerationHistory(target.history);
|
|
16401
|
+
const existing = history.find((entry) => entry.runtime.instanceIds.includes(run.id));
|
|
16402
|
+
if (existing) {
|
|
16403
|
+
if (existing.definitionId !== run.definitionId) {
|
|
16404
|
+
return reconciliationResult(target.id, run.id, "conflict", {
|
|
16405
|
+
reason: "The existing History entry and Workflow Run use different Definitions."
|
|
16406
|
+
});
|
|
16407
|
+
}
|
|
16408
|
+
const repairedPendingState = !isTerminalWorkflowRunStatus(run.status) && !this.isPending(run.id);
|
|
16409
|
+
if (isTerminalWorkflowRunStatus(run.status))
|
|
16410
|
+
await this.settleRun(run, timeoutMs);
|
|
16411
|
+
else if (repairedPendingState) {
|
|
16412
|
+
await this.context.commit({
|
|
16413
|
+
addPendingWorkflowInstanceIds: [run.id],
|
|
16414
|
+
after: [],
|
|
16415
|
+
before: [],
|
|
16416
|
+
history: "barrier",
|
|
16417
|
+
label: "Reconcile generation start",
|
|
16418
|
+
timeoutMs
|
|
16419
|
+
});
|
|
16420
|
+
this.watchRun(run.id, timeoutMs);
|
|
16421
|
+
}
|
|
16422
|
+
return reconciliationResult(target.id, run.id, "consistent", {
|
|
16423
|
+
repairedPendingState,
|
|
16424
|
+
workflowStatus: run.status
|
|
16425
|
+
});
|
|
16426
|
+
}
|
|
16427
|
+
const draft = readGenerationDraft(target.draft);
|
|
16428
|
+
if (!draft) {
|
|
16429
|
+
return reconciliationResult(target.id, run.id, "conflict", {
|
|
16430
|
+
reason: "The target has neither a matching History entry nor its original Draft.",
|
|
16431
|
+
workflowStatus: run.status
|
|
16432
|
+
});
|
|
16433
|
+
}
|
|
16434
|
+
if (draft.definitionId !== run.definitionId) {
|
|
16435
|
+
return reconciliationResult(target.id, run.id, "conflict", {
|
|
16436
|
+
reason: "The target Draft and Workflow Run use different Definitions.",
|
|
16437
|
+
workflowStatus: run.status
|
|
16438
|
+
});
|
|
16439
|
+
}
|
|
16440
|
+
if (!isTerminalWorkflowRunStatus(run.status)) {
|
|
16441
|
+
return reconciliationResult(target.id, run.id, "running-insufficient", {
|
|
16442
|
+
reason: "The running Workflow does not yet expose authoritative target output evidence. Wait for a terminal state; do not start another Run.",
|
|
16443
|
+
workflowStatus: run.status
|
|
16444
|
+
});
|
|
16445
|
+
}
|
|
16446
|
+
if (run.status !== "completed") {
|
|
16447
|
+
return reconciliationResult(target.id, run.id, "terminal", {
|
|
16448
|
+
reason: "The Workflow ended without a completed output, so no History entry was invented.",
|
|
16449
|
+
workflowStatus: run.status
|
|
16450
|
+
});
|
|
16451
|
+
}
|
|
16452
|
+
const submittedAt = parseWorkflowTimestamp(run.createdAt);
|
|
16453
|
+
if (submittedAt === null) {
|
|
16454
|
+
return reconciliationResult(target.id, run.id, "insufficient", {
|
|
16455
|
+
reason: "The completed Workflow Run has no trustworthy submission timestamp.",
|
|
16456
|
+
workflowStatus: run.status
|
|
16457
|
+
});
|
|
16458
|
+
}
|
|
16459
|
+
if ((draft.updatedAt ?? draft.createdAt) > submittedAt) {
|
|
16460
|
+
return reconciliationResult(target.id, run.id, "conflict", {
|
|
16461
|
+
reason: "The target Draft changed after the Workflow Run was submitted.",
|
|
16462
|
+
workflowStatus: run.status
|
|
16463
|
+
});
|
|
16464
|
+
}
|
|
16465
|
+
const definition = await this.requireDefinition(run.definitionId);
|
|
16466
|
+
const primaryOutput = requirePrimaryOutput(definition, target.contentType);
|
|
16467
|
+
const targetOutputs = sync.contents.filter((content) => content.sourceId === run.id || content.workflowInstanceId === run.id).flatMap((content) => content.outputs).filter((output) => output.targetId === target.id && output.targetSlot === draft.id && output.slotName === primaryOutput.slotName);
|
|
16468
|
+
if (targetOutputs.length === 0) {
|
|
16469
|
+
return reconciliationResult(target.id, run.id, "insufficient", {
|
|
16470
|
+
reason: "The completed Workflow Run has no Project Content output bound to this target and Draft.",
|
|
16471
|
+
workflowStatus: run.status
|
|
16472
|
+
});
|
|
16473
|
+
}
|
|
16474
|
+
const outputCoreNodeIds = new Set(run.outputs.map((output) => output.coreNodeId));
|
|
16475
|
+
if (outputCoreNodeIds.size > 0 && targetOutputs.every((output) => !outputCoreNodeIds.has(output.coreNodeId))) {
|
|
16476
|
+
return reconciliationResult(target.id, run.id, "conflict", {
|
|
16477
|
+
reason: "Workflow and Project Content outputs disagree.",
|
|
16478
|
+
workflowStatus: run.status
|
|
16479
|
+
});
|
|
16480
|
+
}
|
|
16481
|
+
const timestamp = this.context.now();
|
|
16482
|
+
const historyEntry = {
|
|
16483
|
+
...draft,
|
|
16484
|
+
runtime: {
|
|
16485
|
+
...run.definitionVersion === void 0 ? {} : { expectedDefinitionVersion: run.definitionVersion },
|
|
16486
|
+
instanceIds: [run.id],
|
|
16487
|
+
materializedInputs: inferReconciledMaterializedInputs(draft, run),
|
|
16488
|
+
originClientId: "unknown",
|
|
16489
|
+
submittedAt
|
|
16490
|
+
},
|
|
16491
|
+
updatedAt: timestamp
|
|
16492
|
+
};
|
|
16493
|
+
const { creationIntent: _creationIntent, ...data } = normalizeOptionalRecord(target.data, "View Node data");
|
|
16494
|
+
const prompt = readPrompt(draft);
|
|
16495
|
+
const after = {
|
|
16496
|
+
...structuredClone(target),
|
|
16497
|
+
data: { ...data, ...prompt === null ? {} : { prompt } },
|
|
16498
|
+
draft: null,
|
|
16499
|
+
history: toDocumentJson([...history, historyEntry]),
|
|
16500
|
+
updatedAt: timestamp
|
|
16501
|
+
};
|
|
16502
|
+
await this.context.commit({
|
|
16503
|
+
after: [after],
|
|
16504
|
+
before: [target],
|
|
16505
|
+
history: "barrier",
|
|
16506
|
+
label: "Reconcile generation start",
|
|
16507
|
+
...this.isPending(run.id) ? { removePendingWorkflowInstanceIds: [run.id] } : {},
|
|
16508
|
+
timeoutMs
|
|
16509
|
+
});
|
|
16510
|
+
return reconciliationResult(target.id, run.id, "repaired", {
|
|
16511
|
+
outputCoreNodeIds: [...new Set(targetOutputs.map((output) => output.coreNodeId))],
|
|
16512
|
+
workflowStatus: run.status
|
|
16513
|
+
});
|
|
16514
|
+
}
|
|
16276
16515
|
async waitWorkflowRun(input, timeoutMs) {
|
|
16277
16516
|
assertOnlyKeys3(input, ["workflowRunId"]);
|
|
16278
16517
|
const id2 = requireString3(input.workflowRunId, "workflowRunId");
|
|
@@ -16479,6 +16718,21 @@ var CoreNodeCreativeLoop = class {
|
|
|
16479
16718
|
this.definitions.set(id2, definition);
|
|
16480
16719
|
return definition;
|
|
16481
16720
|
}
|
|
16721
|
+
async resolveReferenceDataType(referenceViewNodeId) {
|
|
16722
|
+
const referenceViewNode = this.requireViewNode(referenceViewNodeId);
|
|
16723
|
+
if (referenceViewNode.type !== "resource") {
|
|
16724
|
+
throw new Error("Generation References require a resource View Node.");
|
|
16725
|
+
}
|
|
16726
|
+
let sourceDataType = referenceViewNode.contentType ?? "";
|
|
16727
|
+
const referenceCoreNodeId = this.resolveViewNodeCoreNodeId(referenceViewNode);
|
|
16728
|
+
if (sourceDataType !== "text" || asRecord3(referenceViewNode.data).mode === "content") {
|
|
16729
|
+
if (!referenceCoreNodeId)
|
|
16730
|
+
throw new Error("Referenced View Node has no current Core Node.");
|
|
16731
|
+
const coreNode = await this.requireCoreNode(referenceCoreNodeId);
|
|
16732
|
+
sourceDataType = readCoreNodeDataType2(coreNode);
|
|
16733
|
+
}
|
|
16734
|
+
return sourceDataType;
|
|
16735
|
+
}
|
|
16482
16736
|
requireTarget(id2) {
|
|
16483
16737
|
const viewNode = this.requireViewNode(id2);
|
|
16484
16738
|
requireSupportedContentType(viewNode.contentType);
|
|
@@ -16524,8 +16778,6 @@ var CoreNodeCreativeLoop = class {
|
|
|
16524
16778
|
data: {
|
|
16525
16779
|
...contentType === "text" ? { mode: "content" } : {},
|
|
16526
16780
|
...data,
|
|
16527
|
-
creator_id: this.context.actor.id,
|
|
16528
|
-
creator_name: this.context.actor.displayName,
|
|
16529
16781
|
...name ? { label: name } : {}
|
|
16530
16782
|
},
|
|
16531
16783
|
draft: null,
|
|
@@ -16563,6 +16815,14 @@ function createEstimatedCompletionTimes(estimate, submittedAt) {
|
|
|
16563
16815
|
function attention(viewNodeId, result3) {
|
|
16564
16816
|
return { attention: { kind: "view-nodes", viewNodeIds: [viewNodeId] }, result: result3 };
|
|
16565
16817
|
}
|
|
16818
|
+
function reconciliationResult(viewNodeId, workflowRunId, reconciliationStatus, detail) {
|
|
16819
|
+
return attention(viewNodeId, {
|
|
16820
|
+
...detail,
|
|
16821
|
+
reconciliationStatus,
|
|
16822
|
+
viewNodeId,
|
|
16823
|
+
workflowRunId
|
|
16824
|
+
});
|
|
16825
|
+
}
|
|
16566
16826
|
function requireDraft(viewNode) {
|
|
16567
16827
|
const draft = readGenerationDraft(viewNode.draft);
|
|
16568
16828
|
if (!draft)
|
|
@@ -16588,6 +16848,38 @@ function readPrompt(draft) {
|
|
|
16588
16848
|
}
|
|
16589
16849
|
return null;
|
|
16590
16850
|
}
|
|
16851
|
+
function inferReconciledMaterializedInputs(draft, run) {
|
|
16852
|
+
const materialized = {};
|
|
16853
|
+
for (const [slotName, bindings] of Object.entries(draft.inputs.slots)) {
|
|
16854
|
+
const references = bindings.filter((binding) => binding.kind !== "literal");
|
|
16855
|
+
if (references.length === 0)
|
|
16856
|
+
continue;
|
|
16857
|
+
const input = run.inputs[slotName];
|
|
16858
|
+
if (typeof input !== "object" || input === null || Array.isArray(input) || !("coreNodeIds" in input) || !Array.isArray(input.coreNodeIds)) {
|
|
16859
|
+
continue;
|
|
16860
|
+
}
|
|
16861
|
+
const coreNodeIds = input.coreNodeIds.filter((coreNodeId) => typeof coreNodeId === "string" && Boolean(coreNodeId));
|
|
16862
|
+
if (references.length === 1) {
|
|
16863
|
+
const reference = references[0];
|
|
16864
|
+
if (reference)
|
|
16865
|
+
materialized[slotName] = [{ coreNodeIds, inputRefId: reference.id }];
|
|
16866
|
+
continue;
|
|
16867
|
+
}
|
|
16868
|
+
if (references.length !== coreNodeIds.length)
|
|
16869
|
+
continue;
|
|
16870
|
+
materialized[slotName] = references.map((reference, index) => ({
|
|
16871
|
+
coreNodeIds: [coreNodeIds[index]],
|
|
16872
|
+
inputRefId: reference.id
|
|
16873
|
+
}));
|
|
16874
|
+
}
|
|
16875
|
+
return materialized;
|
|
16876
|
+
}
|
|
16877
|
+
function parseWorkflowTimestamp(value) {
|
|
16878
|
+
if (!value)
|
|
16879
|
+
return null;
|
|
16880
|
+
const timestamp = Date.parse(value);
|
|
16881
|
+
return Number.isFinite(timestamp) ? timestamp : null;
|
|
16882
|
+
}
|
|
16591
16883
|
function parseConfig2(value) {
|
|
16592
16884
|
const record2 = asRecord3(value);
|
|
16593
16885
|
for (const item of Object.values(record2)) {
|
|
@@ -16616,6 +16908,14 @@ function asRecord3(value) {
|
|
|
16616
16908
|
}
|
|
16617
16909
|
return value;
|
|
16618
16910
|
}
|
|
16911
|
+
function normalizeOptionalRecord(value, field) {
|
|
16912
|
+
if (value === void 0 || value === null)
|
|
16913
|
+
return {};
|
|
16914
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
16915
|
+
throw new Error(`${field} must be an object when present.`);
|
|
16916
|
+
}
|
|
16917
|
+
return structuredClone(value);
|
|
16918
|
+
}
|
|
16619
16919
|
function requireString3(value, field) {
|
|
16620
16920
|
if (typeof value !== "string" || !value.trim())
|
|
16621
16921
|
throw new Error(`${field} must be non-empty.`);
|
|
@@ -16775,8 +17075,6 @@ var ExternalMediaImporter = class {
|
|
|
16775
17075
|
data: {
|
|
16776
17076
|
contentBindingError: null,
|
|
16777
17077
|
contentBindingStatus: "pending",
|
|
16778
|
-
creator_id: this.context.actor.id,
|
|
16779
|
-
creator_name: this.context.actor.displayName,
|
|
16780
17078
|
[IMPORT_INTENT_DATA_KEY]: structuredClone(intent),
|
|
16781
17079
|
label: intent.name
|
|
16782
17080
|
},
|
|
@@ -17201,8 +17499,6 @@ var MediaUploader = class {
|
|
|
17201
17499
|
data: {
|
|
17202
17500
|
contentBindingError: null,
|
|
17203
17501
|
contentBindingStatus: "pending",
|
|
17204
|
-
creator_id: this.context.actor.id,
|
|
17205
|
-
creator_name: this.context.actor.displayName,
|
|
17206
17502
|
label: intent.name,
|
|
17207
17503
|
[UPLOAD_INTENT_DATA_KEY]: structuredClone(intent)
|
|
17208
17504
|
},
|
|
@@ -17991,6 +18287,7 @@ var SemanticCanvasRuntime = class {
|
|
|
17991
18287
|
unsubscribeRemote;
|
|
17992
18288
|
commands;
|
|
17993
18289
|
contentProjection;
|
|
18290
|
+
creationProvenanceSuffix;
|
|
17994
18291
|
creativeLoop;
|
|
17995
18292
|
externalMediaImporter;
|
|
17996
18293
|
mediaUploader;
|
|
@@ -18000,12 +18297,12 @@ var SemanticCanvasRuntime = class {
|
|
|
18000
18297
|
constructor(options) {
|
|
18001
18298
|
this.options = options;
|
|
18002
18299
|
this.now = options.now ?? Date.now;
|
|
18300
|
+
this.creationProvenanceSuffix = normalizeCreationProvenanceSuffix(options.clientName);
|
|
18003
18301
|
this.commands = createProjectCanvasCommandExecutor(options.document, this.now);
|
|
18004
18302
|
this.contentProjection = new ProjectContentProjection(options.projectContents);
|
|
18005
18303
|
this.projectionRevision = options.initialRevision ?? 1;
|
|
18006
18304
|
this.snapshot = options.document.getSnapshot();
|
|
18007
18305
|
const operationContext = {
|
|
18008
|
-
actor: options.actor,
|
|
18009
18306
|
canWrite: options.role !== "viewer",
|
|
18010
18307
|
clientInstanceId: options.clientInstanceId ?? "unknown",
|
|
18011
18308
|
commit: async (input) => {
|
|
@@ -18342,15 +18639,18 @@ var SemanticCanvasRuntime = class {
|
|
|
18342
18639
|
};
|
|
18343
18640
|
}
|
|
18344
18641
|
async commit(entry, timeoutMs) {
|
|
18345
|
-
|
|
18346
|
-
this.
|
|
18642
|
+
const after = this.stampCreatedViewNodes(entry.after, entry.before);
|
|
18643
|
+
await this.applyHistoryState(after, entry.viewNodeIds, entry.label, timeoutMs);
|
|
18644
|
+
this.undoStack.push({ ...entry, after, kind: "reversible" });
|
|
18347
18645
|
this.redoStack.length = 0;
|
|
18348
18646
|
}
|
|
18349
18647
|
async applyOperationPlan(plan, timeoutMs) {
|
|
18350
18648
|
if (plan.changes.length > 0) {
|
|
18649
|
+
const before = plan.changes.map((change) => change.before);
|
|
18650
|
+
const after = this.stampCreatedViewNodes(plan.changes.map((change) => change.after), before);
|
|
18351
18651
|
const entry = {
|
|
18352
|
-
after
|
|
18353
|
-
before
|
|
18652
|
+
after,
|
|
18653
|
+
before,
|
|
18354
18654
|
kind: "reversible",
|
|
18355
18655
|
label: plan.label,
|
|
18356
18656
|
viewNodeIds: plan.changes.map((change) => change.viewNodeId)
|
|
@@ -18387,16 +18687,23 @@ var SemanticCanvasRuntime = class {
|
|
|
18387
18687
|
});
|
|
18388
18688
|
}
|
|
18389
18689
|
async applySemanticChanges(changes, label, timeoutMs, history, addPendingWorkflowInstanceIds, removePendingWorkflowInstanceIds) {
|
|
18690
|
+
const preparedChanges = changes.map((change) => ({
|
|
18691
|
+
...change,
|
|
18692
|
+
after: change.before === null ? this.stampCreatedViewNode(change.after) : structuredClone(change.after)
|
|
18693
|
+
}));
|
|
18390
18694
|
const previous = this.snapshot;
|
|
18391
18695
|
this.snapshot = await this.commands.changeViewNodes({
|
|
18392
18696
|
...addPendingWorkflowInstanceIds ? { addPendingWorkflowInstanceIds } : {},
|
|
18393
|
-
changes:
|
|
18697
|
+
changes: preparedChanges.map((change) => ({
|
|
18698
|
+
state: change.after,
|
|
18699
|
+
viewNodeId: change.viewNodeId
|
|
18700
|
+
})),
|
|
18394
18701
|
operationName: label,
|
|
18395
18702
|
...removePendingWorkflowInstanceIds ? { removePendingWorkflowInstanceIds } : {},
|
|
18396
18703
|
timeoutMs
|
|
18397
18704
|
});
|
|
18398
18705
|
this.projectionRevision += 1;
|
|
18399
|
-
const viewNodeIds =
|
|
18706
|
+
const viewNodeIds = preparedChanges.map((change) => change.viewNodeId);
|
|
18400
18707
|
const viewNodeChanges = diffSemanticViewNodes(previous.viewNodes, this.snapshot.viewNodes, viewNodeIds);
|
|
18401
18708
|
this.emit({
|
|
18402
18709
|
changedViewNodeIds: viewNodeIds,
|
|
@@ -18406,8 +18713,8 @@ var SemanticCanvasRuntime = class {
|
|
|
18406
18713
|
});
|
|
18407
18714
|
if (history === "undoable") {
|
|
18408
18715
|
this.undoStack.push({
|
|
18409
|
-
after:
|
|
18410
|
-
before:
|
|
18716
|
+
after: preparedChanges.map((change) => change.after),
|
|
18717
|
+
before: preparedChanges.map((change) => change.before),
|
|
18411
18718
|
kind: "reversible",
|
|
18412
18719
|
label,
|
|
18413
18720
|
viewNodeIds
|
|
@@ -18418,6 +18725,22 @@ var SemanticCanvasRuntime = class {
|
|
|
18418
18725
|
this.redoStack.length = 0;
|
|
18419
18726
|
}
|
|
18420
18727
|
}
|
|
18728
|
+
stampCreatedViewNodes(after, before) {
|
|
18729
|
+
return after.map((viewNode, index) => viewNode !== null && before[index] === null ? this.stampCreatedViewNode(viewNode) : structuredClone(viewNode));
|
|
18730
|
+
}
|
|
18731
|
+
stampCreatedViewNode(viewNode) {
|
|
18732
|
+
if (!this.creationProvenanceSuffix)
|
|
18733
|
+
return structuredClone(viewNode);
|
|
18734
|
+
const data = typeof viewNode.data === "object" && viewNode.data !== null && !Array.isArray(viewNode.data) ? structuredClone(viewNode.data) : {};
|
|
18735
|
+
delete data.creator_id;
|
|
18736
|
+
delete data.creator_name;
|
|
18737
|
+
data.createdByCli = this.creationProvenanceSuffix;
|
|
18738
|
+
if (viewNode.type === "note") {
|
|
18739
|
+
data.creator_id = this.options.actor.id;
|
|
18740
|
+
data.creator_name = `${this.options.actor.displayName} (${this.creationProvenanceSuffix})`;
|
|
18741
|
+
}
|
|
18742
|
+
return { ...structuredClone(viewNode), data };
|
|
18743
|
+
}
|
|
18421
18744
|
nextNotePosition() {
|
|
18422
18745
|
const count = this.snapshot.viewNodes.length;
|
|
18423
18746
|
return { x: 160 + count % 4 * 348, y: 160 + Math.floor(count / 4) * 348 };
|
|
@@ -18472,7 +18795,7 @@ function duplicateInputContainsResource(snapshot, input) {
|
|
|
18472
18795
|
return snapshot.viewNodes.some((viewNode) => ids.has(viewNode.id) && viewNode.type === "resource");
|
|
18473
18796
|
}
|
|
18474
18797
|
function isCreativeLoopOperation(name) {
|
|
18475
|
-
return name === "getCoreNode" || name === "placeCoreNode" || name === "createGenerationTarget" || name === "createMediaTarget" || name === "planGeneration" || name === "editGenerationDraft" || name === "addVisualReference" || name === "removeVisualReference" || name === "startGeneration" || name === "getWorkflowRun" || name === "waitWorkflowRun";
|
|
18798
|
+
return name === "getCoreNode" || name === "placeCoreNode" || name === "createGenerationTarget" || name === "createMediaTarget" || name === "planGeneration" || name === "editGenerationDraft" || name === "addVisualReference" || name === "insertPromptReference" || name === "removeVisualReference" || name === "startGeneration" || name === "reconcileGenerationStart" || name === "getWorkflowRun" || name === "waitWorkflowRun";
|
|
18476
18799
|
}
|
|
18477
18800
|
function createViewNodeId() {
|
|
18478
18801
|
return `view_node_${crypto.randomUUID().replaceAll("-", "")}`;
|
|
@@ -18510,6 +18833,17 @@ function requireString6(value, field) {
|
|
|
18510
18833
|
throw new Error(`${field} must be a string.`);
|
|
18511
18834
|
return value;
|
|
18512
18835
|
}
|
|
18836
|
+
function normalizeCreationProvenanceSuffix(value) {
|
|
18837
|
+
if (value === void 0)
|
|
18838
|
+
return null;
|
|
18839
|
+
const normalized = value.trim();
|
|
18840
|
+
if (!normalized)
|
|
18841
|
+
throw new Error("clientName must be non-empty when provided.");
|
|
18842
|
+
if (normalized.includes("(") || normalized.includes(")")) {
|
|
18843
|
+
throw new Error("clientName must not contain parentheses.");
|
|
18844
|
+
}
|
|
18845
|
+
return normalized;
|
|
18846
|
+
}
|
|
18513
18847
|
|
|
18514
18848
|
// src/integrations/backend.ts
|
|
18515
18849
|
var BackendRequestError = class extends Error {
|
|
@@ -23716,6 +24050,7 @@ var AgentCollaborationWatch = class {
|
|
|
23716
24050
|
now;
|
|
23717
24051
|
pending = [];
|
|
23718
24052
|
recent = [];
|
|
24053
|
+
workflowWatermarks = /* @__PURE__ */ new Map();
|
|
23719
24054
|
activeWait = null;
|
|
23720
24055
|
continuityLost = false;
|
|
23721
24056
|
constructor(options = {}) {
|
|
@@ -23728,7 +24063,13 @@ var AgentCollaborationWatch = class {
|
|
|
23728
24063
|
this.now = options.now ?? Date.now;
|
|
23729
24064
|
}
|
|
23730
24065
|
patchInterests(input) {
|
|
23731
|
-
|
|
24066
|
+
const result3 = this.interests.patch(input);
|
|
24067
|
+
for (const key of result3.changedKeys) {
|
|
24068
|
+
for (const watermarkKey of this.workflowWatermarks.keys()) {
|
|
24069
|
+
if (watermarkKey.startsWith(`${key}\0`)) this.workflowWatermarks.delete(watermarkKey);
|
|
24070
|
+
}
|
|
24071
|
+
}
|
|
24072
|
+
return result3;
|
|
23732
24073
|
}
|
|
23733
24074
|
getInterests() {
|
|
23734
24075
|
return this.interests.getAll();
|
|
@@ -23752,10 +24093,24 @@ var AgentCollaborationWatch = class {
|
|
|
23752
24093
|
recordMany(facts) {
|
|
23753
24094
|
if (this.continuityLost) return;
|
|
23754
24095
|
for (const fact of facts) {
|
|
23755
|
-
for (const interest of this.interests.matching(fact))
|
|
24096
|
+
for (const interest of this.interests.matching(fact)) {
|
|
24097
|
+
this.recordWorkflowWatermark(interest.key, fact);
|
|
24098
|
+
this.enqueue(interest.key, fact);
|
|
24099
|
+
}
|
|
23756
24100
|
}
|
|
23757
24101
|
if (this.activeWait && (this.pending.length > 0 || this.continuityLost)) this.deliverActive();
|
|
23758
24102
|
}
|
|
24103
|
+
recordAuthoritativeWorkflow(fact) {
|
|
24104
|
+
if (fact.domain !== "workflow" || this.continuityLost) return;
|
|
24105
|
+
for (const interest of this.interests.matching(fact)) {
|
|
24106
|
+
const key = workflowWatermarkKey(interest.key, fact.ref);
|
|
24107
|
+
const fingerprint = workflowFingerprint(fact);
|
|
24108
|
+
if (this.workflowWatermarks.get(key) === fingerprint) continue;
|
|
24109
|
+
this.workflowWatermarks.set(key, fingerprint);
|
|
24110
|
+
this.enqueue(interest.key, fact);
|
|
24111
|
+
}
|
|
24112
|
+
if (this.activeWait && this.pending.length > 0) this.deliverActive();
|
|
24113
|
+
}
|
|
23759
24114
|
wait(options) {
|
|
23760
24115
|
const timeoutMs = positive(options.timeoutMs, "timeoutMs");
|
|
23761
24116
|
if (this.activeWait)
|
|
@@ -23789,6 +24144,11 @@ var AgentCollaborationWatch = class {
|
|
|
23789
24144
|
resynchronize() {
|
|
23790
24145
|
this.continuityLost = false;
|
|
23791
24146
|
this.pending.length = 0;
|
|
24147
|
+
this.workflowWatermarks.clear();
|
|
24148
|
+
}
|
|
24149
|
+
recordWorkflowWatermark(interest, fact) {
|
|
24150
|
+
if (fact.domain !== "workflow") return;
|
|
24151
|
+
this.workflowWatermarks.set(workflowWatermarkKey(interest, fact.ref), workflowFingerprint(fact));
|
|
23792
24152
|
}
|
|
23793
24153
|
enqueue(interest, fact) {
|
|
23794
24154
|
const terminalPending = this.pending.find(
|
|
@@ -23832,6 +24192,7 @@ var AgentCollaborationWatch = class {
|
|
|
23832
24192
|
merged: entry.merged,
|
|
23833
24193
|
quietForMs: Math.max(0, now - entry.lastObservedAt),
|
|
23834
24194
|
ref: entry.fact.ref,
|
|
24195
|
+
...entry.fact.domain === "canvas" ? { source: entry.fact.source } : {},
|
|
23835
24196
|
summary: structuredClone(entry.fact.summary)
|
|
23836
24197
|
}));
|
|
23837
24198
|
const result3 = {
|
|
@@ -23908,6 +24269,18 @@ function positive(value, field) {
|
|
|
23908
24269
|
function watchError(code, message) {
|
|
23909
24270
|
return Object.assign(new Error(message), { code });
|
|
23910
24271
|
}
|
|
24272
|
+
function workflowWatermarkKey(interest, runId) {
|
|
24273
|
+
return `${interest}\0${runId}`;
|
|
24274
|
+
}
|
|
24275
|
+
function workflowFingerprint(fact) {
|
|
24276
|
+
return JSON.stringify({
|
|
24277
|
+
changeKind: fact.changeKind,
|
|
24278
|
+
kind: fact.kind,
|
|
24279
|
+
status: fact.status,
|
|
24280
|
+
summary: fact.summary,
|
|
24281
|
+
terminal: fact.terminal
|
|
24282
|
+
});
|
|
24283
|
+
}
|
|
23911
24284
|
|
|
23912
24285
|
// src/canvas/session.ts
|
|
23913
24286
|
var CanvasSession = class {
|
|
@@ -23934,6 +24307,7 @@ var CanvasSession = class {
|
|
|
23934
24307
|
runtime = null;
|
|
23935
24308
|
unsubscribeRuntime = null;
|
|
23936
24309
|
observationListeners = /* @__PURE__ */ new Set();
|
|
24310
|
+
knownWorkflowRunIds = /* @__PURE__ */ new Set();
|
|
23937
24311
|
projectionRevision = 0;
|
|
23938
24312
|
actorId = null;
|
|
23939
24313
|
collaborationContext = null;
|
|
@@ -23983,6 +24357,7 @@ var CanvasSession = class {
|
|
|
23983
24357
|
const connectionId = this.health.connectionId;
|
|
23984
24358
|
const runtime = new SemanticCanvasRuntime({
|
|
23985
24359
|
actor: { displayName: actor.displayName, id: actor.accountId },
|
|
24360
|
+
clientName: normalizedClientName,
|
|
23986
24361
|
clientInstanceId: this.clientInstanceId,
|
|
23987
24362
|
document: document2,
|
|
23988
24363
|
foundationData,
|
|
@@ -24001,6 +24376,9 @@ var CanvasSession = class {
|
|
|
24001
24376
|
workflowRuntime
|
|
24002
24377
|
});
|
|
24003
24378
|
this.runtime = runtime;
|
|
24379
|
+
for (const workflowRunId of runtime.getSnapshot().pendingWorkflowInstanceIds) {
|
|
24380
|
+
this.knownWorkflowRunIds.add(workflowRunId);
|
|
24381
|
+
}
|
|
24004
24382
|
this.projectionRevision = runtime.revision;
|
|
24005
24383
|
this.unsubscribeRuntime = runtime.subscribe((observation) => {
|
|
24006
24384
|
this.projectionRevision = observation.revision;
|
|
@@ -24024,11 +24402,58 @@ var CanvasSession = class {
|
|
|
24024
24402
|
}
|
|
24025
24403
|
async execute(name, input, timeoutMs) {
|
|
24026
24404
|
const runtime = this.requireRuntime();
|
|
24405
|
+
if (typeof input.workflowRunId === "string" && input.workflowRunId) {
|
|
24406
|
+
this.knownWorkflowRunIds.add(input.workflowRunId);
|
|
24407
|
+
}
|
|
24027
24408
|
const result3 = await runtime.execute(name, input, timeoutMs);
|
|
24409
|
+
if (typeof result3.result.workflowRunId === "string" && result3.result.workflowRunId) {
|
|
24410
|
+
this.knownWorkflowRunIds.add(result3.result.workflowRunId);
|
|
24411
|
+
}
|
|
24028
24412
|
this.projectionRevision = result3.revision;
|
|
24029
24413
|
if (result3.attention) this.publishAttention(result3.attention);
|
|
24030
24414
|
return result3;
|
|
24031
24415
|
}
|
|
24416
|
+
async catchUpWorkflowInterests(timeoutMs) {
|
|
24417
|
+
const runtime = this.requireRuntime();
|
|
24418
|
+
const deadline = Date.now() + timeoutMs;
|
|
24419
|
+
const knownWorkflowRunIds = [...this.knownWorkflowRunIds];
|
|
24420
|
+
const runIds = [
|
|
24421
|
+
...new Set(
|
|
24422
|
+
this.watch.getInterests().filter((interest) => interest.kind === "workflow").flatMap((interest) => interest.filter.runIds ?? knownWorkflowRunIds)
|
|
24423
|
+
)
|
|
24424
|
+
];
|
|
24425
|
+
for (const workflowRunId of runIds) {
|
|
24426
|
+
const remainingMs = deadline - Date.now();
|
|
24427
|
+
if (remainingMs < 1) break;
|
|
24428
|
+
try {
|
|
24429
|
+
const result3 = await runtime.execute("getWorkflowRun", { workflowRunId }, remainingMs);
|
|
24430
|
+
const workflowRun = result3.result.workflowRun;
|
|
24431
|
+
if (!isWorkflowRun(workflowRun)) continue;
|
|
24432
|
+
for (const fact of projectCanvasObservation(
|
|
24433
|
+
{ kind: "workflow", revision: result3.revision, workflowRun },
|
|
24434
|
+
Date.now()
|
|
24435
|
+
)) {
|
|
24436
|
+
this.watch.recordAuthoritativeWorkflow(fact);
|
|
24437
|
+
}
|
|
24438
|
+
} catch {
|
|
24439
|
+
}
|
|
24440
|
+
}
|
|
24441
|
+
}
|
|
24442
|
+
acknowledgeWatchDelivery(result3) {
|
|
24443
|
+
if (result3.status !== "ready") return;
|
|
24444
|
+
for (const change of result3.changes) {
|
|
24445
|
+
if (change.source !== "remote" || !change.kind.startsWith("note.") && !change.kind.startsWith("view-node.")) {
|
|
24446
|
+
continue;
|
|
24447
|
+
}
|
|
24448
|
+
const bounds = this.requireRuntime().resolveAttentionBounds({
|
|
24449
|
+
kind: "view-nodes",
|
|
24450
|
+
viewNodeIds: [change.ref]
|
|
24451
|
+
});
|
|
24452
|
+
if (!bounds) continue;
|
|
24453
|
+
this.publishAttentionBounds(bounds);
|
|
24454
|
+
return;
|
|
24455
|
+
}
|
|
24456
|
+
}
|
|
24032
24457
|
getCapabilities(detail) {
|
|
24033
24458
|
return this.requireRuntime().capabilities.map(
|
|
24034
24459
|
(descriptor2) => detail ? descriptor2 : {
|
|
@@ -24142,6 +24567,9 @@ function isIndeterminateWrite4(value) {
|
|
|
24142
24567
|
function isWorkflowRecoveryExhausted(value) {
|
|
24143
24568
|
return typeof value === "object" && value !== null && "workflowRecoveryExhausted" in value && value.workflowRecoveryExhausted === true;
|
|
24144
24569
|
}
|
|
24570
|
+
function isWorkflowRun(value) {
|
|
24571
|
+
return typeof value === "object" && value !== null && "id" in value && typeof value.id === "string" && "status" in value && typeof value.status === "string" && "definitionId" in value && typeof value.definitionId === "string" && "outputs" in value && Array.isArray(value.outputs);
|
|
24572
|
+
}
|
|
24145
24573
|
|
|
24146
24574
|
// src/canvas/client.ts
|
|
24147
24575
|
var CANVAS_QUERY_TARGETS = [
|
|
@@ -24236,6 +24664,7 @@ var CanvasClient = class {
|
|
|
24236
24664
|
});
|
|
24237
24665
|
return { receipt };
|
|
24238
24666
|
} catch (error51) {
|
|
24667
|
+
const operationResult2 = readCanvasOperationIndeterminateResult(error51);
|
|
24239
24668
|
const operationUsage = readCanvasOperationUsage(error51);
|
|
24240
24669
|
const indeterminate = isIndeterminateError(error51);
|
|
24241
24670
|
const timedOut = indeterminate && (error51 instanceof IndeterminateBackendWriteError && error51.timedOut || readTimedOut(error51) || error51 instanceof Error && /timed out/i.test(error51.message));
|
|
@@ -24247,6 +24676,7 @@ var CanvasClient = class {
|
|
|
24247
24676
|
message: safeCanvasMessage(error51),
|
|
24248
24677
|
outcome: indeterminate ? "indeterminate" : "failed"
|
|
24249
24678
|
},
|
|
24679
|
+
...operationResult2 ? { result: redactCanvasRecord(operationResult2) } : {},
|
|
24250
24680
|
status: timedOut ? "timed-out" : "failed",
|
|
24251
24681
|
...operationUsage ? { usage: operationUsage } : {}
|
|
24252
24682
|
});
|
|
@@ -24856,7 +25286,16 @@ async function startAgentSessionDaemon(spec, dependencies = {}) {
|
|
|
24856
25286
|
}
|
|
24857
25287
|
if (request.kind === "delivery.ack") {
|
|
24858
25288
|
const acknowledged = outstandingDelivery?.deliveryId === request.deliveryId;
|
|
24859
|
-
if (acknowledged)
|
|
25289
|
+
if (acknowledged) {
|
|
25290
|
+
const result3 = outstandingDelivery?.result;
|
|
25291
|
+
outstandingDelivery = void 0;
|
|
25292
|
+
if (result3) {
|
|
25293
|
+
try {
|
|
25294
|
+
client.session.acknowledgeWatchDelivery?.(result3);
|
|
25295
|
+
} catch {
|
|
25296
|
+
}
|
|
25297
|
+
}
|
|
25298
|
+
}
|
|
24860
25299
|
return { acknowledged };
|
|
24861
25300
|
}
|
|
24862
25301
|
if (request.kind === "interests.get") return watch.getInterests();
|
|
@@ -24882,7 +25321,10 @@ async function startAgentSessionDaemon(spec, dependencies = {}) {
|
|
|
24882
25321
|
}
|
|
24883
25322
|
if (request.kind === "watch.wait") {
|
|
24884
25323
|
if (outstandingDelivery) return outstandingDelivery;
|
|
24885
|
-
const
|
|
25324
|
+
const startedAt = Date.now();
|
|
25325
|
+
await client.session.catchUpWorkflowInterests?.(Math.min(request.timeoutMs, 15e3));
|
|
25326
|
+
const remainingMs = Math.max(1, request.timeoutMs - (Date.now() - startedAt));
|
|
25327
|
+
const result3 = await watch.wait({ signal: context.signal, timeoutMs: remainingMs });
|
|
24886
25328
|
if (result3.status !== "ready") return { result: result3 };
|
|
24887
25329
|
outstandingDelivery = { deliveryId: crypto.randomUUID(), result: result3 };
|
|
24888
25330
|
return outstandingDelivery;
|
|
@@ -24949,6 +25391,8 @@ async function createCanvasClient(spec, dependencies) {
|
|
|
24949
25391
|
executeOperation: (input) => client.executeOperation(input),
|
|
24950
25392
|
query: (input) => client.query(input),
|
|
24951
25393
|
session: {
|
|
25394
|
+
acknowledgeWatchDelivery: (result3) => session.acknowledgeWatchDelivery(result3),
|
|
25395
|
+
catchUpWorkflowInterests: (timeoutMs) => session.catchUpWorkflowInterests(timeoutMs),
|
|
24952
25396
|
getContext: () => session.getCollaborationContext(),
|
|
24953
25397
|
getHealth: () => session.getHealth(),
|
|
24954
25398
|
getIdentity: () => session.getIdentity(),
|
|
@@ -44620,7 +45064,7 @@ function registerCanvasCommands(program2, dependencies, setResult) {
|
|
|
44620
45064
|
// package.json
|
|
44621
45065
|
var package_default = {
|
|
44622
45066
|
name: "@everfir/az8-cli",
|
|
44623
|
-
version: "0.3.0-preview.
|
|
45067
|
+
version: "0.3.0-preview.2",
|
|
44624
45068
|
description: "Semantic Project Canvas client for AZ8 Studio agents.",
|
|
44625
45069
|
license: "UNLICENSED",
|
|
44626
45070
|
type: "module",
|
package/package.json
CHANGED
package/skills/az8-cli/SKILL.md
CHANGED
|
@@ -230,12 +230,20 @@ one-shot processes.
|
|
|
230
230
|
|
|
231
231
|
1. Query `canvas.summary`; query selected details only as needed.
|
|
232
232
|
2. Query `capabilities.detail` and validate the planned Operation input against its schema.
|
|
233
|
-
3.
|
|
233
|
+
3. When artifact type and placement are already clear, make the first meaningful Canvas state
|
|
234
|
+
visible before doing lengthy prompt refinement or generation planning:
|
|
235
|
+
- create the empty generation target first, then plan and edit its Draft;
|
|
236
|
+
- create an empty manual Text Resource with `text: ""`, then fill it with
|
|
237
|
+
`editTextContent`;
|
|
238
|
+
- create a Note with its useful content directly rather than creating an empty sticky.
|
|
239
|
+
Do not create a placeholder while its type or placement is still ambiguous. Watch and the
|
|
240
|
+
Session daemon never create placeholders automatically.
|
|
241
|
+
4. Pick explicit absolute Canvas coordinates. Public move positions remain absolute even for group
|
|
234
242
|
children.
|
|
235
|
-
|
|
236
|
-
|
|
243
|
+
5. Submit one Operation with a new request ID and wait for its terminal Receipt.
|
|
244
|
+
6. Confirm the Receipt outcome and affected IDs, then query the changed View Node when subsequent
|
|
237
245
|
work depends on its exact state.
|
|
238
|
-
|
|
246
|
+
7. Only then plan the next interaction.
|
|
239
247
|
|
|
240
248
|
Common capabilities include notes, manual Text Resources, move/resize/rename, duplicate/remove,
|
|
241
249
|
groups and stacking, Core Node placement, and generation targets. The runtime catalog is
|
|
@@ -270,6 +278,11 @@ Generation is an explicit sequence, never one transaction:
|
|
|
270
278
|
plan.
|
|
271
279
|
4. Execute `plan.operations` exactly in order, one Operation at a time. Each step revalidates
|
|
272
280
|
current facts. Stop after the first non-success.
|
|
281
|
+
When a reference must also appear at a meaningful Prompt position, use
|
|
282
|
+
`insertPromptReference` with the target View Node, visible reference View Node, and
|
|
283
|
+
`placement: "start"` or `"end"`. The CLI creates and validates the binding and At token
|
|
284
|
+
atomically. Do not write `{{@...}}`, choose an input slot/index, or allocate a binding ID
|
|
285
|
+
yourself. `addVisualReference` remains the connection-only operation.
|
|
273
286
|
5. `startGeneration` succeeds when the Workflow Run is accepted and immediate Canvas effects are
|
|
274
287
|
acknowledged. This completes the start interaction; it does not mean generation finished.
|
|
275
288
|
6. Retain the Workflow Run ID. After the successful start Receipt, continue any work that does not
|
|
@@ -283,6 +296,19 @@ Generation is an explicit sequence, never one transaction:
|
|
|
283
296
|
8. On terminal success, query the target detail and resolve its current output Core Node through
|
|
284
297
|
Project Content before downloading or placing it elsewhere.
|
|
285
298
|
|
|
299
|
+
If `startGeneration` returns an indeterminate Receipt after the Workflow was accepted, retain
|
|
300
|
+
`receipt.result.workflowRunId` and `receipt.result.viewNodeId`, reconnect the Session, and invoke
|
|
301
|
+
`reconcileGenerationStart` with those two identities. Never call `startGeneration` again for that
|
|
302
|
+
intent. `running-insufficient` means the Run is still authoritative but does not yet expose enough
|
|
303
|
+
target evidence: wait and reconcile later. `repaired` means the CLI restored the missing Canvas
|
|
304
|
+
launch facts through the semantic Command path. `conflict` or `insufficient` requires inspection;
|
|
305
|
+
neither authorizes a retry.
|
|
306
|
+
|
|
307
|
+
A Workflow Interest performs an authoritative status catch-up for Run IDs already known to the
|
|
308
|
+
Session; explicit `filter.runIds` narrows or restores that set when needed. This closes
|
|
309
|
+
missed-live-event races and delivers each unchanged terminal fact once. Keep explicit Run ID filters
|
|
310
|
+
current across handoffs; the daemon does not scan unrelated Workflow Runs.
|
|
311
|
+
|
|
286
312
|
Workflow Definitions change over time. Query `workflowDefinitions.summary`, then
|
|
287
313
|
`workflowDefinition.detail` only when planning detail is insufficient. Never guess a Definition,
|
|
288
314
|
configuration option, modality, cost, or media compatibility from its display name.
|