@prompty/core 0.1.2 → 0.1.4

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/README.md CHANGED
@@ -1,2 +1,2 @@
1
- # WiP
2
- Test change
1
+ # promptyjs
2
+ A prompty js runtime.
package/dist/index.d.mts CHANGED
@@ -3,27 +3,10 @@ declare class PropertySettings {
3
3
  default: any;
4
4
  description: string;
5
5
  }
6
- interface OpenAIModel {
7
- type: "openai";
8
- name: string;
9
- organization?: string;
10
- api_key: string;
11
- base_url?: string;
12
- }
13
- interface AzureOpenAIModel {
14
- type: "azure_openai";
15
- api_version: string;
16
- azure_deployment: string;
17
- azure_endpoint: string;
18
- api_key?: string;
19
- }
20
- interface MaasModel {
21
- type: "serverless";
22
- endpoint: string;
23
- model: string;
24
- api_key?: string;
6
+ declare class ModelConfiguration {
7
+ type: string;
8
+ [key: string]: any;
25
9
  }
26
- type ModelConfiguration = OpenAIModel | AzureOpenAIModel | MaasModel;
27
10
  declare class ModelSettings {
28
11
  api: string;
29
12
  configuration: ModelConfiguration;
@@ -34,6 +17,12 @@ declare class TemplateSettings {
34
17
  type: string;
35
18
  parser: string;
36
19
  }
20
+ interface ExecutionOptions {
21
+ configuration?: any;
22
+ parameters?: any;
23
+ raw?: boolean;
24
+ connection?: any;
25
+ }
37
26
  declare class Prompty {
38
27
  name: string;
39
28
  description: string;
@@ -41,7 +30,7 @@ declare class Prompty {
41
30
  tags: string[];
42
31
  version: string;
43
32
  base: string;
44
- basePrompty: Prompty;
33
+ basePrompty?: Prompty;
45
34
  model: ModelSettings;
46
35
  sample: any;
47
36
  input: {
@@ -54,14 +43,17 @@ declare class Prompty {
54
43
  file: string;
55
44
  content: string;
56
45
  constructor(content: string);
46
+ private static _findGlobalConfig;
47
+ static load(filePath: string, configuration?: string): Promise<any>;
57
48
  static prepare(prompt: Prompty, inputs?: any): Promise<any>;
58
- static load(filePath: string): Promise<any>;
49
+ static prepareSync(prompt: Prompty, inputs?: any): any;
50
+ static run(prompt: Prompty, inputs?: any, options?: ExecutionOptions): Promise<any>;
59
51
  static export(prompt: Prompty): string;
60
52
  }
61
53
 
62
54
  declare abstract class Invoker {
63
55
  prompty: Prompty;
64
- constructor(prompty?: Prompty);
56
+ constructor(prompty: Prompty);
65
57
  abstract invoke(data: any): Promise<any>;
66
58
  abstract invokeSync(data: any): any;
67
59
  call(data: any): Promise<any>;
@@ -74,11 +66,20 @@ declare class InvokerFactory {
74
66
  private _invokers;
75
67
  register(type: InvokerType, name: string, invokerClass: InvokerConstructor): void;
76
68
  create(type: InvokerType, name: string, prompty: Prompty): Invoker;
69
+ private static getName;
77
70
  static getInstance(): InvokerFactory;
78
- call(type: InvokerType, name: string, prompty: Prompty, data: any): Promise<any>;
79
- callSync(type: InvokerType, name: string, prompty: Prompty, data: any): any;
71
+ call(type: InvokerType, prompty: Prompty, data: any, alt?: any): Promise<any>;
72
+ callRenderer(prompty: Prompty, data: any, alt?: any): Promise<any>;
73
+ callParser(prompty: Prompty, data: any, alt?: any): Promise<any>;
74
+ callExecutor(prompty: Prompty, data: any, alt?: any): Promise<any>;
75
+ callProcessor(prompty: Prompty, data: any, alt?: any): Promise<any>;
76
+ callSync(type: InvokerType, prompty: Prompty, data: any, alt?: any): any;
77
+ callRendererSync(prompty: Prompty, data: any, alt?: any): any;
78
+ callParserSync(prompty: Prompty, data: any, alt?: any): any;
79
+ callExecutorSync(prompty: Prompty, data: any, alt?: any): any;
80
+ callProcessorSync(prompty: Prompty, data: any, alt?: any): any;
80
81
  toDict(): Record<string, Record<string, string>>;
81
82
  toJson(): string;
82
83
  }
83
84
 
84
- export { Invoker, InvokerFactory, type MaasModel, type ModelConfiguration, Prompty };
85
+ export { Invoker, InvokerFactory, ModelConfiguration, Prompty };
package/dist/index.d.ts CHANGED
@@ -3,27 +3,10 @@ declare class PropertySettings {
3
3
  default: any;
4
4
  description: string;
5
5
  }
6
- interface OpenAIModel {
7
- type: "openai";
8
- name: string;
9
- organization?: string;
10
- api_key: string;
11
- base_url?: string;
12
- }
13
- interface AzureOpenAIModel {
14
- type: "azure_openai";
15
- api_version: string;
16
- azure_deployment: string;
17
- azure_endpoint: string;
18
- api_key?: string;
19
- }
20
- interface MaasModel {
21
- type: "serverless";
22
- endpoint: string;
23
- model: string;
24
- api_key?: string;
6
+ declare class ModelConfiguration {
7
+ type: string;
8
+ [key: string]: any;
25
9
  }
26
- type ModelConfiguration = OpenAIModel | AzureOpenAIModel | MaasModel;
27
10
  declare class ModelSettings {
28
11
  api: string;
29
12
  configuration: ModelConfiguration;
@@ -34,6 +17,12 @@ declare class TemplateSettings {
34
17
  type: string;
35
18
  parser: string;
36
19
  }
20
+ interface ExecutionOptions {
21
+ configuration?: any;
22
+ parameters?: any;
23
+ raw?: boolean;
24
+ connection?: any;
25
+ }
37
26
  declare class Prompty {
38
27
  name: string;
39
28
  description: string;
@@ -41,7 +30,7 @@ declare class Prompty {
41
30
  tags: string[];
42
31
  version: string;
43
32
  base: string;
44
- basePrompty: Prompty;
33
+ basePrompty?: Prompty;
45
34
  model: ModelSettings;
46
35
  sample: any;
47
36
  input: {
@@ -54,14 +43,17 @@ declare class Prompty {
54
43
  file: string;
55
44
  content: string;
56
45
  constructor(content: string);
46
+ private static _findGlobalConfig;
47
+ static load(filePath: string, configuration?: string): Promise<any>;
57
48
  static prepare(prompt: Prompty, inputs?: any): Promise<any>;
58
- static load(filePath: string): Promise<any>;
49
+ static prepareSync(prompt: Prompty, inputs?: any): any;
50
+ static run(prompt: Prompty, inputs?: any, options?: ExecutionOptions): Promise<any>;
59
51
  static export(prompt: Prompty): string;
60
52
  }
61
53
 
62
54
  declare abstract class Invoker {
63
55
  prompty: Prompty;
64
- constructor(prompty?: Prompty);
56
+ constructor(prompty: Prompty);
65
57
  abstract invoke(data: any): Promise<any>;
66
58
  abstract invokeSync(data: any): any;
67
59
  call(data: any): Promise<any>;
@@ -74,11 +66,20 @@ declare class InvokerFactory {
74
66
  private _invokers;
75
67
  register(type: InvokerType, name: string, invokerClass: InvokerConstructor): void;
76
68
  create(type: InvokerType, name: string, prompty: Prompty): Invoker;
69
+ private static getName;
77
70
  static getInstance(): InvokerFactory;
78
- call(type: InvokerType, name: string, prompty: Prompty, data: any): Promise<any>;
79
- callSync(type: InvokerType, name: string, prompty: Prompty, data: any): any;
71
+ call(type: InvokerType, prompty: Prompty, data: any, alt?: any): Promise<any>;
72
+ callRenderer(prompty: Prompty, data: any, alt?: any): Promise<any>;
73
+ callParser(prompty: Prompty, data: any, alt?: any): Promise<any>;
74
+ callExecutor(prompty: Prompty, data: any, alt?: any): Promise<any>;
75
+ callProcessor(prompty: Prompty, data: any, alt?: any): Promise<any>;
76
+ callSync(type: InvokerType, prompty: Prompty, data: any, alt?: any): any;
77
+ callRendererSync(prompty: Prompty, data: any, alt?: any): any;
78
+ callParserSync(prompty: Prompty, data: any, alt?: any): any;
79
+ callExecutorSync(prompty: Prompty, data: any, alt?: any): any;
80
+ callProcessorSync(prompty: Prompty, data: any, alt?: any): any;
80
81
  toDict(): Record<string, Record<string, string>>;
81
82
  toJson(): string;
82
83
  }
83
84
 
84
- export { Invoker, InvokerFactory, type MaasModel, type ModelConfiguration, Prompty };
85
+ export { Invoker, InvokerFactory, ModelConfiguration, Prompty };
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -27,20 +28,26 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
29
 
29
30
  // src/index.ts
30
- var src_exports = {};
31
- __export(src_exports, {
31
+ var index_exports = {};
32
+ __export(index_exports, {
32
33
  Invoker: () => Invoker,
33
34
  InvokerFactory: () => InvokerFactory,
35
+ ModelConfiguration: () => ModelConfiguration,
34
36
  Prompty: () => Prompty
35
37
  });
36
- module.exports = __toCommonJS(src_exports);
38
+ module.exports = __toCommonJS(index_exports);
37
39
 
38
40
  // src/core.ts
39
41
  var import_gray_matter = __toESM(require("gray-matter"));
40
42
 
41
43
  // src/utils.ts
42
44
  var fs = __toESM(require("fs/promises"));
43
- var _utils = class _utils {
45
+ var utils = class _utils {
46
+ static async importModuleSync(moduleName) {
47
+ const importedModule = import(moduleName);
48
+ return importedModule;
49
+ }
50
+ static isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
44
51
  static async readFileSafe(filePath, encoding = "utf-8") {
45
52
  if (_utils.isNode) {
46
53
  const data = await fs.readFile(filePath, encoding);
@@ -64,11 +71,10 @@ var _utils = class _utils {
64
71
  return newDict;
65
72
  }
66
73
  };
67
- _utils.isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
68
- var utils = _utils;
69
74
 
70
75
  // src/invokerFactory.ts
71
76
  var Invoker = class {
77
+ prompty;
72
78
  constructor(prompty) {
73
79
  this.prompty = prompty;
74
80
  }
@@ -88,14 +94,13 @@ var NoOpInvoker = class extends Invoker {
88
94
  }
89
95
  };
90
96
  var InvokerFactory = class _InvokerFactory {
91
- constructor() {
92
- this._invokers = {
93
- renderer: { ["NOOP"]: NoOpInvoker },
94
- parser: { ["NOOP"]: NoOpInvoker },
95
- executor: { ["NOOP"]: NoOpInvoker },
96
- processor: { ["NOOP"]: NoOpInvoker }
97
- };
98
- }
97
+ static _instance;
98
+ _invokers = {
99
+ renderer: { ["NOOP"]: NoOpInvoker },
100
+ parser: { ["NOOP"]: NoOpInvoker },
101
+ executor: { ["NOOP"]: NoOpInvoker },
102
+ processor: { ["NOOP"]: NoOpInvoker }
103
+ };
99
104
  register(type, name, invokerClass) {
100
105
  if (!this._invokers[type]) {
101
106
  throw new Error(`Invalid invoker type: ${type}`);
@@ -109,17 +114,69 @@ var InvokerFactory = class _InvokerFactory {
109
114
  }
110
115
  return new invokerClass(prompty);
111
116
  }
117
+ static getName(type, prompty) {
118
+ switch (type) {
119
+ case "renderer":
120
+ return prompty.template.type;
121
+ case "parser":
122
+ return `${prompty.template.parser}.${prompty.model.api}`;
123
+ case "executor":
124
+ return prompty.model.configuration.type;
125
+ case "processor":
126
+ return prompty.model.configuration.type;
127
+ default:
128
+ throw new Error(`Invalid invoker type: ${type}`);
129
+ }
130
+ }
112
131
  static getInstance() {
113
132
  if (!this._instance) {
114
133
  this._instance = new _InvokerFactory();
115
134
  }
116
135
  return this._instance;
117
136
  }
118
- async call(type, name, prompty, data) {
119
- return await this.create(type, name, prompty).call(data);
137
+ async call(type, prompty, data, alt) {
138
+ const name = _InvokerFactory.getName(type, prompty);
139
+ if (name.startsWith("NOOP") && alt) {
140
+ return alt;
141
+ } else if (name.startsWith("NOOP")) {
142
+ return data;
143
+ }
144
+ const invoker = this.create(type, name, prompty);
145
+ return await invoker.call(data);
146
+ }
147
+ async callRenderer(prompty, data, alt) {
148
+ return await this.call("renderer", prompty, data, alt);
149
+ }
150
+ async callParser(prompty, data, alt) {
151
+ return await this.call("parser", prompty, data, alt);
152
+ }
153
+ async callExecutor(prompty, data, alt) {
154
+ return await this.call("executor", prompty, data, alt);
120
155
  }
121
- callSync(type, name, prompty, data) {
122
- return this.create(type, name, prompty).callSync(data);
156
+ async callProcessor(prompty, data, alt) {
157
+ return await this.call("processor", prompty, data, alt);
158
+ }
159
+ callSync(type, prompty, data, alt) {
160
+ const name = _InvokerFactory.getName(type, prompty);
161
+ if (name.startsWith("NOOP") && alt) {
162
+ return alt;
163
+ } else if (name.startsWith("NOOP")) {
164
+ return data;
165
+ }
166
+ const invoker = this.create(type, name, prompty);
167
+ return invoker.callSync(data);
168
+ }
169
+ callRendererSync(prompty, data, alt) {
170
+ return this.callSync("renderer", prompty, data, alt);
171
+ }
172
+ callParserSync(prompty, data, alt) {
173
+ return this.callSync("parser", prompty, data, alt);
174
+ }
175
+ callExecutorSync(prompty, data, alt) {
176
+ return this.callSync("executor", prompty, data, alt);
177
+ }
178
+ callProcessorSync(prompty, data, alt) {
179
+ return this.callSync("processor", prompty, data, alt);
123
180
  }
124
181
  toDict() {
125
182
  const dict = {};
@@ -138,6 +195,7 @@ var InvokerFactory = class _InvokerFactory {
138
195
  // src/parsers.ts
139
196
  var path = __toESM(require("path"));
140
197
  var PromptyChatParser = class extends Invoker {
198
+ roles;
141
199
  constructor(prompty) {
142
200
  super(prompty);
143
201
  this.roles = ["assistant", "function", "system", "user"];
@@ -190,7 +248,7 @@ var PromptyChatParser = class extends Invoker {
190
248
  async invoke(data) {
191
249
  let messages = [];
192
250
  const separator = new RegExp(`\\s*#?\\s*(${this.roles.join("|")})\\s*:\\s*\\n`, "im");
193
- let chunks = data.split(separator).filter((chunk) => chunk.trim());
251
+ let chunks = data.replaceAll("\r\n", "\n").split(separator).filter((chunk) => chunk.trim());
194
252
  if (!this.roles.includes(chunks[0].trim().toLowerCase())) {
195
253
  chunks.unshift("system");
196
254
  }
@@ -204,7 +262,11 @@ var PromptyChatParser = class extends Invoker {
204
262
  const role = chunks[i].trim().toLowerCase();
205
263
  const content = chunks[i + 1].trim();
206
264
  const parsedContent = await this.parseContent(content, role);
207
- messages.push({ role, content: parsedContent });
265
+ if (parsedContent.length == 1 && parsedContent[0].type == "text") {
266
+ messages.push({ role, content: parsedContent[0].text });
267
+ } else {
268
+ messages.push({ role, content: parsedContent });
269
+ }
208
270
  }
209
271
  return messages;
210
272
  }
@@ -219,10 +281,8 @@ factory.register("parser", "prompty.completion", NoOpInvoker);
219
281
  var nunjucks = __toESM(require("nunjucks"));
220
282
  var mustache = __toESM(require("mustache"));
221
283
  var NunjucksRenderer = class extends Invoker {
222
- constructor() {
223
- super(...arguments);
224
- this.templates = {};
225
- }
284
+ templates = {};
285
+ //private name: string;
226
286
  async invoke(data) {
227
287
  return Promise.resolve(this.invokeSync(data));
228
288
  }
@@ -231,10 +291,8 @@ var NunjucksRenderer = class extends Invoker {
231
291
  }
232
292
  };
233
293
  var MustacheRenderer = class extends Invoker {
234
- constructor() {
235
- super(...arguments);
236
- this.templates = {};
237
- }
294
+ templates = {};
295
+ //private name: string;
238
296
  async invoke(data) {
239
297
  return Promise.resolve(this.invokeSync(data));
240
298
  }
@@ -248,85 +306,114 @@ factory2.register("renderer", "mustache", MustacheRenderer);
248
306
 
249
307
  // src/core.ts
250
308
  var yaml = __toESM(require("js-yaml"));
309
+ var import_path = __toESM(require("path"));
310
+ var import_glob = require("glob");
311
+ var ModelConfiguration = class {
312
+ type = "unknown";
313
+ };
251
314
  var ModelSettings = class {
252
- constructor() {
253
- this.api = "chat";
254
- this.configuration = {};
255
- this.parameters = {};
256
- this.response = {};
257
- }
315
+ api = "chat";
316
+ configuration = { type: "unknown" };
317
+ parameters = {};
318
+ response = {};
258
319
  };
259
320
  var TemplateSettings = class {
260
- constructor() {
261
- this.type = "jinja2";
262
- this.parser = "prompty";
263
- }
321
+ type = "jinja2";
322
+ parser = "prompty";
264
323
  };
265
324
  var Prompty = class _Prompty {
325
+ // metadata
326
+ name = "";
327
+ description = "";
328
+ authors = [];
329
+ tags = [];
330
+ version = "";
331
+ base = "";
332
+ basePrompty;
333
+ // model
334
+ model = new ModelSettings();
335
+ // sample
336
+ sample = {};
337
+ // input / output
338
+ input = {};
339
+ output = {};
340
+ // template
341
+ template = new TemplateSettings();
342
+ // misc
343
+ file = "";
344
+ content = "";
266
345
  constructor(content) {
267
- // metadata
268
- this.name = "";
269
- this.description = "";
270
- this.authors = [];
271
- this.tags = [];
272
- this.version = "";
273
- this.base = "";
274
- this.basePrompty = null;
275
- // model
276
- this.model = new ModelSettings();
277
- // sample
278
- this.sample = {};
279
- // input / output
280
- this.input = {};
281
- this.output = {};
282
- // template
283
- this.template = new TemplateSettings();
284
- // misc
285
- this.file = "";
286
- this.content = "";
287
- var _a, _b, _c, _d, _e, _f;
288
- const items = (0, import_gray_matter.default)(content);
346
+ const items = (0, import_gray_matter.default)(content, {
347
+ engines: {
348
+ yaml: {
349
+ parse: (input) => yaml.load(input)
350
+ },
351
+ js: {
352
+ parse: (input) => {
353
+ console.log("JS execution disabled");
354
+ return {};
355
+ }
356
+ }
357
+ }
358
+ });
289
359
  this.name = items.data.name || "";
290
360
  this.description = items.data.description || "";
291
361
  this.authors = items.data.authors || [];
292
362
  this.tags = items.data.tags || [];
293
363
  this.version = items.data.version || "";
294
364
  this.base = items.data.base || "";
295
- this.model.api = ((_a = items.data.model) == null ? void 0 : _a.api) || "chat";
296
- this.model.configuration = ((_b = items.data.model) == null ? void 0 : _b.configuration) || {};
297
- this.model.parameters = ((_c = items.data.model) == null ? void 0 : _c.parameters) || {};
298
- this.model.response = ((_d = items.data.model) == null ? void 0 : _d.response) || {};
365
+ this.model.api = items.data.model?.api || "chat";
366
+ this.model.configuration = items.data.model?.configuration || {};
367
+ this.model.parameters = items.data.model?.parameters || {};
368
+ this.model.response = items.data.model?.response || {};
299
369
  this.sample = items.data.sample || {};
300
370
  this.input = items.data.input || {};
301
371
  this.output = items.data.output || {};
302
372
  if (items.data.template && typeof items.data.template === "string") {
303
373
  this.template.type = items.data.template || this.template.type;
304
374
  } else {
305
- this.template.type = ((_e = items.data.template) == null ? void 0 : _e.type) || this.template.type;
306
- this.template.parser = ((_f = items.data.template) == null ? void 0 : _f.parser) || this.template.parser;
375
+ this.template.type = items.data.template?.type || this.template.type;
376
+ this.template.parser = items.data.template?.parser || this.template.parser;
307
377
  }
308
378
  this.file = content;
309
379
  this.content = items.content;
310
380
  }
381
+ static async _findGlobalConfig(promptyPath) {
382
+ const configs = await (0, import_glob.glob)("**/prompty.json", {
383
+ cwd: process.cwd()
384
+ });
385
+ const filtered = configs.map((c) => import_path.default.resolve(c)).filter((config) => config.length <= promptyPath.length).sort((a, b) => a.length - b.length);
386
+ if (filtered.length > 0) {
387
+ return filtered[filtered.length - 1];
388
+ } else {
389
+ return void 0;
390
+ }
391
+ }
392
+ static async load(filePath, configuration = "default") {
393
+ filePath = import_path.default.resolve(filePath);
394
+ const p = new _Prompty(await utils.readFileSafe(filePath));
395
+ const c = await _Prompty._findGlobalConfig(filePath);
396
+ p.file = filePath;
397
+ return p;
398
+ }
311
399
  static async prepare(prompt, inputs = {}) {
312
400
  const invoker = InvokerFactory.getInstance();
313
401
  inputs = utils.paramHoisting(inputs, prompt.sample);
314
- let render2;
315
- if (prompt.template.type === "NOOP") {
316
- render2 = prompt.content;
317
- } else {
318
- render2 = await invoker.call("renderer", prompt.template.type, prompt, inputs);
319
- }
320
- let result;
321
- if (prompt.template.parser === "NOOP") {
322
- result = render2;
323
- } else {
324
- result = await invoker.call("parser", `${prompt.template.parser}.${prompt.model.api}`, prompt, render2);
325
- }
402
+ const render2 = await invoker.callRenderer(prompt, inputs, prompt.content);
403
+ const result = await invoker.callParser(prompt, render2);
404
+ return result;
405
+ }
406
+ static prepareSync(prompt, inputs = {}) {
407
+ const invoker = InvokerFactory.getInstance();
408
+ inputs = utils.paramHoisting(inputs, prompt.sample);
409
+ const render2 = invoker.callRendererSync(prompt, inputs, prompt.content);
410
+ const result = invoker.callParserSync(prompt, render2);
326
411
  return result;
327
412
  }
328
- static async load(filePath) {
329
- return new _Prompty(await utils.readFileSafe(filePath));
413
+ static async run(prompt, inputs = {}, options = {}) {
414
+ const invoker = InvokerFactory.getInstance();
415
+ inputs = utils.paramHoisting(inputs, prompt.sample);
416
+ return {};
330
417
  }
331
418
  static export(prompt) {
332
419
  const front_matter = {
@@ -350,5 +437,6 @@ var Prompty = class _Prompty {
350
437
  0 && (module.exports = {
351
438
  Invoker,
352
439
  InvokerFactory,
440
+ ModelConfiguration,
353
441
  Prompty
354
442
  });
package/dist/index.mjs CHANGED
@@ -3,7 +3,12 @@ import matter from "gray-matter";
3
3
 
4
4
  // src/utils.ts
5
5
  import * as fs from "fs/promises";
6
- var _utils = class _utils {
6
+ var utils = class _utils {
7
+ static async importModuleSync(moduleName) {
8
+ const importedModule = import(moduleName);
9
+ return importedModule;
10
+ }
11
+ static isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
7
12
  static async readFileSafe(filePath, encoding = "utf-8") {
8
13
  if (_utils.isNode) {
9
14
  const data = await fs.readFile(filePath, encoding);
@@ -27,11 +32,10 @@ var _utils = class _utils {
27
32
  return newDict;
28
33
  }
29
34
  };
30
- _utils.isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
31
- var utils = _utils;
32
35
 
33
36
  // src/invokerFactory.ts
34
37
  var Invoker = class {
38
+ prompty;
35
39
  constructor(prompty) {
36
40
  this.prompty = prompty;
37
41
  }
@@ -51,14 +55,13 @@ var NoOpInvoker = class extends Invoker {
51
55
  }
52
56
  };
53
57
  var InvokerFactory = class _InvokerFactory {
54
- constructor() {
55
- this._invokers = {
56
- renderer: { ["NOOP"]: NoOpInvoker },
57
- parser: { ["NOOP"]: NoOpInvoker },
58
- executor: { ["NOOP"]: NoOpInvoker },
59
- processor: { ["NOOP"]: NoOpInvoker }
60
- };
61
- }
58
+ static _instance;
59
+ _invokers = {
60
+ renderer: { ["NOOP"]: NoOpInvoker },
61
+ parser: { ["NOOP"]: NoOpInvoker },
62
+ executor: { ["NOOP"]: NoOpInvoker },
63
+ processor: { ["NOOP"]: NoOpInvoker }
64
+ };
62
65
  register(type, name, invokerClass) {
63
66
  if (!this._invokers[type]) {
64
67
  throw new Error(`Invalid invoker type: ${type}`);
@@ -72,17 +75,69 @@ var InvokerFactory = class _InvokerFactory {
72
75
  }
73
76
  return new invokerClass(prompty);
74
77
  }
78
+ static getName(type, prompty) {
79
+ switch (type) {
80
+ case "renderer":
81
+ return prompty.template.type;
82
+ case "parser":
83
+ return `${prompty.template.parser}.${prompty.model.api}`;
84
+ case "executor":
85
+ return prompty.model.configuration.type;
86
+ case "processor":
87
+ return prompty.model.configuration.type;
88
+ default:
89
+ throw new Error(`Invalid invoker type: ${type}`);
90
+ }
91
+ }
75
92
  static getInstance() {
76
93
  if (!this._instance) {
77
94
  this._instance = new _InvokerFactory();
78
95
  }
79
96
  return this._instance;
80
97
  }
81
- async call(type, name, prompty, data) {
82
- return await this.create(type, name, prompty).call(data);
98
+ async call(type, prompty, data, alt) {
99
+ const name = _InvokerFactory.getName(type, prompty);
100
+ if (name.startsWith("NOOP") && alt) {
101
+ return alt;
102
+ } else if (name.startsWith("NOOP")) {
103
+ return data;
104
+ }
105
+ const invoker = this.create(type, name, prompty);
106
+ return await invoker.call(data);
107
+ }
108
+ async callRenderer(prompty, data, alt) {
109
+ return await this.call("renderer", prompty, data, alt);
110
+ }
111
+ async callParser(prompty, data, alt) {
112
+ return await this.call("parser", prompty, data, alt);
113
+ }
114
+ async callExecutor(prompty, data, alt) {
115
+ return await this.call("executor", prompty, data, alt);
83
116
  }
84
- callSync(type, name, prompty, data) {
85
- return this.create(type, name, prompty).callSync(data);
117
+ async callProcessor(prompty, data, alt) {
118
+ return await this.call("processor", prompty, data, alt);
119
+ }
120
+ callSync(type, prompty, data, alt) {
121
+ const name = _InvokerFactory.getName(type, prompty);
122
+ if (name.startsWith("NOOP") && alt) {
123
+ return alt;
124
+ } else if (name.startsWith("NOOP")) {
125
+ return data;
126
+ }
127
+ const invoker = this.create(type, name, prompty);
128
+ return invoker.callSync(data);
129
+ }
130
+ callRendererSync(prompty, data, alt) {
131
+ return this.callSync("renderer", prompty, data, alt);
132
+ }
133
+ callParserSync(prompty, data, alt) {
134
+ return this.callSync("parser", prompty, data, alt);
135
+ }
136
+ callExecutorSync(prompty, data, alt) {
137
+ return this.callSync("executor", prompty, data, alt);
138
+ }
139
+ callProcessorSync(prompty, data, alt) {
140
+ return this.callSync("processor", prompty, data, alt);
86
141
  }
87
142
  toDict() {
88
143
  const dict = {};
@@ -101,6 +156,7 @@ var InvokerFactory = class _InvokerFactory {
101
156
  // src/parsers.ts
102
157
  import * as path from "path";
103
158
  var PromptyChatParser = class extends Invoker {
159
+ roles;
104
160
  constructor(prompty) {
105
161
  super(prompty);
106
162
  this.roles = ["assistant", "function", "system", "user"];
@@ -153,7 +209,7 @@ var PromptyChatParser = class extends Invoker {
153
209
  async invoke(data) {
154
210
  let messages = [];
155
211
  const separator = new RegExp(`\\s*#?\\s*(${this.roles.join("|")})\\s*:\\s*\\n`, "im");
156
- let chunks = data.split(separator).filter((chunk) => chunk.trim());
212
+ let chunks = data.replaceAll("\r\n", "\n").split(separator).filter((chunk) => chunk.trim());
157
213
  if (!this.roles.includes(chunks[0].trim().toLowerCase())) {
158
214
  chunks.unshift("system");
159
215
  }
@@ -167,7 +223,11 @@ var PromptyChatParser = class extends Invoker {
167
223
  const role = chunks[i].trim().toLowerCase();
168
224
  const content = chunks[i + 1].trim();
169
225
  const parsedContent = await this.parseContent(content, role);
170
- messages.push({ role, content: parsedContent });
226
+ if (parsedContent.length == 1 && parsedContent[0].type == "text") {
227
+ messages.push({ role, content: parsedContent[0].text });
228
+ } else {
229
+ messages.push({ role, content: parsedContent });
230
+ }
171
231
  }
172
232
  return messages;
173
233
  }
@@ -182,10 +242,8 @@ factory.register("parser", "prompty.completion", NoOpInvoker);
182
242
  import * as nunjucks from "nunjucks";
183
243
  import * as mustache from "mustache";
184
244
  var NunjucksRenderer = class extends Invoker {
185
- constructor() {
186
- super(...arguments);
187
- this.templates = {};
188
- }
245
+ templates = {};
246
+ //private name: string;
189
247
  async invoke(data) {
190
248
  return Promise.resolve(this.invokeSync(data));
191
249
  }
@@ -194,10 +252,8 @@ var NunjucksRenderer = class extends Invoker {
194
252
  }
195
253
  };
196
254
  var MustacheRenderer = class extends Invoker {
197
- constructor() {
198
- super(...arguments);
199
- this.templates = {};
200
- }
255
+ templates = {};
256
+ //private name: string;
201
257
  async invoke(data) {
202
258
  return Promise.resolve(this.invokeSync(data));
203
259
  }
@@ -211,85 +267,114 @@ factory2.register("renderer", "mustache", MustacheRenderer);
211
267
 
212
268
  // src/core.ts
213
269
  import * as yaml from "js-yaml";
270
+ import path2 from "path";
271
+ import { glob } from "glob";
272
+ var ModelConfiguration = class {
273
+ type = "unknown";
274
+ };
214
275
  var ModelSettings = class {
215
- constructor() {
216
- this.api = "chat";
217
- this.configuration = {};
218
- this.parameters = {};
219
- this.response = {};
220
- }
276
+ api = "chat";
277
+ configuration = { type: "unknown" };
278
+ parameters = {};
279
+ response = {};
221
280
  };
222
281
  var TemplateSettings = class {
223
- constructor() {
224
- this.type = "jinja2";
225
- this.parser = "prompty";
226
- }
282
+ type = "jinja2";
283
+ parser = "prompty";
227
284
  };
228
285
  var Prompty = class _Prompty {
286
+ // metadata
287
+ name = "";
288
+ description = "";
289
+ authors = [];
290
+ tags = [];
291
+ version = "";
292
+ base = "";
293
+ basePrompty;
294
+ // model
295
+ model = new ModelSettings();
296
+ // sample
297
+ sample = {};
298
+ // input / output
299
+ input = {};
300
+ output = {};
301
+ // template
302
+ template = new TemplateSettings();
303
+ // misc
304
+ file = "";
305
+ content = "";
229
306
  constructor(content) {
230
- // metadata
231
- this.name = "";
232
- this.description = "";
233
- this.authors = [];
234
- this.tags = [];
235
- this.version = "";
236
- this.base = "";
237
- this.basePrompty = null;
238
- // model
239
- this.model = new ModelSettings();
240
- // sample
241
- this.sample = {};
242
- // input / output
243
- this.input = {};
244
- this.output = {};
245
- // template
246
- this.template = new TemplateSettings();
247
- // misc
248
- this.file = "";
249
- this.content = "";
250
- var _a, _b, _c, _d, _e, _f;
251
- const items = matter(content);
307
+ const items = matter(content, {
308
+ engines: {
309
+ yaml: {
310
+ parse: (input) => yaml.load(input)
311
+ },
312
+ js: {
313
+ parse: (input) => {
314
+ console.log("JS execution disabled");
315
+ return {};
316
+ }
317
+ }
318
+ }
319
+ });
252
320
  this.name = items.data.name || "";
253
321
  this.description = items.data.description || "";
254
322
  this.authors = items.data.authors || [];
255
323
  this.tags = items.data.tags || [];
256
324
  this.version = items.data.version || "";
257
325
  this.base = items.data.base || "";
258
- this.model.api = ((_a = items.data.model) == null ? void 0 : _a.api) || "chat";
259
- this.model.configuration = ((_b = items.data.model) == null ? void 0 : _b.configuration) || {};
260
- this.model.parameters = ((_c = items.data.model) == null ? void 0 : _c.parameters) || {};
261
- this.model.response = ((_d = items.data.model) == null ? void 0 : _d.response) || {};
326
+ this.model.api = items.data.model?.api || "chat";
327
+ this.model.configuration = items.data.model?.configuration || {};
328
+ this.model.parameters = items.data.model?.parameters || {};
329
+ this.model.response = items.data.model?.response || {};
262
330
  this.sample = items.data.sample || {};
263
331
  this.input = items.data.input || {};
264
332
  this.output = items.data.output || {};
265
333
  if (items.data.template && typeof items.data.template === "string") {
266
334
  this.template.type = items.data.template || this.template.type;
267
335
  } else {
268
- this.template.type = ((_e = items.data.template) == null ? void 0 : _e.type) || this.template.type;
269
- this.template.parser = ((_f = items.data.template) == null ? void 0 : _f.parser) || this.template.parser;
336
+ this.template.type = items.data.template?.type || this.template.type;
337
+ this.template.parser = items.data.template?.parser || this.template.parser;
270
338
  }
271
339
  this.file = content;
272
340
  this.content = items.content;
273
341
  }
342
+ static async _findGlobalConfig(promptyPath) {
343
+ const configs = await glob("**/prompty.json", {
344
+ cwd: process.cwd()
345
+ });
346
+ const filtered = configs.map((c) => path2.resolve(c)).filter((config) => config.length <= promptyPath.length).sort((a, b) => a.length - b.length);
347
+ if (filtered.length > 0) {
348
+ return filtered[filtered.length - 1];
349
+ } else {
350
+ return void 0;
351
+ }
352
+ }
353
+ static async load(filePath, configuration = "default") {
354
+ filePath = path2.resolve(filePath);
355
+ const p = new _Prompty(await utils.readFileSafe(filePath));
356
+ const c = await _Prompty._findGlobalConfig(filePath);
357
+ p.file = filePath;
358
+ return p;
359
+ }
274
360
  static async prepare(prompt, inputs = {}) {
275
361
  const invoker = InvokerFactory.getInstance();
276
362
  inputs = utils.paramHoisting(inputs, prompt.sample);
277
- let render2;
278
- if (prompt.template.type === "NOOP") {
279
- render2 = prompt.content;
280
- } else {
281
- render2 = await invoker.call("renderer", prompt.template.type, prompt, inputs);
282
- }
283
- let result;
284
- if (prompt.template.parser === "NOOP") {
285
- result = render2;
286
- } else {
287
- result = await invoker.call("parser", `${prompt.template.parser}.${prompt.model.api}`, prompt, render2);
288
- }
363
+ const render2 = await invoker.callRenderer(prompt, inputs, prompt.content);
364
+ const result = await invoker.callParser(prompt, render2);
365
+ return result;
366
+ }
367
+ static prepareSync(prompt, inputs = {}) {
368
+ const invoker = InvokerFactory.getInstance();
369
+ inputs = utils.paramHoisting(inputs, prompt.sample);
370
+ const render2 = invoker.callRendererSync(prompt, inputs, prompt.content);
371
+ const result = invoker.callParserSync(prompt, render2);
289
372
  return result;
290
373
  }
291
- static async load(filePath) {
292
- return new _Prompty(await utils.readFileSafe(filePath));
374
+ static async run(prompt, inputs = {}, options = {}) {
375
+ const invoker = InvokerFactory.getInstance();
376
+ inputs = utils.paramHoisting(inputs, prompt.sample);
377
+ return {};
293
378
  }
294
379
  static export(prompt) {
295
380
  const front_matter = {
@@ -312,5 +397,6 @@ var Prompty = class _Prompty {
312
397
  export {
313
398
  Invoker,
314
399
  InvokerFactory,
400
+ ModelConfiguration,
315
401
  Prompty
316
402
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prompty/core",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Prompty core package",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -18,25 +18,34 @@
18
18
  "author": "",
19
19
  "license": "ISC",
20
20
  "devDependencies": {
21
- "@changesets/cli": "^2.27.1",
21
+ "@changesets/cli": "^2.29.6",
22
22
  "@types/base-64": "^1.0.2",
23
- "@types/jest": "^29.5.12",
23
+ "@types/glob": "^8.1.0",
24
+ "@types/jest": "^29.5.14",
24
25
  "@types/js-yaml": "^4.0.9",
26
+ "@types/mustache": "^4.2.5",
25
27
  "@types/node": "^20.11.24",
26
28
  "@types/nunjucks": "^3.2.6",
27
29
  "jest": "^29.7.0",
28
30
  "puppeteer": "^22.6.4",
29
- "ts-jest": "^29.1.2",
30
- "tsup": "^8.0.2",
31
- "typescript": "5.2.2"
31
+ "ts-jest": "^29.2.6",
32
+ "tsup": "^8.4.0",
33
+ "typescript": "^5.7.3"
32
34
  },
33
35
  "dependencies": {
34
- "@types/mustache": "^4.2.5",
35
36
  "base-64": "^1.0.0",
37
+ "glob": "^11.0.1",
36
38
  "gray-matter": "^4.0.3",
37
- "js-yaml": "^4.1.0",
39
+ "js-yaml": "^4.1.1",
38
40
  "mustache": "^4.2.0",
39
41
  "nunjucks": "^3.2.4",
40
42
  "openai": "^4.33.0"
43
+ },
44
+ "jest": {
45
+ "preset": "ts-jest",
46
+ "testEnvironment": "node"
47
+ },
48
+ "repository": {
49
+ "url": "https://github.com/microsoft/prompty"
41
50
  }
42
- }
51
+ }