@openscout/scout 0.2.47 → 0.2.48
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 +48 -1
- package/dist/client/assets/index-CA2ASaSK.css +1 -0
- package/dist/client/index.html +2 -2
- package/dist/control-plane-client/assets/addon-fit-DX4qG4td.js +1 -0
- package/dist/control-plane-client/assets/addon-webgl-DCtw1yLn.js +64 -0
- package/dist/control-plane-client/assets/{arc.es-BkYc1VKe.js → arc.es-DndjiskC.js} +1 -1
- package/dist/control-plane-client/assets/index-CCQvN8TG.css +1 -0
- package/dist/control-plane-client/assets/index-DlKOe-t6.js +140 -0
- package/dist/control-plane-client/assets/index-TVkH_WDG.js +1 -0
- package/dist/control-plane-client/assets/xterm-B-qIQCd3.js +16 -0
- package/dist/control-plane-client/index.html +2 -2
- package/dist/main.mjs +574 -2053
- package/dist/pair-supervisor.mjs +12519 -12609
- package/dist/scout-control-plane-web.mjs +9748 -9853
- package/dist/scout-web-server.mjs +8833 -8943
- package/package.json +2 -2
- package/dist/client/assets/index-BIhZnptE.css +0 -1
- package/dist/control-plane-client/assets/index-C3R8grI3.css +0 -1
- package/dist/control-plane-client/assets/index-DLYQAPHm.js +0 -9
- /package/dist/client/assets/{index-Dz8OkaKF.js → index-DAPDqcsj.js} +0 -0
package/dist/main.mjs
CHANGED
|
@@ -2682,31 +2682,6 @@ var init_user_project_hints = __esm(() => {
|
|
|
2682
2682
|
});
|
|
2683
2683
|
|
|
2684
2684
|
// ../runtime/src/setup.ts
|
|
2685
|
-
var exports_setup = {};
|
|
2686
|
-
__export(exports_setup, {
|
|
2687
|
-
writeRelayAgentOverrides: () => writeRelayAgentOverrides,
|
|
2688
|
-
writeProjectConfig: () => writeProjectConfig,
|
|
2689
|
-
writeOpenScoutSettings: () => writeOpenScoutSettings,
|
|
2690
|
-
resolveRelayAgentConfig: () => resolveRelayAgentConfig,
|
|
2691
|
-
readRelayAgentOverrides: () => readRelayAgentOverrides,
|
|
2692
|
-
readProjectConfig: () => readProjectConfig,
|
|
2693
|
-
readOpenScoutSettings: () => readOpenScoutSettings,
|
|
2694
|
-
primaryDirectConversationIdForAgent: () => primaryDirectConversationIdForAgent,
|
|
2695
|
-
loadResolvedRelayAgents: () => loadResolvedRelayAgents,
|
|
2696
|
-
installScoutSkillToHarnesses: () => installScoutSkillToHarnesses,
|
|
2697
|
-
initializeOpenScoutSetup: () => initializeOpenScoutSetup,
|
|
2698
|
-
findNearestProjectRoot: () => findNearestProjectRoot,
|
|
2699
|
-
ensureScoutRelayAgentConfigured: () => ensureScoutRelayAgentConfigured,
|
|
2700
|
-
ensureRelayAgentConfigured: () => ensureRelayAgentConfigured,
|
|
2701
|
-
ensureProjectConfigForDirectory: () => ensureProjectConfigForDirectory,
|
|
2702
|
-
detectPreferredHarness: () => detectPreferredHarness,
|
|
2703
|
-
clearGitBranchCache: () => clearGitBranchCache,
|
|
2704
|
-
buildRelayAgentInstance: () => buildRelayAgentInstance,
|
|
2705
|
-
SCOUT_PRIMARY_CONVERSATION_ID: () => SCOUT_PRIMARY_CONVERSATION_ID,
|
|
2706
|
-
SCOUT_AGENT_ID: () => SCOUT_AGENT_ID,
|
|
2707
|
-
MANAGED_AGENT_HARNESSES: () => MANAGED_AGENT_HARNESSES,
|
|
2708
|
-
DEFAULT_OPERATOR_NAME: () => DEFAULT_OPERATOR_NAME
|
|
2709
|
-
});
|
|
2710
2685
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
2711
2686
|
import { existsSync as existsSync3, readFileSync } from "fs";
|
|
2712
2687
|
import { access, mkdir as mkdir2, readdir as readdir2, readFile as readFile3, realpath, rm, stat as stat2, writeFile as writeFile2 } from "fs/promises";
|
|
@@ -2885,13 +2860,6 @@ function normalizeTelegramConversationId(value) {
|
|
|
2885
2860
|
}
|
|
2886
2861
|
return normalized;
|
|
2887
2862
|
}
|
|
2888
|
-
function primaryDirectConversationIdForAgent(agentId) {
|
|
2889
|
-
const normalizedAgentId = normalizeAgentId(agentId);
|
|
2890
|
-
if (normalizedAgentId === SCOUT_AGENT_ID) {
|
|
2891
|
-
return SCOUT_PRIMARY_CONVERSATION_ID;
|
|
2892
|
-
}
|
|
2893
|
-
return `dm.operator.${normalizedAgentId}`;
|
|
2894
|
-
}
|
|
2895
2863
|
function resolveNodeQualifier() {
|
|
2896
2864
|
const fromEnv = process.env.OPENSCOUT_NODE_QUALIFIER?.trim();
|
|
2897
2865
|
if (fromEnv) {
|
|
@@ -2937,13 +2905,6 @@ function detectGitBranch(projectRoot) {
|
|
|
2937
2905
|
gitBranchCache.set(projectRoot, { branch, expiresAt: now + GIT_BRANCH_CACHE_TTL_MS });
|
|
2938
2906
|
return branch;
|
|
2939
2907
|
}
|
|
2940
|
-
function clearGitBranchCache(projectRoot) {
|
|
2941
|
-
if (projectRoot) {
|
|
2942
|
-
gitBranchCache.delete(projectRoot);
|
|
2943
|
-
} else {
|
|
2944
|
-
gitBranchCache.clear();
|
|
2945
|
-
}
|
|
2946
|
-
}
|
|
2947
2908
|
function resolveWorkspaceQualifier(projectRoot) {
|
|
2948
2909
|
const normalizedProjectRoot = normalizePath(projectRoot);
|
|
2949
2910
|
const branch = detectGitBranch(normalizedProjectRoot);
|
|
@@ -4430,52 +4391,6 @@ async function ensureRelayAgentConfigured(value, options = {}) {
|
|
|
4430
4391
|
registrationKind: "configured"
|
|
4431
4392
|
};
|
|
4432
4393
|
}
|
|
4433
|
-
async function ensureScoutRelayAgentConfigured(options = {}) {
|
|
4434
|
-
const settings = await readOpenScoutSettings({ currentDirectory: options.currentDirectory });
|
|
4435
|
-
const overrides = await readRelayAgentOverrides();
|
|
4436
|
-
const resolvedProjectRoot = options.projectRoot ? normalizePath(options.projectRoot) : options.currentDirectory ? await findNearestProjectRoot(options.currentDirectory) ?? normalizePath(options.currentDirectory) : normalizePath(process.cwd());
|
|
4437
|
-
const qualifiedAgentId = buildRelayAgentInstance(SCOUT_AGENT_ID, resolvedProjectRoot).id;
|
|
4438
|
-
const existing = overrides[qualifiedAgentId] ?? overrides[SCOUT_AGENT_ID];
|
|
4439
|
-
const nextOverride = {
|
|
4440
|
-
...existing,
|
|
4441
|
-
agentId: qualifiedAgentId,
|
|
4442
|
-
definitionId: SCOUT_AGENT_ID,
|
|
4443
|
-
displayName: "Scout",
|
|
4444
|
-
projectName: "OpenScout",
|
|
4445
|
-
projectRoot: resolvedProjectRoot,
|
|
4446
|
-
projectConfigPath: existing?.projectConfigPath ? normalizePath(existing.projectConfigPath) : null,
|
|
4447
|
-
source: "manual",
|
|
4448
|
-
startedAt: existing?.startedAt ?? nowSeconds(),
|
|
4449
|
-
systemPrompt: existing?.systemPrompt?.trim() || undefined,
|
|
4450
|
-
capabilities: normalizeCapabilities(existing?.capabilities),
|
|
4451
|
-
defaultHarness: "claude",
|
|
4452
|
-
harnessProfiles: buildHarnessProfiles({
|
|
4453
|
-
projectRoot: resolvedProjectRoot,
|
|
4454
|
-
sessionKey: qualifiedAgentId,
|
|
4455
|
-
sessionPrefix: settings.agents.sessionPrefix,
|
|
4456
|
-
defaultHarness: "claude",
|
|
4457
|
-
profiles: existing?.harnessProfiles,
|
|
4458
|
-
runtime: existing?.runtime,
|
|
4459
|
-
launchArgs: normalizeLaunchArgs(existing?.launchArgs)
|
|
4460
|
-
}),
|
|
4461
|
-
runtime: {
|
|
4462
|
-
cwd: resolvedProjectRoot,
|
|
4463
|
-
harness: "claude",
|
|
4464
|
-
transport: "claude_stream_json",
|
|
4465
|
-
sessionId: normalizeTmuxSessionName(existing?.runtime?.sessionId, `${SCOUT_AGENT_ID}-claude`, settings.agents.sessionPrefix),
|
|
4466
|
-
wakePolicy: "on_demand"
|
|
4467
|
-
}
|
|
4468
|
-
};
|
|
4469
|
-
nextOverride.launchArgs = nextOverride.harnessProfiles?.claude?.launchArgs ?? [];
|
|
4470
|
-
if (overrides[SCOUT_AGENT_ID]) {
|
|
4471
|
-
delete overrides[SCOUT_AGENT_ID];
|
|
4472
|
-
}
|
|
4473
|
-
if (JSON.stringify(overrides[qualifiedAgentId]) !== JSON.stringify(nextOverride)) {
|
|
4474
|
-
overrides[qualifiedAgentId] = nextOverride;
|
|
4475
|
-
await writeRelayAgentOverrides(overrides);
|
|
4476
|
-
}
|
|
4477
|
-
return nextOverride;
|
|
4478
|
-
}
|
|
4479
4394
|
async function initializeOpenScoutSetup(options = {}) {
|
|
4480
4395
|
return loadResolvedRelayAgents({
|
|
4481
4396
|
currentDirectory: options.currentDirectory,
|
|
@@ -4639,418 +4554,6 @@ async function readOptionalFile(filePath) {
|
|
|
4639
4554
|
return null;
|
|
4640
4555
|
}
|
|
4641
4556
|
}
|
|
4642
|
-
function parseJsonObject(value) {
|
|
4643
|
-
const trimmed = value?.trim();
|
|
4644
|
-
if (!trimmed) {
|
|
4645
|
-
return {};
|
|
4646
|
-
}
|
|
4647
|
-
try {
|
|
4648
|
-
const parsed = JSON.parse(trimmed);
|
|
4649
|
-
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
4650
|
-
} catch {
|
|
4651
|
-
return {};
|
|
4652
|
-
}
|
|
4653
|
-
}
|
|
4654
|
-
function appendActionOutput(blockState, output) {
|
|
4655
|
-
if (!blockState || blockState.block.type !== "action" || !output) {
|
|
4656
|
-
return;
|
|
4657
|
-
}
|
|
4658
|
-
const actionBlock = blockState.block;
|
|
4659
|
-
actionBlock.action.output += output;
|
|
4660
|
-
}
|
|
4661
|
-
function updateBlockCompletion(blockState, completed) {
|
|
4662
|
-
if (!blockState) {
|
|
4663
|
-
return;
|
|
4664
|
-
}
|
|
4665
|
-
blockState.status = completed ? "completed" : "streaming";
|
|
4666
|
-
blockState.block.status = completed ? "completed" : "streaming";
|
|
4667
|
-
}
|
|
4668
|
-
function parseQuestionAnswer(value) {
|
|
4669
|
-
if (Array.isArray(value)) {
|
|
4670
|
-
return value.map((entry) => typeof entry === "string" ? entry.trim() : String(entry).trim()).filter(Boolean);
|
|
4671
|
-
}
|
|
4672
|
-
if (typeof value === "string") {
|
|
4673
|
-
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
4674
|
-
}
|
|
4675
|
-
if (value == null) {
|
|
4676
|
-
return [];
|
|
4677
|
-
}
|
|
4678
|
-
return [String(value)];
|
|
4679
|
-
}
|
|
4680
|
-
function isClaudeSessionGlobalEvent(event) {
|
|
4681
|
-
return event.type === "system" && event.subtype === "init";
|
|
4682
|
-
}
|
|
4683
|
-
function stringifyToolResultContent(value) {
|
|
4684
|
-
if (typeof value === "string") {
|
|
4685
|
-
return value;
|
|
4686
|
-
}
|
|
4687
|
-
if (Array.isArray(value)) {
|
|
4688
|
-
return value.map((entry) => stringifyToolResultContent(entry)).filter(Boolean).join(`
|
|
4689
|
-
`);
|
|
4690
|
-
}
|
|
4691
|
-
if (value == null) {
|
|
4692
|
-
return "";
|
|
4693
|
-
}
|
|
4694
|
-
try {
|
|
4695
|
-
return JSON.stringify(value);
|
|
4696
|
-
} catch {
|
|
4697
|
-
return String(value);
|
|
4698
|
-
}
|
|
4699
|
-
}
|
|
4700
|
-
function buildClaudeAction(toolName, toolUseId, input) {
|
|
4701
|
-
if (toolName === "Edit" || toolName === "Write" || toolName === "MultiEdit") {
|
|
4702
|
-
return {
|
|
4703
|
-
kind: "file_change",
|
|
4704
|
-
path: typeof input.file_path === "string" ? input.file_path : typeof input.path === "string" ? input.path : "",
|
|
4705
|
-
diff: "",
|
|
4706
|
-
status: "running",
|
|
4707
|
-
output: ""
|
|
4708
|
-
};
|
|
4709
|
-
}
|
|
4710
|
-
if (toolName === "Bash") {
|
|
4711
|
-
return {
|
|
4712
|
-
kind: "command",
|
|
4713
|
-
command: typeof input.command === "string" ? input.command : "",
|
|
4714
|
-
status: "running",
|
|
4715
|
-
output: ""
|
|
4716
|
-
};
|
|
4717
|
-
}
|
|
4718
|
-
if (toolName === "Agent") {
|
|
4719
|
-
return {
|
|
4720
|
-
kind: "subagent",
|
|
4721
|
-
agentId: toolUseId,
|
|
4722
|
-
agentName: typeof input.description === "string" ? input.description : undefined,
|
|
4723
|
-
prompt: typeof input.prompt === "string" ? input.prompt : undefined,
|
|
4724
|
-
status: "running",
|
|
4725
|
-
output: ""
|
|
4726
|
-
};
|
|
4727
|
-
}
|
|
4728
|
-
return {
|
|
4729
|
-
kind: "tool_call",
|
|
4730
|
-
toolName,
|
|
4731
|
-
toolCallId: toolUseId,
|
|
4732
|
-
input,
|
|
4733
|
-
status: "running",
|
|
4734
|
-
output: ""
|
|
4735
|
-
};
|
|
4736
|
-
}
|
|
4737
|
-
function buildClaudeStreamJsonSessionSnapshot(raw, options, targetClaudeSessionId) {
|
|
4738
|
-
const lines = raw.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
4739
|
-
let resolvedSessionId = targetClaudeSessionId?.trim() || null;
|
|
4740
|
-
if (!resolvedSessionId) {
|
|
4741
|
-
for (const line of lines) {
|
|
4742
|
-
try {
|
|
4743
|
-
const event = JSON.parse(line);
|
|
4744
|
-
const nextSessionId = typeof event.session_id === "string" ? event.session_id : typeof event.sessionId === "string" ? event.sessionId : null;
|
|
4745
|
-
if (event.type === "system" && event.subtype === "init" && nextSessionId) {
|
|
4746
|
-
resolvedSessionId = nextSessionId;
|
|
4747
|
-
} else if (!resolvedSessionId && nextSessionId) {
|
|
4748
|
-
resolvedSessionId = nextSessionId;
|
|
4749
|
-
}
|
|
4750
|
-
} catch {}
|
|
4751
|
-
}
|
|
4752
|
-
}
|
|
4753
|
-
const snapshot = {
|
|
4754
|
-
session: {
|
|
4755
|
-
id: options.sessionId,
|
|
4756
|
-
name: options.agentName,
|
|
4757
|
-
adapterType: "claude_stream_json",
|
|
4758
|
-
status: "idle",
|
|
4759
|
-
cwd: options.cwd,
|
|
4760
|
-
providerMeta: resolvedSessionId ? { transportSessionId: resolvedSessionId } : undefined
|
|
4761
|
-
},
|
|
4762
|
-
turns: []
|
|
4763
|
-
};
|
|
4764
|
-
let currentTurn = null;
|
|
4765
|
-
const blockById = new Map;
|
|
4766
|
-
let activeContentBlocks = new Map;
|
|
4767
|
-
let pendingToolBlocks = new Map;
|
|
4768
|
-
const startTurn = () => {
|
|
4769
|
-
const turn = {
|
|
4770
|
-
id: `${options.sessionId}:turn:${snapshot.turns.length + 1}`,
|
|
4771
|
-
status: "streaming",
|
|
4772
|
-
blocks: [],
|
|
4773
|
-
startedAt: Date.now(),
|
|
4774
|
-
nextBlockIndex: 0,
|
|
4775
|
-
nextMessageIndex: 0
|
|
4776
|
-
};
|
|
4777
|
-
snapshot.turns.push(turn);
|
|
4778
|
-
snapshot.currentTurnId = turn.id;
|
|
4779
|
-
currentTurn = turn;
|
|
4780
|
-
activeContentBlocks = new Map;
|
|
4781
|
-
pendingToolBlocks = new Map;
|
|
4782
|
-
snapshot.session.status = "active";
|
|
4783
|
-
return turn;
|
|
4784
|
-
};
|
|
4785
|
-
const ensureTurn = () => currentTurn ?? startTurn();
|
|
4786
|
-
const startTextualBlock = (type, index, initialText = "") => {
|
|
4787
|
-
const turn = ensureTurn();
|
|
4788
|
-
const blockId = `${turn.id}:m${turn.nextMessageIndex}:i${index}`;
|
|
4789
|
-
const block = type === "text" ? {
|
|
4790
|
-
id: blockId,
|
|
4791
|
-
turnId: turn.id,
|
|
4792
|
-
index: turn.nextBlockIndex++,
|
|
4793
|
-
type: "text",
|
|
4794
|
-
text: initialText,
|
|
4795
|
-
status: "streaming"
|
|
4796
|
-
} : {
|
|
4797
|
-
id: blockId,
|
|
4798
|
-
turnId: turn.id,
|
|
4799
|
-
index: turn.nextBlockIndex++,
|
|
4800
|
-
type: "reasoning",
|
|
4801
|
-
text: initialText,
|
|
4802
|
-
status: "streaming"
|
|
4803
|
-
};
|
|
4804
|
-
const blockState = {
|
|
4805
|
-
block,
|
|
4806
|
-
status: "streaming"
|
|
4807
|
-
};
|
|
4808
|
-
turn.blocks.push(blockState);
|
|
4809
|
-
blockById.set(blockId, blockState);
|
|
4810
|
-
activeContentBlocks.set(index, blockState);
|
|
4811
|
-
return blockState;
|
|
4812
|
-
};
|
|
4813
|
-
const finalizeCurrentTurn = (status) => {
|
|
4814
|
-
if (!currentTurn) {
|
|
4815
|
-
return;
|
|
4816
|
-
}
|
|
4817
|
-
for (const blockState of activeContentBlocks.values()) {
|
|
4818
|
-
updateBlockCompletion(blockState, true);
|
|
4819
|
-
}
|
|
4820
|
-
activeContentBlocks.clear();
|
|
4821
|
-
currentTurn.status = status;
|
|
4822
|
-
currentTurn.endedAt = Date.now();
|
|
4823
|
-
currentTurn = null;
|
|
4824
|
-
snapshot.currentTurnId = undefined;
|
|
4825
|
-
snapshot.session.status = status === "error" ? "error" : "idle";
|
|
4826
|
-
};
|
|
4827
|
-
for (const line of lines) {
|
|
4828
|
-
let event;
|
|
4829
|
-
try {
|
|
4830
|
-
event = JSON.parse(line);
|
|
4831
|
-
} catch {
|
|
4832
|
-
continue;
|
|
4833
|
-
}
|
|
4834
|
-
const eventSessionId = typeof event.session_id === "string" ? event.session_id : typeof event.sessionId === "string" ? event.sessionId : null;
|
|
4835
|
-
if (resolvedSessionId) {
|
|
4836
|
-
if (eventSessionId && eventSessionId !== resolvedSessionId) {
|
|
4837
|
-
continue;
|
|
4838
|
-
}
|
|
4839
|
-
if (!eventSessionId && !isClaudeSessionGlobalEvent(event)) {
|
|
4840
|
-
continue;
|
|
4841
|
-
}
|
|
4842
|
-
}
|
|
4843
|
-
if (event.type === "system" && event.subtype === "init") {
|
|
4844
|
-
if (typeof event.model === "string" && event.model.trim()) {
|
|
4845
|
-
snapshot.session.model = event.model;
|
|
4846
|
-
}
|
|
4847
|
-
if (typeof event.cwd === "string" && event.cwd.trim()) {
|
|
4848
|
-
snapshot.session.cwd = event.cwd;
|
|
4849
|
-
}
|
|
4850
|
-
snapshot.session.status = currentTurn ? "active" : "idle";
|
|
4851
|
-
continue;
|
|
4852
|
-
}
|
|
4853
|
-
if (event.type === "stream_event") {
|
|
4854
|
-
const streamEvent = event.event;
|
|
4855
|
-
const streamEventType = typeof streamEvent?.type === "string" ? streamEvent.type : "";
|
|
4856
|
-
if (streamEventType === "message_start") {
|
|
4857
|
-
const turn = ensureTurn();
|
|
4858
|
-
turn.nextMessageIndex += 1;
|
|
4859
|
-
activeContentBlocks.clear();
|
|
4860
|
-
pendingToolBlocks.clear();
|
|
4861
|
-
snapshot.session.status = "active";
|
|
4862
|
-
continue;
|
|
4863
|
-
}
|
|
4864
|
-
if (streamEventType === "content_block_start") {
|
|
4865
|
-
const turn = ensureTurn();
|
|
4866
|
-
const blockIndex = typeof streamEvent?.index === "number" ? streamEvent.index : 0;
|
|
4867
|
-
const contentBlock = streamEvent?.content_block;
|
|
4868
|
-
const contentType = typeof contentBlock?.type === "string" ? contentBlock.type : "";
|
|
4869
|
-
if (contentType === "thinking") {
|
|
4870
|
-
startTextualBlock("reasoning", blockIndex, typeof contentBlock?.thinking === "string" ? contentBlock.thinking : "");
|
|
4871
|
-
} else if (contentType === "text") {
|
|
4872
|
-
startTextualBlock("text", blockIndex, typeof contentBlock?.text === "string" ? contentBlock.text : "");
|
|
4873
|
-
} else if (contentType === "tool_use") {
|
|
4874
|
-
pendingToolBlocks.set(blockIndex, {
|
|
4875
|
-
toolUseId: typeof contentBlock?.id === "string" ? contentBlock.id : `${turn.id}:tool:${blockIndex}`,
|
|
4876
|
-
toolName: typeof contentBlock?.name === "string" ? contentBlock.name : "unknown",
|
|
4877
|
-
input: contentBlock?.input && typeof contentBlock.input === "object" && !Array.isArray(contentBlock.input) ? contentBlock.input : {},
|
|
4878
|
-
inputJson: "",
|
|
4879
|
-
blockIndex: turn.nextBlockIndex++
|
|
4880
|
-
});
|
|
4881
|
-
}
|
|
4882
|
-
continue;
|
|
4883
|
-
}
|
|
4884
|
-
if (streamEventType === "content_block_delta") {
|
|
4885
|
-
const blockIndex = typeof streamEvent?.index === "number" ? streamEvent.index : 0;
|
|
4886
|
-
const delta = streamEvent?.delta;
|
|
4887
|
-
const deltaType = typeof delta?.type === "string" ? delta.type : "";
|
|
4888
|
-
if (deltaType === "text_delta") {
|
|
4889
|
-
const blockState = activeContentBlocks.get(blockIndex);
|
|
4890
|
-
if (blockState?.block.type === "text" && typeof delta?.text === "string") {
|
|
4891
|
-
blockState.block.text += delta.text;
|
|
4892
|
-
}
|
|
4893
|
-
continue;
|
|
4894
|
-
}
|
|
4895
|
-
if (deltaType === "thinking_delta") {
|
|
4896
|
-
const blockState = activeContentBlocks.get(blockIndex);
|
|
4897
|
-
if (blockState?.block.type === "reasoning" && typeof delta?.thinking === "string") {
|
|
4898
|
-
blockState.block.text += delta.thinking;
|
|
4899
|
-
}
|
|
4900
|
-
continue;
|
|
4901
|
-
}
|
|
4902
|
-
if (deltaType === "input_json_delta") {
|
|
4903
|
-
const pending = pendingToolBlocks.get(blockIndex);
|
|
4904
|
-
if (pending && typeof delta?.partial_json === "string") {
|
|
4905
|
-
pending.inputJson += delta.partial_json;
|
|
4906
|
-
}
|
|
4907
|
-
}
|
|
4908
|
-
continue;
|
|
4909
|
-
}
|
|
4910
|
-
if (streamEventType === "content_block_stop") {
|
|
4911
|
-
const blockIndex = typeof streamEvent?.index === "number" ? streamEvent.index : 0;
|
|
4912
|
-
const blockState = activeContentBlocks.get(blockIndex);
|
|
4913
|
-
if (blockState) {
|
|
4914
|
-
updateBlockCompletion(blockState, true);
|
|
4915
|
-
activeContentBlocks.delete(blockIndex);
|
|
4916
|
-
continue;
|
|
4917
|
-
}
|
|
4918
|
-
const pendingTool = pendingToolBlocks.get(blockIndex);
|
|
4919
|
-
if (!pendingTool) {
|
|
4920
|
-
continue;
|
|
4921
|
-
}
|
|
4922
|
-
const turn = ensureTurn();
|
|
4923
|
-
const parsedInput = {
|
|
4924
|
-
...pendingTool.input,
|
|
4925
|
-
...parseJsonObject(pendingTool.inputJson)
|
|
4926
|
-
};
|
|
4927
|
-
if (pendingTool.toolName === "AskUserQuestion") {
|
|
4928
|
-
const questions = Array.isArray(parsedInput.questions) ? parsedInput.questions : [];
|
|
4929
|
-
const firstQuestion = questions[0] ?? {};
|
|
4930
|
-
const block = {
|
|
4931
|
-
id: pendingTool.toolUseId,
|
|
4932
|
-
turnId: turn.id,
|
|
4933
|
-
index: pendingTool.blockIndex,
|
|
4934
|
-
type: "question",
|
|
4935
|
-
header: typeof firstQuestion.header === "string" ? firstQuestion.header : undefined,
|
|
4936
|
-
question: typeof firstQuestion.question === "string" ? firstQuestion.question : "",
|
|
4937
|
-
options: Array.isArray(firstQuestion.options) ? firstQuestion.options.map((option) => {
|
|
4938
|
-
if (typeof option === "string") {
|
|
4939
|
-
return { label: option };
|
|
4940
|
-
}
|
|
4941
|
-
const optionRecord = option;
|
|
4942
|
-
return {
|
|
4943
|
-
label: typeof optionRecord.label === "string" ? optionRecord.label : String(option),
|
|
4944
|
-
description: typeof optionRecord.description === "string" ? optionRecord.description : undefined
|
|
4945
|
-
};
|
|
4946
|
-
}) : [],
|
|
4947
|
-
multiSelect: Boolean(firstQuestion.multiSelect),
|
|
4948
|
-
questionStatus: "awaiting_answer",
|
|
4949
|
-
status: "streaming"
|
|
4950
|
-
};
|
|
4951
|
-
const nextBlockState = { block, status: "streaming" };
|
|
4952
|
-
turn.blocks.push(nextBlockState);
|
|
4953
|
-
blockById.set(block.id, nextBlockState);
|
|
4954
|
-
} else {
|
|
4955
|
-
const block = {
|
|
4956
|
-
id: pendingTool.toolUseId,
|
|
4957
|
-
turnId: turn.id,
|
|
4958
|
-
index: pendingTool.blockIndex,
|
|
4959
|
-
type: "action",
|
|
4960
|
-
action: buildClaudeAction(pendingTool.toolName, pendingTool.toolUseId, parsedInput),
|
|
4961
|
-
status: "streaming"
|
|
4962
|
-
};
|
|
4963
|
-
const nextBlockState = { block, status: "streaming" };
|
|
4964
|
-
turn.blocks.push(nextBlockState);
|
|
4965
|
-
blockById.set(block.id, nextBlockState);
|
|
4966
|
-
}
|
|
4967
|
-
pendingToolBlocks.delete(blockIndex);
|
|
4968
|
-
}
|
|
4969
|
-
continue;
|
|
4970
|
-
}
|
|
4971
|
-
if (event.type === "user") {
|
|
4972
|
-
const message = event.message;
|
|
4973
|
-
const content = Array.isArray(message?.content) ? message.content : [];
|
|
4974
|
-
for (const entry of content) {
|
|
4975
|
-
const result = entry;
|
|
4976
|
-
if (result.type !== "tool_result" || typeof result.tool_use_id !== "string") {
|
|
4977
|
-
continue;
|
|
4978
|
-
}
|
|
4979
|
-
const blockState = blockById.get(result.tool_use_id);
|
|
4980
|
-
if (!blockState) {
|
|
4981
|
-
continue;
|
|
4982
|
-
}
|
|
4983
|
-
if (blockState.block.type === "question") {
|
|
4984
|
-
const questionBlock = blockState.block;
|
|
4985
|
-
questionBlock.questionStatus = result.is_error ? "denied" : "answered";
|
|
4986
|
-
const answer = parseQuestionAnswer(result.content);
|
|
4987
|
-
questionBlock.answer = answer.length > 0 ? answer : undefined;
|
|
4988
|
-
updateBlockCompletion(blockState, true);
|
|
4989
|
-
continue;
|
|
4990
|
-
}
|
|
4991
|
-
appendActionOutput(blockState, stringifyToolResultContent(result.content));
|
|
4992
|
-
if (blockState.block.type === "action") {
|
|
4993
|
-
blockState.block.action.status = result.is_error ? "failed" : "completed";
|
|
4994
|
-
}
|
|
4995
|
-
updateBlockCompletion(blockState, true);
|
|
4996
|
-
}
|
|
4997
|
-
continue;
|
|
4998
|
-
}
|
|
4999
|
-
if (event.type === "result") {
|
|
5000
|
-
const permissionDenials = Array.isArray(event.permission_denials) ? event.permission_denials : [];
|
|
5001
|
-
for (const denial of permissionDenials) {
|
|
5002
|
-
if (denial.tool_name !== "AskUserQuestion") {
|
|
5003
|
-
continue;
|
|
5004
|
-
}
|
|
5005
|
-
const toolUseId = typeof denial.tool_use_id === "string" ? denial.tool_use_id : null;
|
|
5006
|
-
const blockState = toolUseId ? blockById.get(toolUseId) : undefined;
|
|
5007
|
-
if (blockState?.block.type === "question") {
|
|
5008
|
-
blockState.block.questionStatus = "denied";
|
|
5009
|
-
updateBlockCompletion(blockState, true);
|
|
5010
|
-
continue;
|
|
5011
|
-
}
|
|
5012
|
-
const input = denial.tool_input && typeof denial.tool_input === "object" && !Array.isArray(denial.tool_input) ? denial.tool_input : {};
|
|
5013
|
-
const questions = Array.isArray(input.questions) ? input.questions : [];
|
|
5014
|
-
const firstQuestion = questions[0] ?? {};
|
|
5015
|
-
const turn = ensureTurn();
|
|
5016
|
-
const block = {
|
|
5017
|
-
id: toolUseId ?? `${turn.id}:denied:${turn.nextBlockIndex}`,
|
|
5018
|
-
turnId: turn.id,
|
|
5019
|
-
index: turn.nextBlockIndex++,
|
|
5020
|
-
type: "question",
|
|
5021
|
-
header: typeof firstQuestion.header === "string" ? firstQuestion.header : undefined,
|
|
5022
|
-
question: typeof firstQuestion.question === "string" ? firstQuestion.question : "",
|
|
5023
|
-
options: Array.isArray(firstQuestion.options) ? firstQuestion.options.map((option) => {
|
|
5024
|
-
if (typeof option === "string") {
|
|
5025
|
-
return { label: option };
|
|
5026
|
-
}
|
|
5027
|
-
const optionRecord = option;
|
|
5028
|
-
return {
|
|
5029
|
-
label: typeof optionRecord.label === "string" ? optionRecord.label : String(option),
|
|
5030
|
-
description: typeof optionRecord.description === "string" ? optionRecord.description : undefined
|
|
5031
|
-
};
|
|
5032
|
-
}) : [],
|
|
5033
|
-
multiSelect: Boolean(firstQuestion.multiSelect),
|
|
5034
|
-
questionStatus: "denied",
|
|
5035
|
-
status: "completed"
|
|
5036
|
-
};
|
|
5037
|
-
const deniedBlock = { block, status: "completed" };
|
|
5038
|
-
turn.blocks.push(deniedBlock);
|
|
5039
|
-
blockById.set(block.id, deniedBlock);
|
|
5040
|
-
}
|
|
5041
|
-
finalizeCurrentTurn(event.is_error ? "error" : "completed");
|
|
5042
|
-
continue;
|
|
5043
|
-
}
|
|
5044
|
-
if (event.type === "error") {
|
|
5045
|
-
finalizeCurrentTurn("error");
|
|
5046
|
-
}
|
|
5047
|
-
}
|
|
5048
|
-
if (!resolvedSessionId && snapshot.turns.length === 0) {
|
|
5049
|
-
return null;
|
|
5050
|
-
}
|
|
5051
|
-
snapshot.session.status = currentTurn ? "active" : snapshot.session.status;
|
|
5052
|
-
return snapshot;
|
|
5053
|
-
}
|
|
5054
4557
|
|
|
5055
4558
|
class ClaudeStreamJsonSession {
|
|
5056
4559
|
options;
|
|
@@ -5333,35 +4836,10 @@ async function ensureClaudeStreamJsonAgentOnline(options) {
|
|
|
5333
4836
|
session.update(options);
|
|
5334
4837
|
return session.ensureOnline();
|
|
5335
4838
|
}
|
|
5336
|
-
async function invokeClaudeStreamJsonAgent(options) {
|
|
5337
|
-
const session = getOrCreateSession(options);
|
|
5338
|
-
session.update(options);
|
|
5339
|
-
return session.invoke(options.prompt, options.timeoutMs);
|
|
5340
|
-
}
|
|
5341
4839
|
function isClaudeStreamJsonAgentAlive(options) {
|
|
5342
4840
|
const session = sessions.get(sessionKey(options));
|
|
5343
4841
|
return Boolean(session?.isAlive());
|
|
5344
4842
|
}
|
|
5345
|
-
async function answerClaudeStreamJsonQuestion(options, input) {
|
|
5346
|
-
const session = sessions.get(sessionKey(options));
|
|
5347
|
-
if (!session) {
|
|
5348
|
-
throw new Error(`Claude stream-json session for ${options.agentName} is not running.`);
|
|
5349
|
-
}
|
|
5350
|
-
session.update(options);
|
|
5351
|
-
await session.answerQuestion(input.blockId, input.answer);
|
|
5352
|
-
}
|
|
5353
|
-
async function getClaudeStreamJsonAgentSnapshot(options) {
|
|
5354
|
-
const stdoutLogPath = join5(options.logsDirectory, "stdout.log");
|
|
5355
|
-
const sessionStatePath = join5(options.runtimeDirectory, "claude-session-id.txt");
|
|
5356
|
-
const [rawLog, persistedSessionId] = await Promise.all([
|
|
5357
|
-
readOptionalFile(stdoutLogPath),
|
|
5358
|
-
readOptionalFile(sessionStatePath)
|
|
5359
|
-
]);
|
|
5360
|
-
if (!rawLog) {
|
|
5361
|
-
return null;
|
|
5362
|
-
}
|
|
5363
|
-
return buildClaudeStreamJsonSessionSnapshot(rawLog, options, persistedSessionId);
|
|
5364
|
-
}
|
|
5365
4843
|
async function shutdownClaudeStreamJsonAgent(options, shutdownOptions = {}) {
|
|
5366
4844
|
const key = sessionKey(options);
|
|
5367
4845
|
const session = sessions.get(key);
|
|
@@ -5383,11 +4861,6 @@ var init_claude_stream_json = __esm(() => {
|
|
|
5383
4861
|
import { spawn as spawn2 } from "child_process";
|
|
5384
4862
|
import { access as access2, appendFile as appendFile2, constants, mkdir as mkdir4, readFile as readFile5, rm as rm3, writeFile as writeFile4 } from "fs/promises";
|
|
5385
4863
|
import { delimiter, join as join6 } from "path";
|
|
5386
|
-
function isCodexThreadGlobalMessage(message) {
|
|
5387
|
-
const result = message.result;
|
|
5388
|
-
const thread = result?.thread;
|
|
5389
|
-
return typeof thread?.id === "string";
|
|
5390
|
-
}
|
|
5391
4864
|
function sessionKey2(options) {
|
|
5392
4865
|
return `${options.agentName}:${options.sessionId}`;
|
|
5393
4866
|
}
|
|
@@ -5454,14 +4927,6 @@ function parseJsonLine(line) {
|
|
|
5454
4927
|
return null;
|
|
5455
4928
|
}
|
|
5456
4929
|
}
|
|
5457
|
-
function parseJsonRecord(line) {
|
|
5458
|
-
try {
|
|
5459
|
-
const value = JSON.parse(line);
|
|
5460
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
5461
|
-
} catch {
|
|
5462
|
-
return null;
|
|
5463
|
-
}
|
|
5464
|
-
}
|
|
5465
4930
|
function errorMessage2(error) {
|
|
5466
4931
|
if (error instanceof Error) {
|
|
5467
4932
|
return error.message;
|
|
@@ -5500,687 +4965,6 @@ async function readOptionalFile2(filePath) {
|
|
|
5500
4965
|
return null;
|
|
5501
4966
|
}
|
|
5502
4967
|
}
|
|
5503
|
-
async function readOptionalJsonRecord(filePath) {
|
|
5504
|
-
const raw = await readOptionalFile2(filePath);
|
|
5505
|
-
return raw ? parseJsonRecord(raw) : null;
|
|
5506
|
-
}
|
|
5507
|
-
function codexThreadStatusToSessionStatus(status) {
|
|
5508
|
-
switch (status) {
|
|
5509
|
-
case "active":
|
|
5510
|
-
return "active";
|
|
5511
|
-
case "idle":
|
|
5512
|
-
return "idle";
|
|
5513
|
-
case "error":
|
|
5514
|
-
return "error";
|
|
5515
|
-
default:
|
|
5516
|
-
return "connecting";
|
|
5517
|
-
}
|
|
5518
|
-
}
|
|
5519
|
-
function codexTurnStatusToTurnStatus(status) {
|
|
5520
|
-
switch (status) {
|
|
5521
|
-
case "completed":
|
|
5522
|
-
return "completed";
|
|
5523
|
-
case "interrupted":
|
|
5524
|
-
return "interrupted";
|
|
5525
|
-
case "failed":
|
|
5526
|
-
return "error";
|
|
5527
|
-
default:
|
|
5528
|
-
return "streaming";
|
|
5529
|
-
}
|
|
5530
|
-
}
|
|
5531
|
-
function stringifyCodexItem(value) {
|
|
5532
|
-
if (typeof value === "string") {
|
|
5533
|
-
return value;
|
|
5534
|
-
}
|
|
5535
|
-
if (value == null) {
|
|
5536
|
-
return "";
|
|
5537
|
-
}
|
|
5538
|
-
try {
|
|
5539
|
-
return JSON.stringify(value);
|
|
5540
|
-
} catch {
|
|
5541
|
-
return String(value);
|
|
5542
|
-
}
|
|
5543
|
-
}
|
|
5544
|
-
function parseCodexTimestamp(value) {
|
|
5545
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
5546
|
-
return value > 1000000000000 ? value : value * 1000;
|
|
5547
|
-
}
|
|
5548
|
-
if (typeof value === "string") {
|
|
5549
|
-
const parsed = Date.parse(value);
|
|
5550
|
-
if (Number.isFinite(parsed)) {
|
|
5551
|
-
return parsed;
|
|
5552
|
-
}
|
|
5553
|
-
}
|
|
5554
|
-
return;
|
|
5555
|
-
}
|
|
5556
|
-
function parseCodexMaybeJson(value) {
|
|
5557
|
-
if (typeof value !== "string") {
|
|
5558
|
-
return value;
|
|
5559
|
-
}
|
|
5560
|
-
const trimmed = value.trim();
|
|
5561
|
-
if (!trimmed) {
|
|
5562
|
-
return value;
|
|
5563
|
-
}
|
|
5564
|
-
try {
|
|
5565
|
-
return JSON.parse(trimmed);
|
|
5566
|
-
} catch {
|
|
5567
|
-
return value;
|
|
5568
|
-
}
|
|
5569
|
-
}
|
|
5570
|
-
function extractCodexReasoningText(item) {
|
|
5571
|
-
const summary = Array.isArray(item.summary) ? item.summary : [];
|
|
5572
|
-
const content = Array.isArray(item.content) ? item.content : [];
|
|
5573
|
-
const summaryText = summary.map((entry) => {
|
|
5574
|
-
if (typeof entry === "string") {
|
|
5575
|
-
return entry;
|
|
5576
|
-
}
|
|
5577
|
-
const record = entry;
|
|
5578
|
-
if (typeof record.text === "string") {
|
|
5579
|
-
return record.text;
|
|
5580
|
-
}
|
|
5581
|
-
if (typeof record.summary === "string") {
|
|
5582
|
-
return record.summary;
|
|
5583
|
-
}
|
|
5584
|
-
return "";
|
|
5585
|
-
}).filter(Boolean).join(`
|
|
5586
|
-
`);
|
|
5587
|
-
const contentText = content.map((entry) => {
|
|
5588
|
-
if (typeof entry === "string") {
|
|
5589
|
-
return entry;
|
|
5590
|
-
}
|
|
5591
|
-
const record = entry;
|
|
5592
|
-
return typeof record.text === "string" ? record.text : "";
|
|
5593
|
-
}).filter(Boolean).join(`
|
|
5594
|
-
`);
|
|
5595
|
-
return [summaryText, contentText].filter(Boolean).join(`
|
|
5596
|
-
|
|
5597
|
-
`).trim();
|
|
5598
|
-
}
|
|
5599
|
-
function extractCodexMessageText(item) {
|
|
5600
|
-
const content = Array.isArray(item.content) ? item.content : [];
|
|
5601
|
-
return content.map((entry) => {
|
|
5602
|
-
if (typeof entry === "string") {
|
|
5603
|
-
return entry;
|
|
5604
|
-
}
|
|
5605
|
-
const record = entry;
|
|
5606
|
-
return typeof record.text === "string" ? record.text : "";
|
|
5607
|
-
}).filter(Boolean).join(`
|
|
5608
|
-
|
|
5609
|
-
`).trim();
|
|
5610
|
-
}
|
|
5611
|
-
function extractCodexUserMessageText(item) {
|
|
5612
|
-
const text = extractCodexMessageText(item);
|
|
5613
|
-
if (text) {
|
|
5614
|
-
return text;
|
|
5615
|
-
}
|
|
5616
|
-
return typeof item.text === "string" ? item.text.trim() : "";
|
|
5617
|
-
}
|
|
5618
|
-
function renderCodexActionOutput(item) {
|
|
5619
|
-
if (typeof item.text === "string" && item.text.trim()) {
|
|
5620
|
-
return item.text;
|
|
5621
|
-
}
|
|
5622
|
-
if (item.action !== undefined) {
|
|
5623
|
-
return stringifyCodexItem(item.action);
|
|
5624
|
-
}
|
|
5625
|
-
return stringifyCodexItem(item);
|
|
5626
|
-
}
|
|
5627
|
-
function buildCodexActionBlock(item, turnId, index) {
|
|
5628
|
-
return {
|
|
5629
|
-
id: typeof item.id === "string" ? item.id : `${turnId}:action:${index}`,
|
|
5630
|
-
turnId,
|
|
5631
|
-
index,
|
|
5632
|
-
type: "action",
|
|
5633
|
-
status: "streaming",
|
|
5634
|
-
action: {
|
|
5635
|
-
kind: "tool_call",
|
|
5636
|
-
toolName: typeof item.type === "string" ? item.type : "unknown",
|
|
5637
|
-
toolCallId: typeof item.id === "string" ? item.id : `${turnId}:action:${index}`,
|
|
5638
|
-
input: item,
|
|
5639
|
-
output: "",
|
|
5640
|
-
status: "running"
|
|
5641
|
-
}
|
|
5642
|
-
};
|
|
5643
|
-
}
|
|
5644
|
-
function buildCodexRolloutActionBlock(item, turnId, index) {
|
|
5645
|
-
const itemType = typeof item.type === "string" ? item.type : "tool_call";
|
|
5646
|
-
const toolCallId = typeof item.call_id === "string" ? item.call_id : `${turnId}:action:${index}`;
|
|
5647
|
-
const toolName = typeof item.name === "string" ? item.name : itemType === "web_search_call" ? "web_search" : itemType;
|
|
5648
|
-
const input = itemType === "function_call" ? parseCodexMaybeJson(item.arguments) : itemType === "custom_tool_call" ? item.input : item;
|
|
5649
|
-
return {
|
|
5650
|
-
id: toolCallId,
|
|
5651
|
-
turnId,
|
|
5652
|
-
index,
|
|
5653
|
-
type: "action",
|
|
5654
|
-
status: "streaming",
|
|
5655
|
-
action: {
|
|
5656
|
-
kind: "tool_call",
|
|
5657
|
-
toolName,
|
|
5658
|
-
toolCallId,
|
|
5659
|
-
input,
|
|
5660
|
-
output: "",
|
|
5661
|
-
status: "running"
|
|
5662
|
-
}
|
|
5663
|
-
};
|
|
5664
|
-
}
|
|
5665
|
-
function finalizeCodexTurnBlocks(turn, status) {
|
|
5666
|
-
for (const blockState of turn.blocks) {
|
|
5667
|
-
if (blockState.status === "completed") {
|
|
5668
|
-
continue;
|
|
5669
|
-
}
|
|
5670
|
-
blockState.status = "completed";
|
|
5671
|
-
blockState.block.status = "completed";
|
|
5672
|
-
if (blockState.block.type === "action") {
|
|
5673
|
-
blockState.block.action.status = status === "completed" ? "completed" : "failed";
|
|
5674
|
-
}
|
|
5675
|
-
}
|
|
5676
|
-
}
|
|
5677
|
-
function setCodexProviderMeta(snapshot, threadId, threadPath) {
|
|
5678
|
-
if (!threadId && !threadPath) {
|
|
5679
|
-
return;
|
|
5680
|
-
}
|
|
5681
|
-
snapshot.session.providerMeta = {
|
|
5682
|
-
...snapshot.session.providerMeta ?? {},
|
|
5683
|
-
...threadId ? { threadId } : {},
|
|
5684
|
-
...threadPath ? { threadPath } : {}
|
|
5685
|
-
};
|
|
5686
|
-
}
|
|
5687
|
-
function buildCodexAppServerSessionSnapshot(raw, options, targetThreadId) {
|
|
5688
|
-
const lines = raw.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
5689
|
-
let resolvedThreadId = targetThreadId?.trim() || null;
|
|
5690
|
-
if (!resolvedThreadId) {
|
|
5691
|
-
for (const line of lines) {
|
|
5692
|
-
try {
|
|
5693
|
-
const message = JSON.parse(line);
|
|
5694
|
-
const resultThread = message.result?.thread;
|
|
5695
|
-
const paramsThread = message.params?.thread;
|
|
5696
|
-
const params = message.params;
|
|
5697
|
-
const nextThreadId = typeof resultThread?.id === "string" ? resultThread.id : typeof paramsThread?.id === "string" ? paramsThread.id : typeof params?.threadId === "string" ? params.threadId : null;
|
|
5698
|
-
if (nextThreadId) {
|
|
5699
|
-
resolvedThreadId = nextThreadId;
|
|
5700
|
-
}
|
|
5701
|
-
} catch {}
|
|
5702
|
-
}
|
|
5703
|
-
}
|
|
5704
|
-
const snapshot = {
|
|
5705
|
-
session: {
|
|
5706
|
-
id: options.sessionId,
|
|
5707
|
-
name: options.agentName,
|
|
5708
|
-
adapterType: "codex_app_server",
|
|
5709
|
-
status: resolvedThreadId ? "idle" : "connecting",
|
|
5710
|
-
cwd: options.cwd,
|
|
5711
|
-
providerMeta: resolvedThreadId ? { threadId: resolvedThreadId } : undefined
|
|
5712
|
-
},
|
|
5713
|
-
turns: []
|
|
5714
|
-
};
|
|
5715
|
-
const turnsById = new Map;
|
|
5716
|
-
const blocksById = new Map;
|
|
5717
|
-
const ensureTurn = (turnId) => {
|
|
5718
|
-
const existing = turnsById.get(turnId);
|
|
5719
|
-
if (existing) {
|
|
5720
|
-
return existing;
|
|
5721
|
-
}
|
|
5722
|
-
const turn = {
|
|
5723
|
-
id: turnId,
|
|
5724
|
-
status: "streaming",
|
|
5725
|
-
blocks: [],
|
|
5726
|
-
startedAt: Date.now(),
|
|
5727
|
-
nextBlockIndex: 0
|
|
5728
|
-
};
|
|
5729
|
-
turnsById.set(turnId, turn);
|
|
5730
|
-
snapshot.turns.push(turn);
|
|
5731
|
-
snapshot.currentTurnId = turnId;
|
|
5732
|
-
snapshot.session.status = "active";
|
|
5733
|
-
return turn;
|
|
5734
|
-
};
|
|
5735
|
-
const completeBlock = (blockState) => {
|
|
5736
|
-
if (!blockState) {
|
|
5737
|
-
return;
|
|
5738
|
-
}
|
|
5739
|
-
blockState.status = "completed";
|
|
5740
|
-
blockState.block.status = "completed";
|
|
5741
|
-
};
|
|
5742
|
-
for (const line of lines) {
|
|
5743
|
-
let message;
|
|
5744
|
-
try {
|
|
5745
|
-
message = JSON.parse(line);
|
|
5746
|
-
} catch {
|
|
5747
|
-
continue;
|
|
5748
|
-
}
|
|
5749
|
-
const params = message.params;
|
|
5750
|
-
const result = message.result;
|
|
5751
|
-
const paramsThread = params?.thread;
|
|
5752
|
-
const resultThread = result?.thread;
|
|
5753
|
-
const lineThreadId = typeof params?.threadId === "string" ? params.threadId : typeof paramsThread?.id === "string" ? paramsThread.id : typeof resultThread?.id === "string" ? resultThread.id : null;
|
|
5754
|
-
if (resolvedThreadId) {
|
|
5755
|
-
if (lineThreadId && lineThreadId !== resolvedThreadId) {
|
|
5756
|
-
continue;
|
|
5757
|
-
}
|
|
5758
|
-
if (!lineThreadId && !isCodexThreadGlobalMessage(message)) {
|
|
5759
|
-
continue;
|
|
5760
|
-
}
|
|
5761
|
-
}
|
|
5762
|
-
const resultModel = typeof result?.model === "string" ? result.model : null;
|
|
5763
|
-
if (resultThread && resultModel) {
|
|
5764
|
-
snapshot.session.model = resultModel;
|
|
5765
|
-
}
|
|
5766
|
-
if (typeof resultThread?.path === "string") {
|
|
5767
|
-
snapshot.session.providerMeta = {
|
|
5768
|
-
...snapshot.session.providerMeta ?? {},
|
|
5769
|
-
threadId: resolvedThreadId ?? resultThread.id,
|
|
5770
|
-
threadPath: resultThread.path
|
|
5771
|
-
};
|
|
5772
|
-
}
|
|
5773
|
-
if (typeof resultThread?.cwd === "string") {
|
|
5774
|
-
snapshot.session.cwd = resultThread.cwd;
|
|
5775
|
-
}
|
|
5776
|
-
if (message.method === "thread/started" || message.method === "thread/name/updated") {
|
|
5777
|
-
if (typeof paramsThread?.path === "string") {
|
|
5778
|
-
snapshot.session.providerMeta = {
|
|
5779
|
-
...snapshot.session.providerMeta ?? {},
|
|
5780
|
-
threadId: resolvedThreadId ?? paramsThread.id,
|
|
5781
|
-
threadPath: paramsThread.path
|
|
5782
|
-
};
|
|
5783
|
-
}
|
|
5784
|
-
if (typeof paramsThread?.cwd === "string") {
|
|
5785
|
-
snapshot.session.cwd = paramsThread.cwd;
|
|
5786
|
-
}
|
|
5787
|
-
if (typeof paramsThread?.name === "string" && paramsThread.name.trim()) {
|
|
5788
|
-
snapshot.session.name = paramsThread.name;
|
|
5789
|
-
}
|
|
5790
|
-
continue;
|
|
5791
|
-
}
|
|
5792
|
-
if (message.method === "thread/status/changed") {
|
|
5793
|
-
const status = params?.status?.type;
|
|
5794
|
-
snapshot.session.status = codexThreadStatusToSessionStatus(typeof status === "string" ? status : undefined);
|
|
5795
|
-
continue;
|
|
5796
|
-
}
|
|
5797
|
-
if (message.method === "turn/started") {
|
|
5798
|
-
const turn = params?.turn;
|
|
5799
|
-
if (typeof turn?.id === "string") {
|
|
5800
|
-
ensureTurn(turn.id);
|
|
5801
|
-
}
|
|
5802
|
-
continue;
|
|
5803
|
-
}
|
|
5804
|
-
if (message.method === "item/started") {
|
|
5805
|
-
const item = params?.item;
|
|
5806
|
-
const turnId = typeof params?.turnId === "string" ? params.turnId : null;
|
|
5807
|
-
const itemType = typeof item?.type === "string" ? item.type : "";
|
|
5808
|
-
const itemId = typeof item?.id === "string" ? item.id : null;
|
|
5809
|
-
if (!turnId || !item || !itemId || !itemType) {
|
|
5810
|
-
continue;
|
|
5811
|
-
}
|
|
5812
|
-
const turn = ensureTurn(turnId);
|
|
5813
|
-
if (itemType === "userMessage") {
|
|
5814
|
-
const block2 = {
|
|
5815
|
-
id: itemId,
|
|
5816
|
-
turnId,
|
|
5817
|
-
index: turn.nextBlockIndex++,
|
|
5818
|
-
type: "text",
|
|
5819
|
-
text: extractCodexUserMessageText(item),
|
|
5820
|
-
status: "streaming"
|
|
5821
|
-
};
|
|
5822
|
-
const blockState2 = { block: block2, status: "streaming" };
|
|
5823
|
-
turn.blocks.push(blockState2);
|
|
5824
|
-
blocksById.set(itemId, blockState2);
|
|
5825
|
-
continue;
|
|
5826
|
-
}
|
|
5827
|
-
if (itemType === "agentMessage") {
|
|
5828
|
-
const block2 = {
|
|
5829
|
-
id: itemId,
|
|
5830
|
-
turnId,
|
|
5831
|
-
index: turn.nextBlockIndex++,
|
|
5832
|
-
type: "text",
|
|
5833
|
-
text: typeof item.text === "string" ? item.text : "",
|
|
5834
|
-
status: "streaming"
|
|
5835
|
-
};
|
|
5836
|
-
const blockState2 = { block: block2, status: "streaming" };
|
|
5837
|
-
turn.blocks.push(blockState2);
|
|
5838
|
-
blocksById.set(itemId, blockState2);
|
|
5839
|
-
continue;
|
|
5840
|
-
}
|
|
5841
|
-
if (itemType === "reasoning") {
|
|
5842
|
-
const text = extractCodexReasoningText(item);
|
|
5843
|
-
if (!text) {
|
|
5844
|
-
continue;
|
|
5845
|
-
}
|
|
5846
|
-
const block2 = {
|
|
5847
|
-
id: itemId,
|
|
5848
|
-
turnId,
|
|
5849
|
-
index: turn.nextBlockIndex++,
|
|
5850
|
-
type: "reasoning",
|
|
5851
|
-
text,
|
|
5852
|
-
status: "streaming"
|
|
5853
|
-
};
|
|
5854
|
-
const blockState2 = { block: block2, status: "streaming" };
|
|
5855
|
-
turn.blocks.push(blockState2);
|
|
5856
|
-
blocksById.set(itemId, blockState2);
|
|
5857
|
-
continue;
|
|
5858
|
-
}
|
|
5859
|
-
const block = buildCodexActionBlock(item, turnId, turn.nextBlockIndex++);
|
|
5860
|
-
const blockState = { block, status: "streaming" };
|
|
5861
|
-
turn.blocks.push(blockState);
|
|
5862
|
-
blocksById.set(block.id, blockState);
|
|
5863
|
-
continue;
|
|
5864
|
-
}
|
|
5865
|
-
if (message.method === "item/agentMessage/delta") {
|
|
5866
|
-
const itemId = typeof params?.itemId === "string" ? params.itemId : null;
|
|
5867
|
-
const delta = typeof params?.delta === "string" ? params.delta : "";
|
|
5868
|
-
const blockState = itemId ? blocksById.get(itemId) : undefined;
|
|
5869
|
-
if (blockState?.block.type === "text") {
|
|
5870
|
-
blockState.block.text += delta;
|
|
5871
|
-
}
|
|
5872
|
-
continue;
|
|
5873
|
-
}
|
|
5874
|
-
if (message.method === "item/completed") {
|
|
5875
|
-
const item = params?.item;
|
|
5876
|
-
const turnId = typeof params?.turnId === "string" ? params.turnId : null;
|
|
5877
|
-
const itemType = typeof item?.type === "string" ? item.type : "";
|
|
5878
|
-
const itemId = typeof item?.id === "string" ? item.id : null;
|
|
5879
|
-
if (!turnId || !item || !itemId || !itemType) {
|
|
5880
|
-
continue;
|
|
5881
|
-
}
|
|
5882
|
-
if (itemType === "userMessage") {
|
|
5883
|
-
const turn2 = ensureTurn(turnId);
|
|
5884
|
-
let blockState2 = blocksById.get(itemId);
|
|
5885
|
-
if (!blockState2) {
|
|
5886
|
-
const block = {
|
|
5887
|
-
id: itemId,
|
|
5888
|
-
turnId,
|
|
5889
|
-
index: turn2.nextBlockIndex++,
|
|
5890
|
-
type: "text",
|
|
5891
|
-
text: "",
|
|
5892
|
-
status: "streaming"
|
|
5893
|
-
};
|
|
5894
|
-
blockState2 = { block, status: "streaming" };
|
|
5895
|
-
turn2.blocks.push(blockState2);
|
|
5896
|
-
blocksById.set(itemId, blockState2);
|
|
5897
|
-
}
|
|
5898
|
-
if (blockState2.block.type === "text") {
|
|
5899
|
-
blockState2.block.text = extractCodexUserMessageText(item);
|
|
5900
|
-
}
|
|
5901
|
-
completeBlock(blockState2);
|
|
5902
|
-
continue;
|
|
5903
|
-
}
|
|
5904
|
-
if (itemType === "agentMessage") {
|
|
5905
|
-
const turn2 = ensureTurn(turnId);
|
|
5906
|
-
let blockState2 = blocksById.get(itemId);
|
|
5907
|
-
if (!blockState2) {
|
|
5908
|
-
const block = {
|
|
5909
|
-
id: itemId,
|
|
5910
|
-
turnId,
|
|
5911
|
-
index: turn2.nextBlockIndex++,
|
|
5912
|
-
type: "text",
|
|
5913
|
-
text: "",
|
|
5914
|
-
status: "streaming"
|
|
5915
|
-
};
|
|
5916
|
-
blockState2 = { block, status: "streaming" };
|
|
5917
|
-
turn2.blocks.push(blockState2);
|
|
5918
|
-
blocksById.set(itemId, blockState2);
|
|
5919
|
-
}
|
|
5920
|
-
if (blockState2.block.type === "text" && typeof item.text === "string" && item.text.length > 0) {
|
|
5921
|
-
blockState2.block.text = item.text;
|
|
5922
|
-
}
|
|
5923
|
-
completeBlock(blockState2);
|
|
5924
|
-
continue;
|
|
5925
|
-
}
|
|
5926
|
-
if (itemType === "reasoning") {
|
|
5927
|
-
const text = extractCodexReasoningText(item);
|
|
5928
|
-
if (!text) {
|
|
5929
|
-
continue;
|
|
5930
|
-
}
|
|
5931
|
-
const turn2 = ensureTurn(turnId);
|
|
5932
|
-
let blockState2 = blocksById.get(itemId);
|
|
5933
|
-
if (!blockState2) {
|
|
5934
|
-
const block = {
|
|
5935
|
-
id: itemId,
|
|
5936
|
-
turnId,
|
|
5937
|
-
index: turn2.nextBlockIndex++,
|
|
5938
|
-
type: "reasoning",
|
|
5939
|
-
text,
|
|
5940
|
-
status: "streaming"
|
|
5941
|
-
};
|
|
5942
|
-
blockState2 = { block, status: "streaming" };
|
|
5943
|
-
turn2.blocks.push(blockState2);
|
|
5944
|
-
blocksById.set(itemId, blockState2);
|
|
5945
|
-
}
|
|
5946
|
-
if (blockState2.block.type === "reasoning" && text) {
|
|
5947
|
-
blockState2.block.text = text;
|
|
5948
|
-
}
|
|
5949
|
-
completeBlock(blockState2);
|
|
5950
|
-
continue;
|
|
5951
|
-
}
|
|
5952
|
-
const turn = ensureTurn(turnId);
|
|
5953
|
-
let blockState = blocksById.get(itemId);
|
|
5954
|
-
if (!blockState) {
|
|
5955
|
-
const block = buildCodexActionBlock(item, turnId, turn.nextBlockIndex++);
|
|
5956
|
-
blockState = { block, status: "streaming" };
|
|
5957
|
-
turn.blocks.push(blockState);
|
|
5958
|
-
blocksById.set(itemId, blockState);
|
|
5959
|
-
}
|
|
5960
|
-
if (blockState.block.type === "action") {
|
|
5961
|
-
blockState.block.action.output = renderCodexActionOutput(item);
|
|
5962
|
-
blockState.block.action.status = "completed";
|
|
5963
|
-
}
|
|
5964
|
-
completeBlock(blockState);
|
|
5965
|
-
continue;
|
|
5966
|
-
}
|
|
5967
|
-
if (message.method === "turn/completed") {
|
|
5968
|
-
const turn = params?.turn;
|
|
5969
|
-
if (!turn || typeof turn.id !== "string") {
|
|
5970
|
-
continue;
|
|
5971
|
-
}
|
|
5972
|
-
const turnState = ensureTurn(turn.id);
|
|
5973
|
-
turnState.status = codexTurnStatusToTurnStatus(typeof turn.status === "string" ? turn.status : undefined);
|
|
5974
|
-
turnState.endedAt = Date.now();
|
|
5975
|
-
if (snapshot.currentTurnId === turn.id) {
|
|
5976
|
-
snapshot.currentTurnId = undefined;
|
|
5977
|
-
}
|
|
5978
|
-
snapshot.session.status = turnState.status === "error" ? "error" : "idle";
|
|
5979
|
-
continue;
|
|
5980
|
-
}
|
|
5981
|
-
if (message.method === "error") {
|
|
5982
|
-
snapshot.session.status = "error";
|
|
5983
|
-
}
|
|
5984
|
-
}
|
|
5985
|
-
if (!resolvedThreadId && snapshot.turns.length === 0) {
|
|
5986
|
-
return null;
|
|
5987
|
-
}
|
|
5988
|
-
return snapshot;
|
|
5989
|
-
}
|
|
5990
|
-
function buildCodexRolloutSessionSnapshot(raw, options, targetThreadId, rolloutPath) {
|
|
5991
|
-
const lines = raw.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
5992
|
-
let resolvedThreadId = targetThreadId?.trim() || null;
|
|
5993
|
-
const snapshot = {
|
|
5994
|
-
session: {
|
|
5995
|
-
id: options.sessionId,
|
|
5996
|
-
name: options.agentName,
|
|
5997
|
-
adapterType: "codex_app_server",
|
|
5998
|
-
status: resolvedThreadId ? "idle" : "connecting",
|
|
5999
|
-
cwd: options.cwd
|
|
6000
|
-
},
|
|
6001
|
-
turns: []
|
|
6002
|
-
};
|
|
6003
|
-
setCodexProviderMeta(snapshot, resolvedThreadId, rolloutPath ?? null);
|
|
6004
|
-
const turnsById = new Map;
|
|
6005
|
-
const blocksByCallId = new Map;
|
|
6006
|
-
let currentTurnId = null;
|
|
6007
|
-
const ensureTurn = (turnId, startedAt) => {
|
|
6008
|
-
const existing = turnsById.get(turnId);
|
|
6009
|
-
if (existing) {
|
|
6010
|
-
if (startedAt && !existing.startedAt) {
|
|
6011
|
-
existing.startedAt = startedAt;
|
|
6012
|
-
}
|
|
6013
|
-
return existing;
|
|
6014
|
-
}
|
|
6015
|
-
const turn = {
|
|
6016
|
-
id: turnId,
|
|
6017
|
-
status: "streaming",
|
|
6018
|
-
blocks: [],
|
|
6019
|
-
startedAt: startedAt ?? Date.now(),
|
|
6020
|
-
nextBlockIndex: 0
|
|
6021
|
-
};
|
|
6022
|
-
turnsById.set(turnId, turn);
|
|
6023
|
-
snapshot.turns.push(turn);
|
|
6024
|
-
snapshot.currentTurnId = turnId;
|
|
6025
|
-
snapshot.session.status = "active";
|
|
6026
|
-
return turn;
|
|
6027
|
-
};
|
|
6028
|
-
for (const line of lines) {
|
|
6029
|
-
const message = parseJsonRecord(line);
|
|
6030
|
-
if (!message) {
|
|
6031
|
-
continue;
|
|
6032
|
-
}
|
|
6033
|
-
const timestamp = parseCodexTimestamp(message.timestamp) ?? Date.now();
|
|
6034
|
-
const entryType = typeof message.type === "string" ? message.type : "";
|
|
6035
|
-
const payload = message.payload && typeof message.payload === "object" && !Array.isArray(message.payload) ? message.payload : undefined;
|
|
6036
|
-
if (!payload) {
|
|
6037
|
-
continue;
|
|
6038
|
-
}
|
|
6039
|
-
if (entryType === "session_meta") {
|
|
6040
|
-
const sessionThreadId = typeof payload.id === "string" ? payload.id : null;
|
|
6041
|
-
if (sessionThreadId) {
|
|
6042
|
-
if (resolvedThreadId && sessionThreadId !== resolvedThreadId) {
|
|
6043
|
-
return null;
|
|
6044
|
-
}
|
|
6045
|
-
resolvedThreadId = sessionThreadId;
|
|
6046
|
-
}
|
|
6047
|
-
if (typeof payload.cwd === "string" && payload.cwd.trim()) {
|
|
6048
|
-
snapshot.session.cwd = payload.cwd;
|
|
6049
|
-
}
|
|
6050
|
-
setCodexProviderMeta(snapshot, resolvedThreadId, rolloutPath ?? null);
|
|
6051
|
-
snapshot.session.status = resolvedThreadId ? "idle" : snapshot.session.status;
|
|
6052
|
-
continue;
|
|
6053
|
-
}
|
|
6054
|
-
if (entryType === "turn_context") {
|
|
6055
|
-
if (typeof payload.cwd === "string" && payload.cwd.trim()) {
|
|
6056
|
-
snapshot.session.cwd = payload.cwd;
|
|
6057
|
-
}
|
|
6058
|
-
if (typeof payload.model === "string" && payload.model.trim()) {
|
|
6059
|
-
snapshot.session.model = payload.model;
|
|
6060
|
-
}
|
|
6061
|
-
continue;
|
|
6062
|
-
}
|
|
6063
|
-
if (entryType === "event_msg") {
|
|
6064
|
-
const payloadType2 = typeof payload.type === "string" ? payload.type : "";
|
|
6065
|
-
if (payloadType2 === "task_started") {
|
|
6066
|
-
const turnId = typeof payload.turn_id === "string" ? payload.turn_id : null;
|
|
6067
|
-
if (!turnId) {
|
|
6068
|
-
continue;
|
|
6069
|
-
}
|
|
6070
|
-
currentTurnId = turnId;
|
|
6071
|
-
ensureTurn(turnId, parseCodexTimestamp(payload.started_at) ?? timestamp);
|
|
6072
|
-
snapshot.currentTurnId = turnId;
|
|
6073
|
-
snapshot.session.status = "active";
|
|
6074
|
-
continue;
|
|
6075
|
-
}
|
|
6076
|
-
if (payloadType2 === "task_complete" || payloadType2 === "turn_aborted") {
|
|
6077
|
-
const turnId = typeof payload.turn_id === "string" ? payload.turn_id : currentTurnId;
|
|
6078
|
-
if (!turnId) {
|
|
6079
|
-
continue;
|
|
6080
|
-
}
|
|
6081
|
-
const turn2 = ensureTurn(turnId);
|
|
6082
|
-
turn2.status = payloadType2 === "task_complete" ? "completed" : payload.reason === "interrupted" ? "interrupted" : "error";
|
|
6083
|
-
turn2.endedAt = parseCodexTimestamp(payload.completed_at) ?? timestamp;
|
|
6084
|
-
finalizeCodexTurnBlocks(turn2, turn2.status);
|
|
6085
|
-
if (snapshot.currentTurnId === turnId) {
|
|
6086
|
-
snapshot.currentTurnId = undefined;
|
|
6087
|
-
}
|
|
6088
|
-
currentTurnId = currentTurnId === turnId ? null : currentTurnId;
|
|
6089
|
-
snapshot.session.status = turn2.status === "error" ? "error" : "idle";
|
|
6090
|
-
}
|
|
6091
|
-
continue;
|
|
6092
|
-
}
|
|
6093
|
-
if (entryType !== "response_item" || !currentTurnId) {
|
|
6094
|
-
continue;
|
|
6095
|
-
}
|
|
6096
|
-
const turn = ensureTurn(currentTurnId);
|
|
6097
|
-
const payloadType = typeof payload.type === "string" ? payload.type : "";
|
|
6098
|
-
if (payloadType === "message" && payload.role === "user") {
|
|
6099
|
-
const text = extractCodexMessageText(payload);
|
|
6100
|
-
if (!text) {
|
|
6101
|
-
continue;
|
|
6102
|
-
}
|
|
6103
|
-
const block = {
|
|
6104
|
-
id: `${turn.id}:text:${turn.nextBlockIndex}`,
|
|
6105
|
-
turnId: turn.id,
|
|
6106
|
-
index: turn.nextBlockIndex++,
|
|
6107
|
-
type: "text",
|
|
6108
|
-
text,
|
|
6109
|
-
status: "completed"
|
|
6110
|
-
};
|
|
6111
|
-
turn.blocks.push({ block, status: "completed" });
|
|
6112
|
-
continue;
|
|
6113
|
-
}
|
|
6114
|
-
if (payloadType === "message" && payload.role === "assistant") {
|
|
6115
|
-
const text = extractCodexMessageText(payload);
|
|
6116
|
-
if (!text) {
|
|
6117
|
-
continue;
|
|
6118
|
-
}
|
|
6119
|
-
const block = {
|
|
6120
|
-
id: `${turn.id}:text:${turn.nextBlockIndex}`,
|
|
6121
|
-
turnId: turn.id,
|
|
6122
|
-
index: turn.nextBlockIndex++,
|
|
6123
|
-
type: "text",
|
|
6124
|
-
text,
|
|
6125
|
-
status: "completed"
|
|
6126
|
-
};
|
|
6127
|
-
turn.blocks.push({ block, status: "completed" });
|
|
6128
|
-
continue;
|
|
6129
|
-
}
|
|
6130
|
-
if (payloadType === "reasoning") {
|
|
6131
|
-
const text = extractCodexReasoningText(payload);
|
|
6132
|
-
if (!text) {
|
|
6133
|
-
continue;
|
|
6134
|
-
}
|
|
6135
|
-
const block = {
|
|
6136
|
-
id: `${turn.id}:reasoning:${turn.nextBlockIndex}`,
|
|
6137
|
-
turnId: turn.id,
|
|
6138
|
-
index: turn.nextBlockIndex++,
|
|
6139
|
-
type: "reasoning",
|
|
6140
|
-
text,
|
|
6141
|
-
status: "completed"
|
|
6142
|
-
};
|
|
6143
|
-
turn.blocks.push({ block, status: "completed" });
|
|
6144
|
-
continue;
|
|
6145
|
-
}
|
|
6146
|
-
if (payloadType === "function_call" || payloadType === "custom_tool_call" || payloadType === "web_search_call") {
|
|
6147
|
-
const block = buildCodexRolloutActionBlock(payload, turn.id, turn.nextBlockIndex++);
|
|
6148
|
-
const blockState = { block, status: "streaming" };
|
|
6149
|
-
turn.blocks.push(blockState);
|
|
6150
|
-
blocksByCallId.set(block.id, blockState);
|
|
6151
|
-
continue;
|
|
6152
|
-
}
|
|
6153
|
-
if (payloadType === "function_call_output" || payloadType === "custom_tool_call_output") {
|
|
6154
|
-
const callId = typeof payload.call_id === "string" ? payload.call_id : null;
|
|
6155
|
-
if (!callId) {
|
|
6156
|
-
continue;
|
|
6157
|
-
}
|
|
6158
|
-
let blockState = blocksByCallId.get(callId);
|
|
6159
|
-
if (!blockState) {
|
|
6160
|
-
const block = buildCodexRolloutActionBlock({
|
|
6161
|
-
type: "tool_call",
|
|
6162
|
-
call_id: callId,
|
|
6163
|
-
name: "unknown"
|
|
6164
|
-
}, turn.id, turn.nextBlockIndex++);
|
|
6165
|
-
blockState = { block, status: "streaming" };
|
|
6166
|
-
turn.blocks.push(blockState);
|
|
6167
|
-
blocksByCallId.set(callId, blockState);
|
|
6168
|
-
}
|
|
6169
|
-
if (blockState.block.type === "action") {
|
|
6170
|
-
blockState.block.action.output = stringifyCodexItem(payload.output);
|
|
6171
|
-
blockState.block.action.status = "completed";
|
|
6172
|
-
}
|
|
6173
|
-
blockState.status = "completed";
|
|
6174
|
-
blockState.block.status = "completed";
|
|
6175
|
-
}
|
|
6176
|
-
}
|
|
6177
|
-
if (!resolvedThreadId && snapshot.turns.length === 0) {
|
|
6178
|
-
return null;
|
|
6179
|
-
}
|
|
6180
|
-
setCodexProviderMeta(snapshot, resolvedThreadId, rolloutPath ?? null);
|
|
6181
|
-
snapshot.session.status = snapshot.currentTurnId ? "active" : snapshot.session.status;
|
|
6182
|
-
return snapshot;
|
|
6183
|
-
}
|
|
6184
4968
|
function isMissingCodexRolloutError(error) {
|
|
6185
4969
|
const message = errorMessage2(error).toLowerCase();
|
|
6186
4970
|
return message.includes("no rollout found for thread id");
|
|
@@ -6827,48 +5611,10 @@ async function ensureCodexAppServerAgentOnline(options) {
|
|
|
6827
5611
|
session.update(options);
|
|
6828
5612
|
return session.ensureOnline();
|
|
6829
5613
|
}
|
|
6830
|
-
async function invokeCodexAppServerAgent(options) {
|
|
6831
|
-
const session = getOrCreateSession2(options);
|
|
6832
|
-
session.update(options);
|
|
6833
|
-
return session.invoke(options.prompt, options.timeoutMs);
|
|
6834
|
-
}
|
|
6835
|
-
async function sendCodexAppServerAgent(options) {
|
|
6836
|
-
const session = getOrCreateSession2(options);
|
|
6837
|
-
session.update(options);
|
|
6838
|
-
if (session.hasActiveTurn()) {
|
|
6839
|
-
return session.steerAndWait(options.prompt, options.timeoutMs);
|
|
6840
|
-
}
|
|
6841
|
-
return session.invoke(options.prompt, options.timeoutMs);
|
|
6842
|
-
}
|
|
6843
5614
|
function isCodexAppServerAgentAlive(options) {
|
|
6844
5615
|
const session = sessions2.get(sessionKey2(options));
|
|
6845
5616
|
return Boolean(session?.isAlive());
|
|
6846
5617
|
}
|
|
6847
|
-
async function getCodexAppServerAgentSnapshot(options) {
|
|
6848
|
-
const stdoutLogPath = join6(options.logsDirectory, "stdout.log");
|
|
6849
|
-
const threadIdPath = join6(options.runtimeDirectory, "codex-thread-id.txt");
|
|
6850
|
-
const statePath = join6(options.runtimeDirectory, "state.json");
|
|
6851
|
-
const [rawLog, persistedThreadId, persistedState] = await Promise.all([
|
|
6852
|
-
readOptionalFile2(stdoutLogPath),
|
|
6853
|
-
readOptionalFile2(threadIdPath),
|
|
6854
|
-
readOptionalJsonRecord(statePath)
|
|
6855
|
-
]);
|
|
6856
|
-
const resolvedThreadId = options.threadId ?? persistedThreadId ?? metadataString(persistedState ?? undefined, "threadId") ?? undefined;
|
|
6857
|
-
const persistedThreadPath = metadataString(persistedState ?? undefined, "threadPath");
|
|
6858
|
-
if (persistedThreadPath) {
|
|
6859
|
-
const rawRollout = await readOptionalFile2(persistedThreadPath);
|
|
6860
|
-
if (rawRollout) {
|
|
6861
|
-
const rolloutSnapshot = buildCodexRolloutSessionSnapshot(rawRollout, options, resolvedThreadId, persistedThreadPath);
|
|
6862
|
-
if (rolloutSnapshot) {
|
|
6863
|
-
return rolloutSnapshot;
|
|
6864
|
-
}
|
|
6865
|
-
}
|
|
6866
|
-
}
|
|
6867
|
-
if (!rawLog) {
|
|
6868
|
-
return null;
|
|
6869
|
-
}
|
|
6870
|
-
return buildCodexAppServerSessionSnapshot(rawLog, options, resolvedThreadId);
|
|
6871
|
-
}
|
|
6872
5618
|
async function shutdownCodexAppServerAgent(options, shutdownOptions = {}) {
|
|
6873
5619
|
const key = sessionKey2(options);
|
|
6874
5620
|
const session = sessions2.get(key);
|
|
@@ -6888,49 +5634,6 @@ var init_codex_app_server = __esm(() => {
|
|
|
6888
5634
|
});
|
|
6889
5635
|
|
|
6890
5636
|
// ../runtime/src/collaboration-contract.ts
|
|
6891
|
-
function metadataValue(metadata, key) {
|
|
6892
|
-
return metadata?.[key];
|
|
6893
|
-
}
|
|
6894
|
-
function recordFromInvocation(invocation, key) {
|
|
6895
|
-
const contextRecord = metadataValue(invocation.context, key);
|
|
6896
|
-
if (typeof contextRecord !== "undefined") {
|
|
6897
|
-
return contextRecord;
|
|
6898
|
-
}
|
|
6899
|
-
const nestedContext = metadataValue(invocation.context, "collaboration");
|
|
6900
|
-
if (nestedContext && typeof nestedContext === "object" && !Array.isArray(nestedContext)) {
|
|
6901
|
-
const nestedValue = metadataValue(nestedContext, key);
|
|
6902
|
-
if (typeof nestedValue !== "undefined") {
|
|
6903
|
-
return nestedValue;
|
|
6904
|
-
}
|
|
6905
|
-
}
|
|
6906
|
-
const metadataRecord2 = metadataValue(invocation.metadata, key);
|
|
6907
|
-
if (typeof metadataRecord2 !== "undefined") {
|
|
6908
|
-
return metadataRecord2;
|
|
6909
|
-
}
|
|
6910
|
-
const nestedMetadata = metadataValue(invocation.metadata, "collaboration");
|
|
6911
|
-
if (nestedMetadata && typeof nestedMetadata === "object" && !Array.isArray(nestedMetadata)) {
|
|
6912
|
-
return metadataValue(nestedMetadata, key);
|
|
6913
|
-
}
|
|
6914
|
-
return;
|
|
6915
|
-
}
|
|
6916
|
-
function stringFromInvocation(invocation, key) {
|
|
6917
|
-
const value = recordFromInvocation(invocation, key);
|
|
6918
|
-
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
6919
|
-
}
|
|
6920
|
-
function waitingOnLabel(value) {
|
|
6921
|
-
if (typeof value === "string" && value.trim().length > 0) {
|
|
6922
|
-
return value.trim();
|
|
6923
|
-
}
|
|
6924
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
6925
|
-
return;
|
|
6926
|
-
}
|
|
6927
|
-
const waitingOn = value;
|
|
6928
|
-
const kind = typeof waitingOn.kind === "string" ? waitingOn.kind : undefined;
|
|
6929
|
-
const label = typeof waitingOn.label === "string" ? waitingOn.label.trim() : "";
|
|
6930
|
-
const targetId = typeof waitingOn.targetId === "string" ? waitingOn.targetId.trim() : "";
|
|
6931
|
-
const parts = [label || kind, targetId || undefined].filter(Boolean);
|
|
6932
|
-
return parts.length > 0 ? parts.join(" \xB7 ") : undefined;
|
|
6933
|
-
}
|
|
6934
5637
|
function buildCollaborationContractPrompt(agentId) {
|
|
6935
5638
|
return [
|
|
6936
5639
|
"Collaboration contract:",
|
|
@@ -6947,38 +5650,6 @@ function buildCollaborationContractPrompt(agentId) {
|
|
|
6947
5650
|
].join(`
|
|
6948
5651
|
`);
|
|
6949
5652
|
}
|
|
6950
|
-
function buildInvocationCollaborationContextPrompt(invocation) {
|
|
6951
|
-
const recordId = stringFromInvocation(invocation, "recordId") ?? stringFromInvocation(invocation, "collaborationRecordId");
|
|
6952
|
-
const kind = stringFromInvocation(invocation, "kind") ?? stringFromInvocation(invocation, "collaborationKind");
|
|
6953
|
-
const state = stringFromInvocation(invocation, "state") ?? stringFromInvocation(invocation, "collaborationState");
|
|
6954
|
-
const ownerId = stringFromInvocation(invocation, "ownerId");
|
|
6955
|
-
const nextMoveOwnerId = stringFromInvocation(invocation, "nextMoveOwnerId");
|
|
6956
|
-
const wakeReason = stringFromInvocation(invocation, "wakeReason");
|
|
6957
|
-
const targetAgentId = stringFromInvocation(invocation, "targetAgentId");
|
|
6958
|
-
const waitingOn = waitingOnLabel(recordFromInvocation(invocation, "waitingOn") ?? recordFromInvocation(invocation, "waiting_on"));
|
|
6959
|
-
const acceptanceState = stringFromInvocation(invocation, "acceptanceState");
|
|
6960
|
-
const requestedById = stringFromInvocation(invocation, "requestedById");
|
|
6961
|
-
const askedById = stringFromInvocation(invocation, "askedById");
|
|
6962
|
-
const askedOfId = stringFromInvocation(invocation, "askedOfId");
|
|
6963
|
-
const lines = [
|
|
6964
|
-
recordId ? ` - Record: ${kind ? `${kind} ` : ""}${recordId}` : undefined,
|
|
6965
|
-
state ? ` - State: ${state}` : undefined,
|
|
6966
|
-
ownerId ? ` - Owner: ${ownerId}` : undefined,
|
|
6967
|
-
nextMoveOwnerId ? ` - Next move owner: ${nextMoveOwnerId}` : undefined,
|
|
6968
|
-
wakeReason ? ` - Wake reason: ${wakeReason}` : undefined,
|
|
6969
|
-
targetAgentId ? ` - Wake target: ${targetAgentId}` : undefined,
|
|
6970
|
-
waitingOn ? ` - Waiting on: ${waitingOn}` : undefined,
|
|
6971
|
-
acceptanceState ? ` - Acceptance: ${acceptanceState}` : undefined,
|
|
6972
|
-
requestedById ? ` - Requested by: ${requestedById}` : undefined,
|
|
6973
|
-
askedById ? ` - Asked by: ${askedById}` : undefined,
|
|
6974
|
-
askedOfId ? ` - Asked of: ${askedOfId}` : undefined
|
|
6975
|
-
].filter((value) => Boolean(value));
|
|
6976
|
-
if (lines.length === 0) {
|
|
6977
|
-
return;
|
|
6978
|
-
}
|
|
6979
|
-
return ["Collaboration context:", ...lines].join(`
|
|
6980
|
-
`);
|
|
6981
|
-
}
|
|
6982
5653
|
|
|
6983
5654
|
// ../runtime/src/broker-service.ts
|
|
6984
5655
|
import { spawnSync } from "child_process";
|
|
@@ -7507,43 +6178,6 @@ var init_local_agent_template = __esm(() => {
|
|
|
7507
6178
|
});
|
|
7508
6179
|
|
|
7509
6180
|
// ../runtime/src/local-agents.ts
|
|
7510
|
-
var exports_local_agents = {};
|
|
7511
|
-
__export(exports_local_agents, {
|
|
7512
|
-
updateLocalAgentConfig: () => updateLocalAgentConfig,
|
|
7513
|
-
stripLocalAgentReplyMetadata: () => stripLocalAgentReplyMetadata,
|
|
7514
|
-
stopLocalAgent: () => stopLocalAgent,
|
|
7515
|
-
stopAllLocalAgents: () => stopAllLocalAgents,
|
|
7516
|
-
startLocalAgent: () => startLocalAgent,
|
|
7517
|
-
shutdownLocalSessionEndpoint: () => shutdownLocalSessionEndpoint,
|
|
7518
|
-
shouldDisableGeneratedCodexEndpoint: () => shouldDisableGeneratedCodexEndpoint,
|
|
7519
|
-
sendTmuxPrompt: () => sendTmuxPrompt,
|
|
7520
|
-
restartLocalAgent: () => restartLocalAgent,
|
|
7521
|
-
restartAllLocalAgents: () => restartAllLocalAgents,
|
|
7522
|
-
resolveLocalAgentIdentity: () => resolveLocalAgentIdentity,
|
|
7523
|
-
resolveLocalAgentByName: () => resolveLocalAgentByName,
|
|
7524
|
-
renderLocalAgentSystemPromptTemplate: () => renderLocalAgentSystemPromptTemplate,
|
|
7525
|
-
loadRegisteredLocalAgentBindings: () => loadRegisteredLocalAgentBindings,
|
|
7526
|
-
listLocalAgents: () => listLocalAgents,
|
|
7527
|
-
isLocalAgentSessionAlive: () => isLocalAgentSessionAlive,
|
|
7528
|
-
isLocalAgentEndpointAlive: () => isLocalAgentEndpointAlive,
|
|
7529
|
-
invokeLocalAgentEndpoint: () => invokeLocalAgentEndpoint,
|
|
7530
|
-
interruptLocalAgent: () => interruptLocalAgent,
|
|
7531
|
-
inferLocalAgentBinding: () => inferLocalAgentBinding,
|
|
7532
|
-
getLocalAgentSessionSnapshot: () => getLocalAgentSessionSnapshot,
|
|
7533
|
-
getLocalAgentEndpointSessionSnapshot: () => getLocalAgentEndpointSessionSnapshot,
|
|
7534
|
-
getLocalAgentConfig: () => getLocalAgentConfig,
|
|
7535
|
-
ensureLocalSessionEndpointOnline: () => ensureLocalSessionEndpointOnline,
|
|
7536
|
-
ensureLocalAgentBindingOnline: () => ensureLocalAgentBindingOnline,
|
|
7537
|
-
buildTmuxLaunchShellCommand: () => buildTmuxLaunchShellCommand,
|
|
7538
|
-
buildLocalAgentSystemPromptTemplate: () => buildLocalAgentSystemPromptTemplate,
|
|
7539
|
-
buildLocalAgentSystemPrompt: () => buildLocalAgentSystemPrompt,
|
|
7540
|
-
buildLocalAgentNudge: () => buildLocalAgentNudge,
|
|
7541
|
-
buildLocalAgentDirectInvocationPrompt: () => buildLocalAgentDirectInvocationPrompt,
|
|
7542
|
-
buildAttachedSessionInvocationPrompt: () => buildAttachedSessionInvocationPrompt,
|
|
7543
|
-
answerLocalAgentSessionQuestion: () => answerLocalAgentSessionQuestion,
|
|
7544
|
-
SUPPORTED_LOCAL_AGENT_HARNESSES: () => SUPPORTED_LOCAL_AGENT_HARNESSES
|
|
7545
|
-
});
|
|
7546
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
7547
6181
|
import { execFileSync as execFileSync3, execSync } from "child_process";
|
|
7548
6182
|
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
7549
6183
|
import { mkdir as mkdir5, rm as rm4, stat as stat3, writeFile as writeFile5 } from "fs/promises";
|
|
@@ -7574,21 +6208,9 @@ function resolveBrokerUrl() {
|
|
|
7574
6208
|
function nowSeconds2() {
|
|
7575
6209
|
return Math.floor(Date.now() / 1000);
|
|
7576
6210
|
}
|
|
7577
|
-
function normalizeBrokerTimestamp(value) {
|
|
7578
|
-
return value > 10000000000 ? Math.floor(value / 1000) : value;
|
|
7579
|
-
}
|
|
7580
6211
|
function brokerRelayCommand() {
|
|
7581
6212
|
return `node ${JSON.stringify(join8(OPENSCOUT_REPO_ROOT, "packages", "cli", "bin", "scout.mjs"))}`;
|
|
7582
6213
|
}
|
|
7583
|
-
function sleep2(ms) {
|
|
7584
|
-
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
7585
|
-
}
|
|
7586
|
-
function createLocalAgentFlightId() {
|
|
7587
|
-
return `f-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
|
|
7588
|
-
}
|
|
7589
|
-
function escapeRegExp(value) {
|
|
7590
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7591
|
-
}
|
|
7592
6214
|
function titleCaseLocalAgentName(value) {
|
|
7593
6215
|
return value.split(/[-_.\s]+/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)).join(" ");
|
|
7594
6216
|
}
|
|
@@ -7833,13 +6455,6 @@ function expandHomePath3(value) {
|
|
|
7833
6455
|
function normalizeProjectPath(value) {
|
|
7834
6456
|
return resolve6(expandHomePath3(value.trim() || "."));
|
|
7835
6457
|
}
|
|
7836
|
-
function compactHomePath(value) {
|
|
7837
|
-
const home = process.env.HOME;
|
|
7838
|
-
if (!home) {
|
|
7839
|
-
return value;
|
|
7840
|
-
}
|
|
7841
|
-
return value.startsWith(home) ? value.replace(home, "~") : value;
|
|
7842
|
-
}
|
|
7843
6458
|
function normalizeTmuxSessionName2(value, agentId) {
|
|
7844
6459
|
const fallback = `relay-${agentId}`;
|
|
7845
6460
|
const trimmed = value?.trim() ?? "";
|
|
@@ -8085,134 +6700,6 @@ function relayAgentOverrideFromLocalAgentRecord(agentId, record, existing) {
|
|
|
8085
6700
|
}
|
|
8086
6701
|
};
|
|
8087
6702
|
}
|
|
8088
|
-
function buildLocalAgentConfigState(agentId, record) {
|
|
8089
|
-
return {
|
|
8090
|
-
agentId,
|
|
8091
|
-
editable: true,
|
|
8092
|
-
systemPrompt: record.systemPrompt || buildLocalAgentSystemPromptTemplate(),
|
|
8093
|
-
runtime: {
|
|
8094
|
-
cwd: compactHomePath(record.cwd),
|
|
8095
|
-
harness: normalizeLocalAgentHarness(record.harness),
|
|
8096
|
-
transport: normalizeLocalAgentTransport(record.transport, normalizeLocalAgentHarness(record.harness)),
|
|
8097
|
-
sessionId: record.tmuxSession,
|
|
8098
|
-
wakePolicy: "on_demand"
|
|
8099
|
-
},
|
|
8100
|
-
launchArgs: normalizeLocalAgentLaunchArgs(record.launchArgs),
|
|
8101
|
-
capabilities: normalizeLocalAgentCapabilities(record.capabilities),
|
|
8102
|
-
applyMode: "restart",
|
|
8103
|
-
templateHint: LOCAL_AGENT_SYSTEM_PROMPT_TEMPLATE_HINT
|
|
8104
|
-
};
|
|
8105
|
-
}
|
|
8106
|
-
async function assertDirectoryExists(directory) {
|
|
8107
|
-
const stats = await stat3(directory);
|
|
8108
|
-
if (!stats.isDirectory()) {
|
|
8109
|
-
throw new Error(`${directory} is not a directory.`);
|
|
8110
|
-
}
|
|
8111
|
-
}
|
|
8112
|
-
async function resolveConfiguredLocalAgentRecord(agentId) {
|
|
8113
|
-
const overrides = await readRelayAgentOverrides();
|
|
8114
|
-
const override = overrides[agentId];
|
|
8115
|
-
if (override) {
|
|
8116
|
-
return localAgentRecordFromRelayAgentOverride(agentId, override);
|
|
8117
|
-
}
|
|
8118
|
-
const registry = await readLocalAgentRegistry();
|
|
8119
|
-
const record = registry[agentId];
|
|
8120
|
-
return record ? normalizeLocalAgentRecord(agentId, record) : null;
|
|
8121
|
-
}
|
|
8122
|
-
async function getLocalAgentConfig(agentId) {
|
|
8123
|
-
const record = await resolveConfiguredLocalAgentRecord(agentId);
|
|
8124
|
-
if (!record) {
|
|
8125
|
-
return null;
|
|
8126
|
-
}
|
|
8127
|
-
return buildLocalAgentConfigState(agentId, record);
|
|
8128
|
-
}
|
|
8129
|
-
async function getLocalAgentSessionSnapshot(agentId) {
|
|
8130
|
-
const record = await resolveConfiguredLocalAgentRecord(agentId);
|
|
8131
|
-
if (!record) {
|
|
8132
|
-
return null;
|
|
8133
|
-
}
|
|
8134
|
-
if (record.transport === "codex_app_server") {
|
|
8135
|
-
return getCodexAppServerAgentSnapshot(buildCodexAgentSessionOptions(agentId, record));
|
|
8136
|
-
}
|
|
8137
|
-
if (record.transport === "claude_stream_json") {
|
|
8138
|
-
return getClaudeStreamJsonAgentSnapshot(buildClaudeAgentSessionOptions(agentId, record));
|
|
8139
|
-
}
|
|
8140
|
-
return null;
|
|
8141
|
-
}
|
|
8142
|
-
async function getLocalAgentEndpointSessionSnapshot(endpoint) {
|
|
8143
|
-
if (endpoint.transport === "codex_app_server") {
|
|
8144
|
-
return getCodexAppServerAgentSnapshot(buildCodexEndpointSessionOptions(endpoint));
|
|
8145
|
-
}
|
|
8146
|
-
if (endpoint.transport === "claude_stream_json") {
|
|
8147
|
-
return getClaudeStreamJsonAgentSnapshot(buildClaudeEndpointSessionOptions(endpoint));
|
|
8148
|
-
}
|
|
8149
|
-
return null;
|
|
8150
|
-
}
|
|
8151
|
-
async function ensureLocalSessionEndpointOnline(endpoint) {
|
|
8152
|
-
if (endpoint.transport === "codex_app_server") {
|
|
8153
|
-
await ensureCodexAppServerAgentOnline(buildCodexEndpointSessionOptions(endpoint));
|
|
8154
|
-
return;
|
|
8155
|
-
}
|
|
8156
|
-
if (endpoint.transport === "claude_stream_json") {
|
|
8157
|
-
await ensureClaudeStreamJsonAgentOnline(buildClaudeEndpointSessionOptions(endpoint));
|
|
8158
|
-
}
|
|
8159
|
-
}
|
|
8160
|
-
async function shutdownLocalSessionEndpoint(endpoint) {
|
|
8161
|
-
if (endpoint.transport === "codex_app_server") {
|
|
8162
|
-
await shutdownCodexAppServerAgent(buildCodexEndpointSessionOptions(endpoint));
|
|
8163
|
-
return;
|
|
8164
|
-
}
|
|
8165
|
-
if (endpoint.transport === "claude_stream_json") {
|
|
8166
|
-
await shutdownClaudeStreamJsonAgent(buildClaudeEndpointSessionOptions(endpoint));
|
|
8167
|
-
}
|
|
8168
|
-
}
|
|
8169
|
-
async function answerLocalAgentSessionQuestion(agentId, input) {
|
|
8170
|
-
const record = await resolveConfiguredLocalAgentRecord(agentId);
|
|
8171
|
-
if (!record) {
|
|
8172
|
-
throw new Error(`Agent ${agentId} is not configured.`);
|
|
8173
|
-
}
|
|
8174
|
-
if (record.transport !== "claude_stream_json") {
|
|
8175
|
-
throw new Error(`Agent ${agentId} does not support direct question answers for transport ${record.transport}.`);
|
|
8176
|
-
}
|
|
8177
|
-
await answerClaudeStreamJsonQuestion(buildClaudeAgentSessionOptions(agentId, record), input);
|
|
8178
|
-
}
|
|
8179
|
-
async function updateLocalAgentConfig(agentId, input) {
|
|
8180
|
-
const [registry, overrides] = await Promise.all([
|
|
8181
|
-
readLocalAgentRegistry(),
|
|
8182
|
-
readRelayAgentOverrides()
|
|
8183
|
-
]);
|
|
8184
|
-
const record = registry[agentId] ?? (overrides[agentId] ? localAgentRecordFromRelayAgentOverride(agentId, overrides[agentId]) : undefined);
|
|
8185
|
-
if (!record) {
|
|
8186
|
-
return null;
|
|
8187
|
-
}
|
|
8188
|
-
const cwd = normalizeProjectPath(input.runtime.cwd || record.cwd);
|
|
8189
|
-
await assertDirectoryExists(cwd);
|
|
8190
|
-
const nextHarness = normalizeLocalAgentHarness(input.runtime.harness);
|
|
8191
|
-
const nextTransport = normalizeLocalAgentTransport(input.runtime.transport ?? record.transport, nextHarness);
|
|
8192
|
-
const nextRecord = normalizeLocalAgentRecord(agentId, {
|
|
8193
|
-
...record,
|
|
8194
|
-
cwd,
|
|
8195
|
-
tmuxSession: input.runtime.sessionId,
|
|
8196
|
-
harness: nextHarness,
|
|
8197
|
-
defaultHarness: nextHarness,
|
|
8198
|
-
harnessProfiles: {
|
|
8199
|
-
...record.harnessProfiles ?? {},
|
|
8200
|
-
[normalizeManagedHarness2(input.runtime.harness, "claude")]: {
|
|
8201
|
-
cwd,
|
|
8202
|
-
transport: nextTransport,
|
|
8203
|
-
sessionId: normalizeTmuxSessionName2(input.runtime.sessionId, `${agentId}-${normalizeManagedHarness2(input.runtime.harness, "claude")}`),
|
|
8204
|
-
launchArgs: input.launchArgs
|
|
8205
|
-
}
|
|
8206
|
-
},
|
|
8207
|
-
transport: nextTransport,
|
|
8208
|
-
systemPrompt: input.systemPrompt.trim() || undefined,
|
|
8209
|
-
launchArgs: input.launchArgs,
|
|
8210
|
-
capabilities: input.capabilities
|
|
8211
|
-
});
|
|
8212
|
-
registry[agentId] = nextRecord;
|
|
8213
|
-
await writeLocalAgentRegistry(registry);
|
|
8214
|
-
return buildLocalAgentConfigState(agentId, nextRecord);
|
|
8215
|
-
}
|
|
8216
6703
|
function buildCodexAgentSessionOptions(agentName, record, systemPrompt) {
|
|
8217
6704
|
return {
|
|
8218
6705
|
agentName,
|
|
@@ -8235,72 +6722,6 @@ function buildClaudeAgentSessionOptions(agentName, record, systemPrompt) {
|
|
|
8235
6722
|
launchArgs: normalizeLocalAgentLaunchArgs(record.launchArgs)
|
|
8236
6723
|
};
|
|
8237
6724
|
}
|
|
8238
|
-
function endpointMetadataString(endpoint, key) {
|
|
8239
|
-
const value = endpoint.metadata?.[key];
|
|
8240
|
-
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
8241
|
-
}
|
|
8242
|
-
function endpointInvocationPrompt(endpoint, agentName, invocation) {
|
|
8243
|
-
const source = endpointMetadataString(endpoint, "source");
|
|
8244
|
-
const externalSource = endpointMetadataString(endpoint, "externalSource");
|
|
8245
|
-
const attachedTransport = endpointMetadataString(endpoint, "attachedTransport");
|
|
8246
|
-
const sessionBacked = endpoint.metadata?.sessionBacked === true;
|
|
8247
|
-
if (invocation.action === "consult" && (sessionBacked || source === "local-session" || externalSource === "local-session" || attachedTransport === "codex_app_server" || attachedTransport === "claude_stream_json")) {
|
|
8248
|
-
return invocation.task;
|
|
8249
|
-
}
|
|
8250
|
-
if (sessionBacked) {
|
|
8251
|
-
return buildAttachedSessionInvocationPrompt(invocation);
|
|
8252
|
-
}
|
|
8253
|
-
return buildLocalAgentDirectInvocationPrompt(agentName, invocation);
|
|
8254
|
-
}
|
|
8255
|
-
function isSessionBackedEndpoint(endpoint) {
|
|
8256
|
-
const source = endpointMetadataString(endpoint, "source");
|
|
8257
|
-
const externalSource = endpointMetadataString(endpoint, "externalSource");
|
|
8258
|
-
const attachedTransport = endpointMetadataString(endpoint, "attachedTransport");
|
|
8259
|
-
return endpoint.metadata?.sessionBacked === true || source === "local-session" || externalSource === "local-session" || attachedTransport === "codex_app_server" || attachedTransport === "claude_stream_json";
|
|
8260
|
-
}
|
|
8261
|
-
function endpointAgentName(endpoint) {
|
|
8262
|
-
return endpointMetadataString(endpoint, "agentName") ?? endpointMetadataString(endpoint, "definitionId") ?? endpoint.agentId;
|
|
8263
|
-
}
|
|
8264
|
-
function endpointRuntimeInstanceId(endpoint) {
|
|
8265
|
-
return endpointMetadataString(endpoint, "runtimeInstanceId") ?? endpointMetadataString(endpoint, "runtimeSessionId") ?? endpoint.sessionId ?? `relay-${endpointAgentName(endpoint)}`;
|
|
8266
|
-
}
|
|
8267
|
-
function endpointCwd(endpoint) {
|
|
8268
|
-
return endpoint.cwd ?? endpoint.projectRoot ?? process.cwd();
|
|
8269
|
-
}
|
|
8270
|
-
function attachedLocalSessionSystemPrompt(endpoint) {
|
|
8271
|
-
const explicit = endpointMetadataString(endpoint, "systemPrompt");
|
|
8272
|
-
if (explicit) {
|
|
8273
|
-
return explicit;
|
|
8274
|
-
}
|
|
8275
|
-
return "Resume the existing session without changing its identity or prior context.";
|
|
8276
|
-
}
|
|
8277
|
-
function buildCodexEndpointSessionOptions(endpoint) {
|
|
8278
|
-
const agentName = endpointAgentName(endpoint);
|
|
8279
|
-
const threadId = endpointMetadataString(endpoint, "threadId") ?? endpointMetadataString(endpoint, "externalSessionId") ?? endpoint.sessionId ?? undefined;
|
|
8280
|
-
return {
|
|
8281
|
-
agentName,
|
|
8282
|
-
sessionId: endpointRuntimeInstanceId(endpoint),
|
|
8283
|
-
cwd: endpointCwd(endpoint),
|
|
8284
|
-
systemPrompt: attachedLocalSessionSystemPrompt(endpoint),
|
|
8285
|
-
runtimeDirectory: relayAgentRuntimeDirectory(agentName),
|
|
8286
|
-
logsDirectory: relayAgentLogsDirectory(agentName),
|
|
8287
|
-
launchArgs: [],
|
|
8288
|
-
threadId,
|
|
8289
|
-
requireExistingThread: Boolean(threadId)
|
|
8290
|
-
};
|
|
8291
|
-
}
|
|
8292
|
-
function buildClaudeEndpointSessionOptions(endpoint) {
|
|
8293
|
-
const agentName = endpointAgentName(endpoint);
|
|
8294
|
-
return {
|
|
8295
|
-
agentName,
|
|
8296
|
-
sessionId: endpointRuntimeInstanceId(endpoint),
|
|
8297
|
-
cwd: endpointCwd(endpoint),
|
|
8298
|
-
systemPrompt: attachedLocalSessionSystemPrompt(endpoint),
|
|
8299
|
-
runtimeDirectory: relayAgentRuntimeDirectory(agentName),
|
|
8300
|
-
logsDirectory: relayAgentLogsDirectory(agentName),
|
|
8301
|
-
launchArgs: []
|
|
8302
|
-
};
|
|
8303
|
-
}
|
|
8304
6725
|
function isLocalAgentRecordOnline(agentName, record) {
|
|
8305
6726
|
const normalizedRecord = normalizeLocalAgentRecord(agentName, record);
|
|
8306
6727
|
if (normalizedRecord.transport === "codex_app_server") {
|
|
@@ -8319,117 +6740,12 @@ function isLocalAgentSessionAlive(sessionName) {
|
|
|
8319
6740
|
return false;
|
|
8320
6741
|
}
|
|
8321
6742
|
}
|
|
8322
|
-
function isLocalAgentEndpointAlive(endpoint) {
|
|
8323
|
-
if (endpoint.transport === "pairing_bridge") {
|
|
8324
|
-
return endpoint.state !== "offline";
|
|
8325
|
-
}
|
|
8326
|
-
if (endpoint.transport === "codex_app_server") {
|
|
8327
|
-
return isCodexAppServerAgentAlive(buildCodexEndpointSessionOptions(endpoint));
|
|
8328
|
-
}
|
|
8329
|
-
if (endpoint.transport === "claude_stream_json") {
|
|
8330
|
-
return isClaudeStreamJsonAgentAlive(buildClaudeEndpointSessionOptions(endpoint));
|
|
8331
|
-
}
|
|
8332
|
-
const sessionId = endpoint.sessionId ?? (typeof endpoint.metadata?.tmuxSession === "string" ? String(endpoint.metadata.tmuxSession) : null);
|
|
8333
|
-
return sessionId ? isLocalAgentSessionAlive(sessionId) : false;
|
|
8334
|
-
}
|
|
8335
|
-
async function readBrokerMessagesSince(sinceSeconds) {
|
|
8336
|
-
const response = await fetch(new URL("/v1/snapshot", resolveBrokerUrl()));
|
|
8337
|
-
if (!response.ok) {
|
|
8338
|
-
throw new Error(`Broker snapshot failed: ${response.status} ${response.statusText}`);
|
|
8339
|
-
}
|
|
8340
|
-
const snapshot = await response.json();
|
|
8341
|
-
return Object.values(snapshot.messages).filter((message) => normalizeBrokerTimestamp(message.createdAt) >= sinceSeconds).sort((lhs, rhs) => normalizeBrokerTimestamp(lhs.createdAt) - normalizeBrokerTimestamp(rhs.createdAt));
|
|
8342
|
-
}
|
|
8343
6743
|
function buildLocalAgentSystemPrompt(agentName, projectName, projectPath, options = {}) {
|
|
8344
6744
|
return renderLocalAgentSystemPromptTemplate(buildLocalAgentSystemPromptTemplate(), buildLocalAgentTemplateContext(agentName, projectName, projectPath), options);
|
|
8345
6745
|
}
|
|
8346
6746
|
function buildLocalAgentInitialMessage(projectName, agentName) {
|
|
8347
6747
|
return `You are now online as the ${agentName} relay agent for ${projectName}. Announce yourself on the relay with: ${brokerRelayCommand()} send --as ${agentName} "relay agent online \u2014 ready to assist with ${projectName}"`;
|
|
8348
6748
|
}
|
|
8349
|
-
function buildLocalAgentDirectInvocationPrompt(agentName, invocation) {
|
|
8350
|
-
const contextLines = Object.entries(invocation.context ?? {}).map(([key, value]) => `- ${key}: ${String(value)}`);
|
|
8351
|
-
const collaborationContract = buildCollaborationContractPrompt(agentName);
|
|
8352
|
-
const collaborationContext = buildInvocationCollaborationContextPrompt(invocation);
|
|
8353
|
-
const actionRules = invocation.action === "execute" ? "You may inspect and modify the workspace when needed. End with the concise broker-visible reply for the requester." : "Do not modify files unless the request explicitly requires it. End with the concise broker-visible reply for the requester.";
|
|
8354
|
-
return [
|
|
8355
|
-
`OpenScout invocation for ${agentName}.`,
|
|
8356
|
-
`Requester: ${invocation.requesterId}.`,
|
|
8357
|
-
`Action: ${invocation.action}.`,
|
|
8358
|
-
invocation.conversationId ? `Conversation: ${invocation.conversationId}.` : undefined,
|
|
8359
|
-
invocation.messageId ? `Message: ${invocation.messageId}.` : undefined,
|
|
8360
|
-
"",
|
|
8361
|
-
actionRules,
|
|
8362
|
-
collaborationContract,
|
|
8363
|
-
"Return only the reply that should be delivered back through the broker.",
|
|
8364
|
-
"",
|
|
8365
|
-
collaborationContext,
|
|
8366
|
-
contextLines.length > 0 ? `Context:
|
|
8367
|
-
${contextLines.join(`
|
|
8368
|
-
`)}` : undefined,
|
|
8369
|
-
"Task:",
|
|
8370
|
-
invocation.task
|
|
8371
|
-
].filter((value) => Boolean(value && value.length > 0)).join(`
|
|
8372
|
-
`);
|
|
8373
|
-
}
|
|
8374
|
-
function buildAttachedSessionInvocationPrompt(invocation) {
|
|
8375
|
-
const contextLines = Object.entries(invocation.context ?? {}).map(([key, value]) => `- ${key}: ${String(value)}`);
|
|
8376
|
-
return [
|
|
8377
|
-
`Scout message from ${invocation.requesterId}.`,
|
|
8378
|
-
invocation.conversationId ? `Conversation: ${invocation.conversationId}.` : undefined,
|
|
8379
|
-
invocation.messageId ? `Reply-To Message: ${invocation.messageId}.` : undefined,
|
|
8380
|
-
invocation.action !== "consult" ? `Requested action: ${invocation.action}.` : undefined,
|
|
8381
|
-
"Treat this as a direct message to the current session and reply normally as yourself in this session.",
|
|
8382
|
-
contextLines.length > 0 ? `Context:
|
|
8383
|
-
${contextLines.join(`
|
|
8384
|
-
`)}` : undefined,
|
|
8385
|
-
"",
|
|
8386
|
-
invocation.task
|
|
8387
|
-
].filter((value) => Boolean(value && value.length > 0)).join(`
|
|
8388
|
-
`);
|
|
8389
|
-
}
|
|
8390
|
-
function buildLocalAgentNudge(agentName, invocation, flightId) {
|
|
8391
|
-
const relayCommand = brokerRelayCommand();
|
|
8392
|
-
const parts = [
|
|
8393
|
-
`New broker ask from ${invocation.requesterId}.`,
|
|
8394
|
-
`Task: ${invocation.task}`,
|
|
8395
|
-
"Follow the OpenScout collaboration contract: answer directly if you can, otherwise make the next owner explicit and avoid broad wakeups."
|
|
8396
|
-
];
|
|
8397
|
-
if (invocation.context && Object.keys(invocation.context).length > 0) {
|
|
8398
|
-
parts.push(`Context: ${JSON.stringify(invocation.context)}`);
|
|
8399
|
-
}
|
|
8400
|
-
parts.push(`Read recent context if needed: ${relayCommand} read -n 20 --as ${agentName}.`);
|
|
8401
|
-
parts.push(`Reply with: ${relayCommand} send --as ${agentName} "[ask:${flightId}] @${invocation.requesterId} <your response>"`);
|
|
8402
|
-
return parts.join(" ");
|
|
8403
|
-
}
|
|
8404
|
-
function stripLocalAgentReplyMetadata(body, flightId, asker) {
|
|
8405
|
-
return body.replace(new RegExp(`\\[ask:${escapeRegExp(flightId)}\\]`, "g"), "").replace(new RegExp(`@${escapeRegExp(asker)}`, "g"), "").trim();
|
|
8406
|
-
}
|
|
8407
|
-
async function sendLocalAgentPrompt(agentName, record, prompt) {
|
|
8408
|
-
if (normalizeLocalAgentHarness(record.harness) === "codex") {
|
|
8409
|
-
const promptPipe = join8(relayAgentRuntimeDirectory(agentName), "prompt.pipe");
|
|
8410
|
-
await writeFile5(promptPipe, prompt.trim() + "\x00");
|
|
8411
|
-
return;
|
|
8412
|
-
}
|
|
8413
|
-
sendTmuxPrompt(record.tmuxSession, prompt);
|
|
8414
|
-
}
|
|
8415
|
-
function sendTmuxPrompt(sessionName, prompt) {
|
|
8416
|
-
const bufferName = `openscout-prompt-${randomUUID2()}`;
|
|
8417
|
-
try {
|
|
8418
|
-
execFileSync3("tmux", ["load-buffer", "-b", bufferName, "-"], {
|
|
8419
|
-
stdio: "pipe",
|
|
8420
|
-
input: prompt
|
|
8421
|
-
});
|
|
8422
|
-
execFileSync3("tmux", ["paste-buffer", "-d", "-b", bufferName, "-t", sessionName], {
|
|
8423
|
-
stdio: "pipe"
|
|
8424
|
-
});
|
|
8425
|
-
execFileSync3("tmux", ["send-keys", "-t", sessionName, "Enter"], { stdio: "pipe" });
|
|
8426
|
-
} catch (error) {
|
|
8427
|
-
try {
|
|
8428
|
-
execFileSync3("tmux", ["delete-buffer", "-b", bufferName], { stdio: "pipe" });
|
|
8429
|
-
} catch {}
|
|
8430
|
-
throw error;
|
|
8431
|
-
}
|
|
8432
|
-
}
|
|
8433
6749
|
function shellQuoteArguments(args) {
|
|
8434
6750
|
return args.map((arg) => JSON.stringify(arg)).join(" ");
|
|
8435
6751
|
}
|
|
@@ -9125,110 +7441,6 @@ async function ensureLocalAgentBindingOnline(agentId, nodeId, options = {}) {
|
|
|
9125
7441
|
const onlineRecord = await ensureLocalAgentOnline(agentId, recordForHarness(localAgentRecordFromRelayAgentOverride(agentId, override), options.harness));
|
|
9126
7442
|
return buildLocalAgentBinding(agentId, onlineRecord, isLocalAgentRecordOnline(agentId, onlineRecord), nodeId, "relay-agent-registry");
|
|
9127
7443
|
}
|
|
9128
|
-
async function invokeLocalAgentEndpoint(endpoint, invocation) {
|
|
9129
|
-
const agentRuntimeId = endpoint.agentId;
|
|
9130
|
-
const definitionId = String(endpoint.metadata?.definitionId ?? endpoint.metadata?.agentName ?? endpoint.agentId);
|
|
9131
|
-
const prompt = endpointInvocationPrompt(endpoint, definitionId, invocation);
|
|
9132
|
-
const registry = await readLocalAgentRegistry();
|
|
9133
|
-
const existing = registry[agentRuntimeId];
|
|
9134
|
-
if (!existing && endpoint.transport === "codex_app_server") {
|
|
9135
|
-
await ensureLocalSessionEndpointOnline(endpoint);
|
|
9136
|
-
const invoke = isSessionBackedEndpoint(endpoint) ? sendCodexAppServerAgent : invokeCodexAppServerAgent;
|
|
9137
|
-
const result = await invoke({
|
|
9138
|
-
...buildCodexEndpointSessionOptions(endpoint),
|
|
9139
|
-
prompt,
|
|
9140
|
-
timeoutMs: invocation.timeoutMs
|
|
9141
|
-
});
|
|
9142
|
-
return {
|
|
9143
|
-
output: result.output
|
|
9144
|
-
};
|
|
9145
|
-
}
|
|
9146
|
-
if (!existing && endpoint.transport === "claude_stream_json") {
|
|
9147
|
-
await ensureLocalSessionEndpointOnline(endpoint);
|
|
9148
|
-
const result = await invokeClaudeStreamJsonAgent({
|
|
9149
|
-
...buildClaudeEndpointSessionOptions(endpoint),
|
|
9150
|
-
prompt,
|
|
9151
|
-
timeoutMs: invocation.timeoutMs
|
|
9152
|
-
});
|
|
9153
|
-
return {
|
|
9154
|
-
output: result.output
|
|
9155
|
-
};
|
|
9156
|
-
}
|
|
9157
|
-
const projectRoot = endpoint.projectRoot ?? endpoint.cwd;
|
|
9158
|
-
const requestedHarness = invocation.execution?.harness;
|
|
9159
|
-
const record = existing ?? (projectRoot ? {
|
|
9160
|
-
definitionId,
|
|
9161
|
-
project: basename3(projectRoot),
|
|
9162
|
-
projectRoot,
|
|
9163
|
-
tmuxSession: String(endpoint.metadata?.tmuxSession ?? `relay-${agentRuntimeId}`),
|
|
9164
|
-
cwd: projectRoot,
|
|
9165
|
-
startedAt: nowSeconds2(),
|
|
9166
|
-
harness: normalizeLocalAgentHarness(typeof endpoint.harness === "string" ? endpoint.harness : undefined),
|
|
9167
|
-
defaultHarness: normalizeLocalAgentHarness(typeof endpoint.harness === "string" ? endpoint.harness : undefined),
|
|
9168
|
-
harnessProfiles: {
|
|
9169
|
-
[normalizeManagedHarness2(typeof endpoint.harness === "string" ? endpoint.harness : undefined, "claude")]: {
|
|
9170
|
-
cwd: projectRoot,
|
|
9171
|
-
sessionId: String(endpoint.sessionId ?? endpoint.metadata?.runtimeInstanceId ?? endpoint.metadata?.runtimeSessionId ?? `relay-${agentRuntimeId}`),
|
|
9172
|
-
transport: normalizeLocalAgentTransport(typeof endpoint.transport === "string" ? endpoint.transport : undefined, normalizeLocalAgentHarness(typeof endpoint.harness === "string" ? endpoint.harness : undefined)),
|
|
9173
|
-
launchArgs: []
|
|
9174
|
-
}
|
|
9175
|
-
},
|
|
9176
|
-
transport: normalizeLocalAgentTransport(typeof endpoint.transport === "string" ? endpoint.transport : undefined, normalizeLocalAgentHarness(typeof endpoint.harness === "string" ? endpoint.harness : undefined)),
|
|
9177
|
-
capabilities: [...DEFAULT_LOCAL_AGENT_CAPABILITIES],
|
|
9178
|
-
launchArgs: []
|
|
9179
|
-
} : null);
|
|
9180
|
-
if (!record) {
|
|
9181
|
-
throw new Error(`Agent ${agentRuntimeId} is not registered and has no project root.`);
|
|
9182
|
-
}
|
|
9183
|
-
const selectedRecord = recordForHarness(record, requestedHarness);
|
|
9184
|
-
const onlineRecord = await ensureLocalAgentOnline(agentRuntimeId, selectedRecord);
|
|
9185
|
-
if (onlineRecord.transport === "codex_app_server") {
|
|
9186
|
-
const result = await invokeCodexAppServerAgent({
|
|
9187
|
-
...buildCodexAgentSessionOptions(agentRuntimeId, onlineRecord, renderLocalAgentSystemPromptTemplate(onlineRecord.systemPrompt || buildLocalAgentSystemPromptTemplate(), buildLocalAgentTemplateContext(definitionId, onlineRecord.project, onlineRecord.cwd), { transport: "codex_app_server" })),
|
|
9188
|
-
prompt,
|
|
9189
|
-
timeoutMs: invocation.timeoutMs
|
|
9190
|
-
});
|
|
9191
|
-
return {
|
|
9192
|
-
output: result.output
|
|
9193
|
-
};
|
|
9194
|
-
}
|
|
9195
|
-
if (onlineRecord.transport === "claude_stream_json") {
|
|
9196
|
-
const result = await invokeClaudeStreamJsonAgent({
|
|
9197
|
-
...buildClaudeAgentSessionOptions(agentRuntimeId, onlineRecord, renderLocalAgentSystemPromptTemplate(onlineRecord.systemPrompt || buildLocalAgentSystemPromptTemplate(), buildLocalAgentTemplateContext(definitionId, onlineRecord.project, onlineRecord.cwd), { transport: "claude_stream_json" })),
|
|
9198
|
-
prompt,
|
|
9199
|
-
timeoutMs: invocation.timeoutMs
|
|
9200
|
-
});
|
|
9201
|
-
return {
|
|
9202
|
-
output: result.output
|
|
9203
|
-
};
|
|
9204
|
-
}
|
|
9205
|
-
const flightId = createLocalAgentFlightId();
|
|
9206
|
-
const askedAt = nowSeconds2();
|
|
9207
|
-
const timeoutSeconds = invocation.timeoutMs ? Math.max(30, Math.floor(invocation.timeoutMs / 1000)) : 300;
|
|
9208
|
-
await sendLocalAgentPrompt(agentRuntimeId, onlineRecord, buildLocalAgentNudge(definitionId, invocation, flightId));
|
|
9209
|
-
const deadline = Date.now() + timeoutSeconds * 1000;
|
|
9210
|
-
while (Date.now() <= deadline) {
|
|
9211
|
-
const messages2 = await readBrokerMessagesSince(askedAt - 1);
|
|
9212
|
-
for (let index = messages2.length - 1;index >= 0; index -= 1) {
|
|
9213
|
-
const message = messages2[index];
|
|
9214
|
-
if (message.actorId !== agentRuntimeId)
|
|
9215
|
-
continue;
|
|
9216
|
-
if (!message.body.includes(`[ask:${flightId}]`))
|
|
9217
|
-
continue;
|
|
9218
|
-
return {
|
|
9219
|
-
output: stripLocalAgentReplyMetadata(message.body, flightId, invocation.requesterId)
|
|
9220
|
-
};
|
|
9221
|
-
}
|
|
9222
|
-
await sleep2(500);
|
|
9223
|
-
}
|
|
9224
|
-
throw new Error(`Timed out after ${timeoutSeconds}s waiting for ${agentRuntimeId}.`);
|
|
9225
|
-
}
|
|
9226
|
-
function shouldDisableGeneratedCodexEndpoint(endpoint) {
|
|
9227
|
-
if (endpoint.transport !== "codex_exec") {
|
|
9228
|
-
return false;
|
|
9229
|
-
}
|
|
9230
|
-
return endpoint.metadata?.source === "scout-app";
|
|
9231
|
-
}
|
|
9232
7444
|
var MODULE_DIRECTORY, OPENSCOUT_REPO_ROOT, DEFAULT_LOCAL_AGENT_CAPABILITIES, DEFAULT_LOCAL_AGENT_HARNESS = "claude", SUPPORTED_LOCAL_AGENT_HARNESSES;
|
|
9233
7445
|
var init_local_agents = __esm(async () => {
|
|
9234
7446
|
init_src();
|
|
@@ -9326,19 +7538,41 @@ function resolveScoutAgentName(agentName) {
|
|
|
9326
7538
|
}
|
|
9327
7539
|
return resolveOperatorName();
|
|
9328
7540
|
}
|
|
9329
|
-
|
|
7541
|
+
function resolveConfiguredSenderIdForProjectRoot(overrides, projectRoot) {
|
|
7542
|
+
for (const [agentId, override] of Object.entries(overrides)) {
|
|
7543
|
+
if (BUILT_IN_AGENT_DEFINITION_IDS.has(agentId)) {
|
|
7544
|
+
continue;
|
|
7545
|
+
}
|
|
7546
|
+
if (!override.projectRoot || override.projectRoot !== projectRoot) {
|
|
7547
|
+
continue;
|
|
7548
|
+
}
|
|
7549
|
+
return agentId;
|
|
7550
|
+
}
|
|
7551
|
+
return null;
|
|
7552
|
+
}
|
|
7553
|
+
async function inferSenderIdForProjectRoot(projectRoot) {
|
|
7554
|
+
const overrides = await readRelayAgentOverrides();
|
|
7555
|
+
const configuredSenderId = resolveConfiguredSenderIdForProjectRoot(overrides, projectRoot);
|
|
7556
|
+
if (configuredSenderId) {
|
|
7557
|
+
return configuredSenderId;
|
|
7558
|
+
}
|
|
7559
|
+
const projectConfig = await readProjectConfig(projectRoot);
|
|
7560
|
+
const configuredDefinitionId = normalizeAgentSelectorSegment(projectConfig?.agent?.id?.trim() ?? "");
|
|
7561
|
+
const definitionId = configuredDefinitionId || normalizeAgentSelectorSegment(basename4(projectRoot)) || "agent";
|
|
7562
|
+
return buildRelayAgentInstance(definitionId, projectRoot).id;
|
|
7563
|
+
}
|
|
7564
|
+
async function resolveScoutSenderId(agentName, currentDirectory, env = process.env) {
|
|
9330
7565
|
if (agentName?.trim()) {
|
|
9331
7566
|
return agentName.trim();
|
|
9332
7567
|
}
|
|
9333
|
-
if (
|
|
9334
|
-
return
|
|
7568
|
+
if (env.OPENSCOUT_AGENT?.trim()) {
|
|
7569
|
+
return env.OPENSCOUT_AGENT.trim();
|
|
7570
|
+
}
|
|
7571
|
+
const projectRoot = await findNearestProjectRoot(currentDirectory);
|
|
7572
|
+
if (!projectRoot) {
|
|
7573
|
+
return resolveOperatorName();
|
|
9335
7574
|
}
|
|
9336
|
-
|
|
9337
|
-
const { resolveLocalAgentByName: resolveLocalAgentByName2 } = await init_local_agents().then(() => exports_local_agents);
|
|
9338
|
-
const projectRoot = await findNearestProjectRoot2(currentDirectory) ?? currentDirectory;
|
|
9339
|
-
const projectName = basename4(projectRoot);
|
|
9340
|
-
const agent = await resolveLocalAgentByName2(projectName);
|
|
9341
|
-
return agent?.agentId ?? projectName;
|
|
7575
|
+
return inferSenderIdForProjectRoot(projectRoot);
|
|
9342
7576
|
}
|
|
9343
7577
|
function parseScoutHarness(value) {
|
|
9344
7578
|
const trimmed = value?.trim();
|
|
@@ -9912,14 +8146,17 @@ async function sendScoutMessage(input) {
|
|
|
9912
8146
|
const senderId = await resolveConversationActorId(broker.baseUrl, broker.snapshot, broker.node.id, input.senderId, currentDirectory);
|
|
9913
8147
|
const availableTargets = (await Promise.all(mentionResolution.resolved.map(async (target) => await ensureTargetRelayAgentRegistered(broker.baseUrl, broker.snapshot, broker.node.id, target.agentId, currentDirectory) ? target : null))).filter((target) => Boolean(target));
|
|
9914
8148
|
const validTargets = [...new Set(availableTargets.map((target) => target.agentId).filter((target) => target !== senderId && Boolean(broker.snapshot.agents[target])))].sort();
|
|
8149
|
+
const unresolvedTargets = mentionResolution.resolved.filter((target) => !validTargets.includes(target.agentId)).map((target) => target.label).concat(mentionResolution.unresolved).concat(mentionResolution.ambiguous.map((entry) => entry.label));
|
|
8150
|
+
if (unresolvedTargets.length > 0) {
|
|
8151
|
+
return { usedBroker: true, invokedTargets: [], unresolvedTargets };
|
|
8152
|
+
}
|
|
9915
8153
|
let conversation;
|
|
9916
8154
|
if (validTargets.length === 1 && !input.channel) {
|
|
9917
8155
|
const dm = await ensureBrokerDirectConversationBetween(broker.baseUrl, broker.snapshot, broker.node.id, senderId, validTargets[0]);
|
|
9918
8156
|
conversation = dm.conversation;
|
|
9919
8157
|
} else {
|
|
9920
|
-
conversation = await ensureBrokerConversation(broker.baseUrl, broker.snapshot, broker.node.id, input.channel, senderId,
|
|
8158
|
+
conversation = await ensureBrokerConversation(broker.baseUrl, broker.snapshot, broker.node.id, input.channel, senderId, validTargets);
|
|
9921
8159
|
}
|
|
9922
|
-
const unresolvedTargets = mentionResolution.resolved.filter((target) => !validTargets.includes(target.agentId)).map((target) => target.label).concat(mentionResolution.unresolved).concat(mentionResolution.ambiguous.map((entry) => entry.label));
|
|
9923
8160
|
const messageId = `m-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
|
|
9924
8161
|
const speechText = input.shouldSpeak ? stripScoutAgentSelectorLabels(input.body) : "";
|
|
9925
8162
|
const returnAddress = buildScoutReturnAddress(broker.snapshot, senderId, {
|
|
@@ -9946,27 +8183,6 @@ async function sendScoutMessage(input) {
|
|
|
9946
8183
|
returnAddress
|
|
9947
8184
|
}
|
|
9948
8185
|
});
|
|
9949
|
-
for (const targetAgentId of validTargets) {
|
|
9950
|
-
await brokerPostJson(broker.baseUrl, scoutBrokerPaths.v1.invocations, {
|
|
9951
|
-
id: `inv-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
9952
|
-
requesterId: senderId,
|
|
9953
|
-
requesterNodeId: broker.node.id,
|
|
9954
|
-
targetAgentId,
|
|
9955
|
-
action: "consult",
|
|
9956
|
-
task: input.body,
|
|
9957
|
-
conversationId: conversation.id,
|
|
9958
|
-
messageId,
|
|
9959
|
-
execution: input.executionHarness ? { harness: input.executionHarness } : undefined,
|
|
9960
|
-
ensureAwake: true,
|
|
9961
|
-
stream: false,
|
|
9962
|
-
createdAt: Date.now(),
|
|
9963
|
-
metadata: {
|
|
9964
|
-
source: "scout-cli",
|
|
9965
|
-
relayChannel: input.channel ?? "shared",
|
|
9966
|
-
returnAddress
|
|
9967
|
-
}
|
|
9968
|
-
});
|
|
9969
|
-
}
|
|
9970
8186
|
return { usedBroker: true, invokedTargets: validTargets, unresolvedTargets };
|
|
9971
8187
|
}
|
|
9972
8188
|
async function openScoutPeerSession(input) {
|
|
@@ -10251,7 +8467,7 @@ async function watchScoutMessages(options) {
|
|
|
10251
8467
|
return;
|
|
10252
8468
|
}
|
|
10253
8469
|
const message = event.payload?.message;
|
|
10254
|
-
if (!message || message.conversationId !== conversationId
|
|
8470
|
+
if (!message || message.conversationId !== conversationId)
|
|
10255
8471
|
return;
|
|
10256
8472
|
options.onMessage(message);
|
|
10257
8473
|
};
|
|
@@ -10548,13 +8764,15 @@ async function runAskCommand(context, args) {
|
|
|
10548
8764
|
await runAskWithOptions(context, options);
|
|
10549
8765
|
}
|
|
10550
8766
|
async function runAskWithOptions(context, options) {
|
|
8767
|
+
const currentDirectory = options.currentDirectory ?? defaultScoutContextDirectory(context);
|
|
8768
|
+
const senderId = await resolveScoutSenderId(options.agentName, currentDirectory, context.env);
|
|
10551
8769
|
const result = await askScoutQuestion({
|
|
10552
|
-
senderId
|
|
8770
|
+
senderId,
|
|
10553
8771
|
targetLabel: options.targetLabel,
|
|
10554
8772
|
body: options.message,
|
|
10555
8773
|
channel: options.channel,
|
|
10556
8774
|
executionHarness: parseScoutHarness(options.harness),
|
|
10557
|
-
currentDirectory
|
|
8775
|
+
currentDirectory
|
|
10558
8776
|
});
|
|
10559
8777
|
if (!result.usedBroker) {
|
|
10560
8778
|
throw new Error("broker is not reachable");
|
|
@@ -10703,6 +8921,57 @@ function renderScoutActivityList(items) {
|
|
|
10703
8921
|
}
|
|
10704
8922
|
var init_broker = () => {};
|
|
10705
8923
|
|
|
8924
|
+
// ../../apps/desktop/src/cli/commands/send.ts
|
|
8925
|
+
var exports_send = {};
|
|
8926
|
+
__export(exports_send, {
|
|
8927
|
+
runSendCommand: () => runSendCommand,
|
|
8928
|
+
formatScoutSendRoutingError: () => formatScoutSendRoutingError
|
|
8929
|
+
});
|
|
8930
|
+
function renderTargetLabel(label) {
|
|
8931
|
+
const trimmed = label.trim();
|
|
8932
|
+
if (!trimmed) {
|
|
8933
|
+
return "";
|
|
8934
|
+
}
|
|
8935
|
+
return trimmed.startsWith("@") ? trimmed : `@${trimmed}`;
|
|
8936
|
+
}
|
|
8937
|
+
function formatScoutSendRoutingError(unresolvedTargets) {
|
|
8938
|
+
const rendered = unresolvedTargets.map(renderTargetLabel).filter((label) => label.length > 0);
|
|
8939
|
+
if (rendered.length === 1) {
|
|
8940
|
+
return `target ${rendered[0]} is not uniquely routable; nothing was sent.`;
|
|
8941
|
+
}
|
|
8942
|
+
return `targets ${rendered.join(", ")} are not uniquely routable; nothing was sent.`;
|
|
8943
|
+
}
|
|
8944
|
+
async function runSendCommand(context, args) {
|
|
8945
|
+
const options = parseSendCommandOptions(args, defaultScoutContextDirectory(context));
|
|
8946
|
+
const currentDirectory = options.currentDirectory ?? defaultScoutContextDirectory(context);
|
|
8947
|
+
const senderId = await resolveScoutSenderId(options.agentName, currentDirectory, context.env);
|
|
8948
|
+
const result = await sendScoutMessage({
|
|
8949
|
+
senderId,
|
|
8950
|
+
body: options.message,
|
|
8951
|
+
channel: options.channel,
|
|
8952
|
+
shouldSpeak: options.shouldSpeak,
|
|
8953
|
+
executionHarness: parseScoutHarness(options.harness),
|
|
8954
|
+
currentDirectory: options.currentDirectory
|
|
8955
|
+
});
|
|
8956
|
+
if (!result.usedBroker) {
|
|
8957
|
+
throw new Error("broker is not reachable");
|
|
8958
|
+
}
|
|
8959
|
+
if (result.unresolvedTargets.length > 0) {
|
|
8960
|
+
throw new Error(formatScoutSendRoutingError(result.unresolvedTargets));
|
|
8961
|
+
}
|
|
8962
|
+
context.output.writeValue({
|
|
8963
|
+
message: options.message,
|
|
8964
|
+
invokedTargets: result.invokedTargets,
|
|
8965
|
+
unresolvedTargets: result.unresolvedTargets
|
|
8966
|
+
}, renderScoutMessagePostResult);
|
|
8967
|
+
}
|
|
8968
|
+
var init_send = __esm(async () => {
|
|
8969
|
+
init_context();
|
|
8970
|
+
init_options();
|
|
8971
|
+
init_broker();
|
|
8972
|
+
await init_service();
|
|
8973
|
+
});
|
|
8974
|
+
|
|
10706
8975
|
// ../../apps/desktop/src/cli/commands/broadcast.ts
|
|
10707
8976
|
var exports_broadcast = {};
|
|
10708
8977
|
__export(exports_broadcast, {
|
|
@@ -10710,15 +8979,20 @@ __export(exports_broadcast, {
|
|
|
10710
8979
|
});
|
|
10711
8980
|
async function runBroadcastCommand(context, args) {
|
|
10712
8981
|
const options = parseSendCommandOptions(args, defaultScoutContextDirectory(context));
|
|
8982
|
+
const currentDirectory = options.currentDirectory ?? defaultScoutContextDirectory(context);
|
|
8983
|
+
const senderId = await resolveScoutSenderId(options.agentName, currentDirectory, context.env);
|
|
10713
8984
|
const result = await sendScoutMessage({
|
|
10714
|
-
senderId
|
|
8985
|
+
senderId,
|
|
10715
8986
|
body: `@all ${options.message}`,
|
|
10716
8987
|
executionHarness: parseScoutHarness(options.harness),
|
|
10717
|
-
currentDirectory
|
|
8988
|
+
currentDirectory
|
|
10718
8989
|
});
|
|
10719
8990
|
if (!result.usedBroker) {
|
|
10720
8991
|
throw new Error("broker is not reachable");
|
|
10721
8992
|
}
|
|
8993
|
+
if (result.unresolvedTargets.length > 0) {
|
|
8994
|
+
throw new Error(formatScoutSendRoutingError(result.unresolvedTargets));
|
|
8995
|
+
}
|
|
10722
8996
|
context.output.writeValue({
|
|
10723
8997
|
message: options.message,
|
|
10724
8998
|
invokedTargets: result.invokedTargets,
|
|
@@ -10729,7 +9003,10 @@ var init_broadcast = __esm(async () => {
|
|
|
10729
9003
|
init_context();
|
|
10730
9004
|
init_options();
|
|
10731
9005
|
init_broker();
|
|
10732
|
-
await
|
|
9006
|
+
await __promiseAll([
|
|
9007
|
+
init_service(),
|
|
9008
|
+
init_send()
|
|
9009
|
+
]);
|
|
10733
9010
|
});
|
|
10734
9011
|
|
|
10735
9012
|
// ../runtime/src/relay-agent-cards.ts
|
|
@@ -11822,7 +10099,7 @@ function resolveScoutBinPath(appRoot) {
|
|
|
11822
10099
|
}
|
|
11823
10100
|
return candidates[candidates.length - 1];
|
|
11824
10101
|
}
|
|
11825
|
-
function loadScoutEnvReport(context, currentDirectory) {
|
|
10102
|
+
async function loadScoutEnvReport(context, currentDirectory) {
|
|
11826
10103
|
const appRoot = resolveScoutAppRoot({
|
|
11827
10104
|
currentDirectory,
|
|
11828
10105
|
env: context.env
|
|
@@ -11840,6 +10117,8 @@ function loadScoutEnvReport(context, currentDirectory) {
|
|
|
11840
10117
|
const binPath = resolveScoutBinPath(appRoot);
|
|
11841
10118
|
const scoutPath = resolveCommandOnPath("scout", context.env);
|
|
11842
10119
|
const fallbackCommand = `bun ${binPath}`;
|
|
10120
|
+
const resolvedId = await resolveScoutSenderId(null, currentDirectory, context.env);
|
|
10121
|
+
const projectRoot = await findNearestProjectRoot(currentDirectory);
|
|
11843
10122
|
return {
|
|
11844
10123
|
executable: {
|
|
11845
10124
|
command: scoutPath ? "scout" : fallbackCommand,
|
|
@@ -11847,8 +10126,9 @@ function loadScoutEnvReport(context, currentDirectory) {
|
|
|
11847
10126
|
scoutPath
|
|
11848
10127
|
},
|
|
11849
10128
|
agent: {
|
|
11850
|
-
resolvedId
|
|
11851
|
-
envAgent: context.env.OPENSCOUT_AGENT?.trim() || null
|
|
10129
|
+
resolvedId,
|
|
10130
|
+
envAgent: context.env.OPENSCOUT_AGENT?.trim() || null,
|
|
10131
|
+
projectRoot
|
|
11852
10132
|
},
|
|
11853
10133
|
context: {
|
|
11854
10134
|
cwd: context.cwd,
|
|
@@ -11875,10 +10155,11 @@ function renderScoutEnvReport(report) {
|
|
|
11875
10155
|
}
|
|
11876
10156
|
async function runEnvCommand(context, args) {
|
|
11877
10157
|
const options = parseContextRootCommandOptions("env", args, defaultScoutContextDirectory(context));
|
|
11878
|
-
const report = loadScoutEnvReport(context, options.currentDirectory);
|
|
10158
|
+
const report = await loadScoutEnvReport(context, options.currentDirectory);
|
|
11879
10159
|
context.output.writeValue(report, renderScoutEnvReport);
|
|
11880
10160
|
}
|
|
11881
10161
|
var init_env = __esm(async () => {
|
|
10162
|
+
init_setup();
|
|
11882
10163
|
init_context();
|
|
11883
10164
|
init_options();
|
|
11884
10165
|
init_paths2();
|
|
@@ -11907,6 +10188,273 @@ var init_latest = __esm(async () => {
|
|
|
11907
10188
|
await init_service();
|
|
11908
10189
|
});
|
|
11909
10190
|
|
|
10191
|
+
// ../../apps/desktop/src/cli/commands/menu.ts
|
|
10192
|
+
var exports_menu = {};
|
|
10193
|
+
__export(exports_menu, {
|
|
10194
|
+
runMenuCommand: () => runMenuCommand,
|
|
10195
|
+
renderMenuCommandHelp: () => renderMenuCommandHelp,
|
|
10196
|
+
parseMenuCommand: () => parseMenuCommand
|
|
10197
|
+
});
|
|
10198
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
10199
|
+
import { existsSync as existsSync10 } from "fs";
|
|
10200
|
+
import { homedir as homedir7 } from "os";
|
|
10201
|
+
import { dirname as dirname10, join as join15, resolve as resolve8 } from "path";
|
|
10202
|
+
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
10203
|
+
function renderMenuCommandHelp() {
|
|
10204
|
+
return [
|
|
10205
|
+
"scout menu \u2014 macOS menu bar app",
|
|
10206
|
+
"",
|
|
10207
|
+
"Usage:",
|
|
10208
|
+
" scout menu",
|
|
10209
|
+
" scout menu launch",
|
|
10210
|
+
" scout menu status",
|
|
10211
|
+
" scout menu restart",
|
|
10212
|
+
" scout menu quit",
|
|
10213
|
+
" scout menu build",
|
|
10214
|
+
" scout menu dmg",
|
|
10215
|
+
"",
|
|
10216
|
+
"Aliases:",
|
|
10217
|
+
" launch = open = start",
|
|
10218
|
+
" quit = stop",
|
|
10219
|
+
"",
|
|
10220
|
+
"Behavior:",
|
|
10221
|
+
" On macOS, `scout menu` launches the installed OpenScout menu app when available.",
|
|
10222
|
+
" When run inside an OpenScout repo checkout, it prefers `apps/macos/bin/openscout-menu.ts`",
|
|
10223
|
+
" so launch/build/restart reuse the repo helper and auto-build the app bundle if needed.",
|
|
10224
|
+
"",
|
|
10225
|
+
"Examples:",
|
|
10226
|
+
" scout menu",
|
|
10227
|
+
" scout menu status",
|
|
10228
|
+
" scout menu restart",
|
|
10229
|
+
" scout menu build --version 0.2.16"
|
|
10230
|
+
].join(`
|
|
10231
|
+
`);
|
|
10232
|
+
}
|
|
10233
|
+
function parseMenuCommand(args) {
|
|
10234
|
+
const [first, ...rest] = args;
|
|
10235
|
+
if (!first) {
|
|
10236
|
+
return { action: "launch", passthroughArgs: [] };
|
|
10237
|
+
}
|
|
10238
|
+
if (first.startsWith("-")) {
|
|
10239
|
+
return { action: "launch", passthroughArgs: args };
|
|
10240
|
+
}
|
|
10241
|
+
switch (first) {
|
|
10242
|
+
case "launch":
|
|
10243
|
+
case "open":
|
|
10244
|
+
case "start":
|
|
10245
|
+
return { action: "launch", passthroughArgs: rest };
|
|
10246
|
+
case "restart":
|
|
10247
|
+
return { action: "restart", passthroughArgs: rest };
|
|
10248
|
+
case "quit":
|
|
10249
|
+
case "stop":
|
|
10250
|
+
return { action: "quit", passthroughArgs: rest };
|
|
10251
|
+
case "status":
|
|
10252
|
+
return { action: "status", passthroughArgs: rest };
|
|
10253
|
+
case "build":
|
|
10254
|
+
return { action: "build", passthroughArgs: rest };
|
|
10255
|
+
case "dmg":
|
|
10256
|
+
return { action: "dmg", passthroughArgs: rest };
|
|
10257
|
+
default:
|
|
10258
|
+
throw new ScoutCliError(`unknown subcommand: ${first} (try: scout menu)`);
|
|
10259
|
+
}
|
|
10260
|
+
}
|
|
10261
|
+
function runProcess(command, args, options) {
|
|
10262
|
+
const result = spawnSync2(command, args, {
|
|
10263
|
+
cwd: options.cwd,
|
|
10264
|
+
env: options.env,
|
|
10265
|
+
encoding: "utf8"
|
|
10266
|
+
});
|
|
10267
|
+
if (result.error) {
|
|
10268
|
+
throw new ScoutCliError(`failed to run ${command}: ${result.error.message}`);
|
|
10269
|
+
}
|
|
10270
|
+
const stdout = result.stdout.trim();
|
|
10271
|
+
const stderr = result.stderr.trim();
|
|
10272
|
+
const ok = (result.status ?? 1) === 0;
|
|
10273
|
+
if (!ok && !options.allowFailure) {
|
|
10274
|
+
const detail = stderr || stdout || `${command} ${args.join(" ")} failed`;
|
|
10275
|
+
throw new ScoutCliError(detail);
|
|
10276
|
+
}
|
|
10277
|
+
return {
|
|
10278
|
+
ok,
|
|
10279
|
+
stdout,
|
|
10280
|
+
stderr,
|
|
10281
|
+
status: result.status
|
|
10282
|
+
};
|
|
10283
|
+
}
|
|
10284
|
+
function findRepoMenuHelper(startDirectory) {
|
|
10285
|
+
let current = resolve8(startDirectory);
|
|
10286
|
+
while (true) {
|
|
10287
|
+
const candidate = join15(current, "apps", "macos", "bin", "openscout-menu.ts");
|
|
10288
|
+
if (existsSync10(candidate)) {
|
|
10289
|
+
return candidate;
|
|
10290
|
+
}
|
|
10291
|
+
const parent = dirname10(current);
|
|
10292
|
+
if (parent === current) {
|
|
10293
|
+
break;
|
|
10294
|
+
}
|
|
10295
|
+
current = parent;
|
|
10296
|
+
}
|
|
10297
|
+
const sourceRelativeCandidate = fileURLToPath7(new URL("../../../../macos/bin/openscout-menu.ts", import.meta.url));
|
|
10298
|
+
return existsSync10(sourceRelativeCandidate) ? sourceRelativeCandidate : null;
|
|
10299
|
+
}
|
|
10300
|
+
function resolveRepoBundlePath(helperPath) {
|
|
10301
|
+
return resolve8(dirname10(helperPath), "..", "dist", MENU_BUNDLE_NAME);
|
|
10302
|
+
}
|
|
10303
|
+
function isMenuRunning(env) {
|
|
10304
|
+
return runProcess("pgrep", ["-x", MENU_PROCESS_NAME], { env, allowFailure: true }).ok;
|
|
10305
|
+
}
|
|
10306
|
+
function stopRunningMenu(env) {
|
|
10307
|
+
return runProcess("pkill", ["-x", MENU_PROCESS_NAME], { env, allowFailure: true }).ok;
|
|
10308
|
+
}
|
|
10309
|
+
function resolveInstalledMenuBundlePath(env) {
|
|
10310
|
+
const spotlight = runProcess("mdfind", [`kMDItemCFBundleIdentifier == '${MENU_BUNDLE_ID}'`], { env, allowFailure: true });
|
|
10311
|
+
const indexedPath = spotlight.stdout.split(`
|
|
10312
|
+
`).map((line) => line.trim()).find(Boolean);
|
|
10313
|
+
if (indexedPath) {
|
|
10314
|
+
return indexedPath;
|
|
10315
|
+
}
|
|
10316
|
+
for (const candidate of COMMON_MENU_BUNDLE_PATHS) {
|
|
10317
|
+
if (existsSync10(candidate)) {
|
|
10318
|
+
return candidate;
|
|
10319
|
+
}
|
|
10320
|
+
}
|
|
10321
|
+
return null;
|
|
10322
|
+
}
|
|
10323
|
+
function openInstalledMenuApp(bundlePath, env) {
|
|
10324
|
+
const bundleAttempts = [
|
|
10325
|
+
{ command: "open", args: ["-b", MENU_BUNDLE_ID] }
|
|
10326
|
+
];
|
|
10327
|
+
if (bundlePath) {
|
|
10328
|
+
bundleAttempts.push({ command: "open", args: [bundlePath] });
|
|
10329
|
+
}
|
|
10330
|
+
let lastFailure = "OpenScout Menu is not installed.";
|
|
10331
|
+
for (const attempt of bundleAttempts) {
|
|
10332
|
+
const result = runProcess(attempt.command, attempt.args, { env, allowFailure: true });
|
|
10333
|
+
if (result.ok) {
|
|
10334
|
+
return;
|
|
10335
|
+
}
|
|
10336
|
+
lastFailure = result.stderr || result.stdout || lastFailure;
|
|
10337
|
+
}
|
|
10338
|
+
throw new ScoutCliError(`${lastFailure} Run this command from the OpenScout repo to auto-build the menu app, or install the app first.`);
|
|
10339
|
+
}
|
|
10340
|
+
function renderMenuResult(result) {
|
|
10341
|
+
if (result.action === "status") {
|
|
10342
|
+
const lines2 = [
|
|
10343
|
+
`Installed: ${result.installed ? "yes" : "no"}`,
|
|
10344
|
+
`Running: ${result.running ? "yes" : "no"}`
|
|
10345
|
+
];
|
|
10346
|
+
if (result.bundlePath) {
|
|
10347
|
+
lines2.splice(1, 0, `Bundle: ${result.bundlePath}`);
|
|
10348
|
+
}
|
|
10349
|
+
if (result.helperPath) {
|
|
10350
|
+
lines2.push(`Helper: ${result.helperPath}`);
|
|
10351
|
+
}
|
|
10352
|
+
return lines2.join(`
|
|
10353
|
+
`);
|
|
10354
|
+
}
|
|
10355
|
+
const lines = [result.message];
|
|
10356
|
+
if (result.bundlePath) {
|
|
10357
|
+
lines.push(`Bundle: ${result.bundlePath}`);
|
|
10358
|
+
}
|
|
10359
|
+
return lines.join(`
|
|
10360
|
+
`);
|
|
10361
|
+
}
|
|
10362
|
+
function renderActionMessage(action) {
|
|
10363
|
+
switch (action) {
|
|
10364
|
+
case "build":
|
|
10365
|
+
return "Built the OpenScout menu app bundle.";
|
|
10366
|
+
case "dmg":
|
|
10367
|
+
return "Built the OpenScout menu app DMG.";
|
|
10368
|
+
case "restart":
|
|
10369
|
+
return "Restarted the OpenScout menu app.";
|
|
10370
|
+
case "quit":
|
|
10371
|
+
return "Stopped the OpenScout menu app.";
|
|
10372
|
+
case "status":
|
|
10373
|
+
return "Checked the OpenScout menu app status.";
|
|
10374
|
+
case "launch":
|
|
10375
|
+
default:
|
|
10376
|
+
return "Opened the OpenScout menu app.";
|
|
10377
|
+
}
|
|
10378
|
+
}
|
|
10379
|
+
function runWithRepoHelper(context, helperPath, command) {
|
|
10380
|
+
runProcess(process.execPath, [helperPath, command.action, ...command.passthroughArgs], {
|
|
10381
|
+
cwd: defaultScoutContextDirectory(context),
|
|
10382
|
+
env: context.env
|
|
10383
|
+
});
|
|
10384
|
+
const bundlePath = resolveRepoBundlePath(helperPath);
|
|
10385
|
+
const running = command.action === "quit" ? false : isMenuRunning(context.env);
|
|
10386
|
+
const installed = existsSync10(bundlePath) || running;
|
|
10387
|
+
return {
|
|
10388
|
+
action: command.action,
|
|
10389
|
+
mode: "repo-helper",
|
|
10390
|
+
bundleId: MENU_BUNDLE_ID,
|
|
10391
|
+
bundlePath,
|
|
10392
|
+
helperPath,
|
|
10393
|
+
installed,
|
|
10394
|
+
running,
|
|
10395
|
+
message: renderActionMessage(command.action)
|
|
10396
|
+
};
|
|
10397
|
+
}
|
|
10398
|
+
function runWithInstalledApp(context, command) {
|
|
10399
|
+
const bundlePath = resolveInstalledMenuBundlePath(context.env);
|
|
10400
|
+
if (command.action === "build" || command.action === "dmg") {
|
|
10401
|
+
throw new ScoutCliError(`scout menu ${command.action} requires an OpenScout repo checkout. Run from the repo root or use bun run macos:${command.action}.`);
|
|
10402
|
+
}
|
|
10403
|
+
switch (command.action) {
|
|
10404
|
+
case "launch":
|
|
10405
|
+
if (!isMenuRunning(context.env)) {
|
|
10406
|
+
openInstalledMenuApp(bundlePath, context.env);
|
|
10407
|
+
}
|
|
10408
|
+
break;
|
|
10409
|
+
case "restart":
|
|
10410
|
+
stopRunningMenu(context.env);
|
|
10411
|
+
openInstalledMenuApp(bundlePath, context.env);
|
|
10412
|
+
break;
|
|
10413
|
+
case "quit":
|
|
10414
|
+
stopRunningMenu(context.env);
|
|
10415
|
+
break;
|
|
10416
|
+
case "status":
|
|
10417
|
+
break;
|
|
10418
|
+
default:
|
|
10419
|
+
break;
|
|
10420
|
+
}
|
|
10421
|
+
const running = command.action === "quit" ? false : isMenuRunning(context.env);
|
|
10422
|
+
const installed = Boolean(bundlePath) || running;
|
|
10423
|
+
return {
|
|
10424
|
+
action: command.action,
|
|
10425
|
+
mode: "installed-app",
|
|
10426
|
+
bundleId: MENU_BUNDLE_ID,
|
|
10427
|
+
bundlePath,
|
|
10428
|
+
helperPath: null,
|
|
10429
|
+
installed,
|
|
10430
|
+
running,
|
|
10431
|
+
message: renderActionMessage(command.action)
|
|
10432
|
+
};
|
|
10433
|
+
}
|
|
10434
|
+
async function runMenuCommand(context, args) {
|
|
10435
|
+
if (HELP_FLAGS.has(args[0] ?? "")) {
|
|
10436
|
+
context.output.writeText(renderMenuCommandHelp());
|
|
10437
|
+
return;
|
|
10438
|
+
}
|
|
10439
|
+
if (process.platform !== "darwin") {
|
|
10440
|
+
throw new ScoutCliError("scout menu is only supported on macOS.");
|
|
10441
|
+
}
|
|
10442
|
+
const command = parseMenuCommand(args);
|
|
10443
|
+
const helperPath = findRepoMenuHelper(defaultScoutContextDirectory(context));
|
|
10444
|
+
const result = helperPath ? runWithRepoHelper(context, helperPath, command) : runWithInstalledApp(context, command);
|
|
10445
|
+
context.output.writeValue(result, renderMenuResult);
|
|
10446
|
+
}
|
|
10447
|
+
var MENU_BUNDLE_ID = "com.openscout.menu", MENU_BUNDLE_NAME = "OpenScoutMenu.app", MENU_PROCESS_NAME = "OpenScoutMenu", HELP_FLAGS, COMMON_MENU_BUNDLE_PATHS;
|
|
10448
|
+
var init_menu = __esm(() => {
|
|
10449
|
+
init_context();
|
|
10450
|
+
init_errors();
|
|
10451
|
+
HELP_FLAGS = new Set(["help", "--help", "-h"]);
|
|
10452
|
+
COMMON_MENU_BUNDLE_PATHS = [
|
|
10453
|
+
join15("/Applications", MENU_BUNDLE_NAME),
|
|
10454
|
+
join15(homedir7(), "Applications", MENU_BUNDLE_NAME)
|
|
10455
|
+
];
|
|
10456
|
+
});
|
|
10457
|
+
|
|
11910
10458
|
// ../runtime/src/tailscale.ts
|
|
11911
10459
|
import { readFile as readFile8 } from "fs/promises";
|
|
11912
10460
|
import { execFile } from "child_process";
|
|
@@ -12369,11 +10917,11 @@ var init_mesh = __esm(async () => {
|
|
|
12369
10917
|
});
|
|
12370
10918
|
|
|
12371
10919
|
// ../../apps/desktop/src/core/pairing/runtime/config.ts
|
|
12372
|
-
import { existsSync as
|
|
12373
|
-
import { homedir as
|
|
10920
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
10921
|
+
import { homedir as homedir8 } from "os";
|
|
12374
10922
|
import path from "path";
|
|
12375
10923
|
function pairingPaths() {
|
|
12376
|
-
const rootDir = path.join(
|
|
10924
|
+
const rootDir = path.join(homedir8(), ".scout/pairing");
|
|
12377
10925
|
return {
|
|
12378
10926
|
rootDir,
|
|
12379
10927
|
configPath: path.join(rootDir, "config.json"),
|
|
@@ -12386,7 +10934,7 @@ function pairingPaths() {
|
|
|
12386
10934
|
}
|
|
12387
10935
|
function loadPairingConfig() {
|
|
12388
10936
|
const { configPath } = pairingPaths();
|
|
12389
|
-
if (!
|
|
10937
|
+
if (!existsSync11(configPath)) {
|
|
12390
10938
|
return {};
|
|
12391
10939
|
}
|
|
12392
10940
|
try {
|
|
@@ -14473,11 +13021,11 @@ var init_noise = __esm(() => {
|
|
|
14473
13021
|
});
|
|
14474
13022
|
|
|
14475
13023
|
// ../../apps/desktop/src/core/pairing/runtime/security/identity.ts
|
|
14476
|
-
import { existsSync as
|
|
14477
|
-
import { join as
|
|
14478
|
-
import { homedir as
|
|
13024
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
|
|
13025
|
+
import { join as join16 } from "path";
|
|
13026
|
+
import { homedir as homedir9 } from "os";
|
|
14479
13027
|
function loadOrCreateIdentity() {
|
|
14480
|
-
if (
|
|
13028
|
+
if (existsSync12(IDENTITY_FILE)) {
|
|
14481
13029
|
return loadIdentity();
|
|
14482
13030
|
}
|
|
14483
13031
|
return createAndSaveIdentity();
|
|
@@ -14501,7 +13049,7 @@ function createAndSaveIdentity() {
|
|
|
14501
13049
|
return keyPair;
|
|
14502
13050
|
}
|
|
14503
13051
|
function loadTrustedPeers() {
|
|
14504
|
-
if (!
|
|
13052
|
+
if (!existsSync12(TRUSTED_PEERS_FILE))
|
|
14505
13053
|
return new Map;
|
|
14506
13054
|
const data = JSON.parse(readFileSync7(TRUSTED_PEERS_FILE, "utf8"));
|
|
14507
13055
|
return new Map(data.map((p) => [p.publicKey, p]));
|
|
@@ -14537,9 +13085,9 @@ function hexToBytes2(hex) {
|
|
|
14537
13085
|
var PAIRING_DIR, IDENTITY_FILE, TRUSTED_PEERS_FILE, QR_VERSION = 1, QR_EXPIRY_MS;
|
|
14538
13086
|
var init_identity = __esm(() => {
|
|
14539
13087
|
init_noise();
|
|
14540
|
-
PAIRING_DIR =
|
|
14541
|
-
IDENTITY_FILE =
|
|
14542
|
-
TRUSTED_PEERS_FILE =
|
|
13088
|
+
PAIRING_DIR = join16(homedir9(), ".scout/pairing");
|
|
13089
|
+
IDENTITY_FILE = join16(PAIRING_DIR, "identity.json");
|
|
13090
|
+
TRUSTED_PEERS_FILE = join16(PAIRING_DIR, "trusted-peers.json");
|
|
14543
13091
|
QR_EXPIRY_MS = 5 * 60 * 1000;
|
|
14544
13092
|
});
|
|
14545
13093
|
|
|
@@ -14684,10 +13232,10 @@ var init_security2 = __esm(() => {
|
|
|
14684
13232
|
});
|
|
14685
13233
|
|
|
14686
13234
|
// ../../apps/desktop/src/core/pairing/runtime/runtime-state.ts
|
|
14687
|
-
import { existsSync as
|
|
13235
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync8, renameSync, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
|
|
14688
13236
|
function readPairingRuntimeSnapshot() {
|
|
14689
13237
|
const { runtimeStatePath } = pairingPaths();
|
|
14690
|
-
if (!
|
|
13238
|
+
if (!existsSync13(runtimeStatePath)) {
|
|
14691
13239
|
return null;
|
|
14692
13240
|
}
|
|
14693
13241
|
try {
|
|
@@ -15216,17 +13764,17 @@ var init_registry = __esm(() => {
|
|
|
15216
13764
|
});
|
|
15217
13765
|
|
|
15218
13766
|
// ../agent-sessions/src/adapters/claude-code.ts
|
|
15219
|
-
import { existsSync as
|
|
15220
|
-
import { homedir as
|
|
15221
|
-
import { join as
|
|
13767
|
+
import { existsSync as existsSync14, readdirSync, statSync as statSync2 } from "fs";
|
|
13768
|
+
import { homedir as homedir10 } from "os";
|
|
13769
|
+
import { join as join17 } from "path";
|
|
15222
13770
|
function resolveClaudeResumeContext(config) {
|
|
15223
13771
|
const rawResumeId = config.options?.["resume"];
|
|
15224
13772
|
const resumeId = typeof rawResumeId === "string" ? rawResumeId.trim().replace(/\.jsonl$/u, "") : "";
|
|
15225
13773
|
if (!resumeId) {
|
|
15226
13774
|
return null;
|
|
15227
13775
|
}
|
|
15228
|
-
const projectsRoot =
|
|
15229
|
-
if (!
|
|
13776
|
+
const projectsRoot = join17(homedir10(), ".claude", "projects");
|
|
13777
|
+
if (!existsSync14(projectsRoot)) {
|
|
15230
13778
|
return null;
|
|
15231
13779
|
}
|
|
15232
13780
|
let projectSlugs;
|
|
@@ -15236,8 +13784,8 @@ function resolveClaudeResumeContext(config) {
|
|
|
15236
13784
|
return null;
|
|
15237
13785
|
}
|
|
15238
13786
|
for (const slug of projectSlugs) {
|
|
15239
|
-
const sessionPath =
|
|
15240
|
-
if (!
|
|
13787
|
+
const sessionPath = join17(projectsRoot, slug, `${resumeId}.jsonl`);
|
|
13788
|
+
if (!existsSync14(sessionPath)) {
|
|
15241
13789
|
continue;
|
|
15242
13790
|
}
|
|
15243
13791
|
const cwd = decodeClaudeProjectsSlug2(slug);
|
|
@@ -15676,11 +14224,11 @@ Referenced files: ${prompt.files.join(", ")}` });
|
|
|
15676
14224
|
});
|
|
15677
14225
|
}
|
|
15678
14226
|
answerQuestion(answer) {
|
|
15679
|
-
const
|
|
15680
|
-
if (!
|
|
14227
|
+
const resolve9 = this.pendingAnswers.get(answer.blockId);
|
|
14228
|
+
if (!resolve9)
|
|
15681
14229
|
return;
|
|
15682
14230
|
this.pendingAnswers.delete(answer.blockId);
|
|
15683
|
-
|
|
14231
|
+
resolve9(answer.answer);
|
|
15684
14232
|
const turn = this.currentTurn;
|
|
15685
14233
|
if (turn) {
|
|
15686
14234
|
this.emit("event", {
|
|
@@ -15694,8 +14242,8 @@ Referenced files: ${prompt.files.join(", ")}` });
|
|
|
15694
14242
|
}
|
|
15695
14243
|
}
|
|
15696
14244
|
async awaitAndSendAnswer(blockId, toolCallId) {
|
|
15697
|
-
const answer = await new Promise((
|
|
15698
|
-
this.pendingAnswers.set(blockId,
|
|
14245
|
+
const answer = await new Promise((resolve9) => {
|
|
14246
|
+
this.pendingAnswers.set(blockId, resolve9);
|
|
15699
14247
|
});
|
|
15700
14248
|
if (!this.process?.stdin || typeof this.process.stdin === "number")
|
|
15701
14249
|
return;
|
|
@@ -15780,8 +14328,8 @@ Referenced files: ${prompt.files.join(", ")}` });
|
|
|
15780
14328
|
// ../agent-sessions/src/adapters/codex.ts
|
|
15781
14329
|
import { spawn as spawn4 } from "child_process";
|
|
15782
14330
|
import { access as access3, appendFile as appendFile3, constants as constants2, mkdir as mkdir8, readFile as readFile9, rm as rm6, writeFile as writeFile7 } from "fs/promises";
|
|
15783
|
-
import { delimiter as delimiter2, join as
|
|
15784
|
-
import { homedir as
|
|
14331
|
+
import { delimiter as delimiter2, join as join18 } from "path";
|
|
14332
|
+
import { homedir as homedir11 } from "os";
|
|
15785
14333
|
function parseJsonLine2(line) {
|
|
15786
14334
|
try {
|
|
15787
14335
|
return JSON.parse(line);
|
|
@@ -15931,7 +14479,7 @@ async function resolveCodexExecutable2() {
|
|
|
15931
14479
|
"/usr/local/bin"
|
|
15932
14480
|
].filter(Boolean);
|
|
15933
14481
|
for (const directory of [...pathEntries, ...commonDirectories]) {
|
|
15934
|
-
const candidate =
|
|
14482
|
+
const candidate = join18(directory, "codex");
|
|
15935
14483
|
if (await isExecutable2(candidate)) {
|
|
15936
14484
|
return candidate;
|
|
15937
14485
|
}
|
|
@@ -16035,7 +14583,7 @@ var init_codex = __esm(() => {
|
|
|
16035
14583
|
this.pendingRequests.clear();
|
|
16036
14584
|
if (child && child.exitCode === null && !child.killed) {
|
|
16037
14585
|
child.kill("SIGTERM");
|
|
16038
|
-
await new Promise((
|
|
14586
|
+
await new Promise((resolve9) => setTimeout(resolve9, 250));
|
|
16039
14587
|
if (child.exitCode === null && !child.killed) {
|
|
16040
14588
|
child.kill("SIGKILL");
|
|
16041
14589
|
}
|
|
@@ -16044,7 +14592,7 @@ var init_codex = __esm(() => {
|
|
|
16044
14592
|
await this.persistState();
|
|
16045
14593
|
}
|
|
16046
14594
|
get codexOptions() {
|
|
16047
|
-
const runtimeRoot =
|
|
14595
|
+
const runtimeRoot = join18(homedir11(), ".scout/pairing", "codex", this.session.id);
|
|
16048
14596
|
const configuredThreadId = this.config.options?.["threadId"];
|
|
16049
14597
|
const requireExistingThread = this.config.options?.["requireExistingThread"];
|
|
16050
14598
|
const rawLaunchArgs = this.config.options?.["launchArgs"];
|
|
@@ -16054,8 +14602,8 @@ var init_codex = __esm(() => {
|
|
|
16054
14602
|
sessionId: this.session.id,
|
|
16055
14603
|
cwd: this.config.cwd ?? process.cwd(),
|
|
16056
14604
|
systemPrompt: this.systemPrompt,
|
|
16057
|
-
runtimeDirectory:
|
|
16058
|
-
logsDirectory:
|
|
14605
|
+
runtimeDirectory: join18(runtimeRoot, "runtime"),
|
|
14606
|
+
logsDirectory: join18(runtimeRoot, "logs"),
|
|
16059
14607
|
launchArgs,
|
|
16060
14608
|
threadId: typeof configuredThreadId === "string" && configuredThreadId.trim().length > 0 ? configuredThreadId.trim() : undefined,
|
|
16061
14609
|
requireExistingThread: requireExistingThread ?? Boolean(configuredThreadId)
|
|
@@ -16066,16 +14614,16 @@ var init_codex = __esm(() => {
|
|
|
16066
14614
|
return typeof raw === "string" && raw.trim().length > 0 ? raw : "You are a helpful agent working through Pairing.";
|
|
16067
14615
|
}
|
|
16068
14616
|
get threadIdPath() {
|
|
16069
|
-
return
|
|
14617
|
+
return join18(this.codexOptions.runtimeDirectory, "codex-thread-id.txt");
|
|
16070
14618
|
}
|
|
16071
14619
|
get statePath() {
|
|
16072
|
-
return
|
|
14620
|
+
return join18(this.codexOptions.runtimeDirectory, "state.json");
|
|
16073
14621
|
}
|
|
16074
14622
|
get stdoutLogPath() {
|
|
16075
|
-
return
|
|
14623
|
+
return join18(this.codexOptions.logsDirectory, "stdout.log");
|
|
16076
14624
|
}
|
|
16077
14625
|
get stderrLogPath() {
|
|
16078
|
-
return
|
|
14626
|
+
return join18(this.codexOptions.logsDirectory, "stderr.log");
|
|
16079
14627
|
}
|
|
16080
14628
|
enqueue(task) {
|
|
16081
14629
|
const next = this.serialized.then(task, task);
|
|
@@ -16104,7 +14652,7 @@ var init_codex = __esm(() => {
|
|
|
16104
14652
|
const options = this.codexOptions;
|
|
16105
14653
|
await mkdir8(options.runtimeDirectory, { recursive: true });
|
|
16106
14654
|
await mkdir8(options.logsDirectory, { recursive: true });
|
|
16107
|
-
await writeFile7(
|
|
14655
|
+
await writeFile7(join18(options.runtimeDirectory, "prompt.txt"), options.systemPrompt);
|
|
16108
14656
|
const codexExecutable = await resolveCodexExecutable2();
|
|
16109
14657
|
const child = spawn4(codexExecutable, ["app-server", ...options.launchArgs], {
|
|
16110
14658
|
cwd: options.cwd,
|
|
@@ -16821,9 +15369,9 @@ var init_codex = __esm(() => {
|
|
|
16821
15369
|
}
|
|
16822
15370
|
async request(method, params) {
|
|
16823
15371
|
const id = String(this.nextRequestId++);
|
|
16824
|
-
return new Promise((
|
|
15372
|
+
return new Promise((resolve9, reject) => {
|
|
16825
15373
|
this.pendingRequests.set(id, {
|
|
16826
|
-
resolve: (value) =>
|
|
15374
|
+
resolve: (value) => resolve9(value),
|
|
16827
15375
|
reject
|
|
16828
15376
|
});
|
|
16829
15377
|
try {
|
|
@@ -18178,8 +16726,8 @@ var init_echo = __esm(() => {
|
|
|
18178
16726
|
blockId: actionId,
|
|
18179
16727
|
approval: { version: 1, description: `Run echo tool with: ${text}`, risk: "low" }
|
|
18180
16728
|
});
|
|
18181
|
-
const decision = await new Promise((
|
|
18182
|
-
this.pendingApprovals.set(this.approvalKey(turnId, actionId), { resolve:
|
|
16729
|
+
const decision = await new Promise((resolve9) => {
|
|
16730
|
+
this.pendingApprovals.set(this.approvalKey(turnId, actionId), { resolve: resolve9 });
|
|
18183
16731
|
});
|
|
18184
16732
|
if (this.interrupted) {
|
|
18185
16733
|
this.emitTurnEnd(sessionId, turnId, "stopped");
|
|
@@ -18254,7 +16802,7 @@ var init_echo = __esm(() => {
|
|
|
18254
16802
|
delay() {
|
|
18255
16803
|
if (this.stepDelay <= 0)
|
|
18256
16804
|
return Promise.resolve();
|
|
18257
|
-
return new Promise((
|
|
16805
|
+
return new Promise((resolve9) => setTimeout(resolve9, this.stepDelay));
|
|
18258
16806
|
}
|
|
18259
16807
|
};
|
|
18260
16808
|
});
|
|
@@ -18273,8 +16821,8 @@ var init_src2 = __esm(() => {
|
|
|
18273
16821
|
|
|
18274
16822
|
// ../../apps/desktop/src/core/pairing/runtime/bridge/log.ts
|
|
18275
16823
|
import { appendFileSync, mkdirSync as mkdirSync7 } from "fs";
|
|
18276
|
-
import { join as
|
|
18277
|
-
import { homedir as
|
|
16824
|
+
import { join as join19 } from "path";
|
|
16825
|
+
import { homedir as homedir12 } from "os";
|
|
18278
16826
|
function write(level, category, message, data) {
|
|
18279
16827
|
const ts = new Date().toISOString().slice(11, 23);
|
|
18280
16828
|
const lvl = level.toUpperCase().padEnd(5);
|
|
@@ -18290,8 +16838,8 @@ function write(level, category, message, data) {
|
|
|
18290
16838
|
}
|
|
18291
16839
|
var LOG_DIR, LOG_FILE, log;
|
|
18292
16840
|
var init_log = __esm(() => {
|
|
18293
|
-
LOG_DIR =
|
|
18294
|
-
LOG_FILE =
|
|
16841
|
+
LOG_DIR = join19(homedir12(), ".scout/pairing");
|
|
16842
|
+
LOG_FILE = join19(LOG_DIR, "bridge.log");
|
|
18295
16843
|
mkdirSync7(LOG_DIR, { recursive: true });
|
|
18296
16844
|
log = {
|
|
18297
16845
|
debug: (cat, msg, data) => write("debug", cat, msg, data),
|
|
@@ -18367,11 +16915,11 @@ var init_bridge = __esm(() => {
|
|
|
18367
16915
|
});
|
|
18368
16916
|
|
|
18369
16917
|
// ../../apps/desktop/src/core/pairing/runtime/bridge/config.ts
|
|
18370
|
-
import { existsSync as
|
|
18371
|
-
import { join as
|
|
18372
|
-
import { homedir as
|
|
16918
|
+
import { existsSync as existsSync15, readFileSync as readFileSync9 } from "fs";
|
|
16919
|
+
import { join as join20 } from "path";
|
|
16920
|
+
import { homedir as homedir13 } from "os";
|
|
18373
16921
|
function loadConfigFile() {
|
|
18374
|
-
if (!
|
|
16922
|
+
if (!existsSync15(CONFIG_FILE)) {
|
|
18375
16923
|
return {};
|
|
18376
16924
|
}
|
|
18377
16925
|
try {
|
|
@@ -18432,17 +16980,17 @@ var init_config3 = __esm(() => {
|
|
|
18432
16980
|
port: 7888,
|
|
18433
16981
|
secure: true
|
|
18434
16982
|
};
|
|
18435
|
-
CONFIG_DIR =
|
|
18436
|
-
CONFIG_FILE =
|
|
16983
|
+
CONFIG_DIR = join20(homedir13(), ".scout/pairing");
|
|
16984
|
+
CONFIG_FILE = join20(CONFIG_DIR, "config.json");
|
|
18437
16985
|
});
|
|
18438
16986
|
|
|
18439
16987
|
// ../../apps/desktop/src/core/pairing/runtime/bridge/fileserver.ts
|
|
18440
16988
|
import { isAbsolute as isAbsolute2 } from "path";
|
|
18441
|
-
import { homedir as
|
|
16989
|
+
import { homedir as homedir14 } from "os";
|
|
18442
16990
|
function isAllowedPath(filePath) {
|
|
18443
16991
|
if (!isAbsolute2(filePath))
|
|
18444
16992
|
return false;
|
|
18445
|
-
const relToHome = filePath.slice(
|
|
16993
|
+
const relToHome = filePath.slice(homedir14().length + 1);
|
|
18446
16994
|
if (relToHome.startsWith(".") && !relToHome.startsWith(".claude") && !relToHome.startsWith(".scout/pairing")) {
|
|
18447
16995
|
return false;
|
|
18448
16996
|
}
|
|
@@ -18501,16 +17049,16 @@ function serveFile(url) {
|
|
|
18501
17049
|
}
|
|
18502
17050
|
var ALLOWED_ROOTS;
|
|
18503
17051
|
var init_fileserver = __esm(() => {
|
|
18504
|
-
ALLOWED_ROOTS = [
|
|
17052
|
+
ALLOWED_ROOTS = [homedir14(), "/tmp"];
|
|
18505
17053
|
});
|
|
18506
17054
|
|
|
18507
17055
|
// ../../apps/desktop/src/server/db-queries.ts
|
|
18508
17056
|
import { Database } from "bun:sqlite";
|
|
18509
|
-
import { homedir as
|
|
18510
|
-
import { join as
|
|
17057
|
+
import { homedir as homedir15 } from "os";
|
|
17058
|
+
import { join as join21 } from "path";
|
|
18511
17059
|
function resolveDbPath() {
|
|
18512
|
-
const controlHome = process.env.OPENSCOUT_CONTROL_HOME ??
|
|
18513
|
-
return
|
|
17060
|
+
const controlHome = process.env.OPENSCOUT_CONTROL_HOME ?? join21(homedir15(), ".openscout", "control-plane");
|
|
17061
|
+
return join21(controlHome, "control-plane.sqlite");
|
|
18514
17062
|
}
|
|
18515
17063
|
function db() {
|
|
18516
17064
|
if (!_db) {
|
|
@@ -18752,11 +17300,11 @@ function queryMobileAgentDetail(agentId) {
|
|
|
18752
17300
|
}
|
|
18753
17301
|
var _db = null, HOME;
|
|
18754
17302
|
var init_db_queries = __esm(() => {
|
|
18755
|
-
HOME =
|
|
17303
|
+
HOME = homedir15();
|
|
18756
17304
|
});
|
|
18757
17305
|
|
|
18758
17306
|
// ../../apps/desktop/src/core/mobile/service.ts
|
|
18759
|
-
import { basename as basename6, resolve as
|
|
17307
|
+
import { basename as basename6, resolve as resolve9 } from "path";
|
|
18760
17308
|
function normalizeTimestamp(value) {
|
|
18761
17309
|
if (!value)
|
|
18762
17310
|
return null;
|
|
@@ -19145,7 +17693,7 @@ async function createScoutSession(input, currentDirectory, deviceId) {
|
|
|
19145
17693
|
if (!rawWorkspaceId) {
|
|
19146
17694
|
throw new Error(`Invalid workspaceId.`);
|
|
19147
17695
|
}
|
|
19148
|
-
const workspaceRoot =
|
|
17696
|
+
const workspaceRoot = resolve9(rawWorkspaceId);
|
|
19149
17697
|
const projectName = basename6(workspaceRoot) || workspaceRoot;
|
|
19150
17698
|
const workspace = {
|
|
19151
17699
|
id: workspaceRoot,
|
|
@@ -19255,17 +17803,17 @@ async function deriveNewAgentName(projectName, branch, harness) {
|
|
|
19255
17803
|
}
|
|
19256
17804
|
async function createGitWorktree(projectRoot, agentName) {
|
|
19257
17805
|
const { execSync: execSync2 } = await import("child_process");
|
|
19258
|
-
const { join:
|
|
19259
|
-
const { mkdirSync: mkdirSync8, existsSync:
|
|
17806
|
+
const { join: join22 } = await import("path");
|
|
17807
|
+
const { mkdirSync: mkdirSync8, existsSync: existsSync16 } = await import("fs");
|
|
19260
17808
|
try {
|
|
19261
17809
|
execSync2("git rev-parse --git-dir", { cwd: projectRoot, stdio: "pipe" });
|
|
19262
17810
|
} catch {
|
|
19263
17811
|
return null;
|
|
19264
17812
|
}
|
|
19265
17813
|
const branchName = `scout/${agentName}`;
|
|
19266
|
-
const worktreeDir =
|
|
19267
|
-
const worktreePath =
|
|
19268
|
-
if (
|
|
17814
|
+
const worktreeDir = join22(projectRoot, ".scout-worktrees");
|
|
17815
|
+
const worktreePath = join22(worktreeDir, agentName);
|
|
17816
|
+
if (existsSync16(worktreePath)) {
|
|
19269
17817
|
return { path: worktreePath, branch: branchName };
|
|
19270
17818
|
}
|
|
19271
17819
|
mkdirSync8(worktreeDir, { recursive: true });
|
|
@@ -19310,8 +17858,8 @@ var init_service5 = __esm(async () => {
|
|
|
19310
17858
|
// ../../apps/desktop/src/core/pairing/runtime/bridge/server.ts
|
|
19311
17859
|
import { readdirSync as readdirSync2, readFileSync as readFileSync10, realpathSync, statSync as statSync3 } from "fs";
|
|
19312
17860
|
import { execSync as execSync2 } from "child_process";
|
|
19313
|
-
import { basename as basename7, isAbsolute as isAbsolute3, join as
|
|
19314
|
-
import { homedir as
|
|
17861
|
+
import { basename as basename7, isAbsolute as isAbsolute3, join as join22, relative as relative2 } from "path";
|
|
17862
|
+
import { homedir as homedir16 } from "os";
|
|
19315
17863
|
function replaySyncEvents(bridge, sessionId, lastSeq) {
|
|
19316
17864
|
return bridge.replay(sessionId, lastSeq);
|
|
19317
17865
|
}
|
|
@@ -19765,13 +18313,13 @@ function resolveMobileCurrentDirectory() {
|
|
|
19765
18313
|
}
|
|
19766
18314
|
}
|
|
19767
18315
|
function resolveWorkspaceRoot(root) {
|
|
19768
|
-
const expandedRoot = root.replace(/^~/,
|
|
18316
|
+
const expandedRoot = root.replace(/^~/, homedir16());
|
|
19769
18317
|
return realpathSync(expandedRoot);
|
|
19770
18318
|
}
|
|
19771
18319
|
function resolveWorkspacePath(root, requestedPath) {
|
|
19772
18320
|
const normalizedRoot = resolveWorkspaceRoot(root);
|
|
19773
|
-
const expandedPath = requestedPath?.replace(/^~/,
|
|
19774
|
-
const candidate = expandedPath ? isAbsolute3(expandedPath) ? expandedPath :
|
|
18321
|
+
const expandedPath = requestedPath?.replace(/^~/, homedir16());
|
|
18322
|
+
const candidate = expandedPath ? isAbsolute3(expandedPath) ? expandedPath : join22(normalizedRoot, expandedPath) : normalizedRoot;
|
|
19775
18323
|
const resolvedCandidate = realpathSync(candidate);
|
|
19776
18324
|
const rel = relative2(normalizedRoot, resolvedCandidate);
|
|
19777
18325
|
if (rel === "" || !rel.startsWith("..") && !isAbsolute3(rel)) {
|
|
@@ -19786,7 +18334,7 @@ function listDirectories(dirPath) {
|
|
|
19786
18334
|
continue;
|
|
19787
18335
|
if (name === "node_modules" || name === ".build" || name === "target")
|
|
19788
18336
|
continue;
|
|
19789
|
-
const fullPath =
|
|
18337
|
+
const fullPath = join22(dirPath, name);
|
|
19790
18338
|
try {
|
|
19791
18339
|
const stat4 = statSync3(fullPath);
|
|
19792
18340
|
if (!stat4.isDirectory())
|
|
@@ -19809,7 +18357,7 @@ function listDirectories(dirPath) {
|
|
|
19809
18357
|
return entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
19810
18358
|
}
|
|
19811
18359
|
async function discoverSessionFiles(maxAgeDays, limit) {
|
|
19812
|
-
const home =
|
|
18360
|
+
const home = homedir16();
|
|
19813
18361
|
const results = [];
|
|
19814
18362
|
const searchPaths = [
|
|
19815
18363
|
{ pattern: `${home}/.claude/projects`, agent: "claude-code" },
|
|
@@ -34717,8 +33265,8 @@ var init_zod = __esm(() => {
|
|
|
34717
33265
|
// ../../apps/desktop/src/core/pairing/runtime/bridge/router.ts
|
|
34718
33266
|
import { readFileSync as readFileSync11, readdirSync as readdirSync3, realpathSync as realpathSync2, statSync as statSync4 } from "fs";
|
|
34719
33267
|
import { execSync as execSync3 } from "child_process";
|
|
34720
|
-
import { basename as basename8, isAbsolute as isAbsolute4, join as
|
|
34721
|
-
import { homedir as
|
|
33268
|
+
import { basename as basename8, isAbsolute as isAbsolute4, join as join23, relative as relative3 } from "path";
|
|
33269
|
+
import { homedir as homedir17 } from "os";
|
|
34722
33270
|
function resolveMobileCurrentDirectory2() {
|
|
34723
33271
|
const config2 = resolveConfig();
|
|
34724
33272
|
const configuredRoot = config2.workspace?.root;
|
|
@@ -34731,13 +33279,13 @@ function resolveMobileCurrentDirectory2() {
|
|
|
34731
33279
|
}
|
|
34732
33280
|
}
|
|
34733
33281
|
function resolveWorkspaceRoot2(root) {
|
|
34734
|
-
const expandedRoot = root.replace(/^~/,
|
|
33282
|
+
const expandedRoot = root.replace(/^~/, homedir17());
|
|
34735
33283
|
return realpathSync2(expandedRoot);
|
|
34736
33284
|
}
|
|
34737
33285
|
function resolveWorkspacePath2(root, requestedPath) {
|
|
34738
33286
|
const normalizedRoot = resolveWorkspaceRoot2(root);
|
|
34739
|
-
const expandedPath = requestedPath?.replace(/^~/,
|
|
34740
|
-
const candidate = expandedPath ? isAbsolute4(expandedPath) ? expandedPath :
|
|
33287
|
+
const expandedPath = requestedPath?.replace(/^~/, homedir17());
|
|
33288
|
+
const candidate = expandedPath ? isAbsolute4(expandedPath) ? expandedPath : join23(normalizedRoot, expandedPath) : normalizedRoot;
|
|
34741
33289
|
const resolvedCandidate = realpathSync2(candidate);
|
|
34742
33290
|
const rel = relative3(normalizedRoot, resolvedCandidate);
|
|
34743
33291
|
if (rel === "" || !rel.startsWith("..") && !isAbsolute4(rel)) {
|
|
@@ -34752,7 +33300,7 @@ function listDirectories2(dirPath) {
|
|
|
34752
33300
|
continue;
|
|
34753
33301
|
if (name === "node_modules" || name === ".build" || name === "target")
|
|
34754
33302
|
continue;
|
|
34755
|
-
const fullPath =
|
|
33303
|
+
const fullPath = join23(dirPath, name);
|
|
34756
33304
|
try {
|
|
34757
33305
|
const stat4 = statSync4(fullPath);
|
|
34758
33306
|
if (!stat4.isDirectory())
|
|
@@ -34791,7 +33339,7 @@ function detectAgent2(filePath) {
|
|
|
34791
33339
|
return "unknown";
|
|
34792
33340
|
}
|
|
34793
33341
|
async function discoverSessionFiles2(maxAgeDays, limit) {
|
|
34794
|
-
const home =
|
|
33342
|
+
const home = homedir17();
|
|
34795
33343
|
const results = [];
|
|
34796
33344
|
const searchPaths = [
|
|
34797
33345
|
{ pattern: `${home}/.claude/projects`, agent: "claude-code" },
|
|
@@ -34873,23 +33421,23 @@ function bridgeEventIterable(bridge, signal) {
|
|
|
34873
33421
|
return {
|
|
34874
33422
|
[Symbol.asyncIterator]() {
|
|
34875
33423
|
const buffer = [];
|
|
34876
|
-
let
|
|
33424
|
+
let resolve10 = null;
|
|
34877
33425
|
let done = false;
|
|
34878
33426
|
const unsub = bridge.onEvent((event) => {
|
|
34879
33427
|
if (done)
|
|
34880
33428
|
return;
|
|
34881
33429
|
buffer.push(event);
|
|
34882
|
-
if (
|
|
34883
|
-
|
|
34884
|
-
|
|
33430
|
+
if (resolve10) {
|
|
33431
|
+
resolve10();
|
|
33432
|
+
resolve10 = null;
|
|
34885
33433
|
}
|
|
34886
33434
|
});
|
|
34887
33435
|
const cleanup = () => {
|
|
34888
33436
|
done = true;
|
|
34889
33437
|
unsub();
|
|
34890
|
-
if (
|
|
34891
|
-
|
|
34892
|
-
|
|
33438
|
+
if (resolve10) {
|
|
33439
|
+
resolve10();
|
|
33440
|
+
resolve10 = null;
|
|
34893
33441
|
}
|
|
34894
33442
|
};
|
|
34895
33443
|
signal?.addEventListener("abort", cleanup, { once: true });
|
|
@@ -34902,7 +33450,7 @@ function bridgeEventIterable(bridge, signal) {
|
|
|
34902
33450
|
return { done: false, value: buffer.shift() };
|
|
34903
33451
|
}
|
|
34904
33452
|
await new Promise((r) => {
|
|
34905
|
-
|
|
33453
|
+
resolve10 = r;
|
|
34906
33454
|
});
|
|
34907
33455
|
}
|
|
34908
33456
|
},
|
|
@@ -37620,15 +36168,15 @@ function resolveSelfTuple(promise2) {
|
|
|
37620
36168
|
return Unpromise.proxy(promise2).then(() => [promise2]);
|
|
37621
36169
|
}
|
|
37622
36170
|
function withResolvers() {
|
|
37623
|
-
let
|
|
36171
|
+
let resolve10;
|
|
37624
36172
|
let reject;
|
|
37625
36173
|
const promise2 = new Promise((_resolve, _reject) => {
|
|
37626
|
-
|
|
36174
|
+
resolve10 = _resolve;
|
|
37627
36175
|
reject = _reject;
|
|
37628
36176
|
});
|
|
37629
36177
|
return {
|
|
37630
36178
|
promise: promise2,
|
|
37631
|
-
resolve:
|
|
36179
|
+
resolve: resolve10,
|
|
37632
36180
|
reject
|
|
37633
36181
|
};
|
|
37634
36182
|
}
|
|
@@ -37667,8 +36215,8 @@ function timerResource(ms) {
|
|
|
37667
36215
|
return makeResource({ start() {
|
|
37668
36216
|
if (timer)
|
|
37669
36217
|
throw new Error("Timer already started");
|
|
37670
|
-
const promise2 = new Promise((
|
|
37671
|
-
timer = setTimeout(() =>
|
|
36218
|
+
const promise2 = new Promise((resolve10) => {
|
|
36219
|
+
timer = setTimeout(() => resolve10(disposablePromiseTimerResult), ms);
|
|
37672
36220
|
});
|
|
37673
36221
|
return promise2;
|
|
37674
36222
|
} }, () => {
|
|
@@ -37717,15 +36265,15 @@ function _takeWithGrace() {
|
|
|
37717
36265
|
return _takeWithGrace.apply(this, arguments);
|
|
37718
36266
|
}
|
|
37719
36267
|
function createDeferred() {
|
|
37720
|
-
let
|
|
36268
|
+
let resolve10;
|
|
37721
36269
|
let reject;
|
|
37722
36270
|
const promise2 = new Promise((res, rej) => {
|
|
37723
|
-
|
|
36271
|
+
resolve10 = res;
|
|
37724
36272
|
reject = rej;
|
|
37725
36273
|
});
|
|
37726
36274
|
return {
|
|
37727
36275
|
promise: promise2,
|
|
37728
|
-
resolve:
|
|
36276
|
+
resolve: resolve10,
|
|
37729
36277
|
reject
|
|
37730
36278
|
};
|
|
37731
36279
|
}
|
|
@@ -38701,8 +37249,8 @@ var import_objectSpread2$13, jsonContentTypeHandler, formDataContentTypeHandler,
|
|
|
38701
37249
|
status: "fulfilled",
|
|
38702
37250
|
value
|
|
38703
37251
|
};
|
|
38704
|
-
subscribers === null || subscribers === undefined || subscribers.forEach(({ resolve:
|
|
38705
|
-
|
|
37252
|
+
subscribers === null || subscribers === undefined || subscribers.forEach(({ resolve: resolve10 }) => {
|
|
37253
|
+
resolve10(value);
|
|
38706
37254
|
});
|
|
38707
37255
|
});
|
|
38708
37256
|
if ("catch" in thenReturn)
|
|
@@ -39433,14 +37981,14 @@ var init_observable = __esm(() => {
|
|
|
39433
37981
|
|
|
39434
37982
|
// ../../apps/desktop/src/core/pairing/runtime/bridge/server-trpc.ts
|
|
39435
37983
|
import { realpathSync as realpathSync3 } from "fs";
|
|
39436
|
-
import { homedir as
|
|
37984
|
+
import { homedir as homedir18 } from "os";
|
|
39437
37985
|
function resolveCurrentDirectory() {
|
|
39438
37986
|
try {
|
|
39439
37987
|
const config2 = resolveConfig();
|
|
39440
37988
|
const configuredRoot = config2.workspace?.root;
|
|
39441
37989
|
if (!configuredRoot)
|
|
39442
37990
|
return process.cwd();
|
|
39443
|
-
const expanded = configuredRoot.replace(/^~/,
|
|
37991
|
+
const expanded = configuredRoot.replace(/^~/, homedir18());
|
|
39444
37992
|
return realpathSync3(expanded);
|
|
39445
37993
|
} catch {
|
|
39446
37994
|
return process.cwd();
|
|
@@ -39558,8 +38106,8 @@ function startBridgeServerTRPC(options) {
|
|
|
39558
38106
|
}
|
|
39559
38107
|
const iterable = isObservable(result) ? observableToAsyncIterable(result, abortController.signal) : result;
|
|
39560
38108
|
const iterator = iterable[Symbol.asyncIterator]();
|
|
39561
|
-
const abortPromise = new Promise((
|
|
39562
|
-
abortController.signal.addEventListener("abort", () =>
|
|
38109
|
+
const abortPromise = new Promise((resolve10) => {
|
|
38110
|
+
abortController.signal.addEventListener("abort", () => resolve10("abort"), {
|
|
39563
38111
|
once: true
|
|
39564
38112
|
});
|
|
39565
38113
|
});
|
|
@@ -39856,7 +38404,7 @@ var init_server_trpc = __esm(async () => {
|
|
|
39856
38404
|
});
|
|
39857
38405
|
|
|
39858
38406
|
// ../../apps/desktop/src/core/pairing/runtime/runtime.ts
|
|
39859
|
-
import { homedir as
|
|
38407
|
+
import { homedir as homedir19 } from "os";
|
|
39860
38408
|
function createPairingAdapterRegistry(configAdapters) {
|
|
39861
38409
|
const adapters = {
|
|
39862
38410
|
"claude-code": createAdapter,
|
|
@@ -39933,7 +38481,7 @@ async function autoStartConfiguredSessions(bridge, sessions3) {
|
|
|
39933
38481
|
try {
|
|
39934
38482
|
const session = await bridge.createSession(entry.adapter, {
|
|
39935
38483
|
name: entry.name,
|
|
39936
|
-
cwd: entry.cwd?.replace(/^~/,
|
|
38484
|
+
cwd: entry.cwd?.replace(/^~/, homedir19()),
|
|
39937
38485
|
options: entry.options
|
|
39938
38486
|
});
|
|
39939
38487
|
console.log(`[bridge] session started: ${session.name} (${entry.adapter})`);
|
|
@@ -40204,11 +38752,11 @@ var BRIDGE_ABSENCE_GRACE_MS = 30000, ROOM_IDLE_TIMEOUT_MS = 60000;
|
|
|
40204
38752
|
|
|
40205
38753
|
// ../../apps/desktop/src/core/pairing/runtime/relay-runtime.ts
|
|
40206
38754
|
import { execSync as execSync4 } from "child_process";
|
|
40207
|
-
import { existsSync as
|
|
40208
|
-
import { homedir as
|
|
40209
|
-
import { join as
|
|
38755
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readdirSync as readdirSync4 } from "fs";
|
|
38756
|
+
import { homedir as homedir20 } from "os";
|
|
38757
|
+
import { join as join24 } from "path";
|
|
40210
38758
|
function findStoredCerts() {
|
|
40211
|
-
if (!
|
|
38759
|
+
if (!existsSync16(PAIRING_DIR2)) {
|
|
40212
38760
|
return null;
|
|
40213
38761
|
}
|
|
40214
38762
|
try {
|
|
@@ -40222,8 +38770,8 @@ function findStoredCerts() {
|
|
|
40222
38770
|
return null;
|
|
40223
38771
|
}
|
|
40224
38772
|
return {
|
|
40225
|
-
cert:
|
|
40226
|
-
key:
|
|
38773
|
+
cert: join24(PAIRING_DIR2, certFile),
|
|
38774
|
+
key: join24(PAIRING_DIR2, keyFile)
|
|
40227
38775
|
};
|
|
40228
38776
|
} catch {
|
|
40229
38777
|
return null;
|
|
@@ -40244,8 +38792,8 @@ function getTailscaleHostname() {
|
|
|
40244
38792
|
}
|
|
40245
38793
|
function generateTailscaleCerts(hostname5) {
|
|
40246
38794
|
mkdirSync9(PAIRING_DIR2, { recursive: true });
|
|
40247
|
-
const certPath =
|
|
40248
|
-
const keyPath =
|
|
38795
|
+
const certPath = join24(PAIRING_DIR2, `${hostname5}.crt`);
|
|
38796
|
+
const keyPath = join24(PAIRING_DIR2, `${hostname5}.key`);
|
|
40249
38797
|
try {
|
|
40250
38798
|
pairingLog.info("relay", "generating tailscale TLS cert", { hostname: hostname5 });
|
|
40251
38799
|
execSync4(`tailscale cert --cert-file "${certPath}" --key-file "${keyPath}" "${hostname5}"`, {
|
|
@@ -40261,8 +38809,8 @@ function generateTailscaleCerts(hostname5) {
|
|
|
40261
38809
|
}
|
|
40262
38810
|
function generateSelfSignedCert(hostname5) {
|
|
40263
38811
|
mkdirSync9(PAIRING_DIR2, { recursive: true });
|
|
40264
|
-
const certPath =
|
|
40265
|
-
const keyPath =
|
|
38812
|
+
const certPath = join24(PAIRING_DIR2, `${hostname5}.crt`);
|
|
38813
|
+
const keyPath = join24(PAIRING_DIR2, `${hostname5}.key`);
|
|
40266
38814
|
try {
|
|
40267
38815
|
execSync4(`openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 ` + `-keyout "${keyPath}" -out "${certPath}" -days 365 -nodes ` + `-subj "/CN=${hostname5}" -addext "subjectAltName=DNS:${hostname5}"`, {
|
|
40268
38816
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -40325,7 +38873,7 @@ function startManagedRelay(port = 7889) {
|
|
|
40325
38873
|
var PAIRING_DIR2;
|
|
40326
38874
|
var init_relay_runtime = __esm(() => {
|
|
40327
38875
|
init_log2();
|
|
40328
|
-
PAIRING_DIR2 =
|
|
38876
|
+
PAIRING_DIR2 = join24(homedir20(), ".scout/pairing");
|
|
40329
38877
|
});
|
|
40330
38878
|
|
|
40331
38879
|
// ../../node_modules/.bun/uqr@0.1.3/node_modules/uqr/dist/index.mjs
|
|
@@ -41190,8 +39738,8 @@ async function runPairCommand(context, args) {
|
|
|
41190
39738
|
process.on("SIGINT", handleSignal);
|
|
41191
39739
|
process.on("SIGTERM", handleSignal);
|
|
41192
39740
|
try {
|
|
41193
|
-
await new Promise((
|
|
41194
|
-
controller.signal.addEventListener("abort", () =>
|
|
39741
|
+
await new Promise((resolve10) => {
|
|
39742
|
+
controller.signal.addEventListener("abort", () => resolve10(), { once: true });
|
|
41195
39743
|
});
|
|
41196
39744
|
} finally {
|
|
41197
39745
|
process.off("SIGINT", handleSignal);
|
|
@@ -41254,39 +39802,6 @@ var init_runtimes = __esm(() => {
|
|
|
41254
39802
|
init_service3();
|
|
41255
39803
|
});
|
|
41256
39804
|
|
|
41257
|
-
// ../../apps/desktop/src/cli/commands/send.ts
|
|
41258
|
-
var exports_send = {};
|
|
41259
|
-
__export(exports_send, {
|
|
41260
|
-
runSendCommand: () => runSendCommand
|
|
41261
|
-
});
|
|
41262
|
-
async function runSendCommand(context, args) {
|
|
41263
|
-
const options = parseSendCommandOptions(args, defaultScoutContextDirectory(context));
|
|
41264
|
-
const currentDirectory = options.currentDirectory ?? defaultScoutContextDirectory(context);
|
|
41265
|
-
const senderId = await resolveScoutSenderId(options.agentName, currentDirectory);
|
|
41266
|
-
const result = await sendScoutMessage({
|
|
41267
|
-
senderId,
|
|
41268
|
-
body: options.message,
|
|
41269
|
-
channel: options.channel,
|
|
41270
|
-
shouldSpeak: options.shouldSpeak,
|
|
41271
|
-
executionHarness: parseScoutHarness(options.harness),
|
|
41272
|
-
currentDirectory: options.currentDirectory
|
|
41273
|
-
});
|
|
41274
|
-
if (!result.usedBroker) {
|
|
41275
|
-
throw new Error("broker is not reachable");
|
|
41276
|
-
}
|
|
41277
|
-
context.output.writeValue({
|
|
41278
|
-
message: options.message,
|
|
41279
|
-
invokedTargets: result.invokedTargets,
|
|
41280
|
-
unresolvedTargets: result.unresolvedTargets
|
|
41281
|
-
}, renderScoutMessagePostResult);
|
|
41282
|
-
}
|
|
41283
|
-
var init_send = __esm(async () => {
|
|
41284
|
-
init_context();
|
|
41285
|
-
init_options();
|
|
41286
|
-
init_broker();
|
|
41287
|
-
await init_service();
|
|
41288
|
-
});
|
|
41289
|
-
|
|
41290
39805
|
// ../../apps/desktop/src/cli/commands/server.ts
|
|
41291
39806
|
var exports_server = {};
|
|
41292
39807
|
__export(exports_server, {
|
|
@@ -41297,9 +39812,9 @@ __export(exports_server, {
|
|
|
41297
39812
|
normalizeServerOpenPath: () => normalizeServerOpenPath
|
|
41298
39813
|
});
|
|
41299
39814
|
import { spawn as spawn5 } from "child_process";
|
|
41300
|
-
import { existsSync as
|
|
41301
|
-
import { dirname as
|
|
41302
|
-
import { fileURLToPath as
|
|
39815
|
+
import { existsSync as existsSync17 } from "fs";
|
|
39816
|
+
import { dirname as dirname11, join as join25, resolve as resolve10 } from "path";
|
|
39817
|
+
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
41303
39818
|
function renderServerCommandHelp() {
|
|
41304
39819
|
return [
|
|
41305
39820
|
"scout server \u2014 desktop web UI (Bun runtime)",
|
|
@@ -41332,25 +39847,25 @@ function renderServerCommandHelp() {
|
|
|
41332
39847
|
`);
|
|
41333
39848
|
}
|
|
41334
39849
|
function resolveScoutWebServerEntry() {
|
|
41335
|
-
const mainDir =
|
|
41336
|
-
const bundled =
|
|
41337
|
-
if (
|
|
39850
|
+
const mainDir = dirname11(fileURLToPath8(import.meta.url));
|
|
39851
|
+
const bundled = join25(mainDir, "scout-web-server.mjs");
|
|
39852
|
+
if (existsSync17(bundled)) {
|
|
41338
39853
|
return bundled;
|
|
41339
39854
|
}
|
|
41340
|
-
const source =
|
|
41341
|
-
if (
|
|
39855
|
+
const source = fileURLToPath8(new URL("../../server/index.ts", import.meta.url));
|
|
39856
|
+
if (existsSync17(source)) {
|
|
41342
39857
|
return source;
|
|
41343
39858
|
}
|
|
41344
39859
|
throw new ScoutCliError("Could not find Scout web server entry. Rebuild @openscout/scout or run from the OpenScout repository.");
|
|
41345
39860
|
}
|
|
41346
39861
|
function resolveScoutControlPlaneWebServerEntry() {
|
|
41347
|
-
const mainDir =
|
|
41348
|
-
const bundled =
|
|
41349
|
-
if (
|
|
39862
|
+
const mainDir = dirname11(fileURLToPath8(import.meta.url));
|
|
39863
|
+
const bundled = join25(mainDir, "scout-control-plane-web.mjs");
|
|
39864
|
+
if (existsSync17(bundled)) {
|
|
41350
39865
|
return bundled;
|
|
41351
39866
|
}
|
|
41352
|
-
const source =
|
|
41353
|
-
if (
|
|
39867
|
+
const source = fileURLToPath8(new URL("../../server/control-plane-index.ts", import.meta.url));
|
|
39868
|
+
if (existsSync17(source)) {
|
|
41354
39869
|
return source;
|
|
41355
39870
|
}
|
|
41356
39871
|
throw new ScoutCliError("Could not find Scout control-plane web server entry. Rebuild @openscout/scout or run from the OpenScout repository.");
|
|
@@ -41424,10 +39939,10 @@ function parseServerFlags(args) {
|
|
|
41424
39939
|
return { env, openPath };
|
|
41425
39940
|
}
|
|
41426
39941
|
function resolveBundledStaticClientRoot(entry, mode) {
|
|
41427
|
-
const entryDir =
|
|
41428
|
-
const clientDirectory = mode === "control-plane" ?
|
|
41429
|
-
const indexPath =
|
|
41430
|
-
return
|
|
39942
|
+
const entryDir = dirname11(entry);
|
|
39943
|
+
const clientDirectory = mode === "control-plane" ? join25(entryDir, "control-plane-client") : join25(entryDir, "client");
|
|
39944
|
+
const indexPath = join25(clientDirectory, "index.html");
|
|
39945
|
+
return existsSync17(indexPath) ? clientDirectory : null;
|
|
41431
39946
|
}
|
|
41432
39947
|
function buildMergedServerEnv(entry, mode, flagEnv) {
|
|
41433
39948
|
const bundledStaticClientRoot = resolveBundledStaticClientRoot(entry, mode);
|
|
@@ -41493,7 +40008,7 @@ function resolveServerPort(env) {
|
|
|
41493
40008
|
return port;
|
|
41494
40009
|
}
|
|
41495
40010
|
function resolveExpectedCurrentDirectory(env) {
|
|
41496
|
-
return
|
|
40011
|
+
return resolve10(env.OPENSCOUT_SETUP_CWD?.trim() || process.cwd());
|
|
41497
40012
|
}
|
|
41498
40013
|
function renderModeLabel(mode) {
|
|
41499
40014
|
return mode === "control-plane" ? "Scout control plane" : "Scout";
|
|
@@ -41617,7 +40132,7 @@ async function waitForScoutServer(port, mode, expectedCurrentDirectory) {
|
|
|
41617
40132
|
while (Date.now() < deadline) {
|
|
41618
40133
|
const probe = await probeScoutServer(port);
|
|
41619
40134
|
if (probe.status === "healthy") {
|
|
41620
|
-
const actualCurrentDirectory =
|
|
40135
|
+
const actualCurrentDirectory = resolve10(probe.health.currentDirectory);
|
|
41621
40136
|
if (probe.health.surface !== mode) {
|
|
41622
40137
|
throw new ScoutCliError(`port ${port} is serving Scout ${renderSurfaceLabel(probe.health.surface)}, not ${renderModeLabel(mode)}.`);
|
|
41623
40138
|
}
|
|
@@ -41639,7 +40154,7 @@ async function openScoutServer(options) {
|
|
|
41639
40154
|
const browserUrl = new URL(normalizeServerOpenPath(options.openPath), `http://127.0.0.1:${port}`).toString();
|
|
41640
40155
|
const probe = await probeScoutServer(port);
|
|
41641
40156
|
if (probe.status === "healthy") {
|
|
41642
|
-
const actualCurrentDirectory =
|
|
40157
|
+
const actualCurrentDirectory = resolve10(probe.health.currentDirectory);
|
|
41643
40158
|
if (probe.health.surface !== options.mode) {
|
|
41644
40159
|
throw new ScoutCliError(`port ${port} is already serving Scout ${renderSurfaceLabel(probe.health.surface)}, not ${renderModeLabel(options.mode)}.`);
|
|
41645
40160
|
}
|
|
@@ -41720,8 +40235,8 @@ var init_server2 = __esm(() => {
|
|
|
41720
40235
|
});
|
|
41721
40236
|
|
|
41722
40237
|
// ../../apps/desktop/src/cli/commands/setup.ts
|
|
41723
|
-
var
|
|
41724
|
-
__export(
|
|
40238
|
+
var exports_setup = {};
|
|
40239
|
+
__export(exports_setup, {
|
|
41725
40240
|
runSetupCommand: () => runSetupCommand
|
|
41726
40241
|
});
|
|
41727
40242
|
async function runSetupCommand(context, args) {
|
|
@@ -41743,7 +40258,7 @@ __export(exports_speak, {
|
|
|
41743
40258
|
async function runSpeakCommand(context, args) {
|
|
41744
40259
|
const options = parseSendCommandOptions(args, defaultScoutContextDirectory(context));
|
|
41745
40260
|
const currentDirectory = options.currentDirectory ?? defaultScoutContextDirectory(context);
|
|
41746
|
-
const senderId = await resolveScoutSenderId(options.agentName, currentDirectory);
|
|
40261
|
+
const senderId = await resolveScoutSenderId(options.agentName, currentDirectory, context.env);
|
|
41747
40262
|
const config3 = await loadScoutRelayConfig();
|
|
41748
40263
|
const voice = getScoutVoiceForChannel(config3, "voice");
|
|
41749
40264
|
await acquireScoutOnAir(senderId);
|
|
@@ -41766,6 +40281,9 @@ async function runSpeakCommand(context, args) {
|
|
|
41766
40281
|
if (!result.usedBroker) {
|
|
41767
40282
|
throw new Error("broker is not reachable");
|
|
41768
40283
|
}
|
|
40284
|
+
if (result.unresolvedTargets.length > 0) {
|
|
40285
|
+
throw new Error(formatScoutSendRoutingError(result.unresolvedTargets));
|
|
40286
|
+
}
|
|
41769
40287
|
context.output.writeValue({
|
|
41770
40288
|
message: options.message,
|
|
41771
40289
|
invokedTargets: result.invokedTargets,
|
|
@@ -41776,7 +40294,10 @@ var init_speak = __esm(async () => {
|
|
|
41776
40294
|
init_context();
|
|
41777
40295
|
init_options();
|
|
41778
40296
|
init_broker();
|
|
41779
|
-
await
|
|
40297
|
+
await __promiseAll([
|
|
40298
|
+
init_service(),
|
|
40299
|
+
init_send()
|
|
40300
|
+
]);
|
|
41780
40301
|
});
|
|
41781
40302
|
|
|
41782
40303
|
// ../../node_modules/.bun/@opentui+core@0.1.96+a7e4efcb39f2fc50/node_modules/@opentui/core/assets/javascript/highlights.scm
|
|
@@ -41828,11 +40349,11 @@ import { EventEmitter } from "events";
|
|
|
41828
40349
|
import { Buffer as Buffer2 } from "buffer";
|
|
41829
40350
|
import { Buffer as Buffer3 } from "buffer";
|
|
41830
40351
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
41831
|
-
import { resolve as
|
|
41832
|
-
import { fileURLToPath as
|
|
40352
|
+
import { resolve as resolve11, dirname as dirname12 } from "path";
|
|
40353
|
+
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
41833
40354
|
import { resolve as resolve22, isAbsolute as isAbsolute5, parse as parse6 } from "path";
|
|
41834
|
-
import { existsSync as
|
|
41835
|
-
import { basename as basename9, join as
|
|
40355
|
+
import { existsSync as existsSync18 } from "fs";
|
|
40356
|
+
import { basename as basename9, join as join26 } from "path";
|
|
41836
40357
|
import os from "os";
|
|
41837
40358
|
import path2 from "path";
|
|
41838
40359
|
import { EventEmitter as EventEmitter3 } from "events";
|
|
@@ -44964,13 +43485,13 @@ class DebounceController {
|
|
|
44964
43485
|
}
|
|
44965
43486
|
debounce(id, ms, fn) {
|
|
44966
43487
|
const scopeMap = TIMERS_MAP.get(this.scopeId);
|
|
44967
|
-
return new Promise((
|
|
43488
|
+
return new Promise((resolve13, reject) => {
|
|
44968
43489
|
if (scopeMap.has(id)) {
|
|
44969
43490
|
clearTimeout(scopeMap.get(id));
|
|
44970
43491
|
}
|
|
44971
43492
|
const timerId = setTimeout(() => {
|
|
44972
43493
|
try {
|
|
44973
|
-
|
|
43494
|
+
resolve13(fn());
|
|
44974
43495
|
} catch (error48) {
|
|
44975
43496
|
reject(error48);
|
|
44976
43497
|
}
|
|
@@ -45060,25 +43581,25 @@ function getParsers() {
|
|
|
45060
43581
|
filetype: "javascript",
|
|
45061
43582
|
aliases: ["javascriptreact"],
|
|
45062
43583
|
queries: {
|
|
45063
|
-
highlights: [
|
|
43584
|
+
highlights: [resolve11(dirname12(fileURLToPath9(import.meta.url)), highlights_default)]
|
|
45064
43585
|
},
|
|
45065
|
-
wasm:
|
|
43586
|
+
wasm: resolve11(dirname12(fileURLToPath9(import.meta.url)), tree_sitter_javascript_default)
|
|
45066
43587
|
},
|
|
45067
43588
|
{
|
|
45068
43589
|
filetype: "typescript",
|
|
45069
43590
|
aliases: ["typescriptreact"],
|
|
45070
43591
|
queries: {
|
|
45071
|
-
highlights: [
|
|
43592
|
+
highlights: [resolve11(dirname12(fileURLToPath9(import.meta.url)), highlights_default2)]
|
|
45072
43593
|
},
|
|
45073
|
-
wasm:
|
|
43594
|
+
wasm: resolve11(dirname12(fileURLToPath9(import.meta.url)), tree_sitter_typescript_default)
|
|
45074
43595
|
},
|
|
45075
43596
|
{
|
|
45076
43597
|
filetype: "markdown",
|
|
45077
43598
|
queries: {
|
|
45078
|
-
highlights: [
|
|
45079
|
-
injections: [
|
|
43599
|
+
highlights: [resolve11(dirname12(fileURLToPath9(import.meta.url)), highlights_default3)],
|
|
43600
|
+
injections: [resolve11(dirname12(fileURLToPath9(import.meta.url)), injections_default)]
|
|
45080
43601
|
},
|
|
45081
|
-
wasm:
|
|
43602
|
+
wasm: resolve11(dirname12(fileURLToPath9(import.meta.url)), tree_sitter_markdown_default),
|
|
45082
43603
|
injectionMapping: {
|
|
45083
43604
|
nodeTypes: {
|
|
45084
43605
|
inline: "markdown_inline",
|
|
@@ -45101,16 +43622,16 @@ function getParsers() {
|
|
|
45101
43622
|
{
|
|
45102
43623
|
filetype: "markdown_inline",
|
|
45103
43624
|
queries: {
|
|
45104
|
-
highlights: [
|
|
43625
|
+
highlights: [resolve11(dirname12(fileURLToPath9(import.meta.url)), highlights_default4)]
|
|
45105
43626
|
},
|
|
45106
|
-
wasm:
|
|
43627
|
+
wasm: resolve11(dirname12(fileURLToPath9(import.meta.url)), tree_sitter_markdown_inline_default)
|
|
45107
43628
|
},
|
|
45108
43629
|
{
|
|
45109
43630
|
filetype: "zig",
|
|
45110
43631
|
queries: {
|
|
45111
|
-
highlights: [
|
|
43632
|
+
highlights: [resolve11(dirname12(fileURLToPath9(import.meta.url)), highlights_default5)]
|
|
45112
43633
|
},
|
|
45113
|
-
wasm:
|
|
43634
|
+
wasm: resolve11(dirname12(fileURLToPath9(import.meta.url)), tree_sitter_zig_default)
|
|
45114
43635
|
}
|
|
45115
43636
|
];
|
|
45116
43637
|
}
|
|
@@ -45123,7 +43644,7 @@ function getBunfsRootPath() {
|
|
|
45123
43644
|
return process.platform === "win32" ? "B:\\~BUN\\root" : "/$bunfs/root";
|
|
45124
43645
|
}
|
|
45125
43646
|
function normalizeBunfsPath(fileName) {
|
|
45126
|
-
return
|
|
43647
|
+
return join26(getBunfsRootPath(), basename9(fileName));
|
|
45127
43648
|
}
|
|
45128
43649
|
function addDefaultParsers(parsers) {
|
|
45129
43650
|
for (const parser of parsers) {
|
|
@@ -56045,7 +54566,7 @@ var init_index_vy1rm1x3 = __esm(async () => {
|
|
|
56045
54566
|
worker_path = this.options.workerPath;
|
|
56046
54567
|
} else {
|
|
56047
54568
|
worker_path = new URL("./parser.worker.js", import.meta.url).href;
|
|
56048
|
-
if (!
|
|
54569
|
+
if (!existsSync18(resolve22(import.meta.dirname, "parser.worker.js"))) {
|
|
56049
54570
|
worker_path = new URL("./parser.worker.ts", import.meta.url).href;
|
|
56050
54571
|
}
|
|
56051
54572
|
}
|
|
@@ -74346,14 +72867,14 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
|
|
|
74346
72867
|
prevActScopeDepth !== actScopeDepth - 1 && console.error("You seem to have overlapping act() calls, this is not supported. Be sure to await previous act() calls before making a new one. ");
|
|
74347
72868
|
actScopeDepth = prevActScopeDepth;
|
|
74348
72869
|
}
|
|
74349
|
-
function recursivelyFlushAsyncActWork(returnValue,
|
|
72870
|
+
function recursivelyFlushAsyncActWork(returnValue, resolve13, reject) {
|
|
74350
72871
|
var queue = ReactSharedInternals.actQueue;
|
|
74351
72872
|
if (queue !== null)
|
|
74352
72873
|
if (queue.length !== 0)
|
|
74353
72874
|
try {
|
|
74354
72875
|
flushActQueue(queue);
|
|
74355
72876
|
enqueueTask(function() {
|
|
74356
|
-
return recursivelyFlushAsyncActWork(returnValue,
|
|
72877
|
+
return recursivelyFlushAsyncActWork(returnValue, resolve13, reject);
|
|
74357
72878
|
});
|
|
74358
72879
|
return;
|
|
74359
72880
|
} catch (error48) {
|
|
@@ -74361,7 +72882,7 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
|
|
|
74361
72882
|
}
|
|
74362
72883
|
else
|
|
74363
72884
|
ReactSharedInternals.actQueue = null;
|
|
74364
|
-
0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) :
|
|
72885
|
+
0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) : resolve13(returnValue);
|
|
74365
72886
|
}
|
|
74366
72887
|
function flushActQueue(queue) {
|
|
74367
72888
|
if (!isFlushing) {
|
|
@@ -74537,14 +73058,14 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
|
|
|
74537
73058
|
didAwaitActCall || didWarnNoAwaitAct || (didWarnNoAwaitAct = true, console.error("You called act(async () => ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);"));
|
|
74538
73059
|
});
|
|
74539
73060
|
return {
|
|
74540
|
-
then: function(
|
|
73061
|
+
then: function(resolve13, reject) {
|
|
74541
73062
|
didAwaitActCall = true;
|
|
74542
73063
|
thenable.then(function(returnValue) {
|
|
74543
73064
|
popActScope(prevActQueue, prevActScopeDepth);
|
|
74544
73065
|
if (prevActScopeDepth === 0) {
|
|
74545
73066
|
try {
|
|
74546
73067
|
flushActQueue(queue), enqueueTask(function() {
|
|
74547
|
-
return recursivelyFlushAsyncActWork(returnValue,
|
|
73068
|
+
return recursivelyFlushAsyncActWork(returnValue, resolve13, reject);
|
|
74548
73069
|
});
|
|
74549
73070
|
} catch (error$0) {
|
|
74550
73071
|
ReactSharedInternals.thrownErrors.push(error$0);
|
|
@@ -74555,7 +73076,7 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
|
|
|
74555
73076
|
reject(_thrownError);
|
|
74556
73077
|
}
|
|
74557
73078
|
} else
|
|
74558
|
-
|
|
73079
|
+
resolve13(returnValue);
|
|
74559
73080
|
}, function(error48) {
|
|
74560
73081
|
popActScope(prevActQueue, prevActScopeDepth);
|
|
74561
73082
|
0 < ReactSharedInternals.thrownErrors.length ? (error48 = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(error48)) : reject(error48);
|
|
@@ -74571,11 +73092,11 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
|
|
|
74571
73092
|
if (0 < ReactSharedInternals.thrownErrors.length)
|
|
74572
73093
|
throw callback = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, callback;
|
|
74573
73094
|
return {
|
|
74574
|
-
then: function(
|
|
73095
|
+
then: function(resolve13, reject) {
|
|
74575
73096
|
didAwaitActCall = true;
|
|
74576
73097
|
prevActScopeDepth === 0 ? (ReactSharedInternals.actQueue = queue, enqueueTask(function() {
|
|
74577
|
-
return recursivelyFlushAsyncActWork(returnValue$jscomp$0,
|
|
74578
|
-
})) :
|
|
73098
|
+
return recursivelyFlushAsyncActWork(returnValue$jscomp$0, resolve13, reject);
|
|
73099
|
+
})) : resolve13(returnValue$jscomp$0);
|
|
74579
73100
|
}
|
|
74580
73101
|
};
|
|
74581
73102
|
};
|
|
@@ -77056,8 +75577,8 @@ It can also happen if the client has a browser extension installed which messes
|
|
|
77056
75577
|
currentEntangledActionThenable = {
|
|
77057
75578
|
status: "pending",
|
|
77058
75579
|
value: undefined,
|
|
77059
|
-
then: function(
|
|
77060
|
-
entangledListeners.push(
|
|
75580
|
+
then: function(resolve13) {
|
|
75581
|
+
entangledListeners.push(resolve13);
|
|
77061
75582
|
}
|
|
77062
75583
|
};
|
|
77063
75584
|
}
|
|
@@ -77081,8 +75602,8 @@ It can also happen if the client has a browser extension installed which messes
|
|
|
77081
75602
|
status: "pending",
|
|
77082
75603
|
value: null,
|
|
77083
75604
|
reason: null,
|
|
77084
|
-
then: function(
|
|
77085
|
-
listeners.push(
|
|
75605
|
+
then: function(resolve13) {
|
|
75606
|
+
listeners.push(resolve13);
|
|
77086
75607
|
}
|
|
77087
75608
|
};
|
|
77088
75609
|
thenable.then(function() {
|
|
@@ -103064,14 +101585,14 @@ async function runScoutMonitorApp(options) {
|
|
|
103064
101585
|
}
|
|
103065
101586
|
const renderer = await createCliRenderer();
|
|
103066
101587
|
let closed = false;
|
|
103067
|
-
await new Promise((
|
|
101588
|
+
await new Promise((resolve13) => {
|
|
103068
101589
|
const close = () => {
|
|
103069
101590
|
if (closed) {
|
|
103070
101591
|
return;
|
|
103071
101592
|
}
|
|
103072
101593
|
closed = true;
|
|
103073
101594
|
renderer.destroy();
|
|
103074
|
-
|
|
101595
|
+
resolve13();
|
|
103075
101596
|
};
|
|
103076
101597
|
createRoot(renderer).render(/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ScoutMonitorApp, {
|
|
103077
101598
|
currentDirectory: options.currentDirectory,
|
|
@@ -103119,8 +101640,8 @@ var exports_up = {};
|
|
|
103119
101640
|
__export(exports_up, {
|
|
103120
101641
|
runUpCommand: () => runUpCommand
|
|
103121
101642
|
});
|
|
103122
|
-
import { existsSync as
|
|
103123
|
-
import { resolve as
|
|
101643
|
+
import { existsSync as existsSync19 } from "fs";
|
|
101644
|
+
import { resolve as resolve13 } from "path";
|
|
103124
101645
|
function looksLikePath(value) {
|
|
103125
101646
|
return value.includes("/") || value.startsWith(".") || value.startsWith("~");
|
|
103126
101647
|
}
|
|
@@ -103168,8 +101689,8 @@ async function runUpCommand(context, args) {
|
|
|
103168
101689
|
throw new ScoutCliError("usage: scout up <name|path> [--name <alias>] [--harness <claude|codex>]");
|
|
103169
101690
|
}
|
|
103170
101691
|
let projectPath;
|
|
103171
|
-
if (looksLikePath(target) ||
|
|
103172
|
-
projectPath =
|
|
101692
|
+
if (looksLikePath(target) || existsSync19(resolve13(target))) {
|
|
101693
|
+
projectPath = resolve13(target);
|
|
103173
101694
|
} else {
|
|
103174
101695
|
const resolved = await resolveLocalAgentByName(target);
|
|
103175
101696
|
if (!resolved) {
|
|
@@ -103207,10 +101728,9 @@ async function runWatchCommand(context, args) {
|
|
|
103207
101728
|
process.on("SIGINT", shutdown);
|
|
103208
101729
|
try {
|
|
103209
101730
|
if (context.output.mode === "plain") {
|
|
103210
|
-
context.stdout(`Watching ${options.channel?.trim() || "shared"}
|
|
101731
|
+
context.stdout(`Watching ${options.channel?.trim() || "shared"}`);
|
|
103211
101732
|
}
|
|
103212
101733
|
await watchScoutMessages({
|
|
103213
|
-
agentId: resolveScoutAgentName(options.agentName),
|
|
103214
101734
|
channel: options.channel,
|
|
103215
101735
|
signal: controller.signal,
|
|
103216
101736
|
onMessage(message) {
|
|
@@ -103251,12 +101771,10 @@ __export(exports_whoami, {
|
|
|
103251
101771
|
runWhoAmICommand: () => runWhoAmICommand
|
|
103252
101772
|
});
|
|
103253
101773
|
async function loadScoutWhoAmIReport(context, currentDirectory) {
|
|
103254
|
-
const
|
|
103255
|
-
const sendSpeakId = await resolveScoutSenderId(null, currentDirectory);
|
|
101774
|
+
const defaultSenderId = await resolveScoutSenderId(null, currentDirectory, context.env);
|
|
103256
101775
|
const projectRoot = await findNearestProjectRoot(currentDirectory);
|
|
103257
101776
|
return {
|
|
103258
|
-
|
|
103259
|
-
sendSpeakId,
|
|
101777
|
+
defaultSenderId,
|
|
103260
101778
|
envAgent: context.env.OPENSCOUT_AGENT?.trim() || null,
|
|
103261
101779
|
currentDirectory,
|
|
103262
101780
|
projectRoot,
|
|
@@ -103265,8 +101783,7 @@ async function loadScoutWhoAmIReport(context, currentDirectory) {
|
|
|
103265
101783
|
}
|
|
103266
101784
|
function renderScoutWhoAmIReport(report) {
|
|
103267
101785
|
const lines = [
|
|
103268
|
-
`
|
|
103269
|
-
`Send/Speak: ${report.sendSpeakId}`,
|
|
101786
|
+
`Default Sender: ${report.defaultSenderId}`,
|
|
103270
101787
|
`Current Directory: ${report.currentDirectory}`,
|
|
103271
101788
|
`Broker: ${report.brokerUrl}`
|
|
103272
101789
|
];
|
|
@@ -103352,6 +101869,8 @@ async function loadScoutCommandHandler(name) {
|
|
|
103352
101869
|
return (await init_env().then(() => exports_env)).runEnvCommand;
|
|
103353
101870
|
case "latest":
|
|
103354
101871
|
return (await init_latest().then(() => exports_latest)).runLatestCommand;
|
|
101872
|
+
case "menu":
|
|
101873
|
+
return (await Promise.resolve().then(() => (init_menu(), exports_menu))).runMenuCommand;
|
|
103355
101874
|
case "mesh":
|
|
103356
101875
|
return (await init_mesh().then(() => exports_mesh)).runMeshCommand;
|
|
103357
101876
|
case "pair":
|
|
@@ -103367,7 +101886,7 @@ async function loadScoutCommandHandler(name) {
|
|
|
103367
101886
|
case "server":
|
|
103368
101887
|
return (await Promise.resolve().then(() => (init_server2(), exports_server))).runServerCommand;
|
|
103369
101888
|
case "setup":
|
|
103370
|
-
return (await Promise.resolve().then(() => (init_setup2(),
|
|
101889
|
+
return (await Promise.resolve().then(() => (init_setup2(), exports_setup))).runSetupCommand;
|
|
103371
101890
|
case "speak":
|
|
103372
101891
|
return (await init_speak().then(() => exports_speak)).runSpeakCommand;
|
|
103373
101892
|
case "tui":
|
|
@@ -103405,6 +101924,7 @@ var SCOUT_COMMANDS = [
|
|
|
103405
101924
|
{ name: "down", summary: "Stop one or all local agents" },
|
|
103406
101925
|
{ name: "ps", summary: "List configured local agents" },
|
|
103407
101926
|
{ name: "restart", summary: "Restart configured local agents" },
|
|
101927
|
+
{ name: "menu", summary: "Launch the OpenScout macOS menu bar app" },
|
|
103408
101928
|
{ name: "config", summary: "View or set user config (name, etc.)" },
|
|
103409
101929
|
{ name: "mesh", summary: "Mesh status and diagnostics" },
|
|
103410
101930
|
{ name: "pair", summary: "Pair a companion device via QR" },
|
|
@@ -103461,6 +101981,7 @@ function renderScoutHelp(version2 = "0.2.18") {
|
|
|
103461
101981
|
" scout whoami",
|
|
103462
101982
|
" scout who",
|
|
103463
101983
|
" scout latest",
|
|
101984
|
+
" scout menu",
|
|
103464
101985
|
" scout server open",
|
|
103465
101986
|
"",
|
|
103466
101987
|
"Addressing:",
|