@skydiveai/pi-extensions 0.1.0-beta.6 → 0.1.0-beta.61
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/index.mjs +44 -9
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1949,11 +1949,33 @@ const subscribers = {
|
|
|
1949
1949
|
subagent: /* @__PURE__ */ new Set()
|
|
1950
1950
|
};
|
|
1951
1951
|
let pollerStarted = false;
|
|
1952
|
+
let firstPollSettled = false;
|
|
1953
|
+
let resolveFirstPoll = null;
|
|
1954
|
+
const firstPollPromise = new Promise((resolve) => {
|
|
1955
|
+
resolveFirstPoll = resolve;
|
|
1956
|
+
});
|
|
1957
|
+
function markFirstPollSettled() {
|
|
1958
|
+
if (firstPollSettled) return;
|
|
1959
|
+
firstPollSettled = true;
|
|
1960
|
+
resolveFirstPoll?.();
|
|
1961
|
+
}
|
|
1952
1962
|
/** Last-polled value of a flag, or `null` if not yet resolved. */
|
|
1953
1963
|
function getPolledFlag(name) {
|
|
1954
1964
|
return name === "contextManagement" ? contextManagement : subagent;
|
|
1955
1965
|
}
|
|
1956
1966
|
/**
|
|
1967
|
+
* Await the first poll already kicked by `startFeatureFlagPoller` (never a new
|
|
1968
|
+
* GET). Resolves when that poll settles, immediately if it already has, or
|
|
1969
|
+
* immediately when there's no flag source to poll. Callers on the hot path
|
|
1970
|
+
* should race this against their own short timeout so a slow/failed flag
|
|
1971
|
+
* service cannot delay first-token; a timeout just means the caller reads the
|
|
1972
|
+
* still-cold cache and falls back to its default, exactly as before.
|
|
1973
|
+
*/
|
|
1974
|
+
function awaitFirstFlagPoll() {
|
|
1975
|
+
if (firstPollSettled || !hasFlagSource()) return Promise.resolve();
|
|
1976
|
+
return firstPollPromise;
|
|
1977
|
+
}
|
|
1978
|
+
/**
|
|
1957
1979
|
* Subscribe to changes of a flag. The callback fires only on a *transition*
|
|
1958
1980
|
* (skipped while the value is unchanged), so a subscriber registered before the
|
|
1959
1981
|
* first poll still learns the initial value. Returns an unsubscribe fn.
|
|
@@ -1977,10 +1999,14 @@ function apply(name, next) {
|
|
|
1977
1999
|
}
|
|
1978
2000
|
}
|
|
1979
2001
|
async function pollOnce() {
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
2002
|
+
try {
|
|
2003
|
+
const flags = await fetchHarnessFlags();
|
|
2004
|
+
if (!flags) return;
|
|
2005
|
+
apply("contextManagement", flags.contextManagement ?? null);
|
|
2006
|
+
apply("subagent", flags.subagent ?? null);
|
|
2007
|
+
} catch (err) {
|
|
2008
|
+
log$9.debug({ err }, "feature-flag poll threw");
|
|
2009
|
+
}
|
|
1984
2010
|
}
|
|
1985
2011
|
/**
|
|
1986
2012
|
* Start the shared background poll (idempotent). No-op when there's no
|
|
@@ -1991,7 +2017,7 @@ async function pollOnce() {
|
|
|
1991
2017
|
function startFeatureFlagPoller() {
|
|
1992
2018
|
if (pollerStarted || !hasFlagSource()) return;
|
|
1993
2019
|
pollerStarted = true;
|
|
1994
|
-
pollOnce();
|
|
2020
|
+
pollOnce().finally(markFirstPollSettled);
|
|
1995
2021
|
setInterval(() => void pollOnce(), FLAG_POLL_INTERVAL_MS).unref?.();
|
|
1996
2022
|
}
|
|
1997
2023
|
//#endregion
|
|
@@ -2755,6 +2781,7 @@ const soulExtension = (pi) => {
|
|
|
2755
2781
|
//#endregion
|
|
2756
2782
|
//#region src/extensions/subagent/index.ts
|
|
2757
2783
|
const log$2 = logger.child({ module: "subagent-ext" });
|
|
2784
|
+
const COLD_START_FLAG_WAIT_MS = 750;
|
|
2758
2785
|
const MAX_TASKS = 8;
|
|
2759
2786
|
const TaskItem = Type.Object({
|
|
2760
2787
|
task: Type.String({ description: "The task to delegate to a subagent run." }),
|
|
@@ -2840,11 +2867,19 @@ function createSubagentExtension({ channelContext }) {
|
|
|
2840
2867
|
return (pi) => {
|
|
2841
2868
|
const messageId = extractMessageId(channelContext);
|
|
2842
2869
|
startFeatureFlagPoller();
|
|
2870
|
+
let registered = false;
|
|
2871
|
+
const registerOnce = () => {
|
|
2872
|
+
if (registered) return;
|
|
2873
|
+
registered = true;
|
|
2874
|
+
pi.registerTool(buildTool(messageId));
|
|
2875
|
+
log$2.info({ event: "subagent_enabled" }, "subagent tool registered");
|
|
2876
|
+
};
|
|
2877
|
+
onFlagChange("subagent", (enabled) => {
|
|
2878
|
+
if (enabled) registerOnce();
|
|
2879
|
+
});
|
|
2843
2880
|
pi.on("session_start", async () => {
|
|
2844
|
-
if (getPolledFlag("subagent") ===
|
|
2845
|
-
|
|
2846
|
-
log$2.info({ event: "subagent_enabled" }, "subagent tool registered");
|
|
2847
|
-
}
|
|
2881
|
+
if (getPolledFlag("subagent") === null) await Promise.race([awaitFirstFlagPoll(), new Promise((resolve) => setTimeout(resolve, COLD_START_FLAG_WAIT_MS).unref?.())]);
|
|
2882
|
+
if (getPolledFlag("subagent") === true) registerOnce();
|
|
2848
2883
|
});
|
|
2849
2884
|
};
|
|
2850
2885
|
}
|