@integrity-labs/agt-cli 0.28.734 → 0.28.735
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/bin/agt.js
CHANGED
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
success,
|
|
42
42
|
table,
|
|
43
43
|
warn
|
|
44
|
-
} from "../chunk-
|
|
44
|
+
} from "../chunk-AZZ7MLBE.js";
|
|
45
45
|
import {
|
|
46
46
|
getProjectDir,
|
|
47
47
|
isSessionResumeDisabled,
|
|
@@ -5467,7 +5467,7 @@ import { execFileSync, execSync } from "child_process";
|
|
|
5467
5467
|
import { existsSync as existsSync11, realpathSync as realpathSync2 } from "fs";
|
|
5468
5468
|
import chalk18 from "chalk";
|
|
5469
5469
|
import ora16 from "ora";
|
|
5470
|
-
var cliVersion = true ? "0.28.
|
|
5470
|
+
var cliVersion = true ? "0.28.735" : "dev";
|
|
5471
5471
|
async function fetchLatestVersion() {
|
|
5472
5472
|
const host2 = getHost();
|
|
5473
5473
|
if (!host2) return null;
|
|
@@ -6654,7 +6654,7 @@ function handleError(err) {
|
|
|
6654
6654
|
}
|
|
6655
6655
|
|
|
6656
6656
|
// src/bin/agt.ts
|
|
6657
|
-
var cliVersion2 = true ? "0.28.
|
|
6657
|
+
var cliVersion2 = true ? "0.28.735" : "dev";
|
|
6658
6658
|
var program = new Command();
|
|
6659
6659
|
program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
|
|
6660
6660
|
program.hook("preAction", async (thisCommand, actionCommand) => {
|
|
@@ -6427,7 +6427,7 @@ function exchangeFailureKind(err) {
|
|
|
6427
6427
|
}
|
|
6428
6428
|
|
|
6429
6429
|
// src/lib/api-client.ts
|
|
6430
|
-
var agtCliVersion = true ? "0.28.
|
|
6430
|
+
var agtCliVersion = true ? "0.28.735" : "dev";
|
|
6431
6431
|
var lastConfigHash = null;
|
|
6432
6432
|
function setConfigHash(hash) {
|
|
6433
6433
|
lastConfigHash = hash && hash.length > 0 ? hash : null;
|
|
@@ -10473,4 +10473,4 @@ export {
|
|
|
10473
10473
|
managerInstallSystemUnitCommand,
|
|
10474
10474
|
managerUninstallSystemUnitCommand
|
|
10475
10475
|
};
|
|
10476
|
-
//# sourceMappingURL=chunk-
|
|
10476
|
+
//# sourceMappingURL=chunk-AZZ7MLBE.js.map
|
|
@@ -57,7 +57,7 @@ import {
|
|
|
57
57
|
safeWriteJsonAtomic,
|
|
58
58
|
setConfigHash,
|
|
59
59
|
tripClass
|
|
60
|
-
} from "../chunk-
|
|
60
|
+
} from "../chunk-AZZ7MLBE.js";
|
|
61
61
|
import {
|
|
62
62
|
getProjectDir as getProjectDir2,
|
|
63
63
|
getReadyTasks,
|
|
@@ -5584,6 +5584,48 @@ var REFRESH_MANIFEST_FLAGS = {
|
|
|
5584
5584
|
integration_skills_manifest: true
|
|
5585
5585
|
};
|
|
5586
5586
|
|
|
5587
|
+
// src/lib/fetch-cadence.ts
|
|
5588
|
+
function createFetchGate(ttlMs) {
|
|
5589
|
+
const lastFetchedAt = /* @__PURE__ */ new Map();
|
|
5590
|
+
const forceCount = /* @__PURE__ */ new Map();
|
|
5591
|
+
const consumedForceCount = /* @__PURE__ */ new Map();
|
|
5592
|
+
let generation = 0;
|
|
5593
|
+
const fetchedAtGeneration = /* @__PURE__ */ new Map();
|
|
5594
|
+
const pendingForces = (key) => (forceCount.get(key) ?? 0) > (consumedForceCount.get(key) ?? 0);
|
|
5595
|
+
return {
|
|
5596
|
+
shouldFetch(key, now = Date.now()) {
|
|
5597
|
+
if (pendingForces(key)) return true;
|
|
5598
|
+
if ((fetchedAtGeneration.get(key) ?? -1) < generation) return true;
|
|
5599
|
+
const last = lastFetchedAt.get(key);
|
|
5600
|
+
if (last === void 0) return true;
|
|
5601
|
+
return now - last >= ttlMs;
|
|
5602
|
+
},
|
|
5603
|
+
beginFetch(key) {
|
|
5604
|
+
return { forceCount: forceCount.get(key) ?? 0, generation };
|
|
5605
|
+
},
|
|
5606
|
+
markFetched(key, token, now = Date.now()) {
|
|
5607
|
+
lastFetchedAt.set(key, now);
|
|
5608
|
+
fetchedAtGeneration.set(key, token.generation);
|
|
5609
|
+
consumedForceCount.set(key, token.forceCount);
|
|
5610
|
+
},
|
|
5611
|
+
forceNext(key) {
|
|
5612
|
+
forceCount.set(key, (forceCount.get(key) ?? 0) + 1);
|
|
5613
|
+
},
|
|
5614
|
+
forceAll() {
|
|
5615
|
+
generation += 1;
|
|
5616
|
+
},
|
|
5617
|
+
forget(key) {
|
|
5618
|
+
lastFetchedAt.delete(key);
|
|
5619
|
+
fetchedAtGeneration.delete(key);
|
|
5620
|
+
forceCount.delete(key);
|
|
5621
|
+
consumedForceCount.delete(key);
|
|
5622
|
+
},
|
|
5623
|
+
size() {
|
|
5624
|
+
return lastFetchedAt.size;
|
|
5625
|
+
}
|
|
5626
|
+
};
|
|
5627
|
+
}
|
|
5628
|
+
|
|
5587
5629
|
// src/lib/channel-hash-cache.ts
|
|
5588
5630
|
import { existsSync as existsSync8, readFileSync as readFileSync19, writeFileSync as writeFileSync10 } from "fs";
|
|
5589
5631
|
import { join as join25 } from "path";
|
|
@@ -12972,6 +13014,9 @@ function resolveAgentFramework(codeName) {
|
|
|
12972
13014
|
function clearAgentCaches(agentId, codeName) {
|
|
12973
13015
|
const channelCacheMutated = clearAgentState(agentId, codeName);
|
|
12974
13016
|
agentChannelTokens.delete(codeName);
|
|
13017
|
+
lastRefreshPayload.delete(agentId);
|
|
13018
|
+
refreshFetchGate.forget(agentId);
|
|
13019
|
+
memoriesFetchGate.forget(agentId);
|
|
12975
13020
|
forgetRealtimeRebindState(agentId);
|
|
12976
13021
|
forgetChannelSyncState(agentId);
|
|
12977
13022
|
sharedBusyBuckets.reset(codeName);
|
|
@@ -13007,7 +13052,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
13007
13052
|
var lastVersionCheckAt = 0;
|
|
13008
13053
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
13009
13054
|
var lastResponsivenessProbeAt = 0;
|
|
13010
|
-
var agtCliVersion = true ? "0.28.
|
|
13055
|
+
var agtCliVersion = true ? "0.28.735" : "dev";
|
|
13011
13056
|
function resolveBrewPath(execFileSync3) {
|
|
13012
13057
|
try {
|
|
13013
13058
|
const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -14517,6 +14562,16 @@ ${SKILLS_INDEX_END}`;
|
|
|
14517
14562
|
);
|
|
14518
14563
|
}
|
|
14519
14564
|
}
|
|
14565
|
+
var DESIRED_STATE_FETCH_TTL_MS = 6e4;
|
|
14566
|
+
var refreshFetchGate = createFetchGate(DESIRED_STATE_FETCH_TTL_MS);
|
|
14567
|
+
var lastRefreshPayload = /* @__PURE__ */ new Map();
|
|
14568
|
+
var memoriesFetchGate = createFetchGate(DESIRED_STATE_FETCH_TTL_MS);
|
|
14569
|
+
var pollCycleFetches = 0;
|
|
14570
|
+
var pollCycleFetchSkips = 0;
|
|
14571
|
+
function forceRefreshFetch() {
|
|
14572
|
+
refreshFetchGate.forceAll();
|
|
14573
|
+
memoriesFetchGate.forceAll();
|
|
14574
|
+
}
|
|
14520
14575
|
var consecutivePollFailures = 0;
|
|
14521
14576
|
function reorderRestartedFirst(agents, restartedIds) {
|
|
14522
14577
|
if (restartedIds.size === 0) return agents;
|
|
@@ -15270,6 +15325,9 @@ async function pollCycleInner() {
|
|
|
15270
15325
|
const processOrder = fastRespawn ? reorderRestartedFirst(agents, new Set(restartAcks.keys())) : agents;
|
|
15271
15326
|
const managedToolkits = createManagedToolkitReader(agents.map((a) => a.agent_id));
|
|
15272
15327
|
managedPruneLedger = createManagedPruneLedger();
|
|
15328
|
+
const cycleStartedAt = Date.now();
|
|
15329
|
+
pollCycleFetches = 0;
|
|
15330
|
+
pollCycleFetchSkips = 0;
|
|
15273
15331
|
for (const agent of processOrder) {
|
|
15274
15332
|
if (restartInFlight.has(agent.agent_id)) {
|
|
15275
15333
|
const existing = state8.agents.find((a) => a.agentId === agent.agent_id);
|
|
@@ -15308,6 +15366,9 @@ async function pollCycleInner() {
|
|
|
15308
15366
|
promptBindProbeAttempts.set(agent.code_name, PROMPT_BIND_PROBE_ATTEMPTS);
|
|
15309
15367
|
}
|
|
15310
15368
|
}
|
|
15369
|
+
log(
|
|
15370
|
+
`[poll-cycle] agents=${processOrder.length} refresh_fetched=${pollCycleFetches} refresh_skipped=${pollCycleFetchSkips} duration_ms=${Date.now() - cycleStartedAt}`
|
|
15371
|
+
);
|
|
15311
15372
|
void maybeReportActivityCache({ api, log });
|
|
15312
15373
|
const crossAgentPrune = managedPruneLedger.summarize();
|
|
15313
15374
|
if (crossAgentPrune) log(crossAgentPrune);
|
|
@@ -15826,6 +15887,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15826
15887
|
if (previousStatus && previousStatus !== agent.status) {
|
|
15827
15888
|
log(`Agent '${agent.code_name}' status changed: ${previousStatus} \u2192 ${agent.status}`);
|
|
15828
15889
|
agentState.knownVersions.delete(agent.agent_id);
|
|
15890
|
+
refreshFetchGate.forceNext(agent.agent_id);
|
|
15829
15891
|
if (previousStatus === "paused" && agent.status === "active" && restartBreaker.isTripped(agent.code_name)) {
|
|
15830
15892
|
restartBreaker.clear(agent.code_name);
|
|
15831
15893
|
reportedTrips.delete(agent.code_name);
|
|
@@ -15865,85 +15927,95 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15865
15927
|
}
|
|
15866
15928
|
agentState.knownStatuses.set(agent.agent_id, agent.status);
|
|
15867
15929
|
let refreshData;
|
|
15868
|
-
|
|
15869
|
-
|
|
15870
|
-
|
|
15871
|
-
|
|
15872
|
-
|
|
15873
|
-
|
|
15874
|
-
|
|
15875
|
-
|
|
15876
|
-
|
|
15877
|
-
|
|
15878
|
-
|
|
15879
|
-
|
|
15880
|
-
manifest
|
|
15881
|
-
|
|
15882
|
-
|
|
15883
|
-
fetchContents: async (hashes) => {
|
|
15884
|
-
const res = await api.post(
|
|
15885
|
-
"/host/knowledge/contents",
|
|
15886
|
-
{ agent_id: agent.agent_id, hashes }
|
|
15887
|
-
);
|
|
15888
|
-
return res.contents ?? [];
|
|
15889
|
-
},
|
|
15890
|
-
log
|
|
15891
|
-
});
|
|
15892
|
-
refreshData.knowledge = resolved;
|
|
15893
|
-
}
|
|
15894
|
-
if (refreshData.global_skills_manifest || refreshData.shared_skills_manifest) {
|
|
15895
|
-
const resolvedSkills = await resolveSkillsFromManifest({
|
|
15896
|
-
globals: refreshData.global_skills_manifest ?? [],
|
|
15897
|
-
shared: refreshData.shared_skills_manifest ?? [],
|
|
15898
|
-
cacheDir: join40(config.configDir, "_skills"),
|
|
15899
|
-
fetchContents: async (hashes) => {
|
|
15900
|
-
const res = await api.post(
|
|
15901
|
-
"/host/skills/contents",
|
|
15902
|
-
{ agent_id: agent.agent_id, hashes }
|
|
15903
|
-
);
|
|
15904
|
-
return res.contents ?? [];
|
|
15905
|
-
},
|
|
15906
|
-
log
|
|
15907
|
-
});
|
|
15908
|
-
if (resolvedSkills) {
|
|
15909
|
-
refreshData.global_skills = resolvedSkills.globals;
|
|
15910
|
-
refreshData.shared_skills = resolvedSkills.shared;
|
|
15911
|
-
}
|
|
15912
|
-
}
|
|
15913
|
-
if (refreshData.integration_skills_manifest) {
|
|
15914
|
-
const resolvedIntegrationSkills = await resolveIntegrationSkillsFromManifest({
|
|
15915
|
-
manifest: refreshData.integration_skills_manifest,
|
|
15916
|
-
cacheDir: join40(config.configDir, "_skills"),
|
|
15917
|
-
fetchContents: async (hashes) => {
|
|
15918
|
-
const res = await api.post(
|
|
15919
|
-
"/host/skills/contents",
|
|
15920
|
-
{ agent_id: agent.agent_id, hashes }
|
|
15921
|
-
);
|
|
15922
|
-
return res.contents ?? [];
|
|
15923
|
-
},
|
|
15924
|
-
log
|
|
15930
|
+
const cachedRefresh = lastRefreshPayload.get(agent.agent_id);
|
|
15931
|
+
const refreshToken = refreshFetchGate.beginFetch(agent.agent_id);
|
|
15932
|
+
if (cachedRefresh !== void 0 && !refreshFetchGate.shouldFetch(agent.agent_id)) {
|
|
15933
|
+
refreshData = cachedRefresh;
|
|
15934
|
+
pollCycleFetchSkips += 1;
|
|
15935
|
+
} else {
|
|
15936
|
+
try {
|
|
15937
|
+
refreshData = await api.post("/host/refresh", {
|
|
15938
|
+
agent_id: agent.agent_id,
|
|
15939
|
+
// ENG-9585: ask for hashes instead of bodies on all three lanes. The
|
|
15940
|
+
// rationale for each flag, and for their staying three flags rather than
|
|
15941
|
+
// one, now lives with the constant — so that a new `/host/refresh` caller
|
|
15942
|
+
// inherits it instead of having to rediscover it. The manifest is
|
|
15943
|
+
// normalised back into `refreshData.knowledge` immediately below.
|
|
15944
|
+
...REFRESH_MANIFEST_FLAGS
|
|
15925
15945
|
});
|
|
15926
|
-
if (
|
|
15927
|
-
|
|
15946
|
+
if (refreshData.knowledge_manifest) {
|
|
15947
|
+
const resolved = await resolveKnowledgeFromManifest({
|
|
15948
|
+
manifest: refreshData.knowledge_manifest,
|
|
15949
|
+
cacheDir: join40(config.configDir, "_knowledge"),
|
|
15950
|
+
delivery: refreshData.agent?.knowledge_delivery ?? "both",
|
|
15951
|
+
fetchContents: async (hashes) => {
|
|
15952
|
+
const res = await api.post(
|
|
15953
|
+
"/host/knowledge/contents",
|
|
15954
|
+
{ agent_id: agent.agent_id, hashes }
|
|
15955
|
+
);
|
|
15956
|
+
return res.contents ?? [];
|
|
15957
|
+
},
|
|
15958
|
+
log
|
|
15959
|
+
});
|
|
15960
|
+
refreshData.knowledge = resolved;
|
|
15961
|
+
}
|
|
15962
|
+
if (refreshData.global_skills_manifest || refreshData.shared_skills_manifest) {
|
|
15963
|
+
const resolvedSkills = await resolveSkillsFromManifest({
|
|
15964
|
+
globals: refreshData.global_skills_manifest ?? [],
|
|
15965
|
+
shared: refreshData.shared_skills_manifest ?? [],
|
|
15966
|
+
cacheDir: join40(config.configDir, "_skills"),
|
|
15967
|
+
fetchContents: async (hashes) => {
|
|
15968
|
+
const res = await api.post(
|
|
15969
|
+
"/host/skills/contents",
|
|
15970
|
+
{ agent_id: agent.agent_id, hashes }
|
|
15971
|
+
);
|
|
15972
|
+
return res.contents ?? [];
|
|
15973
|
+
},
|
|
15974
|
+
log
|
|
15975
|
+
});
|
|
15976
|
+
if (resolvedSkills) {
|
|
15977
|
+
refreshData.global_skills = resolvedSkills.globals;
|
|
15978
|
+
refreshData.shared_skills = resolvedSkills.shared;
|
|
15979
|
+
}
|
|
15928
15980
|
}
|
|
15981
|
+
if (refreshData.integration_skills_manifest) {
|
|
15982
|
+
const resolvedIntegrationSkills = await resolveIntegrationSkillsFromManifest({
|
|
15983
|
+
manifest: refreshData.integration_skills_manifest,
|
|
15984
|
+
cacheDir: join40(config.configDir, "_skills"),
|
|
15985
|
+
fetchContents: async (hashes) => {
|
|
15986
|
+
const res = await api.post(
|
|
15987
|
+
"/host/skills/contents",
|
|
15988
|
+
{ agent_id: agent.agent_id, hashes }
|
|
15989
|
+
);
|
|
15990
|
+
return res.contents ?? [];
|
|
15991
|
+
},
|
|
15992
|
+
log
|
|
15993
|
+
});
|
|
15994
|
+
if (resolvedIntegrationSkills) {
|
|
15995
|
+
refreshData.integration_skills = resolvedIntegrationSkills;
|
|
15996
|
+
}
|
|
15997
|
+
}
|
|
15998
|
+
} catch (err) {
|
|
15999
|
+
log(`Refresh failed for '${agent.code_name}': ${err.message}`);
|
|
16000
|
+
const existing = state8.agents.find((a) => a.agentId === agent.agent_id);
|
|
16001
|
+
agentStates.push(existing ?? {
|
|
16002
|
+
agentId: agent.agent_id,
|
|
16003
|
+
codeName: agent.code_name,
|
|
16004
|
+
status: agent.status,
|
|
16005
|
+
charterVersion: "",
|
|
16006
|
+
toolsVersion: "",
|
|
16007
|
+
secretsHash: null,
|
|
16008
|
+
lastRefreshAt: null,
|
|
16009
|
+
lastProvisionAt: null,
|
|
16010
|
+
lastDriftCheckAt: null,
|
|
16011
|
+
lastSecretsProvisionAt: null,
|
|
16012
|
+
acpSessions: []
|
|
16013
|
+
});
|
|
16014
|
+
return;
|
|
15929
16015
|
}
|
|
15930
|
-
|
|
15931
|
-
|
|
15932
|
-
|
|
15933
|
-
agentStates.push(existing ?? {
|
|
15934
|
-
agentId: agent.agent_id,
|
|
15935
|
-
codeName: agent.code_name,
|
|
15936
|
-
status: agent.status,
|
|
15937
|
-
charterVersion: "",
|
|
15938
|
-
toolsVersion: "",
|
|
15939
|
-
secretsHash: null,
|
|
15940
|
-
lastRefreshAt: null,
|
|
15941
|
-
lastProvisionAt: null,
|
|
15942
|
-
lastDriftCheckAt: null,
|
|
15943
|
-
lastSecretsProvisionAt: null,
|
|
15944
|
-
acpSessions: []
|
|
15945
|
-
});
|
|
15946
|
-
return;
|
|
16016
|
+
lastRefreshPayload.set(agent.agent_id, refreshData);
|
|
16017
|
+
refreshFetchGate.markFetched(agent.agent_id, refreshToken);
|
|
16018
|
+
pollCycleFetches += 1;
|
|
15947
16019
|
}
|
|
15948
16020
|
if (!getAlertSlackWebhook() && refreshData.team?.settings) {
|
|
15949
16021
|
const webhook = refreshData.team.settings["alert_slack_webhook"];
|
|
@@ -16813,8 +16885,8 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
16813
16885
|
for (const integration of integrations) {
|
|
16814
16886
|
if (integration.auth_type !== "oauth2") continue;
|
|
16815
16887
|
const expiresAt = integration.credentials?.token_expires_at;
|
|
16816
|
-
const
|
|
16817
|
-
if (!expiresAt || !
|
|
16888
|
+
const refreshToken2 = integration.credentials?.refresh_token;
|
|
16889
|
+
if (!expiresAt || !refreshToken2) continue;
|
|
16818
16890
|
const msRemaining = new Date(expiresAt).getTime() - Date.now();
|
|
16819
16891
|
if (msRemaining > 10 * 60 * 1e3) continue;
|
|
16820
16892
|
try {
|
|
@@ -17460,7 +17532,14 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
17460
17532
|
}
|
|
17461
17533
|
const fetchTickBoard = createTickBoardFetcher(async () => {
|
|
17462
17534
|
const boardData = await api.post("/host/my-kanban", {
|
|
17463
|
-
agent_id: agent.agent_id
|
|
17535
|
+
agent_id: agent.agent_id,
|
|
17536
|
+
// ENG-9585: this is the ONLY caller that polls (every ~10s, per agent),
|
|
17537
|
+
// and it reads exactly `BoardItem`. `description` and `notes` are 57.8%
|
|
17538
|
+
// of the payload and are read here by nothing — but the `kanban_list` MCP
|
|
17539
|
+
// tool and `agt kanban` DO read them, so the route cannot simply drop
|
|
17540
|
+
// them. Asking for the lean shape is this caller saying what it needs;
|
|
17541
|
+
// every other caller keeps the full payload by default.
|
|
17542
|
+
detail: "board"
|
|
17464
17543
|
});
|
|
17465
17544
|
return (boardData.items ?? []).map(sanitizeBoardItem);
|
|
17466
17545
|
});
|
|
@@ -18945,6 +19024,7 @@ function ensureRealtimeDriftStarted(agentStates) {
|
|
|
18945
19024
|
const agent = agentStates.find((a) => a.agentId === doc.agent_id);
|
|
18946
19025
|
if (agent) {
|
|
18947
19026
|
agentState.knownVersions.delete(doc.agent_id);
|
|
19027
|
+
refreshFetchGate.forceNext(doc.agent_id);
|
|
18948
19028
|
log(`[realtime] Drift invalidated for '${agent.codeName}' \u2014 will re-provision next cycle`);
|
|
18949
19029
|
}
|
|
18950
19030
|
},
|
|
@@ -19108,6 +19188,8 @@ function ensureRealtimeAssignStarted(agentStates) {
|
|
|
19108
19188
|
);
|
|
19109
19189
|
},
|
|
19110
19190
|
onAssign: (payload) => {
|
|
19191
|
+
refreshFetchGate.forceNext(payload.agent_id);
|
|
19192
|
+
memoriesFetchGate.forceNext(payload.agent_id);
|
|
19111
19193
|
log(`[realtime] Agent ${payload.agent_id} assigned \u2014 will pick up next cycle`);
|
|
19112
19194
|
markAgentForFreshMemorySync(payload.agent_id);
|
|
19113
19195
|
},
|
|
@@ -19323,6 +19405,7 @@ function triggerEarlyPoll(reason) {
|
|
|
19323
19405
|
pollTimer = null;
|
|
19324
19406
|
}
|
|
19325
19407
|
log(`[realtime] Triggering early poll: ${reason}`);
|
|
19408
|
+
forceRefreshFetch();
|
|
19326
19409
|
pollTimer = setTimeout(() => {
|
|
19327
19410
|
void pollCycleAndReschedule(pollCycle, {
|
|
19328
19411
|
onError: (err) => log(`[poll-loop] early-poll cycle rejected: ${err?.message ?? String(err)}`),
|
|
@@ -20203,10 +20286,15 @@ async function downloadMemories(agent, memoryDir, log2, { force, configDir }) {
|
|
|
20203
20286
|
const localListHash = createHash19("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
|
|
20204
20287
|
const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
|
|
20205
20288
|
const prevDownload = lastDownloadHash.get(agent.agent_id);
|
|
20289
|
+
const memoriesToken = memoriesFetchGate.beginFetch(agent.agent_id);
|
|
20290
|
+
if (!force && !memoriesFetchGate.shouldFetch(agent.agent_id)) {
|
|
20291
|
+
return { status: "deferred", tombstones: null, truncated: false };
|
|
20292
|
+
}
|
|
20206
20293
|
try {
|
|
20207
20294
|
const dbMemories = await api.post("/host/memories", {
|
|
20208
20295
|
agent_id: agent.agent_id
|
|
20209
20296
|
});
|
|
20297
|
+
memoriesFetchGate.markFetched(agent.agent_id, memoriesToken);
|
|
20210
20298
|
const tombstones = Array.isArray(dbMemories.tombstones) ? dbMemories.tombstones : null;
|
|
20211
20299
|
const responseHash = createHash19("sha256").update(JSON.stringify({ m: dbMemories.memories ?? [], t: tombstones })).digest("hex").slice(0, 16);
|
|
20212
20300
|
if (!force && prevDownload && prevLocalHash === localListHash && lastDownloadHash.get(agent.agent_id) === responseHash) {
|