copilotoffice 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +225 -225
- package/bin/copilotoffice.js +39 -39
- package/dist/electron/main.js +580 -125
- package/dist/electron/terminal/events-watcher.js +53 -2
- package/dist/electron/terminal/ipc-relay.js +30 -0
- package/dist/electron/terminal/preload.js +7 -0
- package/dist/electron/terminal/server.js +404 -72
- package/dist/game.bundle.js +536 -176
- package/package.json +62 -62
- package/src/index.html +44 -44
|
@@ -3044,8 +3044,8 @@ var require_main = __commonJS({
|
|
|
3044
3044
|
exports2.createMessageConnection = exports2.createServerSocketTransport = exports2.createClientSocketTransport = exports2.createServerPipeTransport = exports2.createClientPipeTransport = exports2.generateRandomPipeName = exports2.StreamMessageWriter = exports2.StreamMessageReader = exports2.SocketMessageWriter = exports2.SocketMessageReader = exports2.PortMessageWriter = exports2.PortMessageReader = exports2.IPCMessageWriter = exports2.IPCMessageReader = void 0;
|
|
3045
3045
|
var ril_1 = require_ril();
|
|
3046
3046
|
ril_1.default.install();
|
|
3047
|
-
var
|
|
3048
|
-
var
|
|
3047
|
+
var path7 = require("path");
|
|
3048
|
+
var os5 = require("os");
|
|
3049
3049
|
var crypto_1 = require("crypto");
|
|
3050
3050
|
var net_1 = require("net");
|
|
3051
3051
|
var api_1 = require_api();
|
|
@@ -3180,9 +3180,9 @@ var require_main = __commonJS({
|
|
|
3180
3180
|
}
|
|
3181
3181
|
let result;
|
|
3182
3182
|
if (XDG_RUNTIME_DIR) {
|
|
3183
|
-
result =
|
|
3183
|
+
result = path7.join(XDG_RUNTIME_DIR, `vscode-ipc-${randomSuffix}.sock`);
|
|
3184
3184
|
} else {
|
|
3185
|
-
result =
|
|
3185
|
+
result = path7.join(os5.tmpdir(), `vscode-${randomSuffix}.sock`);
|
|
3186
3186
|
}
|
|
3187
3187
|
const limit = safeIpcPathLengths.get(process.platform);
|
|
3188
3188
|
if (limit !== void 0 && result.length > limit) {
|
|
@@ -6441,40 +6441,40 @@ function normalizeSqliteParams(params) {
|
|
|
6441
6441
|
}
|
|
6442
6442
|
function createSessionFsAdapter(provider) {
|
|
6443
6443
|
return {
|
|
6444
|
-
readFile: async ({ path:
|
|
6444
|
+
readFile: async ({ path: path7 }) => {
|
|
6445
6445
|
try {
|
|
6446
|
-
const content = await provider.readFile(
|
|
6446
|
+
const content = await provider.readFile(path7);
|
|
6447
6447
|
return { content };
|
|
6448
6448
|
} catch (err) {
|
|
6449
6449
|
return { content: "", error: toSessionFsError(err) };
|
|
6450
6450
|
}
|
|
6451
6451
|
},
|
|
6452
|
-
writeFile: async ({ path:
|
|
6452
|
+
writeFile: async ({ path: path7, content, mode }) => {
|
|
6453
6453
|
try {
|
|
6454
|
-
await provider.writeFile(
|
|
6454
|
+
await provider.writeFile(path7, content, mode);
|
|
6455
6455
|
return void 0;
|
|
6456
6456
|
} catch (err) {
|
|
6457
6457
|
return toSessionFsError(err);
|
|
6458
6458
|
}
|
|
6459
6459
|
},
|
|
6460
|
-
appendFile: async ({ path:
|
|
6460
|
+
appendFile: async ({ path: path7, content, mode }) => {
|
|
6461
6461
|
try {
|
|
6462
|
-
await provider.appendFile(
|
|
6462
|
+
await provider.appendFile(path7, content, mode);
|
|
6463
6463
|
return void 0;
|
|
6464
6464
|
} catch (err) {
|
|
6465
6465
|
return toSessionFsError(err);
|
|
6466
6466
|
}
|
|
6467
6467
|
},
|
|
6468
|
-
exists: async ({ path:
|
|
6468
|
+
exists: async ({ path: path7 }) => {
|
|
6469
6469
|
try {
|
|
6470
|
-
return { exists: await provider.exists(
|
|
6470
|
+
return { exists: await provider.exists(path7) };
|
|
6471
6471
|
} catch {
|
|
6472
6472
|
return { exists: false };
|
|
6473
6473
|
}
|
|
6474
6474
|
},
|
|
6475
|
-
stat: async ({ path:
|
|
6475
|
+
stat: async ({ path: path7 }) => {
|
|
6476
6476
|
try {
|
|
6477
|
-
return await provider.stat(
|
|
6477
|
+
return await provider.stat(path7);
|
|
6478
6478
|
} catch (err) {
|
|
6479
6479
|
return {
|
|
6480
6480
|
isFile: false,
|
|
@@ -6486,33 +6486,33 @@ function createSessionFsAdapter(provider) {
|
|
|
6486
6486
|
};
|
|
6487
6487
|
}
|
|
6488
6488
|
},
|
|
6489
|
-
mkdir: async ({ path:
|
|
6489
|
+
mkdir: async ({ path: path7, recursive, mode }) => {
|
|
6490
6490
|
try {
|
|
6491
|
-
await provider.mkdir(
|
|
6491
|
+
await provider.mkdir(path7, recursive ?? false, mode);
|
|
6492
6492
|
return void 0;
|
|
6493
6493
|
} catch (err) {
|
|
6494
6494
|
return toSessionFsError(err);
|
|
6495
6495
|
}
|
|
6496
6496
|
},
|
|
6497
|
-
readdir: async ({ path:
|
|
6497
|
+
readdir: async ({ path: path7 }) => {
|
|
6498
6498
|
try {
|
|
6499
|
-
const entries = await provider.readdir(
|
|
6499
|
+
const entries = await provider.readdir(path7);
|
|
6500
6500
|
return { entries };
|
|
6501
6501
|
} catch (err) {
|
|
6502
6502
|
return { entries: [], error: toSessionFsError(err) };
|
|
6503
6503
|
}
|
|
6504
6504
|
},
|
|
6505
|
-
readdirWithTypes: async ({ path:
|
|
6505
|
+
readdirWithTypes: async ({ path: path7 }) => {
|
|
6506
6506
|
try {
|
|
6507
|
-
const entries = await provider.readdirWithTypes(
|
|
6507
|
+
const entries = await provider.readdirWithTypes(path7);
|
|
6508
6508
|
return { entries };
|
|
6509
6509
|
} catch (err) {
|
|
6510
6510
|
return { entries: [], error: toSessionFsError(err) };
|
|
6511
6511
|
}
|
|
6512
6512
|
},
|
|
6513
|
-
rm: async ({ path:
|
|
6513
|
+
rm: async ({ path: path7, recursive, force }) => {
|
|
6514
6514
|
try {
|
|
6515
|
-
await provider.rm(
|
|
6515
|
+
await provider.rm(path7, recursive ?? false, force ?? false);
|
|
6516
6516
|
return void 0;
|
|
6517
6517
|
} catch (err) {
|
|
6518
6518
|
return toSessionFsError(err);
|
|
@@ -9367,9 +9367,9 @@ var init_dist = __esm({
|
|
|
9367
9367
|
});
|
|
9368
9368
|
|
|
9369
9369
|
// electron/terminal/server.ts
|
|
9370
|
-
var
|
|
9371
|
-
var
|
|
9372
|
-
var
|
|
9370
|
+
var path6 = __toESM(require("path"));
|
|
9371
|
+
var os4 = __toESM(require("os"));
|
|
9372
|
+
var fs5 = __toESM(require("fs"));
|
|
9373
9373
|
var crypto3 = __toESM(require("crypto"));
|
|
9374
9374
|
var import_child_process2 = require("child_process");
|
|
9375
9375
|
|
|
@@ -9566,6 +9566,53 @@ function formatToolStatus(toolName, args) {
|
|
|
9566
9566
|
return `Using ${toolName}`;
|
|
9567
9567
|
}
|
|
9568
9568
|
}
|
|
9569
|
+
function normalizeAskUserArgs(args) {
|
|
9570
|
+
const a = args ?? {};
|
|
9571
|
+
const questionRaw = a.question ?? a.prompt ?? a.message ?? a.text ?? "";
|
|
9572
|
+
const question = typeof questionRaw === "string" ? questionRaw : String(questionRaw ?? "");
|
|
9573
|
+
const rawOptions = a.options ?? a.choices ?? a.answers ?? a.selections ?? [];
|
|
9574
|
+
const options = [];
|
|
9575
|
+
if (Array.isArray(rawOptions)) {
|
|
9576
|
+
for (const opt of rawOptions) {
|
|
9577
|
+
if (typeof opt === "string") {
|
|
9578
|
+
options.push({ text: opt });
|
|
9579
|
+
} else if (opt && typeof opt === "object") {
|
|
9580
|
+
const o = opt;
|
|
9581
|
+
const text = o.text ?? o.label ?? o.value ?? o.name ?? "";
|
|
9582
|
+
options.push({ text: typeof text === "string" ? text : String(text ?? "") });
|
|
9583
|
+
}
|
|
9584
|
+
}
|
|
9585
|
+
}
|
|
9586
|
+
const freeformRaw = a.freeform ?? a.allowFreeform ?? a.allowFreeText ?? a.allowCustom ?? a.freeText ?? false;
|
|
9587
|
+
const freeform = Boolean(freeformRaw);
|
|
9588
|
+
return { question, options, freeform };
|
|
9589
|
+
}
|
|
9590
|
+
function buildAskUserRelay(event, backendName) {
|
|
9591
|
+
const d = event.data ?? {};
|
|
9592
|
+
if (event.type === "user_input.requested") {
|
|
9593
|
+
const options = Array.isArray(d.choices) ? d.choices.map((c) => ({
|
|
9594
|
+
text: typeof c === "string" ? c : String(c?.text ?? c?.label ?? c?.value ?? "")
|
|
9595
|
+
})) : [];
|
|
9596
|
+
return {
|
|
9597
|
+
toolId: String(d.toolCallId ?? ""),
|
|
9598
|
+
requestId: String(d.requestId ?? ""),
|
|
9599
|
+
question: String(d.question ?? ""),
|
|
9600
|
+
options,
|
|
9601
|
+
freeform: Boolean(d.allowFreeform)
|
|
9602
|
+
};
|
|
9603
|
+
}
|
|
9604
|
+
if (event.type === "tool.execution_start" && d.toolName === "ask_user" && backendName === "node-pty") {
|
|
9605
|
+
const norm = normalizeAskUserArgs(d.arguments);
|
|
9606
|
+
return {
|
|
9607
|
+
toolId: String(d.toolCallId ?? ""),
|
|
9608
|
+
requestId: "",
|
|
9609
|
+
question: norm.question,
|
|
9610
|
+
options: norm.options,
|
|
9611
|
+
freeform: norm.freeform
|
|
9612
|
+
};
|
|
9613
|
+
}
|
|
9614
|
+
return null;
|
|
9615
|
+
}
|
|
9569
9616
|
|
|
9570
9617
|
// electron/terminal/event-source.ts
|
|
9571
9618
|
var EVENT_METADATA_KEYS = /* @__PURE__ */ new Set(["type", "id", "timestamp", "parentId"]);
|
|
@@ -9642,23 +9689,232 @@ var FileWatcherEventSourceFactory = class {
|
|
|
9642
9689
|
|
|
9643
9690
|
// electron/terminal/terminal-backend.ts
|
|
9644
9691
|
var import_child_process = require("child_process");
|
|
9692
|
+
var os3 = __toESM(require("os"));
|
|
9693
|
+
var path4 = __toESM(require("path"));
|
|
9694
|
+
|
|
9695
|
+
// electron/terminal/custom-agents.ts
|
|
9696
|
+
var fs2 = __toESM(require("fs"));
|
|
9645
9697
|
var os2 = __toESM(require("os"));
|
|
9646
9698
|
var path2 = __toESM(require("path"));
|
|
9699
|
+
function parseAgentFrontmatter(content) {
|
|
9700
|
+
const normalized = content.replace(/\r\n/g, "\n");
|
|
9701
|
+
if (!normalized.startsWith("---\n") && normalized !== "---") {
|
|
9702
|
+
return { prompt: content.trim() };
|
|
9703
|
+
}
|
|
9704
|
+
const end = normalized.indexOf("\n---", 3);
|
|
9705
|
+
if (end === -1) {
|
|
9706
|
+
return { prompt: content.trim() };
|
|
9707
|
+
}
|
|
9708
|
+
const fmBlock = normalized.slice(4, end);
|
|
9709
|
+
const afterFence = normalized.indexOf("\n", end + 1);
|
|
9710
|
+
const prompt = (afterFence === -1 ? "" : normalized.slice(afterFence + 1)).trim();
|
|
9711
|
+
const raw = parseFrontmatterBlock(fmBlock);
|
|
9712
|
+
const out = { prompt };
|
|
9713
|
+
if (typeof raw.name === "string") out.name = raw.name;
|
|
9714
|
+
if (typeof raw.displayName === "string") out.displayName = raw.displayName;
|
|
9715
|
+
if (typeof raw.description === "string") out.description = raw.description;
|
|
9716
|
+
if (typeof raw.model === "string") out.model = raw.model;
|
|
9717
|
+
if (typeof raw.infer === "boolean") out.infer = raw.infer;
|
|
9718
|
+
if (Array.isArray(raw.tools)) out.tools = raw.tools.map(String);
|
|
9719
|
+
if (Array.isArray(raw.skills)) out.skills = raw.skills.map(String);
|
|
9720
|
+
return out;
|
|
9721
|
+
}
|
|
9722
|
+
function parseFrontmatterBlock(block) {
|
|
9723
|
+
const lines = block.split("\n");
|
|
9724
|
+
const result = {};
|
|
9725
|
+
let i = 0;
|
|
9726
|
+
const keyLine = /^([A-Za-z_][A-Za-z0-9_-]*):(.*)$/;
|
|
9727
|
+
while (i < lines.length) {
|
|
9728
|
+
const line = lines[i];
|
|
9729
|
+
if (!line.trim() || /^\s*#/.test(line)) {
|
|
9730
|
+
i++;
|
|
9731
|
+
continue;
|
|
9732
|
+
}
|
|
9733
|
+
const m = keyLine.exec(line);
|
|
9734
|
+
if (!m || /^\s/.test(line)) {
|
|
9735
|
+
i++;
|
|
9736
|
+
continue;
|
|
9737
|
+
}
|
|
9738
|
+
const key = m[1];
|
|
9739
|
+
const rest = m[2].trim();
|
|
9740
|
+
if (rest === ">" || rest === "|" || rest === ">-" || rest === "|-") {
|
|
9741
|
+
const folded = rest[0] === ">";
|
|
9742
|
+
const collected = [];
|
|
9743
|
+
i++;
|
|
9744
|
+
while (i < lines.length && (lines[i].trim() === "" || /^\s/.test(lines[i]))) {
|
|
9745
|
+
collected.push(lines[i].replace(/^\s+/, ""));
|
|
9746
|
+
i++;
|
|
9747
|
+
}
|
|
9748
|
+
while (collected.length && collected[collected.length - 1] === "") collected.pop();
|
|
9749
|
+
result[key] = folded ? collected.join(" ").replace(/\s+/g, " ").trim() : collected.join("\n");
|
|
9750
|
+
continue;
|
|
9751
|
+
}
|
|
9752
|
+
if (rest.startsWith("[") && rest.endsWith("]")) {
|
|
9753
|
+
result[key] = rest.slice(1, -1).split(",").map((s) => unquote(s.trim())).filter((s) => s.length > 0);
|
|
9754
|
+
i++;
|
|
9755
|
+
continue;
|
|
9756
|
+
}
|
|
9757
|
+
if (rest === "") {
|
|
9758
|
+
const items = [];
|
|
9759
|
+
let j = i + 1;
|
|
9760
|
+
while (j < lines.length && (lines[j].trim() === "" || /^\s/.test(lines[j]))) {
|
|
9761
|
+
const item = /^\s*-\s+(.*)$/.exec(lines[j]);
|
|
9762
|
+
if (item) items.push(unquote(item[1].trim()));
|
|
9763
|
+
else if (lines[j].trim() === "") {
|
|
9764
|
+
} else break;
|
|
9765
|
+
j++;
|
|
9766
|
+
}
|
|
9767
|
+
if (items.length > 0) {
|
|
9768
|
+
result[key] = items;
|
|
9769
|
+
i = j;
|
|
9770
|
+
continue;
|
|
9771
|
+
}
|
|
9772
|
+
result[key] = "";
|
|
9773
|
+
i++;
|
|
9774
|
+
continue;
|
|
9775
|
+
}
|
|
9776
|
+
result[key] = coerceScalar(unquote(rest));
|
|
9777
|
+
i++;
|
|
9778
|
+
}
|
|
9779
|
+
return result;
|
|
9780
|
+
}
|
|
9781
|
+
function unquote(s) {
|
|
9782
|
+
if (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'")) {
|
|
9783
|
+
return s.slice(1, -1);
|
|
9784
|
+
}
|
|
9785
|
+
return s;
|
|
9786
|
+
}
|
|
9787
|
+
function coerceScalar(s) {
|
|
9788
|
+
if (s === "true") return true;
|
|
9789
|
+
if (s === "false") return false;
|
|
9790
|
+
return s;
|
|
9791
|
+
}
|
|
9792
|
+
function toCustomAgentConfig(parsed, fallbackName) {
|
|
9793
|
+
const name = parsed.name || fallbackName;
|
|
9794
|
+
if (!name || !parsed.prompt) return null;
|
|
9795
|
+
const config = {
|
|
9796
|
+
name,
|
|
9797
|
+
prompt: parsed.prompt
|
|
9798
|
+
};
|
|
9799
|
+
if (parsed.displayName) config.displayName = parsed.displayName;
|
|
9800
|
+
if (parsed.description) config.description = parsed.description;
|
|
9801
|
+
if (parsed.tools && parsed.tools.length > 0) config.tools = parsed.tools;
|
|
9802
|
+
if (parsed.model) config.model = parsed.model;
|
|
9803
|
+
if (typeof parsed.infer === "boolean") config.infer = parsed.infer;
|
|
9804
|
+
if (parsed.skills && parsed.skills.length > 0) config.skills = parsed.skills;
|
|
9805
|
+
return config;
|
|
9806
|
+
}
|
|
9807
|
+
function resolveCopilotHome(env = process.env, homeDir = os2.homedir()) {
|
|
9808
|
+
const override = env.COPILOT_HOME?.trim();
|
|
9809
|
+
if (override) return override;
|
|
9810
|
+
return path2.join(homeDir, ".copilot");
|
|
9811
|
+
}
|
|
9812
|
+
function customAgentDirs(cwd, copilotHome = resolveCopilotHome()) {
|
|
9813
|
+
const dirs = [path2.join(copilotHome, "agents")];
|
|
9814
|
+
if (cwd) {
|
|
9815
|
+
dirs.push(path2.join(cwd, ".github", "agents"));
|
|
9816
|
+
}
|
|
9817
|
+
return dirs;
|
|
9818
|
+
}
|
|
9819
|
+
function loadCustomAgents(cwd, copilotHome = resolveCopilotHome()) {
|
|
9820
|
+
const byName = /* @__PURE__ */ new Map();
|
|
9821
|
+
for (const dir of customAgentDirs(cwd, copilotHome)) {
|
|
9822
|
+
let entries;
|
|
9823
|
+
try {
|
|
9824
|
+
entries = fs2.readdirSync(dir);
|
|
9825
|
+
} catch {
|
|
9826
|
+
continue;
|
|
9827
|
+
}
|
|
9828
|
+
for (const entry of entries) {
|
|
9829
|
+
if (!entry.toLowerCase().endsWith(".agent.md")) continue;
|
|
9830
|
+
const full = path2.join(dir, entry);
|
|
9831
|
+
let content;
|
|
9832
|
+
try {
|
|
9833
|
+
content = fs2.readFileSync(full, "utf8");
|
|
9834
|
+
} catch {
|
|
9835
|
+
continue;
|
|
9836
|
+
}
|
|
9837
|
+
const fallbackName = entry.slice(0, -".agent.md".length);
|
|
9838
|
+
const config = toCustomAgentConfig(parseAgentFrontmatter(content), fallbackName);
|
|
9839
|
+
if (config && !byName.has(config.name)) {
|
|
9840
|
+
byName.set(config.name, config);
|
|
9841
|
+
}
|
|
9842
|
+
}
|
|
9843
|
+
}
|
|
9844
|
+
return [...byName.values()];
|
|
9845
|
+
}
|
|
9846
|
+
|
|
9847
|
+
// electron/terminal/custom-skills.ts
|
|
9848
|
+
var fs3 = __toESM(require("fs"));
|
|
9849
|
+
var path3 = __toESM(require("path"));
|
|
9850
|
+
function skillDirs(cwd, copilotHome = resolveCopilotHome()) {
|
|
9851
|
+
const dirs = [];
|
|
9852
|
+
if (cwd) {
|
|
9853
|
+
dirs.push(path3.join(cwd, ".github", "skills"));
|
|
9854
|
+
}
|
|
9855
|
+
dirs.push(path3.join(copilotHome, "skills"));
|
|
9856
|
+
return dirs;
|
|
9857
|
+
}
|
|
9858
|
+
function resolveSkillDirectories(cwd, copilotHome = resolveCopilotHome()) {
|
|
9859
|
+
const out = [];
|
|
9860
|
+
for (const dir of skillDirs(cwd, copilotHome)) {
|
|
9861
|
+
try {
|
|
9862
|
+
if (fs3.statSync(dir).isDirectory()) {
|
|
9863
|
+
out.push(dir);
|
|
9864
|
+
}
|
|
9865
|
+
} catch {
|
|
9866
|
+
}
|
|
9867
|
+
}
|
|
9868
|
+
return out;
|
|
9869
|
+
}
|
|
9870
|
+
|
|
9871
|
+
// electron/terminal/terminal-backend.ts
|
|
9872
|
+
var pendingUserInput = /* @__PURE__ */ new Map();
|
|
9873
|
+
function makeUserInputHandler(sessionId) {
|
|
9874
|
+
return (_request, ctx) => new Promise((resolve) => {
|
|
9875
|
+
const scope = sessionId || ctx?.sessionId || "";
|
|
9876
|
+
const existing = pendingUserInput.get(scope);
|
|
9877
|
+
if (existing) {
|
|
9878
|
+
console.warn(
|
|
9879
|
+
`[terminal-backend] makeUserInputHandler: replacing an UNRESOLVED pending user-input for session="${scope}" (its promise will never resolve)`
|
|
9880
|
+
);
|
|
9881
|
+
}
|
|
9882
|
+
pendingUserInput.set(scope, { resolve, sessionId: scope });
|
|
9883
|
+
});
|
|
9884
|
+
}
|
|
9885
|
+
function handlePendingUserInput(sessionId, answer) {
|
|
9886
|
+
const entry = pendingUserInput.get(sessionId);
|
|
9887
|
+
if (!entry) {
|
|
9888
|
+
console.warn(
|
|
9889
|
+
`[terminal-backend] handlePendingUserInput: no pending user-input for session="${sessionId}" (already resolved or unknown) \u2014 no-op`
|
|
9890
|
+
);
|
|
9891
|
+
return false;
|
|
9892
|
+
}
|
|
9893
|
+
pendingUserInput.delete(sessionId);
|
|
9894
|
+
entry.resolve({ answer: answer.answer, wasFreeform: answer.wasFreeform });
|
|
9895
|
+
return true;
|
|
9896
|
+
}
|
|
9897
|
+
function clearPendingUserInputForSession(sessionId) {
|
|
9898
|
+
return pendingUserInput.delete(sessionId) ? 1 : 0;
|
|
9899
|
+
}
|
|
9900
|
+
function answerTransport(proc) {
|
|
9901
|
+
return typeof proc.submitPrompt === "function" ? "sdk" : "keystroke";
|
|
9902
|
+
}
|
|
9647
9903
|
function splitPathEntries(pathValue) {
|
|
9648
|
-
return pathValue.split(
|
|
9904
|
+
return pathValue.split(path4.delimiter).filter(Boolean);
|
|
9649
9905
|
}
|
|
9650
9906
|
function normalizeEntry(entry) {
|
|
9651
|
-
return
|
|
9907
|
+
return path4.normalize(entry).replace(/[\\\/]+$/, "");
|
|
9652
9908
|
}
|
|
9653
9909
|
function getRepoNodeModulesBin(repoRoot) {
|
|
9654
|
-
return normalizeEntry(
|
|
9910
|
+
return normalizeEntry(path4.join(repoRoot, "node_modules", ".bin"));
|
|
9655
9911
|
}
|
|
9656
9912
|
function isRepoNodeModulesBin(entry, repoRoot) {
|
|
9657
9913
|
return normalizeEntry(entry).toLowerCase() === getRepoNodeModulesBin(repoRoot).toLowerCase();
|
|
9658
9914
|
}
|
|
9659
9915
|
function sanitizeCopilotPath(pathValue, repoRoot) {
|
|
9660
9916
|
if (!pathValue) return "";
|
|
9661
|
-
return splitPathEntries(pathValue).filter((entry) => !isRepoNodeModulesBin(entry, repoRoot)).join(
|
|
9917
|
+
return splitPathEntries(pathValue).filter((entry) => !isRepoNodeModulesBin(entry, repoRoot)).join(path4.delimiter);
|
|
9662
9918
|
}
|
|
9663
9919
|
function resolveBundledCopilotCliPath() {
|
|
9664
9920
|
try {
|
|
@@ -9677,9 +9933,9 @@ function resolveCopilotCliPath(repoRoot, pathValue) {
|
|
|
9677
9933
|
const sanitizedPath = sanitizeCopilotPath(pathValue, repoRoot);
|
|
9678
9934
|
const env = { ...process.env, PATH: sanitizedPath };
|
|
9679
9935
|
try {
|
|
9680
|
-
const command =
|
|
9936
|
+
const command = os3.platform() === "win32" ? "where.exe copilot" : "which -a copilot";
|
|
9681
9937
|
const output = (0, import_child_process.execSync)(command, { encoding: "utf8", env, stdio: ["ignore", "pipe", "ignore"] });
|
|
9682
|
-
const candidates = output.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).filter((candidate) => !candidate.toLowerCase().includes(`${
|
|
9938
|
+
const candidates = output.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).filter((candidate) => !candidate.toLowerCase().includes(`${path4.sep}node_modules${path4.sep}.bin${path4.sep}copilot`.toLowerCase()));
|
|
9683
9939
|
return candidates[0] || null;
|
|
9684
9940
|
} catch {
|
|
9685
9941
|
return null;
|
|
@@ -9731,7 +9987,7 @@ var NodePtyProcess = class {
|
|
|
9731
9987
|
}
|
|
9732
9988
|
kill() {
|
|
9733
9989
|
try {
|
|
9734
|
-
if (
|
|
9990
|
+
if (os3.platform() === "win32") {
|
|
9735
9991
|
try {
|
|
9736
9992
|
(0, import_child_process.execSync)(`taskkill /T /F /PID ${this.proc.pid}`, { stdio: "ignore" });
|
|
9737
9993
|
} catch {
|
|
@@ -9986,7 +10242,21 @@ var CopilotSdkBackend = class _CopilotSdkBackend {
|
|
|
9986
10242
|
const sharedConfig = {
|
|
9987
10243
|
streaming: true,
|
|
9988
10244
|
workingDirectory: options.cwd,
|
|
9989
|
-
|
|
10245
|
+
// Inject the user's custom agents (~/.copilot/agents + <cwd>/.github/agents).
|
|
10246
|
+
// SDK-created sessions don't auto-discover them the way the TUI does, so
|
|
10247
|
+
// without this "New Session" loses every custom agent. See ./custom-agents.
|
|
10248
|
+
customAgents: loadCustomAgents(options.cwd),
|
|
10249
|
+
// Inject the user's skills too (~/.copilot/skills + <cwd>/.github/skills).
|
|
10250
|
+
// SDK-created sessions don't auto-discover them (enableConfigDiscovery
|
|
10251
|
+
// defaults to false), so without this the model never loads any skill even
|
|
10252
|
+
// though the hosted TUI's `/` menu still lists them. See ./custom-skills.
|
|
10253
|
+
enableSkills: true,
|
|
10254
|
+
skillDirectories: resolveSkillDirectories(options.cwd),
|
|
10255
|
+
onPermissionRequest: this.approveAll ?? (async () => ({ kind: "approved" })),
|
|
10256
|
+
// spec 015 prerequisite (forStdio path): register the user-input handler so
|
|
10257
|
+
// the model is told `ask_user` is available and Teams/local answers can
|
|
10258
|
+
// resolve the pending interaction late. See makeUserInputHandler.
|
|
10259
|
+
onUserInputRequest: makeUserInputHandler(options.sessionId)
|
|
9990
10260
|
};
|
|
9991
10261
|
try {
|
|
9992
10262
|
return await client.resumeSession(options.sessionId, sharedConfig);
|
|
@@ -10081,7 +10351,7 @@ var UiServerHostRuntime = class {
|
|
|
10081
10351
|
this.status = "stopped";
|
|
10082
10352
|
clearTimeout(this.listeningTimeout);
|
|
10083
10353
|
try {
|
|
10084
|
-
if (
|
|
10354
|
+
if (os3.platform() === "win32") {
|
|
10085
10355
|
try {
|
|
10086
10356
|
(0, import_child_process.execSync)(`taskkill /T /F /PID ${this.proc.pid}`, { stdio: "ignore" });
|
|
10087
10357
|
} catch {
|
|
@@ -10120,7 +10390,20 @@ var ControlPlaneClient = class {
|
|
|
10120
10390
|
const sharedConfig = {
|
|
10121
10391
|
streaming: true,
|
|
10122
10392
|
workingDirectory: cwd,
|
|
10123
|
-
|
|
10393
|
+
// Inject the user's custom agents (~/.copilot/agents + <cwd>/.github/agents)
|
|
10394
|
+
// so SDK-created ("New Session") sessions expose them like the TUI does.
|
|
10395
|
+
customAgents: loadCustomAgents(cwd),
|
|
10396
|
+
// Inject the user's skills too (~/.copilot/skills + <cwd>/.github/skills)
|
|
10397
|
+
// so SDK-created ("New Session") sessions load them like the TUI does.
|
|
10398
|
+
// See ./custom-skills.
|
|
10399
|
+
enableSkills: true,
|
|
10400
|
+
skillDirectories: resolveSkillDirectories(cwd),
|
|
10401
|
+
onPermissionRequest,
|
|
10402
|
+
// spec 015 prerequisite: advertise `ask_user` (requestUserInput: true) and
|
|
10403
|
+
// provide the late-resolvable answer channel. Without this the model refuses
|
|
10404
|
+
// to call ask_user. The relay of the question itself rides the normal event
|
|
10405
|
+
// stream (user_input.requested → server watcherCallback).
|
|
10406
|
+
onUserInputRequest: makeUserInputHandler(sessionId)
|
|
10124
10407
|
};
|
|
10125
10408
|
try {
|
|
10126
10409
|
return await client.resumeSession(sessionId, sharedConfig);
|
|
@@ -10320,8 +10603,8 @@ var UiServerBackend = class _UiServerBackend {
|
|
|
10320
10603
|
}
|
|
10321
10604
|
};
|
|
10322
10605
|
function createSdkCliLaunchConfig(cliPath) {
|
|
10323
|
-
if (
|
|
10324
|
-
const commandProcessor = process.env.ComSpec ||
|
|
10606
|
+
if (os3.platform() === "win32" && /\.(bat|cmd)$/i.test(cliPath)) {
|
|
10607
|
+
const commandProcessor = process.env.ComSpec || path4.join(process.env.WINDIR || "C:\\Windows", "System32", "cmd.exe");
|
|
10325
10608
|
return {
|
|
10326
10609
|
cliPath: commandProcessor,
|
|
10327
10610
|
cliArgs: ["/c", cliPath]
|
|
@@ -10361,6 +10644,12 @@ function hasActiveViewer(ck, maps) {
|
|
|
10361
10644
|
function shouldForwardSharedHostData(ck, foreground) {
|
|
10362
10645
|
return foreground === void 0 || foreground === ck;
|
|
10363
10646
|
}
|
|
10647
|
+
function foregroundAfterStart(currentForeground, startingCk) {
|
|
10648
|
+
return currentForeground ?? startingCk;
|
|
10649
|
+
}
|
|
10650
|
+
function shouldReassertForeground(intendedForeground, startingCk) {
|
|
10651
|
+
return intendedForeground !== void 0 && intendedForeground !== startingCk;
|
|
10652
|
+
}
|
|
10364
10653
|
|
|
10365
10654
|
// electron/terminal/session-repair.ts
|
|
10366
10655
|
var crypto = __toESM(require("crypto"));
|
|
@@ -10391,12 +10680,12 @@ function repairDuplicateSessionIds(officeId, data, options = {}) {
|
|
|
10391
10680
|
|
|
10392
10681
|
// electron/terminal/pty-registry.ts
|
|
10393
10682
|
var crypto2 = __toESM(require("crypto"));
|
|
10394
|
-
var
|
|
10395
|
-
var
|
|
10396
|
-
var DEFAULT_REGISTRY_FILE =
|
|
10683
|
+
var fs4 = __toESM(require("fs"));
|
|
10684
|
+
var path5 = __toESM(require("path"));
|
|
10685
|
+
var DEFAULT_REGISTRY_FILE = path5.join(process.cwd(), ".data", "pty-pids.json");
|
|
10397
10686
|
function readPtyRegistry(file = DEFAULT_REGISTRY_FILE) {
|
|
10398
10687
|
try {
|
|
10399
|
-
const raw =
|
|
10688
|
+
const raw = fs4.readFileSync(file, "utf8");
|
|
10400
10689
|
const parsed = JSON.parse(raw);
|
|
10401
10690
|
if (!Array.isArray(parsed)) return [];
|
|
10402
10691
|
return parsed.filter(
|
|
@@ -10408,10 +10697,10 @@ function readPtyRegistry(file = DEFAULT_REGISTRY_FILE) {
|
|
|
10408
10697
|
}
|
|
10409
10698
|
function writePtyRegistry(records, file = DEFAULT_REGISTRY_FILE) {
|
|
10410
10699
|
try {
|
|
10411
|
-
|
|
10700
|
+
fs4.mkdirSync(path5.dirname(file), { recursive: true });
|
|
10412
10701
|
const tmp = `${file}.${process.pid}.${crypto2.randomBytes(4).toString("hex")}.tmp`;
|
|
10413
|
-
|
|
10414
|
-
|
|
10702
|
+
fs4.writeFileSync(tmp, JSON.stringify(records, null, 2));
|
|
10703
|
+
fs4.renameSync(tmp, file);
|
|
10415
10704
|
} catch {
|
|
10416
10705
|
}
|
|
10417
10706
|
}
|
|
@@ -10466,13 +10755,13 @@ function normalizePromptText(s) {
|
|
|
10466
10755
|
var MAX_BUFFER_BYTES = 512 * 1024;
|
|
10467
10756
|
var agentScrollbackBuffers = /* @__PURE__ */ new Map();
|
|
10468
10757
|
var agentScrollbackBytes = /* @__PURE__ */ new Map();
|
|
10469
|
-
var DATA_DIR =
|
|
10470
|
-
var OLD_SESSION_FILE =
|
|
10471
|
-
var OFFICES_FILE =
|
|
10758
|
+
var DATA_DIR = path6.join(process.cwd(), ".data");
|
|
10759
|
+
var OLD_SESSION_FILE = path6.join(DATA_DIR, "copilot-office-sessions.json");
|
|
10760
|
+
var OFFICES_FILE = path6.join(DATA_DIR, "copilot-offices.json");
|
|
10472
10761
|
var officeSessions = /* @__PURE__ */ new Map();
|
|
10473
10762
|
var hasAutoTitled = /* @__PURE__ */ new Set();
|
|
10474
10763
|
function getSessionFile(officeId) {
|
|
10475
|
-
return
|
|
10764
|
+
return path6.join(DATA_DIR, `${officeId}.sessions.json`);
|
|
10476
10765
|
}
|
|
10477
10766
|
function getOfficeSession(officeId) {
|
|
10478
10767
|
let data = officeSessions.get(officeId);
|
|
@@ -10513,9 +10802,9 @@ function appendToScrollback(agentId, data) {
|
|
|
10513
10802
|
}
|
|
10514
10803
|
async function loadOfficeSessionFile(officeId) {
|
|
10515
10804
|
try {
|
|
10516
|
-
await
|
|
10805
|
+
await fs5.promises.mkdir(DATA_DIR, { recursive: true });
|
|
10517
10806
|
const filePath = getSessionFile(officeId);
|
|
10518
|
-
const raw = await
|
|
10807
|
+
const raw = await fs5.promises.readFile(filePath, "utf8").catch(() => null);
|
|
10519
10808
|
const data = getOfficeSession(officeId);
|
|
10520
10809
|
if (raw) {
|
|
10521
10810
|
const parsed = JSON.parse(raw);
|
|
@@ -10545,27 +10834,27 @@ async function loadOfficeSessionFile(officeId) {
|
|
|
10545
10834
|
}
|
|
10546
10835
|
async function saveOfficeSessionFile(officeId) {
|
|
10547
10836
|
try {
|
|
10548
|
-
await
|
|
10837
|
+
await fs5.promises.mkdir(DATA_DIR, { recursive: true });
|
|
10549
10838
|
const data = getOfficeSession(officeId);
|
|
10550
10839
|
const json = {
|
|
10551
10840
|
current: Object.fromEntries(data.sessionIds),
|
|
10552
10841
|
history: Object.fromEntries(data.sessionHistory),
|
|
10553
10842
|
metadata: Object.fromEntries(data.sessionMeta)
|
|
10554
10843
|
};
|
|
10555
|
-
await
|
|
10844
|
+
await fs5.promises.writeFile(getSessionFile(officeId), JSON.stringify(json, null, 2));
|
|
10556
10845
|
} catch (e) {
|
|
10557
10846
|
console.error(`[TermServer] Failed to save sessions for ${officeId}:`, e);
|
|
10558
10847
|
}
|
|
10559
10848
|
}
|
|
10560
10849
|
async function createEmptySessionFile(officeId) {
|
|
10561
|
-
await
|
|
10850
|
+
await fs5.promises.mkdir(DATA_DIR, { recursive: true });
|
|
10562
10851
|
const filePath = getSessionFile(officeId);
|
|
10563
10852
|
try {
|
|
10564
|
-
await
|
|
10853
|
+
await fs5.promises.access(filePath, fs5.constants.F_OK);
|
|
10565
10854
|
await loadOfficeSessionFile(officeId);
|
|
10566
10855
|
} catch {
|
|
10567
10856
|
const empty = { current: {}, history: {}, metadata: {} };
|
|
10568
|
-
await
|
|
10857
|
+
await fs5.promises.writeFile(filePath, JSON.stringify(empty, null, 2));
|
|
10569
10858
|
getOfficeSession(officeId);
|
|
10570
10859
|
console.log(`[TermServer] Created empty session file for ${officeId}: ${filePath}`);
|
|
10571
10860
|
}
|
|
@@ -10585,19 +10874,19 @@ async function migrateGlobalSessionFile() {
|
|
|
10585
10874
|
try {
|
|
10586
10875
|
const migratedMarker = OLD_SESSION_FILE + ".migrated";
|
|
10587
10876
|
try {
|
|
10588
|
-
await
|
|
10877
|
+
await fs5.promises.access(migratedMarker, fs5.constants.F_OK);
|
|
10589
10878
|
return;
|
|
10590
10879
|
} catch {
|
|
10591
10880
|
}
|
|
10592
10881
|
let oldRaw = null;
|
|
10593
10882
|
try {
|
|
10594
|
-
oldRaw = await
|
|
10883
|
+
oldRaw = await fs5.promises.readFile(OLD_SESSION_FILE, "utf8");
|
|
10595
10884
|
} catch {
|
|
10596
10885
|
return;
|
|
10597
10886
|
}
|
|
10598
10887
|
let firstOfficeId = "office-0";
|
|
10599
10888
|
try {
|
|
10600
|
-
const officesRaw = await
|
|
10889
|
+
const officesRaw = await fs5.promises.readFile(OFFICES_FILE, "utf8");
|
|
10601
10890
|
const officesData = JSON.parse(officesRaw);
|
|
10602
10891
|
if (Array.isArray(officesData.offices) && officesData.offices.length > 0) {
|
|
10603
10892
|
firstOfficeId = officesData.offices[0].id || "office-0";
|
|
@@ -10606,22 +10895,22 @@ async function migrateGlobalSessionFile() {
|
|
|
10606
10895
|
}
|
|
10607
10896
|
const firstOfficeFile = getSessionFile(firstOfficeId);
|
|
10608
10897
|
try {
|
|
10609
|
-
await
|
|
10898
|
+
await fs5.promises.access(firstOfficeFile, fs5.constants.F_OK);
|
|
10610
10899
|
} catch {
|
|
10611
|
-
await
|
|
10900
|
+
await fs5.promises.writeFile(firstOfficeFile, oldRaw);
|
|
10612
10901
|
console.log(`[TermServer] Migrated global sessions to ${firstOfficeFile}`);
|
|
10613
10902
|
}
|
|
10614
|
-
await
|
|
10903
|
+
await fs5.promises.rename(OLD_SESSION_FILE, migratedMarker);
|
|
10615
10904
|
console.log(`[TermServer] Renamed old session file to ${migratedMarker}`);
|
|
10616
10905
|
} catch (e) {
|
|
10617
10906
|
console.error("[TermServer] Migration error:", e);
|
|
10618
10907
|
}
|
|
10619
10908
|
}
|
|
10620
10909
|
async function loadAllOfficeSessions() {
|
|
10621
|
-
await
|
|
10910
|
+
await fs5.promises.mkdir(DATA_DIR, { recursive: true });
|
|
10622
10911
|
await migrateGlobalSessionFile();
|
|
10623
10912
|
try {
|
|
10624
|
-
const files = await
|
|
10913
|
+
const files = await fs5.promises.readdir(DATA_DIR);
|
|
10625
10914
|
for (const file of files) {
|
|
10626
10915
|
const match = file.match(/^(.+)\.sessions\.json$/);
|
|
10627
10916
|
if (match) {
|
|
@@ -10746,12 +11035,12 @@ async function startTerminalForAgentImpl(officeId, agentId, workingDir, cols, ro
|
|
|
10746
11035
|
}
|
|
10747
11036
|
}
|
|
10748
11037
|
const terminalKey = ck;
|
|
10749
|
-
const shell =
|
|
11038
|
+
const shell = os4.platform() === "win32" ? "powershell.exe" : "bash";
|
|
10750
11039
|
let cwd = process.cwd();
|
|
10751
11040
|
if (workingDir) {
|
|
10752
|
-
const customPath =
|
|
11041
|
+
const customPath = path6.isAbsolute(workingDir) ? workingDir : path6.join(process.cwd(), workingDir);
|
|
10753
11042
|
try {
|
|
10754
|
-
await
|
|
11043
|
+
await fs5.promises.access(customPath, fs5.constants.F_OK);
|
|
10755
11044
|
cwd = customPath;
|
|
10756
11045
|
} catch {
|
|
10757
11046
|
}
|
|
@@ -10810,7 +11099,7 @@ async function startTerminalForAgentImpl(officeId, agentId, workingDir, cols, ro
|
|
|
10810
11099
|
agentToTerminal.set(ck, terminalKey);
|
|
10811
11100
|
if (activeBackend.name === "ui-server") {
|
|
10812
11101
|
const intendedCk = officeForegroundCk.get(officeId);
|
|
10813
|
-
if (intendedCk
|
|
11102
|
+
if (shouldReassertForeground(intendedCk, ck)) {
|
|
10814
11103
|
const fgKey = agentToTerminal.get(intendedCk);
|
|
10815
11104
|
const fgProc = fgKey ? ptyProcesses.get(fgKey) : null;
|
|
10816
11105
|
if (fgProc && typeof fgProc.process.setForeground === "function") {
|
|
@@ -10874,6 +11163,22 @@ async function startTerminalForAgentImpl(officeId, agentId, workingDir, cols, ro
|
|
|
10874
11163
|
const d = event.data;
|
|
10875
11164
|
console.log(`[TermServer] Forwarding tool_start for ${ck}: ${d.toolName}`);
|
|
10876
11165
|
send({ type: "copilot-tool-start", agentId, toolName: d.toolName, toolId: d.toolCallId, status: formatToolStatus(d.toolName, d.arguments) });
|
|
11166
|
+
const askRelay = buildAskUserRelay(event, activeBackend.name);
|
|
11167
|
+
if (askRelay) {
|
|
11168
|
+
send({ type: "copilot-ask-user", agentId, toolId: askRelay.toolId, requestId: askRelay.requestId, question: askRelay.question, options: askRelay.options, freeform: askRelay.freeform });
|
|
11169
|
+
}
|
|
11170
|
+
} else if (event.type === "user_input.requested") {
|
|
11171
|
+
const askRelay = buildAskUserRelay(event, activeBackend.name);
|
|
11172
|
+
if (askRelay) {
|
|
11173
|
+
console.log(`[TermServer] Forwarding ask_user (user_input.requested) for ${ck}: requestId=${askRelay.requestId}, ${askRelay.options.length} option(s)`);
|
|
11174
|
+
send({ type: "copilot-tool-start", agentId, toolName: "ask_user", toolId: askRelay.toolId, status: "Waiting for your answer" });
|
|
11175
|
+
send({ type: "copilot-ask-user", agentId, toolId: askRelay.toolId, requestId: askRelay.requestId, question: askRelay.question, options: askRelay.options, freeform: askRelay.freeform });
|
|
11176
|
+
}
|
|
11177
|
+
} else if (event.type === "user_input.completed") {
|
|
11178
|
+
const d = event.data ?? {};
|
|
11179
|
+
const completedRequestId = d.requestId != null ? String(d.requestId) : "";
|
|
11180
|
+
console.log(`[TermServer] Forwarding ask_user complete (user_input.completed) for ${ck}: requestId=${completedRequestId}`);
|
|
11181
|
+
send({ type: "copilot-ask-user-complete", agentId, requestId: completedRequestId });
|
|
10877
11182
|
} else if (event.type === "tool.execution_complete") {
|
|
10878
11183
|
const d = event.data;
|
|
10879
11184
|
console.log(`[TermServer] Forwarding tool_complete for ${ck}: ${d.toolCallId}`);
|
|
@@ -10951,8 +11256,8 @@ async function startTerminalForAgentImpl(officeId, agentId, workingDir, cols, ro
|
|
|
10951
11256
|
pendingData = "";
|
|
10952
11257
|
};
|
|
10953
11258
|
const isSharedHostBackend = activeBackend.name === "ui-server";
|
|
10954
|
-
if (isSharedHostBackend
|
|
10955
|
-
officeForegroundCk.set(officeId, ck);
|
|
11259
|
+
if (isSharedHostBackend) {
|
|
11260
|
+
officeForegroundCk.set(officeId, foregroundAfterStart(officeForegroundCk.get(officeId), ck));
|
|
10956
11261
|
}
|
|
10957
11262
|
proc.onData((data) => {
|
|
10958
11263
|
if (isSharedHostBackend && !shouldForwardSharedHostData(ck, officeForegroundCk.get(officeId))) {
|
|
@@ -10995,6 +11300,10 @@ async function startTerminalForAgentImpl(officeId, agentId, workingDir, cols, ro
|
|
|
10995
11300
|
w.stop();
|
|
10996
11301
|
agentWatchers.delete(ck);
|
|
10997
11302
|
}
|
|
11303
|
+
const dropped = clearPendingUserInputForSession(sessionId);
|
|
11304
|
+
if (dropped > 0) {
|
|
11305
|
+
console.log(`[TermServer] Cleared ${dropped} pending ask_user interaction(s) for exited session ${sessionId} (${ck})`);
|
|
11306
|
+
}
|
|
10998
11307
|
});
|
|
10999
11308
|
if (!shellOnlyMode && activeBackend.name === "node-pty") {
|
|
11000
11309
|
setTimeout(() => {
|
|
@@ -11051,6 +11360,29 @@ async function handleMessage(msg) {
|
|
|
11051
11360
|
}
|
|
11052
11361
|
break;
|
|
11053
11362
|
}
|
|
11363
|
+
case "submit-answer": {
|
|
11364
|
+
const key = getTerminalKey(msg.officeId, msg.agentId);
|
|
11365
|
+
const proc = key ? ptyProcesses.get(key) : null;
|
|
11366
|
+
if (proc) {
|
|
11367
|
+
agentForwardKeys.add(compositeKey(msg.officeId, msg.agentId));
|
|
11368
|
+
const backendProc = proc.process;
|
|
11369
|
+
if (answerTransport(backendProc) === "sdk") {
|
|
11370
|
+
const resolved = handlePendingUserInput(proc.sessionId, { answer: msg.answer, wasFreeform: msg.wasFreeform });
|
|
11371
|
+
if (!resolved) {
|
|
11372
|
+
console.warn(`[TermServer] submit-answer: no pending user-input for session="${proc.sessionId}" (answerRequestId="${msg.answerRequestId ?? ""}", ${compositeKey(msg.officeId, msg.agentId)}) \u2014 no-op (already resolved or unknown)`);
|
|
11373
|
+
}
|
|
11374
|
+
send({ type: "response", requestId: msg.requestId, result: { success: resolved, error: resolved ? void 0 : "no pending user-input to resolve" } });
|
|
11375
|
+
} else {
|
|
11376
|
+
submitViaKeystrokes(backendProc, msg.answer, key);
|
|
11377
|
+
send({ type: "response", requestId: msg.requestId, result: { success: true } });
|
|
11378
|
+
}
|
|
11379
|
+
} else {
|
|
11380
|
+
const ck = compositeKey(msg.officeId, msg.agentId);
|
|
11381
|
+
console.log(`[TermServer] SUBMIT-ANSWER FAILED \u2014 no PTY for ${ck}`);
|
|
11382
|
+
send({ type: "response", requestId: msg.requestId, result: { success: false, error: `No PTY for ${ck}` } });
|
|
11383
|
+
}
|
|
11384
|
+
break;
|
|
11385
|
+
}
|
|
11054
11386
|
case "set-agent-forwarding": {
|
|
11055
11387
|
const ck = compositeKey(msg.officeId, msg.agentId);
|
|
11056
11388
|
if (msg.enabled) agentForwardKeys.add(ck);
|
|
@@ -11181,9 +11513,9 @@ async function handleMessage(msg) {
|
|
|
11181
11513
|
const ptyProc = termKey ? ptyProcesses.get(termKey) : null;
|
|
11182
11514
|
let cwd = process.cwd();
|
|
11183
11515
|
if (ptyProc?.workingDir) {
|
|
11184
|
-
const customPath =
|
|
11516
|
+
const customPath = path6.join(process.cwd(), ptyProc.workingDir);
|
|
11185
11517
|
try {
|
|
11186
|
-
await
|
|
11518
|
+
await fs5.promises.access(customPath, fs5.constants.F_OK);
|
|
11187
11519
|
cwd = customPath;
|
|
11188
11520
|
} catch {
|
|
11189
11521
|
}
|
|
@@ -11352,7 +11684,7 @@ async function handleMessage(msg) {
|
|
|
11352
11684
|
case "delete-office-session": {
|
|
11353
11685
|
const filePath = getSessionFile(msg.officeId);
|
|
11354
11686
|
try {
|
|
11355
|
-
await
|
|
11687
|
+
await fs5.promises.unlink(filePath);
|
|
11356
11688
|
officeSessions.delete(msg.officeId);
|
|
11357
11689
|
console.log(`[TermServer] Deleted session file for ${msg.officeId}`);
|
|
11358
11690
|
} catch {
|