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.
Files changed (37) hide show
  1. package/README.md +19 -6
  2. package/dist/{chunk-NS6OTKY2.js → chunk-6ICAKKV3.js} +81 -22
  3. package/dist/{chunk-NS6OTKY2.js.map → chunk-6ICAKKV3.js.map} +1 -1
  4. package/dist/{chunk-FJ3D76IV.js → chunk-A2VPKL4X.js} +2 -2
  5. package/dist/{chunk-SVNQNMMV.js → chunk-CGBEKODU.js} +2 -2
  6. package/dist/{chunk-Q67E2GGD.js → chunk-DA2NSBIN.js} +2 -2
  7. package/dist/{chunk-AAQNCAVA.js → chunk-DAJMCV4F.js} +3 -3
  8. package/dist/{chunk-E2AIIPQC.js → chunk-XSSET4QN.js} +2 -2
  9. package/dist/{chunk-W6XHGSPJ.js → chunk-YLJGWVZ6.js} +3 -3
  10. package/dist/index.cjs +80 -21
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.js +7 -7
  13. package/dist/providers/anthropic.cjs +80 -21
  14. package/dist/providers/anthropic.cjs.map +1 -1
  15. package/dist/providers/anthropic.js +2 -2
  16. package/dist/providers/gemini.cjs +80 -21
  17. package/dist/providers/gemini.cjs.map +1 -1
  18. package/dist/providers/gemini.js +2 -2
  19. package/dist/providers/llmasaservice.cjs +80 -21
  20. package/dist/providers/llmasaservice.cjs.map +1 -1
  21. package/dist/providers/llmasaservice.js +3 -3
  22. package/dist/providers/openai-responses.cjs +80 -21
  23. package/dist/providers/openai-responses.cjs.map +1 -1
  24. package/dist/providers/openai-responses.js +2 -2
  25. package/dist/providers/openai.cjs +80 -21
  26. package/dist/providers/openai.cjs.map +1 -1
  27. package/dist/providers/openai.js +2 -2
  28. package/dist/providers/openrouter.cjs +80 -21
  29. package/dist/providers/openrouter.cjs.map +1 -1
  30. package/dist/providers/openrouter.js +3 -3
  31. package/package.json +1 -1
  32. /package/dist/{chunk-FJ3D76IV.js.map → chunk-A2VPKL4X.js.map} +0 -0
  33. /package/dist/{chunk-SVNQNMMV.js.map → chunk-CGBEKODU.js.map} +0 -0
  34. /package/dist/{chunk-Q67E2GGD.js.map → chunk-DA2NSBIN.js.map} +0 -0
  35. /package/dist/{chunk-AAQNCAVA.js.map → chunk-DAJMCV4F.js.map} +0 -0
  36. /package/dist/{chunk-E2AIIPQC.js.map → chunk-XSSET4QN.js.map} +0 -0
  37. /package/dist/{chunk-W6XHGSPJ.js.map → chunk-YLJGWVZ6.js.map} +0 -0
package/README.md CHANGED
@@ -5,17 +5,30 @@
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
6
  [![Node.js](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](https://nodejs.org)
7
7
 
8
- **Turn hardcoded AI prompts into versioned, tested application assets.**
8
+ **Prompts are becoming production code. Manage them that way.**
9
9
 
10
- Your prompts are already in Git. PromptOpsKit makes them manageable.
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. Render provider-ready request bodies without giving up your SDK, gateway, auth, retries, routing, observability, or billing.
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
- From scattered prompt glue:
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
- To one reviewable asset:
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
- throw new Error(
1701
- "TheTokenCompany compression is enabled, but no API key was provided. Pass theTokenCompany.apiKey to renderPrompt() or set THETOKENCOMPANY_API_KEY."
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
- throw new Error("TheTokenCompany compression requires a runtime with fetch support.");
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
- const response = await fetchImpl(`${baseURL}/v1/compress`, {
1711
- method: "POST",
1712
- headers: {
1713
- Authorization: `Bearer ${apiKey}`,
1714
- "Content-Type": "application/json"
1715
- },
1716
- body: JSON.stringify({
1717
- model: options.model,
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
- ...compressionSettings ? { compression_settings: compressionSettings } : {}
1720
- })
1721
- });
1732
+ `request failed: ${toErrorMessage(error)}`
1733
+ );
1734
+ }
1722
1735
  if (!response.ok) {
1723
- const body = await response.text().catch(() => "");
1724
- throw new Error(
1725
- `TheTokenCompany compression failed with HTTP ${response.status}` + (body ? `: ${body}` : ".")
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 data = await response.json();
1729
- if (typeof data.output !== "string" || typeof data.output_tokens !== "number" || typeof data.input_tokens !== "number" || typeof data.tokens_saved !== "number" || typeof data.compression_ratio !== "number") {
1730
- throw new Error("TheTokenCompany compression returned an invalid response payload.");
1750
+ const normalized = normalizeTheTokenCompanyCompressResponse(data);
1751
+ if (!normalized) {
1752
+ return createTheTokenCompanyFallback(
1753
+ input,
1754
+ "response payload was invalid"
1755
+ );
1731
1756
  }
1732
- return data;
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-NS6OTKY2.js.map
1900
+ //# sourceMappingURL=chunk-6ICAKKV3.js.map