ace-wake 0.1.0 → 0.2.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/handbook/extensions/ace-wake/wake/eyes-runtime.js +29 -10
- data/lib/ace/wake/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c2dff41db21b22ff36dbe9d9dda962979e2598072dfba16a406b81cdb1fb0cbf
|
|
4
|
+
data.tar.gz: f303030a7487b009196d4a4f1ffe92ea90f4872e66b20a9549871c968c85eaa9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e3284df4db91ce0b48fa1714b00b818622d0df1c20ee7d5f4b7812683f545696bbeed3bb11089a066825726cd3d5a81d09836747c9ee276b503bae19028770e8
|
|
7
|
+
data.tar.gz: 9496ea0bc29040ce63e62c2be847a782b4b7c0237efa5982a9793dcc9b81de2d5e591bb3b33cc4d9b8e862b7fda6f0477b16a691e67ba2e2e3c5e33d9f77e358
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.2.0] - 2026-10-31
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Agent-callable eyes start with configPath, returning initial pending revisions
|
|
15
|
+
without a redundant wake; quota breakers and retirement remain protected.
|
|
16
|
+
|
|
8
17
|
## [0.1.0] - 2026-10-30
|
|
9
18
|
|
|
10
19
|
First publishable release of the ace-wake asset package (task family
|
|
@@ -25,7 +25,7 @@ export async function observeHitl(cwd, config) {
|
|
|
25
25
|
|
|
26
26
|
export function registerEyes(pi, { observe = observeHitl, now = Date.now,
|
|
27
27
|
schedule = (fn, ms) => setInterval(fn, ms), cancel = clearInterval } = {}) {
|
|
28
|
-
let eyes, timer, attempt, compacting = false, running = false;
|
|
28
|
+
let eyes, timer, attempt, observedSources, bindingGeneration = 0, compacting = false, running = false, arming = false;
|
|
29
29
|
const stopTimer = () => { if (timer !== undefined) cancel(timer); timer = undefined; };
|
|
30
30
|
function arm() {
|
|
31
31
|
stopTimer();
|
|
@@ -35,7 +35,8 @@ export function registerEyes(pi, { observe = observeHitl, now = Date.now,
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
const bind = (ctx) => {
|
|
38
|
-
|
|
38
|
+
const generation = ++bindingGeneration;
|
|
39
|
+
stopTimer(); eyes?.dispose(); attempt = undefined; observedSources = undefined; compacting = false; running = false;
|
|
39
40
|
const entries = ctx.sessionManager.getBranch();
|
|
40
41
|
const snapshot = [...entries].reverse().find((e) => e.type === "custom" && e.customType === EYES_ENTRY)?.data;
|
|
41
42
|
const ownerCwd = path.resolve(ctx.cwd);
|
|
@@ -50,8 +51,14 @@ export function registerEyes(pi, { observe = observeHitl, now = Date.now,
|
|
|
50
51
|
ctx.ui?.setStatus?.("ace-eyes", `eyes ${state.retired ? "retired" : state.breaker?.reason || (state.enabled ? "observing" : "off")} pending:${state.pending}`);
|
|
51
52
|
if (state.breaker || state.retired) stopTimer();
|
|
52
53
|
},
|
|
53
|
-
observe: (config) =>
|
|
54
|
-
|
|
54
|
+
observe: async (config) => {
|
|
55
|
+
const result = await observe(ctx.cwd, config);
|
|
56
|
+
// A disposed binding can still finish its asynchronous owner read.
|
|
57
|
+
// Its source health is never evidence for the current session binding.
|
|
58
|
+
if (generation === bindingGeneration) observedSources = result.sources;
|
|
59
|
+
return result;
|
|
60
|
+
},
|
|
61
|
+
canDeliver: () => !arming && !compacting && (ctx.isIdle() || running),
|
|
55
62
|
deliveryStatus: () => {
|
|
56
63
|
if (attempt?.accepted) return "accepted";
|
|
57
64
|
// sendUserMessage is a void wrapper. Busy/queued is uncertain, not
|
|
@@ -61,8 +68,8 @@ export function registerEyes(pi, { observe = observeHitl, now = Date.now,
|
|
|
61
68
|
},
|
|
62
69
|
deliver: async (batch) => {
|
|
63
70
|
if (!ctx.model) return false;
|
|
64
|
-
const text = `[ace-eyes] Pending
|
|
65
|
-
"Read original
|
|
71
|
+
const text = `[ace-eyes] Pending task/assignment/HITL/deadline revisions: ${JSON.stringify(batch)}. ` +
|
|
72
|
+
"Read ace-overseer observe and the original state owners; adopt reports through ace-overseer process-reports and existing task/assignment gates. " +
|
|
66
73
|
"Reconcile uncertain effects; never repeat external actions on wake alone. After handling each exact revision, " +
|
|
67
74
|
"acknowledge with the ace_eyes tool (action ack, key, revision). Settlement alone is not acknowledgement.";
|
|
68
75
|
attempt = { text, accepted: false };
|
|
@@ -94,9 +101,10 @@ export function registerEyes(pi, { observe = observeHitl, now = Date.now,
|
|
|
94
101
|
if (message?.role === "assistant" && message.stopReason === "error") eyes?.quota(message.errorMessage);
|
|
95
102
|
});
|
|
96
103
|
pi.registerTool?.({
|
|
97
|
-
name: "ace_eyes", label: "Eyes
|
|
104
|
+
name: "ace_eyes", label: "Eyes observation", description: "Start standing observation with an existing config file, read pending semantic events or acknowledge an exact handled revision. Does not accept reports, authorize effects, start actors or reset quota. Use existing report/assignment owners first. Deadlines require an operation identity and revision; cancel when no longer active.",
|
|
98
105
|
parameters: { type: "object", properties: {
|
|
99
|
-
action: { type: "string", enum: ["status", "ack", "deadline", "cancel"] },
|
|
106
|
+
action: { type: "string", enum: ["start", "status", "ack", "deadline", "cancel"] },
|
|
107
|
+
configPath: { type: "string" },
|
|
100
108
|
key: { type: "string" }, revision: { type: "string" }, at: { type: "integer" }
|
|
101
109
|
}, required: ["action"], additionalProperties: false },
|
|
102
110
|
execute: async (_id, args, _signal, _onUpdate, ctx) => {
|
|
@@ -104,13 +112,24 @@ export function registerEyes(pi, { observe = observeHitl, now = Date.now,
|
|
|
104
112
|
if (!ctx) throw new Error("Eyes session not initialized");
|
|
105
113
|
bind(ctx);
|
|
106
114
|
}
|
|
107
|
-
if (args.action === "
|
|
115
|
+
if (args.action === "start") {
|
|
116
|
+
if (!ctx || typeof args.configPath !== "string" || !args.configPath.trim()) {
|
|
117
|
+
throw new Error("Eyes start requires configPath and the current session context");
|
|
118
|
+
}
|
|
119
|
+
const config = JSON.parse(fs.readFileSync(path.resolve(ctx.cwd, args.configPath), "utf8"));
|
|
120
|
+
eyes.start(config); arm();
|
|
121
|
+
// Observe now, but do not enqueue a redundant model turn inside the
|
|
122
|
+
// caller's turn. Pending revisions are returned to the caller below.
|
|
123
|
+
arming = true;
|
|
124
|
+
try { await eyes.tick(); } finally { arming = false; }
|
|
125
|
+
}
|
|
126
|
+
else if (args.action === "ack") eyes.ack(args.key, args.revision);
|
|
108
127
|
else if (args.action === "deadline") eyes.deadline(args.key, args.at, args.revision);
|
|
109
128
|
else if (args.action === "cancel") eyes.cancelDeadline(args.key);
|
|
110
129
|
else if (args.action !== "status") throw new Error("Unknown eyes action");
|
|
111
130
|
// Do not send a second wake from inside the running model turn. The next
|
|
112
131
|
// observation delivers remaining coalesced revisions through the same owner.
|
|
113
|
-
const details = { ...eyes.summary(), pending: eyes.s.pending, deadlines: eyes.s.deadlines };
|
|
132
|
+
const details = { ...eyes.summary(), sources: observedSources, pending: eyes.s.pending, deadlines: eyes.s.deadlines };
|
|
114
133
|
return { content: [{ type: "text", text: JSON.stringify(details) }], details };
|
|
115
134
|
}
|
|
116
135
|
});
|
data/lib/ace/wake/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ace-wake
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michal Czyz
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-10-
|
|
10
|
+
date: 2026-10-31 00:00:00.000000000 Z
|
|
11
11
|
dependencies: []
|
|
12
12
|
description: 'Publishable asset package for the ace-wake Pi harness extension: /loop
|
|
13
13
|
timers and /watch file subscriptions that wake idle agents. Ships the extension
|