promptloom 1.0.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/LICENSE +21 -0
- package/README.md +388 -0
- package/README.zh-CN.md +388 -0
- package/bin/cli.ts +275 -0
- package/dist/index.cjs +522 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +611 -0
- package/dist/index.d.ts +611 -0
- package/dist/index.js +476 -0
- package/dist/index.js.map +1 -0
- package/package.json +58 -0
- package/src/boundary.ts +85 -0
- package/src/compiler.test.ts +625 -0
- package/src/compiler.ts +315 -0
- package/src/index.ts +98 -0
- package/src/providers.ts +160 -0
- package/src/section.ts +103 -0
- package/src/tokens.ts +170 -0
- package/src/tool.ts +128 -0
- package/src/types.ts +214 -0
package/src/boundary.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* promptloom — Cache boundary splitting
|
|
3
|
+
*
|
|
4
|
+
* Implements Claude Code's cache boundary mechanism:
|
|
5
|
+
* - A sentinel string divides the prompt into static (cacheable) and dynamic zones
|
|
6
|
+
* - Content before the boundary gets `cacheScope: 'global'` (cross-org cache)
|
|
7
|
+
* - Content after gets `cacheScope: null` (session-specific)
|
|
8
|
+
*
|
|
9
|
+
* This directly maps to Claude API's `cache_control` field on text blocks.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { CacheBlock, CacheScope } from './types.ts'
|
|
13
|
+
|
|
14
|
+
/** The sentinel string used to mark the cache boundary */
|
|
15
|
+
export const CACHE_BOUNDARY = '__PROMPTLOOM_CACHE_BOUNDARY__'
|
|
16
|
+
|
|
17
|
+
export interface SplitOptions {
|
|
18
|
+
/** Cache scope for content before the boundary (default: 'global') */
|
|
19
|
+
staticScope?: CacheScope
|
|
20
|
+
/** Cache scope for content after the boundary (default: null) */
|
|
21
|
+
dynamicScope?: CacheScope
|
|
22
|
+
/** Fallback scope when no boundary is found (default: 'org') */
|
|
23
|
+
fallbackScope?: CacheScope
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Split a prompt string at the cache boundary into annotated blocks.
|
|
28
|
+
*
|
|
29
|
+
* Mirrors Claude Code's `splitSysPromptPrefix()`:
|
|
30
|
+
*
|
|
31
|
+
* - If boundary found:
|
|
32
|
+
* [static content → staticScope] + [dynamic content → dynamicScope]
|
|
33
|
+
*
|
|
34
|
+
* - If no boundary:
|
|
35
|
+
* [entire content → fallbackScope]
|
|
36
|
+
*/
|
|
37
|
+
export function splitAtBoundary(
|
|
38
|
+
prompt: string,
|
|
39
|
+
options: SplitOptions = {},
|
|
40
|
+
): CacheBlock[] {
|
|
41
|
+
const {
|
|
42
|
+
staticScope = 'global',
|
|
43
|
+
dynamicScope = null,
|
|
44
|
+
fallbackScope = 'org',
|
|
45
|
+
} = options
|
|
46
|
+
|
|
47
|
+
const boundaryIndex = prompt.indexOf(CACHE_BOUNDARY)
|
|
48
|
+
|
|
49
|
+
if (boundaryIndex === -1) {
|
|
50
|
+
// No boundary — single block with fallback scope
|
|
51
|
+
return prompt.trim()
|
|
52
|
+
? [{ text: prompt, cacheScope: fallbackScope }]
|
|
53
|
+
: []
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const before = prompt.slice(0, boundaryIndex).trim()
|
|
57
|
+
const after = prompt.slice(boundaryIndex + CACHE_BOUNDARY.length).trim()
|
|
58
|
+
|
|
59
|
+
const blocks: CacheBlock[] = []
|
|
60
|
+
if (before) {
|
|
61
|
+
blocks.push({ text: before, cacheScope: staticScope })
|
|
62
|
+
}
|
|
63
|
+
if (after) {
|
|
64
|
+
blocks.push({ text: after, cacheScope: dynamicScope })
|
|
65
|
+
}
|
|
66
|
+
return blocks
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Convert cache blocks to Anthropic API text block format.
|
|
71
|
+
*
|
|
72
|
+
* Mirrors Claude Code's `buildSystemPromptBlocks()`.
|
|
73
|
+
*/
|
|
74
|
+
export function toAnthropicBlocks(
|
|
75
|
+
blocks: CacheBlock[],
|
|
76
|
+
enableCaching = true,
|
|
77
|
+
): Array<{ type: 'text'; text: string; cache_control?: { type: 'ephemeral' } }> {
|
|
78
|
+
return blocks.map((block) => ({
|
|
79
|
+
type: 'text' as const,
|
|
80
|
+
text: block.text,
|
|
81
|
+
...(enableCaching && block.cacheScope !== null
|
|
82
|
+
? { cache_control: { type: 'ephemeral' as const } }
|
|
83
|
+
: {}),
|
|
84
|
+
}))
|
|
85
|
+
}
|