switchroom 0.14.74 → 0.14.76
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/agent-scheduler/index.js +2 -0
- package/dist/auth-broker/index.js +24 -1
- package/dist/cli/notion-write-pretool.mjs +2 -0
- package/dist/cli/switchroom.js +252 -25
- package/dist/cli/ui/index.html +57 -5
- package/dist/host-control/main.js +2 -0
- package/dist/vault/approvals/kernel-server.js +2 -0
- package/dist/vault/broker/server.js +2 -0
- package/package.json +1 -1
- package/telegram-plugin/dist/gateway/gateway.js +6 -4
|
@@ -10991,6 +10991,7 @@ var AgentToolsSchema = exports_external.object({
|
|
|
10991
10991
|
var AgentMemorySchema = exports_external.object({
|
|
10992
10992
|
collection: exports_external.string().describe("Hindsight collection name for this agent"),
|
|
10993
10993
|
auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
|
|
10994
|
+
file: exports_external.boolean().default(true).describe("Maintain a curated workspace MEMORY.md file (seeded once, " + "auto-loaded every turn). Set false for hindsight-only memory: " + "the file is not seeded or re-created, so once migrated into " + "Hindsight and deleted it stays gone. Recall + directives carry " + "the memory instead. Cascade: override (per-agent wins over default)."),
|
|
10994
10995
|
isolation: exports_external.enum(["default", "strict"]).default("default").describe("strict = never shared cross-agent, default = eligible for reflect"),
|
|
10995
10996
|
bank_mission: exports_external.string().optional().describe("Bank-level mission statement used during recall to contextualize results"),
|
|
10996
10997
|
retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain"),
|
|
@@ -11210,6 +11211,7 @@ var profileFields = {
|
|
|
11210
11211
|
memory: exports_external.object({
|
|
11211
11212
|
collection: exports_external.string().optional(),
|
|
11212
11213
|
auto_recall: exports_external.boolean().optional(),
|
|
11214
|
+
file: exports_external.boolean().optional(),
|
|
11213
11215
|
isolation: exports_external.enum(["default", "strict"]).optional(),
|
|
11214
11216
|
recall: exports_external.object({
|
|
11215
11217
|
max_memories: exports_external.number().int().min(0).optional(),
|
|
@@ -10991,6 +10991,7 @@ var AgentToolsSchema = exports_external.object({
|
|
|
10991
10991
|
var AgentMemorySchema = exports_external.object({
|
|
10992
10992
|
collection: exports_external.string().describe("Hindsight collection name for this agent"),
|
|
10993
10993
|
auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
|
|
10994
|
+
file: exports_external.boolean().default(true).describe("Maintain a curated workspace MEMORY.md file (seeded once, " + "auto-loaded every turn). Set false for hindsight-only memory: " + "the file is not seeded or re-created, so once migrated into " + "Hindsight and deleted it stays gone. Recall + directives carry " + "the memory instead. Cascade: override (per-agent wins over default)."),
|
|
10994
10995
|
isolation: exports_external.enum(["default", "strict"]).default("default").describe("strict = never shared cross-agent, default = eligible for reflect"),
|
|
10995
10996
|
bank_mission: exports_external.string().optional().describe("Bank-level mission statement used during recall to contextualize results"),
|
|
10996
10997
|
retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain"),
|
|
@@ -11210,6 +11211,7 @@ var profileFields = {
|
|
|
11210
11211
|
memory: exports_external.object({
|
|
11211
11212
|
collection: exports_external.string().optional(),
|
|
11212
11213
|
auto_recall: exports_external.boolean().optional(),
|
|
11214
|
+
file: exports_external.boolean().optional(),
|
|
11213
11215
|
isolation: exports_external.enum(["default", "strict"]).optional(),
|
|
11214
11216
|
recall: exports_external.object({
|
|
11215
11217
|
max_memories: exports_external.number().int().min(0).optional(),
|
|
@@ -13890,8 +13892,29 @@ class AuthBroker {
|
|
|
13890
13892
|
return override;
|
|
13891
13893
|
return auth.active ?? null;
|
|
13892
13894
|
}
|
|
13893
|
-
|
|
13895
|
+
servingAccount(identity2) {
|
|
13894
13896
|
const account = this.callerAccount(identity2);
|
|
13897
|
+
if (identity2.kind !== "consumer")
|
|
13898
|
+
return account;
|
|
13899
|
+
return this.consumerAccountWithFailover(account);
|
|
13900
|
+
}
|
|
13901
|
+
isAccountExhausted(account) {
|
|
13902
|
+
const q = this.quota[account];
|
|
13903
|
+
return q !== undefined && q.exhausted_until > this.now();
|
|
13904
|
+
}
|
|
13905
|
+
consumerAccountWithFailover(pinned) {
|
|
13906
|
+
if (!pinned || !this.isAccountExhausted(pinned))
|
|
13907
|
+
return pinned;
|
|
13908
|
+
for (const cand of this.config.auth?.fallback_order ?? []) {
|
|
13909
|
+
if (cand === pinned || this.isAccountExhausted(cand))
|
|
13910
|
+
continue;
|
|
13911
|
+
if (readAccountCredentials(cand, this.home))
|
|
13912
|
+
return cand;
|
|
13913
|
+
}
|
|
13914
|
+
return pinned;
|
|
13915
|
+
}
|
|
13916
|
+
async opGetCredentials(socket, id, identity2) {
|
|
13917
|
+
const account = this.servingAccount(identity2);
|
|
13895
13918
|
if (!account) {
|
|
13896
13919
|
this.audit({ op: "get-credentials", identity: identity2, ok: false, error: "no-active-account" });
|
|
13897
13920
|
socket.write(encodeError(id, "ACCOUNT_NOT_FOUND", "no active account configured"));
|
|
@@ -11739,6 +11739,7 @@ var AgentToolsSchema = exports_external.object({
|
|
|
11739
11739
|
var AgentMemorySchema = exports_external.object({
|
|
11740
11740
|
collection: exports_external.string().describe("Hindsight collection name for this agent"),
|
|
11741
11741
|
auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
|
|
11742
|
+
file: exports_external.boolean().default(true).describe("Maintain a curated workspace MEMORY.md file (seeded once, " + "auto-loaded every turn). Set false for hindsight-only memory: " + "the file is not seeded or re-created, so once migrated into " + "Hindsight and deleted it stays gone. Recall + directives carry " + "the memory instead. Cascade: override (per-agent wins over default)."),
|
|
11742
11743
|
isolation: exports_external.enum(["default", "strict"]).default("default").describe("strict = never shared cross-agent, default = eligible for reflect"),
|
|
11743
11744
|
bank_mission: exports_external.string().optional().describe("Bank-level mission statement used during recall to contextualize results"),
|
|
11744
11745
|
retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain"),
|
|
@@ -11958,6 +11959,7 @@ var profileFields = {
|
|
|
11958
11959
|
memory: exports_external.object({
|
|
11959
11960
|
collection: exports_external.string().optional(),
|
|
11960
11961
|
auto_recall: exports_external.boolean().optional(),
|
|
11962
|
+
file: exports_external.boolean().optional(),
|
|
11961
11963
|
isolation: exports_external.enum(["default", "strict"]).optional(),
|
|
11962
11964
|
recall: exports_external.object({
|
|
11963
11965
|
max_memories: exports_external.number().int().min(0).optional(),
|
package/dist/cli/switchroom.js
CHANGED
|
@@ -13555,6 +13555,7 @@ var init_schema = __esm(() => {
|
|
|
13555
13555
|
AgentMemorySchema = exports_external.object({
|
|
13556
13556
|
collection: exports_external.string().describe("Hindsight collection name for this agent"),
|
|
13557
13557
|
auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
|
|
13558
|
+
file: exports_external.boolean().default(true).describe("Maintain a curated workspace MEMORY.md file (seeded once, " + "auto-loaded every turn). Set false for hindsight-only memory: " + "the file is not seeded or re-created, so once migrated into " + "Hindsight and deleted it stays gone. Recall + directives carry " + "the memory instead. Cascade: override (per-agent wins over default)."),
|
|
13558
13559
|
isolation: exports_external.enum(["default", "strict"]).default("default").describe("strict = never shared cross-agent, default = eligible for reflect"),
|
|
13559
13560
|
bank_mission: exports_external.string().optional().describe("Bank-level mission statement used during recall to contextualize results"),
|
|
13560
13561
|
retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain"),
|
|
@@ -13774,6 +13775,7 @@ var init_schema = __esm(() => {
|
|
|
13774
13775
|
memory: exports_external.object({
|
|
13775
13776
|
collection: exports_external.string().optional(),
|
|
13776
13777
|
auto_recall: exports_external.boolean().optional(),
|
|
13778
|
+
file: exports_external.boolean().optional(),
|
|
13777
13779
|
isolation: exports_external.enum(["default", "strict"]).optional(),
|
|
13778
13780
|
recall: exports_external.object({
|
|
13779
13781
|
max_memories: exports_external.number().int().min(0).optional(),
|
|
@@ -28938,6 +28940,82 @@ var init_manifest = __esm(() => {
|
|
|
28938
28940
|
]);
|
|
28939
28941
|
});
|
|
28940
28942
|
|
|
28943
|
+
// src/cli/doctor-memory.ts
|
|
28944
|
+
import { execFileSync as execFileSync17 } from "node:child_process";
|
|
28945
|
+
function classifyShmSize(bytes) {
|
|
28946
|
+
const mib = Math.round(bytes / 1024 / 1024);
|
|
28947
|
+
if (bytes < MIN_HINDSIGHT_SHM_BYTES) {
|
|
28948
|
+
return {
|
|
28949
|
+
name: "hindsight shm-size",
|
|
28950
|
+
status: "fail",
|
|
28951
|
+
detail: `${mib}MB \u2014 PostgreSQL needs ~533MB+ for shared segments; writes will ` + `fail with "No space left on device"`,
|
|
28952
|
+
fix: "Recreate hindsight with a larger shm. The launch path now sets " + "--shm-size=2g (#2190); pull a release that includes it and run " + "`switchroom memory --restart`, or recreate the container manually " + "preserving the `switchroom-hindsight-data` volume."
|
|
28953
|
+
};
|
|
28954
|
+
}
|
|
28955
|
+
const gib = (bytes / 1024 / 1024 / 1024).toFixed(bytes % 1024 ** 3 === 0 ? 0 : 1);
|
|
28956
|
+
return { name: "hindsight shm-size", status: "ok", detail: `${gib}g` };
|
|
28957
|
+
}
|
|
28958
|
+
function classifyExtractionLogs(logs) {
|
|
28959
|
+
const noSpace = /No space left on device|could not resize shared memory/i.test(logs);
|
|
28960
|
+
const llmError = /Claude Code returned an error result|claude_code_llm[\s\S]{0,80}error|Fact extraction failed|Content extraction failed/i.test(logs);
|
|
28961
|
+
const quotaHint = /weekly limit|api_error_status["':\s]+429|\b429\b|hit your[\s\S]{0,24}limit/i.test(logs);
|
|
28962
|
+
const zeroFacts = (logs.match(/Extract facts:\s*0 facts/gi) ?? []).length;
|
|
28963
|
+
const okFacts = (logs.match(/Extract facts:\s*[1-9]\d* facts/gi) ?? []).length;
|
|
28964
|
+
if (noSpace) {
|
|
28965
|
+
return {
|
|
28966
|
+
name: "hindsight extraction",
|
|
28967
|
+
status: "fail",
|
|
28968
|
+
detail: "shared-memory exhaustion in recent logs \u2014 memory writes are failing",
|
|
28969
|
+
fix: "See the `hindsight shm-size` check \u2014 the container's /dev/shm is too small."
|
|
28970
|
+
};
|
|
28971
|
+
}
|
|
28972
|
+
if (llmError && okFacts === 0) {
|
|
28973
|
+
return {
|
|
28974
|
+
name: "hindsight extraction",
|
|
28975
|
+
status: "fail",
|
|
28976
|
+
detail: "fact-extraction LLM calls are failing" + (quotaHint ? " (429 / weekly-limit detected)" : "") + " \u2014 retains are accepted but extract 0 facts, so nothing becomes recallable",
|
|
28977
|
+
fix: "Usually hindsight's `auth.consumers[hindsight].account` is quota-" + "exhausted or its OAuth broke. Repoint it to an account with quota in " + "switchroom.yaml, then `docker restart switchroom-auth-broker` and " + "`docker restart switchroom-hindsight` (single-file config mount needs " + "the broker restart to re-read). Confirm with a headless `claude` run " + "inside the container."
|
|
28978
|
+
};
|
|
28979
|
+
}
|
|
28980
|
+
if (zeroFacts >= 3 && okFacts === 0) {
|
|
28981
|
+
return {
|
|
28982
|
+
name: "hindsight extraction",
|
|
28983
|
+
status: "warn",
|
|
28984
|
+
detail: `${zeroFacts} recent extractions produced 0 facts and none succeeded \u2014 ` + "fact extraction may be failing",
|
|
28985
|
+
fix: "Inspect `docker logs switchroom-hindsight` for the extraction error."
|
|
28986
|
+
};
|
|
28987
|
+
}
|
|
28988
|
+
return {
|
|
28989
|
+
name: "hindsight extraction",
|
|
28990
|
+
status: "ok",
|
|
28991
|
+
detail: okFacts > 0 ? `healthy (${okFacts} recent successful extractions)` : "no recent extraction activity to assess"
|
|
28992
|
+
};
|
|
28993
|
+
}
|
|
28994
|
+
function checkHindsightContainerHealth(opts) {
|
|
28995
|
+
const name = opts?.containerName ?? "switchroom-hindsight";
|
|
28996
|
+
const exec = opts?.exec ?? ((cmd, args) => execFileSync17(cmd, args, { stdio: ["ignore", "pipe", "ignore"], timeout: 8000 }).toString());
|
|
28997
|
+
const results = [];
|
|
28998
|
+
let shmRaw;
|
|
28999
|
+
try {
|
|
29000
|
+
shmRaw = exec("docker", ["inspect", name, "--format", "{{.HostConfig.ShmSize}}"]).trim();
|
|
29001
|
+
} catch {
|
|
29002
|
+
return [];
|
|
29003
|
+
}
|
|
29004
|
+
const shmBytes = parseInt(shmRaw, 10);
|
|
29005
|
+
if (Number.isFinite(shmBytes) && shmBytes > 0) {
|
|
29006
|
+
results.push(classifyShmSize(shmBytes));
|
|
29007
|
+
}
|
|
29008
|
+
try {
|
|
29009
|
+
const logs = exec("docker", ["logs", "--since", "10m", name]);
|
|
29010
|
+
results.push(classifyExtractionLogs(logs));
|
|
29011
|
+
} catch {}
|
|
29012
|
+
return results;
|
|
29013
|
+
}
|
|
29014
|
+
var MIN_HINDSIGHT_SHM_BYTES;
|
|
29015
|
+
var init_doctor_memory = __esm(() => {
|
|
29016
|
+
MIN_HINDSIGHT_SHM_BYTES = 1024 * 1024 * 1024;
|
|
29017
|
+
});
|
|
29018
|
+
|
|
28941
29019
|
// src/cli/doctor-docker.ts
|
|
28942
29020
|
import { readFileSync as readFileSync47 } from "node:fs";
|
|
28943
29021
|
function imageTagOf(ref) {
|
|
@@ -31017,7 +31095,7 @@ var init_doctor_agent_smoke = __esm(() => {
|
|
|
31017
31095
|
});
|
|
31018
31096
|
|
|
31019
31097
|
// src/cli/doctor-vault-broker-durability.ts
|
|
31020
|
-
import { execFileSync as
|
|
31098
|
+
import { execFileSync as execFileSync18 } from "node:child_process";
|
|
31021
31099
|
import { existsSync as existsSync54, statSync as statSync22 } from "node:fs";
|
|
31022
31100
|
import { homedir as homedir33 } from "node:os";
|
|
31023
31101
|
import { join as join55 } from "node:path";
|
|
@@ -31079,7 +31157,7 @@ function spawnDockerStat(p) {
|
|
|
31079
31157
|
}
|
|
31080
31158
|
function spawnDockerStatForContainer(containerName2, p) {
|
|
31081
31159
|
try {
|
|
31082
|
-
const stdout =
|
|
31160
|
+
const stdout = execFileSync18("docker", ["exec", containerName2, "stat", "-c", "%i %s", p], { stdio: ["ignore", "pipe", "pipe"], timeout: 3000, encoding: "utf8" });
|
|
31083
31161
|
return { status: 0, stdout, stderr: "", error: null };
|
|
31084
31162
|
} catch (err) {
|
|
31085
31163
|
const e = err;
|
|
@@ -31153,7 +31231,7 @@ function probeBrokerUnlocked(opts) {
|
|
|
31153
31231
|
}
|
|
31154
31232
|
function defaultBrokerStatusProbe() {
|
|
31155
31233
|
try {
|
|
31156
|
-
const out =
|
|
31234
|
+
const out = execFileSync18("switchroom", ["vault", "broker", "status"], { stdio: ["ignore", "pipe", "pipe"], timeout: 3000, encoding: "utf8" });
|
|
31157
31235
|
const parsed = JSON.parse(out.trim());
|
|
31158
31236
|
if (!parsed.running)
|
|
31159
31237
|
return null;
|
|
@@ -31947,6 +32025,7 @@ async function checkHindsight(config) {
|
|
|
31947
32025
|
detail: `${probe2.serverName} ${probe2.serverVersion} at ${host}:${port}`
|
|
31948
32026
|
});
|
|
31949
32027
|
results.push(checkHindsightConsumer(config));
|
|
32028
|
+
results.push(...checkHindsightContainerHealth());
|
|
31950
32029
|
for (const [agentName, agentConfig] of Object.entries(config.agents)) {
|
|
31951
32030
|
const bankId = agentConfig.memory?.collection ?? agentName;
|
|
31952
32031
|
const hasBankMission = !!agentConfig.memory?.bank_mission;
|
|
@@ -33076,6 +33155,7 @@ var init_doctor = __esm(() => {
|
|
|
33076
33155
|
init_accounts();
|
|
33077
33156
|
init_manifest();
|
|
33078
33157
|
init_hindsight();
|
|
33158
|
+
init_doctor_memory();
|
|
33079
33159
|
init_doctor_docker();
|
|
33080
33160
|
init_doctor_auth_broker();
|
|
33081
33161
|
init_doctor_hostd();
|
|
@@ -49601,8 +49681,8 @@ var {
|
|
|
49601
49681
|
} = import__.default;
|
|
49602
49682
|
|
|
49603
49683
|
// src/build-info.ts
|
|
49604
|
-
var VERSION = "0.14.
|
|
49605
|
-
var COMMIT_SHA = "
|
|
49684
|
+
var VERSION = "0.14.76";
|
|
49685
|
+
var COMMIT_SHA = "e7ab9ec6";
|
|
49606
49686
|
|
|
49607
49687
|
// src/cli/agent.ts
|
|
49608
49688
|
init_source();
|
|
@@ -51112,6 +51192,10 @@ function seedWorkspaceBootstrapFiles(params) {
|
|
|
51112
51192
|
}
|
|
51113
51193
|
if (entry === ".gitkeep")
|
|
51114
51194
|
continue;
|
|
51195
|
+
if (params.seedMemoryFile === false && relPath.replace(/\.hbs$/, "") === "MEMORY.md") {
|
|
51196
|
+
params.skipped.push(join8(agentWorkspaceDir, "MEMORY.md"));
|
|
51197
|
+
continue;
|
|
51198
|
+
}
|
|
51115
51199
|
if (entry.endsWith(".hbs")) {
|
|
51116
51200
|
const destRel = relPath.replace(/\.hbs$/, "");
|
|
51117
51201
|
const destPath = join8(agentWorkspaceDir, destRel);
|
|
@@ -51757,7 +51841,8 @@ function scaffoldAgent(name, agentConfigRaw, agentsDir, telegramConfig, switchro
|
|
|
51757
51841
|
context,
|
|
51758
51842
|
created,
|
|
51759
51843
|
skipped,
|
|
51760
|
-
rewrittenWithBackup
|
|
51844
|
+
rewrittenWithBackup,
|
|
51845
|
+
seedMemoryFile: agentConfig.memory?.file !== false
|
|
51761
51846
|
});
|
|
51762
51847
|
ensureClaudeMdSymlinks(phase5WorkspaceDir, created);
|
|
51763
51848
|
const persistentHomeDir = join8(agentDir, "home");
|
|
@@ -52786,7 +52871,8 @@ ${body}
|
|
|
52786
52871
|
context: workspaceContext,
|
|
52787
52872
|
created: changes,
|
|
52788
52873
|
skipped: [],
|
|
52789
|
-
rewrittenWithBackup: changes
|
|
52874
|
+
rewrittenWithBackup: changes,
|
|
52875
|
+
seedMemoryFile: agentConfig.memory?.file !== false
|
|
52790
52876
|
});
|
|
52791
52877
|
ensureClaudeMdSymlinks(reconcileWorkspaceDir, changes);
|
|
52792
52878
|
}
|
|
@@ -66066,6 +66152,7 @@ var HINDSIGHT_DEFAULT_RECALL_MAX_CONCURRENT = 8;
|
|
|
66066
66152
|
var HINDSIGHT_DEFAULT_MEM_LIMIT = "4g";
|
|
66067
66153
|
var HINDSIGHT_DEFAULT_MEM_RESERVATION = "2g";
|
|
66068
66154
|
var HINDSIGHT_DEFAULT_PIDS_LIMIT = 1000;
|
|
66155
|
+
var HINDSIGHT_DEFAULT_SHM_SIZE = "2g";
|
|
66069
66156
|
function isPortFree(port) {
|
|
66070
66157
|
return new Promise((resolve27) => {
|
|
66071
66158
|
const server = createServer4();
|
|
@@ -66156,6 +66243,7 @@ function startHindsight(ports) {
|
|
|
66156
66243
|
`--memory=${HINDSIGHT_DEFAULT_MEM_LIMIT}`,
|
|
66157
66244
|
`--memory-reservation=${HINDSIGHT_DEFAULT_MEM_RESERVATION}`,
|
|
66158
66245
|
`--pids-limit=${HINDSIGHT_DEFAULT_PIDS_LIMIT}`,
|
|
66246
|
+
`--shm-size=${HINDSIGHT_DEFAULT_SHM_SIZE}`,
|
|
66159
66247
|
"-p",
|
|
66160
66248
|
`127.0.0.1:${apiPort}:8888`,
|
|
66161
66249
|
"-p",
|
|
@@ -66209,6 +66297,7 @@ function generateHindsightComposeSnippet() {
|
|
|
66209
66297
|
` mem_limit: ${HINDSIGHT_DEFAULT_MEM_LIMIT}`,
|
|
66210
66298
|
` mem_reservation: ${HINDSIGHT_DEFAULT_MEM_RESERVATION}`,
|
|
66211
66299
|
` pids_limit: ${HINDSIGHT_DEFAULT_PIDS_LIMIT}`,
|
|
66300
|
+
` shm_size: ${HINDSIGHT_DEFAULT_SHM_SIZE}`,
|
|
66212
66301
|
" volumes:",
|
|
66213
66302
|
" - switchroom-hindsight-data:/home/hindsight/.pg0",
|
|
66214
66303
|
` - ${HINDSIGHT_BROKER_SOCK_VOLUME}:/run/switchroom/auth-broker`,
|
|
@@ -71403,10 +71492,66 @@ async function proposeConfigEditViaHostd(args) {
|
|
|
71403
71492
|
}
|
|
71404
71493
|
}
|
|
71405
71494
|
|
|
71495
|
+
// src/web/api.ts
|
|
71496
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
71497
|
+
|
|
71498
|
+
// src/web/microsoft-connect.ts
|
|
71499
|
+
init_oauth2();
|
|
71500
|
+
init_resolver();
|
|
71501
|
+
init_client2();
|
|
71502
|
+
async function startMicrosoftConnect(deps = {}) {
|
|
71503
|
+
const resolved = resolveMicrosoftClientId(deps.configClientId);
|
|
71504
|
+
if (isVaultReference(resolved.clientId)) {
|
|
71505
|
+
return { kind: "byo-vault", ref: resolved.clientId };
|
|
71506
|
+
}
|
|
71507
|
+
const scopes = selectMicrosoftScopes(deps.orgMode ?? false);
|
|
71508
|
+
const cfg = { client_id: resolved.clientId, scopes };
|
|
71509
|
+
try {
|
|
71510
|
+
const device = await (deps.requestDeviceCode ?? requestDeviceCode2)(cfg);
|
|
71511
|
+
return { kind: "started", device, clientId: resolved.clientId, scopes, source: resolved.source };
|
|
71512
|
+
} catch (err) {
|
|
71513
|
+
return { kind: "error", message: err.message };
|
|
71514
|
+
}
|
|
71515
|
+
}
|
|
71516
|
+
async function runMicrosoftConnectPoll(flow, deps = {}) {
|
|
71517
|
+
const now = deps.now ?? Date.now;
|
|
71518
|
+
const cfg = { client_id: flow.clientId, scopes: flow.scopes };
|
|
71519
|
+
let tokens;
|
|
71520
|
+
try {
|
|
71521
|
+
tokens = await (deps.pollDeviceToken ?? pollDeviceToken2)(cfg, flow.device, { now });
|
|
71522
|
+
} catch (err) {
|
|
71523
|
+
return { state: "failed", message: err.message };
|
|
71524
|
+
}
|
|
71525
|
+
const built = buildMicrosoftCredentials({
|
|
71526
|
+
tokens,
|
|
71527
|
+
clientId: flow.clientId,
|
|
71528
|
+
accountEmail: "",
|
|
71529
|
+
fallbackScope: flow.scopes.join(" "),
|
|
71530
|
+
now
|
|
71531
|
+
});
|
|
71532
|
+
if (!built.credentials.microsoftOauth.refreshToken) {
|
|
71533
|
+
return { state: "no-refresh-token" };
|
|
71534
|
+
}
|
|
71535
|
+
const account = built.resolvedEmail;
|
|
71536
|
+
if (!account) {
|
|
71537
|
+
return { state: "failed", message: "Microsoft returned no account identity (no id_token)." };
|
|
71538
|
+
}
|
|
71539
|
+
const addAccount = deps.addAccount ?? ((label, creds) => withAuthBrokerClient((client2) => client2.addAccount(label, creds, true, "microsoft")));
|
|
71540
|
+
try {
|
|
71541
|
+
await addAccount(account, built.credentials);
|
|
71542
|
+
} catch (err) {
|
|
71543
|
+
return { state: "failed", message: err.message };
|
|
71544
|
+
}
|
|
71545
|
+
return {
|
|
71546
|
+
state: "connected",
|
|
71547
|
+
account,
|
|
71548
|
+
accountType: built.credentials.microsoftOauth.accountType
|
|
71549
|
+
};
|
|
71550
|
+
}
|
|
71551
|
+
|
|
71406
71552
|
// src/web/api.ts
|
|
71407
71553
|
init_account_store();
|
|
71408
71554
|
init_client2();
|
|
71409
|
-
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
71410
71555
|
|
|
71411
71556
|
// telegram-plugin/registry/turns-schema.ts
|
|
71412
71557
|
import { chmodSync as chmodSync8, mkdirSync as mkdirSync26 } from "fs";
|
|
@@ -72017,6 +72162,71 @@ function reapConnectionAccessStatuses(now = Date.now()) {
|
|
|
72017
72162
|
function handleGetConnectionAccessStatus(requestId) {
|
|
72018
72163
|
return connectionAccessStatuses.get(requestId) ?? { state: "unknown" };
|
|
72019
72164
|
}
|
|
72165
|
+
var microsoftConnectStatuses = new Map;
|
|
72166
|
+
function reapMicrosoftConnects(now = Date.now()) {
|
|
72167
|
+
for (const [id, s] of microsoftConnectStatuses) {
|
|
72168
|
+
const ttl = s.state === "pending" ? s.expiresInSec * 1000 + 60000 : 30 * 60000;
|
|
72169
|
+
if (now - s.startedAt > ttl)
|
|
72170
|
+
microsoftConnectStatuses.delete(id);
|
|
72171
|
+
}
|
|
72172
|
+
}
|
|
72173
|
+
async function handleStartMicrosoftConnect(config, deps = {}) {
|
|
72174
|
+
const now = deps.now ?? Date.now;
|
|
72175
|
+
const configClientId = config.microsoft_workspace?.microsoft_client_id;
|
|
72176
|
+
const orgMode = deps.orgMode ?? config.microsoft_workspace?.org_mode === true;
|
|
72177
|
+
const started = await startMicrosoftConnect({ ...deps, configClientId, orgMode });
|
|
72178
|
+
if (started.kind === "byo-vault") {
|
|
72179
|
+
return {
|
|
72180
|
+
ok: false,
|
|
72181
|
+
error: `This install uses a vaulted custom Microsoft app (${started.ref}) the dashboard can't read. ` + `Connect from the host: switchroom auth microsoft account add <email>.`
|
|
72182
|
+
};
|
|
72183
|
+
}
|
|
72184
|
+
if (started.kind === "error") {
|
|
72185
|
+
return { ok: false, error: started.message };
|
|
72186
|
+
}
|
|
72187
|
+
const requestId = randomUUID4();
|
|
72188
|
+
microsoftConnectStatuses.set(requestId, {
|
|
72189
|
+
state: "pending",
|
|
72190
|
+
startedAt: now(),
|
|
72191
|
+
userCode: started.device.user_code,
|
|
72192
|
+
verificationUri: started.device.verification_uri,
|
|
72193
|
+
expiresInSec: started.device.expires_in
|
|
72194
|
+
});
|
|
72195
|
+
reapMicrosoftConnects(now());
|
|
72196
|
+
runMicrosoftConnectPoll({ device: started.device, clientId: started.clientId, scopes: started.scopes }, deps).then((res) => {
|
|
72197
|
+
const startedAt = microsoftConnectStatuses.get(requestId)?.startedAt ?? now();
|
|
72198
|
+
if (res.state === "connected") {
|
|
72199
|
+
microsoftConnectStatuses.set(requestId, {
|
|
72200
|
+
state: "connected",
|
|
72201
|
+
startedAt,
|
|
72202
|
+
account: res.account,
|
|
72203
|
+
accountType: res.accountType
|
|
72204
|
+
});
|
|
72205
|
+
captureEvent("microsoft_connect", { outcome: "connected", source: "web_api" });
|
|
72206
|
+
} else {
|
|
72207
|
+
const reason = res.state === "no-refresh-token" ? "Microsoft returned no refresh token (account would expire in ~1h)." : res.message;
|
|
72208
|
+
microsoftConnectStatuses.set(requestId, { state: "failed", startedAt, reason });
|
|
72209
|
+
}
|
|
72210
|
+
}).catch((err) => {
|
|
72211
|
+
const startedAt = microsoftConnectStatuses.get(requestId)?.startedAt ?? now();
|
|
72212
|
+
microsoftConnectStatuses.set(requestId, {
|
|
72213
|
+
state: "failed",
|
|
72214
|
+
startedAt,
|
|
72215
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
72216
|
+
});
|
|
72217
|
+
captureException(err, { action: "microsoft_connect" });
|
|
72218
|
+
});
|
|
72219
|
+
return {
|
|
72220
|
+
ok: true,
|
|
72221
|
+
requestId,
|
|
72222
|
+
userCode: started.device.user_code,
|
|
72223
|
+
verificationUri: started.device.verification_uri,
|
|
72224
|
+
expiresInSec: started.device.expires_in
|
|
72225
|
+
};
|
|
72226
|
+
}
|
|
72227
|
+
function handleGetMicrosoftConnectStatus(requestId) {
|
|
72228
|
+
return microsoftConnectStatuses.get(requestId) ?? { state: "unknown" };
|
|
72229
|
+
}
|
|
72020
72230
|
function handleSetConnectionAccess(configPath, config, args, deps = {}) {
|
|
72021
72231
|
const provider = args.provider;
|
|
72022
72232
|
if (provider !== "google" && provider !== "microsoft") {
|
|
@@ -72800,6 +73010,16 @@ function parseRoute(pathname, method) {
|
|
|
72800
73010
|
params: { requestId: decodeURIComponent(accessStatusMatch[1]) }
|
|
72801
73011
|
};
|
|
72802
73012
|
}
|
|
73013
|
+
if (method === "POST" && pathname === "/api/connections/microsoft/connect") {
|
|
73014
|
+
return { handler: "startMicrosoftConnect", params: {} };
|
|
73015
|
+
}
|
|
73016
|
+
const msConnectMatch = pathname.match(/^\/api\/connections\/microsoft\/connect\/([^/]+)$/);
|
|
73017
|
+
if (method === "GET" && msConnectMatch) {
|
|
73018
|
+
return {
|
|
73019
|
+
handler: "getMicrosoftConnectStatus",
|
|
73020
|
+
params: { requestId: decodeURIComponent(msConnectMatch[1]) }
|
|
73021
|
+
};
|
|
73022
|
+
}
|
|
72803
73023
|
if (method === "POST" && pathname === "/api/auth/use") {
|
|
72804
73024
|
return { handler: "useAccount", params: {} };
|
|
72805
73025
|
}
|
|
@@ -72976,6 +73196,13 @@ function startWebServer(config, port, hostname = "127.0.0.1", configPath) {
|
|
|
72976
73196
|
}
|
|
72977
73197
|
case "getConnectionAccessStatus":
|
|
72978
73198
|
return jsonResponse(handleGetConnectionAccessStatus(route.params.requestId));
|
|
73199
|
+
case "startMicrosoftConnect":
|
|
73200
|
+
return (async () => {
|
|
73201
|
+
const result = await handleStartMicrosoftConnect(freshConfig());
|
|
73202
|
+
return jsonResponse(result, result.ok ? 200 : 400);
|
|
73203
|
+
})();
|
|
73204
|
+
case "getMicrosoftConnectStatus":
|
|
73205
|
+
return jsonResponse(handleGetMicrosoftConnectStatus(route.params.requestId));
|
|
72979
73206
|
case "refreshQuota": {
|
|
72980
73207
|
return (async () => {
|
|
72981
73208
|
let body = {};
|
|
@@ -75714,7 +75941,7 @@ import {
|
|
|
75714
75941
|
} from "node:fs";
|
|
75715
75942
|
import { dirname as dirname15, join as join60 } from "node:path";
|
|
75716
75943
|
import { homedir as homedir35 } from "node:os";
|
|
75717
|
-
import { execFileSync as
|
|
75944
|
+
import { execFileSync as execFileSync19 } from "node:child_process";
|
|
75718
75945
|
|
|
75719
75946
|
class PythonEnvError extends Error {
|
|
75720
75947
|
stderr;
|
|
@@ -75761,7 +75988,7 @@ function ensurePythonEnv(opts) {
|
|
|
75761
75988
|
}
|
|
75762
75989
|
mkdirSync33(dirname15(venvDir), { recursive: true });
|
|
75763
75990
|
try {
|
|
75764
|
-
|
|
75991
|
+
execFileSync19(hostPython, ["-m", "venv", venvDir], { stdio: "pipe" });
|
|
75765
75992
|
} catch (err) {
|
|
75766
75993
|
const e = err;
|
|
75767
75994
|
throw new PythonEnvError(`Failed to create venv for skill "${skillName}" with ${hostPython}: ${e.message}`, e.stderr?.toString());
|
|
@@ -75773,7 +76000,7 @@ function ensurePythonEnv(opts) {
|
|
|
75773
76000
|
delete childEnv.PIP_TARGET;
|
|
75774
76001
|
delete childEnv.PIP_PREFIX;
|
|
75775
76002
|
delete childEnv.PYTHONUSERBASE;
|
|
75776
|
-
|
|
76003
|
+
execFileSync19(pipBin, ["install", "--disable-pip-version-check", "-r", requirementsPath], { stdio: "pipe", env: childEnv });
|
|
75777
76004
|
} catch (err) {
|
|
75778
76005
|
const e = err;
|
|
75779
76006
|
throw new PythonEnvError(`Failed to install requirements for skill "${skillName}": ${e.message}`, e.stderr?.toString());
|
|
@@ -75802,7 +76029,7 @@ import {
|
|
|
75802
76029
|
} from "node:fs";
|
|
75803
76030
|
import { dirname as dirname16, join as join61 } from "node:path";
|
|
75804
76031
|
import { homedir as homedir36 } from "node:os";
|
|
75805
|
-
import { execFileSync as
|
|
76032
|
+
import { execFileSync as execFileSync20 } from "node:child_process";
|
|
75806
76033
|
|
|
75807
76034
|
class NodeEnvError extends Error {
|
|
75808
76035
|
stderr;
|
|
@@ -75886,10 +76113,10 @@ function ensureNodeEnv(opts) {
|
|
|
75886
76113
|
try {
|
|
75887
76114
|
if (installer === "bun") {
|
|
75888
76115
|
const args = copiedLockfile ? ["install", "--frozen-lockfile"] : ["install"];
|
|
75889
|
-
|
|
76116
|
+
execFileSync20("bun", args, { cwd: envDir, stdio: "pipe" });
|
|
75890
76117
|
} else {
|
|
75891
76118
|
const args = copiedLockfile ? ["ci"] : ["install"];
|
|
75892
|
-
|
|
76119
|
+
execFileSync20("npm", args, { cwd: envDir, stdio: "pipe" });
|
|
75893
76120
|
}
|
|
75894
76121
|
} catch (err) {
|
|
75895
76122
|
const e = err;
|
|
@@ -77217,7 +77444,7 @@ function registerDebugCommand(program3) {
|
|
|
77217
77444
|
init_source();
|
|
77218
77445
|
|
|
77219
77446
|
// src/worktree/claim.ts
|
|
77220
|
-
import { execFileSync as
|
|
77447
|
+
import { execFileSync as execFileSync21 } from "node:child_process";
|
|
77221
77448
|
import { closeSync as closeSync12, mkdirSync as mkdirSync36, openSync as openSync12, existsSync as existsSync66, unlinkSync as unlinkSync13 } from "node:fs";
|
|
77222
77449
|
import { join as join66, resolve as resolve42 } from "node:path";
|
|
77223
77450
|
import { homedir as homedir39 } from "node:os";
|
|
@@ -77384,7 +77611,7 @@ async function claimWorktree(input, codeRepos) {
|
|
|
77384
77611
|
releaseLock();
|
|
77385
77612
|
}
|
|
77386
77613
|
try {
|
|
77387
|
-
|
|
77614
|
+
execFileSync21("git", ["worktree", "add", "-b", branch, worktreePath], {
|
|
77388
77615
|
cwd: repoPath,
|
|
77389
77616
|
stdio: "pipe"
|
|
77390
77617
|
});
|
|
@@ -77397,7 +77624,7 @@ async function claimWorktree(input, codeRepos) {
|
|
|
77397
77624
|
}
|
|
77398
77625
|
|
|
77399
77626
|
// src/worktree/release.ts
|
|
77400
|
-
import { execFileSync as
|
|
77627
|
+
import { execFileSync as execFileSync22 } from "node:child_process";
|
|
77401
77628
|
import { existsSync as existsSync67 } from "node:fs";
|
|
77402
77629
|
function releaseWorktree(input) {
|
|
77403
77630
|
const { id } = input;
|
|
@@ -77408,7 +77635,7 @@ function releaseWorktree(input) {
|
|
|
77408
77635
|
let gitSuccess = true;
|
|
77409
77636
|
if (existsSync67(record2.path)) {
|
|
77410
77637
|
try {
|
|
77411
|
-
|
|
77638
|
+
execFileSync22("git", ["worktree", "remove", "--force", record2.path], {
|
|
77412
77639
|
cwd: record2.repo,
|
|
77413
77640
|
stdio: "pipe"
|
|
77414
77641
|
});
|
|
@@ -77444,16 +77671,16 @@ function listWorktrees() {
|
|
|
77444
77671
|
}
|
|
77445
77672
|
|
|
77446
77673
|
// src/worktree/reaper.ts
|
|
77447
|
-
import { execFileSync as
|
|
77674
|
+
import { execFileSync as execFileSync23 } from "node:child_process";
|
|
77448
77675
|
import { existsSync as existsSync68 } from "node:fs";
|
|
77449
77676
|
var STALE_THRESHOLD_MS = 10 * 60 * 1000;
|
|
77450
77677
|
function isPathInUse(path7) {
|
|
77451
77678
|
try {
|
|
77452
|
-
|
|
77679
|
+
execFileSync23("fuser", [path7], { stdio: "pipe" });
|
|
77453
77680
|
return true;
|
|
77454
77681
|
} catch {}
|
|
77455
77682
|
try {
|
|
77456
|
-
const out =
|
|
77683
|
+
const out = execFileSync23("lsof", ["-t", path7], {
|
|
77457
77684
|
stdio: ["ignore", "pipe", "ignore"]
|
|
77458
77685
|
}).toString().trim();
|
|
77459
77686
|
if (out.length > 0)
|
|
@@ -77463,7 +77690,7 @@ function isPathInUse(path7) {
|
|
|
77463
77690
|
}
|
|
77464
77691
|
function hasUncommittedChanges(repoPath, worktreePath) {
|
|
77465
77692
|
try {
|
|
77466
|
-
const out =
|
|
77693
|
+
const out = execFileSync23("git", ["-C", worktreePath, "status", "--porcelain"], { stdio: "pipe" }).toString();
|
|
77467
77694
|
return out.trim().length > 0;
|
|
77468
77695
|
} catch {
|
|
77469
77696
|
return false;
|
|
@@ -77477,7 +77704,7 @@ function reapRecord(record2) {
|
|
|
77477
77704
|
warning = `[worktree-reaper] Reaped worktree with uncommitted changes: ` + `id=${id} branch=${branch} agent=${ownerAgent ?? "unknown"} path=${path7}`;
|
|
77478
77705
|
}
|
|
77479
77706
|
try {
|
|
77480
|
-
|
|
77707
|
+
execFileSync23("git", ["worktree", "remove", "--force", path7], {
|
|
77481
77708
|
cwd: repo,
|
|
77482
77709
|
stdio: "pipe"
|
|
77483
77710
|
});
|
|
@@ -78960,7 +79187,7 @@ agents:
|
|
|
78960
79187
|
init_resolver();
|
|
78961
79188
|
import { dirname as dirname21, join as join72, resolve as resolve44 } from "node:path";
|
|
78962
79189
|
import { homedir as homedir41 } from "node:os";
|
|
78963
|
-
import { execFileSync as
|
|
79190
|
+
import { execFileSync as execFileSync24 } from "node:child_process";
|
|
78964
79191
|
init_vault();
|
|
78965
79192
|
init_loader();
|
|
78966
79193
|
init_loader();
|
|
@@ -79368,7 +79595,7 @@ async function ensureHostMountSources(config) {
|
|
|
79368
79595
|
}
|
|
79369
79596
|
function detectComposeV2() {
|
|
79370
79597
|
try {
|
|
79371
|
-
const out =
|
|
79598
|
+
const out = execFileSync24("docker", ["compose", "version"], {
|
|
79372
79599
|
stdio: ["ignore", "pipe", "pipe"],
|
|
79373
79600
|
encoding: "utf8"
|
|
79374
79601
|
});
|
package/dist/cli/ui/index.html
CHANGED
|
@@ -559,6 +559,51 @@
|
|
|
559
559
|
}
|
|
560
560
|
}
|
|
561
561
|
|
|
562
|
+
// Start an in-browser Microsoft connect: show the device code + link,
|
|
563
|
+
// then poll until the operator completes sign-in on Microsoft's site.
|
|
564
|
+
async function connectMicrosoft() {
|
|
565
|
+
const card = document.getElementById('ms-connect-card');
|
|
566
|
+
const show = (html) => { if (card) card.innerHTML = html; };
|
|
567
|
+
show('<div class="loading" style="padding:.8rem">Starting…</div>');
|
|
568
|
+
try {
|
|
569
|
+
const res = await fetch(`${API}/api/connections/microsoft/connect`, { method: 'POST', headers: authHeaders() });
|
|
570
|
+
const data = await res.json();
|
|
571
|
+
if (!res.ok || !data.ok) { show(''); showError(data.error || `HTTP ${res.status}`); return; }
|
|
572
|
+
const url = data.verificationUri, code = data.userCode;
|
|
573
|
+
show(`<div class="account-card" style="border-color:var(--accent)">
|
|
574
|
+
<div class="account-card-header"><div class="account-label">Connect a Microsoft account</div></div>
|
|
575
|
+
<div style="padding:.3rem 0;line-height:1.7">
|
|
576
|
+
1. Open <a href="${escapeHtml(url)}" target="_blank" rel="noopener" style="color:var(--accent)">${escapeHtml(url)}</a><br>
|
|
577
|
+
2. Enter code: <code style="font-size:1.15rem;letter-spacing:.08em">${escapeHtml(code)}</code><br>
|
|
578
|
+
3. Approve the requested permissions (Mail, Calendar, Files).
|
|
579
|
+
</div>
|
|
580
|
+
<div id="ms-connect-status" style="color:var(--text-dim);margin-top:.3rem">Waiting for sign-in… (this card expires in ~15 min)</div>
|
|
581
|
+
</div>`);
|
|
582
|
+
const statusEl = () => document.getElementById('ms-connect-status');
|
|
583
|
+
const started = Date.now();
|
|
584
|
+
const poll = async () => {
|
|
585
|
+
const sres = await fetch(`${API}/api/connections/microsoft/connect/${encodeURIComponent(data.requestId)}`, { headers: authHeaders() });
|
|
586
|
+
const s = sres.ok ? await sres.json() : { state: 'failed', reason: `HTTP ${sres.status}` };
|
|
587
|
+
if (s.state === 'pending') {
|
|
588
|
+
if (Date.now() - started > ((data.expiresInSec || 900) * 1000 + 30000)) { const e = statusEl(); if (e) e.textContent = 'Expired — click Connect to try again.'; return; }
|
|
589
|
+
setTimeout(poll, 3000);
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
if (s.state === 'connected') {
|
|
593
|
+
show(`<div class="loading" style="padding:.8rem;color:var(--green)">✓ Connected ${escapeHtml(s.account)} (${escapeHtml(s.accountType)}). Use the access toggles below to grant an agent.</div>`);
|
|
594
|
+
fetchConnections();
|
|
595
|
+
} else {
|
|
596
|
+
show('');
|
|
597
|
+
showError(s.reason || 'connect failed');
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
setTimeout(poll, 3000);
|
|
601
|
+
} catch (err) {
|
|
602
|
+
show('');
|
|
603
|
+
showError(err.message);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
562
607
|
async function fetchSchedule() {
|
|
563
608
|
try {
|
|
564
609
|
const res = await fetch(`${API}/api/schedule`, { headers: authHeaders() });
|
|
@@ -1115,11 +1160,18 @@
|
|
|
1115
1160
|
google.map(a => renderOAuthAccountCard(a, { showType: false, provider: 'google', agentNames })).join(''),
|
|
1116
1161
|
);
|
|
1117
1162
|
|
|
1118
|
-
const
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1163
|
+
const msCards = microsoft.map(a => renderOAuthAccountCard(a, { showType: true, provider: 'microsoft', agentNames })).join('');
|
|
1164
|
+
const microsoftSection = `
|
|
1165
|
+
<div style="margin-bottom:1.5rem">
|
|
1166
|
+
<h3 style="margin:0 0 .6rem;font-size:.95rem;color:var(--text-dim);text-transform:uppercase;letter-spacing:.04em">
|
|
1167
|
+
Microsoft 365
|
|
1168
|
+
<button onclick="connectMicrosoft()" class="usage-pill primary" style="margin-left:.6rem;cursor:pointer;border:none;text-transform:none;font-weight:600">+ Connect a Microsoft account</button>
|
|
1169
|
+
</h3>
|
|
1170
|
+
<div id="ms-connect-card"></div>
|
|
1171
|
+
${msCards
|
|
1172
|
+
? `<div class="accounts-grid">${msCards}</div>`
|
|
1173
|
+
: `<div class="loading" style="padding:.8rem">No Microsoft accounts yet — click <b>Connect a Microsoft account</b> above (or <code>/connect microsoft</code> from Telegram).</div>`}
|
|
1174
|
+
</div>`;
|
|
1123
1175
|
|
|
1124
1176
|
let notionCards = '';
|
|
1125
1177
|
if (notion.configured) {
|
|
@@ -13726,6 +13726,7 @@ var AgentToolsSchema = exports_external.object({
|
|
|
13726
13726
|
var AgentMemorySchema = exports_external.object({
|
|
13727
13727
|
collection: exports_external.string().describe("Hindsight collection name for this agent"),
|
|
13728
13728
|
auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
|
|
13729
|
+
file: exports_external.boolean().default(true).describe("Maintain a curated workspace MEMORY.md file (seeded once, " + "auto-loaded every turn). Set false for hindsight-only memory: " + "the file is not seeded or re-created, so once migrated into " + "Hindsight and deleted it stays gone. Recall + directives carry " + "the memory instead. Cascade: override (per-agent wins over default)."),
|
|
13729
13730
|
isolation: exports_external.enum(["default", "strict"]).default("default").describe("strict = never shared cross-agent, default = eligible for reflect"),
|
|
13730
13731
|
bank_mission: exports_external.string().optional().describe("Bank-level mission statement used during recall to contextualize results"),
|
|
13731
13732
|
retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain"),
|
|
@@ -13945,6 +13946,7 @@ var profileFields = {
|
|
|
13945
13946
|
memory: exports_external.object({
|
|
13946
13947
|
collection: exports_external.string().optional(),
|
|
13947
13948
|
auto_recall: exports_external.boolean().optional(),
|
|
13949
|
+
file: exports_external.boolean().optional(),
|
|
13948
13950
|
isolation: exports_external.enum(["default", "strict"]).optional(),
|
|
13949
13951
|
recall: exports_external.object({
|
|
13950
13952
|
max_memories: exports_external.number().int().min(0).optional(),
|
|
@@ -11312,6 +11312,7 @@ var init_schema = __esm(() => {
|
|
|
11312
11312
|
AgentMemorySchema = exports_external.object({
|
|
11313
11313
|
collection: exports_external.string().describe("Hindsight collection name for this agent"),
|
|
11314
11314
|
auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
|
|
11315
|
+
file: exports_external.boolean().default(true).describe("Maintain a curated workspace MEMORY.md file (seeded once, " + "auto-loaded every turn). Set false for hindsight-only memory: " + "the file is not seeded or re-created, so once migrated into " + "Hindsight and deleted it stays gone. Recall + directives carry " + "the memory instead. Cascade: override (per-agent wins over default)."),
|
|
11315
11316
|
isolation: exports_external.enum(["default", "strict"]).default("default").describe("strict = never shared cross-agent, default = eligible for reflect"),
|
|
11316
11317
|
bank_mission: exports_external.string().optional().describe("Bank-level mission statement used during recall to contextualize results"),
|
|
11317
11318
|
retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain"),
|
|
@@ -11531,6 +11532,7 @@ var init_schema = __esm(() => {
|
|
|
11531
11532
|
memory: exports_external.object({
|
|
11532
11533
|
collection: exports_external.string().optional(),
|
|
11533
11534
|
auto_recall: exports_external.boolean().optional(),
|
|
11535
|
+
file: exports_external.boolean().optional(),
|
|
11534
11536
|
isolation: exports_external.enum(["default", "strict"]).optional(),
|
|
11535
11537
|
recall: exports_external.object({
|
|
11536
11538
|
max_memories: exports_external.number().int().min(0).optional(),
|
|
@@ -11312,6 +11312,7 @@ var init_schema = __esm(() => {
|
|
|
11312
11312
|
AgentMemorySchema = exports_external.object({
|
|
11313
11313
|
collection: exports_external.string().describe("Hindsight collection name for this agent"),
|
|
11314
11314
|
auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
|
|
11315
|
+
file: exports_external.boolean().default(true).describe("Maintain a curated workspace MEMORY.md file (seeded once, " + "auto-loaded every turn). Set false for hindsight-only memory: " + "the file is not seeded or re-created, so once migrated into " + "Hindsight and deleted it stays gone. Recall + directives carry " + "the memory instead. Cascade: override (per-agent wins over default)."),
|
|
11315
11316
|
isolation: exports_external.enum(["default", "strict"]).default("default").describe("strict = never shared cross-agent, default = eligible for reflect"),
|
|
11316
11317
|
bank_mission: exports_external.string().optional().describe("Bank-level mission statement used during recall to contextualize results"),
|
|
11317
11318
|
retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain"),
|
|
@@ -11531,6 +11532,7 @@ var init_schema = __esm(() => {
|
|
|
11531
11532
|
memory: exports_external.object({
|
|
11532
11533
|
collection: exports_external.string().optional(),
|
|
11533
11534
|
auto_recall: exports_external.boolean().optional(),
|
|
11535
|
+
file: exports_external.boolean().optional(),
|
|
11534
11536
|
isolation: exports_external.enum(["default", "strict"]).optional(),
|
|
11535
11537
|
recall: exports_external.object({
|
|
11536
11538
|
max_memories: exports_external.number().int().min(0).optional(),
|
package/package.json
CHANGED
|
@@ -23815,6 +23815,7 @@ var init_schema = __esm(() => {
|
|
|
23815
23815
|
AgentMemorySchema = exports_external.object({
|
|
23816
23816
|
collection: exports_external.string().describe("Hindsight collection name for this agent"),
|
|
23817
23817
|
auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
|
|
23818
|
+
file: exports_external.boolean().default(true).describe("Maintain a curated workspace MEMORY.md file (seeded once, " + "auto-loaded every turn). Set false for hindsight-only memory: " + "the file is not seeded or re-created, so once migrated into " + "Hindsight and deleted it stays gone. Recall + directives carry " + "the memory instead. Cascade: override (per-agent wins over default)."),
|
|
23818
23819
|
isolation: exports_external.enum(["default", "strict"]).default("default").describe("strict = never shared cross-agent, default = eligible for reflect"),
|
|
23819
23820
|
bank_mission: exports_external.string().optional().describe("Bank-level mission statement used during recall to contextualize results"),
|
|
23820
23821
|
retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain"),
|
|
@@ -24034,6 +24035,7 @@ var init_schema = __esm(() => {
|
|
|
24034
24035
|
memory: exports_external.object({
|
|
24035
24036
|
collection: exports_external.string().optional(),
|
|
24036
24037
|
auto_recall: exports_external.boolean().optional(),
|
|
24038
|
+
file: exports_external.boolean().optional(),
|
|
24037
24039
|
isolation: exports_external.enum(["default", "strict"]).optional(),
|
|
24038
24040
|
recall: exports_external.object({
|
|
24039
24041
|
max_memories: exports_external.number().int().min(0).optional(),
|
|
@@ -52819,10 +52821,10 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
|
|
|
52819
52821
|
}
|
|
52820
52822
|
|
|
52821
52823
|
// ../src/build-info.ts
|
|
52822
|
-
var VERSION = "0.14.
|
|
52823
|
-
var COMMIT_SHA = "
|
|
52824
|
-
var COMMIT_DATE = "2026-06-
|
|
52825
|
-
var LATEST_PR =
|
|
52824
|
+
var VERSION = "0.14.76";
|
|
52825
|
+
var COMMIT_SHA = "e7ab9ec6";
|
|
52826
|
+
var COMMIT_DATE = "2026-06-06T08:50:42Z";
|
|
52827
|
+
var LATEST_PR = 2196;
|
|
52826
52828
|
var COMMITS_AHEAD_OF_TAG = 0;
|
|
52827
52829
|
|
|
52828
52830
|
// gateway/boot-version.ts
|