Contract: pass approval option warnings, omit threadId on host pushes
This commit is contained in:
1 parent
7ad1045be4
commit
21215210e3
6 files changed
+12
-10
No files matched your search
+4
-3
@@ -87,7 +87,8 @@ PendingRequest {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
For questions (`kind: "user_input"`), `options` is empty and `questions` lists
|
An option may also carry `warning`, a short note about a risky choice such as "Applies to every
|
||||||
|
thread". For questions (`kind: "user_input"`), `options` is empty and `questions` lists
|
||||||
`{ id, header, question, options: [{ label, value }], allowCustomAnswer }`.
|
`{ id, header, question, options: [{ label, value }], allowCustomAnswer }`.
|
||||||
|
|
||||||
## Thread
|
## Thread
|
||||||
@@ -145,8 +146,8 @@ The new thread uses the project's default model, or the host's, and the host's d
|
|||||||
## Notifications
|
## Notifications
|
||||||
|
|
||||||
The gateway pushes when a thread starts waiting for you, finishes, or fails. Each push has an
|
The gateway pushes when a thread starts waiting for you, finishes, or fails. Each push has an
|
||||||
`aps.category` and the custom keys `hostId`, `threadId`, and, for approvals and questions,
|
`aps.category` and the custom keys `hostId`, `threadId` (absent on `host` pushes), and, for
|
||||||
`requestId`.
|
approvals and questions, `requestId`.
|
||||||
|
|
||||||
| Category | When | Actions the watch registers |
|
| Category | When | Actions the watch registers |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ export interface PendingRequest {
|
|||||||
/** What the agent wants to do, such as the command line. Null when the server gave none. */
|
/** What the agent wants to do, such as the command line. Null when the server gave none. */
|
||||||
prompt: string | null;
|
prompt: string | null;
|
||||||
reason: string | null;
|
reason: string | null;
|
||||||
/** Approval choices, in the server's order. Empty for questions. */
|
/** Approval choices, in the server's order. Empty for questions. `warning` flags a risky choice. */
|
||||||
options: Array<{ decision: ApprovalDecision; label: string }>;
|
options: Array<{ decision: ApprovalDecision; label: string; warning?: string }>;
|
||||||
/** Questions for the user. Empty for approvals. */
|
/** Questions for the user. Empty for approvals. */
|
||||||
questions: Array<{
|
questions: Array<{
|
||||||
id: string;
|
id: string;
|
||||||
@@ -126,7 +126,8 @@ export interface ErrorResponse {
|
|||||||
/** Custom keys on every push notification, beside `aps`. */
|
/** Custom keys on every push notification, beside `aps`. */
|
||||||
export interface PushPayload {
|
export interface PushPayload {
|
||||||
hostId: string;
|
hostId: string;
|
||||||
threadId: string;
|
/** Absent on `host` pushes, which are about a host rather than a thread. */
|
||||||
|
threadId?: string;
|
||||||
requestId?: string;
|
requestId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ const sendPush: SendPush = async (push) => {
|
|||||||
alert: { title: push.title, ...(push.subtitle ? { subtitle: push.subtitle } : {}), body: push.body },
|
alert: { title: push.title, ...(push.subtitle ? { subtitle: push.subtitle } : {}), body: push.body },
|
||||||
sound: "default",
|
sound: "default",
|
||||||
category: push.category,
|
category: push.category,
|
||||||
"thread-id": push.data.threadId || push.data.hostId,
|
"thread-id": push.data.threadId ?? push.data.hostId,
|
||||||
},
|
},
|
||||||
...push.data,
|
...push.data,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export class Notifier {
|
|||||||
title: label,
|
title: label,
|
||||||
body,
|
body,
|
||||||
category: "host",
|
category: "host",
|
||||||
data: { hostId, threadId: "" },
|
data: { hostId },
|
||||||
collapseId: `host:${hostId}`,
|
collapseId: `host:${hostId}`,
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ function pendingRequest(thread: ThreadShell, turnItems: BoundedThread["projectio
|
|||||||
);
|
);
|
||||||
if (item && isApprovalRequest(item)) {
|
if (item && isApprovalRequest(item)) {
|
||||||
const options = item.options?.length
|
const options = item.options?.length
|
||||||
? item.options.map(({ decision, label }) => ({ decision, label }))
|
? item.options.map(({ decision, label, warning }) => ({ decision, label, ...(warning ? { warning } : {}) }))
|
||||||
: [
|
: [
|
||||||
{ decision: "accept" as const, label: "Allow" },
|
{ decision: "accept" as const, label: "Allow" },
|
||||||
{ decision: "decline" as const, label: "Deny" },
|
{ decision: "decline" as const, label: "Deny" },
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ describe("summarize", () => {
|
|||||||
reason: null,
|
reason: null,
|
||||||
options: [
|
options: [
|
||||||
{ decision: "accept", label: "Allow once" },
|
{ decision: "accept", label: "Allow once" },
|
||||||
{ decision: "acceptAlways", label: "Always allow" },
|
{ decision: "acceptAlways", label: "Always allow", warning: "Applies to every thread" },
|
||||||
{ decision: "decline", label: "Deny" },
|
{ decision: "decline", label: "Deny" },
|
||||||
],
|
],
|
||||||
questions: [],
|
questions: [],
|
||||||
|
|||||||
Reference in new issue
Block a user