redashify 0.1.0 → 0.2.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.
- package/README.md +4 -4
- package/dist/index.cjs +4 -106
- package/dist/index.d.cts +5 -19
- package/dist/index.d.ts +5 -19
- package/dist/index.js +4 -96
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -93,7 +93,7 @@ const result = await redashify(text, {
|
|
|
93
93
|
| `model` | `string` | *(per provider)* | Model name. Required if no provider default. |
|
|
94
94
|
| `baseURL` | `string` | — | Custom endpoint URL. Overrides provider mapping. |
|
|
95
95
|
| `llm` | `(messages) => Promise<string>` | — | Custom LLM function. Overrides apiKey/provider/model. |
|
|
96
|
-
| `rules` | `string` |
|
|
96
|
+
| `rules` | `string` | `“”` | Custom rules prepended to the system prompt |
|
|
97
97
|
| `contextSize` | `number` | `50` | Characters of context on each side of a dash |
|
|
98
98
|
| `batchSize` | `number` | `50` | Maximum dashes per LLM call |
|
|
99
99
|
|
|
@@ -116,7 +116,7 @@ interface RedashifyResult {
|
|
|
116
116
|
|
|
117
117
|
**No dashes in text:** LLM is not called. Returns immediately with `unchanged: true`.
|
|
118
118
|
|
|
119
|
-
**All dashes already correct:** LLM is called (correctness can
|
|
119
|
+
**All dashes already correct:** LLM is called (correctness can’t be pre-judged), but `corrections` is empty and `unchanged` is `true`.
|
|
120
120
|
|
|
121
121
|
## Custom rules
|
|
122
122
|
|
|
@@ -147,7 +147,7 @@ Keep hyphens in compound modifiers and vote tallies (5-4).`,
|
|
|
147
147
|
|
|
148
148
|
## Design decisions
|
|
149
149
|
|
|
150
|
-
**LLM over regex.** Dash correction depends on semantic context — is
|
|
150
|
+
**LLM over regex.** Dash correction depends on semantic context — is “10-20” a range (en dash) or a compound modifier (hyphen)? Is “--” an em dash or a typo? Regex can’t answer these questions. An LLM can, given a few words of surrounding context.
|
|
151
151
|
|
|
152
152
|
**Privacy by design.** Only short context windows around each dash are sent to the LLM — never the full document. A 10,000-word document with 5 dashes sends ~5 small context snippets, regardless of document length.
|
|
153
153
|
|
|
@@ -159,7 +159,7 @@ Keep hyphens in compound modifiers and vote tallies (5-4).`,
|
|
|
159
159
|
|
|
160
160
|
```sh
|
|
161
161
|
npm install
|
|
162
|
-
npm test
|
|
162
|
+
npm test
|
|
163
163
|
npm run typecheck
|
|
164
164
|
npm run build # ESM + CJS + .d.ts
|
|
165
165
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// src/index.ts
|
|
@@ -37,6 +27,9 @@ __export(index_exports, {
|
|
|
37
27
|
});
|
|
38
28
|
module.exports = __toCommonJS(index_exports);
|
|
39
29
|
|
|
30
|
+
// src/core.ts
|
|
31
|
+
var import_llm_client = require("@lexstyle/llm-client");
|
|
32
|
+
|
|
40
33
|
// src/extractor.ts
|
|
41
34
|
var DASH_RE = /---+|--|\u2014|\u2013|-/g;
|
|
42
35
|
function extractDashes(text, contextSize = 50) {
|
|
@@ -91,83 +84,6 @@ Format: [{"id":0,"dash":"-"},{"id":1,"dash":"\u2013"}]`;
|
|
|
91
84
|
];
|
|
92
85
|
}
|
|
93
86
|
|
|
94
|
-
// src/llmClient.ts
|
|
95
|
-
var import_openai = __toESM(require("openai"), 1);
|
|
96
|
-
var PROVIDER_CONFIGS = {
|
|
97
|
-
openai: { baseURL: "https://api.openai.com/v1", defaultModel: "gpt-4o-mini" },
|
|
98
|
-
anthropic: { baseURL: "https://api.anthropic.com", defaultModel: "claude-haiku-4-5-20251001" },
|
|
99
|
-
gemini: { baseURL: "https://generativelanguage.googleapis.com/v1beta/openai", defaultModel: "gemini-2.0-flash" },
|
|
100
|
-
groq: { baseURL: "https://api.groq.com/openai/v1", defaultModel: "llama-3.3-70b-versatile" },
|
|
101
|
-
together: { baseURL: "https://api.together.xyz/v1", defaultModel: "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo" },
|
|
102
|
-
mistral: { baseURL: "https://api.mistral.ai/v1", defaultModel: "mistral-small-latest" },
|
|
103
|
-
openrouter: { baseURL: "https://openrouter.ai/api/v1", defaultModel: "" },
|
|
104
|
-
xai: { baseURL: "https://api.x.ai/v1", defaultModel: "grok-3-mini-fast" },
|
|
105
|
-
deepseek: { baseURL: "https://api.deepseek.com", defaultModel: "deepseek-chat" }
|
|
106
|
-
};
|
|
107
|
-
function getProviderConfig(provider) {
|
|
108
|
-
if (!(provider in PROVIDER_CONFIGS)) {
|
|
109
|
-
const valid = Object.keys(PROVIDER_CONFIGS).join(", ");
|
|
110
|
-
throw new Error(`Unknown provider "${provider}". Valid providers: ${valid}`);
|
|
111
|
-
}
|
|
112
|
-
return PROVIDER_CONFIGS[provider];
|
|
113
|
-
}
|
|
114
|
-
async function callAnthropic(messages, apiKey, model, baseURL) {
|
|
115
|
-
const resolvedBaseURL = (baseURL ?? PROVIDER_CONFIGS.anthropic.baseURL).replace(/\/+$/, "").replace(/\/v1$/i, "");
|
|
116
|
-
const url = `${resolvedBaseURL}/v1/messages`;
|
|
117
|
-
const systemMsg = messages.find((m) => m.role === "system");
|
|
118
|
-
const nonSystemMsgs = messages.filter((m) => m.role !== "system");
|
|
119
|
-
const body = {
|
|
120
|
-
model,
|
|
121
|
-
max_tokens: 4096,
|
|
122
|
-
messages: nonSystemMsgs.map((m) => ({ role: m.role, content: m.content }))
|
|
123
|
-
};
|
|
124
|
-
if (systemMsg) {
|
|
125
|
-
body.system = systemMsg.content;
|
|
126
|
-
}
|
|
127
|
-
const res = await fetch(url, {
|
|
128
|
-
method: "POST",
|
|
129
|
-
headers: {
|
|
130
|
-
"content-type": "application/json",
|
|
131
|
-
"x-api-key": apiKey,
|
|
132
|
-
"anthropic-version": "2023-06-01"
|
|
133
|
-
},
|
|
134
|
-
body: JSON.stringify(body)
|
|
135
|
-
});
|
|
136
|
-
if (!res.ok) {
|
|
137
|
-
const text = await res.text();
|
|
138
|
-
throw new Error(`Anthropic API error (${res.status}): ${text}`);
|
|
139
|
-
}
|
|
140
|
-
const data = await res.json();
|
|
141
|
-
const textBlock = data.content?.find((b) => b.type === "text");
|
|
142
|
-
if (!textBlock?.text) {
|
|
143
|
-
throw new Error("Anthropic returned an empty response");
|
|
144
|
-
}
|
|
145
|
-
return textBlock.text;
|
|
146
|
-
}
|
|
147
|
-
async function callOpenAICompatible(messages, apiKey, model, baseURL) {
|
|
148
|
-
const client = new import_openai.default({
|
|
149
|
-
apiKey,
|
|
150
|
-
...baseURL ? { baseURL } : {}
|
|
151
|
-
});
|
|
152
|
-
const response = await client.chat.completions.create({
|
|
153
|
-
model,
|
|
154
|
-
messages,
|
|
155
|
-
temperature: 0
|
|
156
|
-
});
|
|
157
|
-
const content = response.choices[0]?.message?.content;
|
|
158
|
-
if (!content) {
|
|
159
|
-
throw new Error("LLM returned an empty response");
|
|
160
|
-
}
|
|
161
|
-
return content;
|
|
162
|
-
}
|
|
163
|
-
async function callLLM(messages, apiKey, model, provider, baseURL) {
|
|
164
|
-
if (provider === "anthropic") {
|
|
165
|
-
return callAnthropic(messages, apiKey, model, baseURL);
|
|
166
|
-
}
|
|
167
|
-
const resolvedBaseURL = baseURL ?? (provider ? PROVIDER_CONFIGS[provider].baseURL : void 0);
|
|
168
|
-
return callOpenAICompatible(messages, apiKey, model, resolvedBaseURL);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
87
|
// src/types.ts
|
|
172
88
|
var VALID_DASHES = Object.freeze(["-", "\u2013", "\u2014"]);
|
|
173
89
|
var VALID_DASH_SET = new Set(VALID_DASHES);
|
|
@@ -278,24 +194,6 @@ function requireInt(value, name, min) {
|
|
|
278
194
|
throw new Error(`Invalid ${name}: ${value}. Must be a finite integer >= ${min}.`);
|
|
279
195
|
}
|
|
280
196
|
}
|
|
281
|
-
function resolveLlm(options) {
|
|
282
|
-
if (options.llm) {
|
|
283
|
-
if (typeof options.llm !== "function") {
|
|
284
|
-
throw new Error("`llm` option must be a function");
|
|
285
|
-
}
|
|
286
|
-
return options.llm;
|
|
287
|
-
}
|
|
288
|
-
if (options.apiKey) {
|
|
289
|
-
const providerConfig = options.provider ? getProviderConfig(options.provider) : void 0;
|
|
290
|
-
const model = options.model ?? providerConfig?.defaultModel;
|
|
291
|
-
if (!model) {
|
|
292
|
-
throw new Error("redashify requires `model` when using `apiKey` (or use a `provider` with a default model)");
|
|
293
|
-
}
|
|
294
|
-
const { apiKey, provider, baseURL } = options;
|
|
295
|
-
return (messages) => callLLM(messages, apiKey, model, provider, baseURL);
|
|
296
|
-
}
|
|
297
|
-
throw new Error("redashify requires either `apiKey` + `model`, `apiKey` + `provider`, or `llm` option");
|
|
298
|
-
}
|
|
299
197
|
function validateBatchIds(corrections, expectedIds) {
|
|
300
198
|
for (const { id } of corrections) {
|
|
301
199
|
if (!expectedIds.has(id)) {
|
|
@@ -316,7 +214,7 @@ async function redashify(text, options) {
|
|
|
316
214
|
requireInt(batchSize, "batchSize", 1);
|
|
317
215
|
const contextSize = options.contextSize ?? 50;
|
|
318
216
|
requireInt(contextSize, "contextSize", 0);
|
|
319
|
-
const llmFn = resolveLlm(options);
|
|
217
|
+
const llmFn = (0, import_llm_client.resolveLlm)(options, "redashify");
|
|
320
218
|
const contexts = extractDashes(text, contextSize);
|
|
321
219
|
if (contexts.length === 0) {
|
|
322
220
|
return { text, corrections: [], unchanged: true };
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { LlmOptions, Message } from '@lexstyle/llm-client';
|
|
2
|
+
export { Message, Provider } from '@lexstyle/llm-client';
|
|
3
|
+
|
|
1
4
|
/** The valid dash characters, exported for documentation/reference */
|
|
2
5
|
declare const VALID_DASHES: readonly ["-", "–", "—"];
|
|
3
6
|
/** A single valid dash character: hyphen, en dash, or em dash */
|
|
@@ -42,25 +45,8 @@ interface RedashifyResult {
|
|
|
42
45
|
/** True if no changes were needed */
|
|
43
46
|
unchanged: boolean;
|
|
44
47
|
}
|
|
45
|
-
/** Chat message format for the LLM function */
|
|
46
|
-
interface Message {
|
|
47
|
-
role: "system" | "user" | "assistant";
|
|
48
|
-
content: string;
|
|
49
|
-
}
|
|
50
|
-
/** Known providers with built-in base URL mapping */
|
|
51
|
-
type Provider = "openai" | "anthropic" | "gemini" | "groq" | "together" | "mistral" | "openrouter" | "xai" | "deepseek";
|
|
52
48
|
/** Options for redashify */
|
|
53
|
-
interface RedashifyOptions {
|
|
54
|
-
/** API key for the LLM provider */
|
|
55
|
-
apiKey?: string;
|
|
56
|
-
/** LLM provider name (e.g. "openai", "groq", "together"). Maps to a known base URL. */
|
|
57
|
-
provider?: Provider;
|
|
58
|
-
/** Model name (e.g. "gpt-4o-mini", "llama-3.3-70b-versatile"). Required when using apiKey without a known provider default. */
|
|
59
|
-
model?: string;
|
|
60
|
-
/** Custom base URL for OpenAI-compatible APIs. Overrides provider mapping. */
|
|
61
|
-
baseURL?: string;
|
|
62
|
-
/** Custom LLM function: receives messages, returns the raw text response. Overrides apiKey/provider/model. */
|
|
63
|
-
llm?: (messages: Message[]) => Promise<string>;
|
|
49
|
+
interface RedashifyOptions extends LlmOptions {
|
|
64
50
|
/** Characters of context on each side of a dash (default: 50) */
|
|
65
51
|
contextSize?: number;
|
|
66
52
|
/** Custom rules to prepend to the system prompt */
|
|
@@ -93,4 +79,4 @@ declare function extractDashes(text: string, contextSize?: number): DashContext[
|
|
|
93
79
|
*/
|
|
94
80
|
declare function buildMessages(contexts: readonly DashContext[], rules?: string): Message[];
|
|
95
81
|
|
|
96
|
-
export { type ApplyResult, type Correction, type DashChar, type DashContext, type
|
|
82
|
+
export { type ApplyResult, type Correction, type DashChar, type DashContext, type RedashifyOptions, type RedashifyResult, VALID_DASHES, buildMessages, extractDashes, redashify };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { LlmOptions, Message } from '@lexstyle/llm-client';
|
|
2
|
+
export { Message, Provider } from '@lexstyle/llm-client';
|
|
3
|
+
|
|
1
4
|
/** The valid dash characters, exported for documentation/reference */
|
|
2
5
|
declare const VALID_DASHES: readonly ["-", "–", "—"];
|
|
3
6
|
/** A single valid dash character: hyphen, en dash, or em dash */
|
|
@@ -42,25 +45,8 @@ interface RedashifyResult {
|
|
|
42
45
|
/** True if no changes were needed */
|
|
43
46
|
unchanged: boolean;
|
|
44
47
|
}
|
|
45
|
-
/** Chat message format for the LLM function */
|
|
46
|
-
interface Message {
|
|
47
|
-
role: "system" | "user" | "assistant";
|
|
48
|
-
content: string;
|
|
49
|
-
}
|
|
50
|
-
/** Known providers with built-in base URL mapping */
|
|
51
|
-
type Provider = "openai" | "anthropic" | "gemini" | "groq" | "together" | "mistral" | "openrouter" | "xai" | "deepseek";
|
|
52
48
|
/** Options for redashify */
|
|
53
|
-
interface RedashifyOptions {
|
|
54
|
-
/** API key for the LLM provider */
|
|
55
|
-
apiKey?: string;
|
|
56
|
-
/** LLM provider name (e.g. "openai", "groq", "together"). Maps to a known base URL. */
|
|
57
|
-
provider?: Provider;
|
|
58
|
-
/** Model name (e.g. "gpt-4o-mini", "llama-3.3-70b-versatile"). Required when using apiKey without a known provider default. */
|
|
59
|
-
model?: string;
|
|
60
|
-
/** Custom base URL for OpenAI-compatible APIs. Overrides provider mapping. */
|
|
61
|
-
baseURL?: string;
|
|
62
|
-
/** Custom LLM function: receives messages, returns the raw text response. Overrides apiKey/provider/model. */
|
|
63
|
-
llm?: (messages: Message[]) => Promise<string>;
|
|
49
|
+
interface RedashifyOptions extends LlmOptions {
|
|
64
50
|
/** Characters of context on each side of a dash (default: 50) */
|
|
65
51
|
contextSize?: number;
|
|
66
52
|
/** Custom rules to prepend to the system prompt */
|
|
@@ -93,4 +79,4 @@ declare function extractDashes(text: string, contextSize?: number): DashContext[
|
|
|
93
79
|
*/
|
|
94
80
|
declare function buildMessages(contexts: readonly DashContext[], rules?: string): Message[];
|
|
95
81
|
|
|
96
|
-
export { type ApplyResult, type Correction, type DashChar, type DashContext, type
|
|
82
|
+
export { type ApplyResult, type Correction, type DashChar, type DashContext, type RedashifyOptions, type RedashifyResult, VALID_DASHES, buildMessages, extractDashes, redashify };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// src/core.ts
|
|
2
|
+
import { resolveLlm } from "@lexstyle/llm-client";
|
|
3
|
+
|
|
1
4
|
// src/extractor.ts
|
|
2
5
|
var DASH_RE = /---+|--|\u2014|\u2013|-/g;
|
|
3
6
|
function extractDashes(text, contextSize = 50) {
|
|
@@ -52,83 +55,6 @@ Format: [{"id":0,"dash":"-"},{"id":1,"dash":"\u2013"}]`;
|
|
|
52
55
|
];
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
// src/llmClient.ts
|
|
56
|
-
import OpenAI from "openai";
|
|
57
|
-
var PROVIDER_CONFIGS = {
|
|
58
|
-
openai: { baseURL: "https://api.openai.com/v1", defaultModel: "gpt-4o-mini" },
|
|
59
|
-
anthropic: { baseURL: "https://api.anthropic.com", defaultModel: "claude-haiku-4-5-20251001" },
|
|
60
|
-
gemini: { baseURL: "https://generativelanguage.googleapis.com/v1beta/openai", defaultModel: "gemini-2.0-flash" },
|
|
61
|
-
groq: { baseURL: "https://api.groq.com/openai/v1", defaultModel: "llama-3.3-70b-versatile" },
|
|
62
|
-
together: { baseURL: "https://api.together.xyz/v1", defaultModel: "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo" },
|
|
63
|
-
mistral: { baseURL: "https://api.mistral.ai/v1", defaultModel: "mistral-small-latest" },
|
|
64
|
-
openrouter: { baseURL: "https://openrouter.ai/api/v1", defaultModel: "" },
|
|
65
|
-
xai: { baseURL: "https://api.x.ai/v1", defaultModel: "grok-3-mini-fast" },
|
|
66
|
-
deepseek: { baseURL: "https://api.deepseek.com", defaultModel: "deepseek-chat" }
|
|
67
|
-
};
|
|
68
|
-
function getProviderConfig(provider) {
|
|
69
|
-
if (!(provider in PROVIDER_CONFIGS)) {
|
|
70
|
-
const valid = Object.keys(PROVIDER_CONFIGS).join(", ");
|
|
71
|
-
throw new Error(`Unknown provider "${provider}". Valid providers: ${valid}`);
|
|
72
|
-
}
|
|
73
|
-
return PROVIDER_CONFIGS[provider];
|
|
74
|
-
}
|
|
75
|
-
async function callAnthropic(messages, apiKey, model, baseURL) {
|
|
76
|
-
const resolvedBaseURL = (baseURL ?? PROVIDER_CONFIGS.anthropic.baseURL).replace(/\/+$/, "").replace(/\/v1$/i, "");
|
|
77
|
-
const url = `${resolvedBaseURL}/v1/messages`;
|
|
78
|
-
const systemMsg = messages.find((m) => m.role === "system");
|
|
79
|
-
const nonSystemMsgs = messages.filter((m) => m.role !== "system");
|
|
80
|
-
const body = {
|
|
81
|
-
model,
|
|
82
|
-
max_tokens: 4096,
|
|
83
|
-
messages: nonSystemMsgs.map((m) => ({ role: m.role, content: m.content }))
|
|
84
|
-
};
|
|
85
|
-
if (systemMsg) {
|
|
86
|
-
body.system = systemMsg.content;
|
|
87
|
-
}
|
|
88
|
-
const res = await fetch(url, {
|
|
89
|
-
method: "POST",
|
|
90
|
-
headers: {
|
|
91
|
-
"content-type": "application/json",
|
|
92
|
-
"x-api-key": apiKey,
|
|
93
|
-
"anthropic-version": "2023-06-01"
|
|
94
|
-
},
|
|
95
|
-
body: JSON.stringify(body)
|
|
96
|
-
});
|
|
97
|
-
if (!res.ok) {
|
|
98
|
-
const text = await res.text();
|
|
99
|
-
throw new Error(`Anthropic API error (${res.status}): ${text}`);
|
|
100
|
-
}
|
|
101
|
-
const data = await res.json();
|
|
102
|
-
const textBlock = data.content?.find((b) => b.type === "text");
|
|
103
|
-
if (!textBlock?.text) {
|
|
104
|
-
throw new Error("Anthropic returned an empty response");
|
|
105
|
-
}
|
|
106
|
-
return textBlock.text;
|
|
107
|
-
}
|
|
108
|
-
async function callOpenAICompatible(messages, apiKey, model, baseURL) {
|
|
109
|
-
const client = new OpenAI({
|
|
110
|
-
apiKey,
|
|
111
|
-
...baseURL ? { baseURL } : {}
|
|
112
|
-
});
|
|
113
|
-
const response = await client.chat.completions.create({
|
|
114
|
-
model,
|
|
115
|
-
messages,
|
|
116
|
-
temperature: 0
|
|
117
|
-
});
|
|
118
|
-
const content = response.choices[0]?.message?.content;
|
|
119
|
-
if (!content) {
|
|
120
|
-
throw new Error("LLM returned an empty response");
|
|
121
|
-
}
|
|
122
|
-
return content;
|
|
123
|
-
}
|
|
124
|
-
async function callLLM(messages, apiKey, model, provider, baseURL) {
|
|
125
|
-
if (provider === "anthropic") {
|
|
126
|
-
return callAnthropic(messages, apiKey, model, baseURL);
|
|
127
|
-
}
|
|
128
|
-
const resolvedBaseURL = baseURL ?? (provider ? PROVIDER_CONFIGS[provider].baseURL : void 0);
|
|
129
|
-
return callOpenAICompatible(messages, apiKey, model, resolvedBaseURL);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
58
|
// src/types.ts
|
|
133
59
|
var VALID_DASHES = Object.freeze(["-", "\u2013", "\u2014"]);
|
|
134
60
|
var VALID_DASH_SET = new Set(VALID_DASHES);
|
|
@@ -239,24 +165,6 @@ function requireInt(value, name, min) {
|
|
|
239
165
|
throw new Error(`Invalid ${name}: ${value}. Must be a finite integer >= ${min}.`);
|
|
240
166
|
}
|
|
241
167
|
}
|
|
242
|
-
function resolveLlm(options) {
|
|
243
|
-
if (options.llm) {
|
|
244
|
-
if (typeof options.llm !== "function") {
|
|
245
|
-
throw new Error("`llm` option must be a function");
|
|
246
|
-
}
|
|
247
|
-
return options.llm;
|
|
248
|
-
}
|
|
249
|
-
if (options.apiKey) {
|
|
250
|
-
const providerConfig = options.provider ? getProviderConfig(options.provider) : void 0;
|
|
251
|
-
const model = options.model ?? providerConfig?.defaultModel;
|
|
252
|
-
if (!model) {
|
|
253
|
-
throw new Error("redashify requires `model` when using `apiKey` (or use a `provider` with a default model)");
|
|
254
|
-
}
|
|
255
|
-
const { apiKey, provider, baseURL } = options;
|
|
256
|
-
return (messages) => callLLM(messages, apiKey, model, provider, baseURL);
|
|
257
|
-
}
|
|
258
|
-
throw new Error("redashify requires either `apiKey` + `model`, `apiKey` + `provider`, or `llm` option");
|
|
259
|
-
}
|
|
260
168
|
function validateBatchIds(corrections, expectedIds) {
|
|
261
169
|
for (const { id } of corrections) {
|
|
262
170
|
if (!expectedIds.has(id)) {
|
|
@@ -277,7 +185,7 @@ async function redashify(text, options) {
|
|
|
277
185
|
requireInt(batchSize, "batchSize", 1);
|
|
278
186
|
const contextSize = options.contextSize ?? 50;
|
|
279
187
|
requireInt(contextSize, "contextSize", 0);
|
|
280
|
-
const llmFn = resolveLlm(options);
|
|
188
|
+
const llmFn = resolveLlm(options, "redashify");
|
|
281
189
|
const contexts = extractDashes(text, contextSize);
|
|
282
190
|
if (contexts.length === 0) {
|
|
283
191
|
return { text, corrections: [], unchanged: true };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "redashify",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Context-aware dash correction powered by LLMs",
|
|
5
5
|
"author": "Haihang Wang",
|
|
6
6
|
"type": "module",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"url": "https://github.com/hangingahaw/redashify/issues"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"
|
|
57
|
+
"@lexstyle/llm-client": "^0.1.0"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"tsup": "^8.0.0",
|