@ricsam/r5d-api 0.0.59 → 0.0.61
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 +13 -3
- package/dist/cjs/index.cjs +108 -47
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/index.mjs +108 -47
- package/dist/mjs/package.json +1 -1
- package/dist/types/index.d.ts +171 -65
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,16 +58,26 @@ Trusted server-side callers that authenticate through custom headers, such as a
|
|
|
58
58
|
- `projects.env.get/update/remove(projectId, ...)`
|
|
59
59
|
- `projects.sessions.list(projectRef, { branch? })`
|
|
60
60
|
- `projects.sessions.create(projectRef, { branchName, name? })`
|
|
61
|
+
- `projects.sessions.start(projectRef, { worker, model, prompt, requestId, worktree?, newWorktree?, source? })`
|
|
62
|
+
- `projects.worktrees.merge(projectRef, sourceWorktree, { worker?, conflictMode })`
|
|
63
|
+
- `projects.worktrees.finishMerge(projectRef, conflictWorktree, { worker, summary? })`
|
|
61
64
|
- `sessions.describe(sessionId)`
|
|
62
65
|
- `sessions.update(sessionId, { name })`
|
|
63
66
|
- `sessions.delete(sessionId)`
|
|
64
67
|
- `sessions.conversation(sessionId)`
|
|
68
|
+
- `sessions.events(sessionId, { signal? })`
|
|
65
69
|
- `sessions.conversationOverview(sessionId)`
|
|
66
70
|
- `sessions.inspectConversationNode(sessionId, nodeId)`
|
|
67
71
|
- `sessions.inspectConversationWork(sessionId, workId, { detail? })`
|
|
68
|
-
- `sessions.
|
|
69
|
-
- `sessions.
|
|
70
|
-
- `sessions.
|
|
72
|
+
- `sessions.status(sessionId)`
|
|
73
|
+
- `sessions.prompt(sessionId, { prompt, worker, mode, model, requestId })`
|
|
74
|
+
- `sessions.stop(sessionId)`
|
|
75
|
+
- `sessions.answerQuestions(sessionId, { answers, worker, mode, model, requestId })`
|
|
76
|
+
- `sessions.answerEnvRequest(sessionId, { envs?, additionalContext?, worker, mode, model, requestId })`
|
|
77
|
+
|
|
78
|
+
`sessions.prompt(...)` returns `promptDisposition: "queued" | "started"`, so callers can distinguish delivery to an active generation from a newly started generation. Session commands never rebind a session to another worker implicitly.
|
|
79
|
+
|
|
80
|
+
`projects.sessions.start(...)` selects either an existing `worktree`, or a `newWorktree` plus `source: { type: "worktree", branchName }`. Session events are exposed as an authenticated async iterable over the raw `/api/sessions/:sessionId/events` SSE stream.
|
|
71
81
|
|
|
72
82
|
## Errors
|
|
73
83
|
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -49,6 +49,56 @@ function withQuery(path, query) {
|
|
|
49
49
|
const queryString = params.toString();
|
|
50
50
|
return queryString.length > 0 ? `${path}?${queryString}` : path;
|
|
51
51
|
}
|
|
52
|
+
function parseSseFrame(frame) {
|
|
53
|
+
const dataLines = [];
|
|
54
|
+
let eventType;
|
|
55
|
+
for (const line of frame.split(/\r?\n/)) {
|
|
56
|
+
if (line.length === 0 || line.startsWith(":")) continue;
|
|
57
|
+
const separator = line.indexOf(":");
|
|
58
|
+
const field = separator < 0 ? line : line.slice(0, separator);
|
|
59
|
+
const value = separator < 0 ? "" : line.slice(separator + 1).replace(/^ /, "");
|
|
60
|
+
if (field === "event") eventType = value;
|
|
61
|
+
if (field === "data") dataLines.push(value);
|
|
62
|
+
}
|
|
63
|
+
if (dataLines.length === 0) return null;
|
|
64
|
+
const parsed = safeJsonParse(dataLines.join("\n"));
|
|
65
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
66
|
+
const record = parsed;
|
|
67
|
+
if (typeof record.type !== "string" && eventType) record.type = eventType;
|
|
68
|
+
if (typeof record.type === "string") return record;
|
|
69
|
+
}
|
|
70
|
+
return eventType ? { type: eventType, data: parsed } : null;
|
|
71
|
+
}
|
|
72
|
+
async function* parseSseStream(stream) {
|
|
73
|
+
const reader = stream.getReader();
|
|
74
|
+
const decoder = new TextDecoder();
|
|
75
|
+
let buffer = "";
|
|
76
|
+
let completed = false;
|
|
77
|
+
try {
|
|
78
|
+
while (true) {
|
|
79
|
+
const { done, value } = await reader.read();
|
|
80
|
+
buffer += decoder.decode(value, { stream: !done });
|
|
81
|
+
let boundary = buffer.search(/\r?\n\r?\n/);
|
|
82
|
+
while (boundary >= 0) {
|
|
83
|
+
const frame = buffer.slice(0, boundary);
|
|
84
|
+
const separator = buffer.slice(boundary).match(/^\r?\n\r?\n/)?.[0] ?? "\n\n";
|
|
85
|
+
buffer = buffer.slice(boundary + separator.length);
|
|
86
|
+
const event2 = parseSseFrame(frame);
|
|
87
|
+
if (event2) yield event2;
|
|
88
|
+
boundary = buffer.search(/\r?\n\r?\n/);
|
|
89
|
+
}
|
|
90
|
+
if (done) {
|
|
91
|
+
completed = true;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const event = parseSseFrame(buffer);
|
|
96
|
+
if (event) yield event;
|
|
97
|
+
} finally {
|
|
98
|
+
if (!completed) await reader.cancel().catch(() => void 0);
|
|
99
|
+
reader.releaseLock();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
52
102
|
class R5dctlClient {
|
|
53
103
|
fetchImpl;
|
|
54
104
|
baseUrl;
|
|
@@ -76,26 +126,25 @@ class R5dctlClient {
|
|
|
76
126
|
resolveBearerToken() {
|
|
77
127
|
return this.token ?? this.apiKey;
|
|
78
128
|
}
|
|
79
|
-
|
|
80
|
-
const
|
|
129
|
+
authHeaders(path, accept, auth = "auto") {
|
|
130
|
+
const headers = { ...this.extraHeaders, Accept: accept };
|
|
131
|
+
if (auth === "none") return headers;
|
|
81
132
|
const bearerToken = this.resolveBearerToken();
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
throw new R5dctlApiError("Authentication required. Set token or apiKey in R5dctlClient.", {
|
|
90
|
-
status: 401,
|
|
91
|
-
path: input.path,
|
|
92
|
-
body: { error: "Missing credentials" }
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
} else {
|
|
96
|
-
headers.Authorization = `Bearer ${bearerToken}`;
|
|
133
|
+
if (!bearerToken) {
|
|
134
|
+
if (this.authMode !== "headers") {
|
|
135
|
+
throw new R5dctlApiError("Authentication required. Set token or apiKey in R5dctlClient.", {
|
|
136
|
+
status: 401,
|
|
137
|
+
path,
|
|
138
|
+
body: { error: "Missing credentials" }
|
|
139
|
+
});
|
|
97
140
|
}
|
|
141
|
+
} else {
|
|
142
|
+
headers.Authorization = `Bearer ${bearerToken}`;
|
|
98
143
|
}
|
|
144
|
+
return headers;
|
|
145
|
+
}
|
|
146
|
+
async request(input) {
|
|
147
|
+
const headers = this.authHeaders(input.path, "application/json", input.auth ?? "auto");
|
|
99
148
|
const hasBody = input.body !== void 0;
|
|
100
149
|
if (hasBody) {
|
|
101
150
|
headers["Content-Type"] = "application/json";
|
|
@@ -118,6 +167,24 @@ class R5dctlClient {
|
|
|
118
167
|
}
|
|
119
168
|
return payload;
|
|
120
169
|
}
|
|
170
|
+
async *events(sessionId, input = {}) {
|
|
171
|
+
const path = `/api/sessions/${encodeURIComponent(sessionId)}/events`;
|
|
172
|
+
const response = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
173
|
+
method: "GET",
|
|
174
|
+
headers: this.authHeaders(path, "text/event-stream"),
|
|
175
|
+
signal: input.signal
|
|
176
|
+
});
|
|
177
|
+
if (!response.ok) {
|
|
178
|
+
const text = await response.text();
|
|
179
|
+
const payload = text.length > 0 ? safeJsonParse(text) : null;
|
|
180
|
+
const message = typeof payload === "object" && payload && "error" in payload && typeof payload.error === "string" ? payload.error : `Request failed (${response.status})`;
|
|
181
|
+
throw new R5dctlApiError(message, { status: response.status, path, body: payload });
|
|
182
|
+
}
|
|
183
|
+
if (!response.body) {
|
|
184
|
+
throw new R5dctlApiError("Session event stream returned no body", { status: response.status, path, body: null });
|
|
185
|
+
}
|
|
186
|
+
yield* parseSseStream(response.body);
|
|
187
|
+
}
|
|
121
188
|
auth = {
|
|
122
189
|
deviceStart: (input) => this.request({
|
|
123
190
|
method: "POST",
|
|
@@ -294,41 +361,25 @@ class R5dctlClient {
|
|
|
294
361
|
method: "POST",
|
|
295
362
|
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/sessions`,
|
|
296
363
|
body: input
|
|
297
|
-
})
|
|
298
|
-
},
|
|
299
|
-
agents: {
|
|
364
|
+
}),
|
|
300
365
|
start: (projectRef, input) => this.request({
|
|
301
366
|
method: "POST",
|
|
302
|
-
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/
|
|
367
|
+
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/sessions/start`,
|
|
303
368
|
body: input
|
|
304
369
|
})
|
|
305
370
|
},
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/abort-merge`,
|
|
319
|
-
body: input
|
|
320
|
-
})
|
|
321
|
-
};
|
|
322
|
-
agents = {
|
|
323
|
-
status: (sessionId) => this.request({
|
|
324
|
-
method: "GET",
|
|
325
|
-
path: `/api/r5dctl/agents/${encodeURIComponent(sessionId)}`
|
|
326
|
-
}),
|
|
327
|
-
sendPrompt: (sessionId, input) => this.request({
|
|
328
|
-
method: "POST",
|
|
329
|
-
path: `/api/r5dctl/agents/${encodeURIComponent(sessionId)}/prompt`,
|
|
330
|
-
body: input
|
|
331
|
-
})
|
|
371
|
+
worktrees: {
|
|
372
|
+
merge: (projectRef, sourceWorktree, input) => this.request({
|
|
373
|
+
method: "POST",
|
|
374
|
+
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/worktrees/${encodeURIComponent(sourceWorktree)}/merge`,
|
|
375
|
+
body: input
|
|
376
|
+
}),
|
|
377
|
+
finishMerge: (projectRef, conflictWorktree, input) => this.request({
|
|
378
|
+
method: "POST",
|
|
379
|
+
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/worktrees/${encodeURIComponent(conflictWorktree)}/merge/finish`,
|
|
380
|
+
body: input
|
|
381
|
+
})
|
|
382
|
+
}
|
|
332
383
|
};
|
|
333
384
|
sessions = {
|
|
334
385
|
recent: (input = {}) => this.request({
|
|
@@ -349,6 +400,11 @@ class R5dctlClient {
|
|
|
349
400
|
method: "DELETE",
|
|
350
401
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}`
|
|
351
402
|
}),
|
|
403
|
+
status: (sessionId) => this.request({
|
|
404
|
+
method: "GET",
|
|
405
|
+
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/status`
|
|
406
|
+
}),
|
|
407
|
+
events: (sessionId, input = {}) => this.events(sessionId, input),
|
|
352
408
|
conversation: (sessionId, input = {}) => this.request({
|
|
353
409
|
method: "GET",
|
|
354
410
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/conversation`,
|
|
@@ -378,6 +434,11 @@ class R5dctlClient {
|
|
|
378
434
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/prompt`,
|
|
379
435
|
body: input
|
|
380
436
|
}),
|
|
437
|
+
stop: (sessionId) => this.request({
|
|
438
|
+
method: "POST",
|
|
439
|
+
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/stop`,
|
|
440
|
+
body: {}
|
|
441
|
+
}),
|
|
381
442
|
answerQuestions: (sessionId, input) => this.request({
|
|
382
443
|
method: "POST",
|
|
383
444
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/answer-questions`,
|
package/dist/cjs/package.json
CHANGED
package/dist/mjs/index.mjs
CHANGED
|
@@ -25,6 +25,56 @@ function withQuery(path, query) {
|
|
|
25
25
|
const queryString = params.toString();
|
|
26
26
|
return queryString.length > 0 ? `${path}?${queryString}` : path;
|
|
27
27
|
}
|
|
28
|
+
function parseSseFrame(frame) {
|
|
29
|
+
const dataLines = [];
|
|
30
|
+
let eventType;
|
|
31
|
+
for (const line of frame.split(/\r?\n/)) {
|
|
32
|
+
if (line.length === 0 || line.startsWith(":")) continue;
|
|
33
|
+
const separator = line.indexOf(":");
|
|
34
|
+
const field = separator < 0 ? line : line.slice(0, separator);
|
|
35
|
+
const value = separator < 0 ? "" : line.slice(separator + 1).replace(/^ /, "");
|
|
36
|
+
if (field === "event") eventType = value;
|
|
37
|
+
if (field === "data") dataLines.push(value);
|
|
38
|
+
}
|
|
39
|
+
if (dataLines.length === 0) return null;
|
|
40
|
+
const parsed = safeJsonParse(dataLines.join("\n"));
|
|
41
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
42
|
+
const record = parsed;
|
|
43
|
+
if (typeof record.type !== "string" && eventType) record.type = eventType;
|
|
44
|
+
if (typeof record.type === "string") return record;
|
|
45
|
+
}
|
|
46
|
+
return eventType ? { type: eventType, data: parsed } : null;
|
|
47
|
+
}
|
|
48
|
+
async function* parseSseStream(stream) {
|
|
49
|
+
const reader = stream.getReader();
|
|
50
|
+
const decoder = new TextDecoder();
|
|
51
|
+
let buffer = "";
|
|
52
|
+
let completed = false;
|
|
53
|
+
try {
|
|
54
|
+
while (true) {
|
|
55
|
+
const { done, value } = await reader.read();
|
|
56
|
+
buffer += decoder.decode(value, { stream: !done });
|
|
57
|
+
let boundary = buffer.search(/\r?\n\r?\n/);
|
|
58
|
+
while (boundary >= 0) {
|
|
59
|
+
const frame = buffer.slice(0, boundary);
|
|
60
|
+
const separator = buffer.slice(boundary).match(/^\r?\n\r?\n/)?.[0] ?? "\n\n";
|
|
61
|
+
buffer = buffer.slice(boundary + separator.length);
|
|
62
|
+
const event2 = parseSseFrame(frame);
|
|
63
|
+
if (event2) yield event2;
|
|
64
|
+
boundary = buffer.search(/\r?\n\r?\n/);
|
|
65
|
+
}
|
|
66
|
+
if (done) {
|
|
67
|
+
completed = true;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const event = parseSseFrame(buffer);
|
|
72
|
+
if (event) yield event;
|
|
73
|
+
} finally {
|
|
74
|
+
if (!completed) await reader.cancel().catch(() => void 0);
|
|
75
|
+
reader.releaseLock();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
28
78
|
class R5dctlClient {
|
|
29
79
|
fetchImpl;
|
|
30
80
|
baseUrl;
|
|
@@ -52,26 +102,25 @@ class R5dctlClient {
|
|
|
52
102
|
resolveBearerToken() {
|
|
53
103
|
return this.token ?? this.apiKey;
|
|
54
104
|
}
|
|
55
|
-
|
|
56
|
-
const
|
|
105
|
+
authHeaders(path, accept, auth = "auto") {
|
|
106
|
+
const headers = { ...this.extraHeaders, Accept: accept };
|
|
107
|
+
if (auth === "none") return headers;
|
|
57
108
|
const bearerToken = this.resolveBearerToken();
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
throw new R5dctlApiError("Authentication required. Set token or apiKey in R5dctlClient.", {
|
|
66
|
-
status: 401,
|
|
67
|
-
path: input.path,
|
|
68
|
-
body: { error: "Missing credentials" }
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
} else {
|
|
72
|
-
headers.Authorization = `Bearer ${bearerToken}`;
|
|
109
|
+
if (!bearerToken) {
|
|
110
|
+
if (this.authMode !== "headers") {
|
|
111
|
+
throw new R5dctlApiError("Authentication required. Set token or apiKey in R5dctlClient.", {
|
|
112
|
+
status: 401,
|
|
113
|
+
path,
|
|
114
|
+
body: { error: "Missing credentials" }
|
|
115
|
+
});
|
|
73
116
|
}
|
|
117
|
+
} else {
|
|
118
|
+
headers.Authorization = `Bearer ${bearerToken}`;
|
|
74
119
|
}
|
|
120
|
+
return headers;
|
|
121
|
+
}
|
|
122
|
+
async request(input) {
|
|
123
|
+
const headers = this.authHeaders(input.path, "application/json", input.auth ?? "auto");
|
|
75
124
|
const hasBody = input.body !== void 0;
|
|
76
125
|
if (hasBody) {
|
|
77
126
|
headers["Content-Type"] = "application/json";
|
|
@@ -94,6 +143,24 @@ class R5dctlClient {
|
|
|
94
143
|
}
|
|
95
144
|
return payload;
|
|
96
145
|
}
|
|
146
|
+
async *events(sessionId, input = {}) {
|
|
147
|
+
const path = `/api/sessions/${encodeURIComponent(sessionId)}/events`;
|
|
148
|
+
const response = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
149
|
+
method: "GET",
|
|
150
|
+
headers: this.authHeaders(path, "text/event-stream"),
|
|
151
|
+
signal: input.signal
|
|
152
|
+
});
|
|
153
|
+
if (!response.ok) {
|
|
154
|
+
const text = await response.text();
|
|
155
|
+
const payload = text.length > 0 ? safeJsonParse(text) : null;
|
|
156
|
+
const message = typeof payload === "object" && payload && "error" in payload && typeof payload.error === "string" ? payload.error : `Request failed (${response.status})`;
|
|
157
|
+
throw new R5dctlApiError(message, { status: response.status, path, body: payload });
|
|
158
|
+
}
|
|
159
|
+
if (!response.body) {
|
|
160
|
+
throw new R5dctlApiError("Session event stream returned no body", { status: response.status, path, body: null });
|
|
161
|
+
}
|
|
162
|
+
yield* parseSseStream(response.body);
|
|
163
|
+
}
|
|
97
164
|
auth = {
|
|
98
165
|
deviceStart: (input) => this.request({
|
|
99
166
|
method: "POST",
|
|
@@ -270,41 +337,25 @@ class R5dctlClient {
|
|
|
270
337
|
method: "POST",
|
|
271
338
|
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/sessions`,
|
|
272
339
|
body: input
|
|
273
|
-
})
|
|
274
|
-
},
|
|
275
|
-
agents: {
|
|
340
|
+
}),
|
|
276
341
|
start: (projectRef, input) => this.request({
|
|
277
342
|
method: "POST",
|
|
278
|
-
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/
|
|
343
|
+
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/sessions/start`,
|
|
279
344
|
body: input
|
|
280
345
|
})
|
|
281
346
|
},
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/abort-merge`,
|
|
295
|
-
body: input
|
|
296
|
-
})
|
|
297
|
-
};
|
|
298
|
-
agents = {
|
|
299
|
-
status: (sessionId) => this.request({
|
|
300
|
-
method: "GET",
|
|
301
|
-
path: `/api/r5dctl/agents/${encodeURIComponent(sessionId)}`
|
|
302
|
-
}),
|
|
303
|
-
sendPrompt: (sessionId, input) => this.request({
|
|
304
|
-
method: "POST",
|
|
305
|
-
path: `/api/r5dctl/agents/${encodeURIComponent(sessionId)}/prompt`,
|
|
306
|
-
body: input
|
|
307
|
-
})
|
|
347
|
+
worktrees: {
|
|
348
|
+
merge: (projectRef, sourceWorktree, input) => this.request({
|
|
349
|
+
method: "POST",
|
|
350
|
+
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/worktrees/${encodeURIComponent(sourceWorktree)}/merge`,
|
|
351
|
+
body: input
|
|
352
|
+
}),
|
|
353
|
+
finishMerge: (projectRef, conflictWorktree, input) => this.request({
|
|
354
|
+
method: "POST",
|
|
355
|
+
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/worktrees/${encodeURIComponent(conflictWorktree)}/merge/finish`,
|
|
356
|
+
body: input
|
|
357
|
+
})
|
|
358
|
+
}
|
|
308
359
|
};
|
|
309
360
|
sessions = {
|
|
310
361
|
recent: (input = {}) => this.request({
|
|
@@ -325,6 +376,11 @@ class R5dctlClient {
|
|
|
325
376
|
method: "DELETE",
|
|
326
377
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}`
|
|
327
378
|
}),
|
|
379
|
+
status: (sessionId) => this.request({
|
|
380
|
+
method: "GET",
|
|
381
|
+
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/status`
|
|
382
|
+
}),
|
|
383
|
+
events: (sessionId, input = {}) => this.events(sessionId, input),
|
|
328
384
|
conversation: (sessionId, input = {}) => this.request({
|
|
329
385
|
method: "GET",
|
|
330
386
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/conversation`,
|
|
@@ -354,6 +410,11 @@ class R5dctlClient {
|
|
|
354
410
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/prompt`,
|
|
355
411
|
body: input
|
|
356
412
|
}),
|
|
413
|
+
stop: (sessionId) => this.request({
|
|
414
|
+
method: "POST",
|
|
415
|
+
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/stop`,
|
|
416
|
+
body: {}
|
|
417
|
+
}),
|
|
357
418
|
answerQuestions: (sessionId, input) => this.request({
|
|
358
419
|
method: "POST",
|
|
359
420
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/answer-questions`,
|
package/dist/mjs/package.json
CHANGED
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
export type ChatMode = "ask" | "plan" | "build" | "agent" | "
|
|
1
|
+
export type ChatMode = "ask" | "plan" | "build" | "agent" | "security_review" | "large_diff_remediation" | "merge_conflict_resolution";
|
|
2
|
+
export type R5dctlSessionMode = "ask" | "plan" | "build" | "agent";
|
|
2
3
|
export type ModelTier = "low" | "medium" | "high" | "max";
|
|
3
|
-
export type
|
|
4
|
+
export type R5dctlWorktreeSource = {
|
|
5
|
+
type: "worktree";
|
|
6
|
+
branchName: string;
|
|
7
|
+
};
|
|
4
8
|
export type R5dctlProject = {
|
|
5
9
|
id: string;
|
|
6
10
|
namespace: string;
|
|
@@ -65,6 +69,86 @@ export type R5dctlConversationResponse = {
|
|
|
65
69
|
pendingQuestions: R5dctlPendingQuestion[];
|
|
66
70
|
requestedEnvs: R5dctlRequestedEnv[];
|
|
67
71
|
};
|
|
72
|
+
export type R5dctlSessionEvent = {
|
|
73
|
+
type: "text_delta";
|
|
74
|
+
text: string;
|
|
75
|
+
} | {
|
|
76
|
+
type: "thinking_delta";
|
|
77
|
+
text: string;
|
|
78
|
+
} | {
|
|
79
|
+
type: "tool_use_start";
|
|
80
|
+
toolCallId: string;
|
|
81
|
+
toolName: string;
|
|
82
|
+
} | {
|
|
83
|
+
type: "input_json_delta";
|
|
84
|
+
toolCallId: string;
|
|
85
|
+
partial_json: string;
|
|
86
|
+
} | {
|
|
87
|
+
type: "stream_reset";
|
|
88
|
+
attempt: number;
|
|
89
|
+
maxAttempts: number;
|
|
90
|
+
} | {
|
|
91
|
+
type: "tool_call";
|
|
92
|
+
data: unknown;
|
|
93
|
+
} | {
|
|
94
|
+
type: "tool_progress";
|
|
95
|
+
toolCallId: string;
|
|
96
|
+
progress: unknown;
|
|
97
|
+
} | {
|
|
98
|
+
type: "response";
|
|
99
|
+
data: {
|
|
100
|
+
node: unknown;
|
|
101
|
+
optimisticResponseId?: string;
|
|
102
|
+
conversationRevision: number;
|
|
103
|
+
};
|
|
104
|
+
} | {
|
|
105
|
+
type: "session";
|
|
106
|
+
data: unknown;
|
|
107
|
+
} | {
|
|
108
|
+
type: "status";
|
|
109
|
+
status: unknown;
|
|
110
|
+
statusVersion: number;
|
|
111
|
+
} | {
|
|
112
|
+
type: "files_updated";
|
|
113
|
+
files: unknown[];
|
|
114
|
+
} | {
|
|
115
|
+
type: "token_usage";
|
|
116
|
+
input: number;
|
|
117
|
+
output: number;
|
|
118
|
+
contextWindow?: number;
|
|
119
|
+
} | {
|
|
120
|
+
type: "queue_updated";
|
|
121
|
+
queue: unknown;
|
|
122
|
+
queueVersion: unknown;
|
|
123
|
+
} | {
|
|
124
|
+
type: "done";
|
|
125
|
+
} | {
|
|
126
|
+
type: "stopped";
|
|
127
|
+
} | {
|
|
128
|
+
type: "error";
|
|
129
|
+
message: string;
|
|
130
|
+
} | {
|
|
131
|
+
type: "agent_running";
|
|
132
|
+
running: boolean;
|
|
133
|
+
} | {
|
|
134
|
+
type: "context_continued";
|
|
135
|
+
sessionId: string;
|
|
136
|
+
target: unknown;
|
|
137
|
+
partNumber: number;
|
|
138
|
+
} | {
|
|
139
|
+
type: "context_handoff_failed";
|
|
140
|
+
message: string;
|
|
141
|
+
} | {
|
|
142
|
+
type: "shell_result";
|
|
143
|
+
stdout: string;
|
|
144
|
+
stderr: string;
|
|
145
|
+
exitCode: number;
|
|
146
|
+
fileChanges: unknown[];
|
|
147
|
+
cwd: string;
|
|
148
|
+
} | {
|
|
149
|
+
type: string;
|
|
150
|
+
[key: string]: unknown;
|
|
151
|
+
};
|
|
68
152
|
export type R5dctlConversationWorkDetail = "compact" | "summary" | "full";
|
|
69
153
|
export type R5dctlConversationWorkMetadata = {
|
|
70
154
|
id: string;
|
|
@@ -94,54 +178,70 @@ export type R5dctlConversationWorkResponse = {
|
|
|
94
178
|
detail: R5dctlConversationWorkDetail;
|
|
95
179
|
workText: string;
|
|
96
180
|
};
|
|
97
|
-
export type
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
181
|
+
export type R5dctlSessionRunStatus = "idle" | "provisioning" | "queued" | "running" | "completed" | "failed" | "stopped";
|
|
182
|
+
export type R5dctlWorktreeMergeResponse = {
|
|
183
|
+
status: "merged" | "up_to_date" | "conflicts" | "conflict_worktree_created" | "resolving" | "failed" | "stale";
|
|
184
|
+
attemptId?: string;
|
|
185
|
+
sourceWorktree: string;
|
|
186
|
+
targetWorktree: string;
|
|
187
|
+
conflictWorktree?: string;
|
|
188
|
+
commitHash?: string;
|
|
189
|
+
resolverSessionId?: string;
|
|
190
|
+
folderPath?: string;
|
|
191
|
+
worker?: string;
|
|
192
|
+
conflictedFiles?: string[];
|
|
193
|
+
failureReason?: string;
|
|
194
|
+
message?: string;
|
|
103
195
|
};
|
|
104
|
-
export type
|
|
196
|
+
export type R5dctlMergeConflictMode = "none" | "worktree" | "agent";
|
|
197
|
+
export type R5dctlSessionRunResponse = {
|
|
105
198
|
sessionId: string;
|
|
106
199
|
branchName: string;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
200
|
+
baselineCommit: string | null;
|
|
201
|
+
workspaceHead: string | null;
|
|
202
|
+
worker: string;
|
|
203
|
+
status: R5dctlSessionRunStatus;
|
|
204
|
+
runStatus: R5dctlSessionRunStatus;
|
|
205
|
+
generation: number;
|
|
206
|
+
createdAt: string;
|
|
111
207
|
updatedAt: string;
|
|
208
|
+
queuedAt?: string;
|
|
209
|
+
startedAt?: string;
|
|
112
210
|
completedAt?: string;
|
|
113
211
|
failedAt?: string;
|
|
212
|
+
stoppedAt?: string;
|
|
114
213
|
error?: string;
|
|
115
|
-
headCommit: string;
|
|
214
|
+
headCommit: string | null;
|
|
215
|
+
headCommitError?: string;
|
|
116
216
|
summary: string;
|
|
117
217
|
diffSummary: string;
|
|
218
|
+
sessionPath: string;
|
|
219
|
+
sessionUrl?: string;
|
|
118
220
|
};
|
|
119
|
-
export type
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
targetBranch: string;
|
|
124
|
-
commitHash: string;
|
|
125
|
-
message: string;
|
|
126
|
-
} | {
|
|
127
|
-
type: "merge_branch";
|
|
128
|
-
status: "conflicts";
|
|
129
|
-
sourceBranch: string;
|
|
130
|
-
targetBranch: string;
|
|
131
|
-
conflictedFiles: string[];
|
|
132
|
-
message: string;
|
|
221
|
+
export type R5dctlSessionStartResponse = R5dctlSessionRunResponse;
|
|
222
|
+
export type R5dctlSessionStatusResponse = R5dctlSessionRunResponse;
|
|
223
|
+
export type R5dctlSessionPromptResponse = R5dctlSessionRunResponse & {
|
|
224
|
+
promptDisposition: "queued" | "started";
|
|
133
225
|
};
|
|
134
|
-
export type
|
|
135
|
-
|
|
136
|
-
status: "
|
|
137
|
-
commitHash: string;
|
|
138
|
-
message: string;
|
|
226
|
+
export type R5dctlSessionStopResponse = {
|
|
227
|
+
sessionId: string;
|
|
228
|
+
status: "stopped";
|
|
139
229
|
};
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
230
|
+
type R5dctlSessionStartBaseInput = {
|
|
231
|
+
worker: string;
|
|
232
|
+
model: ModelTier;
|
|
233
|
+
prompt: string;
|
|
234
|
+
requestId: string;
|
|
144
235
|
};
|
|
236
|
+
export type R5dctlSessionStartInput = R5dctlSessionStartBaseInput & ({
|
|
237
|
+
worktree: string;
|
|
238
|
+
newWorktree?: never;
|
|
239
|
+
source?: never;
|
|
240
|
+
} | {
|
|
241
|
+
worktree?: never;
|
|
242
|
+
newWorktree: string;
|
|
243
|
+
source: R5dctlWorktreeSource;
|
|
244
|
+
});
|
|
145
245
|
export type DeviceAuthorizationStartResponse = {
|
|
146
246
|
requestId: string;
|
|
147
247
|
deviceCode: string;
|
|
@@ -256,7 +356,7 @@ export type R5dctlWorkspaceStatus = {
|
|
|
256
356
|
desiredCanonicalHead: string | null;
|
|
257
357
|
dirtyGeneration: number;
|
|
258
358
|
publishedGeneration: number;
|
|
259
|
-
|
|
359
|
+
publicationState: "idle" | "scheduled" | "preparing" | "submitting" | "blocked";
|
|
260
360
|
casRetries: number;
|
|
261
361
|
lastNotifiedHead: string | null;
|
|
262
362
|
lastNotifiedAt: string | null;
|
|
@@ -431,7 +531,9 @@ export declare class R5dctlClient {
|
|
|
431
531
|
setToken(token?: string): void;
|
|
432
532
|
setApiKey(apiKey?: string): void;
|
|
433
533
|
private resolveBearerToken;
|
|
534
|
+
private authHeaders;
|
|
434
535
|
private request;
|
|
536
|
+
private events;
|
|
435
537
|
readonly auth: {
|
|
436
538
|
deviceStart: (input: {
|
|
437
539
|
deviceName: string;
|
|
@@ -534,30 +636,18 @@ export declare class R5dctlClient {
|
|
|
534
636
|
branch?: string;
|
|
535
637
|
}) => Promise<R5dctlSessionSummary[]>;
|
|
536
638
|
create: (projectRef: string, input: R5dctlSessionCreateInput) => Promise<R5dctlSessionDescription>;
|
|
639
|
+
start: (projectRef: string, input: R5dctlSessionStartInput) => Promise<R5dctlSessionRunResponse>;
|
|
537
640
|
};
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
641
|
+
worktrees: {
|
|
642
|
+
merge: (projectRef: string, sourceWorktree: string, input: {
|
|
643
|
+
worker?: string;
|
|
644
|
+
conflictMode: R5dctlMergeConflictMode;
|
|
645
|
+
}) => Promise<R5dctlWorktreeMergeResponse>;
|
|
646
|
+
finishMerge: (projectRef: string, conflictWorktree: string, input: {
|
|
647
|
+
worker: string;
|
|
648
|
+
summary?: string;
|
|
649
|
+
}) => Promise<R5dctlWorktreeMergeResponse>;
|
|
544
650
|
};
|
|
545
|
-
mergeChanges: (projectRef: string, input: {
|
|
546
|
-
targetBranch: string;
|
|
547
|
-
sourceBranch: string;
|
|
548
|
-
}) => Promise<R5dctlMergeResult>;
|
|
549
|
-
continueMerge: (projectRef: string, input: {
|
|
550
|
-
targetBranch: string;
|
|
551
|
-
}) => Promise<R5dctlContinueMergeResult>;
|
|
552
|
-
abortMerge: (projectRef: string, input: {
|
|
553
|
-
targetBranch: string;
|
|
554
|
-
}) => Promise<R5dctlAbortMergeResult>;
|
|
555
|
-
};
|
|
556
|
-
readonly agents: {
|
|
557
|
-
status: (sessionId: string) => Promise<R5dctlAgentStatusResponse>;
|
|
558
|
-
sendPrompt: (sessionId: string, input: {
|
|
559
|
-
prompt: string;
|
|
560
|
-
}) => Promise<R5dctlAgentStatusResponse>;
|
|
561
651
|
};
|
|
562
652
|
readonly sessions: {
|
|
563
653
|
recent: (input?: {
|
|
@@ -568,6 +658,10 @@ export declare class R5dctlClient {
|
|
|
568
658
|
delete: (sessionId: string) => Promise<{
|
|
569
659
|
success: boolean;
|
|
570
660
|
}>;
|
|
661
|
+
status: (sessionId: string) => Promise<R5dctlSessionRunResponse>;
|
|
662
|
+
events: (sessionId: string, input?: {
|
|
663
|
+
signal?: AbortSignal;
|
|
664
|
+
}) => AsyncGenerator<R5dctlSessionEvent, any, any>;
|
|
571
665
|
conversation: (sessionId: string, input?: R5dctlConversationRenderOptions) => Promise<R5dctlConversationResponse>;
|
|
572
666
|
conversationOverview: (sessionId: string) => Promise<R5dctlConversationOverviewResponse>;
|
|
573
667
|
inspectConversationNode: (sessionId: string, nodeId: string) => Promise<R5dctlConversationNodeResponse>;
|
|
@@ -575,16 +669,28 @@ export declare class R5dctlClient {
|
|
|
575
669
|
detail?: R5dctlConversationWorkDetail;
|
|
576
670
|
}) => Promise<R5dctlConversationWorkResponse>;
|
|
577
671
|
prompt: (sessionId: string, input: {
|
|
578
|
-
|
|
579
|
-
|
|
672
|
+
prompt: string;
|
|
673
|
+
worker: string;
|
|
674
|
+
mode: R5dctlSessionMode;
|
|
580
675
|
model: ModelTier;
|
|
581
|
-
|
|
676
|
+
requestId: string;
|
|
677
|
+
}) => Promise<R5dctlSessionPromptResponse>;
|
|
678
|
+
stop: (sessionId: string) => Promise<R5dctlSessionStopResponse>;
|
|
582
679
|
answerQuestions: (sessionId: string, input: {
|
|
583
680
|
answers: string[];
|
|
584
|
-
|
|
681
|
+
worker: string;
|
|
682
|
+
mode: ChatMode;
|
|
683
|
+
model: ModelTier;
|
|
684
|
+
requestId: string;
|
|
685
|
+
}) => Promise<R5dctlSessionPromptResponse>;
|
|
585
686
|
answerEnvRequest: (sessionId: string, input: {
|
|
586
687
|
envs?: string[];
|
|
587
688
|
additionalContext?: string;
|
|
588
|
-
|
|
689
|
+
worker: string;
|
|
690
|
+
mode: ChatMode;
|
|
691
|
+
model: ModelTier;
|
|
692
|
+
requestId: string;
|
|
693
|
+
}) => Promise<R5dctlSessionPromptResponse>;
|
|
589
694
|
};
|
|
590
695
|
}
|
|
696
|
+
export {};
|