@ricsam/r5d-api 0.0.60 → 0.0.62
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 +11 -7
- package/dist/cjs/index.cjs +107 -45
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/index.mjs +107 -45
- package/dist/mjs/package.json +1 -1
- package/dist/types/index.d.ts +143 -44
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,22 +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.
|
|
62
|
-
- `
|
|
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? })`
|
|
63
64
|
- `sessions.describe(sessionId)`
|
|
64
65
|
- `sessions.update(sessionId, { name })`
|
|
65
66
|
- `sessions.delete(sessionId)`
|
|
66
67
|
- `sessions.conversation(sessionId)`
|
|
68
|
+
- `sessions.events(sessionId, { signal? })`
|
|
67
69
|
- `sessions.conversationOverview(sessionId)`
|
|
68
70
|
- `sessions.inspectConversationNode(sessionId, nodeId)`
|
|
69
71
|
- `sessions.inspectConversationWork(sessionId, workId, { detail? })`
|
|
70
|
-
- `sessions.
|
|
71
|
-
- `sessions.
|
|
72
|
-
- `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 })`
|
|
73
77
|
|
|
74
|
-
`
|
|
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.
|
|
75
79
|
|
|
76
|
-
`projects.
|
|
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.
|
|
77
81
|
|
|
78
82
|
## Errors
|
|
79
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,26 @@ class R5dctlClient {
|
|
|
294
361
|
method: "POST",
|
|
295
362
|
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/sessions`,
|
|
296
363
|
body: input
|
|
364
|
+
}),
|
|
365
|
+
start: (projectRef, input) => this.request({
|
|
366
|
+
method: "POST",
|
|
367
|
+
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/sessions/start`,
|
|
368
|
+
body: input
|
|
297
369
|
})
|
|
298
370
|
},
|
|
299
|
-
|
|
300
|
-
|
|
371
|
+
worktrees: {
|
|
372
|
+
merge: (projectRef, sourceWorktree, input) => this.request({
|
|
301
373
|
method: "POST",
|
|
302
|
-
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/
|
|
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`,
|
|
303
380
|
body: input
|
|
304
381
|
})
|
|
305
382
|
}
|
|
306
383
|
};
|
|
307
|
-
agents = {
|
|
308
|
-
status: (sessionId) => this.request({
|
|
309
|
-
method: "GET",
|
|
310
|
-
path: `/api/r5dctl/agents/${encodeURIComponent(sessionId)}`
|
|
311
|
-
}),
|
|
312
|
-
sendPrompt: (sessionId, input) => this.request({
|
|
313
|
-
method: "POST",
|
|
314
|
-
path: `/api/r5dctl/agents/${encodeURIComponent(sessionId)}/prompt`,
|
|
315
|
-
body: input
|
|
316
|
-
}),
|
|
317
|
-
merge: (sessionId, input) => this.request({
|
|
318
|
-
method: "POST",
|
|
319
|
-
path: `/api/r5dctl/agents/${encodeURIComponent(sessionId)}/merge`,
|
|
320
|
-
body: input
|
|
321
|
-
}),
|
|
322
|
-
stop: (sessionId) => this.request({
|
|
323
|
-
method: "POST",
|
|
324
|
-
path: `/api/r5dctl/agents/${encodeURIComponent(sessionId)}/stop`
|
|
325
|
-
}),
|
|
326
|
-
finishMerge: (sessionId, input) => this.request({
|
|
327
|
-
method: "POST",
|
|
328
|
-
path: `/api/r5dctl/agents/${encodeURIComponent(sessionId)}/finish-merge`,
|
|
329
|
-
body: input
|
|
330
|
-
})
|
|
331
|
-
};
|
|
332
384
|
sessions = {
|
|
333
385
|
recent: (input = {}) => this.request({
|
|
334
386
|
method: "GET",
|
|
@@ -348,6 +400,11 @@ class R5dctlClient {
|
|
|
348
400
|
method: "DELETE",
|
|
349
401
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}`
|
|
350
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),
|
|
351
408
|
conversation: (sessionId, input = {}) => this.request({
|
|
352
409
|
method: "GET",
|
|
353
410
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/conversation`,
|
|
@@ -377,6 +434,11 @@ class R5dctlClient {
|
|
|
377
434
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/prompt`,
|
|
378
435
|
body: input
|
|
379
436
|
}),
|
|
437
|
+
stop: (sessionId) => this.request({
|
|
438
|
+
method: "POST",
|
|
439
|
+
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/stop`,
|
|
440
|
+
body: {}
|
|
441
|
+
}),
|
|
380
442
|
answerQuestions: (sessionId, input) => this.request({
|
|
381
443
|
method: "POST",
|
|
382
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,26 @@ class R5dctlClient {
|
|
|
270
337
|
method: "POST",
|
|
271
338
|
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/sessions`,
|
|
272
339
|
body: input
|
|
340
|
+
}),
|
|
341
|
+
start: (projectRef, input) => this.request({
|
|
342
|
+
method: "POST",
|
|
343
|
+
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/sessions/start`,
|
|
344
|
+
body: input
|
|
273
345
|
})
|
|
274
346
|
},
|
|
275
|
-
|
|
276
|
-
|
|
347
|
+
worktrees: {
|
|
348
|
+
merge: (projectRef, sourceWorktree, input) => this.request({
|
|
277
349
|
method: "POST",
|
|
278
|
-
path: `/api/r5dctl/projects/${encodeURIComponent(projectRef)}/
|
|
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`,
|
|
279
356
|
body: input
|
|
280
357
|
})
|
|
281
358
|
}
|
|
282
359
|
};
|
|
283
|
-
agents = {
|
|
284
|
-
status: (sessionId) => this.request({
|
|
285
|
-
method: "GET",
|
|
286
|
-
path: `/api/r5dctl/agents/${encodeURIComponent(sessionId)}`
|
|
287
|
-
}),
|
|
288
|
-
sendPrompt: (sessionId, input) => this.request({
|
|
289
|
-
method: "POST",
|
|
290
|
-
path: `/api/r5dctl/agents/${encodeURIComponent(sessionId)}/prompt`,
|
|
291
|
-
body: input
|
|
292
|
-
}),
|
|
293
|
-
merge: (sessionId, input) => this.request({
|
|
294
|
-
method: "POST",
|
|
295
|
-
path: `/api/r5dctl/agents/${encodeURIComponent(sessionId)}/merge`,
|
|
296
|
-
body: input
|
|
297
|
-
}),
|
|
298
|
-
stop: (sessionId) => this.request({
|
|
299
|
-
method: "POST",
|
|
300
|
-
path: `/api/r5dctl/agents/${encodeURIComponent(sessionId)}/stop`
|
|
301
|
-
}),
|
|
302
|
-
finishMerge: (sessionId, input) => this.request({
|
|
303
|
-
method: "POST",
|
|
304
|
-
path: `/api/r5dctl/agents/${encodeURIComponent(sessionId)}/finish-merge`,
|
|
305
|
-
body: input
|
|
306
|
-
})
|
|
307
|
-
};
|
|
308
360
|
sessions = {
|
|
309
361
|
recent: (input = {}) => this.request({
|
|
310
362
|
method: "GET",
|
|
@@ -324,6 +376,11 @@ class R5dctlClient {
|
|
|
324
376
|
method: "DELETE",
|
|
325
377
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}`
|
|
326
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),
|
|
327
384
|
conversation: (sessionId, input = {}) => this.request({
|
|
328
385
|
method: "GET",
|
|
329
386
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/conversation`,
|
|
@@ -353,6 +410,11 @@ class R5dctlClient {
|
|
|
353
410
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/prompt`,
|
|
354
411
|
body: input
|
|
355
412
|
}),
|
|
413
|
+
stop: (sessionId) => this.request({
|
|
414
|
+
method: "POST",
|
|
415
|
+
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/stop`,
|
|
416
|
+
body: {}
|
|
417
|
+
}),
|
|
356
418
|
answerQuestions: (sessionId, input) => this.request({
|
|
357
419
|
method: "POST",
|
|
358
420
|
path: `/api/r5dctl/sessions/${encodeURIComponent(sessionId)}/answer-questions`,
|
package/dist/mjs/package.json
CHANGED
package/dist/types/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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 R5dctlAgentSource = {
|
|
4
|
+
export type R5dctlWorktreeSource = {
|
|
5
5
|
type: "worktree";
|
|
6
6
|
branchName: string;
|
|
7
7
|
};
|
|
@@ -69,6 +69,81 @@ export type R5dctlConversationResponse = {
|
|
|
69
69
|
pendingQuestions: R5dctlPendingQuestion[];
|
|
70
70
|
requestedEnvs: R5dctlRequestedEnv[];
|
|
71
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: "fresh_context_failed";
|
|
135
|
+
message: string;
|
|
136
|
+
} | {
|
|
137
|
+
type: "shell_result";
|
|
138
|
+
stdout: string;
|
|
139
|
+
stderr: string;
|
|
140
|
+
exitCode: number;
|
|
141
|
+
fileChanges: unknown[];
|
|
142
|
+
cwd: string;
|
|
143
|
+
} | {
|
|
144
|
+
type: string;
|
|
145
|
+
[key: string]: unknown;
|
|
146
|
+
};
|
|
72
147
|
export type R5dctlConversationWorkDetail = "compact" | "summary" | "full";
|
|
73
148
|
export type R5dctlConversationWorkMetadata = {
|
|
74
149
|
id: string;
|
|
@@ -98,31 +173,31 @@ export type R5dctlConversationWorkResponse = {
|
|
|
98
173
|
detail: R5dctlConversationWorkDetail;
|
|
99
174
|
workText: string;
|
|
100
175
|
};
|
|
101
|
-
export type
|
|
102
|
-
export type
|
|
103
|
-
status: "merged" | "up_to_date" | "conflicts" | "resolving" | "failed" | "stale";
|
|
176
|
+
export type R5dctlSessionRunStatus = "idle" | "provisioning" | "queued" | "running" | "completed" | "failed" | "stopped";
|
|
177
|
+
export type R5dctlWorktreeMergeResponse = {
|
|
178
|
+
status: "merged" | "up_to_date" | "conflicts" | "conflict_worktree_created" | "resolving" | "failed" | "stale";
|
|
104
179
|
attemptId?: string;
|
|
105
|
-
|
|
106
|
-
|
|
180
|
+
sourceWorktree: string;
|
|
181
|
+
targetWorktree: string;
|
|
182
|
+
conflictWorktree?: string;
|
|
107
183
|
commitHash?: string;
|
|
108
184
|
resolverSessionId?: string;
|
|
109
|
-
resolverBranch?: string;
|
|
110
185
|
folderPath?: string;
|
|
111
186
|
worker?: string;
|
|
112
187
|
conflictedFiles?: string[];
|
|
113
188
|
failureReason?: string;
|
|
114
189
|
message?: string;
|
|
115
190
|
};
|
|
116
|
-
export type
|
|
191
|
+
export type R5dctlMergeConflictMode = "none" | "worktree" | "agent";
|
|
192
|
+
export type R5dctlSessionRunResponse = {
|
|
117
193
|
sessionId: string;
|
|
118
194
|
branchName: string;
|
|
119
|
-
source: R5dctlAgentSource;
|
|
120
195
|
baselineCommit: string | null;
|
|
121
196
|
workspaceHead: string | null;
|
|
122
197
|
worker: string;
|
|
123
|
-
status:
|
|
124
|
-
runStatus:
|
|
125
|
-
|
|
198
|
+
status: R5dctlSessionRunStatus;
|
|
199
|
+
runStatus: R5dctlSessionRunStatus;
|
|
200
|
+
generation: number;
|
|
126
201
|
createdAt: string;
|
|
127
202
|
updatedAt: string;
|
|
128
203
|
queuedAt?: string;
|
|
@@ -137,12 +212,31 @@ export type R5dctlAgentStatusResponse = {
|
|
|
137
212
|
diffSummary: string;
|
|
138
213
|
sessionPath: string;
|
|
139
214
|
sessionUrl?: string;
|
|
140
|
-
merge?: R5dctlAgentMergeStatus;
|
|
141
215
|
};
|
|
142
|
-
export type
|
|
143
|
-
export type
|
|
216
|
+
export type R5dctlSessionStartResponse = R5dctlSessionRunResponse;
|
|
217
|
+
export type R5dctlSessionStatusResponse = R5dctlSessionRunResponse;
|
|
218
|
+
export type R5dctlSessionPromptResponse = R5dctlSessionRunResponse & {
|
|
144
219
|
promptDisposition: "queued" | "started";
|
|
145
220
|
};
|
|
221
|
+
export type R5dctlSessionStopResponse = {
|
|
222
|
+
sessionId: string;
|
|
223
|
+
status: "stopped";
|
|
224
|
+
};
|
|
225
|
+
type R5dctlSessionStartBaseInput = {
|
|
226
|
+
worker: string;
|
|
227
|
+
model: ModelTier;
|
|
228
|
+
prompt: string;
|
|
229
|
+
requestId: string;
|
|
230
|
+
};
|
|
231
|
+
export type R5dctlSessionStartInput = R5dctlSessionStartBaseInput & ({
|
|
232
|
+
worktree: string;
|
|
233
|
+
newWorktree?: never;
|
|
234
|
+
source?: never;
|
|
235
|
+
} | {
|
|
236
|
+
worktree?: never;
|
|
237
|
+
newWorktree: string;
|
|
238
|
+
source: R5dctlWorktreeSource;
|
|
239
|
+
});
|
|
146
240
|
export type DeviceAuthorizationStartResponse = {
|
|
147
241
|
requestId: string;
|
|
148
242
|
deviceCode: string;
|
|
@@ -432,7 +526,9 @@ export declare class R5dctlClient {
|
|
|
432
526
|
setToken(token?: string): void;
|
|
433
527
|
setApiKey(apiKey?: string): void;
|
|
434
528
|
private resolveBearerToken;
|
|
529
|
+
private authHeaders;
|
|
435
530
|
private request;
|
|
531
|
+
private events;
|
|
436
532
|
readonly auth: {
|
|
437
533
|
deviceStart: (input: {
|
|
438
534
|
deviceName: string;
|
|
@@ -535,32 +631,19 @@ export declare class R5dctlClient {
|
|
|
535
631
|
branch?: string;
|
|
536
632
|
}) => Promise<R5dctlSessionSummary[]>;
|
|
537
633
|
create: (projectRef: string, input: R5dctlSessionCreateInput) => Promise<R5dctlSessionDescription>;
|
|
634
|
+
start: (projectRef: string, input: R5dctlSessionStartInput) => Promise<R5dctlSessionRunResponse>;
|
|
538
635
|
};
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
636
|
+
worktrees: {
|
|
637
|
+
merge: (projectRef: string, sourceWorktree: string, input: {
|
|
638
|
+
worker?: string;
|
|
639
|
+
conflictMode: R5dctlMergeConflictMode;
|
|
640
|
+
}) => Promise<R5dctlWorktreeMergeResponse>;
|
|
641
|
+
finishMerge: (projectRef: string, conflictWorktree: string, input: {
|
|
544
642
|
worker: string;
|
|
545
|
-
|
|
546
|
-
}) => Promise<
|
|
643
|
+
summary?: string;
|
|
644
|
+
}) => Promise<R5dctlWorktreeMergeResponse>;
|
|
547
645
|
};
|
|
548
646
|
};
|
|
549
|
-
readonly agents: {
|
|
550
|
-
status: (sessionId: string) => Promise<R5dctlAgentStatusResponse>;
|
|
551
|
-
sendPrompt: (sessionId: string, input: {
|
|
552
|
-
prompt: string;
|
|
553
|
-
worker: string;
|
|
554
|
-
}) => Promise<R5dctlAgentPromptResponse>;
|
|
555
|
-
merge: (sessionId: string, input: {
|
|
556
|
-
worker: string;
|
|
557
|
-
}) => Promise<R5dctlAgentStatusResponse>;
|
|
558
|
-
stop: (sessionId: string) => Promise<R5dctlAgentStatusResponse>;
|
|
559
|
-
finishMerge: (sessionId: string, input: {
|
|
560
|
-
worker: string;
|
|
561
|
-
summary: string;
|
|
562
|
-
}) => Promise<R5dctlAgentStatusResponse>;
|
|
563
|
-
};
|
|
564
647
|
readonly sessions: {
|
|
565
648
|
recent: (input?: {
|
|
566
649
|
limit?: number;
|
|
@@ -570,6 +653,10 @@ export declare class R5dctlClient {
|
|
|
570
653
|
delete: (sessionId: string) => Promise<{
|
|
571
654
|
success: boolean;
|
|
572
655
|
}>;
|
|
656
|
+
status: (sessionId: string) => Promise<R5dctlSessionRunResponse>;
|
|
657
|
+
events: (sessionId: string, input?: {
|
|
658
|
+
signal?: AbortSignal;
|
|
659
|
+
}) => AsyncGenerator<R5dctlSessionEvent, any, any>;
|
|
573
660
|
conversation: (sessionId: string, input?: R5dctlConversationRenderOptions) => Promise<R5dctlConversationResponse>;
|
|
574
661
|
conversationOverview: (sessionId: string) => Promise<R5dctlConversationOverviewResponse>;
|
|
575
662
|
inspectConversationNode: (sessionId: string, nodeId: string) => Promise<R5dctlConversationNodeResponse>;
|
|
@@ -577,16 +664,28 @@ export declare class R5dctlClient {
|
|
|
577
664
|
detail?: R5dctlConversationWorkDetail;
|
|
578
665
|
}) => Promise<R5dctlConversationWorkResponse>;
|
|
579
666
|
prompt: (sessionId: string, input: {
|
|
580
|
-
|
|
581
|
-
|
|
667
|
+
prompt: string;
|
|
668
|
+
worker: string;
|
|
669
|
+
mode: R5dctlSessionMode;
|
|
582
670
|
model: ModelTier;
|
|
583
|
-
|
|
671
|
+
requestId: string;
|
|
672
|
+
}) => Promise<R5dctlSessionPromptResponse>;
|
|
673
|
+
stop: (sessionId: string) => Promise<R5dctlSessionStopResponse>;
|
|
584
674
|
answerQuestions: (sessionId: string, input: {
|
|
585
675
|
answers: string[];
|
|
586
|
-
|
|
676
|
+
worker: string;
|
|
677
|
+
mode: ChatMode;
|
|
678
|
+
model: ModelTier;
|
|
679
|
+
requestId: string;
|
|
680
|
+
}) => Promise<R5dctlSessionPromptResponse>;
|
|
587
681
|
answerEnvRequest: (sessionId: string, input: {
|
|
588
682
|
envs?: string[];
|
|
589
683
|
additionalContext?: string;
|
|
590
|
-
|
|
684
|
+
worker: string;
|
|
685
|
+
mode: ChatMode;
|
|
686
|
+
model: ModelTier;
|
|
687
|
+
requestId: string;
|
|
688
|
+
}) => Promise<R5dctlSessionPromptResponse>;
|
|
591
689
|
};
|
|
592
690
|
}
|
|
691
|
+
export {};
|