promptopskit 0.9.0 → 0.9.2
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 +19 -6
- package/dist/{chunk-NS6OTKY2.js → chunk-6ICAKKV3.js} +81 -22
- package/dist/{chunk-NS6OTKY2.js.map → chunk-6ICAKKV3.js.map} +1 -1
- package/dist/{chunk-FJ3D76IV.js → chunk-A2VPKL4X.js} +2 -2
- package/dist/{chunk-SVNQNMMV.js → chunk-CGBEKODU.js} +2 -2
- package/dist/{chunk-Q67E2GGD.js → chunk-DA2NSBIN.js} +2 -2
- package/dist/{chunk-AAQNCAVA.js → chunk-DAJMCV4F.js} +3 -3
- package/dist/{chunk-E2AIIPQC.js → chunk-XSSET4QN.js} +2 -2
- package/dist/{chunk-W6XHGSPJ.js → chunk-YLJGWVZ6.js} +3 -3
- package/dist/index.cjs +80 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +7 -7
- package/dist/providers/anthropic.cjs +80 -21
- package/dist/providers/anthropic.cjs.map +1 -1
- package/dist/providers/anthropic.js +2 -2
- package/dist/providers/gemini.cjs +80 -21
- package/dist/providers/gemini.cjs.map +1 -1
- package/dist/providers/gemini.js +2 -2
- package/dist/providers/llmasaservice.cjs +80 -21
- package/dist/providers/llmasaservice.cjs.map +1 -1
- package/dist/providers/llmasaservice.js +3 -3
- package/dist/providers/openai-responses.cjs +80 -21
- package/dist/providers/openai-responses.cjs.map +1 -1
- package/dist/providers/openai-responses.js +2 -2
- package/dist/providers/openai.cjs +80 -21
- package/dist/providers/openai.cjs.map +1 -1
- package/dist/providers/openai.js +2 -2
- package/dist/providers/openrouter.cjs +80 -21
- package/dist/providers/openrouter.cjs.map +1 -1
- package/dist/providers/openrouter.js +3 -3
- package/package.json +1 -1
- /package/dist/{chunk-FJ3D76IV.js.map → chunk-A2VPKL4X.js.map} +0 -0
- /package/dist/{chunk-SVNQNMMV.js.map → chunk-CGBEKODU.js.map} +0 -0
- /package/dist/{chunk-Q67E2GGD.js.map → chunk-DA2NSBIN.js.map} +0 -0
- /package/dist/{chunk-AAQNCAVA.js.map → chunk-DAJMCV4F.js.map} +0 -0
- /package/dist/{chunk-E2AIIPQC.js.map → chunk-XSSET4QN.js.map} +0 -0
- /package/dist/{chunk-W6XHGSPJ.js.map → chunk-YLJGWVZ6.js.map} +0 -0
package/README.md
CHANGED
|
@@ -5,17 +5,30 @@
|
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
[](https://nodejs.org)
|
|
7
7
|
|
|
8
|
-
**
|
|
8
|
+
**Prompts are becoming production code. Manage them that way.**
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
AI features often start with a few prompt strings. Then model settings, tools, provider quirks, context limits, environment overrides, tests, and customer-specific behavior start spreading across the codebase.
|
|
11
11
|
|
|
12
|
-
Keep prompts, model settings, tools, input validation, shared instructions, environment overrides, and tests together in Markdown files that live in Git and ship with your app.
|
|
12
|
+
PromptOpsKit is an open-source toolkit for turning hardcoded AI prompts into versioned, tested application assets. Keep prompts, model settings, tools, input validation, shared instructions, environment overrides, and tests together in Markdown files that live in Git and ship with your app.
|
|
13
|
+
|
|
14
|
+
No hosted dashboard. No gateway required. No vendor lock-in. Render provider-ready request bodies while keeping your SDK, auth, routing, retries, observability, and billing.
|
|
13
15
|
|
|
14
16
|
PromptOpsKit is not a prompt dashboard, LLM gateway, or hosted runtime service. It is the repo-native layer between scattered prompt strings and production AI calls.
|
|
15
17
|
|
|
18
|
+
## Where this fits in the AI production stack
|
|
19
|
+
|
|
20
|
+
PromptOpsKit handles the open-source prompt asset layer: prompts, model settings, tools, input rules, overrides, and tests in Git.
|
|
21
|
+
|
|
22
|
+
As AI features grow, adjacent production concerns usually appear:
|
|
23
|
+
|
|
24
|
+
- **Provider operations** — routing, caching, cost controls, customer attribution, and gateway reliability. See LLMAsAService.
|
|
25
|
+
- **Customer usage and billing** — usage metering, entitlements, limits, alerts, and usage-based billing. See UsageTap.
|
|
26
|
+
|
|
27
|
+
PromptOpsKit does not require either service. It keeps the prompt layer repo-native and transport-light so teams can adopt the rest of their AI production stack when they need it.
|
|
28
|
+
|
|
16
29
|
## Why PromptOpsKit?
|
|
17
30
|
|
|
18
|
-
|
|
31
|
+
When prototypes become real product features, prompt glue is hard to review and easy to drift:
|
|
19
32
|
|
|
20
33
|
- Prompt strings live inline in code
|
|
21
34
|
- Model config and tools drift in separate files
|
|
@@ -23,7 +36,7 @@ From scattered prompt glue:
|
|
|
23
36
|
- Environment logic hides in if/else branches
|
|
24
37
|
- Testing is ad hoc and hard to review
|
|
25
38
|
|
|
26
|
-
|
|
39
|
+
PromptOpsKit turns that behavior into one reviewable asset:
|
|
27
40
|
|
|
28
41
|
- Prompt, model, tools, and input rules live together
|
|
29
42
|
- `includes` and `defaults.md` avoid copy-paste drift
|
|
@@ -279,7 +292,7 @@ cache:
|
|
|
279
292
|
retention: 24h
|
|
280
293
|
```
|
|
281
294
|
|
|
282
|
-
At render time, pass the caller-owned API key. PromptOpsKit calls `POST https://api.thetokencompany.com/v1/compress` directly with `fetch`; no TheTokenCompany SDK is required.
|
|
295
|
+
At render time, pass the caller-owned API key. PromptOpsKit calls `POST https://api.thetokencompany.com/v1/compress` directly with `fetch`; no TheTokenCompany SDK is required. If credentials are unavailable or the backend call fails, PromptOpsKit preserves the original prompt text, returns a `POK057` warning in `warnings`, and reports zero token savings with matching input/output token counts. Library rendering does not log this fallback to the console.
|
|
283
296
|
|
|
284
297
|
```typescript
|
|
285
298
|
const result = await kit.renderPrompt({
|
|
@@ -1632,6 +1632,7 @@ async function applyPromptCompressionForRender(asset, runtime) {
|
|
|
1632
1632
|
aggressiveness: theTokenCompanyConfig?.aggressiveness
|
|
1633
1633
|
});
|
|
1634
1634
|
promptTemplate = result.output;
|
|
1635
|
+
warnings.push(...result.warnings ?? []);
|
|
1635
1636
|
compression.push({
|
|
1636
1637
|
provider: "thetokencompany",
|
|
1637
1638
|
model,
|
|
@@ -1697,39 +1698,97 @@ function reportHeuristicCompressionWarnings2(warnings, compressionWarnings, scop
|
|
|
1697
1698
|
async function compressWithTheTokenCompany(input, options) {
|
|
1698
1699
|
const apiKey = options.apiKey ?? getEnv("THETOKENCOMPANY_API_KEY") ?? getEnv("TTC_API_KEY");
|
|
1699
1700
|
if (!apiKey) {
|
|
1700
|
-
|
|
1701
|
-
|
|
1701
|
+
return createTheTokenCompanyFallback(
|
|
1702
|
+
input,
|
|
1703
|
+
"no API key was provided"
|
|
1702
1704
|
);
|
|
1703
1705
|
}
|
|
1704
1706
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
1705
1707
|
if (!fetchImpl) {
|
|
1706
|
-
|
|
1708
|
+
return createTheTokenCompanyFallback(
|
|
1709
|
+
input,
|
|
1710
|
+
"fetch is unavailable in this runtime"
|
|
1711
|
+
);
|
|
1707
1712
|
}
|
|
1708
1713
|
const baseURL = (options.baseURL ?? THETOKENCOMPANY_DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
1709
1714
|
const compressionSettings = options.aggressiveness === void 0 ? void 0 : { aggressiveness: options.aggressiveness };
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1715
|
+
let response;
|
|
1716
|
+
try {
|
|
1717
|
+
response = await fetchImpl(`${baseURL}/v1/compress`, {
|
|
1718
|
+
method: "POST",
|
|
1719
|
+
headers: {
|
|
1720
|
+
Authorization: `Bearer ${apiKey}`,
|
|
1721
|
+
"Content-Type": "application/json"
|
|
1722
|
+
},
|
|
1723
|
+
body: JSON.stringify({
|
|
1724
|
+
model: options.model,
|
|
1725
|
+
input,
|
|
1726
|
+
...compressionSettings ? { compression_settings: compressionSettings } : {}
|
|
1727
|
+
})
|
|
1728
|
+
});
|
|
1729
|
+
} catch (error) {
|
|
1730
|
+
return createTheTokenCompanyFallback(
|
|
1718
1731
|
input,
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
}
|
|
1732
|
+
`request failed: ${toErrorMessage(error)}`
|
|
1733
|
+
);
|
|
1734
|
+
}
|
|
1722
1735
|
if (!response.ok) {
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
`
|
|
1736
|
+
return createTheTokenCompanyFallback(
|
|
1737
|
+
input,
|
|
1738
|
+
`service returned HTTP ${response.status}`
|
|
1739
|
+
);
|
|
1740
|
+
}
|
|
1741
|
+
let data;
|
|
1742
|
+
try {
|
|
1743
|
+
data = await response.json();
|
|
1744
|
+
} catch (error) {
|
|
1745
|
+
return createTheTokenCompanyFallback(
|
|
1746
|
+
input,
|
|
1747
|
+
`response body was not valid JSON: ${toErrorMessage(error)}`
|
|
1726
1748
|
);
|
|
1727
1749
|
}
|
|
1728
|
-
const
|
|
1729
|
-
if (
|
|
1730
|
-
|
|
1750
|
+
const normalized = normalizeTheTokenCompanyCompressResponse(data);
|
|
1751
|
+
if (!normalized) {
|
|
1752
|
+
return createTheTokenCompanyFallback(
|
|
1753
|
+
input,
|
|
1754
|
+
"response payload was invalid"
|
|
1755
|
+
);
|
|
1731
1756
|
}
|
|
1732
|
-
return
|
|
1757
|
+
return normalized;
|
|
1758
|
+
}
|
|
1759
|
+
function createTheTokenCompanyFallback(input, reason) {
|
|
1760
|
+
const tokens = estimateHeuristicTokens(input);
|
|
1761
|
+
return {
|
|
1762
|
+
output: input,
|
|
1763
|
+
output_tokens: tokens,
|
|
1764
|
+
input_tokens: tokens,
|
|
1765
|
+
tokens_saved: 0,
|
|
1766
|
+
compression_ratio: tokens === 0 ? 0 : 1,
|
|
1767
|
+
warnings: [
|
|
1768
|
+
`POK057: TheTokenCompany compression skipped; using uncompressed prompt with zero token savings (${reason}).`
|
|
1769
|
+
]
|
|
1770
|
+
};
|
|
1771
|
+
}
|
|
1772
|
+
function toErrorMessage(error) {
|
|
1773
|
+
return error instanceof Error && error.message ? error.message : "unknown error";
|
|
1774
|
+
}
|
|
1775
|
+
function normalizeTheTokenCompanyCompressResponse(data) {
|
|
1776
|
+
if (typeof data.output !== "string" || typeof data.output_tokens !== "number") {
|
|
1777
|
+
return void 0;
|
|
1778
|
+
}
|
|
1779
|
+
const inputTokens = typeof data.input_tokens === "number" ? data.input_tokens : data.original_input_tokens;
|
|
1780
|
+
if (typeof inputTokens !== "number") {
|
|
1781
|
+
return void 0;
|
|
1782
|
+
}
|
|
1783
|
+
const tokensSaved = typeof data.tokens_saved === "number" ? data.tokens_saved : inputTokens - data.output_tokens;
|
|
1784
|
+
const compressionRatio = typeof data.compression_ratio === "number" ? data.compression_ratio : data.output_tokens === 0 ? 0 : inputTokens / data.output_tokens;
|
|
1785
|
+
return {
|
|
1786
|
+
output: data.output,
|
|
1787
|
+
output_tokens: data.output_tokens,
|
|
1788
|
+
input_tokens: inputTokens,
|
|
1789
|
+
tokens_saved: tokensSaved,
|
|
1790
|
+
compression_ratio: compressionRatio
|
|
1791
|
+
};
|
|
1733
1792
|
}
|
|
1734
1793
|
function getEnv(name) {
|
|
1735
1794
|
if (typeof process === "undefined") {
|
|
@@ -1838,4 +1897,4 @@ export {
|
|
|
1838
1897
|
withPromptInputSupport,
|
|
1839
1898
|
applyRawProviderBody
|
|
1840
1899
|
};
|
|
1841
|
-
//# sourceMappingURL=chunk-
|
|
1900
|
+
//# sourceMappingURL=chunk-6ICAKKV3.js.map
|