@paigy/harness 0.3.10 → 0.3.11
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/dist/agy-acp.js +144 -0
- package/dist/cli.js +18 -53
- package/dist/main.js +17 -52
- package/package.json +4 -2
package/dist/agy-acp.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// src/harness/agy-acp.ts
|
|
5
|
+
import { spawn } from "child_process";
|
|
6
|
+
import { randomUUID } from "crypto";
|
|
7
|
+
import { createInterface } from "readline";
|
|
8
|
+
var frame = (body) => JSON.stringify({ jsonrpc: "2.0", ...body });
|
|
9
|
+
function agyArgs(bypass) {
|
|
10
|
+
return [
|
|
11
|
+
"--input-format",
|
|
12
|
+
"stream-json",
|
|
13
|
+
"--output-format",
|
|
14
|
+
"stream-json",
|
|
15
|
+
...bypass ? ["--dangerously-skip-permissions"] : [],
|
|
16
|
+
"--print="
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
var AgyAcp = class {
|
|
20
|
+
sessionId;
|
|
21
|
+
cwd = process.cwd();
|
|
22
|
+
bypass = false;
|
|
23
|
+
started = false;
|
|
24
|
+
promptId;
|
|
25
|
+
/** A frame from the harness. */
|
|
26
|
+
fromClient(msg) {
|
|
27
|
+
const out = { client: [], agy: [] };
|
|
28
|
+
if (msg.method === void 0 || msg.id === void 0) return out;
|
|
29
|
+
switch (msg.method) {
|
|
30
|
+
case "initialize":
|
|
31
|
+
out.client.push(frame({ id: msg.id, result: { protocolVersion: 2, agentCapabilities: {}, authMethods: [] } }));
|
|
32
|
+
return out;
|
|
33
|
+
case "session/new":
|
|
34
|
+
this.sessionId = randomUUID();
|
|
35
|
+
if (typeof msg.params?.cwd === "string") this.cwd = msg.params.cwd;
|
|
36
|
+
out.client.push(frame({ id: msg.id, result: { sessionId: this.sessionId } }));
|
|
37
|
+
return out;
|
|
38
|
+
case "session/set_mode":
|
|
39
|
+
case "session/set_config_option": {
|
|
40
|
+
const value = msg.params?.modeId ?? msg.params?.value;
|
|
41
|
+
if (typeof value === "string") this.bypass = value === "bypassPermissions";
|
|
42
|
+
out.client.push(frame({ id: msg.id, result: {} }));
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
case "session/prompt": {
|
|
46
|
+
const blocks = msg.params?.prompt ?? [];
|
|
47
|
+
const content = blocks.map((b) => b.type === "text" ? b.text ?? "" : "").filter(Boolean).join("\n\n");
|
|
48
|
+
if (!this.started) {
|
|
49
|
+
this.started = true;
|
|
50
|
+
out.start = { cwd: this.cwd, args: agyArgs(this.bypass) };
|
|
51
|
+
}
|
|
52
|
+
this.promptId = msg.id;
|
|
53
|
+
out.agy.push(JSON.stringify({ event: "user", message: { role: "user", content } }));
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
default:
|
|
57
|
+
out.client.push(frame({ id: msg.id, error: { code: -32601, message: `Method not found: ${msg.method}` } }));
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** A line from `agy`. */
|
|
62
|
+
fromAgy(line) {
|
|
63
|
+
const out = { client: [], agy: [] };
|
|
64
|
+
let ev;
|
|
65
|
+
try {
|
|
66
|
+
ev = JSON.parse(line);
|
|
67
|
+
} catch {
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
const update = (body) => out.client.push(frame({ method: "session/update", params: { sessionId: this.sessionId, update: body } }));
|
|
71
|
+
if (ev.event === "step_update") {
|
|
72
|
+
const s = ev.step_update ?? {};
|
|
73
|
+
if (s.step_type === "agent_response" && typeof s.text_delta === "string" && s.text_delta) {
|
|
74
|
+
update({ sessionUpdate: "agent_message_chunk", content: { type: "text", text: s.text_delta } });
|
|
75
|
+
} else if (s.step_type === "tool" && s.state === "ACTIVE" && typeof s.tool_name === "string") {
|
|
76
|
+
update({ sessionUpdate: "tool_call", title: s.tool_name, kind: s.tool_name });
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
if (ev.event === "result" && this.promptId !== void 0) {
|
|
81
|
+
const r = ev.result ?? {};
|
|
82
|
+
const denied = Array.isArray(r.denied_actions) ? r.denied_actions : [];
|
|
83
|
+
if (denied.length) {
|
|
84
|
+
const names = denied.map((d) => d.display_name ?? d.action ?? "a tool").join(", ");
|
|
85
|
+
update({ sessionUpdate: "agent_message_chunk", content: {
|
|
86
|
+
type: "text",
|
|
87
|
+
text: `
|
|
88
|
+
|
|
89
|
+
Antigravity cannot ask for permission when it runs in the background, so it was denied: ${names}.`
|
|
90
|
+
} });
|
|
91
|
+
}
|
|
92
|
+
const id = this.promptId;
|
|
93
|
+
this.promptId = void 0;
|
|
94
|
+
out.client.push(r.status === "SUCCESS" ? frame({ id, result: { stopReason: "end_turn" } }) : frame({ id, error: { code: -32e3, message: String(r.error ?? r.status ?? "agy turn failed") } }));
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
/** `agy` exited: a turn still open fails by name rather than hanging the harness. */
|
|
99
|
+
exited(code) {
|
|
100
|
+
const out = { client: [], agy: [] };
|
|
101
|
+
if (this.promptId !== void 0) {
|
|
102
|
+
out.client.push(frame({ id: this.promptId, error: { code: -32e3, message: `agy exited ${code ?? "by signal"}` } }));
|
|
103
|
+
this.promptId = void 0;
|
|
104
|
+
}
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
function main() {
|
|
109
|
+
const adapter = new AgyAcp();
|
|
110
|
+
let agy;
|
|
111
|
+
const apply = (out) => {
|
|
112
|
+
for (const f of out.client) process.stdout.write(`${f}
|
|
113
|
+
`);
|
|
114
|
+
if (out.start) {
|
|
115
|
+
agy = spawn("agy", out.start.args, { cwd: out.start.cwd, stdio: ["pipe", "pipe", "pipe"], env: process.env });
|
|
116
|
+
createInterface({ input: agy.stdout }).on("line", (l) => apply(adapter.fromAgy(l)));
|
|
117
|
+
agy.stderr.on("data", (chunk) => process.stderr.write(chunk));
|
|
118
|
+
agy.on("exit", (code) => {
|
|
119
|
+
apply(adapter.exited(code));
|
|
120
|
+
process.exit(code ?? 1);
|
|
121
|
+
});
|
|
122
|
+
agy.on("error", (e) => {
|
|
123
|
+
process.stderr.write(`agy: ${e.message}
|
|
124
|
+
`);
|
|
125
|
+
apply(adapter.exited(null));
|
|
126
|
+
process.exit(1);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
for (const l of out.agy) agy?.stdin?.write(`${l}
|
|
130
|
+
`);
|
|
131
|
+
};
|
|
132
|
+
createInterface({ input: process.stdin }).on("line", (line) => {
|
|
133
|
+
try {
|
|
134
|
+
apply(adapter.fromClient(JSON.parse(line)));
|
|
135
|
+
} catch {
|
|
136
|
+
}
|
|
137
|
+
}).on("close", () => {
|
|
138
|
+
agy?.stdin?.end();
|
|
139
|
+
if (!agy) process.exit(0);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/agy-acp.ts
|
|
144
|
+
main();
|
package/dist/cli.js
CHANGED
|
@@ -125,6 +125,8 @@ var init_catalog = __esm({
|
|
|
125
125
|
name: "agy",
|
|
126
126
|
label: "Antigravity",
|
|
127
127
|
cli: "agy",
|
|
128
|
+
// `agy` has no ACP mode; its adapter ships inside the harness (`harness/agy-acp.ts`).
|
|
129
|
+
adapter: "paigy-agy-acp",
|
|
128
130
|
authProbe: ["agy", "help"],
|
|
129
131
|
loginHint: "Install and set up Antigravity (`agy`).",
|
|
130
132
|
installCli: "curl -fsSL https://antigravity.dev/install.sh | bash"
|
|
@@ -23893,7 +23895,7 @@ async function listNotes(opts = {}) {
|
|
|
23893
23895
|
}
|
|
23894
23896
|
async function listConnections(opts = {}) {
|
|
23895
23897
|
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/tokens`, {
|
|
23896
|
-
headers: { authorization: `Bearer ${authToken(opts.token)}
|
|
23898
|
+
headers: { authorization: `Bearer ${authToken(opts.token)}`, "x-paigy-model": "goal-entry-v1" }
|
|
23897
23899
|
}));
|
|
23898
23900
|
if (!res.ok) throw new Error(`list_connections failed: ${res.status} ${await res.text()}`);
|
|
23899
23901
|
return await res.json();
|
|
@@ -23940,9 +23942,7 @@ async function contact(input, opts = {}) {
|
|
|
23940
23942
|
const read = async (signal2) => {
|
|
23941
23943
|
const res = ensureAuthed(await send2(`${BACKEND_URL}/api/deliveries/${encodeURIComponent(deliveryId)}`, { headers, signal: signal2 }));
|
|
23942
23944
|
if (!res.ok) await fail("read_delivery", res);
|
|
23943
|
-
|
|
23944
|
-
return delivery.kind === "notification" ? { ...delivery, message: `${delivery.message}
|
|
23945
|
-
Inbox delivery is asynchronous; use claim_goal/get_goal to collect durable answers. Do not poll this Notification.` } : delivery;
|
|
23945
|
+
return await res.json();
|
|
23946
23946
|
};
|
|
23947
23947
|
const settled = (d) => d.kind === "notification" || d.state === "closed" || d.answers.length > 0 || d.entries.some((e) => e.kind === "contribution");
|
|
23948
23948
|
if (opts.waits === false) return read(opts.signal);
|
|
@@ -24062,7 +24062,7 @@ async function subscribeWake(onNudge, opts = {}) {
|
|
|
24062
24062
|
}
|
|
24063
24063
|
};
|
|
24064
24064
|
}
|
|
24065
|
-
var import_undici, require2, __create2, __defProp2, __getOwnPropDesc2, __getOwnPropNames2, __getProtoOf2, __hasOwnProp2, __require2, __commonJS2, __copyProps2, __toESM2, require_nacl_fast, BACKEND_URL, NETWORK_MSG, PROXY_ENV, agent, INSTANCE_ID, WORKSPACE_ID, envSession, SESSION_ID, ignoreOverride, defaultOptions, getDefaultOptions, getRefs, getRelativePath, parseCatchDef, integerDateParser, isJsonSchema7AllOfType, emojiRegex2, zodPatterns, ALPHA_NUMERIC, primitiveMappings, asAnyOf, parseOptionalDef, parsePipelineDef, parseReadonlyDef, selectParser, get$ref, addMeta, zodToJsonSchema, OPTIONS_MIN, OPTIONS_MAX, StartContactSchema, ContactSchema, CONTACT_SCHEMA, CONTACT_DESCRIPTION, CreateGoalSchema, CreateGoalToolSchema, CREATE_GOAL_DESCRIPTION, UpdateGoalSchema, UpdateGoalToolSchema, ClaimGoalSchema, GetGoalSchema, GET_GOAL_DESCRIPTION, UPDATE_GOAL_DESCRIPTION, CLAIM_GOAL_DESCRIPTION, CHECK_REPLIES_DESCRIPTION, CheckRepliesSchema, GetThreadSchema, GET_THREAD_DESCRIPTION, SearchThreadsSchema, SEARCH_THREADS_DESCRIPTION, AGENT_TOOLS, AGENT_TOOL_NAMES, ContextSchema, ParticipantSchema, TransformSchema, OptionSchema, VisualSchema, NotifyLevelSchema, SelectShapeSchema, ReceiptEventSchema, AttentionSchema, NotifyRequestFields, NotifyRequestSchema, NotifyStatusSchema, AgentStateSchema, TurnSchema, UserAnswerSchema, IntentSchema, RideAlongSchema, AwaitItemSchema, VoiceKeySchema, AgendaTurnSchema, CLAIM_STALE_MS, InboxItemSchema, APNS_TOKEN_RE, PushTokenSchema, MissedCallSchema, BrokerTuningSchema, UserSettingsSchema, HistoryItemSchema, ACTIVITY_LINES, ACTIVITY_LINE_MAX, AgentActivitySchema, ConnectionSummarySchema, LedgerItemSchema, AgentLedgerSchema, ReassignResultSchema, MoveRingSchema, MoveSchema, QueueQuestionSchema, QueueItemSchema, NoteSourceSchema, NoteStatusSchema, NoteRepeatSchema, DecisionSchema, NoteSchema, TriageItemSchema, TriageAssignmentSchema, TriageStatusSchema, SubmitTriageSchema, TriageProposalSchema, AcceptTriageSchema, AcceptTriageResultSchema, DeliveryModeSchema, WAKE_EVENT, wakeChannel, RegisterDeliverySchema, OAuthStartSchema, DeliveryConfigSchema,
|
|
24065
|
+
var import_undici, require2, __create2, __defProp2, __getOwnPropDesc2, __getOwnPropNames2, __getProtoOf2, __hasOwnProp2, __require2, __commonJS2, __copyProps2, __toESM2, require_nacl_fast, BACKEND_URL, NETWORK_MSG, PROXY_ENV, agent, INSTANCE_ID, WORKSPACE_ID, envSession, SESSION_ID, ignoreOverride, defaultOptions, getDefaultOptions, getRefs, getRelativePath, parseCatchDef, integerDateParser, isJsonSchema7AllOfType, emojiRegex2, zodPatterns, ALPHA_NUMERIC, primitiveMappings, asAnyOf, parseOptionalDef, parsePipelineDef, parseReadonlyDef, selectParser, get$ref, addMeta, zodToJsonSchema, OPTIONS_MIN, OPTIONS_MAX, StartContactSchema, ContactSchema, CONTACT_SCHEMA, CONTACT_DESCRIPTION, CreateGoalSchema, CreateGoalToolSchema, CREATE_GOAL_DESCRIPTION, UpdateGoalSchema, UpdateGoalToolSchema, ClaimGoalSchema, GetGoalSchema, GET_GOAL_DESCRIPTION, UPDATE_GOAL_DESCRIPTION, CLAIM_GOAL_DESCRIPTION, CHECK_REPLIES_DESCRIPTION, CheckRepliesSchema, GetThreadSchema, GET_THREAD_DESCRIPTION, SearchThreadsSchema, SEARCH_THREADS_DESCRIPTION, AGENT_TOOLS, AGENT_TOOL_NAMES, ContextSchema, ParticipantSchema, TransformSchema, OptionSchema, VisualSchema, NotifyLevelSchema, SelectShapeSchema, ReceiptEventSchema, AttentionSchema, NotifyRequestFields, NotifyRequestSchema, NotifyStatusSchema, AgentStateSchema, TurnSchema, UserAnswerSchema, IntentSchema, RideAlongSchema, AwaitItemSchema, VoiceKeySchema, AgendaTurnSchema, CLAIM_STALE_MS, InboxItemSchema, APNS_TOKEN_RE, PushTokenSchema, MissedCallSchema, BrokerTuningSchema, UserSettingsSchema, HistoryItemSchema, ACTIVITY_LINES, ACTIVITY_LINE_MAX, AgentActivitySchema, ConnectionSummarySchema, LedgerItemSchema, AgentLedgerSchema, ReassignResultSchema, MoveRingSchema, MoveSchema, QueueQuestionSchema, QueueItemSchema, NoteSourceSchema, NoteStatusSchema, NoteRepeatSchema, DecisionSchema, NoteSchema, TriageItemSchema, TriageAssignmentSchema, TriageStatusSchema, SubmitTriageSchema, TriageProposalSchema, AcceptTriageSchema, AcceptTriageResultSchema, DeliveryModeSchema, WAKE_EVENT, wakeChannel, RegisterDeliverySchema, OAuthStartSchema, DeliveryConfigSchema, EnvelopeRecipientSchema, EnvelopeHeaderSchema, EnvelopeSchema, SealedAnswerSchema, DeviceCredentialSchema, DeviceRosterSchema, WakeNudgeSchema, PairingStatusSchema, PairingRevealSchema, DeviceCodeSchema, DeviceInfoSchema, DeviceTokenSchema, SupportRequestSchema, NotificationFeedbackKindSchema, FeedbackResolutionSchema, FeedbackOutcomeSchema, import_tweetnacl, import_tweetnacl2, import_tweetnacl3, import_tweetnacl4, import_tweetnacl5, AGENT_NAME, TOKEN_PATH, KEY_PATH, sleep, UnpairedError, ApiError, AWAIT_WINDOW_MS, tokenOverride, authToken, HEARTBEAT_MS, RETRY_MS, JOIN, lines;
|
|
24066
24066
|
var init_dist = __esm({
|
|
24067
24067
|
"../../packages/sdk/dist/index.js"() {
|
|
24068
24068
|
"use strict";
|
|
@@ -26774,10 +26774,10 @@ var init_dist = __esm({
|
|
|
26774
26774
|
UpdateGoalToolSchema = UpdateGoalSchema.omit({ operationId: true }).extend({ goalId: external_exports.string().uuid() }).strict();
|
|
26775
26775
|
ClaimGoalSchema = external_exports.object({ goalId: external_exports.string().uuid().optional() }).strict();
|
|
26776
26776
|
GetGoalSchema = external_exports.object({ goalId: external_exports.string().uuid() }).strict();
|
|
26777
|
-
GET_GOAL_DESCRIPTION = "Read
|
|
26778
|
-
UPDATE_GOAL_DESCRIPTION = "Update an owned Goal at an exact revision. State, ownership, dependencies, children, progress, and review acknowledgement are explicit; stale revisions are rejected. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. Returns the
|
|
26779
|
-
CLAIM_GOAL_DESCRIPTION = "Claim the oldest runnable or review-pending Goal you own, or pass goalId to claim that Goal. Returns
|
|
26780
|
-
CHECK_REPLIES_DESCRIPTION = "Your open Deliveries: every Notification or Call currently addressed to you \u2014 a request the user started toward you, an answer relayed to something you asked, a handoff \u2014 one row each: its Goals,
|
|
26777
|
+
GET_GOAL_DESCRIPTION = "Read one Goal without claiming it: its outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), and `next`, the one step to take. Foreign or sibling-owned Goals are not disclosed.";
|
|
26778
|
+
UPDATE_GOAL_DESCRIPTION = "Update an owned Goal at an exact revision. State, ownership, dependencies, children, progress, and review acknowledgement are explicit; stale revisions are rejected. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. Returns the Goal as get_goal reads it, at its new revision.";
|
|
26779
|
+
CLAIM_GOAL_DESCRIPTION = "Claim the oldest runnable or review-pending Goal you own, or pass goalId to claim that Goal. Returns the Goal as get_goal reads it, and creates or renews the execution lease.";
|
|
26780
|
+
CHECK_REPLIES_DESCRIPTION = "Your open Deliveries: every Notification or Call currently addressed to you \u2014 a request the user started toward you, an answer relayed to something you asked, a handoff \u2014 one row each: its Goals, how many decisions are still open, and the newest words in brief. A pure read with no arguments: nothing is consumed, acknowledged or claimed by reading it, so call it on startup, after a long wait, or whenever you want to know what is outstanding. To act on one, claim its Goal (claim_goal) or reread it in full with contact({deliveryId}). Once you have acted on what arrived, update_goal with reviewed: true closes the Deliveries addressed to you on that Goal. Your runnable and review-pending Goals come from claim_goal, not from here.";
|
|
26781
26781
|
CheckRepliesSchema = external_exports.object({}).strict();
|
|
26782
26782
|
GetThreadSchema = external_exports.object({
|
|
26783
26783
|
parentId: external_exports.string().describe("The Thread to read \u2014 the threadId a Delivery returned, or the parentId of a search hit.")
|
|
@@ -27718,25 +27718,6 @@ var init_dist = __esm({
|
|
|
27718
27718
|
* carries credentials; only a `poll` registration can come back with null here. */
|
|
27719
27719
|
realtime: external_exports.object({ url: external_exports.string(), anonKey: external_exports.string() }).nullable()
|
|
27720
27720
|
});
|
|
27721
|
-
StatusSchema = external_exports.object({
|
|
27722
|
-
name: external_exports.string(),
|
|
27723
|
-
sessionMode: external_exports.enum(["default", "all_calls", "silent"]),
|
|
27724
|
-
/** A phone is registered for push/ring (any push token on the account). */
|
|
27725
|
-
phone: external_exports.boolean(),
|
|
27726
|
-
/** HOW MANY THINGS ARE WAITING ON THIS IDENTITY — replies it never collected and requests
|
|
27727
|
-
* it never picked up. THE SAME NUMBER the harness's wake gate reads
|
|
27728
|
-
* (`pendingSummary.unacknowledged`), from the same function, because a statusline saying
|
|
27729
|
-
* zero while the sweep sees one is two ideas of "waiting".
|
|
27730
|
-
*
|
|
27731
|
-
* Why it is here at all (owner, 2026-09-07): nothing can interrupt an idle agent process
|
|
27732
|
-
* that nobody spawned, so a terminal session only learns of work by asking. The harness
|
|
27733
|
-
* used to paper over that by spawning a SECOND process on the identity; now it stands
|
|
27734
|
-
* back, correctly, and the person sitting at the terminal is the one who can act. A
|
|
27735
|
-
* coffee-beans request sat unread for three days.
|
|
27736
|
-
*
|
|
27737
|
-
* Optional: an older API sends no field, and the statusline then renders exactly as before. */
|
|
27738
|
-
waiting: external_exports.number().int().nonnegative().optional()
|
|
27739
|
-
});
|
|
27740
27721
|
EnvelopeRecipientSchema = external_exports.object({
|
|
27741
27722
|
keyId: external_exports.string(),
|
|
27742
27723
|
epk: external_exports.string(),
|
|
@@ -33379,7 +33360,7 @@ init_catalog();
|
|
|
33379
33360
|
var ADAPTER_BIN = {
|
|
33380
33361
|
claude: "claude-agent-acp",
|
|
33381
33362
|
codex: "codex-acp",
|
|
33382
|
-
agy: "agy"
|
|
33363
|
+
agy: "paigy-agy-acp"
|
|
33383
33364
|
};
|
|
33384
33365
|
function splitLines(buffer, chunk) {
|
|
33385
33366
|
const combined = buffer + chunk;
|
|
@@ -34842,10 +34823,10 @@ var UpdateGoalSchema2 = external_exports.object({
|
|
|
34842
34823
|
var UpdateGoalToolSchema2 = UpdateGoalSchema2.omit({ operationId: true }).extend({ goalId: external_exports.string().uuid() }).strict();
|
|
34843
34824
|
var ClaimGoalSchema2 = external_exports.object({ goalId: external_exports.string().uuid().optional() }).strict();
|
|
34844
34825
|
var GetGoalSchema2 = external_exports.object({ goalId: external_exports.string().uuid() }).strict();
|
|
34845
|
-
var GET_GOAL_DESCRIPTION2 = "Read
|
|
34846
|
-
var UPDATE_GOAL_DESCRIPTION2 = "Update an owned Goal at an exact revision. State, ownership, dependencies, children, progress, and review acknowledgement are explicit; stale revisions are rejected. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. Returns the
|
|
34847
|
-
var CLAIM_GOAL_DESCRIPTION2 = "Claim the oldest runnable or review-pending Goal you own, or pass goalId to claim that Goal. Returns
|
|
34848
|
-
var CHECK_REPLIES_DESCRIPTION2 = "Your open Deliveries: every Notification or Call currently addressed to you \u2014 a request the user started toward you, an answer relayed to something you asked, a handoff \u2014 one row each: its Goals,
|
|
34826
|
+
var GET_GOAL_DESCRIPTION2 = "Read one Goal without claiming it: its outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), and `next`, the one step to take. Foreign or sibling-owned Goals are not disclosed.";
|
|
34827
|
+
var UPDATE_GOAL_DESCRIPTION2 = "Update an owned Goal at an exact revision. State, ownership, dependencies, children, progress, and review acknowledgement are explicit; stale revisions are rejected. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. Returns the Goal as get_goal reads it, at its new revision.";
|
|
34828
|
+
var CLAIM_GOAL_DESCRIPTION2 = "Claim the oldest runnable or review-pending Goal you own, or pass goalId to claim that Goal. Returns the Goal as get_goal reads it, and creates or renews the execution lease.";
|
|
34829
|
+
var CHECK_REPLIES_DESCRIPTION2 = "Your open Deliveries: every Notification or Call currently addressed to you \u2014 a request the user started toward you, an answer relayed to something you asked, a handoff \u2014 one row each: its Goals, how many decisions are still open, and the newest words in brief. A pure read with no arguments: nothing is consumed, acknowledged or claimed by reading it, so call it on startup, after a long wait, or whenever you want to know what is outstanding. To act on one, claim its Goal (claim_goal) or reread it in full with contact({deliveryId}). Once you have acted on what arrived, update_goal with reviewed: true closes the Deliveries addressed to you on that Goal. Your runnable and review-pending Goals come from claim_goal, not from here.";
|
|
34849
34830
|
var CheckRepliesSchema2 = external_exports.object({}).strict();
|
|
34850
34831
|
var GetThreadSchema2 = external_exports.object({
|
|
34851
34832
|
parentId: external_exports.string().describe("The Thread to read \u2014 the threadId a Delivery returned, or the parentId of a search hit.")
|
|
@@ -35799,25 +35780,6 @@ var DeliveryConfigSchema2 = external_exports.object({
|
|
|
35799
35780
|
* carries credentials; only a `poll` registration can come back with null here. */
|
|
35800
35781
|
realtime: external_exports.object({ url: external_exports.string(), anonKey: external_exports.string() }).nullable()
|
|
35801
35782
|
});
|
|
35802
|
-
var StatusSchema2 = external_exports.object({
|
|
35803
|
-
name: external_exports.string(),
|
|
35804
|
-
sessionMode: external_exports.enum(["default", "all_calls", "silent"]),
|
|
35805
|
-
/** A phone is registered for push/ring (any push token on the account). */
|
|
35806
|
-
phone: external_exports.boolean(),
|
|
35807
|
-
/** HOW MANY THINGS ARE WAITING ON THIS IDENTITY — replies it never collected and requests
|
|
35808
|
-
* it never picked up. THE SAME NUMBER the harness's wake gate reads
|
|
35809
|
-
* (`pendingSummary.unacknowledged`), from the same function, because a statusline saying
|
|
35810
|
-
* zero while the sweep sees one is two ideas of "waiting".
|
|
35811
|
-
*
|
|
35812
|
-
* Why it is here at all (owner, 2026-09-07): nothing can interrupt an idle agent process
|
|
35813
|
-
* that nobody spawned, so a terminal session only learns of work by asking. The harness
|
|
35814
|
-
* used to paper over that by spawning a SECOND process on the identity; now it stands
|
|
35815
|
-
* back, correctly, and the person sitting at the terminal is the one who can act. A
|
|
35816
|
-
* coffee-beans request sat unread for three days.
|
|
35817
|
-
*
|
|
35818
|
-
* Optional: an older API sends no field, and the statusline then renders exactly as before. */
|
|
35819
|
-
waiting: external_exports.number().int().nonnegative().optional()
|
|
35820
|
-
});
|
|
35821
35783
|
var EnvelopeRecipientSchema2 = external_exports.object({
|
|
35822
35784
|
keyId: external_exports.string(),
|
|
35823
35785
|
epk: external_exports.string(),
|
|
@@ -36004,7 +35966,9 @@ async function step(session, state, rail) {
|
|
|
36004
35966
|
unheard(brief2, state);
|
|
36005
35967
|
if (ended(brief2.state)) await rail.update(brief2.goalId, { revision: brief2.revision, changes: { reviewed: true }, reason: "Typed into the session." });
|
|
36006
35968
|
else state.goal = { id: brief2.goalId, revision: brief2.revision };
|
|
36007
|
-
|
|
35969
|
+
const outcome = brief2.outcome?.trim() ?? "";
|
|
35970
|
+
const said = (brief2.entries ?? []).map((e) => entryWords(e).trim()).filter((w) => w && w.toLowerCase() !== outcome.toLowerCase());
|
|
35971
|
+
send(session, state, [outcome, ...said].filter(Boolean).join("\n\n"));
|
|
36008
35972
|
return;
|
|
36009
35973
|
}
|
|
36010
35974
|
const brief = await rail.read(state.goal.id);
|
|
@@ -36359,6 +36323,7 @@ function startHost(opts) {
|
|
|
36359
36323
|
const asHost = { token: opts.token };
|
|
36360
36324
|
const refreshIdentities = async () => {
|
|
36361
36325
|
for (const slot of listSlots()) {
|
|
36326
|
+
if (slot === "Desktop") continue;
|
|
36362
36327
|
const token = readToken(slot);
|
|
36363
36328
|
if (!token) continue;
|
|
36364
36329
|
const me = await whoAmI({ token }).catch(() => null);
|
package/dist/main.js
CHANGED
|
@@ -12234,10 +12234,10 @@ var UpdateGoalSchema = external_exports.object({
|
|
|
12234
12234
|
var UpdateGoalToolSchema = UpdateGoalSchema.omit({ operationId: true }).extend({ goalId: external_exports.string().uuid() }).strict();
|
|
12235
12235
|
var ClaimGoalSchema = external_exports.object({ goalId: external_exports.string().uuid().optional() }).strict();
|
|
12236
12236
|
var GetGoalSchema = external_exports.object({ goalId: external_exports.string().uuid() }).strict();
|
|
12237
|
-
var GET_GOAL_DESCRIPTION = "Read
|
|
12238
|
-
var UPDATE_GOAL_DESCRIPTION = "Update an owned Goal at an exact revision. State, ownership, dependencies, children, progress, and review acknowledgement are explicit; stale revisions are rejected. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. Returns the
|
|
12239
|
-
var CLAIM_GOAL_DESCRIPTION = "Claim the oldest runnable or review-pending Goal you own, or pass goalId to claim that Goal. Returns
|
|
12240
|
-
var CHECK_REPLIES_DESCRIPTION = "Your open Deliveries: every Notification or Call currently addressed to you \u2014 a request the user started toward you, an answer relayed to something you asked, a handoff \u2014 one row each: its Goals,
|
|
12237
|
+
var GET_GOAL_DESCRIPTION = "Read one Goal without claiming it: its outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), and `next`, the one step to take. Foreign or sibling-owned Goals are not disclosed.";
|
|
12238
|
+
var UPDATE_GOAL_DESCRIPTION = "Update an owned Goal at an exact revision. State, ownership, dependencies, children, progress, and review acknowledgement are explicit; stale revisions are rejected. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. Returns the Goal as get_goal reads it, at its new revision.";
|
|
12239
|
+
var CLAIM_GOAL_DESCRIPTION = "Claim the oldest runnable or review-pending Goal you own, or pass goalId to claim that Goal. Returns the Goal as get_goal reads it, and creates or renews the execution lease.";
|
|
12240
|
+
var CHECK_REPLIES_DESCRIPTION = "Your open Deliveries: every Notification or Call currently addressed to you \u2014 a request the user started toward you, an answer relayed to something you asked, a handoff \u2014 one row each: its Goals, how many decisions are still open, and the newest words in brief. A pure read with no arguments: nothing is consumed, acknowledged or claimed by reading it, so call it on startup, after a long wait, or whenever you want to know what is outstanding. To act on one, claim its Goal (claim_goal) or reread it in full with contact({deliveryId}). Once you have acted on what arrived, update_goal with reviewed: true closes the Deliveries addressed to you on that Goal. Your runnable and review-pending Goals come from claim_goal, not from here.";
|
|
12241
12241
|
var CheckRepliesSchema = external_exports.object({}).strict();
|
|
12242
12242
|
var GetThreadSchema = external_exports.object({
|
|
12243
12243
|
parentId: external_exports.string().describe("The Thread to read \u2014 the threadId a Delivery returned, or the parentId of a search hit.")
|
|
@@ -13233,25 +13233,6 @@ var DeliveryConfigSchema = external_exports.object({
|
|
|
13233
13233
|
* carries credentials; only a `poll` registration can come back with null here. */
|
|
13234
13234
|
realtime: external_exports.object({ url: external_exports.string(), anonKey: external_exports.string() }).nullable()
|
|
13235
13235
|
});
|
|
13236
|
-
var StatusSchema = external_exports.object({
|
|
13237
|
-
name: external_exports.string(),
|
|
13238
|
-
sessionMode: external_exports.enum(["default", "all_calls", "silent"]),
|
|
13239
|
-
/** A phone is registered for push/ring (any push token on the account). */
|
|
13240
|
-
phone: external_exports.boolean(),
|
|
13241
|
-
/** HOW MANY THINGS ARE WAITING ON THIS IDENTITY — replies it never collected and requests
|
|
13242
|
-
* it never picked up. THE SAME NUMBER the harness's wake gate reads
|
|
13243
|
-
* (`pendingSummary.unacknowledged`), from the same function, because a statusline saying
|
|
13244
|
-
* zero while the sweep sees one is two ideas of "waiting".
|
|
13245
|
-
*
|
|
13246
|
-
* Why it is here at all (owner, 2026-09-07): nothing can interrupt an idle agent process
|
|
13247
|
-
* that nobody spawned, so a terminal session only learns of work by asking. The harness
|
|
13248
|
-
* used to paper over that by spawning a SECOND process on the identity; now it stands
|
|
13249
|
-
* back, correctly, and the person sitting at the terminal is the one who can act. A
|
|
13250
|
-
* coffee-beans request sat unread for three days.
|
|
13251
|
-
*
|
|
13252
|
-
* Optional: an older API sends no field, and the statusline then renders exactly as before. */
|
|
13253
|
-
waiting: external_exports.number().int().nonnegative().optional()
|
|
13254
|
-
});
|
|
13255
13236
|
var EnvelopeRecipientSchema = external_exports.object({
|
|
13256
13237
|
keyId: external_exports.string(),
|
|
13257
13238
|
epk: external_exports.string(),
|
|
@@ -13593,7 +13574,7 @@ async function listNotes(opts = {}) {
|
|
|
13593
13574
|
}
|
|
13594
13575
|
async function listConnections(opts = {}) {
|
|
13595
13576
|
const res = ensureAuthed(await reach(`${BACKEND_URL}/api/tokens`, {
|
|
13596
|
-
headers: { authorization: `Bearer ${authToken(opts.token)}
|
|
13577
|
+
headers: { authorization: `Bearer ${authToken(opts.token)}`, "x-paigy-model": "goal-entry-v1" }
|
|
13597
13578
|
}));
|
|
13598
13579
|
if (!res.ok) throw new Error(`list_connections failed: ${res.status} ${await res.text()}`);
|
|
13599
13580
|
return await res.json();
|
|
@@ -13655,9 +13636,7 @@ async function contact(input, opts = {}) {
|
|
|
13655
13636
|
const read = async (signal2) => {
|
|
13656
13637
|
const res = ensureAuthed(await send2(`${BACKEND_URL}/api/deliveries/${encodeURIComponent(deliveryId)}`, { headers, signal: signal2 }));
|
|
13657
13638
|
if (!res.ok) await fail("read_delivery", res);
|
|
13658
|
-
|
|
13659
|
-
return delivery.kind === "notification" ? { ...delivery, message: `${delivery.message}
|
|
13660
|
-
Inbox delivery is asynchronous; use claim_goal/get_goal to collect durable answers. Do not poll this Notification.` } : delivery;
|
|
13639
|
+
return await res.json();
|
|
13661
13640
|
};
|
|
13662
13641
|
const settled = (d) => d.kind === "notification" || d.state === "closed" || d.answers.length > 0 || d.entries.some((e) => e.kind === "contribution");
|
|
13663
13642
|
if (opts.waits === false) return read(opts.signal);
|
|
@@ -13816,6 +13795,8 @@ var CATALOG = [
|
|
|
13816
13795
|
name: "agy",
|
|
13817
13796
|
label: "Antigravity",
|
|
13818
13797
|
cli: "agy",
|
|
13798
|
+
// `agy` has no ACP mode; its adapter ships inside the harness (`harness/agy-acp.ts`).
|
|
13799
|
+
adapter: "paigy-agy-acp",
|
|
13819
13800
|
authProbe: ["agy", "help"],
|
|
13820
13801
|
loginHint: "Install and set up Antigravity (`agy`).",
|
|
13821
13802
|
installCli: "curl -fsSL https://antigravity.dev/install.sh | bash"
|
|
@@ -15305,10 +15286,10 @@ var UpdateGoalSchema2 = external_exports.object({
|
|
|
15305
15286
|
var UpdateGoalToolSchema2 = UpdateGoalSchema2.omit({ operationId: true }).extend({ goalId: external_exports.string().uuid() }).strict();
|
|
15306
15287
|
var ClaimGoalSchema2 = external_exports.object({ goalId: external_exports.string().uuid().optional() }).strict();
|
|
15307
15288
|
var GetGoalSchema2 = external_exports.object({ goalId: external_exports.string().uuid() }).strict();
|
|
15308
|
-
var GET_GOAL_DESCRIPTION2 = "Read
|
|
15309
|
-
var UPDATE_GOAL_DESCRIPTION2 = "Update an owned Goal at an exact revision. State, ownership, dependencies, children, progress, and review acknowledgement are explicit; stale revisions are rejected. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. Returns the
|
|
15310
|
-
var CLAIM_GOAL_DESCRIPTION2 = "Claim the oldest runnable or review-pending Goal you own, or pass goalId to claim that Goal. Returns
|
|
15311
|
-
var CHECK_REPLIES_DESCRIPTION2 = "Your open Deliveries: every Notification or Call currently addressed to you \u2014 a request the user started toward you, an answer relayed to something you asked, a handoff \u2014 one row each: its Goals,
|
|
15289
|
+
var GET_GOAL_DESCRIPTION2 = "Read one Goal without claiming it: its outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), and `next`, the one step to take. Foreign or sibling-owned Goals are not disclosed.";
|
|
15290
|
+
var UPDATE_GOAL_DESCRIPTION2 = "Update an owned Goal at an exact revision. State, ownership, dependencies, children, progress, and review acknowledgement are explicit; stale revisions are rejected. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision. dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. Returns the Goal as get_goal reads it, at its new revision.";
|
|
15291
|
+
var CLAIM_GOAL_DESCRIPTION2 = "Claim the oldest runnable or review-pending Goal you own, or pass goalId to claim that Goal. Returns the Goal as get_goal reads it, and creates or renews the execution lease.";
|
|
15292
|
+
var CHECK_REPLIES_DESCRIPTION2 = "Your open Deliveries: every Notification or Call currently addressed to you \u2014 a request the user started toward you, an answer relayed to something you asked, a handoff \u2014 one row each: its Goals, how many decisions are still open, and the newest words in brief. A pure read with no arguments: nothing is consumed, acknowledged or claimed by reading it, so call it on startup, after a long wait, or whenever you want to know what is outstanding. To act on one, claim its Goal (claim_goal) or reread it in full with contact({deliveryId}). Once you have acted on what arrived, update_goal with reviewed: true closes the Deliveries addressed to you on that Goal. Your runnable and review-pending Goals come from claim_goal, not from here.";
|
|
15312
15293
|
var CheckRepliesSchema2 = external_exports.object({}).strict();
|
|
15313
15294
|
var GetThreadSchema2 = external_exports.object({
|
|
15314
15295
|
parentId: external_exports.string().describe("The Thread to read \u2014 the threadId a Delivery returned, or the parentId of a search hit.")
|
|
@@ -16262,25 +16243,6 @@ var DeliveryConfigSchema2 = external_exports.object({
|
|
|
16262
16243
|
* carries credentials; only a `poll` registration can come back with null here. */
|
|
16263
16244
|
realtime: external_exports.object({ url: external_exports.string(), anonKey: external_exports.string() }).nullable()
|
|
16264
16245
|
});
|
|
16265
|
-
var StatusSchema2 = external_exports.object({
|
|
16266
|
-
name: external_exports.string(),
|
|
16267
|
-
sessionMode: external_exports.enum(["default", "all_calls", "silent"]),
|
|
16268
|
-
/** A phone is registered for push/ring (any push token on the account). */
|
|
16269
|
-
phone: external_exports.boolean(),
|
|
16270
|
-
/** HOW MANY THINGS ARE WAITING ON THIS IDENTITY — replies it never collected and requests
|
|
16271
|
-
* it never picked up. THE SAME NUMBER the harness's wake gate reads
|
|
16272
|
-
* (`pendingSummary.unacknowledged`), from the same function, because a statusline saying
|
|
16273
|
-
* zero while the sweep sees one is two ideas of "waiting".
|
|
16274
|
-
*
|
|
16275
|
-
* Why it is here at all (owner, 2026-09-07): nothing can interrupt an idle agent process
|
|
16276
|
-
* that nobody spawned, so a terminal session only learns of work by asking. The harness
|
|
16277
|
-
* used to paper over that by spawning a SECOND process on the identity; now it stands
|
|
16278
|
-
* back, correctly, and the person sitting at the terminal is the one who can act. A
|
|
16279
|
-
* coffee-beans request sat unread for three days.
|
|
16280
|
-
*
|
|
16281
|
-
* Optional: an older API sends no field, and the statusline then renders exactly as before. */
|
|
16282
|
-
waiting: external_exports.number().int().nonnegative().optional()
|
|
16283
|
-
});
|
|
16284
16246
|
var EnvelopeRecipientSchema2 = external_exports.object({
|
|
16285
16247
|
keyId: external_exports.string(),
|
|
16286
16248
|
epk: external_exports.string(),
|
|
@@ -16657,7 +16619,7 @@ var frame2 = (body) => JSON.stringify({ jsonrpc: "2.0", ...body });
|
|
|
16657
16619
|
var ADAPTER_BIN = {
|
|
16658
16620
|
claude: "claude-agent-acp",
|
|
16659
16621
|
codex: "codex-acp",
|
|
16660
|
-
agy: "agy"
|
|
16622
|
+
agy: "paigy-agy-acp"
|
|
16661
16623
|
};
|
|
16662
16624
|
function splitLines(buffer, chunk) {
|
|
16663
16625
|
const combined = buffer + chunk;
|
|
@@ -16759,7 +16721,9 @@ async function step(session, state, rail) {
|
|
|
16759
16721
|
unheard(brief2, state);
|
|
16760
16722
|
if (ended(brief2.state)) await rail.update(brief2.goalId, { revision: brief2.revision, changes: { reviewed: true }, reason: "Typed into the session." });
|
|
16761
16723
|
else state.goal = { id: brief2.goalId, revision: brief2.revision };
|
|
16762
|
-
|
|
16724
|
+
const outcome = brief2.outcome?.trim() ?? "";
|
|
16725
|
+
const said = (brief2.entries ?? []).map((e) => entryWords(e).trim()).filter((w) => w && w.toLowerCase() !== outcome.toLowerCase());
|
|
16726
|
+
send(session, state, [outcome, ...said].filter(Boolean).join("\n\n"));
|
|
16763
16727
|
return;
|
|
16764
16728
|
}
|
|
16765
16729
|
const brief = await rail.read(state.goal.id);
|
|
@@ -17088,6 +17052,7 @@ function startHost(opts) {
|
|
|
17088
17052
|
const asHost = { token: opts.token };
|
|
17089
17053
|
const refreshIdentities = async () => {
|
|
17090
17054
|
for (const slot of listSlots()) {
|
|
17055
|
+
if (slot === "Desktop") continue;
|
|
17091
17056
|
const token = readToken(slot);
|
|
17092
17057
|
if (!token) continue;
|
|
17093
17058
|
const me = await whoAmI({ token }).catch(() => null);
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paigy/harness",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.11",
|
|
4
4
|
"description": "Run Claude Code / Codex on this machine, bridged to Paigy — launchable from your phone.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/main.js",
|
|
8
8
|
"bin": {
|
|
9
9
|
"paigy-harness": "dist/cli.js",
|
|
10
|
-
"paigy": "dist/cli.js"
|
|
10
|
+
"paigy": "dist/cli.js",
|
|
11
|
+
"paigy-agy-acp": "dist/agy-acp.js"
|
|
11
12
|
},
|
|
12
13
|
"scripts": {
|
|
13
14
|
"build": "tsup",
|
|
@@ -32,6 +33,7 @@
|
|
|
32
33
|
},
|
|
33
34
|
"files": [
|
|
34
35
|
"dist/cli.js",
|
|
36
|
+
"dist/agy-acp.js",
|
|
35
37
|
"README.md"
|
|
36
38
|
],
|
|
37
39
|
"publishConfig": {
|