praxis-agent 0.34.0 → 0.35.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 -0
- package/dist/application/session-service.d.ts +0 -1
- package/dist/application/session-service.js +1619 -1617
- package/dist/application/subagent-service.js +27 -16
- package/dist/application/turn-lifecycle.d.ts +38 -0
- package/dist/application/turn-lifecycle.js +36 -0
- package/dist/cli/interactive.js +17 -7
- package/dist/cli/protocol.js +5 -2
- package/dist/cli/tui/claude-style.d.ts +5 -48
- package/dist/cli/tui/claude-style.js +19 -73
- package/dist/cli/tui/transcript-presentation.d.ts +89 -0
- package/dist/cli/tui/transcript-presentation.js +169 -0
- package/dist/cli/tui/transcript-viewport.d.ts +5 -34
- package/dist/cli/tui/transcript-viewport.js +639 -158
- package/dist/cli/tui/tui-view-model.d.ts +6 -2
- package/dist/cli/tui/tui-view-model.js +23 -6
- package/dist/compatibility/claude/context.d.ts +2 -2
- package/dist/compatibility/claude/context.js +2 -14
- package/dist/compatibility/claude/data-plane-adapter.d.ts +9 -0
- package/dist/compatibility/claude/data-plane-adapter.js +44 -0
- package/dist/compatibility/claude/paths.js +2 -2
- package/dist/compatibility/claude/shared-resources.d.ts +7 -38
- package/dist/compatibility/claude/transcript-codec.d.ts +21 -0
- package/dist/compatibility/claude/transcript-codec.js +512 -0
- package/dist/core/context.d.ts +25 -7
- package/dist/core/context.js +46 -0
- package/dist/core/prompt-composer.d.ts +8 -16
- package/dist/core/prompt-composer.js +65 -25
- package/dist/core/resources.d.ts +39 -0
- package/dist/core/resources.js +2 -0
- package/dist/core/runtime.d.ts +1 -1
- package/dist/core/session.d.ts +2 -0
- package/dist/core/session.js +5 -0
- package/dist/core/transcript-codec.d.ts +70 -0
- package/dist/core/transcript-codec.js +60 -0
- package/dist/core/transcript-event.d.ts +33 -0
- package/dist/core/transcript-event.js +198 -0
- package/dist/persistence/data-plane-adapter.d.ts +32 -0
- package/dist/persistence/data-plane-adapter.js +2 -0
- package/dist/persistence/data-plane.d.ts +4 -20
- package/dist/persistence/data-plane.js +10 -47
- package/dist/persistence/native-data-plane-adapter.d.ts +9 -0
- package/dist/persistence/native-data-plane-adapter.js +39 -0
- package/dist/persistence/native-resources.d.ts +4 -4
- package/dist/persistence/native-transcript-codec.d.ts +13 -0
- package/dist/persistence/native-transcript-codec.js +102 -0
- package/dist/tools/claude-user-message.d.ts +0 -1
- package/dist/tools/claude-user-message.js +0 -1
- package/package.json +6 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createContextSnapshot, } from './context.js';
|
|
1
2
|
const PRODUCT_POLICY = `# Praxis
|
|
2
3
|
|
|
3
4
|
You are Praxis, a local CLI coding agent. Work until the user's request is genuinely handled or a concrete blocker requires their input.
|
|
@@ -9,6 +10,8 @@ You are Praxis, a local CLI coding agent. Work until the user's request is genui
|
|
|
9
10
|
- Summarize or clear bulky intermediate results once their useful facts have been retained.
|
|
10
11
|
- Treat the context window as bounded: preserve decisions and evidence before reducing detail.
|
|
11
12
|
- Keep responses concise and use the user's language unless they request otherwise.`;
|
|
13
|
+
const BRIEF_OUTPUT_POLICY = 'When brief mode is enabled, SendUserMessage is the primary user-visible reply channel. Use it for the answer, progress checkpoints, and blockers. Set status to normal for a direct reply and proactive for an unsolicited update.';
|
|
14
|
+
const STRUCTURED_OUTPUT_POLICY = 'You MUST call StructuredOutput exactly once at the end with a value matching the requested JSON Schema.';
|
|
12
15
|
function baseSection(mode, content) {
|
|
13
16
|
if (mode === 'bare')
|
|
14
17
|
return undefined;
|
|
@@ -51,6 +54,52 @@ function normalizedSections(sections, group) {
|
|
|
51
54
|
return { ...section };
|
|
52
55
|
});
|
|
53
56
|
}
|
|
57
|
+
function turnSections(turn) {
|
|
58
|
+
if (!turn)
|
|
59
|
+
return [];
|
|
60
|
+
return [
|
|
61
|
+
...(turn.planMode?.trim()
|
|
62
|
+
? [
|
|
63
|
+
{
|
|
64
|
+
id: 'plan-mode',
|
|
65
|
+
content: turn.planMode,
|
|
66
|
+
placement: 'system',
|
|
67
|
+
stability: 'volatile',
|
|
68
|
+
},
|
|
69
|
+
]
|
|
70
|
+
: []),
|
|
71
|
+
...(turn.sessionMemory?.trim()
|
|
72
|
+
? [
|
|
73
|
+
{
|
|
74
|
+
id: 'session-memory',
|
|
75
|
+
content: turn.sessionMemory,
|
|
76
|
+
placement: 'system',
|
|
77
|
+
stability: 'volatile',
|
|
78
|
+
},
|
|
79
|
+
]
|
|
80
|
+
: []),
|
|
81
|
+
...(turn.briefOutput
|
|
82
|
+
? [
|
|
83
|
+
{
|
|
84
|
+
id: 'brief-output',
|
|
85
|
+
content: BRIEF_OUTPUT_POLICY,
|
|
86
|
+
placement: 'system',
|
|
87
|
+
stability: 'volatile',
|
|
88
|
+
},
|
|
89
|
+
]
|
|
90
|
+
: []),
|
|
91
|
+
...(turn.structuredOutput
|
|
92
|
+
? [
|
|
93
|
+
{
|
|
94
|
+
id: 'structured-output',
|
|
95
|
+
content: STRUCTURED_OUTPUT_POLICY,
|
|
96
|
+
placement: 'system',
|
|
97
|
+
stability: 'volatile',
|
|
98
|
+
},
|
|
99
|
+
]
|
|
100
|
+
: []),
|
|
101
|
+
];
|
|
102
|
+
}
|
|
54
103
|
export class PromptComposer {
|
|
55
104
|
compose(options) {
|
|
56
105
|
const base = baseSection(options.mode, options.baseSystemPrompt);
|
|
@@ -63,37 +112,28 @@ export class PromptComposer {
|
|
|
63
112
|
stability: 'session',
|
|
64
113
|
}
|
|
65
114
|
: undefined;
|
|
66
|
-
const tailSections = normalizedSections(options.tailSections ?? [], 'tailSections');
|
|
115
|
+
const tailSections = normalizedSections([...(options.tailSections ?? []), ...turnSections(options.turn)], 'tailSections');
|
|
67
116
|
const sections = [
|
|
68
117
|
...(base ? [base] : []),
|
|
69
118
|
...sessionSections,
|
|
70
119
|
...(append ? [append] : []),
|
|
71
120
|
...tailSections,
|
|
72
121
|
];
|
|
73
|
-
|
|
74
|
-
for (const section of sections) {
|
|
75
|
-
if (identities.has(section.id)) {
|
|
76
|
-
throw new Error(`Duplicate prompt section ${section.id}`);
|
|
77
|
-
}
|
|
78
|
-
identities.add(section.id);
|
|
79
|
-
}
|
|
80
|
-
const systemSections = sections.filter((section) => section.placement === 'system');
|
|
81
|
-
const firstVolatileSystemIndex = systemSections.findIndex((section) => section.stability === 'volatile');
|
|
82
|
-
const firstUserMessageContext = sections
|
|
83
|
-
.filter((section) => section.placement === 'first-user')
|
|
84
|
-
.map((section) => section.content)
|
|
85
|
-
.join('\n\n');
|
|
86
|
-
return {
|
|
87
|
-
sections,
|
|
88
|
-
systemMessages: systemSections.map((section) => ({
|
|
89
|
-
role: 'system',
|
|
90
|
-
content: section.content,
|
|
91
|
-
})),
|
|
92
|
-
stableSystemSectionCount: firstVolatileSystemIndex < 0
|
|
93
|
-
? systemSections.length
|
|
94
|
-
: firstVolatileSystemIndex,
|
|
95
|
-
...(firstUserMessageContext ? { firstUserMessageContext } : {}),
|
|
96
|
-
};
|
|
122
|
+
return createContextSnapshot(sections);
|
|
97
123
|
}
|
|
98
124
|
}
|
|
125
|
+
const defaultContextAssembler = {
|
|
126
|
+
async assemble(options = {}) {
|
|
127
|
+
return new PromptComposer().compose({
|
|
128
|
+
mode: options.mode ?? 'bare',
|
|
129
|
+
...(options.baseSystemPrompt === undefined
|
|
130
|
+
? {}
|
|
131
|
+
: { baseSystemPrompt: options.baseSystemPrompt }),
|
|
132
|
+
...(options.turn === undefined ? {} : { turn: options.turn }),
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
export async function assembleContextSnapshot(assembler, options = {}) {
|
|
137
|
+
return (assembler ?? defaultContextAssembler).assemble(options);
|
|
138
|
+
}
|
|
99
139
|
//# sourceMappingURL=prompt-composer.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type ResourceScope = 'local' | 'project' | 'user';
|
|
2
|
+
export interface TextResource {
|
|
3
|
+
path: string;
|
|
4
|
+
scope: ResourceScope;
|
|
5
|
+
content: string;
|
|
6
|
+
importedFrom?: string;
|
|
7
|
+
importRoot?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface JsonResource {
|
|
10
|
+
path: string;
|
|
11
|
+
scope: ResourceScope;
|
|
12
|
+
value: unknown;
|
|
13
|
+
plugin?: true;
|
|
14
|
+
pluginName?: string;
|
|
15
|
+
pluginSource?: string;
|
|
16
|
+
environment?: Readonly<Record<string, string>>;
|
|
17
|
+
sensitiveValues?: readonly string[];
|
|
18
|
+
}
|
|
19
|
+
export interface ContextResources {
|
|
20
|
+
instructions: TextResource[];
|
|
21
|
+
conditionalRules: ConditionalRule[];
|
|
22
|
+
memoryIndex: TextResource | null;
|
|
23
|
+
}
|
|
24
|
+
export interface ConditionalRule extends TextResource {
|
|
25
|
+
baseDirectory: string;
|
|
26
|
+
content: string;
|
|
27
|
+
globs: string[];
|
|
28
|
+
rawContent: string;
|
|
29
|
+
}
|
|
30
|
+
export interface SharedResources {
|
|
31
|
+
instructions: TextResource[];
|
|
32
|
+
memory: TextResource[];
|
|
33
|
+
skills: TextResource[];
|
|
34
|
+
commands: TextResource[];
|
|
35
|
+
agents: TextResource[];
|
|
36
|
+
settings: JsonResource[];
|
|
37
|
+
mcp: JsonResource[];
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=resources.d.ts.map
|
package/dist/core/runtime.d.ts
CHANGED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { TranscriptEvent } from './transcript-event.js';
|
|
2
|
+
export type TranscriptCodecDiagnostic = {
|
|
3
|
+
kind: 'unsupported-version';
|
|
4
|
+
lineNumber: number | null;
|
|
5
|
+
byteOffset: number;
|
|
6
|
+
message: string;
|
|
7
|
+
schemaVersion: string | number;
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'corrupt-line';
|
|
10
|
+
lineNumber: number | null;
|
|
11
|
+
byteOffset: number;
|
|
12
|
+
message: string;
|
|
13
|
+
schemaVersion?: string | number;
|
|
14
|
+
} | {
|
|
15
|
+
kind: 'unsupported-event';
|
|
16
|
+
lineNumber: number | null;
|
|
17
|
+
byteOffset: number;
|
|
18
|
+
message: string;
|
|
19
|
+
eventKind?: string;
|
|
20
|
+
};
|
|
21
|
+
export interface OpaquePreservationToken {
|
|
22
|
+
readonly __opaqueToken: unique symbol;
|
|
23
|
+
}
|
|
24
|
+
type TokenPayload = {
|
|
25
|
+
owner: symbol;
|
|
26
|
+
raw: string;
|
|
27
|
+
eventFingerprint: string;
|
|
28
|
+
};
|
|
29
|
+
export type PreservationTokenSource = {
|
|
30
|
+
owner: symbol;
|
|
31
|
+
raw: string;
|
|
32
|
+
event: TranscriptEvent;
|
|
33
|
+
};
|
|
34
|
+
export declare function createPreservationToken(owner: symbol, source: PreservationTokenSource): OpaquePreservationToken;
|
|
35
|
+
export declare function readPreservationToken(token: OpaquePreservationToken, owner: symbol): TokenPayload | null;
|
|
36
|
+
export interface DecodedTranscriptRecord {
|
|
37
|
+
readonly event: TranscriptEvent;
|
|
38
|
+
readonly preservation?: OpaquePreservationToken;
|
|
39
|
+
}
|
|
40
|
+
export type TranscriptLineResult = {
|
|
41
|
+
ok: true;
|
|
42
|
+
record: DecodedTranscriptRecord;
|
|
43
|
+
} | {
|
|
44
|
+
ok: false;
|
|
45
|
+
issue: TranscriptCodecDiagnostic;
|
|
46
|
+
};
|
|
47
|
+
export type TranscriptEncodeResult = {
|
|
48
|
+
ok: true;
|
|
49
|
+
line: string;
|
|
50
|
+
} | {
|
|
51
|
+
ok: false;
|
|
52
|
+
issue: TranscriptCodecDiagnostic;
|
|
53
|
+
};
|
|
54
|
+
export interface TranscriptDocumentResult {
|
|
55
|
+
readonly records: readonly DecodedTranscriptRecord[];
|
|
56
|
+
readonly issue: TranscriptCodecDiagnostic | null;
|
|
57
|
+
readonly validPrefixByteLength: number;
|
|
58
|
+
}
|
|
59
|
+
export interface TranscriptCodec {
|
|
60
|
+
readonly id: string;
|
|
61
|
+
readonly version: string | number;
|
|
62
|
+
readonly writeMode: 'read-only' | 'read-write';
|
|
63
|
+
decodeLine(line: string, lineNumber?: number, byteOffset?: number): TranscriptLineResult;
|
|
64
|
+
encodeLine(event: TranscriptEvent, preservation?: OpaquePreservationToken): TranscriptEncodeResult;
|
|
65
|
+
decodeDocument(source: string | Uint8Array): TranscriptDocumentResult;
|
|
66
|
+
}
|
|
67
|
+
export declare function diagnostic(kind: TranscriptCodecDiagnostic['kind'], message: string, byteOffset: number, lineNumber: number | null, extra?: Partial<TranscriptCodecDiagnostic>): TranscriptCodecDiagnostic;
|
|
68
|
+
export declare function decodeDocumentWith(codec: TranscriptCodec, source: string | Uint8Array): TranscriptDocumentResult;
|
|
69
|
+
export {};
|
|
70
|
+
//# sourceMappingURL=transcript-codec.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const tokenPayloads = new WeakMap();
|
|
2
|
+
export function createPreservationToken(owner, source) {
|
|
3
|
+
const token = Object.freeze({});
|
|
4
|
+
tokenPayloads.set(token, {
|
|
5
|
+
owner: source.owner,
|
|
6
|
+
raw: source.raw,
|
|
7
|
+
eventFingerprint: JSON.stringify(source.event),
|
|
8
|
+
});
|
|
9
|
+
return token;
|
|
10
|
+
}
|
|
11
|
+
export function readPreservationToken(token, owner) {
|
|
12
|
+
const payload = tokenPayloads.get(token);
|
|
13
|
+
return payload?.owner === owner ? payload : null;
|
|
14
|
+
}
|
|
15
|
+
export function diagnostic(kind, message, byteOffset, lineNumber, extra = {}) {
|
|
16
|
+
return {
|
|
17
|
+
kind,
|
|
18
|
+
message,
|
|
19
|
+
byteOffset,
|
|
20
|
+
lineNumber,
|
|
21
|
+
...extra,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function decodeDocumentWith(codec, source) {
|
|
25
|
+
const bytes = typeof source === 'string' ? new TextEncoder().encode(source) : source;
|
|
26
|
+
const lines = [];
|
|
27
|
+
let start = 0;
|
|
28
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
29
|
+
if (bytes[i] === 0x0a) {
|
|
30
|
+
lines.push({ bytes: bytes.subarray(start, i), terminatorBytes: 1 });
|
|
31
|
+
start = i + 1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (start < bytes.length) {
|
|
35
|
+
lines.push({ bytes: bytes.subarray(start), terminatorBytes: 0 });
|
|
36
|
+
}
|
|
37
|
+
const records = [];
|
|
38
|
+
let offset = 0;
|
|
39
|
+
for (const [index, sourceLine] of lines.entries()) {
|
|
40
|
+
const bytesLine = sourceLine.bytes;
|
|
41
|
+
let line;
|
|
42
|
+
try {
|
|
43
|
+
line = new TextDecoder('utf-8', { fatal: true }).decode(bytesLine);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return {
|
|
47
|
+
records,
|
|
48
|
+
issue: diagnostic('corrupt-line', 'Invalid UTF-8 transcript line', offset, index + 1),
|
|
49
|
+
validPrefixByteLength: offset,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const result = codec.decodeLine(line, index + 1, offset);
|
|
53
|
+
if (!result.ok)
|
|
54
|
+
return { records, issue: result.issue, validPrefixByteLength: offset };
|
|
55
|
+
records.push(result.record);
|
|
56
|
+
offset += bytesLine.length + sourceLine.terminatorBytes;
|
|
57
|
+
}
|
|
58
|
+
return { records, issue: null, validPrefixByteLength: offset };
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=transcript-codec.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ModelContentBlock, ModelDocument, ModelImage, ModelMessage, ModelTerminalReason } from './runtime.js';
|
|
2
|
+
export interface TranscriptEventIdentity {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly parentId: string | null;
|
|
5
|
+
readonly sessionId: string;
|
|
6
|
+
readonly timestamp: string;
|
|
7
|
+
}
|
|
8
|
+
export interface TranscriptMessagesEvent extends TranscriptEventIdentity {
|
|
9
|
+
readonly kind: 'messages';
|
|
10
|
+
readonly messages: readonly ModelMessage[];
|
|
11
|
+
readonly model?: string;
|
|
12
|
+
readonly terminalReason?: ModelTerminalReason;
|
|
13
|
+
}
|
|
14
|
+
export interface TranscriptContextBoundaryEvent extends TranscriptEventIdentity {
|
|
15
|
+
readonly kind: 'context-boundary';
|
|
16
|
+
readonly logicalParentId: string;
|
|
17
|
+
readonly trigger: 'auto' | 'manual';
|
|
18
|
+
readonly preTokens: number;
|
|
19
|
+
readonly postTokens: number;
|
|
20
|
+
readonly durationMs: number;
|
|
21
|
+
}
|
|
22
|
+
export interface TranscriptContextSummaryEvent extends TranscriptEventIdentity {
|
|
23
|
+
readonly kind: 'context-summary';
|
|
24
|
+
readonly summary: string;
|
|
25
|
+
}
|
|
26
|
+
export type TranscriptEvent = TranscriptMessagesEvent | TranscriptContextBoundaryEvent | TranscriptContextSummaryEvent;
|
|
27
|
+
export declare function isModelImage(value: unknown): value is ModelImage;
|
|
28
|
+
export declare function isModelDocument(value: unknown): value is ModelDocument;
|
|
29
|
+
export declare function isModelContentBlock(value: unknown): value is ModelContentBlock;
|
|
30
|
+
export declare function isTranscriptEvent(value: unknown): value is TranscriptEvent;
|
|
31
|
+
export declare function parseTranscriptEvent(value: unknown): TranscriptEvent;
|
|
32
|
+
export declare function validateTranscriptEvent(value: unknown): value is TranscriptEvent;
|
|
33
|
+
//# sourceMappingURL=transcript-event.d.ts.map
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
const terminalReasons = new Set([
|
|
2
|
+
'end_turn',
|
|
3
|
+
'tool_use',
|
|
4
|
+
'max_tokens',
|
|
5
|
+
'prompt_too_long',
|
|
6
|
+
]);
|
|
7
|
+
const imageTypes = new Set([
|
|
8
|
+
'image/png',
|
|
9
|
+
'image/jpeg',
|
|
10
|
+
'image/gif',
|
|
11
|
+
'image/webp',
|
|
12
|
+
]);
|
|
13
|
+
const documentTypes = new Set([
|
|
14
|
+
'application/pdf',
|
|
15
|
+
'text/plain',
|
|
16
|
+
'text/markdown',
|
|
17
|
+
'application/json',
|
|
18
|
+
]);
|
|
19
|
+
function isRecord(value) {
|
|
20
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
21
|
+
}
|
|
22
|
+
function isNonEmptyString(value) {
|
|
23
|
+
return typeof value === 'string' && value.length > 0;
|
|
24
|
+
}
|
|
25
|
+
function hasOnlyKeys(value, keys) {
|
|
26
|
+
return Object.keys(value).every((key) => keys.includes(key));
|
|
27
|
+
}
|
|
28
|
+
export function isModelImage(value) {
|
|
29
|
+
return (isRecord(value) &&
|
|
30
|
+
hasOnlyKeys(value, ['type', 'mediaType', 'data']) &&
|
|
31
|
+
value.type === 'image' &&
|
|
32
|
+
imageTypes.has(String(value.mediaType)) &&
|
|
33
|
+
isNonEmptyString(value.data));
|
|
34
|
+
}
|
|
35
|
+
export function isModelDocument(value) {
|
|
36
|
+
return (isRecord(value) &&
|
|
37
|
+
hasOnlyKeys(value, ['type', 'mediaType', 'data']) &&
|
|
38
|
+
value.type === 'document' &&
|
|
39
|
+
documentTypes.has(String(value.mediaType)) &&
|
|
40
|
+
isNonEmptyString(value.data));
|
|
41
|
+
}
|
|
42
|
+
function isModelMedia(value) {
|
|
43
|
+
return isModelImage(value) || isModelDocument(value);
|
|
44
|
+
}
|
|
45
|
+
export function isModelContentBlock(value) {
|
|
46
|
+
if (!isRecord(value))
|
|
47
|
+
return false;
|
|
48
|
+
if (value.type === 'text') {
|
|
49
|
+
return (hasOnlyKeys(value, ['type', 'text']) && typeof value.text === 'string');
|
|
50
|
+
}
|
|
51
|
+
return isModelMedia(value);
|
|
52
|
+
}
|
|
53
|
+
function isModelToolCall(value) {
|
|
54
|
+
return (isRecord(value) &&
|
|
55
|
+
hasOnlyKeys(value, ['id', 'name', 'input']) &&
|
|
56
|
+
isNonEmptyString(value.id) &&
|
|
57
|
+
isNonEmptyString(value.name) &&
|
|
58
|
+
isRecord(value.input));
|
|
59
|
+
}
|
|
60
|
+
function isModelThinkingBlock(value) {
|
|
61
|
+
return isRecord(value) && value.type === 'thinking'
|
|
62
|
+
? hasOnlyKeys(value, ['type', 'thinking', 'signature']) &&
|
|
63
|
+
typeof value.thinking === 'string' &&
|
|
64
|
+
isNonEmptyString(value.signature)
|
|
65
|
+
: isRecord(value) && value.type === 'redacted_thinking'
|
|
66
|
+
? hasOnlyKeys(value, ['type', 'data']) && isNonEmptyString(value.data)
|
|
67
|
+
: false;
|
|
68
|
+
}
|
|
69
|
+
function isModelMessage(value) {
|
|
70
|
+
if (!isRecord(value) || !isNonEmptyString(value.role))
|
|
71
|
+
return false;
|
|
72
|
+
if (value.role === 'system') {
|
|
73
|
+
return (hasOnlyKeys(value, ['role', 'content']) &&
|
|
74
|
+
typeof value.content === 'string');
|
|
75
|
+
}
|
|
76
|
+
if (value.role === 'user') {
|
|
77
|
+
return (hasOnlyKeys(value, [
|
|
78
|
+
'role',
|
|
79
|
+
'content',
|
|
80
|
+
'contentBlocks',
|
|
81
|
+
'images',
|
|
82
|
+
'documents',
|
|
83
|
+
]) &&
|
|
84
|
+
typeof value.content === 'string' &&
|
|
85
|
+
(!('contentBlocks' in value) ||
|
|
86
|
+
(Array.isArray(value.contentBlocks) &&
|
|
87
|
+
value.contentBlocks.every(isModelContentBlock))) &&
|
|
88
|
+
(!('images' in value) ||
|
|
89
|
+
(Array.isArray(value.images) && value.images.every(isModelImage))) &&
|
|
90
|
+
(!('documents' in value) ||
|
|
91
|
+
(Array.isArray(value.documents) &&
|
|
92
|
+
value.documents.every(isModelDocument))));
|
|
93
|
+
}
|
|
94
|
+
if (value.role === 'assistant') {
|
|
95
|
+
return (hasOnlyKeys(value, ['role', 'content', 'thinkingBlocks', 'toolCalls']) &&
|
|
96
|
+
typeof value.content === 'string' &&
|
|
97
|
+
(!('thinkingBlocks' in value) ||
|
|
98
|
+
(Array.isArray(value.thinkingBlocks) &&
|
|
99
|
+
value.thinkingBlocks.every(isModelThinkingBlock))) &&
|
|
100
|
+
(!('toolCalls' in value) ||
|
|
101
|
+
(Array.isArray(value.toolCalls) &&
|
|
102
|
+
value.toolCalls.every(isModelToolCall))));
|
|
103
|
+
}
|
|
104
|
+
return (value.role === 'tool' &&
|
|
105
|
+
hasOnlyKeys(value, [
|
|
106
|
+
'role',
|
|
107
|
+
'toolCallId',
|
|
108
|
+
'content',
|
|
109
|
+
'contentBlocks',
|
|
110
|
+
'images',
|
|
111
|
+
'documents',
|
|
112
|
+
'isError',
|
|
113
|
+
]) &&
|
|
114
|
+
isNonEmptyString(value.toolCallId) &&
|
|
115
|
+
typeof value.content === 'string' &&
|
|
116
|
+
typeof value.isError === 'boolean' &&
|
|
117
|
+
(!('contentBlocks' in value) ||
|
|
118
|
+
(Array.isArray(value.contentBlocks) &&
|
|
119
|
+
value.contentBlocks.every(isModelContentBlock))) &&
|
|
120
|
+
(!('images' in value) ||
|
|
121
|
+
(Array.isArray(value.images) && value.images.every(isModelImage))) &&
|
|
122
|
+
(!('documents' in value) ||
|
|
123
|
+
(Array.isArray(value.documents) &&
|
|
124
|
+
value.documents.every(isModelDocument))));
|
|
125
|
+
}
|
|
126
|
+
function hasValidIdentity(value) {
|
|
127
|
+
return (isNonEmptyString(value.id) &&
|
|
128
|
+
(value.parentId === null || isNonEmptyString(value.parentId)) &&
|
|
129
|
+
isNonEmptyString(value.sessionId) &&
|
|
130
|
+
typeof value.timestamp === 'string' &&
|
|
131
|
+
!Number.isNaN(Date.parse(value.timestamp)) &&
|
|
132
|
+
new Date(value.timestamp).toISOString() === value.timestamp);
|
|
133
|
+
}
|
|
134
|
+
function isNonNegativeNumber(value) {
|
|
135
|
+
return typeof value === 'number' && Number.isFinite(value) && value >= 0;
|
|
136
|
+
}
|
|
137
|
+
export function isTranscriptEvent(value) {
|
|
138
|
+
if (!isRecord(value) ||
|
|
139
|
+
!hasValidIdentity(value) ||
|
|
140
|
+
typeof value.kind !== 'string')
|
|
141
|
+
return false;
|
|
142
|
+
if (value.kind === 'messages') {
|
|
143
|
+
return (hasOnlyKeys(value, [
|
|
144
|
+
'kind',
|
|
145
|
+
'id',
|
|
146
|
+
'parentId',
|
|
147
|
+
'sessionId',
|
|
148
|
+
'timestamp',
|
|
149
|
+
'messages',
|
|
150
|
+
'model',
|
|
151
|
+
'terminalReason',
|
|
152
|
+
]) &&
|
|
153
|
+
Array.isArray(value.messages) &&
|
|
154
|
+
value.messages.length > 0 &&
|
|
155
|
+
value.messages.every(isModelMessage) &&
|
|
156
|
+
(!('model' in value) || isNonEmptyString(value.model)) &&
|
|
157
|
+
(!('terminalReason' in value) ||
|
|
158
|
+
terminalReasons.has(value.terminalReason)));
|
|
159
|
+
}
|
|
160
|
+
if (value.kind === 'context-boundary') {
|
|
161
|
+
return (hasOnlyKeys(value, [
|
|
162
|
+
'kind',
|
|
163
|
+
'id',
|
|
164
|
+
'parentId',
|
|
165
|
+
'sessionId',
|
|
166
|
+
'timestamp',
|
|
167
|
+
'logicalParentId',
|
|
168
|
+
'trigger',
|
|
169
|
+
'preTokens',
|
|
170
|
+
'postTokens',
|
|
171
|
+
'durationMs',
|
|
172
|
+
]) &&
|
|
173
|
+
isNonEmptyString(value.logicalParentId) &&
|
|
174
|
+
(value.trigger === 'auto' || value.trigger === 'manual') &&
|
|
175
|
+
isNonNegativeNumber(value.preTokens) &&
|
|
176
|
+
isNonNegativeNumber(value.postTokens) &&
|
|
177
|
+
isNonNegativeNumber(value.durationMs));
|
|
178
|
+
}
|
|
179
|
+
return (value.kind === 'context-summary' &&
|
|
180
|
+
hasOnlyKeys(value, [
|
|
181
|
+
'kind',
|
|
182
|
+
'id',
|
|
183
|
+
'parentId',
|
|
184
|
+
'sessionId',
|
|
185
|
+
'timestamp',
|
|
186
|
+
'summary',
|
|
187
|
+
]) &&
|
|
188
|
+
typeof value.summary === 'string');
|
|
189
|
+
}
|
|
190
|
+
export function parseTranscriptEvent(value) {
|
|
191
|
+
if (!isTranscriptEvent(value))
|
|
192
|
+
throw new Error('Invalid TranscriptEvent');
|
|
193
|
+
return value;
|
|
194
|
+
}
|
|
195
|
+
export function validateTranscriptEvent(value) {
|
|
196
|
+
return isTranscriptEvent(value);
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=transcript-event.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type DataPlane = 'native' | 'claude';
|
|
2
|
+
export interface DataPlaneRootOptions {
|
|
3
|
+
root?: string;
|
|
4
|
+
environment?: Readonly<Record<string, string | undefined>>;
|
|
5
|
+
homeDirectory?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface DataPlaneAdapterOptions extends DataPlaneRootOptions {
|
|
8
|
+
cwd: string;
|
|
9
|
+
sessionId: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ScheduledTaskFileOptions {
|
|
12
|
+
cwd: string;
|
|
13
|
+
root: string;
|
|
14
|
+
}
|
|
15
|
+
export interface DataPlanePaths {
|
|
16
|
+
dataPlane: DataPlane;
|
|
17
|
+
root: string;
|
|
18
|
+
projectRoot: string;
|
|
19
|
+
sessionFile: string;
|
|
20
|
+
taskRoot: string;
|
|
21
|
+
stateRoot: string;
|
|
22
|
+
/** Compatibility alias for callers that previously received `praxisRoot`. */
|
|
23
|
+
praxisRoot: string;
|
|
24
|
+
memoryRoot: string;
|
|
25
|
+
}
|
|
26
|
+
export interface DataPlaneAdapter {
|
|
27
|
+
readonly dataPlane: DataPlane;
|
|
28
|
+
resolveRoot(options: DataPlaneRootOptions): string;
|
|
29
|
+
resolvePaths(options: DataPlaneAdapterOptions): DataPlanePaths;
|
|
30
|
+
resolveScheduledTaskFile(options: ScheduledTaskFileOptions): string;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=data-plane-adapter.d.ts.map
|
|
@@ -1,29 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
import type { DataPlane, DataPlanePaths, DataPlaneRootOptions } from './data-plane-adapter.js';
|
|
2
|
+
export type { DataPlane, DataPlanePaths } from './data-plane-adapter.js';
|
|
3
|
+
export interface ResolveDataPlaneOptions extends DataPlaneRootOptions {
|
|
3
4
|
dataPlane?: DataPlane;
|
|
4
5
|
cwd: string;
|
|
5
6
|
sessionId: string;
|
|
6
|
-
root?: string;
|
|
7
|
-
environment?: Readonly<Record<string, string | undefined>>;
|
|
8
|
-
homeDirectory?: string;
|
|
9
|
-
}
|
|
10
|
-
export interface DataPlanePaths {
|
|
11
|
-
dataPlane: DataPlane;
|
|
12
|
-
root: string;
|
|
13
|
-
projectRoot: string;
|
|
14
|
-
sessionFile: string;
|
|
15
|
-
taskRoot: string;
|
|
16
|
-
stateRoot: string;
|
|
17
|
-
/** Compatibility alias for callers that previously received `praxisRoot`. */
|
|
18
|
-
praxisRoot: string;
|
|
19
|
-
memoryRoot: string;
|
|
20
7
|
}
|
|
21
8
|
export declare function resolveDataPlane(environment?: Readonly<Record<string, string | undefined>>): DataPlane;
|
|
22
|
-
export declare function resolveDataPlaneRoot(options?: {
|
|
9
|
+
export declare function resolveDataPlaneRoot(options?: DataPlaneRootOptions & {
|
|
23
10
|
dataPlane?: DataPlane;
|
|
24
|
-
root?: string;
|
|
25
|
-
environment?: Readonly<Record<string, string | undefined>>;
|
|
26
|
-
homeDirectory?: string;
|
|
27
11
|
}): string;
|
|
28
12
|
export declare function resolveDataPlanePaths(options: ResolveDataPlaneOptions): DataPlanePaths;
|
|
29
13
|
export declare function resolveScheduledTaskFile(options: {
|