@pugi/sdk 0.1.0-alpha.10
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 +29 -0
- package/dist/agent-contracts.d.ts +311 -0
- package/dist/agent-contracts.js +67 -0
- package/dist/audit-trace.d.ts +1161 -0
- package/dist/audit-trace.js +185 -0
- package/dist/device-flow.d.ts +98 -0
- package/dist/device-flow.js +55 -0
- package/dist/engine-adapter.d.ts +376 -0
- package/dist/engine-adapter.js +47 -0
- package/dist/engine-loop.d.ts +457 -0
- package/dist/engine-loop.js +342 -0
- package/dist/handoff.d.ts +605 -0
- package/dist/handoff.js +76 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +11 -0
- package/dist/mcp-schemas.d.ts +27 -0
- package/dist/mcp-schemas.js +11 -0
- package/dist/permission-rules.d.ts +65 -0
- package/dist/permission-rules.js +35 -0
- package/dist/subagent-contracts.d.ts +549 -0
- package/dist/subagent-contracts.js +230 -0
- package/dist/transport.d.ts +559 -0
- package/dist/transport.js +482 -0
- package/package.json +47 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { permissionDecisionSchema } from './permission-rules.js';
|
|
3
|
+
import { subagentIsolationSchema, subagentRoleSchema } from './subagent-contracts.js';
|
|
4
|
+
export const auditEventBaseSchema = z.object({
|
|
5
|
+
id: z.string().min(1),
|
|
6
|
+
sessionId: z.string().min(1),
|
|
7
|
+
timestamp: z.string().datetime(),
|
|
8
|
+
});
|
|
9
|
+
export const toolCallEventSchema = auditEventBaseSchema.extend({
|
|
10
|
+
type: z.literal('tool_call'),
|
|
11
|
+
tool: z.string().min(1),
|
|
12
|
+
inputSummary: z.string().min(1),
|
|
13
|
+
permissionDecision: permissionDecisionSchema.optional(),
|
|
14
|
+
});
|
|
15
|
+
export const toolResultEventSchema = auditEventBaseSchema.extend({
|
|
16
|
+
type: z.literal('tool_result'),
|
|
17
|
+
toolCallId: z.string().min(1),
|
|
18
|
+
status: z.enum(['success', 'error', 'cancelled']),
|
|
19
|
+
outputSummary: z.string().min(1),
|
|
20
|
+
outputRef: z.string().min(1).optional(),
|
|
21
|
+
});
|
|
22
|
+
export const fileMutationEventSchema = auditEventBaseSchema.extend({
|
|
23
|
+
type: z.literal('file_mutation'),
|
|
24
|
+
toolCallId: z.string().min(1),
|
|
25
|
+
path: z.string().min(1),
|
|
26
|
+
operation: z.enum(['create', 'update', 'delete', 'move']),
|
|
27
|
+
beforeBlob: z.string().min(1).optional(),
|
|
28
|
+
afterBlob: z.string().min(1).optional(),
|
|
29
|
+
beforeHash: z.string().min(1).optional(),
|
|
30
|
+
afterHash: z.string().min(1).optional(),
|
|
31
|
+
diffRef: z.string().min(1).optional(),
|
|
32
|
+
});
|
|
33
|
+
export const sessionEventSchema = auditEventBaseSchema.extend({
|
|
34
|
+
type: z.literal('session'),
|
|
35
|
+
name: z.enum(['created', 'command_started', 'command_completed']),
|
|
36
|
+
command: z.string().min(1).optional(),
|
|
37
|
+
status: z.enum(['success', 'error']).optional(),
|
|
38
|
+
});
|
|
39
|
+
const hookEventName = z.enum([
|
|
40
|
+
'SessionStart',
|
|
41
|
+
'UserPromptSubmit',
|
|
42
|
+
'PreToolUse',
|
|
43
|
+
'PermissionRequest',
|
|
44
|
+
'PostToolUse',
|
|
45
|
+
'PostToolUseFailure',
|
|
46
|
+
'Stop',
|
|
47
|
+
'SessionEnd',
|
|
48
|
+
]);
|
|
49
|
+
export const hookInvokedEventSchema = auditEventBaseSchema.extend({
|
|
50
|
+
type: z.literal('hook.invoked'),
|
|
51
|
+
event: hookEventName,
|
|
52
|
+
matchSummary: z.string().min(1),
|
|
53
|
+
runSummary: z.string().min(1),
|
|
54
|
+
});
|
|
55
|
+
export const hookResultEventSchema = auditEventBaseSchema.extend({
|
|
56
|
+
type: z.literal('hook.result'),
|
|
57
|
+
event: hookEventName,
|
|
58
|
+
ok: z.boolean(),
|
|
59
|
+
exitCode: z.number().int(),
|
|
60
|
+
elapsedMs: z.number().int().nonnegative(),
|
|
61
|
+
stdoutLen: z.number().int().nonnegative(),
|
|
62
|
+
stderrLen: z.number().int().nonnegative(),
|
|
63
|
+
});
|
|
64
|
+
export const hookSkippedEventSchema = auditEventBaseSchema.extend({
|
|
65
|
+
type: z.literal('hook.skipped'),
|
|
66
|
+
event: hookEventName,
|
|
67
|
+
reason: z.enum(['dedup', 'no-match', 'untrusted-project']),
|
|
68
|
+
});
|
|
69
|
+
export const compactionTierSchema = z.enum([
|
|
70
|
+
'microcompact',
|
|
71
|
+
'cached_microcompact',
|
|
72
|
+
'reactive_summary',
|
|
73
|
+
'session_memory',
|
|
74
|
+
'full_compaction',
|
|
75
|
+
'reset',
|
|
76
|
+
]);
|
|
77
|
+
export const compactionStartedEventSchema = auditEventBaseSchema.extend({
|
|
78
|
+
type: z.literal('compaction.started'),
|
|
79
|
+
tier: compactionTierSchema,
|
|
80
|
+
trigger: z.object({
|
|
81
|
+
budgetUsed: z.number().nonnegative(),
|
|
82
|
+
budgetMax: z.number().positive(),
|
|
83
|
+
}),
|
|
84
|
+
});
|
|
85
|
+
export const compactionCompletedEventSchema = auditEventBaseSchema.extend({
|
|
86
|
+
type: z.literal('compaction.completed'),
|
|
87
|
+
tier: compactionTierSchema,
|
|
88
|
+
bytesReclaimed: z.number().nonnegative(),
|
|
89
|
+
newContextSize: z.number().nonnegative(),
|
|
90
|
+
artifactsCreated: z.array(z.object({
|
|
91
|
+
sha256: z.string().min(1),
|
|
92
|
+
size: z.number().nonnegative(),
|
|
93
|
+
producedBy: z.string().min(1),
|
|
94
|
+
})),
|
|
95
|
+
});
|
|
96
|
+
export const compactionSkippedEventSchema = auditEventBaseSchema.extend({
|
|
97
|
+
type: z.literal('compaction.skipped'),
|
|
98
|
+
tier: compactionTierSchema,
|
|
99
|
+
reason: z.string(),
|
|
100
|
+
});
|
|
101
|
+
export const compactionInvariantViolatedEventSchema = auditEventBaseSchema.extend({
|
|
102
|
+
type: z.literal('compaction.invariant_violated'),
|
|
103
|
+
invariant: z.enum([
|
|
104
|
+
'secrets-never-summarize',
|
|
105
|
+
'open-decisions-preserved',
|
|
106
|
+
'artifact-refs-resolvable',
|
|
107
|
+
'static-hash-unchanged',
|
|
108
|
+
]),
|
|
109
|
+
evidence: z.string(),
|
|
110
|
+
artifactRef: z.string().min(1).optional(),
|
|
111
|
+
});
|
|
112
|
+
/**
|
|
113
|
+
* Subagent lifecycle events. Extended in Sprint a5.4 (M1 gap remediation D)
|
|
114
|
+
* so dispatcher activity surfaces in the same `.pugi/events.jsonl` audit
|
|
115
|
+
* stream as tool calls, hooks, and compactions. The dispatcher
|
|
116
|
+
* implementation lives in `apps/pugi-cli/src/core/subagents/dispatcher.ts`;
|
|
117
|
+
* the wire-level shape and role/isolation enums are defined in
|
|
118
|
+
* `subagent-contracts.ts` and re-used here so a single source of truth
|
|
119
|
+
* governs validation on both sides of the boundary.
|
|
120
|
+
*/
|
|
121
|
+
export const subagentSpawnedAuditEventSchema = auditEventBaseSchema.extend({
|
|
122
|
+
type: z.literal('subagent.spawned'),
|
|
123
|
+
taskId: z.string().min(1),
|
|
124
|
+
role: subagentRoleSchema,
|
|
125
|
+
personaSlug: z.string().min(1),
|
|
126
|
+
parentSessionId: z.string().min(1),
|
|
127
|
+
isolation: subagentIsolationSchema,
|
|
128
|
+
});
|
|
129
|
+
export const subagentToolCallAuditEventSchema = auditEventBaseSchema.extend({
|
|
130
|
+
type: z.literal('subagent.tool_call'),
|
|
131
|
+
taskId: z.string().min(1),
|
|
132
|
+
role: subagentRoleSchema,
|
|
133
|
+
personaSlug: z.string().min(1),
|
|
134
|
+
toolName: z.string().min(1),
|
|
135
|
+
toolCallId: z.string().min(1),
|
|
136
|
+
});
|
|
137
|
+
export const subagentCompletedAuditEventSchema = auditEventBaseSchema.extend({
|
|
138
|
+
type: z.literal('subagent.completed'),
|
|
139
|
+
taskId: z.string().min(1),
|
|
140
|
+
role: subagentRoleSchema,
|
|
141
|
+
personaSlug: z.string().min(1),
|
|
142
|
+
toolCallCount: z.number().int().nonnegative(),
|
|
143
|
+
tokensIn: z.number().int().nonnegative(),
|
|
144
|
+
tokensOut: z.number().int().nonnegative(),
|
|
145
|
+
durationMs: z.number().int().nonnegative(),
|
|
146
|
+
});
|
|
147
|
+
export const subagentBlockedAuditEventSchema = auditEventBaseSchema.extend({
|
|
148
|
+
type: z.literal('subagent.blocked'),
|
|
149
|
+
taskId: z.string().min(1),
|
|
150
|
+
role: subagentRoleSchema,
|
|
151
|
+
personaSlug: z.string().min(1),
|
|
152
|
+
reason: z.enum([
|
|
153
|
+
'budget_exhausted',
|
|
154
|
+
'plan_mode_refused',
|
|
155
|
+
'permission_denied',
|
|
156
|
+
'tool_unavailable',
|
|
157
|
+
]),
|
|
158
|
+
detail: z.string().min(1),
|
|
159
|
+
});
|
|
160
|
+
export const subagentFailedAuditEventSchema = auditEventBaseSchema.extend({
|
|
161
|
+
type: z.literal('subagent.failed'),
|
|
162
|
+
taskId: z.string().min(1),
|
|
163
|
+
role: subagentRoleSchema,
|
|
164
|
+
personaSlug: z.string().min(1),
|
|
165
|
+
error: z.string().min(1),
|
|
166
|
+
});
|
|
167
|
+
export const auditEventSchema = z.discriminatedUnion('type', [
|
|
168
|
+
sessionEventSchema,
|
|
169
|
+
toolCallEventSchema,
|
|
170
|
+
toolResultEventSchema,
|
|
171
|
+
fileMutationEventSchema,
|
|
172
|
+
hookInvokedEventSchema,
|
|
173
|
+
hookResultEventSchema,
|
|
174
|
+
hookSkippedEventSchema,
|
|
175
|
+
compactionStartedEventSchema,
|
|
176
|
+
compactionCompletedEventSchema,
|
|
177
|
+
compactionSkippedEventSchema,
|
|
178
|
+
compactionInvariantViolatedEventSchema,
|
|
179
|
+
subagentSpawnedAuditEventSchema,
|
|
180
|
+
subagentToolCallAuditEventSchema,
|
|
181
|
+
subagentCompletedAuditEventSchema,
|
|
182
|
+
subagentBlockedAuditEventSchema,
|
|
183
|
+
subagentFailedAuditEventSchema,
|
|
184
|
+
]);
|
|
185
|
+
//# sourceMappingURL=audit-trace.js.map
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* OAuth 2.0 Device Authorization Grant (RFC 8628) wire contracts.
|
|
4
|
+
*
|
|
5
|
+
* The CLI hits two endpoints:
|
|
6
|
+
* POST /api/auth/device/start
|
|
7
|
+
* POST /api/auth/device/poll
|
|
8
|
+
*
|
|
9
|
+
* The cabinet UI hits two more (JWT-authenticated):
|
|
10
|
+
* POST /api/auth/device/approve
|
|
11
|
+
* POST /api/auth/device/deny
|
|
12
|
+
*
|
|
13
|
+
* Field naming follows RFC 8628 (snake_case) on the wire, not the
|
|
14
|
+
* camelCase server type used by Prisma — Zod schemas below are the
|
|
15
|
+
* canonical wire shape. CLI consumers parse the response with these
|
|
16
|
+
* schemas to defeat a hostile or buggy runtime returning malformed
|
|
17
|
+
* fields.
|
|
18
|
+
*/
|
|
19
|
+
export declare const pugiDeviceStartRequestSchema: z.ZodObject<{
|
|
20
|
+
clientId: z.ZodLiteral<"pugi-cli">;
|
|
21
|
+
}, "strip", z.ZodTypeAny, {
|
|
22
|
+
clientId: "pugi-cli";
|
|
23
|
+
}, {
|
|
24
|
+
clientId: "pugi-cli";
|
|
25
|
+
}>;
|
|
26
|
+
export type PugiDeviceStartRequest = z.infer<typeof pugiDeviceStartRequestSchema>;
|
|
27
|
+
export declare const pugiDeviceStartResponseSchema: z.ZodObject<{
|
|
28
|
+
device_code: z.ZodString;
|
|
29
|
+
user_code: z.ZodString;
|
|
30
|
+
verification_uri: z.ZodString;
|
|
31
|
+
verification_uri_complete: z.ZodString;
|
|
32
|
+
expires_in: z.ZodNumber;
|
|
33
|
+
interval: z.ZodNumber;
|
|
34
|
+
}, "strip", z.ZodTypeAny, {
|
|
35
|
+
device_code: string;
|
|
36
|
+
user_code: string;
|
|
37
|
+
verification_uri: string;
|
|
38
|
+
verification_uri_complete: string;
|
|
39
|
+
expires_in: number;
|
|
40
|
+
interval: number;
|
|
41
|
+
}, {
|
|
42
|
+
device_code: string;
|
|
43
|
+
user_code: string;
|
|
44
|
+
verification_uri: string;
|
|
45
|
+
verification_uri_complete: string;
|
|
46
|
+
expires_in: number;
|
|
47
|
+
interval: number;
|
|
48
|
+
}>;
|
|
49
|
+
export type PugiDeviceStartResponse = z.infer<typeof pugiDeviceStartResponseSchema>;
|
|
50
|
+
export declare const pugiDevicePollRequestSchema: z.ZodObject<{
|
|
51
|
+
deviceCode: z.ZodString;
|
|
52
|
+
}, "strip", z.ZodTypeAny, {
|
|
53
|
+
deviceCode: string;
|
|
54
|
+
}, {
|
|
55
|
+
deviceCode: string;
|
|
56
|
+
}>;
|
|
57
|
+
export type PugiDevicePollRequest = z.infer<typeof pugiDevicePollRequestSchema>;
|
|
58
|
+
export declare const pugiDevicePollStatusSchema: z.ZodEnum<["pending", "authorized", "denied", "expired", "redeemed"]>;
|
|
59
|
+
export type PugiDevicePollStatus = z.infer<typeof pugiDevicePollStatusSchema>;
|
|
60
|
+
export declare const pugiDevicePollResponseSchema: z.ZodDiscriminatedUnion<"status", [z.ZodObject<{
|
|
61
|
+
status: z.ZodLiteral<"authorized">;
|
|
62
|
+
access_token: z.ZodString;
|
|
63
|
+
token_type: z.ZodLiteral<"Bearer">;
|
|
64
|
+
}, "strip", z.ZodTypeAny, {
|
|
65
|
+
status: "authorized";
|
|
66
|
+
access_token: string;
|
|
67
|
+
token_type: "Bearer";
|
|
68
|
+
}, {
|
|
69
|
+
status: "authorized";
|
|
70
|
+
access_token: string;
|
|
71
|
+
token_type: "Bearer";
|
|
72
|
+
}>, z.ZodObject<{
|
|
73
|
+
status: z.ZodLiteral<"pending">;
|
|
74
|
+
}, "strip", z.ZodTypeAny, {
|
|
75
|
+
status: "pending";
|
|
76
|
+
}, {
|
|
77
|
+
status: "pending";
|
|
78
|
+
}>, z.ZodObject<{
|
|
79
|
+
status: z.ZodLiteral<"denied">;
|
|
80
|
+
}, "strip", z.ZodTypeAny, {
|
|
81
|
+
status: "denied";
|
|
82
|
+
}, {
|
|
83
|
+
status: "denied";
|
|
84
|
+
}>, z.ZodObject<{
|
|
85
|
+
status: z.ZodLiteral<"expired">;
|
|
86
|
+
}, "strip", z.ZodTypeAny, {
|
|
87
|
+
status: "expired";
|
|
88
|
+
}, {
|
|
89
|
+
status: "expired";
|
|
90
|
+
}>, z.ZodObject<{
|
|
91
|
+
status: z.ZodLiteral<"redeemed">;
|
|
92
|
+
}, "strip", z.ZodTypeAny, {
|
|
93
|
+
status: "redeemed";
|
|
94
|
+
}, {
|
|
95
|
+
status: "redeemed";
|
|
96
|
+
}>]>;
|
|
97
|
+
export type PugiDevicePollResponse = z.infer<typeof pugiDevicePollResponseSchema>;
|
|
98
|
+
//# sourceMappingURL=device-flow.d.ts.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* OAuth 2.0 Device Authorization Grant (RFC 8628) wire contracts.
|
|
4
|
+
*
|
|
5
|
+
* The CLI hits two endpoints:
|
|
6
|
+
* POST /api/auth/device/start
|
|
7
|
+
* POST /api/auth/device/poll
|
|
8
|
+
*
|
|
9
|
+
* The cabinet UI hits two more (JWT-authenticated):
|
|
10
|
+
* POST /api/auth/device/approve
|
|
11
|
+
* POST /api/auth/device/deny
|
|
12
|
+
*
|
|
13
|
+
* Field naming follows RFC 8628 (snake_case) on the wire, not the
|
|
14
|
+
* camelCase server type used by Prisma — Zod schemas below are the
|
|
15
|
+
* canonical wire shape. CLI consumers parse the response with these
|
|
16
|
+
* schemas to defeat a hostile or buggy runtime returning malformed
|
|
17
|
+
* fields.
|
|
18
|
+
*/
|
|
19
|
+
export const pugiDeviceStartRequestSchema = z.object({
|
|
20
|
+
clientId: z.literal('pugi-cli'),
|
|
21
|
+
});
|
|
22
|
+
export const pugiDeviceStartResponseSchema = z.object({
|
|
23
|
+
device_code: z.string().length(64),
|
|
24
|
+
user_code: z.string().min(8).max(16),
|
|
25
|
+
verification_uri: z.string().url(),
|
|
26
|
+
verification_uri_complete: z.string().url(),
|
|
27
|
+
// Cap `expires_in` at 1 hour so a hostile or misconfigured runtime
|
|
28
|
+
// cannot trap the CLI in a year-long poll loop by returning a huge
|
|
29
|
+
// expiration. The server today uses 10 min; this is just the upper
|
|
30
|
+
// bound the SDK trusts.
|
|
31
|
+
expires_in: z.number().int().positive().max(3600),
|
|
32
|
+
interval: z.number().int().min(1).max(60),
|
|
33
|
+
});
|
|
34
|
+
export const pugiDevicePollRequestSchema = z.object({
|
|
35
|
+
deviceCode: z.string().min(32).max(128),
|
|
36
|
+
});
|
|
37
|
+
export const pugiDevicePollStatusSchema = z.enum([
|
|
38
|
+
'pending',
|
|
39
|
+
'authorized',
|
|
40
|
+
'denied',
|
|
41
|
+
'expired',
|
|
42
|
+
'redeemed',
|
|
43
|
+
]);
|
|
44
|
+
export const pugiDevicePollResponseSchema = z.discriminatedUnion('status', [
|
|
45
|
+
z.object({
|
|
46
|
+
status: z.literal('authorized'),
|
|
47
|
+
access_token: z.string().min(1),
|
|
48
|
+
token_type: z.literal('Bearer'),
|
|
49
|
+
}),
|
|
50
|
+
z.object({ status: z.literal('pending') }),
|
|
51
|
+
z.object({ status: z.literal('denied') }),
|
|
52
|
+
z.object({ status: z.literal('expired') }),
|
|
53
|
+
z.object({ status: z.literal('redeemed') }),
|
|
54
|
+
]);
|
|
55
|
+
//# sourceMappingURL=device-flow.js.map
|