@synergenius/flow-weaver 0.21.16 → 0.21.17

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.
@@ -28,7 +28,7 @@ export declare class AnnotationGenerator {
28
28
  * Reserved STEP ports (execute, onSuccess, onFailure) use @input/@output.
29
29
  * Custom STEP ports use @step.
30
30
  */
31
- export declare function generateJSDocPortTag(name: string, port: TPortDefinition, direction: 'input' | 'output', _implicitOrder?: number): string;
31
+ export declare function generateJSDocPortTag(rawName: string, port: TPortDefinition, direction: 'input' | 'output', _implicitOrder?: number): string;
32
32
  /**
33
33
  * Simply return ports as-is to preserve exact order from the AST
34
34
  * Don't compute or add any new metadata - only preserve what's already there
@@ -380,7 +380,9 @@ export class AnnotationGenerator {
380
380
  * Reserved STEP ports (execute, onSuccess, onFailure) use @input/@output.
381
381
  * Custom STEP ports use @step.
382
382
  */
383
- export function generateJSDocPortTag(name, port, direction, _implicitOrder) {
383
+ export function generateJSDocPortTag(rawName, port, direction, _implicitOrder) {
384
+ // Support scoped key format: use _realName if present (for multi-scope mandatory ports)
385
+ const name = port._realName ?? rawName;
384
386
  // Determine tag: @step for explicit control flow, @input/@output for data
385
387
  // Reserved STEP ports (execute, onSuccess, onFailure) stay as @input/@output
386
388
  // Scoped mandatory ports (start, success, failure) with scope attribute also stay as @input/@output
@@ -721,6 +721,8 @@ export type TPortDefinition = {
721
721
  order?: number;
722
722
  /** Additional metadata */
723
723
  metadata?: Record<string, unknown>;
724
+ /** Internal: real port name when stored under a scoped composite key (multi-scope mandatory ports) */
725
+ _realName?: string;
724
726
  };
725
727
  /**
726
728
  * Data Type - The type of data a port carries.
@@ -9671,7 +9671,7 @@ var VERSION;
9671
9671
  var init_generated_version = __esm({
9672
9672
  "src/generated-version.ts"() {
9673
9673
  "use strict";
9674
- VERSION = "0.21.16";
9674
+ VERSION = "0.21.17";
9675
9675
  }
9676
9676
  });
9677
9677
 
@@ -18434,7 +18434,8 @@ var init_sugar_optimizer = __esm({
18434
18434
  });
18435
18435
 
18436
18436
  // src/annotation-generator.ts
18437
- function generateJSDocPortTag(name, port, direction, _implicitOrder) {
18437
+ function generateJSDocPortTag(rawName, port, direction, _implicitOrder) {
18438
+ const name = port._realName ?? rawName;
18438
18439
  const tag = shouldUseStepTag(name, port) ? "step" : direction;
18439
18440
  let portStr = `@${tag} `;
18440
18441
  if (port.optional && port.default !== void 0) {
@@ -93230,7 +93231,7 @@ function displayInstalledPackage(pkg) {
93230
93231
  // src/cli/index.ts
93231
93232
  init_logger();
93232
93233
  init_error_utils();
93233
- var version2 = true ? "0.21.16" : "0.0.0-dev";
93234
+ var version2 = true ? "0.21.17" : "0.0.0-dev";
93234
93235
  var program2 = new Command();
93235
93236
  program2.name("fw").description("Flow Weaver Annotations - Compile and validate workflow files").option("-v, --version", "Output the current version").option("--no-color", "Disable colors").option("--color", "Force colors").on("option:version", () => {
93236
93237
  logger.banner(version2);
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.21.16";
1
+ export declare const VERSION = "0.21.17";
2
2
  //# sourceMappingURL=generated-version.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Auto-generated by scripts/generate-version.ts — do not edit manually
2
- export const VERSION = '0.21.16';
2
+ export const VERSION = '0.21.17';
3
3
  //# sourceMappingURL=generated-version.js.map
@@ -151,47 +151,56 @@ export function syncSignatureToJSDoc(functionText) {
151
151
  .map((p) => p.name);
152
152
  const signatureInputOrder = rawParamOrder.length >= parsedOrder.length ? rawParamOrder : parsedOrder;
153
153
  // ==========================================================================
154
- // Auto-generate mandatory scoped ports for declared @scope tags
154
+ // Auto-generate mandatory scoped ports for all scopes
155
+ // Collects from both @scope tags AND per-port scope:name annotations
155
156
  // ==========================================================================
157
+ const declaredScopes = new Set();
158
+ // From @scope tags
156
159
  const jsdocMatch = functionText.match(JSDOC_BLOCK_REGEX);
157
160
  if (jsdocMatch) {
158
161
  const jsdoc = jsdocMatch[0];
159
- const declaredScopes = new Set();
160
162
  SCOPE_TAG_REGEX.lastIndex = 0;
161
163
  let scopeMatch;
162
164
  while ((scopeMatch = SCOPE_TAG_REGEX.exec(jsdoc)) != null) {
163
165
  declaredScopes.add(scopeMatch[1]);
164
166
  }
165
- // For each declared scope, ensure mandatory ports exist
166
- for (const scopeName of declaredScopes) {
167
- // Mandatory OUTPUT: start (STEP)
168
- if (!finalOutputs[SCOPED_PORT_NAMES.START] || finalOutputs[SCOPED_PORT_NAMES.START].scope !== scopeName) {
169
- // Check if 'start' exists with this scope
170
- const hasStart = Object.entries(finalOutputs).some(([name, port]) => name === SCOPED_PORT_NAMES.START && port.scope === scopeName);
171
- if (!hasStart) {
172
- finalOutputs[SCOPED_PORT_NAMES.START] = {
173
- dataType: "STEP",
174
- scope: scopeName,
175
- };
176
- }
177
- }
178
- // Mandatory INPUT: success (STEP)
179
- const hasSuccess = Object.entries(finalInputs).some(([name, port]) => name === SCOPED_PORT_NAMES.SUCCESS && port.scope === scopeName);
180
- if (!hasSuccess) {
181
- finalInputs[SCOPED_PORT_NAMES.SUCCESS] = {
182
- dataType: "STEP",
183
- scope: scopeName,
184
- };
185
- }
186
- // Mandatory INPUT: failure (STEP)
187
- const hasFailure = Object.entries(finalInputs).some(([name, port]) => name === SCOPED_PORT_NAMES.FAILURE && port.scope === scopeName);
188
- if (!hasFailure) {
189
- finalInputs[SCOPED_PORT_NAMES.FAILURE] = {
190
- dataType: "STEP",
191
- scope: scopeName,
192
- };
193
- }
194
- }
167
+ }
168
+ // From per-port scope annotations, but ONLY when the scope has a matching
169
+ // callback parameter (confirming it's a real scope, not just a labeled port)
170
+ for (const port of Object.values(finalInputs)) {
171
+ if (port.scope && callbackInfo.has(port.scope))
172
+ declaredScopes.add(port.scope);
173
+ }
174
+ for (const port of Object.values(finalOutputs)) {
175
+ if (port.scope && callbackInfo.has(port.scope))
176
+ declaredScopes.add(port.scope);
177
+ }
178
+ // For each scope, ensure mandatory ports exist.
179
+ // Port Records use name as key. When multiple scopes need the same mandatory port
180
+ // (e.g., "start" for scope "a" and "start" for scope "b"), we use a scoped key
181
+ // format "name\0scope" for the second+ scope. generateJSDocPortTag receives the
182
+ // real name via the port definition's _realName field.
183
+ for (const scopeName of declaredScopes) {
184
+ // Helper: find if mandatory port exists for this specific scope
185
+ const hasPortForScope = (ports, portName, scope) => Object.entries(ports).some(([name, port]) => (name === portName || port._realName === portName) && port.scope === scope);
186
+ // Helper: add a mandatory port, using a scoped key if the base key is taken by another scope
187
+ const addMandatoryPort = (ports, portName, scope, extra) => {
188
+ if (hasPortForScope(ports, portName, scope))
189
+ return;
190
+ // Use base key if available, otherwise use scoped key
191
+ const key = !ports[portName] || ports[portName].scope === scope
192
+ ? portName
193
+ : `${portName}\0${scope}`;
194
+ ports[key] = {
195
+ dataType: "STEP",
196
+ scope,
197
+ ...(key !== portName && { _realName: portName }),
198
+ ...extra,
199
+ };
200
+ };
201
+ addMandatoryPort(finalOutputs, SCOPED_PORT_NAMES.START, scopeName);
202
+ addMandatoryPort(finalInputs, SCOPED_PORT_NAMES.SUCCESS, scopeName);
203
+ addMandatoryPort(finalInputs, SCOPED_PORT_NAMES.FAILURE, scopeName, { failure: true });
195
204
  }
196
205
  return updatePortsInFunctionText(functionText, finalInputs, finalOutputs, signatureInputOrder);
197
206
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synergenius/flow-weaver",
3
- "version": "0.21.16",
3
+ "version": "0.21.17",
4
4
  "description": "Deterministic workflow compiler for AI agents. Compiles to standalone TypeScript, no runtime dependencies.",
5
5
  "private": false,
6
6
  "type": "module",