@meistrari/tela-cli 1.3.0 → 1.4.0

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.
@@ -15,6 +15,7 @@ import {
15
15
  canvas,
16
16
  code,
17
17
  crop,
18
+ docTemplate,
18
19
  input,
19
20
  llm,
20
21
  splitter,
@@ -35,7 +36,9 @@ import type { WorkflowCodeConfig } from '@meistrari/workflow-code'
35
36
  | [`splitter()`](#splitteroptions) | Splitting file inputs, compatible prior outputs, or existing Vault files. |
36
37
  | [`crop()`](#cropoptions) | Cropping selected PDF pages from compatible files or existing Vault files. |
37
38
  | [`vault.asset()`](#vaultassetpath-options) | Declaring a local file that `sync` uploads and locks in Vault. |
39
+ | [`docTemplate()`](#doctemplateoptions) | Rendering a `.docx` Vault template with keyed placeholders. |
38
40
  | [`vault.ref()`](#vaultrefreference) | Declaring an inert reference to an existing `vault://...` file. |
41
+ | [`vault.asset()`](#vaultassetpath-options) | Declaring a local file dependency uploaded and locked by `sync`. |
39
42
  | [`remote()`](#remote) | Generated catalog paths and explicit ID refs for inert remote authoring. |
40
43
  | [`canvas()`](#canvasremoteref-options) | Executable Canvas or Workflow refs from the remote catalog. |
41
44
  | [`agent(remoteRef, options)`](#agentremoteref-options) | Published-Agent calls from the remote catalog. |
@@ -491,6 +494,29 @@ function crop(options: CropOptions): CropNodeHandle
491
494
  ```
492
495
 
493
496
  Declares Workflow V3's existing `document-cropper` action. Its exclusive `input.file` supports the same compatible workflow input, prior-node output, `vault.ref()`, `vault.asset()`, and Vault-array forms as `splitter.input.file`.
497
+ ### `docTemplate(options)`
498
+
499
+ ```ts
500
+ type DocTemplateOptions = {
501
+ name: string
502
+ key?: string
503
+ input: {
504
+ template: WorkflowCodeVaultSource
505
+ | ((context: ExclusiveRefFactoryContext) => WorkflowCodeExclusiveRef<string>)
506
+ placeholders?: Record<string, string | WorkflowCodeVaultSource>
507
+ | ((context: PromptFactoryContext) => Record<string, string | WorkflowCodeVaultSource | PromptRefValue>)
508
+ outputFilename: string
509
+ mustache?: boolean
510
+ createPermalink?: boolean
511
+ templateFilename?: string
512
+ templateFileSize?: number
513
+ }
514
+ }
515
+
516
+ function docTemplate(options: DocTemplateOptions): DocTemplateNodeHandle
517
+ ```
518
+
519
+ Declares the Workflow V3 `document-templater` action. `input.template` may be a `.docx` file declared with `vault.ref()` or `vault.asset()`, or a callback reference to a text workflow input/string-compatible field from an earlier node. Placeholders are authored as a keyed object; literal strings remain literal, and compatible workflow/Vault references lower to the reference strings consumed by the runtime action.
494
520
 
495
521
  | Option | Type | Required | Default | Description |
496
522
  | --- | --- | --- | --- | --- |
@@ -549,6 +575,44 @@ const selectedPages = crop({
549
575
  ```
550
576
 
551
577
  `path`, `name`, and `mimeType` must be non-empty strings when present. Offline compile without a matching explicit asset snapshot reports `vault.asset.missing_lock`; it never falls back to reading the local file. If the file changes, the next `sync` uploads the new content and updates the lock.
578
+ | `input.template` | `WorkflowCodeVaultSource` | Yes | — | Existing `vault.ref()` or local `vault.asset()` `.docx` template. |
579
+ | `input.template` | `WorkflowCodeVaultSource` or callback | Yes | — | Existing `vault.ref()`, local `vault.asset()`, text input ref, or string-compatible earlier-node ref containing the template Vault URL. |
580
+ | `input.placeholders` | Record or callback | No | `{}` | Literal strings, Vault sources, text inputs, or string-compatible earlier-node fields keyed by template placeholder. |
581
+ | `input.outputFilename` | `string` | Yes | — | Filename for the generated document. |
582
+ | `input.mustache` | `boolean` | No | `false` | Enables the runtime action's Mustache mode. |
583
+ | `input.createPermalink` | `boolean` | No | `false` | Requests a permalink for the rendered document. |
584
+ | `input.templateFilename` | `string` | No | Known Vault name | Explicit `.docx` template name, validated against known metadata. |
585
+ | `input.templateFileSize` | `number` | No | Known Vault size | Explicit byte size, validated against known metadata. |
586
+
587
+ ```ts
588
+ const template = vault.asset('./templates/invoice.docx', {
589
+ name: 'invoice.docx',
590
+ mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
591
+ })
592
+
593
+ const renderInvoice = docTemplate({
594
+ name: 'Render invoice',
595
+ input: {
596
+ template,
597
+ outputFilename: 'rendered-invoice.docx',
598
+ placeholders: ({ ref, paths }) => ({
599
+ customer: ref(customerName),
600
+ total: ref(extractInvoice, paths(extractInvoice).total),
601
+ footer: 'Generated by Tela',
602
+ }),
603
+ },
604
+ })
605
+
606
+ const renderSelectedTemplate = docTemplate({
607
+ name: 'Render selected template',
608
+ input: {
609
+ template: ({ ref, paths }) => ref(selectTemplate, paths(selectTemplate).vaultUrl),
610
+ outputFilename: 'selected-template.docx',
611
+ },
612
+ })
613
+ ```
614
+
615
+ The returned handle exposes typed `generatedDocument`, `generatedAt`, and optional permalink fields. Before workflow mutation, `sync` uploads changed local assets, reuses matching locks, validates access to every directly used Vault ref, checks known filename/size metadata, and rejects known non-`.docx` templates. Dynamic template refs are validated for scope and string compatibility, but their runtime Vault value cannot be inspected during sync. File inputs and non-string node fields are incompatible template or placeholder references.
552
616
 
553
617
  ### `vault.ref(reference)`
554
618
 
@@ -575,6 +639,26 @@ const existingPages = splitter({
575
639
 
576
640
  During compile, a direct Vault ref used by `splitter.input.file` or `crop.input.file` lowers to a transport-file object containing both `fileUrl` and `vaultReference`. Compile remains offline. Before remote workflow mutation, sync and publish validate access to every compiled Vault ref in the active Tela context.
577
641
 
642
+ ### `vault.asset(path, options)`
643
+
644
+ ```ts
645
+ const vault: {
646
+ asset: (
647
+ path: string,
648
+ options?: { name?: string, mimeType?: string },
649
+ ) => WorkflowCodeVaultAsset
650
+ }
651
+ ```
652
+
653
+ Creates an inert local file declaration. Source evaluation does not read, hash, or upload the path. `sync` resolves it inside the Workflow Code project, uploads new or changed content, and persists the returned `vault://...` ref with its content hash and known metadata in the target lockfile. An unchanged asset reuses that lock.
654
+
655
+ ```ts
656
+ const template = vault.asset('./templates/invoice.docx', {
657
+ name: 'invoice.docx',
658
+ mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
659
+ })
660
+ ```
661
+
578
662
  ### `agent(remoteRef, options)`
579
663
 
580
664
  ```ts
@@ -14,7 +14,7 @@
14
14
  "slug": "api-reference",
15
15
  "title": "API Reference",
16
16
  "file": "api-reference.md",
17
- "sha256": "fc121fd8c0e83e4f39ecef45b50d4fc9b0bc64888bd10d0590b3ca168af0a42d"
17
+ "sha256": "380cf0c8543400f6fd311936f1b4fb984f12d27b0472213b8a2b431405f0755e"
18
18
  },
19
19
  {
20
20
  "slug": "cli",
package/dist/index.js CHANGED
@@ -368782,7 +368782,7 @@ var require_output_schema = __commonJS({
368782
368782
  "../../packages/workflow-code/dist/compiler/output-schema.js"(exports2) {
368783
368783
  "use strict";
368784
368784
  Object.defineProperty(exports2, "__esModule", { value: true });
368785
- exports2.CROP_OUTPUT_JSON_SCHEMA = exports2.SPLITTER_OUTPUT_JSON_SCHEMA = exports2.FILE_INPUT_JSON_SCHEMA = exports2.FILE_OUTPUT_JSON_SCHEMA = void 0;
368785
+ exports2.DOC_TEMPLATE_OUTPUT_JSON_SCHEMA = exports2.CROP_OUTPUT_JSON_SCHEMA = exports2.SPLITTER_OUTPUT_JSON_SCHEMA = exports2.FILE_INPUT_JSON_SCHEMA = exports2.FILE_OUTPUT_JSON_SCHEMA = void 0;
368786
368786
  exports2.createPromptOutputJsonSchema = createPromptOutputJsonSchema;
368787
368787
  exports2.selectOutputJsonSchema = selectOutputJsonSchema;
368788
368788
  exports2.isFileCompatibleOutputJsonSchema = isFileCompatibleOutputJsonSchema;
@@ -368834,6 +368834,17 @@ var require_output_schema = __commonJS({
368834
368834
  required: Object.freeze(["indexes", "originalFile", "file"])
368835
368835
  })
368836
368836
  });
368837
+ exports2.DOC_TEMPLATE_OUTPUT_JSON_SCHEMA = Object.freeze({
368838
+ type: "object",
368839
+ properties: Object.freeze({
368840
+ generatedDocument: exports2.FILE_OUTPUT_JSON_SCHEMA,
368841
+ generatedAt: Object.freeze({ type: "string" }),
368842
+ permalinkUrl: Object.freeze({ type: "string" }),
368843
+ permalinkId: Object.freeze({ type: "string" }),
368844
+ permalinkExpiresAt: Object.freeze({ anyOf: Object.freeze([{ type: "string" }, { type: "null" }]) })
368845
+ }),
368846
+ required: Object.freeze(["generatedDocument", "generatedAt"])
368847
+ });
368837
368848
  function createPromptOutputJsonSchema(schema) {
368838
368849
  return schema === void 0 || schema === null ? void 0 : { type: "object", properties: schema };
368839
368850
  }
@@ -369376,7 +369387,8 @@ var require_extract3 = __commonJS({
369376
369387
  required: declaration.required
369377
369388
  }));
369378
369389
  const nodeBindings = input.builtNodes.slice(0, input.currentNodeIndex).flatMap((node) => {
369379
- const schema = input.nodeOutputSchemasById.get(input.nodeIdsByKey.get(node.key ?? node.name) ?? "");
369390
+ const nodeId = input.nodeIdsByKey.get(node.key ?? node.name);
369391
+ const schema = nodeId === void 0 ? void 0 : input.nodeOutputSchemasById.get(nodeId);
369380
369392
  return schema ? [{ name: node.name, schema, required: true }] : [];
369381
369393
  });
369382
369394
  return [...inputBindings, ...nodeBindings];
@@ -370531,6 +370543,7 @@ var require_refs = __commonJS({
370531
370543
  exports2.resolveReferenceRecordRefs = resolveReferenceRecordRefs;
370532
370544
  exports2.resolveWorkflowRef = resolveWorkflowRef;
370533
370545
  exports2.resolveExclusiveRef = resolveExclusiveRef;
370546
+ exports2.resolveVisibleNodeIdentity = resolveVisibleNodeIdentity;
370534
370547
  var workflow_shared_1 = require_cjs2();
370535
370548
  function resolvePromptRefs(context) {
370536
370549
  const diagnostics = [];
@@ -370621,7 +370634,7 @@ var require_refs = __commonJS({
370621
370634
  const candidates = context.nodeIdentitiesByKey.get(ref.targetKey) ?? [];
370622
370635
  if (candidates.length === 0)
370623
370636
  return void 0;
370624
- const visible = findVisibleCandidate(ref.targetKey, context);
370637
+ const visible = resolveVisibleNodeIdentity(ref.targetKey, context);
370625
370638
  if (visible) {
370626
370639
  const reference = workflow_shared_1.ActionOutputReferenceURI.fromStepId(visible.id);
370627
370640
  return { reference: formatPromptReference(reference, ref), nodeId: visible.id };
@@ -370631,7 +370644,7 @@ var require_refs = __commonJS({
370631
370644
  }
370632
370645
  return "scope";
370633
370646
  }
370634
- function findVisibleCandidate(key, context) {
370647
+ function resolveVisibleNodeIdentity(key, context) {
370635
370648
  const currentScopeCandidate = resolvePriorCandidateInScope(key, context.currentNode.scopePath, context.currentNode.sequenceIndex, context);
370636
370649
  if (currentScopeCandidate)
370637
370650
  return currentScopeCandidate;
@@ -370962,9 +370975,9 @@ var require_modules = __commonJS({
370962
370975
  currentNodeIndex: context.nodeIndex,
370963
370976
  inputNamesByKey: context.inputNamesByKey,
370964
370977
  nodeNamesByKey: context.nodeNamesByKey,
370978
+ nodeIdsByKey: context.nodeIdsByKey,
370965
370979
  nodeIndexesByKey: context.nodeIndexesByKey,
370966
- nodeOutputSchemasById: context.nodeOutputSchemasById,
370967
- nodeIdsByKey: context.nodeIdsByKey
370980
+ nodeOutputSchemasById: context.nodeOutputSchemasById
370968
370981
  });
370969
370982
  context.diagnostics.push(...extracted.diagnostics);
370970
370983
  if (extracted.diagnostics.some((item) => item.severity === "error"))
@@ -371106,6 +371119,255 @@ var require_modules = __commonJS({
371106
371119
  diagnostics.push(invalidDocumentInputDiagnostic(node, "crop", "type must be pdf"));
371107
371120
  return diagnostics;
371108
371121
  }
371122
+ var DOCX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
371123
+ var docTemplateModule = {
371124
+ kind: "doc-template",
371125
+ actionId: workflow_shared_1.WORKFLOW_ACTION_IDS.documentTemplater,
371126
+ createFailedInput() {
371127
+ return {
371128
+ vaultUrl: "vault://00000000-0000-4000-8000-000000000000",
371129
+ placeholders: [],
371130
+ outputFilename: "compilation-failed.docx",
371131
+ mustache: false,
371132
+ createPermalink: false
371133
+ };
371134
+ },
371135
+ validate(node) {
371136
+ return validateDocTemplateInput(node);
371137
+ },
371138
+ lower(node, context) {
371139
+ if (validateDocTemplateInput(node).length > 0)
371140
+ return void 0;
371141
+ const template = lowerDocTemplateSource(node.input.template, context);
371142
+ const placeholders = lowerDocTemplatePlaceholders(node, context);
371143
+ context.diagnostics.push(...template.diagnostics, ...placeholders.diagnostics);
371144
+ if (!template.reference)
371145
+ return void 0;
371146
+ const templateFilename = node.input.templateFilename ?? template.lock?.name;
371147
+ const templateFileSize = node.input.templateFileSize ?? template.lock?.size;
371148
+ context.diagnostics.push(...validateKnownTemplateMetadata(node, template.lock));
371149
+ const linearPorts = defaultLinearPorts(context.nodeId);
371150
+ return {
371151
+ node: {
371152
+ id: context.nodeId,
371153
+ name: node.name,
371154
+ actionId: workflow_shared_1.WORKFLOW_ACTION_IDS.documentTemplater,
371155
+ ports: [
371156
+ { id: linearPorts.input, dir: "in", type: "default" },
371157
+ { id: linearPorts.output, dir: "out", type: "default" }
371158
+ ],
371159
+ input: {
371160
+ vaultUrl: template.reference,
371161
+ placeholders: Object.entries(placeholders.values).map(([key, reference]) => ({ key, reference })),
371162
+ outputFilename: node.input.outputFilename,
371163
+ mustache: node.input.mustache ?? false,
371164
+ createPermalink: node.input.createPermalink ?? false,
371165
+ ...templateFilename === void 0 ? {} : { templateFilename },
371166
+ ...templateFileSize === void 0 ? {} : { templateFileSize }
371167
+ }
371168
+ },
371169
+ linearPorts,
371170
+ outputSchema: output_schema_1.DOC_TEMPLATE_OUTPUT_JSON_SCHEMA,
371171
+ vaultRefs: [...template.vaultRefs, ...placeholders.vaultRefs],
371172
+ ...(0, reference_1.isWorkflowCodeVaultReference)(template.reference) ? { vaultRequirements: [{
371173
+ reference: template.reference,
371174
+ ...templateFilename === void 0 ? {} : { expectedName: templateFilename },
371175
+ ...templateFileSize === void 0 ? {} : { expectedSize: templateFileSize },
371176
+ requiredExtension: ".docx",
371177
+ requiredMimeType: DOCX_MIME_TYPE
371178
+ }] } : {}
371179
+ };
371180
+ }
371181
+ };
371182
+ function validateDocTemplateInput(node) {
371183
+ if (!node.input || typeof node.input !== "object")
371184
+ return [invalidDocTemplateInputDiagnostic(node, "input must be an object")];
371185
+ const diagnostics = [];
371186
+ if (!isVaultSource(node.input.template) && !isExclusiveWorkflowRef(node.input.template))
371187
+ diagnostics.push(invalidDocTemplateInputDiagnostic(node, "template must be vault.ref(), vault.asset(), or a workflow reference callback"));
371188
+ if (typeof node.input.outputFilename !== "string" || node.input.outputFilename.trim().length === 0)
371189
+ diagnostics.push(invalidDocTemplateInputDiagnostic(node, "outputFilename must be a non-empty string"));
371190
+ if (!isRecord3(node.input.placeholders))
371191
+ diagnostics.push(invalidDocTemplateInputDiagnostic(node, "placeholders must be an object"));
371192
+ else if (Object.entries(node.input.placeholders).some(([key, value]) => key.trim().length === 0 || !isReferencePlaceholder(value) && !isVaultSource(value)))
371193
+ diagnostics.push(invalidDocTemplateInputDiagnostic(node, "placeholder keys must be non-empty and values must be string literals or compatible refs"));
371194
+ if (node.input.mustache !== void 0 && typeof node.input.mustache !== "boolean")
371195
+ diagnostics.push(invalidDocTemplateInputDiagnostic(node, "mustache must be a boolean"));
371196
+ if (node.input.createPermalink !== void 0 && typeof node.input.createPermalink !== "boolean")
371197
+ diagnostics.push(invalidDocTemplateInputDiagnostic(node, "createPermalink must be a boolean"));
371198
+ if (node.input.templateFilename !== void 0 && (typeof node.input.templateFilename !== "string" || !hasDocxExtension(node.input.templateFilename)))
371199
+ diagnostics.push(invalidDocTemplateInputDiagnostic(node, "templateFilename must name a .docx file"));
371200
+ if (node.input.templateFileSize !== void 0 && (typeof node.input.templateFileSize !== "number" || !Number.isFinite(node.input.templateFileSize) || node.input.templateFileSize < 0))
371201
+ diagnostics.push(invalidDocTemplateInputDiagnostic(node, "templateFileSize must be a non-negative finite number"));
371202
+ if (isVaultAsset(node.input.template)) {
371203
+ const assetName = node.input.template.name ?? node.input.template.path;
371204
+ if (!hasDocxExtension(assetName))
371205
+ diagnostics.push(invalidDocTemplateInputDiagnostic(node, "vault.asset() template must name a .docx file"));
371206
+ if (node.input.template.mimeType !== void 0 && node.input.template.mimeType !== DOCX_MIME_TYPE)
371207
+ diagnostics.push(invalidDocTemplateInputDiagnostic(node, `vault.asset() template MIME type must be ${DOCX_MIME_TYPE}`));
371208
+ }
371209
+ return diagnostics;
371210
+ }
371211
+ function invalidDocTemplateInputDiagnostic(node, detail) {
371212
+ return {
371213
+ code: "compiler.module.invalid_input",
371214
+ severity: "error",
371215
+ message: `Node ${node.name || "<unnamed>"} has invalid docTemplate input: ${detail}`
371216
+ };
371217
+ }
371218
+ function lowerDocTemplateSource(source, context) {
371219
+ if (isExclusiveWorkflowRef(source)) {
371220
+ const compatibility = validateDocTemplateSourceTarget(source, context);
371221
+ if (compatibility.length > 0)
371222
+ return { vaultRefs: [], diagnostics: compatibility };
371223
+ const resolved = (0, refs_1.resolveExclusiveRef)(source, {
371224
+ inputIdsByKey: context.inputIdsByKey,
371225
+ nodeIdentitiesByKey: context.nodeIdentitiesByKey,
371226
+ nodesByPath: context.nodesByPath,
371227
+ currentNode: context.currentNode
371228
+ });
371229
+ return { reference: resolved.reference, vaultRefs: [], diagnostics: resolved.diagnostics };
371230
+ }
371231
+ if (isVaultRef(source)) {
371232
+ if (!(0, reference_1.isWorkflowCodeVaultReference)(source.reference))
371233
+ return { vaultRefs: [], diagnostics: [invalidVaultRefDiagnostic(source.reference)] };
371234
+ return { reference: source.reference, vaultRefs: [source.reference], diagnostics: [] };
371235
+ }
371236
+ if (!isVaultAsset(source))
371237
+ return { vaultRefs: [], diagnostics: [] };
371238
+ const lock = context.vaultAssetsByKey.get((0, asset_1.workflowCodeVaultAssetKey)(context.workflowKey, source));
371239
+ if (!lock || !(0, reference_1.isWorkflowCodeVaultReference)(lock.ref)) {
371240
+ return {
371241
+ vaultRefs: [],
371242
+ diagnostics: [{
371243
+ code: "vault.asset.missing_lock",
371244
+ severity: "error",
371245
+ message: `Vault asset ${source.path} has no uploaded lock for this workflow`,
371246
+ hint: "Run tela workflow sync so the CLI can upload and lock the local asset before compilation."
371247
+ }]
371248
+ };
371249
+ }
371250
+ return {
371251
+ reference: lock.ref,
371252
+ lock,
371253
+ vaultRefs: [lock.ref],
371254
+ diagnostics: []
371255
+ };
371256
+ }
371257
+ function validateDocTemplateSourceTarget(source, context) {
371258
+ if (source.targetKind === "input") {
371259
+ const target2 = context.builtInputs.find((input) => (input.key ?? input.name) === source.targetKey);
371260
+ if (!target2 || target2.inputType === "text")
371261
+ return [];
371262
+ return [incompatibleDocTemplateSourceDiagnostic(source.targetKey)];
371263
+ }
371264
+ const target = resolveVisibleNodeOutput(source.targetKey, context);
371265
+ if (!target)
371266
+ return [];
371267
+ const directStringLlm = target.declaration?.nodeKind === "llm" && target.declaration.schema == null && (source.path?.length ?? 0) === 0;
371268
+ const selectedSchema = (0, output_schema_1.selectOutputJsonSchema)(target.schema, source.path ?? []);
371269
+ return directStringLlm || (0, output_schema_1.isStringCompatibleOutputJsonSchema)(selectedSchema) ? [] : [incompatibleDocTemplateSourceDiagnostic(source.targetKey)];
371270
+ }
371271
+ function incompatibleDocTemplateSourceDiagnostic(targetKey) {
371272
+ return {
371273
+ code: "compiler.ref.incompatible",
371274
+ severity: "error",
371275
+ message: `Template reference ${targetKey} does not select a string-compatible value for docTemplate.input.template`
371276
+ };
371277
+ }
371278
+ function lowerDocTemplatePlaceholders(node, context) {
371279
+ const diagnostics = validateDocTemplatePlaceholderCompatibility(node, context);
371280
+ const resolved = (0, refs_1.resolveReferenceRecordRefs)({
371281
+ values: node.input.placeholders,
371282
+ refs: node.placeholderRefs ?? [],
371283
+ inputIdsByKey: context.inputIdsByKey,
371284
+ inputTypesByKey: context.inputTypesByKey,
371285
+ nodeIdentitiesByKey: context.nodeIdentitiesByKey,
371286
+ nodesByPath: context.nodesByPath,
371287
+ currentNode: context.currentNode
371288
+ });
371289
+ diagnostics.push(...resolved.diagnostics);
371290
+ const values = {};
371291
+ const vaultRefs = [];
371292
+ for (const [key, value] of Object.entries(resolved.values)) {
371293
+ if (typeof value === "string") {
371294
+ values[key] = value;
371295
+ continue;
371296
+ }
371297
+ if (isVaultRef(value)) {
371298
+ if ((0, reference_1.isWorkflowCodeVaultReference)(value.reference)) {
371299
+ values[key] = value.reference;
371300
+ vaultRefs.push(value.reference);
371301
+ } else {
371302
+ diagnostics.push(invalidVaultRefDiagnostic(value.reference));
371303
+ }
371304
+ continue;
371305
+ }
371306
+ if (isVaultAsset(value)) {
371307
+ const lock = context.vaultAssetsByKey.get((0, asset_1.workflowCodeVaultAssetKey)(context.workflowKey, value));
371308
+ if (!lock || !(0, reference_1.isWorkflowCodeVaultReference)(lock.ref)) {
371309
+ diagnostics.push({
371310
+ code: "vault.asset.missing_lock",
371311
+ severity: "error",
371312
+ message: `Vault asset ${value.path} has no uploaded lock for this workflow`,
371313
+ hint: "Run tela workflow sync so the CLI can upload and lock the local asset before compilation."
371314
+ });
371315
+ } else {
371316
+ values[key] = lock.ref;
371317
+ vaultRefs.push(lock.ref);
371318
+ }
371319
+ }
371320
+ }
371321
+ return { values: Object.freeze(values), vaultRefs, diagnostics };
371322
+ }
371323
+ function validateDocTemplatePlaceholderCompatibility(node, context) {
371324
+ const diagnostics = [];
371325
+ for (const ref of node.placeholderRefs ?? []) {
371326
+ if (ref.targetKind === "input") {
371327
+ if (context.inputTypesByKey.get(ref.targetKey) === "file")
371328
+ diagnostics.push(incompatibleDocTemplatePlaceholderDiagnostic(ref.key, ref.targetKey));
371329
+ continue;
371330
+ }
371331
+ const target = resolveVisibleNodeOutput(ref.targetKey, context);
371332
+ if (!target)
371333
+ continue;
371334
+ const directStringLlm = target.declaration?.nodeKind === "llm" && target.declaration.schema == null && (ref.path?.length ?? 0) === 0;
371335
+ const selected = (0, output_schema_1.selectOutputJsonSchema)(target.schema, ref.path ?? []);
371336
+ if (!directStringLlm && !(0, output_schema_1.isStringCompatibleOutputJsonSchema)(selected))
371337
+ diagnostics.push(incompatibleDocTemplatePlaceholderDiagnostic(ref.key, ref.targetKey));
371338
+ }
371339
+ return diagnostics;
371340
+ }
371341
+ function incompatibleDocTemplatePlaceholderDiagnostic(key, targetKey) {
371342
+ return {
371343
+ code: "compiler.ref.incompatible",
371344
+ severity: "error",
371345
+ message: `Placeholder ${key} reference ${targetKey} does not select a string-compatible value`
371346
+ };
371347
+ }
371348
+ function validateKnownTemplateMetadata(node, lock) {
371349
+ if (!lock)
371350
+ return [];
371351
+ const diagnostics = [];
371352
+ if (node.input.templateFilename !== void 0 && lock.name !== void 0 && node.input.templateFilename !== lock.name)
371353
+ diagnostics.push(invalidDocTemplateInputDiagnostic(node, `templateFilename ${node.input.templateFilename} does not match locked asset name ${lock.name}`));
371354
+ if (node.input.templateFileSize !== void 0 && lock.size !== void 0 && node.input.templateFileSize !== lock.size)
371355
+ diagnostics.push(invalidDocTemplateInputDiagnostic(node, `templateFileSize ${node.input.templateFileSize} does not match locked asset size ${lock.size}`));
371356
+ if (lock.name !== void 0 && !hasDocxExtension(lock.name))
371357
+ diagnostics.push(invalidDocTemplateInputDiagnostic(node, `locked asset name ${lock.name} is not a .docx file`));
371358
+ if (lock.mimeType !== void 0 && lock.mimeType !== DOCX_MIME_TYPE)
371359
+ diagnostics.push(invalidDocTemplateInputDiagnostic(node, `locked asset MIME type ${lock.mimeType} is not ${DOCX_MIME_TYPE}`));
371360
+ return diagnostics;
371361
+ }
371362
+ function hasDocxExtension(value) {
371363
+ return value.toLowerCase().endsWith(".docx");
371364
+ }
371365
+ function isReferencePlaceholder(value) {
371366
+ return typeof value === "string";
371367
+ }
371368
+ function isVaultSource(value) {
371369
+ return isVaultRef(value) || isVaultAsset(value);
371370
+ }
371109
371371
  function validateSplitterInput(node) {
371110
371372
  if (!node.input || typeof node.input !== "object")
371111
371373
  return [invalidSplitterInputDiagnostic(node, "input must be an object")];
@@ -371220,19 +371482,34 @@ var require_modules = __commonJS({
371220
371482
  }
371221
371483
  function validateExclusiveFileTarget(file2, context, targetField) {
371222
371484
  if (file2.targetKind === "input") {
371223
- const target = context.builtInputs.find((input) => (input.key ?? input.name) === file2.targetKey);
371224
- if (!target || target.inputType === "file")
371485
+ const target2 = context.builtInputs.find((input) => (input.key ?? input.name) === file2.targetKey);
371486
+ if (!target2 || target2.inputType === "file")
371225
371487
  return [];
371226
371488
  return [incompatibleDocumentRefDiagnostic(file2.targetKey, targetField)];
371227
371489
  }
371228
- const resolved = (0, refs_1.resolveWorkflowRef)(file2, context);
371229
- if (resolved.nodeId === void 0)
371490
+ const target = resolveVisibleNodeOutput(file2.targetKey, context);
371491
+ if (!target)
371230
371492
  return [];
371231
- const selectedSchema = (0, output_schema_1.selectOutputJsonSchema)(context.nodeOutputSchemasById.get(resolved.nodeId), file2.path ?? []);
371232
- if (selectedSchema === void 0 && context.remoteMode.kind === "symbolic" && context.remoteTemplateNodeIds.has(resolved.nodeId))
371493
+ const selectedSchema = (0, output_schema_1.selectOutputJsonSchema)(target.schema, file2.path ?? []);
371494
+ if (selectedSchema === void 0 && context.remoteMode.kind === "symbolic" && context.remoteTemplateNodeIds.has(target.id))
371233
371495
  return [];
371234
371496
  return (0, output_schema_1.isFileCompatibleOutputJsonSchema)(selectedSchema) ? [] : [incompatibleDocumentRefDiagnostic(file2.targetKey, targetField)];
371235
371497
  }
371498
+ function resolveVisibleNodeOutput(targetKey, context) {
371499
+ const identity2 = (0, refs_1.resolveVisibleNodeIdentity)(targetKey, {
371500
+ inputIdsByKey: context.inputIdsByKey,
371501
+ nodeIdentitiesByKey: context.nodeIdentitiesByKey,
371502
+ nodesByPath: context.nodesByPath,
371503
+ currentNode: context.currentNode
371504
+ });
371505
+ if (!identity2)
371506
+ return void 0;
371507
+ return {
371508
+ id: identity2.id,
371509
+ declaration: context.nodeDeclarationsById.get(identity2.id),
371510
+ schema: context.nodeOutputSchemasById.get(identity2.id)
371511
+ };
371512
+ }
371236
371513
  function incompatibleDocumentRefDiagnostic(targetKey, targetField) {
371237
371514
  return {
371238
371515
  code: "compiler.ref.incompatible",
@@ -371455,7 +371732,8 @@ var require_modules = __commonJS({
371455
371732
  [codeModule.kind, codeModule],
371456
371733
  [mapModule.kind, mapModule],
371457
371734
  [splitterModule.kind, splitterModule],
371458
- [cropModule.kind, cropModule]
371735
+ [cropModule.kind, cropModule],
371736
+ [docTemplateModule.kind, docTemplateModule]
371459
371737
  ]);
371460
371738
  }
371461
371739
  });
@@ -371649,10 +371927,31 @@ var require_transpile = __commonJS({
371649
371927
  return createFailedSplitterNode(workflowKey, declaration);
371650
371928
  if (declaration.node.nodeKind === "crop")
371651
371929
  return createFailedCropNode(workflowKey, declaration);
371930
+ if (declaration.node.nodeKind === "doc-template")
371931
+ return createFailedDocTemplateNode(workflowKey, declaration);
371652
371932
  if (declaration.node.nodeKind === "remote-executable" || declaration.node.nodeKind === "remote-agent" || declaration.node.nodeKind === "remote-template")
371653
371933
  return createFailedRemoteNode(workflowKey, declaration);
371654
371934
  return createFailedPromptNode(workflowKey, declaration);
371655
371935
  }
371936
+ function createFailedDocTemplateNode(workflowKey, declaration) {
371937
+ const nodeId = (0, ids_1.stableNodeId)(workflowKey, declaration.node, declaration.path);
371938
+ const linearPorts = failedNodePorts(nodeId);
371939
+ const module3 = modules_1.nodeModuleRegistry.get(declaration.node.nodeKind);
371940
+ return {
371941
+ declarationIndex: declaration.ordinal,
371942
+ path: declaration.path,
371943
+ scopePath: declaration.scopePath,
371944
+ sequenceIndex: declaration.sequenceIndex,
371945
+ linearPorts,
371946
+ node: {
371947
+ id: nodeId,
371948
+ name: declaration.node.name,
371949
+ actionId: module3?.actionId ?? workflow_shared_1.WORKFLOW_ACTION_IDS.documentTemplater,
371950
+ ports: workflowNodePorts(linearPorts),
371951
+ input: module3?.createFailedInput(declaration.node) ?? {}
371952
+ }
371953
+ };
371954
+ }
371656
371955
  function createFailedRemoteNode(workflowKey, declaration) {
371657
371956
  const nodeId = (0, ids_1.stableNodeId)(workflowKey, declaration.node, declaration.path);
371658
371957
  const linearPorts = failedNodePorts(nodeId);
@@ -371916,9 +372215,9 @@ var require_transpile = __commonJS({
371916
372215
  nodeIndexesByKey.set(key, ordinal);
371917
372216
  });
371918
372217
  const { nodesByPath, nodeIdentitiesByKey } = createScopedIdentities(workflowKey, flattenedNodes);
372218
+ const nodeDeclarationsById = new Map(flattenedNodes.map(({ node, path: path3 }) => [(0, ids_1.stableNodeId)(workflowKey, node, path3), node]));
371919
372219
  const inputNamesByKey = new Map(declarationInputs.map((declaration) => [declaration.key ?? declaration.name, declaration.name]));
371920
372220
  const nodeNamesByKey = new Map(topLevelNodes.map(({ node }) => [node.key ?? node.name, node.name]));
371921
- const nodeOutputSchemasByKey = /* @__PURE__ */ new Map();
371922
372221
  const nodeOutputSchemasById = /* @__PURE__ */ new Map();
371923
372222
  const remoteTemplateNodeIds = new Set(flattenedNodes.filter(({ node }) => node.nodeKind === "remote-template").map(({ node, path: path3 }) => (0, ids_1.stableNodeId)(workflowKey, node, path3)));
371924
372223
  const buildBinding = input.declaration[contracts_1.BUILD_BINDING];
@@ -371955,9 +372254,9 @@ var require_transpile = __commonJS({
371955
372254
  },
371956
372255
  nodeIdsByKey,
371957
372256
  nodeIndexesByKey,
372257
+ nodeDeclarationsById,
371958
372258
  inputNamesByKey,
371959
372259
  nodeNamesByKey,
371960
- nodeOutputSchemasByKey,
371961
372260
  nodeOutputSchemasById,
371962
372261
  remoteTemplateNodeIds,
371963
372262
  builtInputs: declarationInputs,
@@ -371970,10 +372269,8 @@ var require_transpile = __commonJS({
371970
372269
  remoteRefs,
371971
372270
  diagnostics
371972
372271
  });
371973
- if (lowered?.outputSchema !== void 0) {
371974
- nodeOutputSchemasByKey.set(node.key ?? node.name, lowered.outputSchema);
372272
+ if (lowered?.outputSchema !== void 0)
371975
372273
  nodeOutputSchemasById.set((0, ids_1.stableNodeId)(workflowKey, node, flattened.path), lowered.outputSchema);
371976
- }
371977
372274
  return lowered ? {
371978
372275
  ...lowered,
371979
372276
  declarationIndex: index,
@@ -371985,6 +372282,7 @@ var require_transpile = __commonJS({
371985
372282
  const loweredModuleNodes = loweredModuleNodesByDeclaration.filter(isLoweredModuleNodeWithIndex);
371986
372283
  const vaultRefs = [...new Set(loweredModuleNodes.flatMap((item) => item.vaultRefs ?? []))].sort((left, right) => left.localeCompare(right));
371987
372284
  const vaultAssets = collectVaultAssetUses(flattenedNodes, workflowKey);
372285
+ const vaultRequirements = [...new Map(loweredModuleNodes.flatMap((item) => item.vaultRequirements ?? []).map((item) => [JSON.stringify(item), item])).values()].sort((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right)));
371988
372286
  const loweredByPath = createLoweredByPath(loweredModuleNodes);
371989
372287
  const nodes = loweredModuleNodes.map((item) => item.node);
371990
372288
  const edges = createTopologyEdges(rootRecords, loweredByPath);
@@ -372027,7 +372325,8 @@ var require_transpile = __commonJS({
372027
372325
  },
372028
372326
  resources: Object.freeze({
372029
372327
  vaultRefs: Object.freeze(vaultRefs),
372030
- ...vaultAssets.length === 0 ? {} : { vaultAssets: Object.freeze(vaultAssets) }
372328
+ ...vaultAssets.length === 0 ? {} : { vaultAssets: Object.freeze(vaultAssets) },
372329
+ ...vaultRequirements.length === 0 ? {} : { vaultRequirements: Object.freeze(vaultRequirements) }
372031
372330
  }),
372032
372331
  diagnostics
372033
372332
  });
@@ -372035,9 +372334,7 @@ var require_transpile = __commonJS({
372035
372334
  function collectVaultAssetUses(records, workflowKey) {
372036
372335
  const byKey = /* @__PURE__ */ new Map();
372037
372336
  for (const { node } of records) {
372038
- if (node.nodeKind !== "splitter" && node.nodeKind !== "crop")
372039
- continue;
372040
- const values = Array.isArray(node.input.file) ? node.input.file : [node.input.file];
372337
+ const values = node.nodeKind === "doc-template" ? [node.input.template, ...Object.values(node.input.placeholders)] : node.nodeKind === "splitter" || node.nodeKind === "crop" ? Array.isArray(node.input.file) ? node.input.file : [node.input.file] : [];
372041
372338
  for (const value of values) {
372042
372339
  if (!isVaultAsset(value))
372043
372340
  continue;
@@ -372812,6 +373109,7 @@ var require_evaluate_source = __commonJS({
372812
373109
  collectWorkflowCodeAliasBindings(node, node.statements, "agent", scopedBindings.promptNodeBindings, scopedBindings.promptNodeNamespaceBindings, scopedBindings.promptNodeNamespaceMemberBindings);
372813
373110
  collectWorkflowCodeAliasBindings(node, node.statements, "llm", scopedBindings.promptNodeBindings, scopedBindings.promptNodeNamespaceBindings, scopedBindings.promptNodeNamespaceMemberBindings);
372814
373111
  collectWorkflowCodeAliasBindings(node, node.statements, "map", scopedBindings.promptNodeBindings, scopedBindings.promptNodeNamespaceBindings, scopedBindings.promptNodeNamespaceMemberBindings);
373112
+ collectWorkflowCodeAliasBindings(node, node.statements, "docTemplate", scopedBindings.promptNodeBindings, scopedBindings.promptNodeNamespaceBindings, scopedBindings.promptNodeNamespaceMemberBindings);
372815
373113
  return typescript_1.default.visitEachChild(node, createVisit(scopedBindings), context);
372816
373114
  }
372817
373115
  if (isForLikeStatement(node)) {
@@ -372980,7 +373278,7 @@ var require_evaluate_source = __commonJS({
372980
373278
  return Boolean(namespaceMemberBindings.get(root)?.has(members.join(".")));
372981
373279
  }
372982
373280
  function isPromptNodeMemberName(name) {
372983
- return name === "agent" || name === "llm" || name === "map";
373281
+ return name === "agent" || name === "docTemplate" || name === "llm" || name === "map";
372984
373282
  }
372985
373283
  function isWorkflowCodeMemberExpression(expression, memberName, memberBindings, namespaceBindings, namespaceMemberBindings) {
372986
373284
  const unwrapped = unwrapExpression(expression);
@@ -373616,6 +373914,7 @@ var require_evaluate_source = __commonJS({
373616
373914
  exportedNames.build.add("build");
373617
373915
  exportedNames.code.add("code");
373618
373916
  exportedNames.promptNodes.add("agent");
373917
+ exportedNames.promptNodes.add("docTemplate");
373619
373918
  exportedNames.promptNodes.add("llm");
373620
373919
  exportedNames.promptNodes.add("map");
373621
373920
  return;
@@ -374113,12 +374412,41 @@ const __workflowCodeApi = (() => {
374113
374412
  }),
374114
374413
  })
374115
374414
  }
374415
+ const docTemplateNode = (options) => {
374416
+ if (!options || typeof options !== 'object' || !options.input || typeof options.input !== 'object')
374417
+ throwAuthoringDiagnostic('docTemplate.input must be an object', options && typeof options === 'object' ? options.__workflowCodeSource : undefined)
374418
+ assertNonEmptyString(options.name, 'docTemplate.name', options.__workflowCodeSource)
374419
+ assertNonEmptyString(options.input.outputFilename, 'docTemplate.input.outputFilename', options.__workflowCodeSource)
374420
+ const template = typeof options.input.template === 'function'
374421
+ ? options.input.template(exclusiveRefContext(options.__workflowCodeSource))
374422
+ : options.input.template
374423
+ if (!isVaultRef(template) && !isVaultAsset(template) && !isWorkflowRef(template))
374424
+ throwAuthoringDiagnostic('docTemplate.input.template must be vault.ref(), vault.asset(), or a workflow reference callback', options.__workflowCodeSource)
374425
+ const placeholders = renderReferenceRecord(options.input.placeholders ?? {}, options.__workflowCodeSource)
374426
+ return freeze({
374427
+ kind: 'node',
374428
+ nodeKind: 'doc-template',
374429
+ name: options.name,
374430
+ ...(options.key !== undefined ? { key: options.key } : {}),
374431
+ input: freeze({
374432
+ template,
374433
+ placeholders: placeholders.values,
374434
+ outputFilename: options.input.outputFilename,
374435
+ ...(options.input.mustache === undefined ? {} : { mustache: options.input.mustache }),
374436
+ ...(options.input.createPermalink === undefined ? {} : { createPermalink: options.input.createPermalink }),
374437
+ ...(options.input.templateFilename === undefined ? {} : { templateFilename: options.input.templateFilename }),
374438
+ ...(options.input.templateFileSize === undefined ? {} : { templateFileSize: options.input.templateFileSize }),
374439
+ }),
374440
+ ...(placeholders.refs.length === 0 ? {} : { placeholderRefs: placeholders.refs }),
374441
+ })
374442
+ }
374116
374443
  return freeze({
374117
374444
  agent: (ref, options) => publishedAgent(ref, options),
374118
374445
  build: buildWorkflow,
374119
374446
  canvas: canvasNode,
374120
374447
  code: codeNode,
374121
374448
  crop: cropNode,
374449
+ docTemplate: docTemplateNode,
374122
374450
  input: freeze({ text: (options) => baseInput('text', options), file: (options) => baseInput('file', options) }),
374123
374451
  llm: (options) => promptNode('llm', options, llmInput),
374124
374452
  map: mapNode,
@@ -376253,8 +376581,8 @@ var require_vault_preflight = __commonJS({
376253
376581
  }
376254
376582
  const results = await Promise.all(references.map(async (reference) => {
376255
376583
  try {
376256
- await input.vaultApi?.validateVaultRef({ reference });
376257
- return [];
376584
+ const metadata = await input.vaultApi?.validateVaultRef({ reference });
376585
+ return validateRequirements(reference, metadata, input.compiled);
376258
376586
  } catch (error48) {
376259
376587
  if (hasDiagnostics(error48))
376260
376588
  return error48.diagnostics;
@@ -376264,6 +376592,27 @@ var require_vault_preflight = __commonJS({
376264
376592
  const diagnostics = results.flat();
376265
376593
  return diagnostics.length > 0 ? { ok: false, diagnostics } : { ok: true, value: createValidation(references) };
376266
376594
  }
376595
+ function validateRequirements(reference, metadata, compiled) {
376596
+ if (!metadata)
376597
+ return [];
376598
+ const requirements = compiled.flatMap((item) => item.resources.vaultRequirements ?? []).filter((requirement) => requirement.reference === reference);
376599
+ const diagnostics = [];
376600
+ for (const requirement of requirements) {
376601
+ if (requirement.expectedName !== void 0 && metadata.name !== void 0 && requirement.expectedName !== metadata.name) {
376602
+ diagnostics.push((0, diagnostics_1.diagnostic)("vault.template.metadata_mismatch", "error", `Vault template ${reference} is named ${metadata.name}, not the declared ${requirement.expectedName}.`, "Update templateFilename or select the matching Vault file before syncing."));
376603
+ }
376604
+ if (requirement.expectedSize !== void 0 && metadata.size !== void 0 && requirement.expectedSize !== metadata.size) {
376605
+ diagnostics.push((0, diagnostics_1.diagnostic)("vault.template.metadata_mismatch", "error", `Vault template ${reference} has size ${metadata.size}, not the declared ${requirement.expectedSize}.`, "Update templateFileSize or select the matching Vault file before syncing."));
376606
+ }
376607
+ if (requirement.requiredExtension !== void 0 && metadata.name !== void 0 && !metadata.name.toLowerCase().endsWith(requirement.requiredExtension)) {
376608
+ diagnostics.push((0, diagnostics_1.diagnostic)("vault.template.invalid_file", "error", `Vault template ${reference} is named ${metadata.name}; docTemplate() requires a ${requirement.requiredExtension} file.`, "Upload a .docx template or correct the Vault reference before syncing."));
376609
+ }
376610
+ if (requirement.requiredMimeType !== void 0 && metadata.mimeType !== void 0 && metadata.mimeType !== requirement.requiredMimeType) {
376611
+ diagnostics.push((0, diagnostics_1.diagnostic)("vault.template.invalid_file", "error", `Vault template ${reference} has MIME type ${metadata.mimeType}; docTemplate() requires ${requirement.requiredMimeType}.`, "Upload a .docx template or correct the Vault reference before syncing."));
376612
+ }
376613
+ }
376614
+ return diagnostics;
376615
+ }
376267
376616
  function collectVaultRefs(compiled) {
376268
376617
  return [...new Set(compiled.flatMap((item) => item.resources?.vaultRefs ?? []))].sort((left, right) => left.localeCompare(right));
376269
376618
  }
@@ -376574,12 +376923,21 @@ var require_remote_api2 = __commonJS({
376574
376923
  throw workflowApiError("vault.ref.inaccessible", "The active Tela environment does not configure a Vault service URL.", "Add services.vault to the active Tela environment and retry.");
376575
376924
  }
376576
376925
  try {
376577
- await vaultRequest(`/files/${encodeURIComponent((0, reference_1.vaultReferenceId)(input.reference))}`, {
376926
+ const result = await vaultRequest(`/files/${encodeURIComponent((0, reference_1.vaultReferenceId)(input.reference))}`, {
376578
376927
  failureCode: "vault.ref.inaccessible",
376579
376928
  invalidResponseCode: "vault.ref.inaccessible",
376580
376929
  failureMessage: (status2) => `Vault reference ${input.reference} is not accessible in the active Tela context (HTTP ${status2}).`,
376581
376930
  failureHint: "Check the selected workspace, context credentials, and file permissions."
376582
376931
  });
376932
+ const metadata = isRecord3(result.metadata) ? result.metadata : {};
376933
+ const name = typeof metadata.originalFileName === "string" ? metadata.originalFileName : typeof metadata.name === "string" ? metadata.name : void 0;
376934
+ const size = typeof metadata.size === "number" ? metadata.size : typeof result.size === "number" ? result.size : void 0;
376935
+ const mimeType = typeof metadata.mimeType === "string" ? metadata.mimeType : void 0;
376936
+ return {
376937
+ ...name === void 0 ? {} : { name },
376938
+ ...size === void 0 ? {} : { size },
376939
+ ...mimeType === void 0 ? {} : { mimeType }
376940
+ };
376583
376941
  } catch (error48) {
376584
376942
  if (hasDiagnostics(error48))
376585
376943
  throw error48;
@@ -376947,18 +377305,30 @@ var require_vault_assets = __commonJS({
376947
377305
  "../../packages/workflow-code/dist/cli/sync/vault-assets.js"(exports2) {
376948
377306
  "use strict";
376949
377307
  Object.defineProperty(exports2, "__esModule", { value: true });
377308
+ exports2.snapshotPreparedWorkflowVaultAssets = snapshotPreparedWorkflowVaultAssets;
377309
+ exports2.prepareWorkflowVaultAssetUploads = prepareWorkflowVaultAssetUploads;
377310
+ exports2.uploadPreparedWorkflowVaultAssets = uploadPreparedWorkflowVaultAssets;
376950
377311
  exports2.prepareWorkflowVaultAssets = prepareWorkflowVaultAssets;
376951
377312
  var node_crypto_1 = require("node:crypto");
376952
377313
  var node_fs_1 = require("node:fs");
376953
377314
  var promises_1 = require("node:fs/promises");
376954
377315
  var node_path_1 = require("node:path");
376955
377316
  var diagnostics_1 = require_diagnostics();
376956
- async function prepareWorkflowVaultAssets(input) {
377317
+ function snapshotPreparedWorkflowVaultAssets(assets) {
377318
+ return assets.map((asset) => asset.previous ?? Object.freeze({
377319
+ ...asset.asset,
377320
+ name: asset.name,
377321
+ resolvedPath: asset.resolvedPath,
377322
+ contentHash: asset.contentHash,
377323
+ size: asset.content.byteLength,
377324
+ // The compiler only needs lock-derived local metadata at this stage.
377325
+ ref: `vault://${asset.contentHash}`,
377326
+ uploadedAt: ""
377327
+ }));
377328
+ }
377329
+ async function prepareWorkflowVaultAssetUploads(input) {
376957
377330
  if (input.assets.length === 0)
376958
377331
  return { ok: true, value: [] };
376959
- if (!input.vaultApi) {
376960
- return { ok: false, diagnostics: [(0, diagnostics_1.diagnostic)("vault.asset.upload_failed", "error", "Vault assets cannot be uploaded because the active remote client has no Vault service.", "Configure services.vault for the active Tela environment and retry before syncing.")] };
376961
- }
376962
377332
  const existingByKey = new Map((input.existing ?? []).map((asset) => [asset.key, asset]));
376963
377333
  const prepared = [];
376964
377334
  let projectRoot;
@@ -376998,33 +377368,70 @@ var require_vault_assets = __commonJS({
376998
377368
  }
376999
377369
  const contentHash = (0, node_crypto_1.createHash)("sha256").update(content).digest("hex");
377000
377370
  const previous = existingByKey.get(asset.key);
377001
- if (previous?.contentHash === contentHash) {
377002
- prepared.push(previous);
377371
+ const name = asset.name ?? (0, node_path_1.basename)(resolvedPath);
377372
+ prepared.push(Object.freeze({
377373
+ asset,
377374
+ name,
377375
+ resolvedPath,
377376
+ content,
377377
+ contentHash,
377378
+ ...previous?.contentHash === contentHash ? { previous } : {}
377379
+ }));
377380
+ }
377381
+ return { ok: true, value: prepared };
377382
+ }
377383
+ async function uploadPreparedWorkflowVaultAssets(input) {
377384
+ if (input.assets.length === 0)
377385
+ return { ok: true, value: [] };
377386
+ if (!input.vaultApi) {
377387
+ return { ok: false, diagnostics: [(0, diagnostics_1.diagnostic)("vault.asset.upload_failed", "error", "Vault assets cannot be uploaded because the active remote client has no Vault service.", "Configure services.vault for the active Tela environment and retry before syncing.")] };
377388
+ }
377389
+ const uploaded = [];
377390
+ for (const asset of input.assets) {
377391
+ if (asset.previous) {
377392
+ uploaded.push(asset.previous);
377003
377393
  continue;
377004
377394
  }
377005
- const name = asset.name ?? (0, node_path_1.basename)(resolvedPath);
377006
377395
  try {
377007
377396
  const ref = await input.vaultApi.uploadVaultAsset({
377008
- name,
377009
- ...asset.mimeType === void 0 ? {} : { mimeType: asset.mimeType },
377010
- content
377397
+ name: asset.name,
377398
+ ...asset.asset.mimeType === void 0 ? {} : { mimeType: asset.asset.mimeType },
377399
+ content: asset.content
377011
377400
  });
377012
- prepared.push(Object.freeze({
377013
- ...asset,
377014
- name,
377015
- resolvedPath,
377016
- contentHash,
377017
- size: content.byteLength,
377401
+ uploaded.push(Object.freeze({
377402
+ ...asset.asset,
377403
+ name: asset.name,
377404
+ resolvedPath: asset.resolvedPath,
377405
+ contentHash: asset.contentHash,
377406
+ size: asset.content.byteLength,
377018
377407
  ref,
377019
377408
  uploadedAt: input.now?.() ?? (/* @__PURE__ */ new Date()).toISOString()
377020
377409
  }));
377410
+ const persisted = await input.onUploaded?.(snapshotKnownWorkflowVaultAssets(input.assets, uploaded));
377411
+ if (persisted !== void 0 && !persisted.ok)
377412
+ return persisted;
377021
377413
  } catch (error48) {
377022
377414
  if (hasDiagnostics(error48))
377023
377415
  return { ok: false, diagnostics: error48.diagnostics };
377024
- return { ok: false, diagnostics: [(0, diagnostics_1.diagnostic)("vault.asset.upload_failed", "error", `Vault asset ${asset.path} could not be uploaded.`, "Check the active Vault service and retry sync.")] };
377416
+ return { ok: false, diagnostics: [(0, diagnostics_1.diagnostic)("vault.asset.upload_failed", "error", `Vault asset ${asset.asset.path} could not be uploaded.`, "Check the active Vault service and retry sync.")] };
377025
377417
  }
377026
377418
  }
377027
- return { ok: true, value: prepared };
377419
+ return { ok: true, value: uploaded };
377420
+ }
377421
+ function snapshotKnownWorkflowVaultAssets(plans, uploaded) {
377422
+ return plans.flatMap((plan, index) => {
377423
+ const snapshot = uploaded[index] ?? plan.previous;
377424
+ return snapshot === void 0 ? [] : [snapshot];
377425
+ });
377426
+ }
377427
+ async function prepareWorkflowVaultAssets(input) {
377428
+ if (input.assets.length > 0 && !input.vaultApi) {
377429
+ return { ok: false, diagnostics: [(0, diagnostics_1.diagnostic)("vault.asset.upload_failed", "error", "Vault assets cannot be uploaded because the active remote client has no Vault service.", "Configure services.vault for the active Tela environment and retry before syncing.")] };
377430
+ }
377431
+ const prepared = await prepareWorkflowVaultAssetUploads(input);
377432
+ if (!prepared.ok)
377433
+ return prepared;
377434
+ return await uploadPreparedWorkflowVaultAssets({ assets: prepared.value, vaultApi: input.vaultApi, now: input.now });
377028
377435
  }
377029
377436
  function isWithinRoot(path3, rootDir) {
377030
377437
  const relativePath = (0, node_path_1.relative)((0, node_path_1.resolve)(rootDir), path3);
@@ -377036,6 +377443,79 @@ var require_vault_assets = __commonJS({
377036
377443
  }
377037
377444
  });
377038
377445
 
377446
+ // ../../packages/workflow-code/dist/cli/sync/vault-locks.js
377447
+ var require_vault_locks = __commonJS({
377448
+ "../../packages/workflow-code/dist/cli/sync/vault-locks.js"(exports2) {
377449
+ "use strict";
377450
+ Object.defineProperty(exports2, "__esModule", { value: true });
377451
+ exports2.createWorkflowVaultAssetLockPersister = createWorkflowVaultAssetLockPersister;
377452
+ var diagnostics_1 = require_diagnostics();
377453
+ var state_1 = require_state2();
377454
+ async function createWorkflowVaultAssetLockPersister(input) {
377455
+ const lockfilePath = (0, state_1.deriveLockfilePath)(input.cwd, input.facts);
377456
+ if (!lockfilePath.ok)
377457
+ return { ok: false, diagnostics: lockfilePath.diagnostics };
377458
+ const remote = await fetchPromptSnapshot(input.remoteApi, input.facts);
377459
+ if (!remote.ok)
377460
+ return { ok: false, diagnostics: remote.diagnostics };
377461
+ let current = input.existing;
377462
+ return {
377463
+ ok: true,
377464
+ value: {
377465
+ persist: async (vaultAssets) => {
377466
+ const plan = (0, state_1.planRemoteSnapshotWrite)(lockfilePath.value, input.facts, remote.value, current, void 0, vaultAssets);
377467
+ if (!plan.ok)
377468
+ return { ok: false, diagnostics: plan.diagnostics };
377469
+ const written = await (0, state_1.writePlannedLockfile)(plan.value);
377470
+ if (!written.ok)
377471
+ return { ok: false, diagnostics: written.diagnostics };
377472
+ current = {
377473
+ path: lockfilePath.value,
377474
+ hash: written.value.hash,
377475
+ content: plan.value.content,
377476
+ lockfile: plan.value.lockfile
377477
+ };
377478
+ return { ok: true, value: current };
377479
+ }
377480
+ }
377481
+ };
377482
+ }
377483
+ async function fetchPromptSnapshot(remoteApi, facts) {
377484
+ const promptId = facts.context.promptId;
377485
+ if (promptId === void 0) {
377486
+ return {
377487
+ ok: false,
377488
+ diagnostics: [(0, diagnostics_1.diagnostic)("state.prompt_id.missing", "error", `Workflow target ${facts.targetName} has no prompt id for context ${facts.context.key}`, "Add promptId to the active workflow context binding before retrying the upload.")]
377489
+ };
377490
+ }
377491
+ try {
377492
+ const snapshot = await remoteApi.fetchPromptSnapshot({
377493
+ promptId,
377494
+ projectId: facts.context.projectId
377495
+ });
377496
+ if (snapshot.prompt.id !== promptId) {
377497
+ return {
377498
+ ok: false,
377499
+ diagnostics: [(0, diagnostics_1.diagnostic)("sync.remote.prompt_mismatch", "error", `Remote prompt ${snapshot.prompt.id} does not match configured prompt ${promptId}`, "Check the workflow target promptId binding.")]
377500
+ };
377501
+ }
377502
+ return { ok: true, value: snapshot };
377503
+ } catch (error48) {
377504
+ return {
377505
+ ok: false,
377506
+ diagnostics: diagnosticsFromError(error48)
377507
+ };
377508
+ }
377509
+ }
377510
+ function diagnosticsFromError(error48) {
377511
+ if (error48 && typeof error48 === "object" && "diagnostics" in error48 && Array.isArray(error48.diagnostics))
377512
+ return error48.diagnostics;
377513
+ const detail = error48 instanceof Error ? ` ${error48.message}` : "";
377514
+ return [(0, diagnostics_1.diagnostic)("sync.remote.request_failed", "error", `Unable to fetch the workflow state before persisting uploaded Vault assets.${detail}`, "Check the active Tela context and retry sync.")];
377515
+ }
377516
+ }
377517
+ });
377518
+
377039
377519
  // ../../packages/workflow-code/dist/cli/sync/index.js
377040
377520
  var require_sync2 = __commonJS({
377041
377521
  "../../packages/workflow-code/dist/cli/sync/index.js"(exports2) {
@@ -377062,6 +377542,7 @@ var require_sync2 = __commonJS({
377062
377542
  __exportStar(require_remote_api2(), exports2);
377063
377543
  __exportStar(require_types5(), exports2);
377064
377544
  __exportStar(require_vault_assets(), exports2);
377545
+ __exportStar(require_vault_locks(), exports2);
377065
377546
  __exportStar(require_vault_preflight(), exports2);
377066
377547
  }
377067
377548
  });
@@ -377503,7 +377984,7 @@ var require_publish2 = __commonJS({
377503
377984
  tsconfig: configResult.value.config.tsconfig,
377504
377985
  targets: resolved.targets,
377505
377986
  rootDir: context.cwd,
377506
- vaultApi: remoteApi
377987
+ remoteApi
377507
377988
  });
377508
377989
  if (!prepared.ok)
377509
377990
  return { exitCode: 1, diagnostics: [...environmentCreationDiagnostics, ...prepared.diagnostics], compiled: prepared.compiled };
@@ -377596,7 +378077,7 @@ var require_publish2 = __commonJS({
377596
378077
  return { ok: true, targets: Object.entries(workflows).map(([name, target]) => ({ name, target })) };
377597
378078
  }
377598
378079
  async function preparePublishTargets(options2) {
377599
- const prepared = [];
378080
+ const staged = [];
377600
378081
  for (const selected of options2.targets) {
377601
378082
  const source = await (0, load_source_1.loadWorkflowSource)((0, node_path_1.dirname)(options2.configPath), selected.target, options2.configEnv, options2.tsconfig);
377602
378083
  if (!source.ok)
@@ -377640,26 +378121,75 @@ var require_publish2 = __commonJS({
377640
378121
  if (!lockfileIdentity.ok)
377641
378122
  return { ok: false, diagnostics: lockfileIdentity.diagnostics, compiled: initial };
377642
378123
  }
377643
- const vaultAssets = await (0, sync_1.prepareWorkflowVaultAssets)({
378124
+ const vaultPlans = await (0, sync_1.prepareWorkflowVaultAssetUploads)({
377644
378125
  rootDir: (0, node_path_1.dirname)(options2.configPath),
377645
378126
  assets: initial.resources.vaultAssets ?? [],
377646
- existing: existing.ok ? existing.value.lockfile.vaultAssets : void 0,
377647
- vaultApi: options2.vaultApi
378127
+ existing: existing.ok ? existing.value.lockfile.vaultAssets : void 0
377648
378128
  });
377649
- if (!vaultAssets.ok)
377650
- return { ok: false, diagnostics: vaultAssets.diagnostics, compiled: initial };
377651
- const compiled = (0, compiler_1.transpileWorkflow)({
378129
+ if (!vaultPlans.ok)
378130
+ return { ok: false, diagnostics: vaultPlans.diagnostics, compiled: initial };
378131
+ const preflight = (0, compiler_1.transpileWorkflow)({
377652
378132
  targetName: selected.name,
377653
378133
  workflowKey: selected.target.workflowKey,
377654
378134
  title: selected.target.title,
377655
378135
  declaration: source.value.declaration,
377656
378136
  source: source.value.source,
378137
+ vaultAssets: (0, sync_1.snapshotPreparedWorkflowVaultAssets)(vaultPlans.value)
378138
+ });
378139
+ if (preflight.diagnostics.some((item) => item.severity === "error"))
378140
+ return { ok: false, diagnostics: [...preflight.diagnostics], compiled: preflight };
378141
+ staged.push({
378142
+ ...selected,
378143
+ source: source.value,
378144
+ preflight,
378145
+ vaultPlans: vaultPlans.value,
378146
+ ...existing.ok ? { lockfileState: existing.value } : {}
378147
+ });
378148
+ }
378149
+ const prepared = [];
378150
+ for (const stagedTarget of staged) {
378151
+ let onUploaded;
378152
+ if (stagedTarget.vaultPlans.some((asset) => asset.previous === void 0)) {
378153
+ const persister = await (0, sync_1.createWorkflowVaultAssetLockPersister)({
378154
+ cwd: options2.rootDir,
378155
+ facts: {
378156
+ targetName: stagedTarget.name,
378157
+ workflowKey: stagedTarget.preflight.workflowKey,
378158
+ context: {
378159
+ key: stagedTarget.identity.contextKey ?? "default",
378160
+ ...stagedTarget.identity.contextId === void 0 ? {} : { id: stagedTarget.identity.contextId },
378161
+ projectId: stagedTarget.identity.projectId,
378162
+ promptId: stagedTarget.identity.promptId
378163
+ }
378164
+ },
378165
+ existing: stagedTarget.lockfileState,
378166
+ remoteApi: options2.remoteApi
378167
+ });
378168
+ if (!persister.ok)
378169
+ return { ok: false, diagnostics: persister.diagnostics, compiled: stagedTarget.preflight };
378170
+ onUploaded = persister.value.persist;
378171
+ }
378172
+ const vaultAssets = await (0, sync_1.uploadPreparedWorkflowVaultAssets)({
378173
+ assets: stagedTarget.vaultPlans,
378174
+ vaultApi: options2.remoteApi,
378175
+ ...onUploaded === void 0 ? {} : { onUploaded }
378176
+ });
378177
+ if (!vaultAssets.ok)
378178
+ return { ok: false, diagnostics: vaultAssets.diagnostics, compiled: stagedTarget.preflight };
378179
+ const compiled = (0, compiler_1.transpileWorkflow)({
378180
+ targetName: stagedTarget.name,
378181
+ workflowKey: stagedTarget.target.workflowKey,
378182
+ title: stagedTarget.target.title,
378183
+ declaration: stagedTarget.source.declaration,
378184
+ source: stagedTarget.source.source,
377657
378185
  vaultAssets: vaultAssets.value
377658
378186
  });
377659
378187
  if (compiled.diagnostics.some((item) => item.severity === "error"))
377660
378188
  return { ok: false, diagnostics: [...compiled.diagnostics], compiled };
377661
378189
  prepared.push({
377662
- ...selected,
378190
+ name: stagedTarget.name,
378191
+ target: stagedTarget.target,
378192
+ identity: stagedTarget.identity,
377663
378193
  compiled,
377664
378194
  vaultAssets: vaultAssets.value
377665
378195
  });
@@ -377871,30 +378401,14 @@ var require_sync3 = __commonJS({
377871
378401
  const existing = await (0, state_1.readLockfile)(lockPath.value);
377872
378402
  if (!existing.ok && existing.diagnostics[0]?.code !== "state.lockfile.missing")
377873
378403
  return { ok: false, diagnostics: existing.diagnostics, compiled: initialSymbolic };
377874
- const vaultAssets = await (0, sync_1.prepareWorkflowVaultAssets)({
377875
- rootDir: options2.projectDir,
377876
- assets: initialSymbolic.resources.vaultAssets ?? [],
377877
- existing: existing.ok ? existing.value.lockfile.vaultAssets : void 0,
377878
- vaultApi: options2.vaultApi
377879
- });
377880
- if (!vaultAssets.ok)
377881
- return { ok: false, diagnostics: vaultAssets.diagnostics, compiled: initialSymbolic };
377882
- const symbolic = (0, compiler_1.transpileWorkflow)({
377883
- targetName: selected.name,
377884
- workflowKey: selected.target.workflowKey,
377885
- title: selected.target.title,
377886
- declaration: sourceResult.value.declaration,
377887
- source: sourceResult.value.source,
377888
- vaultAssets: vaultAssets.value
377889
- });
377890
- if (symbolic.diagnostics.some((item) => item.severity === "error"))
377891
- return { ok: false, diagnostics: [...symbolic.diagnostics], compiled: symbolic };
377892
378404
  symbolicPrepared.push({
377893
378405
  ...selected,
377894
378406
  source: sourceResult.value,
377895
- symbolic,
377896
- compiled: symbolic,
377897
- vaultAssets: vaultAssets.value,
378407
+ symbolic: initialSymbolic,
378408
+ compiled: initialSymbolic,
378409
+ vaultAssets: [],
378410
+ ...existing.ok ? { lockfile: existing.value.lockfile } : {},
378411
+ ...existing.ok ? { lockfileState: existing.value } : {},
377898
378412
  identity: {
377899
378413
  contextKey: identity2.value.contextKey,
377900
378414
  contextId: identity2.value.contextId,
@@ -377905,7 +378419,7 @@ var require_sync3 = __commonJS({
377905
378419
  }
377906
378420
  const needsCatalog = options2.catalogApi !== void 0 || symbolicPrepared.some((item) => item.symbolic.remoteRefs.length > 0);
377907
378421
  if (!needsCatalog)
377908
- return { ok: true, targets: symbolicPrepared };
378422
+ return await prepareVaultAssetsForTargets({ ...options2, remoteApi: options2.vaultApi }, symbolicPrepared);
377909
378423
  let api;
377910
378424
  try {
377911
378425
  api = options2.catalogApi ?? await (0, catalog_1.createWorkflowCatalogApi)();
@@ -377928,19 +378442,12 @@ var require_sync3 = __commonJS({
377928
378442
  }
377929
378443
  const prepared = [];
377930
378444
  for (const item of symbolicPrepared) {
377931
- const facts = factsForPrepared(item);
377932
- const lockPath = (0, state_1.deriveLockfilePath)(options2.rootDir, facts);
377933
- if (!lockPath.ok)
377934
- return { ok: false, diagnostics: lockPath.diagnostics, compiled: item.symbolic };
377935
- const existing = await (0, state_1.readLockfile)(lockPath.value);
377936
- if (!existing.ok && existing.diagnostics[0]?.code !== "state.lockfile.missing")
377937
- return { ok: false, diagnostics: existing.diagnostics, compiled: item.symbolic };
377938
378445
  const initialGenerated = (0, catalog_1.validateAndLockRemoteRefs)({
377939
378446
  contextId: snapshot.context.id,
377940
378447
  workspaceId: snapshot.context.workspaceId,
377941
378448
  snapshot,
377942
378449
  refs: item.symbolic.remoteRefs,
377943
- existing: existing.ok ? existing.value.lockfile.generatedMetadata : void 0
378450
+ existing: item.lockfile?.generatedMetadata
377944
378451
  });
377945
378452
  if (initialGenerated.diagnostics.some((diagnostic) => diagnostic.severity === "error"))
377946
378453
  return { ok: false, diagnostics: [...initialGenerated.diagnostics], compiled: item.symbolic };
@@ -377958,26 +378465,87 @@ var require_sync3 = __commonJS({
377958
378465
  workspaceId: snapshot.context.workspaceId,
377959
378466
  snapshot,
377960
378467
  refs: compiled.remoteRefs,
377961
- existing: existing.ok ? existing.value.lockfile.generatedMetadata : void 0
378468
+ existing: item.lockfile?.generatedMetadata
377962
378469
  });
377963
378470
  const diagnostics = [...generated.diagnostics, ...compiled.diagnostics];
377964
- if (diagnostics.some((diagnostic) => diagnostic.severity === "error"))
378471
+ if (diagnostics.some((diagnostic) => diagnostic.severity === "error" && diagnostic.code !== "vault.asset.missing_lock"))
377965
378472
  return { ok: false, diagnostics, compiled };
377966
- prepared.push({ ...item, generatedMetadata: generated.locks, compiled });
378473
+ prepared.push({
378474
+ ...item,
378475
+ generatedMetadata: generated.locks,
378476
+ remote: { kind: "resolved", snapshot, locks: generated.locks.refs },
378477
+ compiled
378478
+ });
377967
378479
  }
377968
- return { ok: true, targets: prepared };
378480
+ return await prepareVaultAssetsForTargets({ ...options2, remoteApi: options2.vaultApi }, prepared);
377969
378481
  }
377970
- function factsForPrepared(prepared) {
377971
- return {
377972
- targetName: prepared.name,
377973
- workflowKey: prepared.symbolic.workflowKey,
377974
- context: {
377975
- key: prepared.identity.contextKey ?? "default",
377976
- ...prepared.identity.contextId === void 0 ? {} : { id: prepared.identity.contextId },
377977
- projectId: prepared.identity.projectId,
377978
- promptId: prepared.identity.promptId
378482
+ async function prepareVaultAssetsForTargets(options2, targets) {
378483
+ const staged = [];
378484
+ for (const target of targets) {
378485
+ const vaultAssets = await (0, sync_1.prepareWorkflowVaultAssetUploads)({
378486
+ rootDir: options2.projectDir,
378487
+ assets: target.symbolic.resources.vaultAssets ?? [],
378488
+ existing: target.lockfile?.vaultAssets
378489
+ });
378490
+ if (!vaultAssets.ok)
378491
+ return { ok: false, diagnostics: vaultAssets.diagnostics, compiled: target.compiled };
378492
+ const preflight = (0, compiler_1.transpileWorkflow)({
378493
+ targetName: target.name,
378494
+ workflowKey: target.target.workflowKey,
378495
+ title: target.target.title,
378496
+ declaration: target.source.declaration,
378497
+ source: target.source.source,
378498
+ ...target.remote === void 0 ? {} : { remote: target.remote },
378499
+ vaultAssets: (0, sync_1.snapshotPreparedWorkflowVaultAssets)(vaultAssets.value)
378500
+ });
378501
+ if (preflight.diagnostics.some((item) => item.severity === "error"))
378502
+ return { ok: false, diagnostics: [...preflight.diagnostics], compiled: preflight };
378503
+ staged.push({ target, vaultAssets: vaultAssets.value });
378504
+ }
378505
+ const prepared = [];
378506
+ for (const item of staged) {
378507
+ let onUploaded;
378508
+ if (item.vaultAssets.some((asset) => asset.previous === void 0)) {
378509
+ const persister = await (0, sync_1.createWorkflowVaultAssetLockPersister)({
378510
+ cwd: options2.rootDir,
378511
+ facts: {
378512
+ targetName: item.target.name,
378513
+ workflowKey: item.target.symbolic.workflowKey,
378514
+ context: {
378515
+ key: item.target.identity.contextKey ?? "default",
378516
+ ...item.target.identity.contextId === void 0 ? {} : { id: item.target.identity.contextId },
378517
+ projectId: item.target.identity.projectId,
378518
+ promptId: item.target.identity.promptId
378519
+ }
378520
+ },
378521
+ existing: item.target.lockfileState,
378522
+ remoteApi: options2.remoteApi
378523
+ });
378524
+ if (!persister.ok)
378525
+ return { ok: false, diagnostics: persister.diagnostics, compiled: item.target.compiled };
378526
+ onUploaded = persister.value.persist;
377979
378527
  }
377980
- };
378528
+ const vaultAssets = await (0, sync_1.uploadPreparedWorkflowVaultAssets)({
378529
+ assets: item.vaultAssets,
378530
+ vaultApi: options2.vaultApi,
378531
+ ...onUploaded === void 0 ? {} : { onUploaded }
378532
+ });
378533
+ if (!vaultAssets.ok)
378534
+ return { ok: false, diagnostics: vaultAssets.diagnostics, compiled: item.target.compiled };
378535
+ const compiled = (0, compiler_1.transpileWorkflow)({
378536
+ targetName: item.target.name,
378537
+ workflowKey: item.target.target.workflowKey,
378538
+ title: item.target.target.title,
378539
+ declaration: item.target.source.declaration,
378540
+ source: item.target.source.source,
378541
+ ...item.target.remote === void 0 ? {} : { remote: item.target.remote },
378542
+ vaultAssets: vaultAssets.value
378543
+ });
378544
+ if (compiled.diagnostics.some((item2) => item2.severity === "error"))
378545
+ return { ok: false, diagnostics: [...compiled.diagnostics], compiled };
378546
+ prepared.push({ ...item.target, compiled, vaultAssets: vaultAssets.value });
378547
+ }
378548
+ return { ok: true, targets: prepared };
377981
378549
  }
377982
378550
  function renderSingleSyncResult(item) {
377983
378551
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/tela-cli",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Tela command line tools for local state and agent workflows.",
5
5
  "engines": {
6
6
  "node": ">=22"