@awebai/oats-pi 0.60.0 → 0.61.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.
- package/README.md +11 -6
- package/extension/index.ts +20 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,12 +12,17 @@ from the same release tag). This bridge registers no operational tools. It only:
|
|
|
12
12
|
instance;
|
|
13
13
|
- holds an instance's opening task (`@TASK.md`) on pi's own path until no
|
|
14
14
|
turn another extension started is active, so pi runs it exactly once,
|
|
15
|
-
as its input processing made it, instead of refusing it. It never
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
as its input processing made it, instead of refusing it. It never waits
|
|
16
|
+
for the task's own run: pi 1.2 and later count that run as active from
|
|
17
|
+
before its before_agent_start, and queue a message sent meanwhile into it,
|
|
18
|
+
after the task. It never sends, re-sends or alters a message. The
|
|
19
|
+
exception: an extension loaded behind the bridge that starts a turn (or
|
|
20
|
+
awaits I/O while one starts) inside its own input handling of the opening
|
|
21
|
+
prompt, or on a pi before 1.2 in its before_agent_start, can still make pi
|
|
22
|
+
refuse it, because pi's interactive mode sends the initial message with no
|
|
23
|
+
streamingBehavior. @awebai/pi has no such handler. A session that shuts
|
|
24
|
+
down (a reload, say) releases the hold, and pi then runs or refuses the
|
|
25
|
+
task by its own rules;
|
|
21
26
|
- journals compaction summaries and sends resume nudges when the active
|
|
22
27
|
knowledge capability created `STATE.md`/`log.md`. A startup gets the nudge
|
|
23
28
|
only when pi kept an earlier session of the home (pi files a session once
|
package/extension/index.ts
CHANGED
|
@@ -106,26 +106,32 @@ function sessionHeader(file: string, head: Buffer): { type?: unknown; cwd?: unkn
|
|
|
106
106
|
/**
|
|
107
107
|
* The opening task runs once, after any turn another extension starts, as
|
|
108
108
|
* pi's input processing made it. pi sends the launch's `@TASK.md` as the
|
|
109
|
-
* session's first prompt with no streamingBehavior (pi
|
|
110
|
-
* modes/interactive/interactive-mode.js:
|
|
111
|
-
* extension's run (the @awebai/pi welcome)
|
|
112
|
-
* or alters a message: it holds that prompt
|
|
113
|
-
* handler and again in before_agent_start (a
|
|
114
|
-
* prompt's preflight), until no run is active.
|
|
115
|
-
*
|
|
116
|
-
* before_agent_start
|
|
117
|
-
*
|
|
109
|
+
* session's first prompt with no streamingBehavior (pi 1.3.0
|
|
110
|
+
* modes/interactive/interactive-mode.js:894-897, as an SDK session.prompt()
|
|
111
|
+
* does) and refuses it while another extension's run (the @awebai/pi welcome)
|
|
112
|
+
* is active. The bridge never sends or alters a message: it holds that prompt
|
|
113
|
+
* on pi's own path, in its input handler and again in before_agent_start (a
|
|
114
|
+
* run can start during the prompt's preflight), until no run is active.
|
|
115
|
+
* pi 1.2 and later count the prompt's own run as active from before its
|
|
116
|
+
* before_agent_start (core/agent-session.js:1392-1397) and queue a message
|
|
117
|
+
* sent meanwhile into that run; their event carries messageType, and there
|
|
118
|
+
* only the input handler holds. A run that an extension behind the bridge starts (or that starts
|
|
119
|
+
* while one awaits) in its own input handling of the prompt, or on a pi
|
|
120
|
+
* before 1.2 in its before_agent_start, can still make pi refuse it, and pi
|
|
121
|
+
* says nothing an extension could act on. Every later prompt is left to pi.
|
|
122
|
+
* A session that shuts down releases the hold.
|
|
118
123
|
*/
|
|
119
124
|
function holdOpeningTask(pi: ExtensionAPI) {
|
|
120
125
|
let taken = false;
|
|
121
126
|
// The opening prompt has yet to reach before_agent_start.
|
|
122
127
|
let awaitingStart = false;
|
|
123
128
|
const waiters: (() => void)[] = [];
|
|
129
|
+
let shutDown = false;
|
|
124
130
|
// pi refuses a prompt while pi-agent-core holds a run (ctx.signal is that
|
|
125
131
|
// run's), and one with no streamingBehavior while the session is not idle.
|
|
126
132
|
const busy = (ctx: ExtensionContext) => ctx.signal !== undefined || !ctx.isIdle();
|
|
127
133
|
const untilFree = async (ctx: ExtensionContext) => {
|
|
128
|
-
while (busy(ctx)) await new Promise<void>((resolve) => waiters.push(resolve));
|
|
134
|
+
while (!shutDown && busy(ctx)) await new Promise<void>((resolve) => waiters.push(resolve));
|
|
129
135
|
};
|
|
130
136
|
const wake = () => { for (const resume of waiters.splice(0)) resume(); };
|
|
131
137
|
// Waiters re-check on agent_settled (pi 0.80.4 and later). A pi without it
|
|
@@ -148,12 +154,14 @@ function holdOpeningTask(pi: ExtensionAPI) {
|
|
|
148
154
|
await untilFree(ctx);
|
|
149
155
|
return { action: "continue" };
|
|
150
156
|
});
|
|
151
|
-
pi.on("before_agent_start", async (
|
|
152
|
-
|
|
157
|
+
pi.on("before_agent_start", async (event, ctx) => {
|
|
158
|
+
// On pi 1.2 and later (messageType) the session's run is the prompt's own.
|
|
159
|
+
if (!awaitingStart || event.messageType !== undefined) return;
|
|
153
160
|
awaitingStart = false;
|
|
154
161
|
await untilFree(ctx);
|
|
155
162
|
});
|
|
156
163
|
pi.on("agent_start", stopRechecking);
|
|
157
164
|
pi.on("agent_end", () => { stopRechecking(); recheck = setTimeout(recheckWaiters, 0); });
|
|
158
165
|
pi.on("agent_settled", () => { stopRechecking(); wake(); });
|
|
166
|
+
pi.on("session_shutdown", () => { shutDown = true; stopRechecking(); wake(); });
|
|
159
167
|
}
|
package/package.json
CHANGED