libretto 0.6.19 → 0.6.21

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.
@@ -89,115 +89,14 @@ function readInstalledSkillVersions(): string[] {
89
89
  return [...versions];
90
90
  }
91
91
 
92
- function parseVersion(version: string): {
93
- major: number;
94
- minor: number;
95
- patch: number;
96
- prerelease: string | null;
97
- } | null {
98
- const match = version.match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/);
99
- if (!match) {
100
- return null;
101
- }
102
-
103
- return {
104
- major: Number(match[1]),
105
- minor: Number(match[2]),
106
- patch: Number(match[3]),
107
- prerelease: match[4] ?? null,
108
- };
109
- }
110
-
111
- function compareVersions(left: string, right: string): number {
112
- const parsedLeft = parseVersion(left);
113
- const parsedRight = parseVersion(right);
114
- if (!parsedLeft || !parsedRight) {
115
- return left.localeCompare(right);
116
- }
117
-
118
- for (const key of ["major", "minor", "patch"] as const) {
119
- const diff = parsedLeft[key] - parsedRight[key];
120
- if (diff !== 0) {
121
- return diff;
122
- }
123
- }
124
-
125
- if (parsedLeft.prerelease === parsedRight.prerelease) {
126
- return 0;
127
- }
128
- if (parsedLeft.prerelease === null) {
129
- return 1;
130
- }
131
- if (parsedRight.prerelease === null) {
132
- return -1;
133
- }
134
- return parsedLeft.prerelease.localeCompare(parsedRight.prerelease);
135
- }
136
-
137
- function selectTargetVersion(versions: string[]): string {
138
- const counts = new Map<string, number>();
139
- for (const version of versions) {
140
- counts.set(version, (counts.get(version) ?? 0) + 1);
141
- }
142
-
143
- const byCountThenVersion = [...counts.entries()].sort(
144
- ([leftVersion, leftCount], [rightVersion, rightCount]) =>
145
- rightCount - leftCount || compareVersions(rightVersion, leftVersion),
146
- );
147
-
148
- return byCountThenVersion[0]?.[0] ?? versions[0] ?? "latest";
149
- }
150
-
151
- function formatVersion(version: string, targetVersion: string): string {
152
- return version === targetVersion ? version : `${version} (out of date)`;
153
- }
154
-
155
92
  function formatSkillVersions(
156
93
  versions: string[],
157
- targetVersion: string,
158
94
  ): string {
159
95
  if (versions.length === 0) {
160
96
  return "not installed";
161
97
  }
162
98
 
163
- return versions
164
- .map((version) => formatVersion(version, targetVersion))
165
- .join(", ");
166
- }
167
-
168
- function formatUpdateInstructions(components: {
169
- cliVersion: string;
170
- localPackageVersion: string | null;
171
- skillVersions: string[];
172
- targetVersion: string;
173
- }): string[] {
174
- const instructions: string[] = [];
175
-
176
- if (components.cliVersion !== components.targetVersion) {
177
- instructions.push(
178
- ` global CLI: curl -fsSL https://libretto.sh/install.sh | LIBRETTO_VERSION=${components.targetVersion} bash`,
179
- );
180
- }
181
-
182
- if (
183
- components.localPackageVersion &&
184
- components.localPackageVersion !== components.targetVersion
185
- ) {
186
- instructions.push(
187
- ` local package: npm install libretto@${components.targetVersion}`,
188
- );
189
- }
190
-
191
- if (
192
- components.skillVersions.length > 0 &&
193
- components.skillVersions.some(
194
- (skillVersion) => skillVersion !== components.targetVersion,
195
- )
196
- ) {
197
- instructions.push(" agent skill: libretto setup");
198
- }
199
-
200
- return instructions;
99
+ return versions.join(", ");
201
100
  }
202
101
 
203
102
  function formatVersionWarning(components: {
@@ -205,34 +104,16 @@ function formatVersionWarning(components: {
205
104
  localPackageVersion: string | null;
206
105
  skillVersions: string[];
207
106
  }): string {
208
- const targetVersion = selectTargetVersion([
209
- components.cliVersion,
210
- ...(components.localPackageVersion ? [components.localPackageVersion] : []),
211
- ...components.skillVersions,
212
- ]);
213
107
  const skillLabel =
214
108
  components.skillVersions.length > 1 ? "agent skills" : "agent skill";
215
- const updateInstructions = formatUpdateInstructions({
216
- ...components,
217
- targetVersion,
218
- });
219
109
 
220
110
  return [
221
- "WARNING: Libretto version mismatch detected.",
222
- "",
223
- ` global CLI: ${formatVersion(components.cliVersion, targetVersion)}`,
111
+ "WARNING: Libretto skill version does not match the local package.",
224
112
  ` local package: ${
225
- components.localPackageVersion
226
- ? formatVersion(components.localPackageVersion, targetVersion)
227
- : "not installed"
113
+ components.localPackageVersion ?? `${components.cliVersion} (current command)`
228
114
  }`,
229
- ` ${skillLabel}: ${formatSkillVersions(
230
- components.skillVersions,
231
- targetVersion,
232
- )}`,
233
- "",
234
- "How to update:",
235
- ...updateInstructions,
115
+ ` ${skillLabel}: ${formatSkillVersions(components.skillVersions)}`,
116
+ "Fix: run libretto setup",
236
117
  ].join("\n");
237
118
  }
238
119
 
@@ -240,14 +121,12 @@ export function warnIfLibrettoVersionsDiffer(): void {
240
121
  try {
241
122
  const cliVersion = readCurrentCliVersion();
242
123
  const localPackageVersion = readLocalPackageVersion();
124
+ const packageVersion = localPackageVersion ?? cliVersion;
243
125
  const skillVersions = readInstalledSkillVersions();
244
- const observedVersions = new Set([
245
- cliVersion,
246
- ...(localPackageVersion ? [localPackageVersion] : []),
247
- ...skillVersions,
248
- ]);
249
-
250
- if (observedVersions.size <= 1) {
126
+ if (
127
+ skillVersions.length === 0 ||
128
+ skillVersions.every((skillVersion) => skillVersion === packageVersion)
129
+ ) {
251
130
  return;
252
131
  }
253
132
 
package/src/index.ts CHANGED
@@ -100,11 +100,13 @@ export {
100
100
  LibrettoWorkflow,
101
101
  LibrettoWorkflowInputError,
102
102
  LIBRETTO_WORKFLOW_BRAND,
103
+ validateWorkflowInput,
103
104
  workflow,
104
105
  type ExportedLibrettoWorkflow,
105
106
  type LibrettoWorkflowContext,
106
107
  type LibrettoWorkflowHandler,
107
108
  type LibrettoWorkflowSchemas,
109
+ type WorkflowInputValidator,
108
110
  } from "./shared/workflow/workflow.js";
109
111
  const isDirectExecution = (): boolean => {
110
112
  const entryArg = process.argv[1];
@@ -49,6 +49,32 @@ function formatZodErrorMessage(
49
49
  ].join("\n");
50
50
  }
51
51
 
52
+ function parseWorkflowInput<InputSchema extends z.ZodType>(
53
+ workflowName: string,
54
+ inputSchema: InputSchema | undefined,
55
+ input: unknown,
56
+ ): z.infer<InputSchema> {
57
+ if (!inputSchema) return input as z.infer<InputSchema>;
58
+
59
+ const result = inputSchema.safeParse(input);
60
+ if (!result.success) {
61
+ throw new LibrettoWorkflowInputError(workflowName, result.error);
62
+ }
63
+ return result.data;
64
+ }
65
+
66
+ export type WorkflowInputValidator = {
67
+ readonly name: string;
68
+ readonly inputSchema?: z.ZodType;
69
+ };
70
+
71
+ export function validateWorkflowInput(
72
+ workflow: WorkflowInputValidator,
73
+ input: unknown,
74
+ ): void {
75
+ parseWorkflowInput(workflow.name, workflow.inputSchema, input);
76
+ }
77
+
52
78
  export class LibrettoWorkflow<
53
79
  InputSchema extends z.ZodType = z.ZodType<unknown>,
54
80
  OutputSchema extends z.ZodType = z.ZodType<unknown>,
@@ -86,16 +112,7 @@ export class LibrettoWorkflow<
86
112
  ctx: LibrettoWorkflowContext,
87
113
  input: unknown,
88
114
  ): Promise<z.infer<OutputSchema>> {
89
- let parsed: z.infer<InputSchema>;
90
- if (this.inputSchema) {
91
- const result = this.inputSchema.safeParse(input);
92
- if (!result.success) {
93
- throw new LibrettoWorkflowInputError(this.name, result.error);
94
- }
95
- parsed = result.data;
96
- } else {
97
- parsed = input as z.infer<InputSchema>;
98
- }
115
+ const parsed = parseWorkflowInput(this.name, this.inputSchema, input);
99
116
  return this.handler(ctx, parsed);
100
117
  }
101
118
  }