opencode-irf 0.0.1 → 0.0.3

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.
Files changed (46) hide show
  1. package/dist/irf.d.ts +4 -0
  2. package/dist/irf.d.ts.map +1 -0
  3. package/dist/irf.js +131 -0
  4. package/dist/irf.js.map +1 -0
  5. package/dist/src/discover.d.ts +11 -0
  6. package/dist/src/discover.d.ts.map +1 -0
  7. package/dist/src/discover.js +92 -0
  8. package/dist/src/discover.js.map +1 -0
  9. package/dist/src/process.d.ts +26 -0
  10. package/dist/src/process.d.ts.map +1 -0
  11. package/dist/src/process.js +56 -0
  12. package/dist/src/process.js.map +1 -0
  13. package/dist/src/prompt.d.ts +7 -0
  14. package/dist/src/prompt.d.ts.map +1 -0
  15. package/dist/src/prompt.js +84 -0
  16. package/dist/src/prompt.js.map +1 -0
  17. package/dist/src/schema.d.ts +69 -0
  18. package/dist/src/schema.d.ts.map +1 -0
  19. package/dist/src/schema.js +48 -0
  20. package/dist/src/schema.js.map +1 -0
  21. package/dist/src/session.d.ts +23 -0
  22. package/dist/src/session.d.ts.map +1 -0
  23. package/dist/src/session.js +112 -0
  24. package/dist/src/session.js.map +1 -0
  25. package/dist/src/utils/compare.d.ts +18 -0
  26. package/dist/src/utils/compare.d.ts.map +1 -0
  27. package/dist/src/utils/compare.js +74 -0
  28. package/dist/src/utils/compare.js.map +1 -0
  29. package/dist/src/utils/extractLlmError.d.ts +13 -0
  30. package/dist/src/utils/extractLlmError.d.ts.map +1 -0
  31. package/dist/src/utils/extractLlmError.js +12 -0
  32. package/dist/src/utils/extractLlmError.js.map +1 -0
  33. package/dist/src/utils/safe.d.ts +12 -0
  34. package/dist/src/utils/safe.d.ts.map +1 -0
  35. package/dist/src/utils/safe.js +31 -0
  36. package/dist/src/utils/safe.js.map +1 -0
  37. package/dist/src/utils/stripCodeFences.d.ts +2 -0
  38. package/dist/src/utils/stripCodeFences.d.ts.map +1 -0
  39. package/dist/src/utils/stripCodeFences.js +9 -0
  40. package/dist/src/utils/stripCodeFences.js.map +1 -0
  41. package/dist/src/utils/validate.d.ts +19 -0
  42. package/dist/src/utils/validate.d.ts.map +1 -0
  43. package/dist/src/utils/validate.js +30 -0
  44. package/dist/src/utils/validate.js.map +1 -0
  45. package/package.json +33 -24
  46. package/dist/index.js +0 -631
package/dist/irf.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type { Plugin } from '@opencode-ai/plugin';
2
+ declare const plugin: Plugin;
3
+ export default plugin;
4
+ //# sourceMappingURL=irf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"irf.d.ts","sourceRoot":"","sources":["../irf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAsDjD,QAAA,MAAM,MAAM,EAAE,MAkGb,CAAA;AAED,eAAe,MAAM,CAAA"}
package/dist/irf.js ADDED
@@ -0,0 +1,131 @@
1
+ import { tool } from '@opencode-ai/plugin';
2
+ import { discover, readFilePaths } from './src/discover';
3
+ import { processFile } from './src/process';
4
+ import { isFormatMode } from './src/prompt';
5
+ import { detectModel, promptWithRetry } from './src/session';
6
+ import { buildTable } from './src/utils/compare';
7
+ import { safeAsync } from './src/utils/safe';
8
+ // resolve instruction files from explicit paths or opencode.json discovery
9
+ const resolveFiles = async (directory, filesArg) => {
10
+ if (filesArg) {
11
+ const paths = filesArg.split(',').map((p) => p.trim()).filter((p) => p.length > 0);
12
+ if (paths.length === 0) {
13
+ return { data: null, error: 'No valid file paths provided' };
14
+ }
15
+ return { data: await readFilePaths(directory, paths), error: null };
16
+ }
17
+ return await discover(directory);
18
+ };
19
+ const ERROR_LABELS = {
20
+ readError: 'Read failed',
21
+ parseError: 'Parse failed',
22
+ formatError: 'Format failed',
23
+ writeError: 'Write failed',
24
+ };
25
+ // format a file result into a markdown status line
26
+ const formatFileResult = (result) => {
27
+ if (result.status === 'success') {
28
+ return '**' + result.path + '**: ' + result.rulesCount + ' rules written';
29
+ }
30
+ return '**' + result.path + '**: ' + ERROR_LABELS[result.status] + ' - ' + result.error;
31
+ };
32
+ // append comparison table section to output lines
33
+ const appendComparisonTable = (lines, comparisons) => {
34
+ if (comparisons.length === 0) {
35
+ return;
36
+ }
37
+ lines.push('');
38
+ lines.push('## Comparison');
39
+ lines.push('```');
40
+ lines.push(buildTable(comparisons));
41
+ lines.push('```');
42
+ lines.push('');
43
+ lines.push('IMPORTANT: Show the comparison table above to the user exactly as-is.');
44
+ };
45
+ // deno-lint-ignore require-await
46
+ const plugin = async ({ directory, client }) => {
47
+ return {
48
+ tool: {
49
+ 'irf-rewrite': tool({
50
+ description: [
51
+ 'Discover instruction files from opencode.json, parse them into structured rules, format them into human-readable rules, and write the formatted rules back to the original files.',
52
+ 'Accepts an optional mode: verbose (full Rule/Reason pairs), balanced (LLM decides which rules need reasons), or concise (bullet list, no reasons).',
53
+ 'Defaults to balanced.',
54
+ 'Accepts an optional files parameter to process specific files instead of running discovery.',
55
+ ].join(' '),
56
+ args: {
57
+ mode: tool.schema.string().optional().describe('Output format: verbose, balanced, or concise (default: balanced)'),
58
+ files: tool.schema.string().optional().describe('Comma-separated file paths to process instead of discovering from opencode.json'),
59
+ },
60
+ async execute(args, context) {
61
+ // validate mode argument
62
+ const mode = isFormatMode(args.mode) ? args.mode : 'balanced';
63
+ try {
64
+ // resolve files: explicit paths or discovery
65
+ const resolved = await resolveFiles(directory, args.files);
66
+ if (resolved.error !== null) {
67
+ return resolved.error;
68
+ }
69
+ const files = resolved.data;
70
+ // detect model from current session
71
+ const model = await detectModel(client, context.sessionID);
72
+ if (!model) {
73
+ return 'Could not detect current model. Send a message first, then call irf-rewrite.';
74
+ }
75
+ // create a session for internal LLM calls
76
+ const sessionResult = await client.session.create({
77
+ body: {
78
+ title: 'IRF Parse',
79
+ },
80
+ });
81
+ if (!sessionResult.data) {
82
+ return 'Failed to create internal session';
83
+ }
84
+ const sessionId = sessionResult.data.id;
85
+ // close over session details so processFile only needs a prompt callback
86
+ const prompt = (text, schema) => promptWithRetry({
87
+ client,
88
+ sessionId,
89
+ initialPrompt: text,
90
+ schema,
91
+ model,
92
+ });
93
+ // process files sequentially; parallel prompting through a shared
94
+ // session may cause ordering issues depending on SDK behavior
95
+ const results = [];
96
+ const comparisons = [];
97
+ for (const file of files) {
98
+ // bail if the tool call was cancelled
99
+ if (context.abort.aborted) {
100
+ results.push('Cancelled');
101
+ break;
102
+ }
103
+ const fileResult = await processFile({
104
+ file,
105
+ prompt,
106
+ mode,
107
+ });
108
+ if (fileResult.status === 'success') {
109
+ comparisons.push(fileResult.comparison);
110
+ }
111
+ results.push(formatFileResult(fileResult));
112
+ }
113
+ // clean up the internal session
114
+ await safeAsync(() => client.session.delete({
115
+ path: { id: sessionId },
116
+ }));
117
+ // build comparison table
118
+ appendComparisonTable(results, comparisons);
119
+ return results.join('\n');
120
+ }
121
+ catch (err) {
122
+ const msg = err instanceof Error ? err.message : String(err);
123
+ return 'irf-rewrite error: ' + msg;
124
+ }
125
+ },
126
+ }),
127
+ },
128
+ };
129
+ };
130
+ export default plugin;
131
+ //# sourceMappingURL=irf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"irf.js","sourceRoot":"","sources":["../irf.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAC1C,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAExD,OAAO,EAAmB,WAAW,EAAiB,MAAM,eAAe,CAAA;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAyB,MAAM,qBAAqB,CAAA;AAEvE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAE5C,2EAA2E;AAC3E,MAAM,YAAY,GAAG,KAAK,EAAE,SAAiB,EAAE,QAAiB,EAAsC,EAAE;IACtG,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QAClF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAAA;QAC9D,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;IACrE,CAAC;IAED,OAAO,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAA;AAClC,CAAC,CAAA;AAED,MAAM,YAAY,GAA6D;IAC7E,SAAS,EAAE,aAAa;IACxB,UAAU,EAAE,cAAc;IAC1B,WAAW,EAAE,eAAe;IAC5B,UAAU,EAAE,cAAc;CAC3B,CAAA;AAED,mDAAmD;AACnD,MAAM,gBAAgB,GAAG,CAAC,MAAkB,EAAU,EAAE;IACtD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,IAAI,GAAG,MAAM,CAAC,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,UAAU,GAAG,gBAAgB,CAAA;IAC3E,CAAC;IACD,OAAO,IAAI,GAAG,MAAM,CAAC,IAAI,GAAG,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,KAAK,GAAG,MAAM,CAAC,KAAK,CAAA;AACzF,CAAC,CAAA;AAED,kDAAkD;AAClD,MAAM,qBAAqB,GAAG,CAAC,KAAe,EAAE,WAA+B,EAAQ,EAAE;IACvF,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAM;IACR,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;IAC3B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAA;IACnC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAA;AACrF,CAAC,CAAA;AAED,iCAAiC;AACjC,MAAM,MAAM,GAAW,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE;IACrD,OAAO;QACL,IAAI,EAAE;YACJ,aAAa,EAAE,IAAI,CAAC;gBAClB,WAAW,EAAE;oBACX,mLAAmL;oBACnL,oJAAoJ;oBACpJ,uBAAuB;oBACvB,6FAA6F;iBAC9F,CAAC,IAAI,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE;oBACJ,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAC5C,kEAAkE,CACnE;oBACD,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAC7C,iFAAiF,CAClF;iBACF;gBACD,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO;oBACzB,yBAAyB;oBACzB,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAA;oBAC7D,IAAI,CAAC;wBACH,6CAA6C;wBAC7C,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAA;wBAC1D,IAAI,QAAQ,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;4BAC5B,OAAO,QAAQ,CAAC,KAAK,CAAA;wBACvB,CAAC;wBACD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAA;wBAE3B,oCAAoC;wBACpC,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;wBAC1D,IAAI,CAAC,KAAK,EAAE,CAAC;4BACX,OAAO,8EAA8E,CAAA;wBACvF,CAAC;wBAED,0CAA0C;wBAC1C,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;4BAChD,IAAI,EAAE;gCACJ,KAAK,EAAE,WAAW;6BACnB;yBACF,CAAC,CAAA;wBACF,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;4BACxB,OAAO,mCAAmC,CAAA;wBAC5C,CAAC;wBACD,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,EAAE,CAAA;wBAEvC,yEAAyE;wBACzE,MAAM,MAAM,GAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CACxC,eAAe,CAAC;4BACd,MAAM;4BACN,SAAS;4BACT,aAAa,EAAE,IAAI;4BACnB,MAAM;4BACN,KAAK;yBACN,CAAC,CAAA;wBAEJ,kEAAkE;wBAClE,8DAA8D;wBAC9D,MAAM,OAAO,GAAa,EAAE,CAAA;wBAC5B,MAAM,WAAW,GAAuB,EAAE,CAAA;wBAE1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;4BACzB,sCAAsC;4BACtC,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;gCAC1B,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;gCACzB,MAAK;4BACP,CAAC;4BAED,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC;gCACnC,IAAI;gCACJ,MAAM;gCACN,IAAI;6BACL,CAAC,CAAA;4BACF,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gCACpC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAA;4BACzC,CAAC;4BACD,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAA;wBAC5C,CAAC;wBAED,gCAAgC;wBAChC,MAAM,SAAS,CAAC,GAAG,EAAE,CACnB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;4BACpB,IAAI,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE;yBACxB,CAAC,CACH,CAAA;wBAED,yBAAyB;wBACzB,qBAAqB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;wBAE3C,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;oBAC3B,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;wBAC5D,OAAO,qBAAqB,GAAG,GAAG,CAAA;oBACpC,CAAC;gBACH,CAAC;aACF,CAAC;SACH;KACF,CAAA;AACH,CAAC,CAAA;AAED,eAAe,MAAM,CAAA"}
@@ -0,0 +1,11 @@
1
+ import { type Result } from './utils/safe';
2
+ export type InstructionFile = {
3
+ path: string;
4
+ content: string;
5
+ error?: string;
6
+ };
7
+ type DiscoverResult = Result<InstructionFile[]>;
8
+ export declare const readFilePaths: (directory: string, paths: string[]) => Promise<InstructionFile[]>;
9
+ export declare const discover: (directory: string) => Promise<DiscoverResult>;
10
+ export {};
11
+ //# sourceMappingURL=discover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/discover.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,MAAM,EAAmB,MAAM,cAAc,CAAA;AAE3D,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,KAAK,cAAc,GAAG,MAAM,CAAC,eAAe,EAAE,CAAC,CAAA;AA4E/C,eAAO,MAAM,aAAa,GAAU,WAAW,MAAM,EAAE,OAAO,MAAM,EAAE,KAAG,OAAO,CAAC,eAAe,EAAE,CAGjG,CAAA;AAED,eAAO,MAAM,QAAQ,GAAU,WAAW,MAAM,KAAG,OAAO,CAAC,cAAc,CAwBxE,CAAA"}
@@ -0,0 +1,92 @@
1
+ import { glob, readFile } from 'node:fs/promises';
2
+ import { join, resolve } from 'node:path';
3
+ import { safe, safeAsync } from './utils/safe';
4
+ const readConfig = async (directory) => {
5
+ const configPath = join(directory, 'opencode.json');
6
+ const { data, error } = await safeAsync(() => readFile(configPath, 'utf-8'));
7
+ if (error) {
8
+ return {
9
+ data: null,
10
+ error: 'Could not read ' + configPath + ': ' + error.message,
11
+ };
12
+ }
13
+ const { data: parsed, error: parseError } = safe(() => JSON.parse(data));
14
+ if (parseError) {
15
+ return {
16
+ data: null,
17
+ error: 'Invalid JSON in ' + configPath + ': ' + parseError.message,
18
+ };
19
+ }
20
+ const instructions = parsed.instructions;
21
+ if (!instructions || !Array.isArray(instructions) || instructions.length === 0) {
22
+ return {
23
+ data: null,
24
+ error: 'No "instructions" array found in ' + configPath,
25
+ };
26
+ }
27
+ const patterns = instructions.filter((entry) => typeof entry === 'string');
28
+ if (patterns.length === 0) {
29
+ return {
30
+ data: null,
31
+ error: 'No valid string patterns in "instructions" in ' + configPath,
32
+ };
33
+ }
34
+ return {
35
+ data: patterns,
36
+ error: null,
37
+ };
38
+ };
39
+ const resolveFiles = async (directory, patterns) => {
40
+ const seen = new Set();
41
+ const files = [];
42
+ for (const pattern of patterns) {
43
+ for await (const path of glob(pattern, { cwd: directory })) {
44
+ const full = join(directory, path);
45
+ if (!seen.has(full)) {
46
+ seen.add(full);
47
+ files.push(full);
48
+ }
49
+ }
50
+ }
51
+ return files;
52
+ };
53
+ const readFiles = async (files) => {
54
+ const results = [];
55
+ for (const file of files) {
56
+ const { data, error } = await safeAsync(() => readFile(file, 'utf-8'));
57
+ if (error) {
58
+ results.push({ path: file, content: '', error: error.message });
59
+ continue;
60
+ }
61
+ results.push({ path: file, content: data });
62
+ }
63
+ return results;
64
+ };
65
+ // read specific file paths into InstructionFile entries, resolving relative paths against directory
66
+ export const readFilePaths = async (directory, paths) => {
67
+ const resolved = paths.map((p) => resolve(directory, p));
68
+ return await readFiles(resolved);
69
+ };
70
+ export const discover = async (directory) => {
71
+ const config = await readConfig(directory);
72
+ if (config.error !== null) {
73
+ return {
74
+ data: null,
75
+ error: config.error,
76
+ };
77
+ }
78
+ const patterns = config.data;
79
+ const files = await resolveFiles(directory, patterns);
80
+ if (files.length === 0) {
81
+ return {
82
+ data: null,
83
+ error: 'No instruction files found matching patterns: ' + patterns.join(', '),
84
+ };
85
+ }
86
+ const results = await readFiles(files);
87
+ return {
88
+ data: results,
89
+ error: null,
90
+ };
91
+ };
92
+ //# sourceMappingURL=discover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/discover.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { z } from 'zod';
2
+ import type { InstructionFile } from './discover';
3
+ import { type FormatMode } from './prompt';
4
+ import { type ComparisonResult } from './utils/compare';
5
+ import type { Result } from './utils/safe';
6
+ type FileResultSuccess = {
7
+ status: 'success';
8
+ path: string;
9
+ rulesCount: number;
10
+ comparison: ComparisonResult;
11
+ };
12
+ type FileResultError = {
13
+ status: 'readError' | 'parseError' | 'formatError' | 'writeError';
14
+ path: string;
15
+ error: string;
16
+ };
17
+ export type FileResult = FileResultSuccess | FileResultError;
18
+ export type PromptFn = <T>(prompt: string, schema: z.ZodType<T>) => Promise<Result<T>>;
19
+ type ProcessFileOptions = {
20
+ file: InstructionFile;
21
+ prompt: PromptFn;
22
+ mode?: FormatMode;
23
+ };
24
+ export declare const processFile: (options: ProcessFileOptions) => Promise<FileResult>;
25
+ export {};
26
+ //# sourceMappingURL=process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/process.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,EAAuC,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAE/E,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAG1C,KAAK,iBAAiB,GAAG;IACvB,MAAM,EAAE,SAAS,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,gBAAgB,CAAA;CAC7B,CAAA;AAED,KAAK,eAAe,GAAG;IACrB,MAAM,EAAE,WAAW,GAAG,YAAY,GAAG,aAAa,GAAG,YAAY,CAAA;IACjE,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,iBAAiB,GAAG,eAAe,CAAA;AAG5D,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;AAEtF,KAAK,kBAAkB,GAAG;IACxB,IAAI,EAAE,eAAe,CAAA;IACrB,MAAM,EAAE,QAAQ,CAAA;IAChB,IAAI,CAAC,EAAE,UAAU,CAAA;CAClB,CAAA;AAGD,eAAO,MAAM,WAAW,GAAU,SAAS,kBAAkB,KAAG,OAAO,CAAC,UAAU,CAsDjF,CAAA"}
@@ -0,0 +1,56 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import { basename } from 'node:path';
3
+ import { buildFormatPrompt, buildParsePrompt } from './prompt';
4
+ import { FormatResponseSchema, ParseResponseSchema } from './schema';
5
+ import { compareBytes } from './utils/compare';
6
+ import { safeAsync } from './utils/safe';
7
+ // process a single instruction file through the parse -> format -> write pipeline
8
+ export const processFile = async (options) => {
9
+ const { file, prompt, mode = 'balanced' } = options;
10
+ // skip files that failed to read
11
+ if (file.error) {
12
+ return {
13
+ status: 'readError',
14
+ path: file.path,
15
+ error: file.error,
16
+ };
17
+ }
18
+ // step 1: parse instruction text -> structured rules
19
+ const parseResult = await prompt(buildParsePrompt(file.content), ParseResponseSchema);
20
+ if (parseResult.error !== null) {
21
+ return {
22
+ status: 'parseError',
23
+ path: file.path,
24
+ error: String(parseResult.error),
25
+ };
26
+ }
27
+ // step 2: format structured rules -> human-readable rules
28
+ const formatResult = await prompt(buildFormatPrompt(JSON.stringify(parseResult.data), mode), FormatResponseSchema);
29
+ if (formatResult.error !== null) {
30
+ return {
31
+ status: 'formatError',
32
+ path: file.path,
33
+ error: String(formatResult.error),
34
+ };
35
+ }
36
+ // step 3: write formatted rules back to original file
37
+ const formattedRules = formatResult.data.rules;
38
+ const joiner = mode === 'concise' ? '\n' : '\n\n';
39
+ const content = formattedRules.join(joiner) + '\n';
40
+ const { error: writeError } = await safeAsync(() => writeFile(file.path, content, 'utf-8'));
41
+ if (writeError) {
42
+ return {
43
+ status: 'writeError',
44
+ path: file.path,
45
+ error: writeError.message,
46
+ };
47
+ }
48
+ const comparison = compareBytes(basename(file.path), file.content, content);
49
+ return {
50
+ status: 'success',
51
+ path: file.path,
52
+ rulesCount: formattedRules.length,
53
+ comparison,
54
+ };
55
+ };
56
+ //# sourceMappingURL=process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAGpC,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAmB,MAAM,UAAU,CAAA;AAC/E,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACpE,OAAO,EAAE,YAAY,EAAyB,MAAM,iBAAiB,CAAA;AAErE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AA0BxC,kFAAkF;AAClF,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,OAA2B,EAAuB,EAAE;IACpF,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAG,UAAU,EAAE,GAAG,OAAO,CAAA;IAEnD,iCAAiC;IACjC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,OAAO;YACL,MAAM,EAAE,WAAW;YACnB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAA;IACH,CAAC;IAED,qDAAqD;IACrD,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,mBAAmB,CAAC,CAAA;IAErF,IAAI,WAAW,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QAC/B,OAAO;YACL,MAAM,EAAE,YAAY;YACpB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC;SACjC,CAAA;IACH,CAAC;IAED,0DAA0D;IAC1D,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,oBAAoB,CAAC,CAAA;IAElH,IAAI,YAAY,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QAChC,OAAO;YACL,MAAM,EAAE,aAAa;YACrB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC;SAClC,CAAA;IACH,CAAC;IAED,sDAAsD;IACtD,MAAM,cAAc,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAA;IAC9C,MAAM,MAAM,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAA;IACjD,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;IAClD,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;IAC3F,IAAI,UAAU,EAAE,CAAC;QACf,OAAO;YACL,MAAM,EAAE,YAAY;YACpB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,UAAU,CAAC,OAAO;SAC1B,CAAA;IACH,CAAC;IAED,MAAM,UAAU,GAAG,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAC3E,OAAO;QACL,MAAM,EAAE,SAAS;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,UAAU,EAAE,cAAc,CAAC,MAAM;QACjC,UAAU;KACX,CAAA;AACH,CAAC,CAAA"}
@@ -0,0 +1,7 @@
1
+ export type FormatMode = 'verbose' | 'balanced' | 'concise';
2
+ export declare const FORMAT_MODES: FormatMode[];
3
+ export declare const isFormatMode: (v: unknown) => v is FormatMode;
4
+ export declare const buildParsePrompt: (input: string) => string;
5
+ export declare const buildFormatPrompt: (parsedRulesJson: string, mode?: FormatMode) => string;
6
+ export declare const buildRetryPrompt: (errorMessage: string) => string;
7
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/prompt.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAA;AAE3D,eAAO,MAAM,YAAY,EAAE,UAAU,EAAuC,CAAA;AAE5E,eAAO,MAAM,YAAY,GAAI,GAAG,OAAO,KAAG,CAAC,IAAI,UACkB,CAAA;AAEjE,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,KAAG,MAchD,CAAA;AAgED,eAAO,MAAM,iBAAiB,GAAI,iBAAiB,MAAM,EAAE,OAAM,UAAuB,KAAG,MAG1F,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAI,cAAc,MAAM,KAAG,MAGvD,CAAA"}
@@ -0,0 +1,84 @@
1
+ import { parseSchemaExample } from './schema';
2
+ export const FORMAT_MODES = ['verbose', 'balanced', 'concise'];
3
+ export const isFormatMode = (v) => typeof v === 'string' && FORMAT_MODES.includes(v);
4
+ export const buildParsePrompt = (input) => {
5
+ const instructions = [
6
+ 'You are a rule parser that converts raw instructions into structured parsed rules.',
7
+ 'Take the provided instructions and break them down into structured components.',
8
+ 'Each rule should have: strength, action (verb), target (object), context (optional condition/scope), and reason (justification).',
9
+ 'Focus on extracting the core components without adding extra details.',
10
+ '',
11
+ 'Return ONLY valid JSON matching this exact schema:',
12
+ parseSchemaExample,
13
+ '',
14
+ 'Do not include any text outside the JSON object. Do not wrap it in markdown code fences.',
15
+ ].join('\n');
16
+ return [instructions, 'Instructions to parse:', input].join('\n\n');
17
+ };
18
+ const verboseInstructions = [
19
+ 'You are a rule formatter that converts structured parsed rules into human-readable rules.',
20
+ 'Take the provided parsed rule components and create natural language versions.',
21
+ 'Every rule must include both a Rule line and a Reason line.',
22
+ 'Each rule must follow this exact format:',
23
+ '',
24
+ 'Rule: <clear, concise, actionable statement>',
25
+ 'Reason: <justification from the parsed rule>',
26
+ '',
27
+ 'Each human-readable rule should directly correspond to the parsed components without adding extra details.',
28
+ 'Make the rules clear, concise, and actionable.',
29
+ '',
30
+ 'Return ONLY valid JSON matching this exact schema:',
31
+ '{"rules": ["Rule: ...\\nReason: ...", "Rule: ...\\nReason: ..."]}',
32
+ '',
33
+ 'Do not include any text outside the JSON object. Do not wrap it in markdown code fences.',
34
+ ];
35
+ const balancedInstructions = [
36
+ 'You are a rule formatter that converts structured parsed rules into human-readable rules.',
37
+ 'Take the provided parsed rule components and create natural language versions.',
38
+ 'Use your judgment for each rule:',
39
+ '- If the rule is non-obvious or counterintuitive, include both the Rule and Reason lines.',
40
+ '- If the rule is self-explanatory, include only the Rule line and omit the Reason.',
41
+ '',
42
+ 'Format rules that include a reason:',
43
+ 'Rule: <clear, concise, actionable statement>',
44
+ 'Reason: <justification from the parsed rule>',
45
+ '',
46
+ 'Format rules that are self-explanatory:',
47
+ 'Rule: <clear, concise, actionable statement>',
48
+ '',
49
+ 'Each human-readable rule should directly correspond to the parsed components without adding extra details.',
50
+ 'Make the rules clear, concise, and actionable.',
51
+ '',
52
+ 'Return ONLY valid JSON matching this exact schema:',
53
+ '{"rules": ["Rule: ...\\nReason: ...", "Rule: ..."]}',
54
+ '',
55
+ 'Do not include any text outside the JSON object. Do not wrap it in markdown code fences.',
56
+ ];
57
+ const conciseInstructions = [
58
+ 'You are a rule formatter that converts structured parsed rules into concise directives.',
59
+ 'Take the provided parsed rule components and create a bullet list of clear directives.',
60
+ 'Do not include reasons or justifications. Output only the actionable statement.',
61
+ 'Each rule must be a single line starting with "- " (dash space).',
62
+ '',
63
+ 'Each directive should directly correspond to the parsed components without adding extra details.',
64
+ 'Make the directives clear, concise, and actionable.',
65
+ '',
66
+ 'Return ONLY valid JSON matching this exact schema:',
67
+ '{"rules": ["- ...", "- ..."]}',
68
+ '',
69
+ 'Do not include any text outside the JSON object. Do not wrap it in markdown code fences.',
70
+ ];
71
+ const formatInstructions = {
72
+ verbose: verboseInstructions,
73
+ balanced: balancedInstructions,
74
+ concise: conciseInstructions,
75
+ };
76
+ export const buildFormatPrompt = (parsedRulesJson, mode = 'balanced') => {
77
+ const instructions = formatInstructions[mode].join('\n');
78
+ return [instructions, 'Parsed rules to convert:', parsedRulesJson].join('\n\n');
79
+ };
80
+ export const buildRetryPrompt = (errorMessage) => {
81
+ return 'Your previous response was invalid. ' + errorMessage
82
+ + '\n\nReturn ONLY valid JSON. Do not include any text outside the JSON object.';
83
+ };
84
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAI7C,MAAM,CAAC,MAAM,YAAY,GAAiB,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,CAAC,CAAA;AAE5E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAU,EAAmB,EAAE,CAC1D,OAAO,CAAC,KAAK,QAAQ,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAe,CAAC,CAAA;AAEjE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAa,EAAU,EAAE;IACxD,MAAM,YAAY,GAAG;QACnB,oFAAoF;QACpF,gFAAgF;QAChF,kIAAkI;QAClI,uEAAuE;QACvE,EAAE;QACF,oDAAoD;QACpD,kBAAkB;QAClB,EAAE;QACF,0FAA0F;KAC3F,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEZ,OAAO,CAAC,YAAY,EAAE,wBAAwB,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AACrE,CAAC,CAAA;AAED,MAAM,mBAAmB,GAAG;IAC1B,2FAA2F;IAC3F,gFAAgF;IAChF,6DAA6D;IAC7D,0CAA0C;IAC1C,EAAE;IACF,8CAA8C;IAC9C,8CAA8C;IAC9C,EAAE;IACF,4GAA4G;IAC5G,gDAAgD;IAChD,EAAE;IACF,oDAAoD;IACpD,mEAAmE;IACnE,EAAE;IACF,0FAA0F;CAC3F,CAAA;AAED,MAAM,oBAAoB,GAAG;IAC3B,2FAA2F;IAC3F,gFAAgF;IAChF,kCAAkC;IAClC,2FAA2F;IAC3F,oFAAoF;IACpF,EAAE;IACF,qCAAqC;IACrC,8CAA8C;IAC9C,8CAA8C;IAC9C,EAAE;IACF,yCAAyC;IACzC,8CAA8C;IAC9C,EAAE;IACF,4GAA4G;IAC5G,gDAAgD;IAChD,EAAE;IACF,oDAAoD;IACpD,qDAAqD;IACrD,EAAE;IACF,0FAA0F;CAC3F,CAAA;AAED,MAAM,mBAAmB,GAAG;IAC1B,yFAAyF;IACzF,wFAAwF;IACxF,iFAAiF;IACjF,kEAAkE;IAClE,EAAE;IACF,kGAAkG;IAClG,qDAAqD;IACrD,EAAE;IACF,oDAAoD;IACpD,+BAA+B;IAC/B,EAAE;IACF,0FAA0F;CAC3F,CAAA;AAED,MAAM,kBAAkB,GAAiC;IACvD,OAAO,EAAE,mBAAmB;IAC5B,QAAQ,EAAE,oBAAoB;IAC9B,OAAO,EAAE,mBAAmB;CAC7B,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,eAAuB,EAAE,OAAmB,UAAU,EAAU,EAAE;IAClG,MAAM,YAAY,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACxD,OAAO,CAAC,YAAY,EAAE,0BAA0B,EAAE,eAAe,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AACjF,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,YAAoB,EAAU,EAAE;IAC/D,OAAO,sCAAsC,GAAG,YAAY;UACxD,8EAA8E,CAAA;AACpF,CAAC,CAAA"}
@@ -0,0 +1,69 @@
1
+ import { z } from 'zod';
2
+ export declare const StrengthSchema: z.ZodEnum<{
3
+ obligatory: "obligatory";
4
+ permissible: "permissible";
5
+ forbidden: "forbidden";
6
+ optional: "optional";
7
+ supererogatory: "supererogatory";
8
+ indifferent: "indifferent";
9
+ omissible: "omissible";
10
+ }>;
11
+ export declare const ActionSchema: z.ZodString;
12
+ export declare const TargetSchema: z.ZodString;
13
+ export declare const ContextSchema: z.ZodString;
14
+ export declare const ReasonSchema: z.ZodString;
15
+ export declare const ParsedRuleSchema: z.ZodObject<{
16
+ strength: z.ZodEnum<{
17
+ obligatory: "obligatory";
18
+ permissible: "permissible";
19
+ forbidden: "forbidden";
20
+ optional: "optional";
21
+ supererogatory: "supererogatory";
22
+ indifferent: "indifferent";
23
+ omissible: "omissible";
24
+ }>;
25
+ action: z.ZodString;
26
+ target: z.ZodString;
27
+ context: z.ZodOptional<z.ZodString>;
28
+ reason: z.ZodString;
29
+ }, z.core.$strip>;
30
+ export declare const RuleSchema: z.ZodString;
31
+ export declare const ParsedSchema: z.ZodArray<z.ZodObject<{
32
+ strength: z.ZodEnum<{
33
+ obligatory: "obligatory";
34
+ permissible: "permissible";
35
+ forbidden: "forbidden";
36
+ optional: "optional";
37
+ supererogatory: "supererogatory";
38
+ indifferent: "indifferent";
39
+ omissible: "omissible";
40
+ }>;
41
+ action: z.ZodString;
42
+ target: z.ZodString;
43
+ context: z.ZodOptional<z.ZodString>;
44
+ reason: z.ZodString;
45
+ }, z.core.$strip>>;
46
+ export declare const ParseResponseSchema: z.ZodObject<{
47
+ rules: z.ZodArray<z.ZodObject<{
48
+ strength: z.ZodEnum<{
49
+ obligatory: "obligatory";
50
+ permissible: "permissible";
51
+ forbidden: "forbidden";
52
+ optional: "optional";
53
+ supererogatory: "supererogatory";
54
+ indifferent: "indifferent";
55
+ omissible: "omissible";
56
+ }>;
57
+ action: z.ZodString;
58
+ target: z.ZodString;
59
+ context: z.ZodOptional<z.ZodString>;
60
+ reason: z.ZodString;
61
+ }, z.core.$strip>>;
62
+ }, z.core.$strip>;
63
+ export declare const FormatResponseSchema: z.ZodObject<{
64
+ rules: z.ZodArray<z.ZodString>;
65
+ }, z.core.$strip>;
66
+ export type Strength = z.infer<typeof StrengthSchema>;
67
+ export type ParsedRule = z.infer<typeof ParsedRuleSchema>;
68
+ export declare const parseSchemaExample: string;
69
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,cAAc;;;;;;;;EASoC,CAAA;AAE/D,eAAO,MAAM,YAAY,aACmC,CAAA;AAE5D,eAAO,MAAM,YAAY,aAC6B,CAAA;AAEtD,eAAO,MAAM,aAAa,aAC4C,CAAA;AAEtE,eAAO,MAAM,YAAY,aAC2B,CAAA;AAEpD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;iBAOuC,CAAA;AAEpE,eAAO,MAAM,UAAU,aAC0C,CAAA;AAEjE,eAAO,MAAM,YAAY;;;;;;;;;;;;;;kBACW,CAAA;AAEpC,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;iBAE9B,CAAA;AAEF,eAAO,MAAM,oBAAoB;;iBAE/B,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA;AACrD,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAGzD,eAAO,MAAM,kBAAkB,QAQ7B,CAAA"}
@@ -0,0 +1,48 @@
1
+ import { z } from 'zod';
2
+ export const StrengthSchema = z.enum([
3
+ 'obligatory',
4
+ 'permissible',
5
+ 'forbidden',
6
+ 'optional',
7
+ 'supererogatory',
8
+ 'indifferent',
9
+ 'omissible',
10
+ ])
11
+ .describe('Deontic modality expressing enforcement strength');
12
+ export const ActionSchema = z.string()
13
+ .describe('Imperative verb describing the action to take');
14
+ export const TargetSchema = z.string()
15
+ .describe('Object or subject the action applies to');
16
+ export const ContextSchema = z.string()
17
+ .describe('Condition, scope, or circumstance when the rule applies');
18
+ export const ReasonSchema = z.string()
19
+ .describe('Justification for why the rule exists');
20
+ export const ParsedRuleSchema = z.object({
21
+ strength: StrengthSchema,
22
+ action: ActionSchema,
23
+ target: TargetSchema,
24
+ context: ContextSchema.optional(),
25
+ reason: ReasonSchema,
26
+ })
27
+ .describe('Single instruction decomposed into deontic components');
28
+ export const RuleSchema = z.string()
29
+ .describe('Human-readable rule derived from parsed components');
30
+ export const ParsedSchema = z.array(ParsedRuleSchema)
31
+ .describe('Array of parsed rules');
32
+ export const ParseResponseSchema = z.object({
33
+ rules: ParsedSchema,
34
+ });
35
+ export const FormatResponseSchema = z.object({
36
+ rules: z.array(RuleSchema),
37
+ });
38
+ // generate a JSON schema example string from the Zod schema for use in prompts
39
+ export const parseSchemaExample = JSON.stringify({
40
+ rules: [{
41
+ strength: StrengthSchema.options.join('/'),
42
+ action: ActionSchema.description || 'verb',
43
+ target: TargetSchema.description || 'object',
44
+ context: ContextSchema.description || 'optional condition',
45
+ reason: ReasonSchema.description || 'justification',
46
+ }],
47
+ });
48
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC;IACnC,YAAY;IACZ,aAAa;IACb,WAAW;IACX,UAAU;IACV,gBAAgB;IAChB,aAAa;IACb,WAAW;CACZ,CAAC;KACC,QAAQ,CAAC,kDAAkD,CAAC,CAAA;AAE/D,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,EAAE;KACnC,QAAQ,CAAC,+CAA+C,CAAC,CAAA;AAE5D,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,EAAE;KACnC,QAAQ,CAAC,yCAAyC,CAAC,CAAA;AAEtD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,EAAE;KACpC,QAAQ,CAAC,yDAAyD,CAAC,CAAA;AAEtE,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,EAAE;KACnC,QAAQ,CAAC,uCAAuC,CAAC,CAAA;AAEpD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,QAAQ,EAAE,cAAc;IACxB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,aAAa,CAAC,QAAQ,EAAE;IACjC,MAAM,EAAE,YAAY;CACrB,CAAC;KACC,QAAQ,CAAC,uDAAuD,CAAC,CAAA;AAEpE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,EAAE;KACjC,QAAQ,CAAC,oDAAoD,CAAC,CAAA;AAEjE,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC;KAClD,QAAQ,CAAC,uBAAuB,CAAC,CAAA;AAEpC,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,KAAK,EAAE,YAAY;CACpB,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC;CAC3B,CAAC,CAAA;AAKF,+EAA+E;AAC/E,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,SAAS,CAAC;IAC/C,KAAK,EAAE,CAAC;YACN,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;YAC1C,MAAM,EAAE,YAAY,CAAC,WAAW,IAAI,MAAM;YAC1C,MAAM,EAAE,YAAY,CAAC,WAAW,IAAI,QAAQ;YAC5C,OAAO,EAAE,aAAa,CAAC,WAAW,IAAI,oBAAoB;YAC1D,MAAM,EAAE,YAAY,CAAC,WAAW,IAAI,eAAe;SACpD,CAAC;CACH,CAAC,CAAA"}
@@ -0,0 +1,23 @@
1
+ import type { PluginInput } from '@opencode-ai/plugin';
2
+ import type { z } from 'zod';
3
+ import type { Result } from './utils/safe';
4
+ export type PromptModel = {
5
+ providerID: string;
6
+ modelID: string;
7
+ };
8
+ type Part = {
9
+ type: string;
10
+ text?: string;
11
+ };
12
+ export declare const extractText: (parts: Part[]) => string;
13
+ export declare const detectModel: (client: PluginInput["client"], sessionId: string) => Promise<PromptModel | null>;
14
+ type PromptWithRetryOptions<T> = {
15
+ client: PluginInput['client'];
16
+ sessionId: string;
17
+ initialPrompt: string;
18
+ schema: z.ZodType<T>;
19
+ model: PromptModel;
20
+ };
21
+ export declare const promptWithRetry: <T>(options: PromptWithRetryOptions<T>) => Promise<Result<T>>;
22
+ export {};
23
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAG5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAM1C,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAGD,KAAK,IAAI,GAAG;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAgBD,eAAO,MAAM,WAAW,GAAI,OAAO,IAAI,EAAE,KAAG,MAM3C,CAAA;AAGD,eAAO,MAAM,WAAW,GAAU,QAAQ,WAAW,CAAC,QAAQ,CAAC,EAAE,WAAW,MAAM,KAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAuB9G,CAAA;AAED,KAAK,sBAAsB,CAAC,CAAC,IAAI;IAC/B,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IACpB,KAAK,EAAE,WAAW,CAAA;CACnB,CAAA;AAGD,eAAO,MAAM,eAAe,GAAU,CAAC,EAAE,SAAS,sBAAsB,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CA0E9F,CAAA"}