copilotoffice 1.1.0 → 2.0.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/dist/electron/main.js +114 -56
- package/dist/electron/terminal/preload.js +12 -0
- package/dist/electron/terminal/server.js +104 -30
- package/dist/game.bundle.js +1936 -385
- package/package.json +3 -3
package/dist/game.bundle.js
CHANGED
|
@@ -121442,23 +121442,23 @@ var CopilotOffice = (() => {
|
|
|
121442
121442
|
* @return {Phaser.Textures.Frame} A clone of this Frame.
|
|
121443
121443
|
*/
|
|
121444
121444
|
clone: function() {
|
|
121445
|
-
var
|
|
121446
|
-
|
|
121447
|
-
|
|
121448
|
-
|
|
121449
|
-
|
|
121450
|
-
|
|
121451
|
-
|
|
121452
|
-
|
|
121453
|
-
|
|
121454
|
-
|
|
121455
|
-
|
|
121456
|
-
|
|
121457
|
-
|
|
121458
|
-
|
|
121459
|
-
|
|
121460
|
-
|
|
121461
|
-
return
|
|
121445
|
+
var clone2 = new Frame(this.texture, this.name, this.sourceIndex);
|
|
121446
|
+
clone2.cutX = this.cutX;
|
|
121447
|
+
clone2.cutY = this.cutY;
|
|
121448
|
+
clone2.cutWidth = this.cutWidth;
|
|
121449
|
+
clone2.cutHeight = this.cutHeight;
|
|
121450
|
+
clone2.x = this.x;
|
|
121451
|
+
clone2.y = this.y;
|
|
121452
|
+
clone2.width = this.width;
|
|
121453
|
+
clone2.height = this.height;
|
|
121454
|
+
clone2.halfWidth = this.halfWidth;
|
|
121455
|
+
clone2.halfHeight = this.halfHeight;
|
|
121456
|
+
clone2.centerX = this.centerX;
|
|
121457
|
+
clone2.centerY = this.centerY;
|
|
121458
|
+
clone2.rotated = this.rotated;
|
|
121459
|
+
clone2.data = Extend(true, clone2.data, this.data);
|
|
121460
|
+
clone2.updateUVs();
|
|
121461
|
+
return clone2;
|
|
121462
121462
|
},
|
|
121463
121463
|
/**
|
|
121464
121464
|
* Destroys this Frame by nulling its reference to the parent Texture and and data objects.
|
|
@@ -138673,15 +138673,15 @@ var CopilotOffice = (() => {
|
|
|
138673
138673
|
/***/
|
|
138674
138674
|
((module2) => {
|
|
138675
138675
|
var Clone = function(obj) {
|
|
138676
|
-
var
|
|
138676
|
+
var clone2 = {};
|
|
138677
138677
|
for (var key in obj) {
|
|
138678
138678
|
if (Array.isArray(obj[key])) {
|
|
138679
|
-
|
|
138679
|
+
clone2[key] = obj[key].slice(0);
|
|
138680
138680
|
} else {
|
|
138681
|
-
|
|
138681
|
+
clone2[key] = obj[key];
|
|
138682
138682
|
}
|
|
138683
138683
|
}
|
|
138684
|
-
return
|
|
138684
|
+
return clone2;
|
|
138685
138685
|
};
|
|
138686
138686
|
module2.exports = Clone;
|
|
138687
138687
|
})
|
|
@@ -138713,7 +138713,7 @@ var CopilotOffice = (() => {
|
|
|
138713
138713
|
((module2, __unused_webpack_exports, __webpack_require__2) => {
|
|
138714
138714
|
var IsPlainObject = __webpack_require__2(41212);
|
|
138715
138715
|
var Extend = function() {
|
|
138716
|
-
var options, name, src, copy, copyIsArray,
|
|
138716
|
+
var options, name, src, copy, copyIsArray, clone2, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false;
|
|
138717
138717
|
if (typeof target === "boolean") {
|
|
138718
138718
|
deep = target;
|
|
138719
138719
|
target = arguments[1] || {};
|
|
@@ -138734,11 +138734,11 @@ var CopilotOffice = (() => {
|
|
|
138734
138734
|
if (deep && copy && (IsPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) {
|
|
138735
138735
|
if (copyIsArray) {
|
|
138736
138736
|
copyIsArray = false;
|
|
138737
|
-
|
|
138737
|
+
clone2 = src && Array.isArray(src) ? src : [];
|
|
138738
138738
|
} else {
|
|
138739
|
-
|
|
138739
|
+
clone2 = src && IsPlainObject(src) ? src : {};
|
|
138740
138740
|
}
|
|
138741
|
-
target[name] = Extend(deep,
|
|
138741
|
+
target[name] = Extend(deep, clone2, copy);
|
|
138742
138742
|
} else if (copy !== void 0) {
|
|
138743
138743
|
target[name] = copy;
|
|
138744
138744
|
}
|
|
@@ -138922,13 +138922,13 @@ var CopilotOffice = (() => {
|
|
|
138922
138922
|
((module2, __unused_webpack_exports, __webpack_require__2) => {
|
|
138923
138923
|
var Clone = __webpack_require__2(41786);
|
|
138924
138924
|
var Merge = function(obj1, obj2) {
|
|
138925
|
-
var
|
|
138925
|
+
var clone2 = Clone(obj1);
|
|
138926
138926
|
for (var key in obj2) {
|
|
138927
|
-
if (!
|
|
138928
|
-
|
|
138927
|
+
if (!clone2.hasOwnProperty(key)) {
|
|
138928
|
+
clone2[key] = obj2[key];
|
|
138929
138929
|
}
|
|
138930
138930
|
}
|
|
138931
|
-
return
|
|
138931
|
+
return clone2;
|
|
138932
138932
|
};
|
|
138933
138933
|
module2.exports = Merge;
|
|
138934
138934
|
})
|
|
@@ -138939,13 +138939,13 @@ var CopilotOffice = (() => {
|
|
|
138939
138939
|
((module2, __unused_webpack_exports, __webpack_require__2) => {
|
|
138940
138940
|
var Clone = __webpack_require__2(41786);
|
|
138941
138941
|
var MergeRight = function(obj1, obj2) {
|
|
138942
|
-
var
|
|
138942
|
+
var clone2 = Clone(obj1);
|
|
138943
138943
|
for (var key in obj2) {
|
|
138944
|
-
if (
|
|
138945
|
-
|
|
138944
|
+
if (clone2.hasOwnProperty(key)) {
|
|
138945
|
+
clone2[key] = obj2[key];
|
|
138946
138946
|
}
|
|
138947
138947
|
}
|
|
138948
|
-
return
|
|
138948
|
+
return clone2;
|
|
138949
138949
|
};
|
|
138950
138950
|
module2.exports = MergeRight;
|
|
138951
138951
|
})
|
|
@@ -139192,6 +139192,22 @@ var CopilotOffice = (() => {
|
|
|
139192
139192
|
}
|
|
139193
139193
|
return vy < 0 ? 3 /* UP */ : 0 /* DOWN */;
|
|
139194
139194
|
}
|
|
139195
|
+
function nextWalkAction(spriteKey, vx, vy, current) {
|
|
139196
|
+
const newDir = directionFromVelocity(vx, vy);
|
|
139197
|
+
if (newDir === null) {
|
|
139198
|
+
return {
|
|
139199
|
+
kind: "idle",
|
|
139200
|
+
direction: current.direction,
|
|
139201
|
+
standFrame: getStandFrame(current.direction)
|
|
139202
|
+
};
|
|
139203
|
+
}
|
|
139204
|
+
return {
|
|
139205
|
+
kind: "play",
|
|
139206
|
+
direction: newDir,
|
|
139207
|
+
animKey: walkAnimKey(spriteKey, newDir),
|
|
139208
|
+
directionChanged: newDir !== current.direction
|
|
139209
|
+
};
|
|
139210
|
+
}
|
|
139195
139211
|
function registerWalkAnimations(anims, spriteKey) {
|
|
139196
139212
|
const directions = [0 /* DOWN */, 1 /* LEFT */, 2 /* RIGHT */, 3 /* UP */];
|
|
139197
139213
|
for (const dir of directions) {
|
|
@@ -140056,10 +140072,19 @@ var CopilotOffice = (() => {
|
|
|
140056
140072
|
}
|
|
140057
140073
|
return valid;
|
|
140058
140074
|
}
|
|
140059
|
-
var FLEET_NAMES, FLEET_COLORS, FLEET_SEAT_POSITIONS, ARTHUR_FLEET_SEAT_INDEX, FLEET_AGENTS, RESERVE_AGENTS, SHOW_ARCHITECT_IN_DEFAULT_OFFICE, CORE_AGENT_IDS, RESERVE_AGENT_DESK, AGENTS, DEFAULT_AGENTS, DEFAULT_RESERVE_MAP, RANDOM_POOL_CONFIGS, RANDOM_SPRITE_COUNT, CORE_POSITIONS, RESERVE_DESK_IDS, RESERVE_POSITIONS, ROLE_TITLES;
|
|
140075
|
+
var ARCHITECT_AGENT_ID, GENERALIST_AGENT_ID, DEBUGGER_AGENT_ID, ADMIN_AGENT_ID, DEFAULT_PLAN_AGENT_IDS, FLEET_NAMES, FLEET_COLORS, FLEET_SEAT_POSITIONS, ARTHUR_FLEET_SEAT_INDEX, FLEET_AGENTS, RESERVE_AGENTS, SHOW_ARCHITECT_IN_DEFAULT_OFFICE, CORE_AGENT_IDS, RESERVE_AGENT_DESK, AGENTS, DEFAULT_AGENTS, DEFAULT_RESERVE_MAP, RANDOM_POOL_CONFIGS, RANDOM_SPRITE_COUNT, CORE_POSITIONS, RESERVE_DESK_IDS, RESERVE_POSITIONS, ROLE_TITLES;
|
|
140060
140076
|
var init_agents = __esm({
|
|
140061
140077
|
"src/config/agents.ts"() {
|
|
140062
140078
|
"use strict";
|
|
140079
|
+
ARCHITECT_AGENT_ID = "architect";
|
|
140080
|
+
GENERALIST_AGENT_ID = "generalist";
|
|
140081
|
+
DEBUGGER_AGENT_ID = "debugger";
|
|
140082
|
+
ADMIN_AGENT_ID = "admin";
|
|
140083
|
+
DEFAULT_PLAN_AGENT_IDS = [
|
|
140084
|
+
GENERALIST_AGENT_ID,
|
|
140085
|
+
DEBUGGER_AGENT_ID,
|
|
140086
|
+
ADMIN_AGENT_ID
|
|
140087
|
+
];
|
|
140063
140088
|
FLEET_NAMES = [
|
|
140064
140089
|
"Liam",
|
|
140065
140090
|
"Emma",
|
|
@@ -140216,7 +140241,7 @@ var CopilotOffice = (() => {
|
|
|
140216
140241
|
FLEET_AGENTS = FLEET_SEAT_POSITIONS.map((pos, i) => {
|
|
140217
140242
|
if (i === ARTHUR_FLEET_SEAT_INDEX) {
|
|
140218
140243
|
return {
|
|
140219
|
-
id:
|
|
140244
|
+
id: ARCHITECT_AGENT_ID,
|
|
140220
140245
|
name: "Arthur",
|
|
140221
140246
|
skill: "general",
|
|
140222
140247
|
sprite: "npc_architect",
|
|
@@ -140303,10 +140328,10 @@ var CopilotOffice = (() => {
|
|
|
140303
140328
|
};
|
|
140304
140329
|
SHOW_ARCHITECT_IN_DEFAULT_OFFICE = false;
|
|
140305
140330
|
CORE_AGENT_IDS = /* @__PURE__ */ new Set([
|
|
140306
|
-
|
|
140307
|
-
...SHOW_ARCHITECT_IN_DEFAULT_OFFICE ? [
|
|
140308
|
-
|
|
140309
|
-
|
|
140331
|
+
GENERALIST_AGENT_ID,
|
|
140332
|
+
...SHOW_ARCHITECT_IN_DEFAULT_OFFICE ? [ARCHITECT_AGENT_ID] : [],
|
|
140333
|
+
DEBUGGER_AGENT_ID,
|
|
140334
|
+
ADMIN_AGENT_ID
|
|
140310
140335
|
]);
|
|
140311
140336
|
RESERVE_AGENT_DESK = Object.fromEntries(
|
|
140312
140337
|
Object.entries(RESERVE_AGENTS).map(([deskId, config]) => [config.id, deskId])
|
|
@@ -140325,7 +140350,7 @@ var CopilotOffice = (() => {
|
|
|
140325
140350
|
description: "the Generalist"
|
|
140326
140351
|
},
|
|
140327
140352
|
...SHOW_ARCHITECT_IN_DEFAULT_OFFICE ? [{
|
|
140328
|
-
id:
|
|
140353
|
+
id: ARCHITECT_AGENT_ID,
|
|
140329
140354
|
name: "Arthur",
|
|
140330
140355
|
skill: "general",
|
|
140331
140356
|
sprite: "npc_architect",
|
|
@@ -141697,13 +141722,15 @@ var CopilotOffice = (() => {
|
|
|
141697
141722
|
if (vx !== 0 && vy !== 0) {
|
|
141698
141723
|
body.velocity.normalize().scale(currentSpeed);
|
|
141699
141724
|
}
|
|
141700
|
-
const
|
|
141701
|
-
|
|
141702
|
-
|
|
141703
|
-
|
|
141704
|
-
|
|
141725
|
+
const action = nextWalkAction("player", vx, vy, {
|
|
141726
|
+
direction: this.currentDirection,
|
|
141727
|
+
isWalking: this.isWalking
|
|
141728
|
+
});
|
|
141729
|
+
if (action.kind === "play") {
|
|
141730
|
+
this.currentDirection = action.direction;
|
|
141731
|
+
if (!this.isWalking || action.directionChanged) {
|
|
141705
141732
|
this.isWalking = true;
|
|
141706
|
-
this.anims.play(
|
|
141733
|
+
this.anims.play(action.animKey, true);
|
|
141707
141734
|
}
|
|
141708
141735
|
} else {
|
|
141709
141736
|
this.stopWalking();
|
|
@@ -148170,12 +148197,191 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148170
148197
|
}
|
|
148171
148198
|
});
|
|
148172
148199
|
|
|
148200
|
+
// src/config/zIndex.ts
|
|
148201
|
+
var ZIndex;
|
|
148202
|
+
var init_zIndex = __esm({
|
|
148203
|
+
"src/config/zIndex.ts"() {
|
|
148204
|
+
"use strict";
|
|
148205
|
+
ZIndex = {
|
|
148206
|
+
/** Status bar at the bottom of the app shell. */
|
|
148207
|
+
STATUS_BAR: 100,
|
|
148208
|
+
/** In-scene HTML overlay rendered by OfficeScene above the Phaser canvas
|
|
148209
|
+
* but below all modal surfaces (e.g. fleet-progress sticker). */
|
|
148210
|
+
OFFICE_SCENE_OVERLAY: 150,
|
|
148211
|
+
/** Transient toast notifications (auto-dismissed). */
|
|
148212
|
+
TOAST: 9e3,
|
|
148213
|
+
/** Terminal overlay panel host (xterm.js + tab strip). */
|
|
148214
|
+
TERMINAL_OVERLAY: 1e4,
|
|
148215
|
+
/** Sprite/session card that floats above the terminal overlay. */
|
|
148216
|
+
TERMINAL_SPRITE_CARD: 10001,
|
|
148217
|
+
/** Serious-mode terminal controller (full-pane mode). Sits above the
|
|
148218
|
+
* terminal overlay so its chrome (mode toggle, footer) stays on top. */
|
|
148219
|
+
SERIOUS_TERMINAL: 10003,
|
|
148220
|
+
/** Sprite customizer modal. Above terminal but below settings. */
|
|
148221
|
+
SPRITE_CUSTOMIZER: 15e3,
|
|
148222
|
+
/** Settings panel modal. */
|
|
148223
|
+
SETTINGS: 2e4,
|
|
148224
|
+
/** Notification settings modal. Shares SETTINGS' layer because the two
|
|
148225
|
+
* are never open simultaneously by app construction (both routed via
|
|
148226
|
+
* the same `settings:open` / `settings:close` bus). */
|
|
148227
|
+
NOTIFICATION_SETTINGS: 2e4,
|
|
148228
|
+
/** Generic blocking modal dialog (e.g. layout chooser, new office dialog).
|
|
148229
|
+
* Sits above everything except the absolute top-most modal layer. */
|
|
148230
|
+
MODAL_DIALOG: 99999,
|
|
148231
|
+
/** Reserved for the topmost modal layer (e.g. critical confirmation that
|
|
148232
|
+
* must sit above an already-open MODAL_DIALOG). */
|
|
148233
|
+
TOP_MODAL: 1e5
|
|
148234
|
+
};
|
|
148235
|
+
}
|
|
148236
|
+
});
|
|
148237
|
+
|
|
148238
|
+
// src/util/lifecycleLog.ts
|
|
148239
|
+
function logLifecycleTransition(t) {
|
|
148240
|
+
if (t.from === t.to) return;
|
|
148241
|
+
const full = { ...t, timestamp: Date.now() };
|
|
148242
|
+
const reasonStr = full.reason ? ` reason=${full.reason}` : "";
|
|
148243
|
+
const detailStr = full.detail ? ` detail=${JSON.stringify(full.detail)}` : "";
|
|
148244
|
+
console.log(
|
|
148245
|
+
`[lifecycle] agent=${full.agentId} office=${full.officeId} ${full.from}\u2192${full.to}${reasonStr}${detailStr}`
|
|
148246
|
+
);
|
|
148247
|
+
for (const fn of subscribers) {
|
|
148248
|
+
try {
|
|
148249
|
+
fn(full);
|
|
148250
|
+
} catch (err) {
|
|
148251
|
+
console.warn("[lifecycle] subscriber threw:", err);
|
|
148252
|
+
}
|
|
148253
|
+
}
|
|
148254
|
+
}
|
|
148255
|
+
var subscribers;
|
|
148256
|
+
var init_lifecycleLog = __esm({
|
|
148257
|
+
"src/util/lifecycleLog.ts"() {
|
|
148258
|
+
"use strict";
|
|
148259
|
+
subscribers = /* @__PURE__ */ new Set();
|
|
148260
|
+
}
|
|
148261
|
+
});
|
|
148262
|
+
|
|
148263
|
+
// src/office/officePersistence.ts
|
|
148264
|
+
function serializeOffices(state) {
|
|
148265
|
+
return JSON.stringify(
|
|
148266
|
+
{
|
|
148267
|
+
currentOfficeId: state.currentOfficeId,
|
|
148268
|
+
offices: state.offices
|
|
148269
|
+
},
|
|
148270
|
+
null,
|
|
148271
|
+
2
|
|
148272
|
+
);
|
|
148273
|
+
}
|
|
148274
|
+
function deserializeOffices(stored) {
|
|
148275
|
+
if (!stored) return { currentOfficeId: null, offices: [] };
|
|
148276
|
+
let data;
|
|
148277
|
+
try {
|
|
148278
|
+
data = JSON.parse(stored);
|
|
148279
|
+
} catch {
|
|
148280
|
+
return { currentOfficeId: null, offices: [] };
|
|
148281
|
+
}
|
|
148282
|
+
if (data === null || typeof data !== "object") {
|
|
148283
|
+
return { currentOfficeId: null, offices: [] };
|
|
148284
|
+
}
|
|
148285
|
+
const record = data;
|
|
148286
|
+
const rawOffices = Array.isArray(record.offices) ? record.offices : [];
|
|
148287
|
+
const offices = [];
|
|
148288
|
+
for (let i = 0; i < rawOffices.length; i++) {
|
|
148289
|
+
const raw = rawOffices[i];
|
|
148290
|
+
if (raw === null || typeof raw !== "object") continue;
|
|
148291
|
+
const cfg = raw;
|
|
148292
|
+
const name = typeof cfg.name === "string" ? cfg.name : `Office ${i}`;
|
|
148293
|
+
const workingDirectory = typeof cfg.workingDirectory === "string" ? cfg.workingDirectory : ".";
|
|
148294
|
+
const createdAt = typeof cfg.createdAt === "number" ? cfg.createdAt : Date.now();
|
|
148295
|
+
const layout = cfg.layout === "fleet-vteam" ? "fleet-vteam" : "default";
|
|
148296
|
+
const seatedAgents = Array.isArray(cfg.seatedAgents) ? cfg.seatedAgents.filter(
|
|
148297
|
+
(s) => !!s && typeof s === "object" && typeof s.deskId === "string" && typeof s.agentId === "string"
|
|
148298
|
+
) : [];
|
|
148299
|
+
const normalized = {
|
|
148300
|
+
// Reindex from array position — this replaces legacy UUID-style ids and
|
|
148301
|
+
// matches the prior inline loader behaviour exactly.
|
|
148302
|
+
id: `office-${i}`,
|
|
148303
|
+
name,
|
|
148304
|
+
workingDirectory,
|
|
148305
|
+
createdAt,
|
|
148306
|
+
layout,
|
|
148307
|
+
seatedAgents
|
|
148308
|
+
};
|
|
148309
|
+
if (cfg.customAgents !== void 0) {
|
|
148310
|
+
normalized.customAgents = cfg.customAgents;
|
|
148311
|
+
}
|
|
148312
|
+
if (cfg.customReserveAgents !== void 0) {
|
|
148313
|
+
normalized.customReserveAgents = cfg.customReserveAgents;
|
|
148314
|
+
}
|
|
148315
|
+
offices.push(normalized);
|
|
148316
|
+
}
|
|
148317
|
+
let currentOfficeId = null;
|
|
148318
|
+
if (record.currentOfficeId !== void 0 && record.currentOfficeId !== null) {
|
|
148319
|
+
currentOfficeId = String(record.currentOfficeId);
|
|
148320
|
+
}
|
|
148321
|
+
if (!currentOfficeId || !offices.some((o) => o.id === currentOfficeId)) {
|
|
148322
|
+
currentOfficeId = offices.length > 0 ? offices[0].id : null;
|
|
148323
|
+
}
|
|
148324
|
+
return { currentOfficeId, offices };
|
|
148325
|
+
}
|
|
148326
|
+
function createBridgePersistencePort() {
|
|
148327
|
+
const getBridge = () => typeof window !== "undefined" ? window.copilotBridge : void 0;
|
|
148328
|
+
return {
|
|
148329
|
+
async loadDurable() {
|
|
148330
|
+
const bridge = getBridge();
|
|
148331
|
+
if (!bridge?.loadOffices) return null;
|
|
148332
|
+
try {
|
|
148333
|
+
const result = await bridge.loadOffices();
|
|
148334
|
+
if (result?.success && typeof result.data === "string") {
|
|
148335
|
+
return result.data;
|
|
148336
|
+
}
|
|
148337
|
+
} catch (e) {
|
|
148338
|
+
console.warn("[OfficePersistence] loadOffices failed:", e);
|
|
148339
|
+
}
|
|
148340
|
+
return null;
|
|
148341
|
+
},
|
|
148342
|
+
async saveDurable(json) {
|
|
148343
|
+
const bridge = getBridge();
|
|
148344
|
+
if (!bridge?.saveOffices) return;
|
|
148345
|
+
try {
|
|
148346
|
+
await bridge.saveOffices(json);
|
|
148347
|
+
} catch (e) {
|
|
148348
|
+
console.warn("[OfficePersistence] saveOffices failed:", e);
|
|
148349
|
+
}
|
|
148350
|
+
},
|
|
148351
|
+
async createOfficeSession(officeId) {
|
|
148352
|
+
const bridge = getBridge();
|
|
148353
|
+
if (!bridge?.createOfficeSession) return;
|
|
148354
|
+
try {
|
|
148355
|
+
await bridge.createOfficeSession(officeId);
|
|
148356
|
+
} catch (e) {
|
|
148357
|
+
console.warn("[OfficePersistence] createOfficeSession failed:", e);
|
|
148358
|
+
}
|
|
148359
|
+
},
|
|
148360
|
+
async deleteOfficeSession(officeId) {
|
|
148361
|
+
const bridge = getBridge();
|
|
148362
|
+
if (!bridge?.deleteOfficeSession) return;
|
|
148363
|
+
try {
|
|
148364
|
+
await bridge.deleteOfficeSession(officeId);
|
|
148365
|
+
} catch (e) {
|
|
148366
|
+
console.warn("[OfficePersistence] deleteOfficeSession failed:", e);
|
|
148367
|
+
}
|
|
148368
|
+
}
|
|
148369
|
+
};
|
|
148370
|
+
}
|
|
148371
|
+
var init_officePersistence = __esm({
|
|
148372
|
+
"src/office/officePersistence.ts"() {
|
|
148373
|
+
"use strict";
|
|
148374
|
+
}
|
|
148375
|
+
});
|
|
148376
|
+
|
|
148173
148377
|
// src/office/officeManager.ts
|
|
148174
148378
|
var VALID_TRANSITIONS, MAX_RECENT_ACTIONS, OfficeManager, officeManager;
|
|
148175
148379
|
var init_officeManager = __esm({
|
|
148176
148380
|
"src/office/officeManager.ts"() {
|
|
148177
148381
|
"use strict";
|
|
148178
148382
|
init_agents();
|
|
148383
|
+
init_lifecycleLog();
|
|
148384
|
+
init_officePersistence();
|
|
148179
148385
|
VALID_TRANSITIONS = {
|
|
148180
148386
|
slacking: /* @__PURE__ */ new Set(["starting", "ready"]),
|
|
148181
148387
|
starting: /* @__PURE__ */ new Set(["ready", "error", "slacking"]),
|
|
@@ -148186,14 +148392,24 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148186
148392
|
};
|
|
148187
148393
|
MAX_RECENT_ACTIONS = 8;
|
|
148188
148394
|
OfficeManager = class {
|
|
148189
|
-
constructor() {
|
|
148395
|
+
constructor(persistence = createBridgePersistencePort()) {
|
|
148190
148396
|
this.offices = /* @__PURE__ */ new Map();
|
|
148191
148397
|
this.sessionToOffice = /* @__PURE__ */ new Map();
|
|
148192
148398
|
// sessionId → officeId
|
|
148193
148399
|
this._currentOfficeId = null;
|
|
148400
|
+
// Spec 008 (2026-06-12): durable load is async but renderer boot triggers
|
|
148401
|
+
// saves (status updates, agent registrations) almost immediately. Without
|
|
148402
|
+
// gating, those saves serialize the localStorage-only state and clobber
|
|
148403
|
+
// the multi-office file on disk before the durable load can hydrate. We
|
|
148404
|
+
// hold all durable writes until loadFromStorage's async path settles, then
|
|
148405
|
+
// flush whatever the most-recent state was. localStorage writes are NOT
|
|
148406
|
+
// gated — they're fast, synchronous, and only matter for next cold boot.
|
|
148407
|
+
this.durableLoadSettled = false;
|
|
148408
|
+
this.pendingDurableWrite = false;
|
|
148194
148409
|
// Callbacks for UI updates
|
|
148195
148410
|
this.onOfficeChanged = null;
|
|
148196
148411
|
this.onOfficesUpdated = null;
|
|
148412
|
+
this.persistence = persistence;
|
|
148197
148413
|
this.loadFromStorage();
|
|
148198
148414
|
}
|
|
148199
148415
|
get currentOfficeId() {
|
|
@@ -148237,11 +148453,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148237
148453
|
this._currentOfficeId = id;
|
|
148238
148454
|
}
|
|
148239
148455
|
this.saveToStorage();
|
|
148240
|
-
|
|
148241
|
-
window.copilotBridge.createOfficeSession(id).catch((e) => {
|
|
148242
|
-
console.warn("[OfficeManager] Failed to create session file:", e);
|
|
148243
|
-
});
|
|
148244
|
-
}
|
|
148456
|
+
void this.persistence.createOfficeSession(id);
|
|
148245
148457
|
this.onOfficesUpdated?.();
|
|
148246
148458
|
return data;
|
|
148247
148459
|
}
|
|
@@ -148259,11 +148471,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148259
148471
|
}
|
|
148260
148472
|
}
|
|
148261
148473
|
this.offices.delete(officeId);
|
|
148262
|
-
|
|
148263
|
-
window.copilotBridge.deleteOfficeSession(officeId).catch((e) => {
|
|
148264
|
-
console.warn("[OfficeManager] Failed to delete session file:", e);
|
|
148265
|
-
});
|
|
148266
|
-
}
|
|
148474
|
+
void this.persistence.deleteOfficeSession(officeId);
|
|
148267
148475
|
if (this._currentOfficeId === officeId) {
|
|
148268
148476
|
this._currentOfficeId = this.offices.has("office-0") ? "office-0" : this.offices.keys().next().value || null;
|
|
148269
148477
|
if (this._currentOfficeId) {
|
|
@@ -148335,70 +148543,63 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148335
148543
|
const office = this.offices.get(officeId);
|
|
148336
148544
|
return office?.config.seatedAgents ?? [];
|
|
148337
148545
|
}
|
|
148338
|
-
// Persistence — saves to both localStorage (fast) and .
|
|
148546
|
+
// Persistence — saves to both localStorage (fast) and durable file via port.
|
|
148339
148547
|
saveToStorage() {
|
|
148340
|
-
const
|
|
148548
|
+
const json = serializeOffices({
|
|
148341
148549
|
currentOfficeId: this._currentOfficeId,
|
|
148342
148550
|
offices: Array.from(this.offices.values()).map((o) => o.config)
|
|
148343
|
-
};
|
|
148344
|
-
const json = JSON.stringify(data, null, 2);
|
|
148551
|
+
});
|
|
148345
148552
|
try {
|
|
148346
148553
|
localStorage.setItem("copilot-offices", json);
|
|
148347
148554
|
} catch (e) {
|
|
148348
148555
|
console.warn("[OfficeManager] Failed to save to localStorage:", e);
|
|
148349
148556
|
}
|
|
148350
|
-
if (
|
|
148351
|
-
|
|
148352
|
-
|
|
148353
|
-
});
|
|
148557
|
+
if (!this.durableLoadSettled) {
|
|
148558
|
+
this.pendingDurableWrite = true;
|
|
148559
|
+
return;
|
|
148354
148560
|
}
|
|
148561
|
+
void this.persistence.saveDurable(json);
|
|
148562
|
+
}
|
|
148563
|
+
flushPendingDurableWrite() {
|
|
148564
|
+
if (!this.pendingDurableWrite) return;
|
|
148565
|
+
this.pendingDurableWrite = false;
|
|
148566
|
+
const json = serializeOffices({
|
|
148567
|
+
currentOfficeId: this._currentOfficeId,
|
|
148568
|
+
offices: Array.from(this.offices.values()).map((o) => o.config)
|
|
148569
|
+
});
|
|
148570
|
+
void this.persistence.saveDurable(json);
|
|
148355
148571
|
}
|
|
148356
148572
|
loadFromStorage() {
|
|
148357
|
-
this.
|
|
148358
|
-
|
|
148359
|
-
|
|
148360
|
-
|
|
148361
|
-
|
|
148362
|
-
|
|
148363
|
-
|
|
148364
|
-
|
|
148365
|
-
|
|
148366
|
-
|
|
148367
|
-
|
|
148368
|
-
|
|
148573
|
+
this.applyStoredState(localStorage.getItem("copilot-offices"));
|
|
148574
|
+
void this.persistence.loadDurable().then((data) => {
|
|
148575
|
+
if (data) {
|
|
148576
|
+
console.log("[OfficeManager] Loaded offices from durable persistence");
|
|
148577
|
+
this.applyStoredState(data);
|
|
148578
|
+
this.onOfficesUpdated?.();
|
|
148579
|
+
}
|
|
148580
|
+
}).catch((e) => {
|
|
148581
|
+
console.warn("[OfficeManager] Failed to load from durable persistence:", e);
|
|
148582
|
+
}).finally(() => {
|
|
148583
|
+
this.durableLoadSettled = true;
|
|
148584
|
+
this.flushPendingDurableWrite();
|
|
148585
|
+
});
|
|
148369
148586
|
}
|
|
148370
|
-
|
|
148371
|
-
|
|
148372
|
-
|
|
148373
|
-
|
|
148374
|
-
|
|
148375
|
-
|
|
148376
|
-
|
|
148377
|
-
|
|
148378
|
-
|
|
148379
|
-
|
|
148380
|
-
|
|
148381
|
-
|
|
148382
|
-
|
|
148383
|
-
|
|
148384
|
-
|
|
148385
|
-
|
|
148386
|
-
agentTools: existing?.agentTools ?? /* @__PURE__ */ new Map()
|
|
148387
|
-
};
|
|
148388
|
-
this.offices.set(id, officeData);
|
|
148389
|
-
}
|
|
148390
|
-
}
|
|
148391
|
-
let currentId = null;
|
|
148392
|
-
if (data.currentOfficeId !== void 0 && data.currentOfficeId !== null) {
|
|
148393
|
-
currentId = String(data.currentOfficeId);
|
|
148394
|
-
}
|
|
148395
|
-
if (currentId && this.offices.has(currentId)) {
|
|
148396
|
-
this._currentOfficeId = currentId;
|
|
148397
|
-
} else if (this.offices.size > 0) {
|
|
148398
|
-
this._currentOfficeId = this.offices.keys().next().value;
|
|
148399
|
-
}
|
|
148400
|
-
} catch (e) {
|
|
148401
|
-
console.warn("[OfficeManager] Failed to parse office data:", e);
|
|
148587
|
+
applyStoredState(stored) {
|
|
148588
|
+
const { currentOfficeId, offices } = deserializeOffices(stored);
|
|
148589
|
+
if (offices.length === 0 && currentOfficeId === null) return;
|
|
148590
|
+
for (const config of offices) {
|
|
148591
|
+
const existing = this.offices.get(config.id);
|
|
148592
|
+
const officeData = {
|
|
148593
|
+
config,
|
|
148594
|
+
agents: existing?.agents ?? /* @__PURE__ */ new Map(),
|
|
148595
|
+
agentTools: existing?.agentTools ?? /* @__PURE__ */ new Map()
|
|
148596
|
+
};
|
|
148597
|
+
this.offices.set(config.id, officeData);
|
|
148598
|
+
}
|
|
148599
|
+
if (currentOfficeId && this.offices.has(currentOfficeId)) {
|
|
148600
|
+
this._currentOfficeId = currentOfficeId;
|
|
148601
|
+
} else if (this.offices.size > 0) {
|
|
148602
|
+
this._currentOfficeId = this.offices.keys().next().value;
|
|
148402
148603
|
}
|
|
148403
148604
|
}
|
|
148404
148605
|
// Agent status helpers
|
|
@@ -148428,9 +148629,27 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148428
148629
|
console.warn(`[OfficeManager] Invalid transition: ${agentId} ${from} \u2192 ${target}`);
|
|
148429
148630
|
}
|
|
148430
148631
|
}
|
|
148431
|
-
|
|
148632
|
+
/**
|
|
148633
|
+
* Emit a structured lifecycle telemetry entry for a transition that has
|
|
148634
|
+
* already been applied to `status`. Callers pass the pre-mutation effective
|
|
148635
|
+
* state captured before mutating. Safe additive observability — never mutates
|
|
148636
|
+
* state and self-transitions are suppressed by the helper.
|
|
148637
|
+
*/
|
|
148638
|
+
emitLifecycleTransition(officeId, agentId, status, from, reason, detail) {
|
|
148639
|
+
const to = this.getEffectiveState(status);
|
|
148640
|
+
logLifecycleTransition({
|
|
148641
|
+
agentId,
|
|
148642
|
+
officeId,
|
|
148643
|
+
from,
|
|
148644
|
+
to,
|
|
148645
|
+
reason,
|
|
148646
|
+
detail
|
|
148647
|
+
});
|
|
148648
|
+
}
|
|
148649
|
+
setAgentSlacking(officeId, agentId, reason) {
|
|
148432
148650
|
const status = this.getOrCreateStatus(officeId, agentId);
|
|
148433
148651
|
if (!status) return;
|
|
148652
|
+
const from = this.getEffectiveState(status);
|
|
148434
148653
|
this.validateTransition(agentId, status, "slacking");
|
|
148435
148654
|
status.state = "slacking";
|
|
148436
148655
|
status.subState = null;
|
|
@@ -148440,11 +148659,13 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148440
148659
|
status.activityStartTime = null;
|
|
148441
148660
|
status.recentActions = [];
|
|
148442
148661
|
status.taskSummary = null;
|
|
148662
|
+
this.emitLifecycleTransition(officeId, agentId, status, from, reason);
|
|
148443
148663
|
}
|
|
148444
|
-
setAgentStarting(officeId, agentId) {
|
|
148664
|
+
setAgentStarting(officeId, agentId, reason) {
|
|
148445
148665
|
const status = this.getOrCreateStatus(officeId, agentId);
|
|
148446
148666
|
if (!status) return;
|
|
148447
148667
|
if (status.subState === "starting") return;
|
|
148668
|
+
const from = this.getEffectiveState(status);
|
|
148448
148669
|
this.validateTransition(agentId, status, "starting");
|
|
148449
148670
|
status.state = "active";
|
|
148450
148671
|
status.subState = "starting";
|
|
@@ -148452,10 +148673,12 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148452
148673
|
status.currentTool = null;
|
|
148453
148674
|
status.completionPendingAck = false;
|
|
148454
148675
|
status.activityStartTime = Date.now();
|
|
148676
|
+
this.emitLifecycleTransition(officeId, agentId, status, from, reason);
|
|
148455
148677
|
}
|
|
148456
|
-
setAgentReady(officeId, agentId) {
|
|
148678
|
+
setAgentReady(officeId, agentId, reason) {
|
|
148457
148679
|
const status = this.getOrCreateStatus(officeId, agentId);
|
|
148458
148680
|
if (!status) return;
|
|
148681
|
+
const from = this.getEffectiveState(status);
|
|
148459
148682
|
this.validateTransition(agentId, status, "ready");
|
|
148460
148683
|
status.state = "active";
|
|
148461
148684
|
status.subState = "ready";
|
|
@@ -148463,10 +148686,12 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148463
148686
|
status.currentTool = null;
|
|
148464
148687
|
status.completionPendingAck = false;
|
|
148465
148688
|
status.activityStartTime = null;
|
|
148689
|
+
this.emitLifecycleTransition(officeId, agentId, status, from, reason);
|
|
148466
148690
|
}
|
|
148467
|
-
setAgentDonePendingAck(officeId, agentId) {
|
|
148691
|
+
setAgentDonePendingAck(officeId, agentId, reason) {
|
|
148468
148692
|
const status = this.getOrCreateStatus(officeId, agentId);
|
|
148469
148693
|
if (!status) return;
|
|
148694
|
+
const from = this.getEffectiveState(status);
|
|
148470
148695
|
this.validateTransition(agentId, status, "ready");
|
|
148471
148696
|
status.state = "active";
|
|
148472
148697
|
status.subState = "ready";
|
|
@@ -148474,6 +148699,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148474
148699
|
status.currentTool = null;
|
|
148475
148700
|
status.completionPendingAck = true;
|
|
148476
148701
|
status.activityStartTime = null;
|
|
148702
|
+
this.emitLifecycleTransition(officeId, agentId, status, from, reason ?? "done_pending_ack");
|
|
148477
148703
|
}
|
|
148478
148704
|
acknowledgeAgentCompletion(officeId, agentId) {
|
|
148479
148705
|
const status = this.getOrCreateStatus(officeId, agentId);
|
|
@@ -148481,9 +148707,10 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148481
148707
|
status.completionPendingAck = false;
|
|
148482
148708
|
return true;
|
|
148483
148709
|
}
|
|
148484
|
-
setAgentWaiting(officeId, agentId) {
|
|
148710
|
+
setAgentWaiting(officeId, agentId, reason) {
|
|
148485
148711
|
const status = this.getOrCreateStatus(officeId, agentId);
|
|
148486
148712
|
if (!status) return;
|
|
148713
|
+
const from = this.getEffectiveState(status);
|
|
148487
148714
|
this.validateTransition(agentId, status, "waiting");
|
|
148488
148715
|
status.state = "active";
|
|
148489
148716
|
status.subState = "waiting";
|
|
@@ -148491,10 +148718,12 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148491
148718
|
status.currentTool = null;
|
|
148492
148719
|
status.completionPendingAck = false;
|
|
148493
148720
|
if (!status.activityStartTime) status.activityStartTime = Date.now();
|
|
148721
|
+
this.emitLifecycleTransition(officeId, agentId, status, from, reason);
|
|
148494
148722
|
}
|
|
148495
|
-
setAgentThinking(officeId, agentId, detail) {
|
|
148723
|
+
setAgentThinking(officeId, agentId, detail, reason) {
|
|
148496
148724
|
const status = this.getOrCreateStatus(officeId, agentId);
|
|
148497
148725
|
if (!status) return;
|
|
148726
|
+
const from = this.getEffectiveState(status);
|
|
148498
148727
|
this.validateTransition(agentId, status, "thinking");
|
|
148499
148728
|
status.state = "active";
|
|
148500
148729
|
status.subState = "thinking";
|
|
@@ -148504,6 +148733,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148504
148733
|
status.currentTool = tools?.length ? tools[tools.length - 1].name : null;
|
|
148505
148734
|
status.completionPendingAck = false;
|
|
148506
148735
|
if (!status.activityStartTime) status.activityStartTime = Date.now();
|
|
148736
|
+
this.emitLifecycleTransition(officeId, agentId, status, from, reason, detail ?? void 0);
|
|
148507
148737
|
}
|
|
148508
148738
|
clearAgentThinkingDetail(officeId, agentId) {
|
|
148509
148739
|
const status = this.getOrCreateStatus(officeId, agentId);
|
|
@@ -148524,9 +148754,10 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148524
148754
|
status.unreadCount = 0;
|
|
148525
148755
|
status.lastEvent = null;
|
|
148526
148756
|
}
|
|
148527
|
-
setAgentError(officeId, agentId, detail = null) {
|
|
148757
|
+
setAgentError(officeId, agentId, detail = null, reason) {
|
|
148528
148758
|
const status = this.getOrCreateStatus(officeId, agentId);
|
|
148529
148759
|
if (!status) return;
|
|
148760
|
+
const from = this.getEffectiveState(status);
|
|
148530
148761
|
this.validateTransition(agentId, status, "error");
|
|
148531
148762
|
status.state = "active";
|
|
148532
148763
|
status.subState = "error";
|
|
@@ -148534,6 +148765,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148534
148765
|
status.currentTool = null;
|
|
148535
148766
|
status.completionPendingAck = false;
|
|
148536
148767
|
status.activityStartTime = null;
|
|
148768
|
+
this.emitLifecycleTransition(officeId, agentId, status, from, reason, detail ?? void 0);
|
|
148537
148769
|
}
|
|
148538
148770
|
setLastCompletedAction(officeId, agentId, action) {
|
|
148539
148771
|
const status = this.getOrCreateStatus(officeId, agentId);
|
|
@@ -148569,6 +148801,271 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148569
148801
|
}
|
|
148570
148802
|
});
|
|
148571
148803
|
|
|
148804
|
+
// src/ui/clipboardToast.ts
|
|
148805
|
+
function ensureToastElement() {
|
|
148806
|
+
if (typeof document === "undefined") return null;
|
|
148807
|
+
let el = document.getElementById(TOAST_ID);
|
|
148808
|
+
if (el) return el;
|
|
148809
|
+
el = document.createElement("div");
|
|
148810
|
+
el.id = TOAST_ID;
|
|
148811
|
+
el.style.cssText = `
|
|
148812
|
+
position: fixed;
|
|
148813
|
+
top: 24px;
|
|
148814
|
+
left: 50%;
|
|
148815
|
+
transform: translateX(-50%);
|
|
148816
|
+
z-index: ${ZIndex.TERMINAL_SPRITE_CARD + 20};
|
|
148817
|
+
padding: 8px 16px;
|
|
148818
|
+
border-radius: 6px;
|
|
148819
|
+
font-family: 'Cascadia Code', Consolas, monospace;
|
|
148820
|
+
font-size: 13px;
|
|
148821
|
+
color: #ffffff;
|
|
148822
|
+
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
|
|
148823
|
+
pointer-events: none;
|
|
148824
|
+
opacity: 0;
|
|
148825
|
+
transition: opacity 120ms ease-out;
|
|
148826
|
+
max-width: 60vw;
|
|
148827
|
+
text-align: center;
|
|
148828
|
+
`;
|
|
148829
|
+
document.body.appendChild(el);
|
|
148830
|
+
return el;
|
|
148831
|
+
}
|
|
148832
|
+
function showClipboardToast(message, kind = "info") {
|
|
148833
|
+
const el = ensureToastElement();
|
|
148834
|
+
if (!el) return;
|
|
148835
|
+
el.textContent = message;
|
|
148836
|
+
el.style.background = KIND_BG[kind];
|
|
148837
|
+
el.style.opacity = "1";
|
|
148838
|
+
if (dismissTimer) clearTimeout(dismissTimer);
|
|
148839
|
+
dismissTimer = setTimeout(() => {
|
|
148840
|
+
el.style.opacity = "0";
|
|
148841
|
+
}, TOAST_DURATION_MS);
|
|
148842
|
+
}
|
|
148843
|
+
var TOAST_ID, TOAST_DURATION_MS, dismissTimer, KIND_BG;
|
|
148844
|
+
var init_clipboardToast = __esm({
|
|
148845
|
+
"src/ui/clipboardToast.ts"() {
|
|
148846
|
+
"use strict";
|
|
148847
|
+
init_zIndex();
|
|
148848
|
+
TOAST_ID = "copilot-office-clipboard-toast";
|
|
148849
|
+
TOAST_DURATION_MS = 1500;
|
|
148850
|
+
dismissTimer = null;
|
|
148851
|
+
KIND_BG = {
|
|
148852
|
+
success: "#1f6f3a",
|
|
148853
|
+
info: "#27355a",
|
|
148854
|
+
error: "#7a2230"
|
|
148855
|
+
};
|
|
148856
|
+
}
|
|
148857
|
+
});
|
|
148858
|
+
|
|
148859
|
+
// src/ui/xtermStyles.ts
|
|
148860
|
+
function ensureXtermStyles() {
|
|
148861
|
+
if (typeof document === "undefined") return;
|
|
148862
|
+
if (document.getElementById(STYLE_ID)) return;
|
|
148863
|
+
const style = document.createElement("style");
|
|
148864
|
+
style.id = STYLE_ID;
|
|
148865
|
+
style.textContent = `
|
|
148866
|
+
.xterm {
|
|
148867
|
+
height: 100%;
|
|
148868
|
+
}
|
|
148869
|
+
.xterm-viewport {
|
|
148870
|
+
overflow-y: scroll !important;
|
|
148871
|
+
background-color: #0a0a14 !important;
|
|
148872
|
+
scrollbar-width: none;
|
|
148873
|
+
scrollbar-gutter: auto;
|
|
148874
|
+
}
|
|
148875
|
+
.xterm-viewport::-webkit-scrollbar {
|
|
148876
|
+
width: 0 !important;
|
|
148877
|
+
height: 0 !important;
|
|
148878
|
+
display: none !important;
|
|
148879
|
+
}
|
|
148880
|
+
#terminal-container .xterm {
|
|
148881
|
+
height: 100%;
|
|
148882
|
+
}
|
|
148883
|
+
#serious-terminal-container .xterm {
|
|
148884
|
+
height: 100%;
|
|
148885
|
+
}
|
|
148886
|
+
`;
|
|
148887
|
+
document.head.appendChild(style);
|
|
148888
|
+
}
|
|
148889
|
+
var STYLE_ID;
|
|
148890
|
+
var init_xtermStyles = __esm({
|
|
148891
|
+
"src/ui/xtermStyles.ts"() {
|
|
148892
|
+
"use strict";
|
|
148893
|
+
STYLE_ID = "copilot-office-xterm-styles";
|
|
148894
|
+
}
|
|
148895
|
+
});
|
|
148896
|
+
|
|
148897
|
+
// src/ui/terminalWheel.ts
|
|
148898
|
+
function wheelToPtySequence(deltaY, opts = {}) {
|
|
148899
|
+
if (!deltaY) return "";
|
|
148900
|
+
const pages = Math.max(1, Math.round(opts.pagesPerNotch ?? 1));
|
|
148901
|
+
const key = deltaY < 0 ? PAGE_UP : PAGE_DOWN;
|
|
148902
|
+
return key.repeat(pages);
|
|
148903
|
+
}
|
|
148904
|
+
var PAGE_UP, PAGE_DOWN;
|
|
148905
|
+
var init_terminalWheel = __esm({
|
|
148906
|
+
"src/ui/terminalWheel.ts"() {
|
|
148907
|
+
"use strict";
|
|
148908
|
+
PAGE_UP = "\x1B[5~";
|
|
148909
|
+
PAGE_DOWN = "\x1B[6~";
|
|
148910
|
+
}
|
|
148911
|
+
});
|
|
148912
|
+
|
|
148913
|
+
// src/agents/AutoStartCoordinator.ts
|
|
148914
|
+
function readSessionStorage() {
|
|
148915
|
+
try {
|
|
148916
|
+
if (typeof sessionStorage !== "undefined") return sessionStorage;
|
|
148917
|
+
} catch {
|
|
148918
|
+
}
|
|
148919
|
+
return null;
|
|
148920
|
+
}
|
|
148921
|
+
function setAutoStartCoordinator(c) {
|
|
148922
|
+
_instance = c;
|
|
148923
|
+
}
|
|
148924
|
+
function getAutoStartCoordinator() {
|
|
148925
|
+
return _instance;
|
|
148926
|
+
}
|
|
148927
|
+
var WARMED_STORAGE_KEY, WarmedOfficeRegistry, AgentReplaceTracker, AutoStartCoordinator, _instance;
|
|
148928
|
+
var init_AutoStartCoordinator = __esm({
|
|
148929
|
+
"src/agents/AutoStartCoordinator.ts"() {
|
|
148930
|
+
"use strict";
|
|
148931
|
+
WARMED_STORAGE_KEY = "copilot-office-auto-start:warmed";
|
|
148932
|
+
WarmedOfficeRegistry = class {
|
|
148933
|
+
constructor() {
|
|
148934
|
+
const storage = readSessionStorage();
|
|
148935
|
+
let initial = [];
|
|
148936
|
+
if (storage) {
|
|
148937
|
+
try {
|
|
148938
|
+
const raw = storage.getItem(WARMED_STORAGE_KEY);
|
|
148939
|
+
if (raw) {
|
|
148940
|
+
const parsed = JSON.parse(raw);
|
|
148941
|
+
if (Array.isArray(parsed)) initial = parsed.filter((s) => typeof s === "string");
|
|
148942
|
+
}
|
|
148943
|
+
} catch {
|
|
148944
|
+
}
|
|
148945
|
+
}
|
|
148946
|
+
this.warmed = new Set(initial);
|
|
148947
|
+
}
|
|
148948
|
+
has(officeId) {
|
|
148949
|
+
return this.warmed.has(officeId);
|
|
148950
|
+
}
|
|
148951
|
+
mark(officeId) {
|
|
148952
|
+
this.warmed.add(officeId);
|
|
148953
|
+
const storage = readSessionStorage();
|
|
148954
|
+
if (!storage) return;
|
|
148955
|
+
try {
|
|
148956
|
+
storage.setItem(WARMED_STORAGE_KEY, JSON.stringify(Array.from(this.warmed)));
|
|
148957
|
+
} catch {
|
|
148958
|
+
}
|
|
148959
|
+
}
|
|
148960
|
+
/** @internal — test helper. */
|
|
148961
|
+
snapshot() {
|
|
148962
|
+
return Array.from(this.warmed);
|
|
148963
|
+
}
|
|
148964
|
+
/** @internal — e2e helper for spec 009 A4 (Settings OFF gate). */
|
|
148965
|
+
clearAll() {
|
|
148966
|
+
this.warmed.clear();
|
|
148967
|
+
const storage = readSessionStorage();
|
|
148968
|
+
if (storage) {
|
|
148969
|
+
try {
|
|
148970
|
+
storage.removeItem(WARMED_STORAGE_KEY);
|
|
148971
|
+
} catch {
|
|
148972
|
+
}
|
|
148973
|
+
}
|
|
148974
|
+
}
|
|
148975
|
+
};
|
|
148976
|
+
AgentReplaceTracker = class {
|
|
148977
|
+
constructor() {
|
|
148978
|
+
this.inFlight = /* @__PURE__ */ new Map();
|
|
148979
|
+
}
|
|
148980
|
+
has(agentId) {
|
|
148981
|
+
return this.inFlight.has(agentId);
|
|
148982
|
+
}
|
|
148983
|
+
get(agentId) {
|
|
148984
|
+
return this.inFlight.get(agentId);
|
|
148985
|
+
}
|
|
148986
|
+
set(agentId, p) {
|
|
148987
|
+
this.inFlight.set(agentId, p);
|
|
148988
|
+
}
|
|
148989
|
+
delete(agentId) {
|
|
148990
|
+
this.inFlight.delete(agentId);
|
|
148991
|
+
}
|
|
148992
|
+
};
|
|
148993
|
+
AutoStartCoordinator = class {
|
|
148994
|
+
constructor(deps) {
|
|
148995
|
+
this.deps = deps;
|
|
148996
|
+
this.warmedOffices = new WarmedOfficeRegistry();
|
|
148997
|
+
this.replaceTracker = new AgentReplaceTracker();
|
|
148998
|
+
}
|
|
148999
|
+
/** Rule #1 + #2 trigger. Idempotent: no-op if office already warmed or
|
|
149000
|
+
* setting is OFF. Returns the agents it kicked off (for testing). */
|
|
149001
|
+
async tryWarmCurrentOffice() {
|
|
149002
|
+
if (!this.deps.getSettings().autoStartKnownAgents) return [];
|
|
149003
|
+
const oid = this.deps.getCurrentOfficeId();
|
|
149004
|
+
if (!oid) return [];
|
|
149005
|
+
if (this.warmedOffices.has(oid)) return [];
|
|
149006
|
+
this.warmedOffices.mark(oid);
|
|
149007
|
+
let roster;
|
|
149008
|
+
try {
|
|
149009
|
+
roster = this.deps.getCanonicalAgentIds(oid) || [];
|
|
149010
|
+
} catch {
|
|
149011
|
+
roster = [];
|
|
149012
|
+
}
|
|
149013
|
+
let meta;
|
|
149014
|
+
try {
|
|
149015
|
+
meta = await this.deps.getSessionMeta(oid) || {};
|
|
149016
|
+
} catch {
|
|
149017
|
+
meta = {};
|
|
149018
|
+
}
|
|
149019
|
+
const titled = [];
|
|
149020
|
+
for (const id of roster) {
|
|
149021
|
+
const entry = meta[id];
|
|
149022
|
+
const title = entry && typeof entry.title === "string" ? entry.title.trim() : "";
|
|
149023
|
+
if (title) titled.push(id);
|
|
149024
|
+
}
|
|
149025
|
+
const sids = await Promise.all(
|
|
149026
|
+
titled.map(
|
|
149027
|
+
(id) => Promise.resolve().then(() => this.deps.getCurrentSessionId(oid, id)).catch(() => null)
|
|
149028
|
+
)
|
|
149029
|
+
);
|
|
149030
|
+
const qualifying = [];
|
|
149031
|
+
for (let i = 0; i < titled.length; i++) {
|
|
149032
|
+
if (sids[i]) qualifying.push(titled[i]);
|
|
149033
|
+
}
|
|
149034
|
+
for (const id of qualifying) {
|
|
149035
|
+
void Promise.resolve().then(() => this.deps.warmAgentSession(oid, id)).catch((err) => {
|
|
149036
|
+
try {
|
|
149037
|
+
console.warn(
|
|
149038
|
+
`[AutoStartCoordinator] warmAgentSession failed for ${oid}/${id}:`,
|
|
149039
|
+
err
|
|
149040
|
+
);
|
|
149041
|
+
} catch {
|
|
149042
|
+
}
|
|
149043
|
+
});
|
|
149044
|
+
}
|
|
149045
|
+
return qualifying;
|
|
149046
|
+
}
|
|
149047
|
+
/** Rule #3 trigger. Returns the in-flight promise for an existing replace,
|
|
149048
|
+
* otherwise starts and tracks a new one. Setting OFF short-circuits to
|
|
149049
|
+
* just resetSession (acts like Close Session, per FR-017). */
|
|
149050
|
+
replaceSession(officeId, agentId) {
|
|
149051
|
+
const existing = this.replaceTracker.get(agentId);
|
|
149052
|
+
if (existing) return existing;
|
|
149053
|
+
const p = (async () => {
|
|
149054
|
+
await this.deps.resetSession(officeId, agentId);
|
|
149055
|
+
if (this.deps.getSettings().autoStartKnownAgents) {
|
|
149056
|
+
await this.deps.warmAgentSession(officeId, agentId);
|
|
149057
|
+
}
|
|
149058
|
+
})().finally(() => {
|
|
149059
|
+
this.replaceTracker.delete(agentId);
|
|
149060
|
+
});
|
|
149061
|
+
this.replaceTracker.set(agentId, p);
|
|
149062
|
+
return p;
|
|
149063
|
+
}
|
|
149064
|
+
};
|
|
149065
|
+
_instance = null;
|
|
149066
|
+
}
|
|
149067
|
+
});
|
|
149068
|
+
|
|
148572
149069
|
// src/ui/TerminalOverlay.ts
|
|
148573
149070
|
function withTimeout(promise, ms, label) {
|
|
148574
149071
|
let timeoutId = null;
|
|
@@ -148584,14 +149081,22 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148584
149081
|
});
|
|
148585
149082
|
});
|
|
148586
149083
|
}
|
|
148587
|
-
var import_xterm, import_addon_fit, IPC_TIMEOUT, TerminalOverlay;
|
|
149084
|
+
var import_xterm, import_addon_fit, IPC_TIMEOUT, DEBUG_COLD_START, DEBUG_SPRITE_SERIOUS, TerminalOverlay;
|
|
148588
149085
|
var init_TerminalOverlay = __esm({
|
|
148589
149086
|
"src/ui/TerminalOverlay.ts"() {
|
|
148590
149087
|
"use strict";
|
|
148591
149088
|
import_xterm = __toESM(require_xterm());
|
|
148592
149089
|
import_addon_fit = __toESM(require_addon_fit());
|
|
149090
|
+
init_agents();
|
|
149091
|
+
init_zIndex();
|
|
148593
149092
|
init_officeManager();
|
|
149093
|
+
init_clipboardToast();
|
|
149094
|
+
init_xtermStyles();
|
|
149095
|
+
init_terminalWheel();
|
|
149096
|
+
init_AutoStartCoordinator();
|
|
148594
149097
|
IPC_TIMEOUT = 1e4;
|
|
149098
|
+
DEBUG_COLD_START = typeof window !== "undefined" && window.__COPILOT_OFFICE_DEBUG_COLD_START__ === true || false;
|
|
149099
|
+
DEBUG_SPRITE_SERIOUS = false;
|
|
148595
149100
|
TerminalOverlay = class _TerminalOverlay {
|
|
148596
149101
|
constructor(scene, inputManager, getOfficeId) {
|
|
148597
149102
|
this.container = null;
|
|
@@ -148613,6 +149118,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148613
149118
|
this.mobileKeyboardBtn = null;
|
|
148614
149119
|
this.isFocused = false;
|
|
148615
149120
|
this.resizeHandler = null;
|
|
149121
|
+
this.clipboardHandler = null;
|
|
148616
149122
|
this.resizeObserver = null;
|
|
148617
149123
|
this.refitTimers = [];
|
|
148618
149124
|
this.refitGeneration = 0;
|
|
@@ -148621,11 +149127,18 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148621
149127
|
this.isReplaying = false;
|
|
148622
149128
|
this.launchMode = "copilot";
|
|
148623
149129
|
this.pendingInputLine = "";
|
|
148624
|
-
|
|
148625
|
-
|
|
148626
|
-
this.sessionRefreshExpiryTimer = null;
|
|
149130
|
+
// Spec 007: awaitingSessionIdRefresh / sessionRefresh*Timer fields removed
|
|
149131
|
+
// along with the parseSessionId / scheduleSessionIdRefresh helpers.
|
|
148627
149132
|
this.currentSessionTitle = null;
|
|
148628
149133
|
this.isEditingSessionTitle = false;
|
|
149134
|
+
this.terminalContextMenu = null;
|
|
149135
|
+
this.terminalContextMenuDismiss = null;
|
|
149136
|
+
// Disposable returned by xterm.terminal.onData(...). Re-registered per show()
|
|
149137
|
+
// so the handler's closure captures the new agent id (feature 002, C3/V6).
|
|
149138
|
+
this.onDataDisposable = null;
|
|
149139
|
+
// Toggled while show() is awaiting detach/attach so onData cannot fire input
|
|
149140
|
+
// against a half-attached agent (feature 002, V5).
|
|
149141
|
+
this.isSwitchingAgent = false;
|
|
148629
149142
|
this.scene = scene;
|
|
148630
149143
|
this.inputManager = inputManager;
|
|
148631
149144
|
this.getOfficeId = getOfficeId;
|
|
@@ -148645,7 +149158,6 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148645
149158
|
if (this.isReplaying) return;
|
|
148646
149159
|
if (agentId === this.currentAgentId && this.terminal) {
|
|
148647
149160
|
this.terminal.write(data);
|
|
148648
|
-
this.parseSessionId(data);
|
|
148649
149161
|
}
|
|
148650
149162
|
});
|
|
148651
149163
|
window.copilotBridge.onTerminalExit((agentId, exitCode) => {
|
|
@@ -148671,49 +149183,12 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148671
149183
|
this.setupTerminalListeners();
|
|
148672
149184
|
console.log("[TerminalOverlay] Re-attached terminal IPC listeners");
|
|
148673
149185
|
}
|
|
148674
|
-
|
|
148675
|
-
|
|
148676
|
-
|
|
148677
|
-
|
|
148678
|
-
|
|
148679
|
-
|
|
148680
|
-
clearTimeout(this.sessionRefreshExpiryTimer);
|
|
148681
|
-
this.sessionRefreshExpiryTimer = null;
|
|
148682
|
-
}
|
|
148683
|
-
}
|
|
148684
|
-
scheduleSessionIdRefresh(agentId) {
|
|
148685
|
-
if (!window.copilotBridge) return;
|
|
148686
|
-
const officeId = this.getActiveOfficeId();
|
|
148687
|
-
this.awaitingSessionIdRefresh = true;
|
|
148688
|
-
this.clearSessionRefreshTimers();
|
|
148689
|
-
const el = this.spriteCardElement?.querySelector(".session-id-display");
|
|
148690
|
-
if (el) {
|
|
148691
|
-
el.textContent = "syncing...";
|
|
148692
|
-
}
|
|
148693
|
-
this.sessionRefreshCommandTimer = setTimeout(() => {
|
|
148694
|
-
this.sessionRefreshCommandTimer = null;
|
|
148695
|
-
void window.copilotBridge.terminalWrite(officeId, agentId, "/session\r").catch(() => {
|
|
148696
|
-
});
|
|
148697
|
-
}, 400);
|
|
148698
|
-
this.sessionRefreshExpiryTimer = setTimeout(() => {
|
|
148699
|
-
this.sessionRefreshExpiryTimer = null;
|
|
148700
|
-
this.awaitingSessionIdRefresh = false;
|
|
148701
|
-
this.updateSessionDisplay();
|
|
148702
|
-
}, 12e3);
|
|
148703
|
-
}
|
|
148704
|
-
parseSessionId(data) {
|
|
148705
|
-
if (!this.awaitingSessionIdRefresh || !this.currentAgentId || !window.copilotBridge) return;
|
|
148706
|
-
const match = data.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i);
|
|
148707
|
-
if (!match) return;
|
|
148708
|
-
const nextSessionId = match[0].toLowerCase();
|
|
148709
|
-
this.awaitingSessionIdRefresh = false;
|
|
148710
|
-
this.clearSessionRefreshTimers();
|
|
148711
|
-
this.sessionId = nextSessionId;
|
|
148712
|
-
this.updateSessionDisplay();
|
|
148713
|
-
const officeId = this.getActiveOfficeId();
|
|
148714
|
-
void window.copilotBridge.setSessionId(officeId, this.currentAgentId, nextSessionId).catch(() => {
|
|
148715
|
-
});
|
|
148716
|
-
}
|
|
149186
|
+
// Spec 007: parseSessionId / scheduleSessionIdRefresh / awaitingSessionIdRefresh
|
|
149187
|
+
// were removed. They greedily matched any UUID-shaped substring in PTY data
|
|
149188
|
+
// (which could be a constant install/trace/OAuth UUID emitted by Copilot CLI
|
|
149189
|
+
// before the real session UUID), then persisted that wrong value as the
|
|
149190
|
+
// agent's session id. The server is now the only source of truth for session
|
|
149191
|
+
// ids — see `bridge.resetSession` in the /new path below.
|
|
148717
149192
|
getActiveOfficeId() {
|
|
148718
149193
|
return this.attachedOfficeId ?? this.getOfficeId();
|
|
148719
149194
|
}
|
|
@@ -148723,6 +149198,75 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148723
149198
|
}
|
|
148724
149199
|
this.refitTimers.length = 0;
|
|
148725
149200
|
}
|
|
149201
|
+
// Spec 006: diagnostic toast prefix so multi-instance and channel issues
|
|
149202
|
+
// are visible in the UI (no DevTools required).
|
|
149203
|
+
tag() {
|
|
149204
|
+
return `[O${this.instanceId}]`;
|
|
149205
|
+
}
|
|
149206
|
+
// Spec 005 + 006: write text to OS clipboard via Electron main process.
|
|
149207
|
+
// Diagnostic toast on every outcome so we never have to guess again.
|
|
149208
|
+
async copyToClipboard(text, source = "live") {
|
|
149209
|
+
const t = this.tag();
|
|
149210
|
+
if (!text) {
|
|
149211
|
+
showClipboardToast(`${t} empty selection`, "info");
|
|
149212
|
+
return false;
|
|
149213
|
+
}
|
|
149214
|
+
const bridge = window.copilotBridge;
|
|
149215
|
+
if (!bridge?.clipboardWriteText) {
|
|
149216
|
+
try {
|
|
149217
|
+
await navigator.clipboard.writeText(text);
|
|
149218
|
+
showClipboardToast(`${t} OK ${text.length} (fallback)`, "success");
|
|
149219
|
+
return true;
|
|
149220
|
+
} catch {
|
|
149221
|
+
showClipboardToast(`${t} no-bridge`, "error");
|
|
149222
|
+
return false;
|
|
149223
|
+
}
|
|
149224
|
+
}
|
|
149225
|
+
try {
|
|
149226
|
+
const r = await bridge.clipboardWriteText(text);
|
|
149227
|
+
if (r?.success === true) {
|
|
149228
|
+
showClipboardToast(`${t} OK ${text.length} (verified)`, "success");
|
|
149229
|
+
return true;
|
|
149230
|
+
}
|
|
149231
|
+
if (r?.verified === false) {
|
|
149232
|
+
showClipboardToast(`${t} verify-fail (wrote=${text.length})`, "error");
|
|
149233
|
+
} else {
|
|
149234
|
+
showClipboardToast(`${t} bridge-err: ${r?.error || "unknown"}`, "error");
|
|
149235
|
+
}
|
|
149236
|
+
return false;
|
|
149237
|
+
} catch (e) {
|
|
149238
|
+
showClipboardToast(`${t} bridge-err: ${e?.message || "threw"}`, "error");
|
|
149239
|
+
return false;
|
|
149240
|
+
}
|
|
149241
|
+
}
|
|
149242
|
+
// Spec 005: read OS clipboard via Electron main, forward to PTY.
|
|
149243
|
+
async pasteFromClipboardToTerminal() {
|
|
149244
|
+
if (!this.currentAgentId || !window.copilotBridge) return;
|
|
149245
|
+
let text = "";
|
|
149246
|
+
try {
|
|
149247
|
+
const bridge = window.copilotBridge;
|
|
149248
|
+
if (bridge?.clipboardReadText) {
|
|
149249
|
+
const r = await bridge.clipboardReadText();
|
|
149250
|
+
if (r?.success) text = r.text || "";
|
|
149251
|
+
} else if (navigator.clipboard?.readText) {
|
|
149252
|
+
text = await navigator.clipboard.readText();
|
|
149253
|
+
}
|
|
149254
|
+
} catch (e) {
|
|
149255
|
+
showClipboardToast(`Paste failed: ${e?.message || "bridge threw"}`, "error");
|
|
149256
|
+
return;
|
|
149257
|
+
}
|
|
149258
|
+
if (!text) {
|
|
149259
|
+
showClipboardToast("Clipboard is empty", "info");
|
|
149260
|
+
return;
|
|
149261
|
+
}
|
|
149262
|
+
const officeId = this.attachedOfficeId ?? this.getOfficeId();
|
|
149263
|
+
try {
|
|
149264
|
+
await window.copilotBridge.terminalWrite(officeId, this.currentAgentId, text);
|
|
149265
|
+
showClipboardToast(`Pasted ${text.length} char${text.length === 1 ? "" : "s"}`, "success");
|
|
149266
|
+
} catch (e) {
|
|
149267
|
+
showClipboardToast(`Paste failed: ${e?.message || "terminalWrite threw"}`, "error");
|
|
149268
|
+
}
|
|
149269
|
+
}
|
|
148726
149270
|
resolveTerminalDimensions() {
|
|
148727
149271
|
if (!this.terminal || !this.fitAddon) return null;
|
|
148728
149272
|
this.fitAddon.fit();
|
|
@@ -148760,7 +149304,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148760
149304
|
const el = this.spriteCardElement?.querySelector(".session-id-display");
|
|
148761
149305
|
if (el && this.sessionId) {
|
|
148762
149306
|
el.textContent = this.sessionId;
|
|
148763
|
-
el.title = `Click to copy. Resume with: copilot --
|
|
149307
|
+
el.title = `Click to copy. Resume with: copilot --session-id ${this.sessionId}`;
|
|
148764
149308
|
el.onclick = () => this.copySessionId();
|
|
148765
149309
|
}
|
|
148766
149310
|
}
|
|
@@ -148849,20 +149393,42 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148849
149393
|
async show(agent, onClose, options) {
|
|
148850
149394
|
const previousAgentId = this.currentAgentId;
|
|
148851
149395
|
const previousOfficeId = this.attachedOfficeId ?? this.getOfficeId();
|
|
149396
|
+
const nextOfficeId = this.getOfficeId();
|
|
149397
|
+
const isSwitchingAgent = previousAgentId !== null && (previousAgentId !== agent.id || previousOfficeId !== nextOfficeId);
|
|
148852
149398
|
if (previousAgentId && previousAgentId !== agent.id) {
|
|
148853
149399
|
this.acknowledgeCompletedWork(previousOfficeId, previousAgentId);
|
|
148854
149400
|
}
|
|
149401
|
+
if (isSwitchingAgent && previousAgentId && window.copilotBridge) {
|
|
149402
|
+
this.isSwitchingAgent = true;
|
|
149403
|
+
this.onDataDisposable?.dispose();
|
|
149404
|
+
this.onDataDisposable = null;
|
|
149405
|
+
try {
|
|
149406
|
+
const detachStartedAt = Date.now();
|
|
149407
|
+
await withTimeout(
|
|
149408
|
+
window.copilotBridge.terminalDetach(previousOfficeId, previousAgentId),
|
|
149409
|
+
IPC_TIMEOUT,
|
|
149410
|
+
"terminalDetach"
|
|
149411
|
+
);
|
|
149412
|
+
if (DEBUG_COLD_START) {
|
|
149413
|
+
console.log(
|
|
149414
|
+
`[TerminalOverlay] switch from=${previousAgentId} to=${agent.id} detachMs=${Date.now() - detachStartedAt}`
|
|
149415
|
+
);
|
|
149416
|
+
}
|
|
149417
|
+
} catch (e) {
|
|
149418
|
+
console.warn(`[TerminalOverlay] terminalDetach failed for ${previousAgentId}: ${String(e)}`);
|
|
149419
|
+
}
|
|
149420
|
+
}
|
|
148855
149421
|
this.currentAgentId = agent.id;
|
|
148856
149422
|
this.onCloseCallback = onClose;
|
|
148857
149423
|
this.isReadOnly = options?.readOnly ?? false;
|
|
148858
149424
|
this.launchMode = options?.launchMode ?? "copilot";
|
|
148859
|
-
this.attachedOfficeId =
|
|
149425
|
+
this.attachedOfficeId = nextOfficeId;
|
|
148860
149426
|
const officeId = this.getActiveOfficeId();
|
|
148861
149427
|
this.currentAgent = agent;
|
|
148862
149428
|
if (!this.container) {
|
|
148863
149429
|
this.createContainer();
|
|
148864
149430
|
}
|
|
148865
|
-
const inceptionBadge = agent.id ===
|
|
149431
|
+
const inceptionBadge = agent.id === ADMIN_AGENT_ID ? " \u{1F3AD} INCEPTION MODE" : "";
|
|
148866
149432
|
let sessionTitle = null;
|
|
148867
149433
|
if (window.copilotBridge?.getSessionMeta) {
|
|
148868
149434
|
try {
|
|
@@ -148899,8 +149465,6 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148899
149465
|
if (this.container) {
|
|
148900
149466
|
this.container.style.display = "flex";
|
|
148901
149467
|
}
|
|
148902
|
-
this.awaitingSessionIdRefresh = false;
|
|
148903
|
-
this.clearSessionRefreshTimers();
|
|
148904
149468
|
if (this.spriteCardElement) {
|
|
148905
149469
|
this.spriteCardElement.style.display = "flex";
|
|
148906
149470
|
}
|
|
@@ -148921,8 +149485,6 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148921
149485
|
this.updateSessionTitleDisplay(sessionTitle);
|
|
148922
149486
|
this.drawAgentSprite(agent);
|
|
148923
149487
|
this.pendingInputLine = "";
|
|
148924
|
-
this.awaitingSessionIdRefresh = false;
|
|
148925
|
-
this.clearSessionRefreshTimers();
|
|
148926
149488
|
this.clearRefitTimers();
|
|
148927
149489
|
this.refitGeneration += 1;
|
|
148928
149490
|
if (!this.terminal) {
|
|
@@ -148980,6 +149542,14 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
148980
149542
|
}
|
|
148981
149543
|
}
|
|
148982
149544
|
this.isVisible = true;
|
|
149545
|
+
const attachStartedAt = Date.now();
|
|
149546
|
+
this.isSwitchingAgent = false;
|
|
149547
|
+
this.registerOnDataHandler(agent.id, officeId);
|
|
149548
|
+
if (DEBUG_COLD_START && isSwitchingAgent) {
|
|
149549
|
+
console.log(
|
|
149550
|
+
`[TerminalOverlay] switch attach complete to=${agent.id} attachMs=${Date.now() - attachStartedAt}`
|
|
149551
|
+
);
|
|
149552
|
+
}
|
|
148983
149553
|
this.scene.game.events.emit("npc:highlight", agent.id);
|
|
148984
149554
|
const spriteCanvas = this.spriteCardElement?.querySelector(".agent-sprite-canvas");
|
|
148985
149555
|
if (spriteCanvas) {
|
|
@@ -149006,8 +149576,6 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149006
149576
|
}, 50);
|
|
149007
149577
|
}
|
|
149008
149578
|
async startNewSession(agentId, workingDir, officeId) {
|
|
149009
|
-
this.awaitingSessionIdRefresh = false;
|
|
149010
|
-
this.clearSessionRefreshTimers();
|
|
149011
149579
|
this.sessionId = null;
|
|
149012
149580
|
this.updateSessionDisplay();
|
|
149013
149581
|
const el = this.spriteCardElement?.querySelector(".session-id-display");
|
|
@@ -149042,8 +149610,19 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149042
149610
|
this.updateSessionDisplay();
|
|
149043
149611
|
}
|
|
149044
149612
|
}
|
|
149045
|
-
|
|
149046
|
-
|
|
149613
|
+
// Spec 007: after the user types /new in the PTY, ask the server to mint
|
|
149614
|
+
// a fresh per-agent session UUID. Authoritative — never parses CLI output.
|
|
149615
|
+
async fetchSessionId(agentId) {
|
|
149616
|
+
if (!window.copilotBridge) return;
|
|
149617
|
+
const officeId = this.getActiveOfficeId();
|
|
149618
|
+
try {
|
|
149619
|
+
const r = await window.copilotBridge.resetSession(officeId, agentId);
|
|
149620
|
+
if (r?.success && r.sessionId && agentId === this.currentAgentId) {
|
|
149621
|
+
this.sessionId = r.sessionId;
|
|
149622
|
+
this.updateSessionDisplay();
|
|
149623
|
+
}
|
|
149624
|
+
} catch {
|
|
149625
|
+
}
|
|
149047
149626
|
}
|
|
149048
149627
|
createContainer() {
|
|
149049
149628
|
this.container = document.createElement("div");
|
|
@@ -149059,7 +149638,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149059
149638
|
border-radius: 0;
|
|
149060
149639
|
display: none;
|
|
149061
149640
|
flex-direction: column;
|
|
149062
|
-
z-index:
|
|
149641
|
+
z-index: ${ZIndex.TERMINAL_OVERLAY};
|
|
149063
149642
|
`;
|
|
149064
149643
|
this.headerElement = document.createElement("div");
|
|
149065
149644
|
this.headerElement.style.cssText = `
|
|
@@ -149080,7 +149659,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149080
149659
|
terminalOuter.id = "terminal-container";
|
|
149081
149660
|
terminalOuter.style.cssText = `
|
|
149082
149661
|
flex: 1;
|
|
149083
|
-
overflow:
|
|
149662
|
+
overflow: auto;
|
|
149084
149663
|
min-height: 0;
|
|
149085
149664
|
padding: 10px;
|
|
149086
149665
|
box-sizing: border-box;
|
|
@@ -149089,13 +149668,18 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149089
149668
|
this.terminalDiv.style.cssText = `
|
|
149090
149669
|
width: 100%;
|
|
149091
149670
|
height: 100%;
|
|
149092
|
-
overflow: hidden;
|
|
149093
149671
|
`;
|
|
149094
149672
|
terminalOuter.appendChild(this.terminalDiv);
|
|
149095
149673
|
terminalOuter.addEventListener("mousedown", () => {
|
|
149096
149674
|
if (this.isVisible && !this.isFocused) {
|
|
149097
149675
|
this.focusTerminal();
|
|
149098
149676
|
}
|
|
149677
|
+
this.terminal?.focus();
|
|
149678
|
+
});
|
|
149679
|
+
terminalOuter.addEventListener("mouseup", () => {
|
|
149680
|
+
if (this.isVisible) {
|
|
149681
|
+
requestAnimationFrame(() => this.terminal?.focus());
|
|
149682
|
+
}
|
|
149099
149683
|
});
|
|
149100
149684
|
this.container.appendChild(terminalOuter);
|
|
149101
149685
|
const terminalPanel = document.getElementById("terminal-panel") || document.body;
|
|
@@ -149114,6 +149698,16 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149114
149698
|
}
|
|
149115
149699
|
/** Create the SpriteCard — a full-width bottom bar showing agent sprite, info, and controls. */
|
|
149116
149700
|
createSpriteCard() {
|
|
149701
|
+
const stale = document.getElementById("sprite-card");
|
|
149702
|
+
if (stale) {
|
|
149703
|
+
try {
|
|
149704
|
+
stale.remove();
|
|
149705
|
+
} catch {
|
|
149706
|
+
}
|
|
149707
|
+
if (DEBUG_SPRITE_SERIOUS) {
|
|
149708
|
+
console.log("[TerminalOverlay] createSpriteCard removed stale #sprite-card before append");
|
|
149709
|
+
}
|
|
149710
|
+
}
|
|
149117
149711
|
this.spriteCardElement = document.createElement("div");
|
|
149118
149712
|
this.spriteCardElement.id = "sprite-card";
|
|
149119
149713
|
this.spriteCardElement.style.cssText = `
|
|
@@ -149130,7 +149724,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149130
149724
|
padding: 16px 24px;
|
|
149131
149725
|
box-sizing: border-box;
|
|
149132
149726
|
position: relative;
|
|
149133
|
-
z-index:
|
|
149727
|
+
z-index: ${ZIndex.TERMINAL_SPRITE_CARD};
|
|
149134
149728
|
`;
|
|
149135
149729
|
const agentDisplay = document.createElement("div");
|
|
149136
149730
|
agentDisplay.className = "agent-display";
|
|
@@ -149277,49 +149871,65 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149277
149871
|
this.footerElement = this.spriteCardElement;
|
|
149278
149872
|
}
|
|
149279
149873
|
copySessionId() {
|
|
149280
|
-
if (this.sessionId)
|
|
149281
|
-
|
|
149874
|
+
if (!this.sessionId) return;
|
|
149875
|
+
void this.copyToClipboard(this.sessionId, "session").then((success) => {
|
|
149876
|
+
if (!this.sessionIdElement) return;
|
|
149877
|
+
const original = this.sessionIdElement.textContent;
|
|
149878
|
+
this.sessionIdElement.textContent = success ? "Copied!" : "Copy failed";
|
|
149879
|
+
this.sessionIdElement.style.color = success ? "#50fa7b" : "#ff6b6b";
|
|
149880
|
+
setTimeout(() => {
|
|
149282
149881
|
if (this.sessionIdElement) {
|
|
149283
|
-
|
|
149284
|
-
this.sessionIdElement.
|
|
149285
|
-
this.sessionIdElement.style.color = "#50fa7b";
|
|
149286
|
-
setTimeout(() => {
|
|
149287
|
-
if (this.sessionIdElement) {
|
|
149288
|
-
this.sessionIdElement.textContent = original;
|
|
149289
|
-
this.sessionIdElement.style.color = "#4a9eff";
|
|
149290
|
-
}
|
|
149291
|
-
}, 1e3);
|
|
149882
|
+
this.sessionIdElement.textContent = original;
|
|
149883
|
+
this.sessionIdElement.style.color = "#4a9eff";
|
|
149292
149884
|
}
|
|
149293
|
-
});
|
|
149294
|
-
}
|
|
149885
|
+
}, 1e3);
|
|
149886
|
+
});
|
|
149295
149887
|
}
|
|
149296
149888
|
async handleNewSession() {
|
|
149297
149889
|
if (!this.currentAgentId || !this.currentAgent || this.isReadOnly) return;
|
|
149298
|
-
this.awaitingSessionIdRefresh = false;
|
|
149299
|
-
this.clearSessionRefreshTimers();
|
|
149300
149890
|
const officeId = this.attachedOfficeId ?? this.getOfficeId();
|
|
149301
|
-
|
|
149891
|
+
const agentId = this.currentAgentId;
|
|
149892
|
+
console.log(`[TerminalOverlay] handleNewSession: agent=${agentId}, office=${officeId}`);
|
|
149302
149893
|
this.clearRefitTimers();
|
|
149303
149894
|
this.refitGeneration += 1;
|
|
149304
149895
|
this.pendingInputLine = "";
|
|
149305
149896
|
this.terminal?.clear();
|
|
149306
149897
|
this.terminal?.writeln("\x1B[33m[Starting new session...]\x1B[0m\r\n");
|
|
149307
|
-
await withTimeout(
|
|
149308
|
-
window.copilotBridge.resetSession(officeId, this.currentAgentId),
|
|
149309
|
-
IPC_TIMEOUT,
|
|
149310
|
-
"resetSession"
|
|
149311
|
-
).catch(() => {
|
|
149312
|
-
});
|
|
149313
149898
|
const el = this.spriteCardElement?.querySelector(".session-id-display");
|
|
149314
149899
|
if (el) el.textContent = "starting...";
|
|
149315
149900
|
this.sessionId = null;
|
|
149316
149901
|
this.updateSessionDisplay();
|
|
149317
149902
|
this.updateSessionTitleDisplay(null);
|
|
149318
|
-
const
|
|
149903
|
+
const coordinator = getAutoStartCoordinator();
|
|
149904
|
+
if (coordinator) {
|
|
149905
|
+
try {
|
|
149906
|
+
await coordinator.replaceSession(officeId, agentId);
|
|
149907
|
+
} catch (err) {
|
|
149908
|
+
this.terminal?.writeln(`Failed to start terminal: ${err?.message || String(err)}`);
|
|
149909
|
+
}
|
|
149910
|
+
try {
|
|
149911
|
+
if (window.copilotBridge?.getSessionId) {
|
|
149912
|
+
const sid = await window.copilotBridge.getSessionId(officeId, agentId);
|
|
149913
|
+
if (sid) {
|
|
149914
|
+
this.sessionId = sid;
|
|
149915
|
+
this.updateSessionDisplay();
|
|
149916
|
+
}
|
|
149917
|
+
}
|
|
149918
|
+
} catch {
|
|
149919
|
+
}
|
|
149920
|
+
return;
|
|
149921
|
+
}
|
|
149922
|
+
await withTimeout(
|
|
149923
|
+
window.copilotBridge.resetSession(officeId, agentId),
|
|
149924
|
+
IPC_TIMEOUT,
|
|
149925
|
+
"resetSession"
|
|
149926
|
+
).catch(() => {
|
|
149927
|
+
});
|
|
149928
|
+
const dims = this.fitAndResizeTerminal({ officeId, agentId });
|
|
149319
149929
|
const result = await withTimeout(
|
|
149320
149930
|
this.launchMode === "shell" ? window.copilotBridge.terminalStart(
|
|
149321
149931
|
officeId,
|
|
149322
|
-
|
|
149932
|
+
agentId,
|
|
149323
149933
|
this.currentAgent.workingDir || officeManager.getCurrentWorkingDirectory(),
|
|
149324
149934
|
dims?.cols,
|
|
149325
149935
|
dims?.rows,
|
|
@@ -149327,7 +149937,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149327
149937
|
"shell"
|
|
149328
149938
|
) : window.copilotBridge.terminalStart(
|
|
149329
149939
|
officeId,
|
|
149330
|
-
|
|
149940
|
+
agentId,
|
|
149331
149941
|
this.currentAgent.workingDir || officeManager.getCurrentWorkingDirectory(),
|
|
149332
149942
|
dims?.cols,
|
|
149333
149943
|
dims?.rows
|
|
@@ -149390,7 +150000,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149390
150000
|
min-width: 320px;
|
|
149391
150001
|
max-height: 250px;
|
|
149392
150002
|
overflow-y: auto;
|
|
149393
|
-
z-index:
|
|
150003
|
+
z-index: ${ZIndex.TERMINAL_SPRITE_CARD};
|
|
149394
150004
|
font-family: 'Cascadia Code', Consolas, monospace;
|
|
149395
150005
|
font-size: 12px;
|
|
149396
150006
|
box-shadow: 0 -4px 12px rgba(0,0,0,0.5);
|
|
@@ -149448,21 +150058,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149448
150058
|
this.closeHistoryPopover();
|
|
149449
150059
|
}
|
|
149450
150060
|
injectStyles() {
|
|
149451
|
-
|
|
149452
|
-
const style = document.createElement("style");
|
|
149453
|
-
style.id = "xterm-styles";
|
|
149454
|
-
style.textContent = `
|
|
149455
|
-
.xterm {
|
|
149456
|
-
height: 100%;
|
|
149457
|
-
}
|
|
149458
|
-
.xterm-viewport {
|
|
149459
|
-
background-color: #0a0a14 !important;
|
|
149460
|
-
}
|
|
149461
|
-
#terminal-container .xterm {
|
|
149462
|
-
height: 100%;
|
|
149463
|
-
}
|
|
149464
|
-
`;
|
|
149465
|
-
document.head.appendChild(style);
|
|
150061
|
+
ensureXtermStyles();
|
|
149466
150062
|
}
|
|
149467
150063
|
createTerminal() {
|
|
149468
150064
|
if (!this.terminalDiv) return;
|
|
@@ -149502,23 +150098,109 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149502
150098
|
this.terminal.loadAddon(this.fitAddon);
|
|
149503
150099
|
this.terminal.open(this.terminalDiv);
|
|
149504
150100
|
this.fitAndResizeTerminal();
|
|
150101
|
+
const MOUSE_MODES = /* @__PURE__ */ new Set([1e3, 1002, 1003, 1006]);
|
|
150102
|
+
this.terminal.parser.registerCsiHandler({ prefix: "?", final: "h" }, (params) => {
|
|
150103
|
+
for (const p of params) {
|
|
150104
|
+
if (typeof p === "number" && MOUSE_MODES.has(p)) return true;
|
|
150105
|
+
}
|
|
150106
|
+
return false;
|
|
150107
|
+
});
|
|
150108
|
+
this.terminal.attachCustomWheelEventHandler((event) => {
|
|
150109
|
+
const term = this.terminal;
|
|
150110
|
+
if (!term) return true;
|
|
150111
|
+
if (term.buffer.active.type !== "alternate") return true;
|
|
150112
|
+
const seq = wheelToPtySequence(event.deltaY);
|
|
150113
|
+
if (!seq) return true;
|
|
150114
|
+
const officeId = this.attachedOfficeId ?? this.getOfficeId();
|
|
150115
|
+
if (officeId && this.currentAgentId && window.copilotBridge) {
|
|
150116
|
+
void window.copilotBridge.terminalWrite(officeId, this.currentAgentId, seq);
|
|
150117
|
+
}
|
|
150118
|
+
return false;
|
|
150119
|
+
});
|
|
150120
|
+
this.installTerminalContextMenu();
|
|
149505
150121
|
this.terminal.attachCustomKeyEventHandler((event) => {
|
|
149506
|
-
|
|
150122
|
+
const isModifierPressed = event.ctrlKey || event.metaKey;
|
|
150123
|
+
const key = event.key.toLowerCase();
|
|
150124
|
+
if (event.type !== "keydown" || !isModifierPressed) return true;
|
|
150125
|
+
if (key === "c") {
|
|
150126
|
+
const selection = this.terminal?.hasSelection() ? this.terminal.getSelection() ?? "" : "";
|
|
150127
|
+
if (!selection) {
|
|
150128
|
+
return true;
|
|
150129
|
+
}
|
|
150130
|
+
event.preventDefault();
|
|
150131
|
+
event.stopPropagation();
|
|
150132
|
+
void this.copyToClipboard(selection, "live");
|
|
150133
|
+
return false;
|
|
150134
|
+
}
|
|
150135
|
+
if (key === "v") {
|
|
149507
150136
|
if (this.isReadOnly) return false;
|
|
149508
150137
|
event.preventDefault();
|
|
149509
150138
|
event.stopPropagation();
|
|
149510
|
-
|
|
149511
|
-
if (text) this.terminal.paste(text);
|
|
149512
|
-
}).catch((err) => {
|
|
149513
|
-
console.warn("[Terminal] Clipboard read failed:", err);
|
|
149514
|
-
});
|
|
150139
|
+
void this.pasteFromClipboardToTerminal();
|
|
149515
150140
|
return false;
|
|
149516
150141
|
}
|
|
149517
150142
|
return true;
|
|
149518
150143
|
});
|
|
149519
|
-
this.
|
|
150144
|
+
if (this.clipboardHandler) {
|
|
150145
|
+
document.removeEventListener("keydown", this.clipboardHandler, true);
|
|
150146
|
+
}
|
|
150147
|
+
this.clipboardHandler = (event) => {
|
|
150148
|
+
if (!this.isVisible) return;
|
|
150149
|
+
if (this.isEditingSessionTitle) return;
|
|
150150
|
+
const active = document.activeElement;
|
|
150151
|
+
if (active && (active.tagName === "INPUT" || active.tagName === "TEXTAREA") && active !== this.terminal?.textarea) {
|
|
150152
|
+
return;
|
|
150153
|
+
}
|
|
150154
|
+
const isModifierPressed = event.ctrlKey || event.metaKey;
|
|
150155
|
+
if (!isModifierPressed || event.type !== "keydown") return;
|
|
150156
|
+
const key = event.key.toLowerCase();
|
|
150157
|
+
if (key === "c") {
|
|
150158
|
+
const selection = this.terminal?.hasSelection() ? this.terminal.getSelection() ?? "" : "";
|
|
150159
|
+
if (!selection) return;
|
|
150160
|
+
event.preventDefault();
|
|
150161
|
+
event.stopImmediatePropagation();
|
|
150162
|
+
void this.copyToClipboard(selection, "live");
|
|
150163
|
+
} else if (key === "v") {
|
|
150164
|
+
if (this.isReadOnly) return;
|
|
150165
|
+
event.preventDefault();
|
|
150166
|
+
event.stopImmediatePropagation();
|
|
150167
|
+
void this.pasteFromClipboardToTerminal();
|
|
150168
|
+
}
|
|
150169
|
+
};
|
|
150170
|
+
document.addEventListener("keydown", this.clipboardHandler, true);
|
|
150171
|
+
this.resizeHandler = () => {
|
|
150172
|
+
if (this.isVisible) {
|
|
150173
|
+
this.applySpriteCardResponsiveStyles();
|
|
150174
|
+
this.updateMobileKeyboardButtonVisibility();
|
|
150175
|
+
this.debouncedRefit();
|
|
150176
|
+
}
|
|
150177
|
+
};
|
|
150178
|
+
window.addEventListener("resize", this.resizeHandler);
|
|
150179
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
150180
|
+
if (this.isVisible) {
|
|
150181
|
+
this.applySpriteCardResponsiveStyles();
|
|
150182
|
+
this.updateMobileKeyboardButtonVisibility();
|
|
150183
|
+
this.debouncedRefit();
|
|
150184
|
+
}
|
|
150185
|
+
});
|
|
150186
|
+
if (this.terminalDiv) {
|
|
150187
|
+
this.resizeObserver.observe(this.terminalDiv);
|
|
150188
|
+
}
|
|
150189
|
+
}
|
|
150190
|
+
/**
|
|
150191
|
+
* Re-register the xterm `onData` handler with a fresh closure that captures
|
|
150192
|
+
* the bound `agentId` and `officeId` at registration time. Disposes any
|
|
150193
|
+
* previous registration so stale closures cannot send user keystrokes to
|
|
150194
|
+
* the wrong agent during an agent switch (feature 002, C3/V6).
|
|
150195
|
+
*/
|
|
150196
|
+
registerOnDataHandler(boundAgentId, boundOfficeId) {
|
|
150197
|
+
if (!this.terminal) return;
|
|
150198
|
+
this.onDataDisposable?.dispose();
|
|
150199
|
+
this.onDataDisposable = null;
|
|
150200
|
+
const result = this.terminal.onData((data) => {
|
|
149520
150201
|
if (this.isReadOnly) return;
|
|
149521
|
-
if (
|
|
150202
|
+
if (this.isSwitchingAgent) return;
|
|
150203
|
+
if (!window.copilotBridge) return;
|
|
149522
150204
|
let outbound = "";
|
|
149523
150205
|
let shouldStartSlashNewSession = false;
|
|
149524
150206
|
for (const ch of data) {
|
|
@@ -149542,30 +150224,98 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149542
150224
|
outbound += ch;
|
|
149543
150225
|
}
|
|
149544
150226
|
if (outbound.length > 0) {
|
|
149545
|
-
window.copilotBridge.terminalWrite(
|
|
150227
|
+
window.copilotBridge.terminalWrite(boundOfficeId, boundAgentId, outbound);
|
|
149546
150228
|
}
|
|
149547
150229
|
if (shouldStartSlashNewSession) {
|
|
149548
|
-
this.fetchSessionId(
|
|
150230
|
+
this.fetchSessionId(boundAgentId);
|
|
149549
150231
|
}
|
|
149550
150232
|
});
|
|
149551
|
-
this.
|
|
149552
|
-
|
|
149553
|
-
|
|
149554
|
-
|
|
149555
|
-
|
|
149556
|
-
|
|
150233
|
+
this.onDataDisposable = result && typeof result.dispose === "function" ? result : null;
|
|
150234
|
+
}
|
|
150235
|
+
/**
|
|
150236
|
+
* Spec 004: terminal right-click context menu with Copy (enabled iff
|
|
150237
|
+
* non-empty selection) and Paste (always enabled). Built once, reused
|
|
150238
|
+
* across selections; dismissed on any outside mousedown or Escape.
|
|
150239
|
+
*/
|
|
150240
|
+
installTerminalContextMenu() {
|
|
150241
|
+
if (!this.terminal || !this.terminalDiv) return;
|
|
150242
|
+
const menu = document.createElement("div");
|
|
150243
|
+
menu.id = "terminal-context-menu";
|
|
150244
|
+
menu.style.cssText = `
|
|
150245
|
+
position: fixed;
|
|
150246
|
+
display: none;
|
|
150247
|
+
z-index: ${ZIndex.TERMINAL_SPRITE_CARD + 10};
|
|
150248
|
+
min-width: 160px;
|
|
150249
|
+
background: #1c1c2a;
|
|
150250
|
+
border: 1px solid #3a3a55;
|
|
150251
|
+
border-radius: 6px;
|
|
150252
|
+
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.55);
|
|
150253
|
+
padding: 4px 0;
|
|
150254
|
+
font-family: 'Cascadia Code', Consolas, monospace;
|
|
150255
|
+
font-size: 13px;
|
|
150256
|
+
color: #cfd0e0;
|
|
150257
|
+
user-select: none;
|
|
150258
|
+
`;
|
|
150259
|
+
const makeItem = (label, onClick) => {
|
|
150260
|
+
const item = document.createElement("div");
|
|
150261
|
+
item.textContent = label;
|
|
150262
|
+
item.style.cssText = `
|
|
150263
|
+
padding: 6px 14px;
|
|
150264
|
+
cursor: pointer;
|
|
150265
|
+
`;
|
|
150266
|
+
item.dataset.enabled = "true";
|
|
150267
|
+
item.addEventListener("mouseenter", () => {
|
|
150268
|
+
if (item.dataset.enabled === "true") item.style.background = "#2a2a45";
|
|
150269
|
+
});
|
|
150270
|
+
item.addEventListener("mouseleave", () => {
|
|
150271
|
+
item.style.background = "";
|
|
150272
|
+
});
|
|
150273
|
+
item.addEventListener("mousedown", (e) => {
|
|
150274
|
+
e.preventDefault();
|
|
150275
|
+
e.stopPropagation();
|
|
150276
|
+
});
|
|
150277
|
+
item.addEventListener("click", (e) => {
|
|
150278
|
+
e.preventDefault();
|
|
150279
|
+
e.stopPropagation();
|
|
150280
|
+
if (item.dataset.enabled !== "true") return;
|
|
150281
|
+
this.hideTerminalContextMenu();
|
|
150282
|
+
onClick();
|
|
150283
|
+
});
|
|
150284
|
+
return item;
|
|
149557
150285
|
};
|
|
149558
|
-
|
|
149559
|
-
|
|
149560
|
-
|
|
149561
|
-
this.applySpriteCardResponsiveStyles();
|
|
149562
|
-
this.updateMobileKeyboardButtonVisibility();
|
|
149563
|
-
this.debouncedRefit();
|
|
149564
|
-
}
|
|
150286
|
+
const copyItem = makeItem("Copy", () => {
|
|
150287
|
+
const selection = this.terminal?.hasSelection() ? this.terminal.getSelection() ?? "" : "";
|
|
150288
|
+
void this.copyToClipboard(selection, "live");
|
|
149565
150289
|
});
|
|
149566
|
-
|
|
149567
|
-
this.
|
|
149568
|
-
}
|
|
150290
|
+
const pasteItem = makeItem("Paste", () => {
|
|
150291
|
+
void this.pasteFromClipboardToTerminal();
|
|
150292
|
+
});
|
|
150293
|
+
menu.appendChild(copyItem);
|
|
150294
|
+
menu.appendChild(pasteItem);
|
|
150295
|
+
document.body.appendChild(menu);
|
|
150296
|
+
this.terminalContextMenu = menu;
|
|
150297
|
+
this.terminalDiv.addEventListener("contextmenu", (event) => {
|
|
150298
|
+
if (!this.isVisible) return;
|
|
150299
|
+
event.preventDefault();
|
|
150300
|
+
const vw = window.innerWidth;
|
|
150301
|
+
const vh = window.innerHeight;
|
|
150302
|
+
menu.style.display = "block";
|
|
150303
|
+
const rect = menu.getBoundingClientRect();
|
|
150304
|
+
const left = Math.min(event.clientX, vw - rect.width - 4);
|
|
150305
|
+
const top = Math.min(event.clientY, vh - rect.height - 4);
|
|
150306
|
+
menu.style.left = `${Math.max(0, left)}px`;
|
|
150307
|
+
menu.style.top = `${Math.max(0, top)}px`;
|
|
150308
|
+
});
|
|
150309
|
+
this.terminalContextMenuDismiss = (e) => {
|
|
150310
|
+
if (!this.terminalContextMenu || this.terminalContextMenu.style.display === "none") return;
|
|
150311
|
+
if (e instanceof KeyboardEvent && e.key !== "Escape") return;
|
|
150312
|
+
this.hideTerminalContextMenu();
|
|
150313
|
+
};
|
|
150314
|
+
document.addEventListener("mousedown", this.terminalContextMenuDismiss, true);
|
|
150315
|
+
document.addEventListener("keydown", this.terminalContextMenuDismiss, true);
|
|
150316
|
+
}
|
|
150317
|
+
hideTerminalContextMenu() {
|
|
150318
|
+
if (this.terminalContextMenu) this.terminalContextMenu.style.display = "none";
|
|
149569
150319
|
}
|
|
149570
150320
|
/** Toggle between half-width and full-width terminal panel. */
|
|
149571
150321
|
toggleFullWidth() {
|
|
@@ -149666,15 +150416,12 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149666
150416
|
}
|
|
149667
150417
|
/** Give keyboard focus to the terminal. Safe to call when already focused. */
|
|
149668
150418
|
focusTerminal() {
|
|
149669
|
-
console.log("[TerminalOverlay] focusTerminal() \u2014 delegating to InputManager");
|
|
149670
150419
|
this.inputManager.switchToTerminal(
|
|
149671
150420
|
"TerminalOverlay.focusTerminal()",
|
|
149672
150421
|
() => this.handleNewSession(),
|
|
149673
150422
|
() => this.toggleFullWidth()
|
|
149674
150423
|
);
|
|
149675
|
-
|
|
149676
|
-
this.terminal?.focus();
|
|
149677
|
-
}
|
|
150424
|
+
this.terminal?.focus();
|
|
149678
150425
|
this.inputManager.focusTerminalXterm(this.terminal);
|
|
149679
150426
|
if (this.currentAgent) {
|
|
149680
150427
|
this.scene.game.events.emit("npc:highlight", this.currentAgent.id);
|
|
@@ -149689,7 +150436,6 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149689
150436
|
}
|
|
149690
150437
|
/** Give keyboard focus back to the game canvas. Safe to call when already blurred. */
|
|
149691
150438
|
blurTerminal() {
|
|
149692
|
-
console.log("[TerminalOverlay] blurTerminal() \u2014 delegating to InputManager");
|
|
149693
150439
|
const mobileLocked = window.__copilotOfficeMobileModeActive?.() === true;
|
|
149694
150440
|
if (mobileLocked) {
|
|
149695
150441
|
this.inputManager.switchToNone("TerminalOverlay.blurTerminal() mobile lock");
|
|
@@ -149719,7 +150465,12 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149719
150465
|
}
|
|
149720
150466
|
setupKeyboardHandler() {
|
|
149721
150467
|
}
|
|
150468
|
+
// Spec 008-smoke: expose state for the e2e debug hook.
|
|
150469
|
+
getActiveAgentId() {
|
|
150470
|
+
return this.currentAgentId;
|
|
150471
|
+
}
|
|
149722
150472
|
hide() {
|
|
150473
|
+
this.hideTerminalContextMenu();
|
|
149723
150474
|
if (this.container) {
|
|
149724
150475
|
this.container.style.display = "none";
|
|
149725
150476
|
}
|
|
@@ -149730,8 +150481,6 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149730
150481
|
this.isVisible = false;
|
|
149731
150482
|
this.isReadOnly = false;
|
|
149732
150483
|
this.pendingInputLine = "";
|
|
149733
|
-
this.awaitingSessionIdRefresh = false;
|
|
149734
|
-
this.clearSessionRefreshTimers();
|
|
149735
150484
|
this.closeHistoryPopover();
|
|
149736
150485
|
this.restorePanelLayout();
|
|
149737
150486
|
this.inputManager.deactivateTerminalF10();
|
|
@@ -149770,9 +150519,26 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149770
150519
|
return false;
|
|
149771
150520
|
}
|
|
149772
150521
|
destroy() {
|
|
150522
|
+
this.hideTerminalContextMenu();
|
|
150523
|
+
if (this.clipboardHandler) {
|
|
150524
|
+
document.removeEventListener("keydown", this.clipboardHandler, true);
|
|
150525
|
+
this.clipboardHandler = null;
|
|
150526
|
+
}
|
|
150527
|
+
if (this.terminalContextMenuDismiss) {
|
|
150528
|
+
document.removeEventListener("mousedown", this.terminalContextMenuDismiss, true);
|
|
150529
|
+
document.removeEventListener("keydown", this.terminalContextMenuDismiss, true);
|
|
150530
|
+
this.terminalContextMenuDismiss = null;
|
|
150531
|
+
}
|
|
150532
|
+
if (this.terminalContextMenu && this.terminalContextMenu.parentNode) {
|
|
150533
|
+
try {
|
|
150534
|
+
this.terminalContextMenu.parentNode.removeChild(this.terminalContextMenu);
|
|
150535
|
+
} catch {
|
|
150536
|
+
}
|
|
150537
|
+
}
|
|
150538
|
+
this.terminalContextMenu = null;
|
|
150539
|
+
this.onDataDisposable?.dispose();
|
|
150540
|
+
this.onDataDisposable = null;
|
|
149773
150541
|
this.clearRefitTimers();
|
|
149774
|
-
this.awaitingSessionIdRefresh = false;
|
|
149775
|
-
this.clearSessionRefreshTimers();
|
|
149776
150542
|
if (this.resizeHandler) {
|
|
149777
150543
|
window.removeEventListener("resize", this.resizeHandler);
|
|
149778
150544
|
this.resizeHandler = null;
|
|
@@ -149785,11 +150551,23 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
149785
150551
|
this.terminal.dispose();
|
|
149786
150552
|
}
|
|
149787
150553
|
if (this.container && this.container.parentNode) {
|
|
149788
|
-
|
|
150554
|
+
try {
|
|
150555
|
+
this.container.parentNode.removeChild(this.container);
|
|
150556
|
+
} catch {
|
|
150557
|
+
}
|
|
150558
|
+
}
|
|
150559
|
+
try {
|
|
150560
|
+
if (this.spriteCardElement && this.spriteCardElement.parentNode) {
|
|
150561
|
+
this.spriteCardElement.parentNode.removeChild(this.spriteCardElement);
|
|
150562
|
+
}
|
|
150563
|
+
} catch {
|
|
149789
150564
|
}
|
|
149790
|
-
|
|
149791
|
-
|
|
150565
|
+
try {
|
|
150566
|
+
const fallback = document.getElementById("sprite-card");
|
|
150567
|
+
if (fallback) fallback.remove();
|
|
150568
|
+
} catch {
|
|
149792
150569
|
}
|
|
150570
|
+
this.spriteCardElement = null;
|
|
149793
150571
|
if (window.copilotBridge) {
|
|
149794
150572
|
window.copilotBridge.removeTerminalListeners();
|
|
149795
150573
|
}
|
|
@@ -150934,6 +151712,16 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
150934
151712
|
const meta = cachedSessionMeta[agent.id];
|
|
150935
151713
|
const hasSession = liveStatus?.state === "active";
|
|
150936
151714
|
const metaTitle = meta?.title || "";
|
|
151715
|
+
const metaSessionId = meta?.sessionId || "";
|
|
151716
|
+
const sessionIdBadgeHtml = metaSessionId ? `<div class="session-id-badge" data-agent="${agent.id}" data-session-id="${metaSessionId}" title="Click to copy: ${metaSessionId}" style="
|
|
151717
|
+
display: inline-block; align-self: flex-start;
|
|
151718
|
+
font-family: ui-monospace, Menlo, Consolas, monospace;
|
|
151719
|
+
font-size: 10px; color: #8ec3ff;
|
|
151720
|
+
background: #1a2030; border: 1px solid #2a3550;
|
|
151721
|
+
padding: 1px 6px; border-radius: 3px;
|
|
151722
|
+
cursor: pointer; user-select: text;
|
|
151723
|
+
max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
151724
|
+
">${metaSessionId}</div>` : "";
|
|
150937
151725
|
const sessionPanelHtml = hasSession ? `
|
|
150938
151726
|
<div class="session-meta-panel" data-agent="${agent.id}" style="
|
|
150939
151727
|
flex: 2; min-width: 0;
|
|
@@ -150950,6 +151738,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
150950
151738
|
overflow: hidden; text-overflow: ellipsis;
|
|
150951
151739
|
display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
|
|
150952
151740
|
" title="${metaTitle ? metaTitle.replace(/"/g, """) : "Click to set title"}">${metaTitle || "Untitled session"}</div>
|
|
151741
|
+
${sessionIdBadgeHtml}
|
|
150953
151742
|
<button class="session-new-btn" data-agent="${agent.id}" style="
|
|
150954
151743
|
margin-top: 2px;
|
|
150955
151744
|
align-self: flex-start;
|
|
@@ -150957,6 +151746,12 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
150957
151746
|
font-size: ${t.sessionButton}; padding: 4px 10px; border-radius: 4px;
|
|
150958
151747
|
cursor: pointer; transition: background 0.15s, border-color 0.15s;
|
|
150959
151748
|
" title="Start a new session for this agent">\u{1F504} New Session</button>
|
|
151749
|
+
<button class="session-close-btn" data-agent="${agent.id}" style="
|
|
151750
|
+
align-self: flex-start;
|
|
151751
|
+
background: #3a2a2a; border: 1px solid #6a4a4a; color: #f7a9a9;
|
|
151752
|
+
font-size: ${t.sessionButton}; padding: 4px 10px; border-radius: 4px;
|
|
151753
|
+
cursor: pointer; transition: background 0.15s, border-color 0.15s;
|
|
151754
|
+
" title="Close this agent's session (agent returns to slacking)">\u2716 Close Session</button>
|
|
150960
151755
|
<div style="display: flex; justify-content: flex-end;">
|
|
150961
151756
|
<button class="session-edit-btn" data-agent="${agent.id}" style="
|
|
150962
151757
|
background: none; border: 1px solid #333; color: #667;
|
|
@@ -151075,6 +151870,10 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
151075
151870
|
context.emitOpenTerminal(agentId);
|
|
151076
151871
|
},
|
|
151077
151872
|
handleMetaPanelClick(target, agentId, context) {
|
|
151873
|
+
if (target.closest(".session-close-btn")) {
|
|
151874
|
+
context.closeSession(agentId);
|
|
151875
|
+
return;
|
|
151876
|
+
}
|
|
151078
151877
|
if (target.closest(".session-new-btn")) {
|
|
151079
151878
|
context.startNewSession(agentId);
|
|
151080
151879
|
return;
|
|
@@ -151093,6 +151892,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
151093
151892
|
"src/layouts/fleet/FleetDashboard.ts"() {
|
|
151094
151893
|
"use strict";
|
|
151095
151894
|
init_types();
|
|
151895
|
+
init_agents();
|
|
151096
151896
|
fleetDashboard = {
|
|
151097
151897
|
renderCards(ctx) {
|
|
151098
151898
|
const { agents, office, selectedAgentId, formatElapsed, formatRelativeTime } = ctx;
|
|
@@ -151142,7 +151942,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
151142
151942
|
}
|
|
151143
151943
|
const colorHex = "#" + agent.color.toString(16).padStart(6, "0");
|
|
151144
151944
|
const isSelected = agent.id === selectedAgentId;
|
|
151145
|
-
const isArthur = agent.id ===
|
|
151945
|
+
const isArthur = agent.id === ARCHITECT_AGENT_ID;
|
|
151146
151946
|
const borderColor = isSelected ? "#4a5a7a" : "#252540";
|
|
151147
151947
|
const bgColor = isSelected ? "#1a1e2e" : "#13131f";
|
|
151148
151948
|
const cursor = isArthur ? "pointer" : "default";
|
|
@@ -151245,9 +152045,10 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
151245
152045
|
var init_FleetClickHandler = __esm({
|
|
151246
152046
|
"src/layouts/fleet/FleetClickHandler.ts"() {
|
|
151247
152047
|
"use strict";
|
|
152048
|
+
init_agents();
|
|
151248
152049
|
fleetClickHandler = {
|
|
151249
152050
|
handleCardClick(agentId, context) {
|
|
151250
|
-
if (agentId ===
|
|
152051
|
+
if (agentId === ARCHITECT_AGENT_ID) {
|
|
151251
152052
|
context.setSelectedAgent(agentId);
|
|
151252
152053
|
context.emitOpenTerminal(agentId);
|
|
151253
152054
|
return;
|
|
@@ -151263,7 +152064,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
151263
152064
|
function getLayout(layout) {
|
|
151264
152065
|
return layouts[layout] ?? layouts["default"];
|
|
151265
152066
|
}
|
|
151266
|
-
var layouts;
|
|
152067
|
+
var defaultBehaviors, fleetBehaviors, layouts;
|
|
151267
152068
|
var init_layouts = __esm({
|
|
151268
152069
|
"src/layouts/index.ts"() {
|
|
151269
152070
|
"use strict";
|
|
@@ -151272,16 +152073,30 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
151272
152073
|
init_DefaultClickHandler();
|
|
151273
152074
|
init_FleetDashboard();
|
|
151274
152075
|
init_FleetClickHandler();
|
|
152076
|
+
defaultBehaviors = {
|
|
152077
|
+
supportsReserveAgents: true,
|
|
152078
|
+
restrictsInteractionToArchitect: false,
|
|
152079
|
+
hasPlayerPcTerminal: true,
|
|
152080
|
+
supportsFleetExecution: false
|
|
152081
|
+
};
|
|
152082
|
+
fleetBehaviors = {
|
|
152083
|
+
supportsReserveAgents: false,
|
|
152084
|
+
restrictsInteractionToArchitect: true,
|
|
152085
|
+
hasPlayerPcTerminal: false,
|
|
152086
|
+
supportsFleetExecution: true
|
|
152087
|
+
};
|
|
151275
152088
|
layouts = {
|
|
151276
152089
|
"default": {
|
|
151277
152090
|
agents: AGENTS,
|
|
151278
152091
|
dashboard: defaultDashboard,
|
|
151279
|
-
clickHandler: defaultClickHandler
|
|
152092
|
+
clickHandler: defaultClickHandler,
|
|
152093
|
+
behaviors: defaultBehaviors
|
|
151280
152094
|
},
|
|
151281
152095
|
"fleet-vteam": {
|
|
151282
152096
|
agents: FLEET_AGENTS,
|
|
151283
152097
|
dashboard: fleetDashboard,
|
|
151284
|
-
clickHandler: fleetClickHandler
|
|
152098
|
+
clickHandler: fleetClickHandler,
|
|
152099
|
+
behaviors: fleetBehaviors
|
|
151285
152100
|
}
|
|
151286
152101
|
};
|
|
151287
152102
|
}
|
|
@@ -151625,30 +152440,27 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
151625
152440
|
this.terminal.deactivateF10();
|
|
151626
152441
|
}
|
|
151627
152442
|
/**
|
|
151628
|
-
* Focus the xterm Terminal instance
|
|
151629
|
-
*
|
|
151630
|
-
*
|
|
152443
|
+
* Focus the xterm Terminal instance. Calls focus() synchronously for
|
|
152444
|
+
* immediate keyboard capture, then verifies after a short delay and retries
|
|
152445
|
+
* if the DOM wasn't ready (e.g. display transition still in flight).
|
|
151631
152446
|
*/
|
|
151632
152447
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
151633
152448
|
focusTerminalXterm(terminal) {
|
|
151634
|
-
|
|
151635
|
-
const
|
|
152449
|
+
terminal?.focus();
|
|
152450
|
+
const verify = (n, delay) => {
|
|
151636
152451
|
setTimeout(() => {
|
|
151637
|
-
terminal?.focus();
|
|
151638
|
-
console.log(`[InputManager] focusTerminalXterm() attempt ${n} executed | time: ${Date.now()}`);
|
|
151639
152452
|
const textarea = terminal?.textarea;
|
|
151640
|
-
if (textarea && document.activeElement !== textarea
|
|
151641
|
-
|
|
151642
|
-
|
|
152453
|
+
if (textarea && document.activeElement !== textarea) {
|
|
152454
|
+
terminal?.focus();
|
|
152455
|
+
if (n < 3) verify(n + 1, delay * 2);
|
|
151643
152456
|
}
|
|
151644
152457
|
}, delay);
|
|
151645
152458
|
};
|
|
151646
|
-
|
|
152459
|
+
verify(1, 50);
|
|
151647
152460
|
}
|
|
151648
152461
|
/** Blur the xterm Terminal instance (return DOM focus away from xterm). */
|
|
151649
152462
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
151650
152463
|
blurTerminalXterm(terminal) {
|
|
151651
|
-
console.log(`[InputManager] blurTerminalXterm() | time: ${Date.now()}`);
|
|
151652
152464
|
terminal?.blur();
|
|
151653
152465
|
}
|
|
151654
152466
|
/** Enable or disable verbose per-keydown logging in GlobalInputListener. */
|
|
@@ -152308,11 +153120,72 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
152308
153120
|
}
|
|
152309
153121
|
});
|
|
152310
153122
|
|
|
153123
|
+
// src/config/agentAutoStart.ts
|
|
153124
|
+
function clone() {
|
|
153125
|
+
return { ...DEFAULT_AGENT_AUTO_START_SETTINGS };
|
|
153126
|
+
}
|
|
153127
|
+
function readStorage() {
|
|
153128
|
+
try {
|
|
153129
|
+
if (typeof localStorage !== "undefined") return localStorage;
|
|
153130
|
+
} catch {
|
|
153131
|
+
}
|
|
153132
|
+
return null;
|
|
153133
|
+
}
|
|
153134
|
+
function getAgentAutoStartSettings() {
|
|
153135
|
+
const storage = readStorage();
|
|
153136
|
+
if (!storage) return clone();
|
|
153137
|
+
let raw;
|
|
153138
|
+
try {
|
|
153139
|
+
raw = storage.getItem(STORAGE_KEY2);
|
|
153140
|
+
} catch {
|
|
153141
|
+
return clone();
|
|
153142
|
+
}
|
|
153143
|
+
if (raw === null || raw === void 0) return clone();
|
|
153144
|
+
let parsed;
|
|
153145
|
+
try {
|
|
153146
|
+
parsed = JSON.parse(raw);
|
|
153147
|
+
} catch {
|
|
153148
|
+
try {
|
|
153149
|
+
storage.removeItem(STORAGE_KEY2);
|
|
153150
|
+
} catch {
|
|
153151
|
+
}
|
|
153152
|
+
return clone();
|
|
153153
|
+
}
|
|
153154
|
+
if (!parsed || typeof parsed !== "object") return clone();
|
|
153155
|
+
const candidate = parsed.autoStartKnownAgents;
|
|
153156
|
+
if (typeof candidate !== "boolean") return clone();
|
|
153157
|
+
return { autoStartKnownAgents: candidate };
|
|
153158
|
+
}
|
|
153159
|
+
function setAgentAutoStartSettings(next) {
|
|
153160
|
+
const storage = readStorage();
|
|
153161
|
+
if (!storage) return;
|
|
153162
|
+
try {
|
|
153163
|
+
storage.setItem(
|
|
153164
|
+
STORAGE_KEY2,
|
|
153165
|
+
JSON.stringify({ autoStartKnownAgents: !!next.autoStartKnownAgents })
|
|
153166
|
+
);
|
|
153167
|
+
} catch {
|
|
153168
|
+
}
|
|
153169
|
+
}
|
|
153170
|
+
function shouldAutoStart() {
|
|
153171
|
+
return getAgentAutoStartSettings().autoStartKnownAgents === true;
|
|
153172
|
+
}
|
|
153173
|
+
var DEFAULT_AGENT_AUTO_START_SETTINGS, STORAGE_KEY2;
|
|
153174
|
+
var init_agentAutoStart = __esm({
|
|
153175
|
+
"src/config/agentAutoStart.ts"() {
|
|
153176
|
+
"use strict";
|
|
153177
|
+
DEFAULT_AGENT_AUTO_START_SETTINGS = {
|
|
153178
|
+
autoStartKnownAgents: true
|
|
153179
|
+
};
|
|
153180
|
+
STORAGE_KEY2 = "copilot-office-agent-auto-start";
|
|
153181
|
+
}
|
|
153182
|
+
});
|
|
153183
|
+
|
|
152311
153184
|
// src/scenes/OfficeScene.ts
|
|
152312
153185
|
function debugLog(scene, ...args) {
|
|
152313
153186
|
if (scene.physics.world.drawDebug) console.log("[Debug]", ...args);
|
|
152314
153187
|
}
|
|
152315
|
-
var import_phaser8, ENABLE_DECORATIONS, ENABLE_BASKETBALL, ENABLE_GALAXIAN, ENABLE_ZOOM_BAR, PC_TERMINAL_ID, OfficeScene;
|
|
153188
|
+
var import_phaser8, DEBUG_COLD_START2, ENABLE_DECORATIONS, ENABLE_BASKETBALL, ENABLE_GALAXIAN, ENABLE_ZOOM_BAR, PC_TERMINAL_ID, OfficeScene;
|
|
152316
153189
|
var init_OfficeScene = __esm({
|
|
152317
153190
|
"src/scenes/OfficeScene.ts"() {
|
|
152318
153191
|
"use strict";
|
|
@@ -152325,12 +153198,15 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
152325
153198
|
init_agents();
|
|
152326
153199
|
init_layouts();
|
|
152327
153200
|
init_depths();
|
|
153201
|
+
init_zIndex();
|
|
152328
153202
|
init_InputManager();
|
|
152329
153203
|
init_officeManager();
|
|
152330
153204
|
init_fleetTracker();
|
|
152331
153205
|
init_fleetVisualizer();
|
|
152332
153206
|
init_DirectionalSprite();
|
|
152333
153207
|
init_CameraDragController();
|
|
153208
|
+
init_agentAutoStart();
|
|
153209
|
+
DEBUG_COLD_START2 = typeof window !== "undefined" && window.__COPILOT_OFFICE_DEBUG_COLD_START__ === true || false;
|
|
152334
153210
|
ENABLE_DECORATIONS = false;
|
|
152335
153211
|
ENABLE_BASKETBALL = false;
|
|
152336
153212
|
ENABLE_GALAXIAN = true;
|
|
@@ -152371,6 +153247,10 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
152371
153247
|
this.skipButton = null;
|
|
152372
153248
|
this.isPortraitDashboardMode = false;
|
|
152373
153249
|
}
|
|
153250
|
+
// Spec 008-smoke: accessor for the e2e debug hook in src/main.ts.
|
|
153251
|
+
getTerminalOverlay() {
|
|
153252
|
+
return this.terminalOverlay;
|
|
153253
|
+
}
|
|
152374
153254
|
setAnimating(value) {
|
|
152375
153255
|
this.animating = value;
|
|
152376
153256
|
this.game.registry.set("animating", value);
|
|
@@ -152456,13 +153336,13 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
152456
153336
|
} else {
|
|
152457
153337
|
this.triggerEntrance();
|
|
152458
153338
|
}
|
|
152459
|
-
const arthurNPC = this.npcs.find((n) => n.config.id ===
|
|
153339
|
+
const arthurNPC = this.npcs.find((n) => n.config.id === ARCHITECT_AGENT_ID);
|
|
152460
153340
|
if (arthurNPC) {
|
|
152461
153341
|
arthurNPC.updateAgentStatus(void 0);
|
|
152462
153342
|
}
|
|
152463
153343
|
const seatedNpcs = [];
|
|
152464
153344
|
for (const agent of AGENTS) {
|
|
152465
|
-
if (agent.id ===
|
|
153345
|
+
if (agent.id === ARCHITECT_AGENT_ID) continue;
|
|
152466
153346
|
const npc = this.npcs.find((n) => n.config.id === agent.id);
|
|
152467
153347
|
if (!npc) continue;
|
|
152468
153348
|
const deskX = npc.config.position.x * this.tileSize + this.tileSize / 2;
|
|
@@ -152476,7 +153356,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
152476
153356
|
const showAllBadges = () => {
|
|
152477
153357
|
seatedNpcs.forEach((n) => n.setBadgeVisible(true));
|
|
152478
153358
|
};
|
|
152479
|
-
this.triggerAgentWalkIn([
|
|
153359
|
+
this.triggerAgentWalkIn([ARCHITECT_AGENT_ID], showAllBadges);
|
|
152480
153360
|
}
|
|
152481
153361
|
});
|
|
152482
153362
|
this.basketballGame = new BasketballGame(this);
|
|
@@ -152577,7 +153457,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
152577
153457
|
this.openPlayerPcTerminal();
|
|
152578
153458
|
return;
|
|
152579
153459
|
}
|
|
152580
|
-
if (this.currentLayout
|
|
153460
|
+
if (getLayout(this.currentLayout).behaviors.restrictsInteractionToArchitect && agentId !== ARCHITECT_AGENT_ID) return;
|
|
152581
153461
|
const agents = getLayout(this.currentLayout).agents;
|
|
152582
153462
|
const agent = agents.find((a) => a.id === agentId);
|
|
152583
153463
|
if (agent) this.startConversation(agent);
|
|
@@ -152772,6 +153652,14 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
152772
153652
|
this.game.events.off("zoom:change");
|
|
152773
153653
|
this.cameraDrag?.destroy();
|
|
152774
153654
|
this.inputManager.destroy();
|
|
153655
|
+
if (DEBUG_SPRITE_SERIOUS) {
|
|
153656
|
+
console.log("[OfficeScene] shutdown destroying terminalOverlay");
|
|
153657
|
+
}
|
|
153658
|
+
try {
|
|
153659
|
+
this.terminalOverlay?.destroy();
|
|
153660
|
+
} catch (e) {
|
|
153661
|
+
console.warn("[OfficeScene] shutdown overlay destroy failed", e);
|
|
153662
|
+
}
|
|
152775
153663
|
}, this);
|
|
152776
153664
|
}
|
|
152777
153665
|
startBackgroundMusic() {
|
|
@@ -153667,7 +154555,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
153667
154555
|
font-family: 'Cascadia Code', Consolas, monospace;
|
|
153668
154556
|
font-size: 16px;
|
|
153669
154557
|
font-weight: bold;
|
|
153670
|
-
z-index:
|
|
154558
|
+
z-index: ${ZIndex.OFFICE_SCENE_OVERLAY};
|
|
153671
154559
|
transition: background 0.15s;
|
|
153672
154560
|
`;
|
|
153673
154561
|
btn.addEventListener("mouseenter", () => {
|
|
@@ -153793,7 +154681,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
153793
154681
|
const isReEntry = !this.fleetPrompt;
|
|
153794
154682
|
console.log(`[OfficeScene] initFleetPipeline: attachOfficeId=${attachOfficeId}, sourceOfficeId=${this.fleetSourceOfficeId}, currentOfficeId=${officeManager.currentOfficeId}, isReEntry=${isReEntry}`);
|
|
153795
154683
|
try {
|
|
153796
|
-
this.fleetTracker = new FleetTracker(
|
|
154684
|
+
this.fleetTracker = new FleetTracker(ARCHITECT_AGENT_ID, attachOfficeId);
|
|
153797
154685
|
await this.fleetTracker.startTracking();
|
|
153798
154686
|
this.fleetVisualizer = new FleetVisualizer(
|
|
153799
154687
|
this.fleetTracker,
|
|
@@ -153806,8 +154694,8 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
153806
154694
|
const fleetOfficeId = officeManager.currentOfficeId;
|
|
153807
154695
|
if (fleetOfficeId && window.copilotBridge?.terminalWrite) {
|
|
153808
154696
|
const fleetCmd = `/fleet ${this.fleetPrompt}\r`;
|
|
153809
|
-
console.log(`[OfficeScene] Sending /fleet to ${fleetOfficeId}
|
|
153810
|
-
const result = await window.copilotBridge.terminalWrite(fleetOfficeId,
|
|
154697
|
+
console.log(`[OfficeScene] Sending /fleet to ${fleetOfficeId}:${ARCHITECT_AGENT_ID} (${fleetCmd.length} chars)`);
|
|
154698
|
+
const result = await window.copilotBridge.terminalWrite(fleetOfficeId, ARCHITECT_AGENT_ID, fleetCmd);
|
|
153811
154699
|
console.log(`[OfficeScene] /fleet command result:`, result);
|
|
153812
154700
|
} else {
|
|
153813
154701
|
console.warn("[OfficeScene] Cannot send /fleet \u2014 no officeId or copilotBridge");
|
|
@@ -153857,23 +154745,49 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
153857
154745
|
});
|
|
153858
154746
|
}
|
|
153859
154747
|
async preStartAgentSessions() {
|
|
154748
|
+
if (!shouldAutoStart()) {
|
|
154749
|
+
if (DEBUG_COLD_START2) {
|
|
154750
|
+
console.log("[OfficeScene] preStart skipped (autoStartKnownAgents=false)");
|
|
154751
|
+
}
|
|
154752
|
+
return;
|
|
154753
|
+
}
|
|
153860
154754
|
if (typeof window !== "undefined" && window.copilotBridge) {
|
|
153861
154755
|
const oid = officeManager.currentOfficeId || "office-0";
|
|
153862
|
-
const startAgent = async (
|
|
153863
|
-
const
|
|
153864
|
-
const savedSessionId = await window.copilotBridge.getSessionId(oid,
|
|
154756
|
+
const startAgent = async (agentConfig, label) => {
|
|
154757
|
+
const startedAt = Date.now();
|
|
154758
|
+
const savedSessionId = await window.copilotBridge.getSessionId(oid, agentConfig.id);
|
|
153865
154759
|
if (savedSessionId) {
|
|
153866
154760
|
console.log(`[CopilotOffice] Resuming ${label} session: ${savedSessionId}`);
|
|
153867
154761
|
} else {
|
|
153868
154762
|
console.log(`[CopilotOffice] Starting new ${label} session (no saved session found)`);
|
|
153869
154763
|
}
|
|
153870
|
-
await window.copilotBridge.terminalStart(
|
|
154764
|
+
const result = await window.copilotBridge.terminalStart(
|
|
154765
|
+
oid,
|
|
154766
|
+
agentConfig.id,
|
|
154767
|
+
agentConfig.workingDir || officeManager.getCurrentWorkingDirectory()
|
|
154768
|
+
);
|
|
153871
154769
|
console.log(`[CopilotOffice] ${label} session ready`);
|
|
154770
|
+
if (DEBUG_COLD_START2) {
|
|
154771
|
+
const sessionId = (result && result.sessionId) ?? "unknown";
|
|
154772
|
+
const elapsedMs = Date.now() - startedAt;
|
|
154773
|
+
console.log(
|
|
154774
|
+
`[OfficeScene] preStart agent=${agentConfig.id} sessionId=${sessionId} elapsedMs=${elapsedMs}`
|
|
154775
|
+
);
|
|
154776
|
+
}
|
|
153872
154777
|
};
|
|
153873
|
-
const
|
|
153874
|
-
|
|
153875
|
-
|
|
154778
|
+
const roster = getLayout(this.currentLayout).agents;
|
|
154779
|
+
const agentsToStart = roster.length > 0 ? roster : AGENTS;
|
|
154780
|
+
const results = await Promise.allSettled(
|
|
154781
|
+
agentsToStart.map((a) => startAgent(a, `${a.name} (${a.description})`))
|
|
153876
154782
|
);
|
|
154783
|
+
for (let i = 0; i < results.length; i++) {
|
|
154784
|
+
const r = results[i];
|
|
154785
|
+
if (r.status === "rejected") {
|
|
154786
|
+
console.warn(
|
|
154787
|
+
`[CopilotOffice] preStart failed for ${agentsToStart[i].id}: ${String(r.reason)}`
|
|
154788
|
+
);
|
|
154789
|
+
}
|
|
154790
|
+
}
|
|
153877
154791
|
}
|
|
153878
154792
|
}
|
|
153879
154793
|
update() {
|
|
@@ -153926,7 +154840,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
153926
154840
|
}
|
|
153927
154841
|
}
|
|
153928
154842
|
}
|
|
153929
|
-
if (import_phaser8.default.Input.Keyboard.JustDown(this.dismissKey) && this.currentLayout
|
|
154843
|
+
if (import_phaser8.default.Input.Keyboard.JustDown(this.dismissKey) && getLayout(this.currentLayout).behaviors.supportsReserveAgents) {
|
|
153930
154844
|
const targetNPC = this.nearestNPC ?? (this.nearestDesk ? this.npcs.find((n) => n.config.id === this.nearestDesk.agentId) ?? null : null);
|
|
153931
154845
|
if (targetNPC && !CORE_AGENT_IDS.has(targetNPC.config.id) && RESERVE_AGENT_DESK[targetNPC.config.id]) {
|
|
153932
154846
|
this.dismissReserveAgent(targetNPC);
|
|
@@ -154114,7 +155028,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
154114
155028
|
}
|
|
154115
155029
|
startConversation(agent) {
|
|
154116
155030
|
if (this.currentLayout === "fleet-vteam") {
|
|
154117
|
-
if (agent.id !==
|
|
155031
|
+
if (agent.id !== ARCHITECT_AGENT_ID) return;
|
|
154118
155032
|
this.game.events.emit("agent:interact", agent.id);
|
|
154119
155033
|
this.terminalOverlay.show(
|
|
154120
155034
|
agent,
|
|
@@ -154124,7 +155038,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
154124
155038
|
);
|
|
154125
155039
|
return;
|
|
154126
155040
|
}
|
|
154127
|
-
if (agent.id ===
|
|
155041
|
+
if (agent.id === ARCHITECT_AGENT_ID) {
|
|
154128
155042
|
this.enterMeeting();
|
|
154129
155043
|
return;
|
|
154130
155044
|
}
|
|
@@ -154155,7 +155069,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
154155
155069
|
);
|
|
154156
155070
|
}
|
|
154157
155071
|
openPlayerPcTerminal() {
|
|
154158
|
-
if (this.currentLayout
|
|
155072
|
+
if (!getLayout(this.currentLayout).behaviors.hasPlayerPcTerminal) return;
|
|
154159
155073
|
const workingDir = officeManager.getCurrentWorkingDirectory();
|
|
154160
155074
|
const pcTerminalConfig = {
|
|
154161
155075
|
id: PC_TERMINAL_ID,
|
|
@@ -154479,7 +155393,8 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
154479
155393
|
var init_planParser = __esm({
|
|
154480
155394
|
"src/meeting/planParser.ts"() {
|
|
154481
155395
|
"use strict";
|
|
154482
|
-
|
|
155396
|
+
init_agents();
|
|
155397
|
+
DEFAULT_VALID_AGENT_IDS = DEFAULT_PLAN_AGENT_IDS;
|
|
154483
155398
|
}
|
|
154484
155399
|
});
|
|
154485
155400
|
|
|
@@ -154548,7 +155463,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
154548
155463
|
this.inputManager = new InputManager(this);
|
|
154549
155464
|
this.planApproval = new PlanApprovalOverlay();
|
|
154550
155465
|
this.terminalOverlay = new TerminalOverlay(this, this.inputManager, () => officeManager.currentOfficeId || "office-0");
|
|
154551
|
-
const arthur = AGENTS.find((a) => a.id ===
|
|
155466
|
+
const arthur = AGENTS.find((a) => a.id === ARCHITECT_AGENT_ID);
|
|
154552
155467
|
if (arthur) {
|
|
154553
155468
|
this.terminalOverlay.show(arthur, () => {
|
|
154554
155469
|
console.log("[MeetingScene] Terminal closed");
|
|
@@ -154705,7 +155620,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
154705
155620
|
if (typeof window === "undefined" || !window.copilotBridge) return;
|
|
154706
155621
|
const handler = (_agentId, data) => {
|
|
154707
155622
|
if (this.isExiting) return;
|
|
154708
|
-
if (_agentId !==
|
|
155623
|
+
if (_agentId !== ARCHITECT_AGENT_ID) return;
|
|
154709
155624
|
this.terminalOutputBuffer += data;
|
|
154710
155625
|
this.time.delayedCall(500, () => {
|
|
154711
155626
|
if (this.isExiting) return;
|
|
@@ -154731,7 +155646,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
154731
155646
|
onRevise: (feedback) => {
|
|
154732
155647
|
console.log("[MeetingScene] Revision requested:", feedback);
|
|
154733
155648
|
if (window.copilotBridge) {
|
|
154734
|
-
window.copilotBridge.terminalWrite(officeManager.currentOfficeId || "office-0",
|
|
155649
|
+
window.copilotBridge.terminalWrite(officeManager.currentOfficeId || "office-0", ARCHITECT_AGENT_ID, feedback + "\r");
|
|
154735
155650
|
}
|
|
154736
155651
|
this.meetingPlan = null;
|
|
154737
155652
|
this.terminalOutputBuffer = "";
|
|
@@ -154844,6 +155759,14 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
154844
155759
|
this.terminalOverlay?.hide();
|
|
154845
155760
|
}
|
|
154846
155761
|
this.inputManager?.destroy();
|
|
155762
|
+
if (DEBUG_SPRITE_SERIOUS) {
|
|
155763
|
+
console.log("[MeetingScene] shutdown destroying terminalOverlay");
|
|
155764
|
+
}
|
|
155765
|
+
try {
|
|
155766
|
+
this.terminalOverlay?.destroy();
|
|
155767
|
+
} catch (e) {
|
|
155768
|
+
console.warn("[MeetingScene] shutdown overlay destroy failed", e);
|
|
155769
|
+
}
|
|
154847
155770
|
this.meetingPlan = null;
|
|
154848
155771
|
this.terminalOutputBuffer = "";
|
|
154849
155772
|
this.isExiting = false;
|
|
@@ -154874,6 +155797,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
154874
155797
|
var init_ToastNotification = __esm({
|
|
154875
155798
|
"src/ui/ToastNotification.ts"() {
|
|
154876
155799
|
"use strict";
|
|
155800
|
+
init_zIndex();
|
|
154877
155801
|
MAX_VISIBLE = 3;
|
|
154878
155802
|
AUTO_DISMISS_MS = 5e3;
|
|
154879
155803
|
ANIMATION_MS = 300;
|
|
@@ -154890,7 +155814,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
154890
155814
|
top: 80px;
|
|
154891
155815
|
left: 16px;
|
|
154892
155816
|
width: calc(50% - 32px);
|
|
154893
|
-
z-index:
|
|
155817
|
+
z-index: ${ZIndex.TOAST};
|
|
154894
155818
|
pointer-events: none;
|
|
154895
155819
|
display: flex;
|
|
154896
155820
|
flex-direction: column;
|
|
@@ -154987,7 +155911,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
154987
155911
|
// src/config/notifications.ts
|
|
154988
155912
|
function loadNotificationSettings() {
|
|
154989
155913
|
try {
|
|
154990
|
-
const raw = localStorage.getItem(
|
|
155914
|
+
const raw = localStorage.getItem(STORAGE_KEY3);
|
|
154991
155915
|
if (!raw) return structuredClone(DEFAULT_SETTINGS);
|
|
154992
155916
|
const parsed = JSON.parse(raw);
|
|
154993
155917
|
const merged = structuredClone(DEFAULT_SETTINGS);
|
|
@@ -155007,13 +155931,13 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155007
155931
|
}
|
|
155008
155932
|
}
|
|
155009
155933
|
function saveNotificationSettings(settings) {
|
|
155010
|
-
localStorage.setItem(
|
|
155934
|
+
localStorage.setItem(STORAGE_KEY3, JSON.stringify(settings));
|
|
155011
155935
|
}
|
|
155012
155936
|
function resetNotificationSettings() {
|
|
155013
|
-
localStorage.removeItem(
|
|
155937
|
+
localStorage.removeItem(STORAGE_KEY3);
|
|
155014
155938
|
return structuredClone(DEFAULT_SETTINGS);
|
|
155015
155939
|
}
|
|
155016
|
-
var NOTIFICATION_EVENT_LABELS, DEFAULT_SETTINGS,
|
|
155940
|
+
var NOTIFICATION_EVENT_LABELS, DEFAULT_SETTINGS, STORAGE_KEY3;
|
|
155017
155941
|
var init_notifications = __esm({
|
|
155018
155942
|
"src/config/notifications.ts"() {
|
|
155019
155943
|
"use strict";
|
|
@@ -155073,7 +155997,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155073
155997
|
}
|
|
155074
155998
|
}
|
|
155075
155999
|
};
|
|
155076
|
-
|
|
156000
|
+
STORAGE_KEY3 = "copilot-notification-settings";
|
|
155077
156001
|
}
|
|
155078
156002
|
});
|
|
155079
156003
|
|
|
@@ -155174,6 +156098,8 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155174
156098
|
"src/ui/SettingsPanel.ts"() {
|
|
155175
156099
|
"use strict";
|
|
155176
156100
|
init_notifications();
|
|
156101
|
+
init_agentAutoStart();
|
|
156102
|
+
init_zIndex();
|
|
155177
156103
|
ALL_EVENT_TYPES = [
|
|
155178
156104
|
"turnEnd",
|
|
155179
156105
|
"askUser",
|
|
@@ -155207,7 +156133,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155207
156133
|
position: fixed;
|
|
155208
156134
|
inset: 0;
|
|
155209
156135
|
background: rgba(0,0,0,0.6);
|
|
155210
|
-
z-index:
|
|
156136
|
+
z-index: ${ZIndex.SETTINGS};
|
|
155211
156137
|
display: flex;
|
|
155212
156138
|
align-items: center;
|
|
155213
156139
|
justify-content: center;
|
|
@@ -155258,8 +156184,31 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155258
156184
|
</div>
|
|
155259
156185
|
|
|
155260
156186
|
${this.renderAudioSection()}
|
|
156187
|
+
${this.renderAgentsSection()}
|
|
155261
156188
|
${this.renderNotificationsSection()}
|
|
155262
156189
|
${this.renderAboutSection()}
|
|
156190
|
+
`;
|
|
156191
|
+
}
|
|
156192
|
+
renderAgentsSection() {
|
|
156193
|
+
const settings = getAgentAutoStartSettings();
|
|
156194
|
+
return `
|
|
156195
|
+
<div class="settings-section" style="margin-bottom: 20px;">
|
|
156196
|
+
<h3 style="margin: 0 0 12px; font-size: 14px; color: #889; border-bottom: 1px solid #2a2a3e; padding-bottom: 8px;">
|
|
156197
|
+
\u{1F916} Agents
|
|
156198
|
+
</h3>
|
|
156199
|
+
<label style="display: flex; align-items: center; gap: 10px; padding: 8px 0; cursor: pointer;">
|
|
156200
|
+
<input
|
|
156201
|
+
type="checkbox"
|
|
156202
|
+
id="settings-agent-auto-start"
|
|
156203
|
+
${settings.autoStartKnownAgents ? "checked" : ""}
|
|
156204
|
+
style="cursor: pointer; width: 15px; height: 15px;"
|
|
156205
|
+
/>
|
|
156206
|
+
<span style="color: #aab; font-size: 13px;">Auto-start known agents</span>
|
|
156207
|
+
</label>
|
|
156208
|
+
<p style="margin: 4px 0 0 25px; font-size: 10px; color: #556;">
|
|
156209
|
+
When ON, agents with a saved session resume automatically on launch, office switch, and New Session.
|
|
156210
|
+
</p>
|
|
156211
|
+
</div>
|
|
155263
156212
|
`;
|
|
155264
156213
|
}
|
|
155265
156214
|
renderAudioSection() {
|
|
@@ -155408,8 +156357,16 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155408
156357
|
bindEvents(panel) {
|
|
155409
156358
|
panel.querySelector("#settings-close-btn")?.addEventListener("click", () => this.close());
|
|
155410
156359
|
this.bindAudioEvents(panel);
|
|
156360
|
+
this.bindAgentsEvents(panel);
|
|
155411
156361
|
this.bindNotificationEvents(panel);
|
|
155412
156362
|
}
|
|
156363
|
+
bindAgentsEvents(panel) {
|
|
156364
|
+
const cb = panel.querySelector("#settings-agent-auto-start");
|
|
156365
|
+
if (!cb) return;
|
|
156366
|
+
cb.addEventListener("change", () => {
|
|
156367
|
+
setAgentAutoStartSettings({ autoStartKnownAgents: cb.checked });
|
|
156368
|
+
});
|
|
156369
|
+
}
|
|
155413
156370
|
bindAudioEvents(panel) {
|
|
155414
156371
|
const muteBtn = panel.querySelector("#settings-bgm-mute-btn");
|
|
155415
156372
|
const slider = panel.querySelector("#settings-bgm-slider");
|
|
@@ -155448,7 +156405,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155448
156405
|
settings.events[eventType].enabled = checkbox.checked;
|
|
155449
156406
|
});
|
|
155450
156407
|
});
|
|
155451
|
-
panel.querySelectorAll('input[type="checkbox"]:not([data-field="enabled"])').forEach((checkbox) => {
|
|
156408
|
+
panel.querySelectorAll('input[type="checkbox"][data-event]:not([data-field="enabled"])').forEach((checkbox) => {
|
|
155452
156409
|
checkbox.addEventListener("change", () => {
|
|
155453
156410
|
const eventType = checkbox.dataset.event;
|
|
155454
156411
|
const field = checkbox.dataset.field;
|
|
@@ -155503,6 +156460,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155503
156460
|
"src/ui/SpriteCustomizerPanel.ts"() {
|
|
155504
156461
|
"use strict";
|
|
155505
156462
|
init_playerCustomization();
|
|
156463
|
+
init_zIndex();
|
|
155506
156464
|
COLOR_REGIONS = ["hair", "skin", "suit", "tie", "pants", "shoes"];
|
|
155507
156465
|
SpriteCustomizerPanel = class {
|
|
155508
156466
|
constructor(options) {
|
|
@@ -155511,15 +156469,18 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155511
156469
|
this.outsideClickHandler = null;
|
|
155512
156470
|
this.escapeHandler = null;
|
|
155513
156471
|
this.onColorsChanged = options.onColorsChanged;
|
|
156472
|
+
this.onOpenCallback = options.onOpen;
|
|
156473
|
+
this.onCloseCallback = options.onClose;
|
|
155514
156474
|
this.currentColors = loadPlayerColors();
|
|
155515
156475
|
}
|
|
155516
156476
|
show(anchorElement) {
|
|
156477
|
+
const wasOpen = this.container !== null;
|
|
155517
156478
|
if (this.container) this.hide();
|
|
155518
156479
|
this.currentColors = loadPlayerColors();
|
|
155519
156480
|
this.container = document.createElement("div");
|
|
155520
156481
|
this.container.style.cssText = `
|
|
155521
156482
|
position: fixed;
|
|
155522
|
-
z-index:
|
|
156483
|
+
z-index: ${ZIndex.SPRITE_CUSTOMIZER};
|
|
155523
156484
|
width: 320px;
|
|
155524
156485
|
background: #1a1a2e;
|
|
155525
156486
|
border: 2px solid #333;
|
|
@@ -155543,8 +156504,10 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155543
156504
|
}
|
|
155544
156505
|
this.previewImg = this.container.querySelector("#sprite-preview-img");
|
|
155545
156506
|
this.bindEvents();
|
|
156507
|
+
if (!wasOpen) this.onOpenCallback?.();
|
|
155546
156508
|
}
|
|
155547
156509
|
hide() {
|
|
156510
|
+
const wasOpen = this.container !== null;
|
|
155548
156511
|
if (this.outsideClickHandler) {
|
|
155549
156512
|
document.removeEventListener("mousedown", this.outsideClickHandler, true);
|
|
155550
156513
|
this.outsideClickHandler = null;
|
|
@@ -155558,6 +156521,7 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155558
156521
|
this.container = null;
|
|
155559
156522
|
}
|
|
155560
156523
|
this.previewImg = null;
|
|
156524
|
+
if (wasOpen) this.onCloseCallback?.();
|
|
155561
156525
|
}
|
|
155562
156526
|
toggle(anchorElement) {
|
|
155563
156527
|
if (this.container) {
|
|
@@ -155731,6 +156695,12 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155731
156695
|
"use strict";
|
|
155732
156696
|
import_xterm2 = __toESM(require_xterm());
|
|
155733
156697
|
import_addon_fit2 = __toESM(require_addon_fit());
|
|
156698
|
+
init_zIndex();
|
|
156699
|
+
init_TerminalOverlay();
|
|
156700
|
+
init_clipboardToast();
|
|
156701
|
+
init_xtermStyles();
|
|
156702
|
+
init_terminalWheel();
|
|
156703
|
+
init_AutoStartCoordinator();
|
|
155734
156704
|
SeriousTerminalController = class _SeriousTerminalController {
|
|
155735
156705
|
constructor(host, options = {}) {
|
|
155736
156706
|
this.historyPopover = null;
|
|
@@ -155746,6 +156716,15 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155746
156716
|
this.sessionId = null;
|
|
155747
156717
|
this.activeOptions = null;
|
|
155748
156718
|
this.isFullWidth = false;
|
|
156719
|
+
this.terminalContextMenu = null;
|
|
156720
|
+
this.terminalContextMenuDismiss = null;
|
|
156721
|
+
this.seriousInstanceId = String(_SeriousTerminalController.nextSeriousId++);
|
|
156722
|
+
// Spec 003 V13/V14: the onData callback registered on the xterm closes
|
|
156723
|
+
// over the office/agent ids captured at openAgentTerminal time, not the
|
|
156724
|
+
// live this.activeOfficeId/this.activeAgentId. Holding the disposable
|
|
156725
|
+
// here lets the next open() drop the previous binding before installing
|
|
156726
|
+
// a new one — exactly one live onData per controller at any moment.
|
|
156727
|
+
this.onDataDisposable = null;
|
|
155749
156728
|
this.host = host;
|
|
155750
156729
|
this.onClose = options.onClose;
|
|
155751
156730
|
this.isFullWidth = localStorage.getItem(_SeriousTerminalController.FULL_WIDTH_STORAGE_KEY) === "true";
|
|
@@ -155804,13 +156783,13 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155804
156783
|
this.terminalOuterEl.style.cssText = `
|
|
155805
156784
|
flex: 1;
|
|
155806
156785
|
min-height: 0;
|
|
155807
|
-
overflow:
|
|
156786
|
+
overflow: auto;
|
|
155808
156787
|
background: #0d111b;
|
|
155809
156788
|
padding: 10px;
|
|
155810
156789
|
box-sizing: border-box;
|
|
155811
156790
|
`;
|
|
155812
156791
|
this.terminalDivEl = document.createElement("div");
|
|
155813
|
-
this.terminalDivEl.style.cssText = "width: 100%; height: 100%;
|
|
156792
|
+
this.terminalDivEl.style.cssText = "width: 100%; height: 100%;";
|
|
155814
156793
|
this.terminalOuterEl.appendChild(this.terminalDivEl);
|
|
155815
156794
|
this.terminalOuterEl.addEventListener("mousedown", () => this.terminal?.focus());
|
|
155816
156795
|
this.spriteCardEl = document.createElement("div");
|
|
@@ -155954,9 +156933,29 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155954
156933
|
static {
|
|
155955
156934
|
this.FULL_WIDTH_STORAGE_KEY = "agencyOffice:seriousTerminalFullWidth";
|
|
155956
156935
|
}
|
|
156936
|
+
static {
|
|
156937
|
+
this.nextSeriousId = 0;
|
|
156938
|
+
}
|
|
155957
156939
|
isVisible() {
|
|
155958
156940
|
return this.visible;
|
|
155959
156941
|
}
|
|
156942
|
+
// Spec 008-smoke: expose active agent id for the e2e debug hook.
|
|
156943
|
+
getActiveAgentId() {
|
|
156944
|
+
return this.activeAgentId ?? null;
|
|
156945
|
+
}
|
|
156946
|
+
// Spec 008-smoke (T10): expose the visible sprite-card + session-id panel
|
|
156947
|
+
// text so e2e tests can assert what the operator actually sees after agent
|
|
156948
|
+
// switches. Used to repro the user-reported "locked to one agent" symptom.
|
|
156949
|
+
getPanelSnapshot() {
|
|
156950
|
+
return {
|
|
156951
|
+
activeAgentId: this.activeAgentId ?? null,
|
|
156952
|
+
titleText: this.titleEl.textContent ?? "",
|
|
156953
|
+
spriteName: this.spriteNameEl.textContent ?? "",
|
|
156954
|
+
spriteSubtitle: this.spriteSubtitleEl.textContent ?? "",
|
|
156955
|
+
sessionIdText: this.sessionIdEl.textContent ?? "",
|
|
156956
|
+
sessionIdField: this.sessionId ?? null
|
|
156957
|
+
};
|
|
156958
|
+
}
|
|
155960
156959
|
refreshCardFromOverview() {
|
|
155961
156960
|
if (!this.visible || !this.activeAgentId) return;
|
|
155962
156961
|
this.renderExactOverviewCard(this.activeAgentId);
|
|
@@ -155974,15 +156973,51 @@ WARNING: This link could potentially be dangerous`)) {
|
|
|
155974
156973
|
this.openedAt = Date.now();
|
|
155975
156974
|
this.sessionId = null;
|
|
155976
156975
|
this.container.style.display = "flex";
|
|
155977
|
-
|
|
155978
|
-
|
|
155979
|
-
|
|
155980
|
-
|
|
155981
|
-
|
|
155982
|
-
|
|
155983
|
-
|
|
155984
|
-
|
|
155985
|
-
|
|
156976
|
+
try {
|
|
156977
|
+
this.terminal.clear();
|
|
156978
|
+
this.titleEl.textContent = `${options.name} (${options.agentId})`;
|
|
156979
|
+
this.subtitleEl.textContent = options.description;
|
|
156980
|
+
this.updateSpriteCard(options);
|
|
156981
|
+
void this.updateSessionTitle(options.officeId, options.agentId);
|
|
156982
|
+
this.updateSessionIdDisplay();
|
|
156983
|
+
this.setStatus("Opening...");
|
|
156984
|
+
this.applyPanelLayout();
|
|
156985
|
+
this.refitAndResize(options.officeId, options.agentId);
|
|
156986
|
+
} catch (err) {
|
|
156987
|
+
const message = `serious-mode open failed during render: ${err?.message || String(err)}`;
|
|
156988
|
+
try {
|
|
156989
|
+
this.setStatus(message);
|
|
156990
|
+
} catch {
|
|
156991
|
+
}
|
|
156992
|
+
try {
|
|
156993
|
+
this.terminal.writeln(`\r
|
|
156994
|
+
[render error: ${message}]\r
|
|
156995
|
+
`);
|
|
156996
|
+
} catch {
|
|
156997
|
+
}
|
|
156998
|
+
if (DEBUG_SPRITE_SERIOUS) {
|
|
156999
|
+
console.log(
|
|
157000
|
+
`[SeriousTerminalController] openAgentTerminal render failure (officeId=${options.officeId} agentId=${options.agentId}): ${message}`
|
|
157001
|
+
);
|
|
157002
|
+
} else {
|
|
157003
|
+
console.warn("[SeriousTerminalController] openAgentTerminal render failure", err);
|
|
157004
|
+
}
|
|
157005
|
+
}
|
|
157006
|
+
const boundOfficeId = options.officeId;
|
|
157007
|
+
const boundAgentId = options.agentId;
|
|
157008
|
+
try {
|
|
157009
|
+
this.onDataDisposable?.dispose();
|
|
157010
|
+
} catch {
|
|
157011
|
+
}
|
|
157012
|
+
this.onDataDisposable = this.terminal.onData((data) => {
|
|
157013
|
+
if (!window.copilotBridge) return;
|
|
157014
|
+
void window.copilotBridge.terminalWrite(boundOfficeId, boundAgentId, data);
|
|
157015
|
+
});
|
|
157016
|
+
if (DEBUG_SPRITE_SERIOUS) {
|
|
157017
|
+
console.log(
|
|
157018
|
+
`[SeriousTerminalController] onData rebound officeId=${boundOfficeId} agentId=${boundAgentId}`
|
|
157019
|
+
);
|
|
157020
|
+
}
|
|
155986
157021
|
try {
|
|
155987
157022
|
const exists = await window.copilotBridge.terminalExists(options.officeId, options.agentId);
|
|
155988
157023
|
if (!exists) {
|
|
@@ -156034,6 +157069,21 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156034
157069
|
}
|
|
156035
157070
|
async startNewSession(options) {
|
|
156036
157071
|
if (!window.copilotBridge) return;
|
|
157072
|
+
const coordinator = getAutoStartCoordinator();
|
|
157073
|
+
if (coordinator) {
|
|
157074
|
+
try {
|
|
157075
|
+
await coordinator.replaceSession(options.officeId, options.agentId);
|
|
157076
|
+
} catch (err) {
|
|
157077
|
+
console.warn(
|
|
157078
|
+
`[SeriousTerminalController] replaceSession failed for ${options.agentId}: ${err?.message || String(err)}`
|
|
157079
|
+
);
|
|
157080
|
+
}
|
|
157081
|
+
const isCurrentView2 = this.visible && this.activeOfficeId === options.officeId && this.activeAgentId === options.agentId;
|
|
157082
|
+
if (isCurrentView2) {
|
|
157083
|
+
await this.openAgentTerminal(options);
|
|
157084
|
+
}
|
|
157085
|
+
return;
|
|
157086
|
+
}
|
|
156037
157087
|
try {
|
|
156038
157088
|
await window.copilotBridge.resetSession(options.officeId, options.agentId);
|
|
156039
157089
|
} catch {
|
|
@@ -156068,6 +157118,12 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156068
157118
|
}
|
|
156069
157119
|
this.visible = false;
|
|
156070
157120
|
this.container.style.display = "none";
|
|
157121
|
+
this.hideTerminalContextMenu();
|
|
157122
|
+
try {
|
|
157123
|
+
this.onDataDisposable?.dispose();
|
|
157124
|
+
} catch {
|
|
157125
|
+
}
|
|
157126
|
+
this.onDataDisposable = null;
|
|
156071
157127
|
this.activeOfficeId = null;
|
|
156072
157128
|
this.activeAgentId = null;
|
|
156073
157129
|
this.activeOptions = null;
|
|
@@ -156193,7 +157249,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156193
157249
|
border-radius: 8px;
|
|
156194
157250
|
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.45);
|
|
156195
157251
|
padding: 10px 12px;
|
|
156196
|
-
z-index:
|
|
157252
|
+
z-index: ${ZIndex.SERIOUS_TERMINAL};
|
|
156197
157253
|
color: #c8d4ff;
|
|
156198
157254
|
font-size: 12px;
|
|
156199
157255
|
white-space: pre-wrap;
|
|
@@ -156229,17 +157285,166 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156229
157285
|
}
|
|
156230
157286
|
copySessionId() {
|
|
156231
157287
|
if (!this.sessionId) return;
|
|
156232
|
-
|
|
157288
|
+
void this.copyToClipboard(this.sessionId, "session").then((success) => {
|
|
156233
157289
|
const original = this.sessionIdEl.textContent;
|
|
156234
|
-
this.sessionIdEl.textContent = "Copied!";
|
|
156235
|
-
this.sessionIdEl.style.color = "#61d394";
|
|
157290
|
+
this.sessionIdEl.textContent = success ? "Copied!" : "Copy failed";
|
|
157291
|
+
this.sessionIdEl.style.color = success ? "#61d394" : "#ff6b6b";
|
|
156236
157292
|
setTimeout(() => {
|
|
156237
157293
|
this.sessionIdEl.textContent = original;
|
|
156238
157294
|
this.sessionIdEl.style.color = "#8ec3ff";
|
|
156239
157295
|
}, 900);
|
|
156240
|
-
}).catch(() => {
|
|
156241
157296
|
});
|
|
156242
157297
|
}
|
|
157298
|
+
// Spec 006: diagnostic prefix so multi-instance and channel issues
|
|
157299
|
+
// are visible in the toast UI without opening DevTools.
|
|
157300
|
+
tag() {
|
|
157301
|
+
return `[S${this.seriousInstanceId}]`;
|
|
157302
|
+
}
|
|
157303
|
+
// Spec 005 + 006: single canonical clipboard write path via Electron main.
|
|
157304
|
+
// Diagnostic toast on every outcome.
|
|
157305
|
+
async copyToClipboard(text, source = "live") {
|
|
157306
|
+
const t = this.tag();
|
|
157307
|
+
if (!text) {
|
|
157308
|
+
showClipboardToast(`${t} empty selection`, "info");
|
|
157309
|
+
return false;
|
|
157310
|
+
}
|
|
157311
|
+
const bridge = window.copilotBridge;
|
|
157312
|
+
if (!bridge?.clipboardWriteText) {
|
|
157313
|
+
try {
|
|
157314
|
+
await navigator.clipboard.writeText(text);
|
|
157315
|
+
showClipboardToast(`${t} OK ${text.length} (fallback)`, "success");
|
|
157316
|
+
return true;
|
|
157317
|
+
} catch {
|
|
157318
|
+
showClipboardToast(`${t} no-bridge`, "error");
|
|
157319
|
+
return false;
|
|
157320
|
+
}
|
|
157321
|
+
}
|
|
157322
|
+
try {
|
|
157323
|
+
const r = await bridge.clipboardWriteText(text);
|
|
157324
|
+
if (r?.success === true) {
|
|
157325
|
+
showClipboardToast(`${t} OK ${text.length} (verified)`, "success");
|
|
157326
|
+
return true;
|
|
157327
|
+
}
|
|
157328
|
+
if (r?.verified === false) {
|
|
157329
|
+
showClipboardToast(`${t} verify-fail (wrote=${text.length})`, "error");
|
|
157330
|
+
} else {
|
|
157331
|
+
showClipboardToast(`${t} bridge-err: ${r?.error || "unknown"}`, "error");
|
|
157332
|
+
}
|
|
157333
|
+
return false;
|
|
157334
|
+
} catch (e) {
|
|
157335
|
+
showClipboardToast(`${t} bridge-err: ${e?.message || "threw"}`, "error");
|
|
157336
|
+
return false;
|
|
157337
|
+
}
|
|
157338
|
+
}
|
|
157339
|
+
// Spec 005: read OS clipboard via Electron main, forward to PTY.
|
|
157340
|
+
async pasteFromClipboardToTerminal() {
|
|
157341
|
+
if (!this.activeOfficeId || !this.activeAgentId || !window.copilotBridge) return;
|
|
157342
|
+
let text = "";
|
|
157343
|
+
try {
|
|
157344
|
+
const bridge = window.copilotBridge;
|
|
157345
|
+
if (bridge?.clipboardReadText) {
|
|
157346
|
+
const r = await bridge.clipboardReadText();
|
|
157347
|
+
if (r?.success) text = r.text || "";
|
|
157348
|
+
} else if (navigator.clipboard?.readText) {
|
|
157349
|
+
text = await navigator.clipboard.readText();
|
|
157350
|
+
}
|
|
157351
|
+
} catch (e) {
|
|
157352
|
+
showClipboardToast(`Paste failed: ${e?.message || "bridge threw"}`, "error");
|
|
157353
|
+
return;
|
|
157354
|
+
}
|
|
157355
|
+
if (!text) {
|
|
157356
|
+
showClipboardToast("Clipboard is empty", "info");
|
|
157357
|
+
return;
|
|
157358
|
+
}
|
|
157359
|
+
try {
|
|
157360
|
+
await window.copilotBridge.terminalWrite(this.activeOfficeId, this.activeAgentId, text);
|
|
157361
|
+
showClipboardToast(`Pasted ${text.length} char${text.length === 1 ? "" : "s"}`, "success");
|
|
157362
|
+
} catch (e) {
|
|
157363
|
+
showClipboardToast(`Paste failed: ${e?.message || "terminalWrite threw"}`, "error");
|
|
157364
|
+
}
|
|
157365
|
+
}
|
|
157366
|
+
/**
|
|
157367
|
+
* Spec 004: terminal right-click context menu (Copy / Paste). Built once
|
|
157368
|
+
* during attachTerminal, reused per right-click. Dismissed on outside
|
|
157369
|
+
* mousedown or Escape.
|
|
157370
|
+
*/
|
|
157371
|
+
installTerminalContextMenu() {
|
|
157372
|
+
if (!this.terminal || !this.terminalDivEl) return;
|
|
157373
|
+
const menu = document.createElement("div");
|
|
157374
|
+
menu.id = "serious-terminal-context-menu";
|
|
157375
|
+
menu.style.cssText = `
|
|
157376
|
+
position: fixed;
|
|
157377
|
+
display: none;
|
|
157378
|
+
z-index: ${ZIndex.TERMINAL_SPRITE_CARD + 10};
|
|
157379
|
+
min-width: 160px;
|
|
157380
|
+
background: #1c1c2a;
|
|
157381
|
+
border: 1px solid #3a3a55;
|
|
157382
|
+
border-radius: 6px;
|
|
157383
|
+
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.55);
|
|
157384
|
+
padding: 4px 0;
|
|
157385
|
+
font-family: 'Cascadia Code', Consolas, monospace;
|
|
157386
|
+
font-size: 13px;
|
|
157387
|
+
color: #cfd0e0;
|
|
157388
|
+
user-select: none;
|
|
157389
|
+
`;
|
|
157390
|
+
const makeItem = (label, onClick) => {
|
|
157391
|
+
const item = document.createElement("div");
|
|
157392
|
+
item.textContent = label;
|
|
157393
|
+
item.style.cssText = `padding: 6px 14px; cursor: pointer;`;
|
|
157394
|
+
item.dataset.enabled = "true";
|
|
157395
|
+
item.addEventListener("mouseenter", () => {
|
|
157396
|
+
if (item.dataset.enabled === "true") item.style.background = "#2a2a45";
|
|
157397
|
+
});
|
|
157398
|
+
item.addEventListener("mouseleave", () => {
|
|
157399
|
+
item.style.background = "";
|
|
157400
|
+
});
|
|
157401
|
+
item.addEventListener("mousedown", (e) => {
|
|
157402
|
+
e.preventDefault();
|
|
157403
|
+
e.stopPropagation();
|
|
157404
|
+
});
|
|
157405
|
+
item.addEventListener("click", (e) => {
|
|
157406
|
+
e.preventDefault();
|
|
157407
|
+
e.stopPropagation();
|
|
157408
|
+
if (item.dataset.enabled !== "true") return;
|
|
157409
|
+
this.hideTerminalContextMenu();
|
|
157410
|
+
onClick();
|
|
157411
|
+
});
|
|
157412
|
+
return item;
|
|
157413
|
+
};
|
|
157414
|
+
const copyItem = makeItem("Copy", () => {
|
|
157415
|
+
const selection = this.terminal?.hasSelection() ? this.terminal.getSelection() ?? "" : "";
|
|
157416
|
+
void this.copyToClipboard(selection, "live");
|
|
157417
|
+
});
|
|
157418
|
+
const pasteItem = makeItem("Paste", () => {
|
|
157419
|
+
void this.pasteFromClipboardToTerminal();
|
|
157420
|
+
});
|
|
157421
|
+
menu.appendChild(copyItem);
|
|
157422
|
+
menu.appendChild(pasteItem);
|
|
157423
|
+
document.body.appendChild(menu);
|
|
157424
|
+
this.terminalContextMenu = menu;
|
|
157425
|
+
this.terminalDivEl.addEventListener("contextmenu", (event) => {
|
|
157426
|
+
if (!this.visible) return;
|
|
157427
|
+
event.preventDefault();
|
|
157428
|
+
const vw = window.innerWidth;
|
|
157429
|
+
const vh = window.innerHeight;
|
|
157430
|
+
menu.style.display = "block";
|
|
157431
|
+
const rect = menu.getBoundingClientRect();
|
|
157432
|
+
const left = Math.min(event.clientX, vw - rect.width - 4);
|
|
157433
|
+
const top = Math.min(event.clientY, vh - rect.height - 4);
|
|
157434
|
+
menu.style.left = `${Math.max(0, left)}px`;
|
|
157435
|
+
menu.style.top = `${Math.max(0, top)}px`;
|
|
157436
|
+
});
|
|
157437
|
+
this.terminalContextMenuDismiss = (e) => {
|
|
157438
|
+
if (!this.terminalContextMenu || this.terminalContextMenu.style.display === "none") return;
|
|
157439
|
+
if (e instanceof KeyboardEvent && e.key !== "Escape") return;
|
|
157440
|
+
this.hideTerminalContextMenu();
|
|
157441
|
+
};
|
|
157442
|
+
document.addEventListener("mousedown", this.terminalContextMenuDismiss, true);
|
|
157443
|
+
document.addEventListener("keydown", this.terminalContextMenuDismiss, true);
|
|
157444
|
+
}
|
|
157445
|
+
hideTerminalContextMenu() {
|
|
157446
|
+
if (this.terminalContextMenu) this.terminalContextMenu.style.display = "none";
|
|
157447
|
+
}
|
|
156243
157448
|
renderAgentSprite(seed, baseColor) {
|
|
156244
157449
|
const ctx = this.spriteCanvasEl.getContext("2d");
|
|
156245
157450
|
if (!ctx) return;
|
|
@@ -156277,15 +157482,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156277
157482
|
return r << 16 | g << 8 | b;
|
|
156278
157483
|
}
|
|
156279
157484
|
ensureXtermStyles() {
|
|
156280
|
-
|
|
156281
|
-
const style = document.createElement("style");
|
|
156282
|
-
style.id = "xterm-styles";
|
|
156283
|
-
style.textContent = `
|
|
156284
|
-
.xterm { height: 100%; }
|
|
156285
|
-
.xterm-viewport { overflow-y: auto !important; }
|
|
156286
|
-
#serious-terminal-container .xterm { height: 100%; }
|
|
156287
|
-
`;
|
|
156288
|
-
document.head.appendChild(style);
|
|
157485
|
+
ensureXtermStyles();
|
|
156289
157486
|
}
|
|
156290
157487
|
createTerminal() {
|
|
156291
157488
|
this.terminal = new import_xterm2.Terminal({
|
|
@@ -156308,21 +157505,54 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156308
157505
|
this.terminal.loadAddon(this.fitAddon);
|
|
156309
157506
|
this.terminalDivEl.id = "serious-terminal-container";
|
|
156310
157507
|
this.terminal.open(this.terminalDivEl);
|
|
157508
|
+
const MOUSE_MODES = /* @__PURE__ */ new Set([1e3, 1002, 1003, 1006]);
|
|
157509
|
+
this.terminal.parser.registerCsiHandler({ prefix: "?", final: "h" }, (params) => {
|
|
157510
|
+
for (const p of params) {
|
|
157511
|
+
if (typeof p === "number" && MOUSE_MODES.has(p)) return true;
|
|
157512
|
+
}
|
|
157513
|
+
return false;
|
|
157514
|
+
});
|
|
157515
|
+
this.terminal.attachCustomWheelEventHandler((event) => {
|
|
157516
|
+
const term = this.terminal;
|
|
157517
|
+
if (!term) return true;
|
|
157518
|
+
if (term.buffer.active.type !== "alternate") return true;
|
|
157519
|
+
const seq = wheelToPtySequence(event.deltaY);
|
|
157520
|
+
if (!seq) return true;
|
|
157521
|
+
if (this.activeOfficeId && this.activeAgentId && window.copilotBridge) {
|
|
157522
|
+
void window.copilotBridge.terminalWrite(this.activeOfficeId, this.activeAgentId, seq);
|
|
157523
|
+
}
|
|
157524
|
+
return false;
|
|
157525
|
+
});
|
|
157526
|
+
this.installTerminalContextMenu();
|
|
156311
157527
|
this.terminal.attachCustomKeyEventHandler((event) => {
|
|
156312
|
-
|
|
157528
|
+
const isModifierPressed = event.ctrlKey || event.metaKey;
|
|
157529
|
+
const key = event.key.toLowerCase();
|
|
157530
|
+
if (event.type !== "keydown" || !isModifierPressed) return true;
|
|
157531
|
+
if (key === "c") {
|
|
157532
|
+
const selection = this.terminal?.hasSelection() ? this.terminal.getSelection() ?? "" : "";
|
|
157533
|
+
if (!selection) {
|
|
157534
|
+
return true;
|
|
157535
|
+
}
|
|
156313
157536
|
event.preventDefault();
|
|
156314
157537
|
event.stopPropagation();
|
|
156315
|
-
|
|
156316
|
-
|
|
156317
|
-
|
|
156318
|
-
|
|
157538
|
+
void this.copyToClipboard(selection, "live");
|
|
157539
|
+
return false;
|
|
157540
|
+
}
|
|
157541
|
+
if (key === "v") {
|
|
157542
|
+
event.preventDefault();
|
|
157543
|
+
event.stopPropagation();
|
|
157544
|
+
void this.pasteFromClipboardToTerminal();
|
|
157545
|
+
return false;
|
|
157546
|
+
}
|
|
157547
|
+
if (key === "f") {
|
|
157548
|
+
event.preventDefault();
|
|
157549
|
+
event.stopPropagation();
|
|
157550
|
+
this.toggleFullWidth();
|
|
156319
157551
|
return false;
|
|
156320
157552
|
}
|
|
156321
157553
|
return true;
|
|
156322
157554
|
});
|
|
156323
|
-
this.terminal.onData((
|
|
156324
|
-
if (!window.copilotBridge || !this.activeOfficeId || !this.activeAgentId) return;
|
|
156325
|
-
void window.copilotBridge.terminalWrite(this.activeOfficeId, this.activeAgentId, data);
|
|
157555
|
+
this.terminal.onData((_data) => {
|
|
156326
157556
|
});
|
|
156327
157557
|
this.resizeHandler = () => {
|
|
156328
157558
|
if (!this.visible || !this.activeOfficeId || !this.activeAgentId) return;
|
|
@@ -156408,6 +157638,48 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156408
157638
|
}
|
|
156409
157639
|
});
|
|
156410
157640
|
|
|
157641
|
+
// src/util/toolStatus.ts
|
|
157642
|
+
function normalizeToolName(toolName) {
|
|
157643
|
+
return (toolName ?? "").trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
157644
|
+
}
|
|
157645
|
+
function isAskUserTool(toolName, status) {
|
|
157646
|
+
const normalized = normalizeToolName(toolName);
|
|
157647
|
+
if (normalized === "ask_user" || normalized === "askuser") return true;
|
|
157648
|
+
const statusText = (status ?? "").toLowerCase();
|
|
157649
|
+
return statusText.includes("waiting for your answer") || statusText.includes("waiting on user input");
|
|
157650
|
+
}
|
|
157651
|
+
function nextSubStateAfterToolComplete(remainingTools) {
|
|
157652
|
+
if (remainingTools.length === 0) return { kind: "idle" };
|
|
157653
|
+
if (remainingTools.some((t) => isAskUserTool(t.name, t.status))) {
|
|
157654
|
+
return { kind: "waiting" };
|
|
157655
|
+
}
|
|
157656
|
+
const last = remainingTools[remainingTools.length - 1];
|
|
157657
|
+
return { kind: "thinking", detail: String(last.name ?? "") };
|
|
157658
|
+
}
|
|
157659
|
+
var init_toolStatus = __esm({
|
|
157660
|
+
"src/util/toolStatus.ts"() {
|
|
157661
|
+
"use strict";
|
|
157662
|
+
}
|
|
157663
|
+
});
|
|
157664
|
+
|
|
157665
|
+
// src/util/startupTimeoutGuard.ts
|
|
157666
|
+
function decideStartupTimeoutTransition(inputs) {
|
|
157667
|
+
if (inputs.subState !== "starting") return { kind: "no-transition" };
|
|
157668
|
+
if (!inputs.activityStartTime) return { kind: "no-transition" };
|
|
157669
|
+
if (inputs.now - inputs.activityStartTime <= inputs.timeoutMs) {
|
|
157670
|
+
return { kind: "no-transition" };
|
|
157671
|
+
}
|
|
157672
|
+
if (inputs.serverAlive === true) {
|
|
157673
|
+
return { kind: "recover-to-ready" };
|
|
157674
|
+
}
|
|
157675
|
+
return { kind: "transition-to-error", reason: "Startup timed out" };
|
|
157676
|
+
}
|
|
157677
|
+
var init_startupTimeoutGuard = __esm({
|
|
157678
|
+
"src/util/startupTimeoutGuard.ts"() {
|
|
157679
|
+
"use strict";
|
|
157680
|
+
}
|
|
157681
|
+
});
|
|
157682
|
+
|
|
156411
157683
|
// src/main.ts
|
|
156412
157684
|
var require_main = __commonJS({
|
|
156413
157685
|
"src/main.ts"() {
|
|
@@ -156418,6 +157690,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156418
157690
|
init_officeManager();
|
|
156419
157691
|
init_agents();
|
|
156420
157692
|
init_responsiveLayout();
|
|
157693
|
+
init_zIndex();
|
|
156421
157694
|
init_layouts();
|
|
156422
157695
|
init_ToastNotification();
|
|
156423
157696
|
init_NotificationService();
|
|
@@ -156425,7 +157698,12 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156425
157698
|
init_SpriteCustomizerPanel();
|
|
156426
157699
|
init_SeriousTerminalController();
|
|
156427
157700
|
init_SpriteGenerator();
|
|
157701
|
+
init_toolStatus();
|
|
157702
|
+
init_startupTimeoutGuard();
|
|
157703
|
+
init_AutoStartCoordinator();
|
|
157704
|
+
init_agentAutoStart();
|
|
156428
157705
|
officeManager.ensureDefaultOffice();
|
|
157706
|
+
recordOfficeAccess(officeManager.currentOfficeId);
|
|
156429
157707
|
function getCurrentLayout() {
|
|
156430
157708
|
return officeManager.currentOffice?.config.layout ?? "default";
|
|
156431
157709
|
}
|
|
@@ -156443,15 +157721,6 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156443
157721
|
restoreSeatedReserveAgents(officeManager.getSeatedAgents(office.config.id));
|
|
156444
157722
|
}
|
|
156445
157723
|
}
|
|
156446
|
-
function normalizeToolName(toolName) {
|
|
156447
|
-
return (toolName ?? "").trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
156448
|
-
}
|
|
156449
|
-
function isAskUserTool(toolName, status) {
|
|
156450
|
-
const normalized = normalizeToolName(toolName);
|
|
156451
|
-
if (normalized === "ask_user" || normalized === "askuser") return true;
|
|
156452
|
-
const statusText = (status ?? "").toLowerCase();
|
|
156453
|
-
return statusText.includes("waiting for your answer") || statusText.includes("waiting on user input");
|
|
156454
|
-
}
|
|
156455
157724
|
function isDonePendingAck(status) {
|
|
156456
157725
|
return !!status?.completionPendingAck;
|
|
156457
157726
|
}
|
|
@@ -156465,6 +157734,25 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156465
157734
|
var SESSION_META_CACHE_STORAGE_KEY = "agencyOffice:sessionMetaCacheByOffice";
|
|
156466
157735
|
var OVERVIEW_SPRITE_CACHE_STORAGE_KEY = "agencyOffice:overviewSpriteCache";
|
|
156467
157736
|
var PC_TERMINAL_ID2 = "pc-terminal";
|
|
157737
|
+
var OFFICE_SORT_STORAGE_KEY = "agencyOffice:officeSortMode";
|
|
157738
|
+
var OFFICE_ACCESS_TIMES_KEY = "agencyOffice:officeAccessTimes";
|
|
157739
|
+
var officeSortMode = localStorage.getItem(OFFICE_SORT_STORAGE_KEY) || "default";
|
|
157740
|
+
function getOfficeAccessTimes() {
|
|
157741
|
+
try {
|
|
157742
|
+
const raw = localStorage.getItem(OFFICE_ACCESS_TIMES_KEY);
|
|
157743
|
+
return raw ? JSON.parse(raw) : {};
|
|
157744
|
+
} catch {
|
|
157745
|
+
return {};
|
|
157746
|
+
}
|
|
157747
|
+
}
|
|
157748
|
+
function recordOfficeAccess(officeId) {
|
|
157749
|
+
const times = getOfficeAccessTimes();
|
|
157750
|
+
times[officeId] = Date.now();
|
|
157751
|
+
try {
|
|
157752
|
+
localStorage.setItem(OFFICE_ACCESS_TIMES_KEY, JSON.stringify(times));
|
|
157753
|
+
} catch {
|
|
157754
|
+
}
|
|
157755
|
+
}
|
|
156468
157756
|
function sanitizeAppMode(value) {
|
|
156469
157757
|
return value === "serious" ? "serious" : "game";
|
|
156470
157758
|
}
|
|
@@ -156690,6 +157978,17 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156690
157978
|
if (previousMode === "serious" && appMode === "game") {
|
|
156691
157979
|
void seriousTerminalController?.closeView({ detach: true, silent: true });
|
|
156692
157980
|
}
|
|
157981
|
+
if (previousMode === "game" && appMode === "serious") {
|
|
157982
|
+
try {
|
|
157983
|
+
const scene = phaserGameRef?.scene.getScene("OfficeScene");
|
|
157984
|
+
const overlay = scene?.getTerminalOverlay?.();
|
|
157985
|
+
if (overlay?.getIsVisible?.()) {
|
|
157986
|
+
overlay.hide?.();
|
|
157987
|
+
}
|
|
157988
|
+
} catch (err) {
|
|
157989
|
+
console.warn("[main] failed to hide game-mode terminal overlay on mode flip", err);
|
|
157990
|
+
}
|
|
157991
|
+
}
|
|
156693
157992
|
if (appMode === "serious") {
|
|
156694
157993
|
prewarmOverviewSpriteCacheFromTextures();
|
|
156695
157994
|
teardownPhaserGame();
|
|
@@ -156728,9 +158027,86 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156728
158027
|
if (typeof window !== "undefined") {
|
|
156729
158028
|
window.__copilotOfficeMobileModeActive = isMobileModeActive;
|
|
156730
158029
|
}
|
|
158030
|
+
if (typeof window !== "undefined" && window.__copilotOfficeE2E === true) {
|
|
158031
|
+
installE2eDebugHook();
|
|
158032
|
+
}
|
|
158033
|
+
function installE2eDebugHook() {
|
|
158034
|
+
const debugApi = {
|
|
158035
|
+
getActiveMode: () => appMode,
|
|
158036
|
+
setMode: (mode) => {
|
|
158037
|
+
if (mode === appMode) return;
|
|
158038
|
+
applyAppMode(mode, { persist: true, refreshTabs: true });
|
|
158039
|
+
},
|
|
158040
|
+
getCurrentOfficeId: () => officeManager.currentOfficeId,
|
|
158041
|
+
listAgents: () => {
|
|
158042
|
+
return getCurrentAgents().map((a) => ({
|
|
158043
|
+
id: a.id,
|
|
158044
|
+
name: a.name,
|
|
158045
|
+
tileX: a.tileX,
|
|
158046
|
+
tileY: a.tileY
|
|
158047
|
+
}));
|
|
158048
|
+
},
|
|
158049
|
+
getActiveTerminalAgentId: () => {
|
|
158050
|
+
if (appMode === "serious") {
|
|
158051
|
+
return seriousTerminalController?.getActiveAgentId?.() ?? null;
|
|
158052
|
+
}
|
|
158053
|
+
const scene = phaserGameRef?.scene.getScene("OfficeScene");
|
|
158054
|
+
const overlay = scene?.getTerminalOverlay?.();
|
|
158055
|
+
if (!overlay || !overlay.getIsVisible()) return null;
|
|
158056
|
+
return overlay.getActiveAgentId();
|
|
158057
|
+
},
|
|
158058
|
+
openAgentTerminal: async (agentId) => {
|
|
158059
|
+
await openAgentTerminal(agentId);
|
|
158060
|
+
},
|
|
158061
|
+
closeActiveTerminal: async () => {
|
|
158062
|
+
if (appMode === "serious") {
|
|
158063
|
+
await seriousTerminalController?.closeView({ detach: true });
|
|
158064
|
+
return;
|
|
158065
|
+
}
|
|
158066
|
+
const scene = phaserGameRef?.scene.getScene("OfficeScene");
|
|
158067
|
+
scene?.getTerminalOverlay?.()?.hide();
|
|
158068
|
+
},
|
|
158069
|
+
switchOffice: (officeId) => {
|
|
158070
|
+
switchToOffice(officeId);
|
|
158071
|
+
},
|
|
158072
|
+
getCachedSessionMetaForRender: () => {
|
|
158073
|
+
return { ...cachedSessionMeta };
|
|
158074
|
+
},
|
|
158075
|
+
getSeriousPanelSnapshot: () => {
|
|
158076
|
+
if (appMode !== "serious") return null;
|
|
158077
|
+
const snap = seriousTerminalController?.getPanelSnapshot?.();
|
|
158078
|
+
return snap ?? null;
|
|
158079
|
+
},
|
|
158080
|
+
getWarmedOfficeIds: () => autoStartCoordinator.warmedOffices.snapshot(),
|
|
158081
|
+
getAutoStartTerminalStartCount: () => autoStartTerminalStartCount,
|
|
158082
|
+
triggerAutoStartForCurrentOffice: () => autoStartCoordinator.tryWarmCurrentOffice(),
|
|
158083
|
+
replaceAgentSession: (officeId, agentId) => autoStartCoordinator.replaceSession(officeId, agentId),
|
|
158084
|
+
setAutoStartEnabled: (enabled) => {
|
|
158085
|
+
setAgentAutoStartSettings({ autoStartKnownAgents: enabled });
|
|
158086
|
+
},
|
|
158087
|
+
getAutoStartEnabled: () => getAgentAutoStartSettings().autoStartKnownAgents,
|
|
158088
|
+
clearWarmedOfficeRegistry: () => {
|
|
158089
|
+
autoStartCoordinator.warmedOffices.clearAll();
|
|
158090
|
+
},
|
|
158091
|
+
getCurrentSessionIdForAgent: async (officeId, agentId) => {
|
|
158092
|
+
if (!window.copilotBridge?.getSessionId) return null;
|
|
158093
|
+
try {
|
|
158094
|
+
return await window.copilotBridge.getSessionId(officeId, agentId);
|
|
158095
|
+
} catch {
|
|
158096
|
+
return null;
|
|
158097
|
+
}
|
|
158098
|
+
}
|
|
158099
|
+
};
|
|
158100
|
+
window.__copilotOfficeDebug = debugApi;
|
|
158101
|
+
console.log("[main] Spec 008-smoke: __copilotOfficeDebug installed");
|
|
158102
|
+
}
|
|
156731
158103
|
function renderOfficeTabs() {
|
|
156732
|
-
|
|
158104
|
+
let offices = officeManager.getAllOffices();
|
|
156733
158105
|
const currentId = officeManager.currentOfficeId;
|
|
158106
|
+
if (officeSortMode === "recent") {
|
|
158107
|
+
const accessTimes = getOfficeAccessTimes();
|
|
158108
|
+
offices = [...offices].sort((a, b) => (accessTimes[b.id] || 0) - (accessTimes[a.id] || 0));
|
|
158109
|
+
}
|
|
156734
158110
|
let html = "";
|
|
156735
158111
|
for (const office of offices) {
|
|
156736
158112
|
const isActive = office.id === currentId;
|
|
@@ -156941,6 +158317,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156941
158317
|
selectedAgentId = null;
|
|
156942
158318
|
void seriousTerminalController?.closeView({ detach: true });
|
|
156943
158319
|
officeManager.switchOffice(officeId);
|
|
158320
|
+
recordOfficeAccess(officeId);
|
|
156944
158321
|
cachedSessionMeta = getSessionMetaCacheForOffice(officeId);
|
|
156945
158322
|
syncActiveRosterForCurrentOffice();
|
|
156946
158323
|
phaserGameRef?.events.emit("office:switch", officeId, officeManager.currentOffice?.config.workingDirectory);
|
|
@@ -156949,6 +158326,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156949
158326
|
updateStatusBar();
|
|
156950
158327
|
void reconnectAgentStatuses();
|
|
156951
158328
|
fetchSessionMeta();
|
|
158329
|
+
void autoStartCoordinator.tryWarmCurrentOffice();
|
|
156952
158330
|
console.log(`[Office] Switched to office: ${officeManager.currentOffice?.config.name}`);
|
|
156953
158331
|
}
|
|
156954
158332
|
function showNewOfficeDialog() {
|
|
@@ -156956,7 +158334,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
156956
158334
|
const overlay = document.createElement("div");
|
|
156957
158335
|
overlay.style.cssText = `
|
|
156958
158336
|
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
|
|
156959
|
-
background: rgba(0,0,0,0.7); z-index:
|
|
158337
|
+
background: rgba(0,0,0,0.7); z-index: ${ZIndex.MODAL_DIALOG};
|
|
156960
158338
|
display: flex; align-items: center; justify-content: center;
|
|
156961
158339
|
`;
|
|
156962
158340
|
const dialog = document.createElement("div");
|
|
@@ -157069,7 +158447,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
157069
158447
|
min-width: 280px;
|
|
157070
158448
|
font-family: 'Cascadia Code', Consolas, monospace;
|
|
157071
158449
|
color: #eee;
|
|
157072
|
-
z-index:
|
|
158450
|
+
z-index: ${ZIndex.TOP_MODAL};
|
|
157073
158451
|
box-shadow: 0 8px 24px rgba(0,0,0,0.5);
|
|
157074
158452
|
`;
|
|
157075
158453
|
const escapeHtml = (s) => s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -157158,20 +158536,49 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
157158
158536
|
<div id="terminal-title" style="font-size: 18px; font-weight: bold; color: #8af; margin-bottom: 4px;">\u{1F3E2} Office Overview</div>
|
|
157159
158537
|
<div id="terminal-subtitle" style="font-size: 12px; color: #555;"></div>
|
|
157160
158538
|
</div>
|
|
157161
|
-
<
|
|
157162
|
-
|
|
157163
|
-
|
|
157164
|
-
|
|
157165
|
-
|
|
157166
|
-
|
|
157167
|
-
|
|
157168
|
-
|
|
157169
|
-
|
|
157170
|
-
|
|
157171
|
-
|
|
157172
|
-
|
|
158539
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
158540
|
+
<button id="office-sort-btn" style="
|
|
158541
|
+
padding: 6px 12px;
|
|
158542
|
+
background: ${officeSortMode === "recent" ? "#2a3a5a" : "#252538"};
|
|
158543
|
+
color: ${officeSortMode === "recent" ? "#8af" : "#666"};
|
|
158544
|
+
border: 1px solid ${officeSortMode === "recent" ? "#4488ff" : "#444"};
|
|
158545
|
+
border-radius: 4px;
|
|
158546
|
+
font-family: 'Cascadia Code', Consolas, monospace;
|
|
158547
|
+
font-size: 12px;
|
|
158548
|
+
cursor: pointer;
|
|
158549
|
+
white-space: nowrap;
|
|
158550
|
+
transition: all 0.2s;
|
|
158551
|
+
" title="Sort office tabs">\u21C5 ${officeSortMode === "recent" ? "Recent" : "Default"}</button>
|
|
158552
|
+
<button id="close-office-btn" style="
|
|
158553
|
+
display: none;
|
|
158554
|
+
padding: 6px 14px;
|
|
158555
|
+
background: #cc3344;
|
|
158556
|
+
color: #fff;
|
|
158557
|
+
border: none;
|
|
158558
|
+
border-radius: 4px;
|
|
158559
|
+
font-family: 'Cascadia Code', Consolas, monospace;
|
|
158560
|
+
font-size: 12px;
|
|
158561
|
+
cursor: pointer;
|
|
158562
|
+
white-space: nowrap;
|
|
158563
|
+
">\u2715 Close Office</button>
|
|
158564
|
+
</div>
|
|
157173
158565
|
`;
|
|
157174
158566
|
overviewHost.appendChild(overviewHeader);
|
|
158567
|
+
document.getElementById("office-sort-btn").addEventListener("click", () => {
|
|
158568
|
+
officeSortMode = officeSortMode === "default" ? "recent" : "default";
|
|
158569
|
+
try {
|
|
158570
|
+
localStorage.setItem(OFFICE_SORT_STORAGE_KEY, officeSortMode);
|
|
158571
|
+
} catch {
|
|
158572
|
+
}
|
|
158573
|
+
renderOfficeTabs();
|
|
158574
|
+
const sortBtn = document.getElementById("office-sort-btn");
|
|
158575
|
+
if (sortBtn) {
|
|
158576
|
+
sortBtn.textContent = `\u21C5 ${officeSortMode === "recent" ? "Recent" : "Default"}`;
|
|
158577
|
+
sortBtn.style.background = officeSortMode === "recent" ? "#2a3a5a" : "#252538";
|
|
158578
|
+
sortBtn.style.color = officeSortMode === "recent" ? "#8af" : "#666";
|
|
158579
|
+
sortBtn.style.borderColor = officeSortMode === "recent" ? "#4488ff" : "#444";
|
|
158580
|
+
}
|
|
158581
|
+
});
|
|
157175
158582
|
document.getElementById("close-office-btn").addEventListener("click", () => {
|
|
157176
158583
|
const currentId = officeManager.currentOfficeId;
|
|
157177
158584
|
const office = officeManager.currentOffice;
|
|
@@ -157209,7 +158616,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
157209
158616
|
font-family: monospace;
|
|
157210
158617
|
font-size: 16px;
|
|
157211
158618
|
color: #888;
|
|
157212
|
-
z-index:
|
|
158619
|
+
z-index: ${ZIndex.STATUS_BAR};
|
|
157213
158620
|
`;
|
|
157214
158621
|
document.body.appendChild(statusBar);
|
|
157215
158622
|
var bgmMuted = localStorage.getItem("copilot-office-bgm-muted") !== "false";
|
|
@@ -157289,6 +158696,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
157289
158696
|
seriousPlaceholder.style.display = "none";
|
|
157290
158697
|
}
|
|
157291
158698
|
async function openAgentTerminal(agentId) {
|
|
158699
|
+
selectedAgentId = agentId;
|
|
157292
158700
|
if (appMode === "game") {
|
|
157293
158701
|
phaserGameRef?.events.emit("open:agent:terminal", agentId);
|
|
157294
158702
|
return;
|
|
@@ -157318,6 +158726,80 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
157318
158726
|
updateTerminalContent();
|
|
157319
158727
|
}
|
|
157320
158728
|
});
|
|
158729
|
+
var autoStartTerminalStartCount = 0;
|
|
158730
|
+
async function warmAgentSession(officeId, agentId) {
|
|
158731
|
+
if (!window.copilotBridge) return;
|
|
158732
|
+
const launchConfig = getSeriousLaunchConfig(agentId);
|
|
158733
|
+
if (!launchConfig) return;
|
|
158734
|
+
const workingDir = launchConfig.workingDir;
|
|
158735
|
+
const launchMode = launchConfig.launchMode;
|
|
158736
|
+
const officeStatus = officeManager.getAgentStatus(officeId, agentId);
|
|
158737
|
+
if (officeStatus?.state === "slacking") {
|
|
158738
|
+
officeManager.setAgentStarting(officeId, agentId);
|
|
158739
|
+
phaserGameRef?.events.emit("agent:status:changed", agentId);
|
|
158740
|
+
updateStatusBar();
|
|
158741
|
+
updateTerminalContent();
|
|
158742
|
+
}
|
|
158743
|
+
autoStartTerminalStartCount += 1;
|
|
158744
|
+
await window.copilotBridge.terminalStart(
|
|
158745
|
+
officeId,
|
|
158746
|
+
agentId,
|
|
158747
|
+
workingDir,
|
|
158748
|
+
void 0,
|
|
158749
|
+
void 0,
|
|
158750
|
+
void 0,
|
|
158751
|
+
launchMode
|
|
158752
|
+
);
|
|
158753
|
+
}
|
|
158754
|
+
function buildCanonicalAgentIdsForOffice(officeId) {
|
|
158755
|
+
const office = officeManager.currentOfficeId === officeId ? officeManager.currentOffice : null;
|
|
158756
|
+
if (office && officeManager.currentOfficeId === officeId) {
|
|
158757
|
+
return getCurrentAgents().map((a) => a.id);
|
|
158758
|
+
}
|
|
158759
|
+
const layoutKey = officeManager.currentOffice?.config.layout ?? "default";
|
|
158760
|
+
const layoutAgents = getLayout(layoutKey).agents.map((a) => a.id);
|
|
158761
|
+
const customIds = (officeManager.currentOffice?.config.customAgents ?? []).map(
|
|
158762
|
+
(a) => a.id
|
|
158763
|
+
);
|
|
158764
|
+
return Array.from(/* @__PURE__ */ new Set([...layoutAgents, ...customIds]));
|
|
158765
|
+
}
|
|
158766
|
+
var autoStartCoordinator = new AutoStartCoordinator({
|
|
158767
|
+
getCurrentOfficeId: () => officeManager.currentOfficeId,
|
|
158768
|
+
getCanonicalAgentIds: (oid) => buildCanonicalAgentIdsForOffice(oid),
|
|
158769
|
+
getSessionMeta: async (oid) => {
|
|
158770
|
+
if (!window.copilotBridge?.getAllSessionMeta) {
|
|
158771
|
+
return officeManager.currentOfficeId === oid ? cachedSessionMeta : getSessionMetaCacheForOffice(oid);
|
|
158772
|
+
}
|
|
158773
|
+
try {
|
|
158774
|
+
const fresh = await window.copilotBridge.getAllSessionMeta(oid);
|
|
158775
|
+
return fresh || {};
|
|
158776
|
+
} catch {
|
|
158777
|
+
return officeManager.currentOfficeId === oid ? cachedSessionMeta : getSessionMetaCacheForOffice(oid);
|
|
158778
|
+
}
|
|
158779
|
+
},
|
|
158780
|
+
getCurrentSessionId: async (oid, aid) => {
|
|
158781
|
+
if (!window.copilotBridge?.getSessionId) return null;
|
|
158782
|
+
try {
|
|
158783
|
+
return await window.copilotBridge.getSessionId(oid, aid);
|
|
158784
|
+
} catch {
|
|
158785
|
+
return null;
|
|
158786
|
+
}
|
|
158787
|
+
},
|
|
158788
|
+
getAgentLaunchConfig: (_oid, aid) => {
|
|
158789
|
+
const cfg = getSeriousLaunchConfig(aid);
|
|
158790
|
+
return {
|
|
158791
|
+
workingDir: cfg?.workingDir ?? officeManager.getCurrentWorkingDirectory(),
|
|
158792
|
+
launchMode: cfg?.launchMode ?? "copilot"
|
|
158793
|
+
};
|
|
158794
|
+
},
|
|
158795
|
+
resetSession: async (oid, aid) => {
|
|
158796
|
+
if (!window.copilotBridge) return;
|
|
158797
|
+
await window.copilotBridge.resetSession(oid, aid);
|
|
158798
|
+
},
|
|
158799
|
+
warmAgentSession: (oid, aid) => warmAgentSession(oid, aid),
|
|
158800
|
+
getSettings: () => getAgentAutoStartSettings()
|
|
158801
|
+
});
|
|
158802
|
+
setAutoStartCoordinator(autoStartCoordinator);
|
|
157321
158803
|
var notificationService = new NotificationService(
|
|
157322
158804
|
toastManager,
|
|
157323
158805
|
(agentId) => {
|
|
@@ -157373,6 +158855,14 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
157373
158855
|
const base64 = scene.textures.getBase64("player");
|
|
157374
158856
|
spriteCustomizerPanel.updatePreview(base64);
|
|
157375
158857
|
}
|
|
158858
|
+
},
|
|
158859
|
+
// Route focus through InputManager: reuse the settings:open / settings:close
|
|
158860
|
+
// bus that OfficeScene already wires to suspendGameInput / resumeGameInput.
|
|
158861
|
+
onOpen: () => {
|
|
158862
|
+
phaserGameRef?.events.emit("settings:open");
|
|
158863
|
+
},
|
|
158864
|
+
onClose: () => {
|
|
158865
|
+
phaserGameRef?.events.emit("settings:close");
|
|
157376
158866
|
}
|
|
157377
158867
|
});
|
|
157378
158868
|
var lastTerminalContentHtml = "";
|
|
@@ -157558,10 +159048,27 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
157558
159048
|
e.stopPropagation();
|
|
157559
159049
|
const agentId = metaPanel.dataset.agent;
|
|
157560
159050
|
if (!agentId) return;
|
|
159051
|
+
const idBadge = target.closest(".session-id-badge");
|
|
159052
|
+
if (idBadge) {
|
|
159053
|
+
const fullId = idBadge.dataset.sessionId ?? idBadge.textContent?.trim() ?? "";
|
|
159054
|
+
if (fullId) {
|
|
159055
|
+
void navigator.clipboard?.writeText(fullId).catch(() => {
|
|
159056
|
+
});
|
|
159057
|
+
const original = idBadge.textContent;
|
|
159058
|
+
idBadge.textContent = "\u2713 copied";
|
|
159059
|
+
setTimeout(() => {
|
|
159060
|
+
if (idBadge) idBadge.textContent = original;
|
|
159061
|
+
}, 700);
|
|
159062
|
+
}
|
|
159063
|
+
return;
|
|
159064
|
+
}
|
|
157561
159065
|
layout.clickHandler.handleMetaPanelClick(target, agentId, {
|
|
157562
159066
|
startSessionMetaEdit,
|
|
157563
159067
|
startNewSession: (id) => {
|
|
157564
159068
|
void startSessionFromOverview(id);
|
|
159069
|
+
},
|
|
159070
|
+
closeSession: (id) => {
|
|
159071
|
+
void closeSessionFromOverview(id);
|
|
157565
159072
|
}
|
|
157566
159073
|
});
|
|
157567
159074
|
return;
|
|
@@ -157621,6 +159128,25 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
157621
159128
|
updateStatusBar();
|
|
157622
159129
|
updateTerminalContent();
|
|
157623
159130
|
}
|
|
159131
|
+
async function closeSessionFromOverview(agentId) {
|
|
159132
|
+
if (!window.copilotBridge) return;
|
|
159133
|
+
const officeId = officeManager.currentOfficeId || "office-0";
|
|
159134
|
+
try {
|
|
159135
|
+
await window.copilotBridge.resetSession(officeId, agentId);
|
|
159136
|
+
} catch (error) {
|
|
159137
|
+
console.warn(`[Office] Failed to close session from overview for ${agentId}:`, error);
|
|
159138
|
+
return;
|
|
159139
|
+
}
|
|
159140
|
+
const meta = cachedSessionMeta[agentId];
|
|
159141
|
+
if (meta) {
|
|
159142
|
+
cachedSessionMeta[agentId] = { ...meta, sessionId: void 0 };
|
|
159143
|
+
setSessionMetaCacheForOffice(officeId, cachedSessionMeta);
|
|
159144
|
+
}
|
|
159145
|
+
officeManager.setAgentSlacking(officeId, agentId);
|
|
159146
|
+
phaserGameRef?.events.emit("agent:status:changed", agentId);
|
|
159147
|
+
updateStatusBar();
|
|
159148
|
+
updateTerminalContent();
|
|
159149
|
+
}
|
|
157624
159150
|
function startSessionMetaEdit(agentId) {
|
|
157625
159151
|
const panel = overviewHost.querySelector(`.session-meta-panel[data-agent="${agentId}"]`);
|
|
157626
159152
|
if (!panel) return;
|
|
@@ -157696,11 +159222,11 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
157696
159222
|
officeManager.setTaskSummary(officeId, agentId, status);
|
|
157697
159223
|
}
|
|
157698
159224
|
if (isAskUserTool(toolName, status)) {
|
|
157699
|
-
officeManager.setAgentWaiting(officeId, agentId);
|
|
159225
|
+
officeManager.setAgentWaiting(officeId, agentId, "ask_user");
|
|
157700
159226
|
console.log(`[Office] Status: ${agentId} \u2192 waiting (ask_user)`);
|
|
157701
159227
|
notifyAgent(agentId, "askUser");
|
|
157702
159228
|
} else {
|
|
157703
|
-
officeManager.setAgentThinking(officeId, agentId, `${toolName}
|
|
159229
|
+
officeManager.setAgentThinking(officeId, agentId, `${toolName}`, "tool_start");
|
|
157704
159230
|
console.log(`[Office] Status: ${agentId} \u2192 thinking (${toolName})`);
|
|
157705
159231
|
notifyAgent(agentId, "toolStart", { toolName });
|
|
157706
159232
|
}
|
|
@@ -157722,18 +159248,18 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
157722
159248
|
officeManager.setLastCompletedAction(officeId, agentId, completedToolName);
|
|
157723
159249
|
officeManager.pushRecentAction(officeId, agentId, completedToolName, "completed");
|
|
157724
159250
|
notifyAgent(agentId, "toolComplete", { toolName: completedToolName });
|
|
157725
|
-
|
|
159251
|
+
const next = nextSubStateAfterToolComplete(remaining);
|
|
159252
|
+
if (next.kind === "idle") {
|
|
157726
159253
|
const currentStatus = officeManager.getAgentStatus(officeId, agentId);
|
|
157727
159254
|
if (currentStatus?.subState === "thinking") {
|
|
157728
|
-
officeManager.setAgentThinking(officeId, agentId, currentStatus.thinkingDetail ?? "Processing...");
|
|
159255
|
+
officeManager.setAgentThinking(officeId, agentId, currentStatus.thinkingDetail ?? "Processing...", "tool_complete_settling");
|
|
157729
159256
|
} else {
|
|
157730
|
-
officeManager.setAgentReady(officeId, agentId);
|
|
159257
|
+
officeManager.setAgentReady(officeId, agentId, "tool_complete");
|
|
157731
159258
|
}
|
|
157732
|
-
} else if (
|
|
157733
|
-
officeManager.setAgentWaiting(officeId, agentId);
|
|
159259
|
+
} else if (next.kind === "waiting") {
|
|
159260
|
+
officeManager.setAgentWaiting(officeId, agentId, "ask_user_race_guard");
|
|
157734
159261
|
} else {
|
|
157735
|
-
|
|
157736
|
-
officeManager.setAgentThinking(officeId, agentId, `${last.name}`);
|
|
159262
|
+
officeManager.setAgentThinking(officeId, agentId, next.detail, "tool_complete");
|
|
157737
159263
|
}
|
|
157738
159264
|
}
|
|
157739
159265
|
phaserGameRef?.events.emit("agent:status:changed", agentId);
|
|
@@ -157752,9 +159278,9 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
157752
159278
|
agentTools.set(agentId, []);
|
|
157753
159279
|
}
|
|
157754
159280
|
if (waitingToolActive) {
|
|
157755
|
-
officeManager.setAgentWaiting(officeId, agentId);
|
|
159281
|
+
officeManager.setAgentWaiting(officeId, agentId, "turn_end_ask_user_active");
|
|
157756
159282
|
} else {
|
|
157757
|
-
officeManager.setAgentDonePendingAck(officeId, agentId);
|
|
159283
|
+
officeManager.setAgentDonePendingAck(officeId, agentId, "turn_end");
|
|
157758
159284
|
}
|
|
157759
159285
|
notifyAgent(agentId, "turnEnd");
|
|
157760
159286
|
}
|
|
@@ -157808,10 +159334,10 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
157808
159334
|
const current = officeManager.getAgentStatus(officeId, agentId);
|
|
157809
159335
|
if (status === "preloading") {
|
|
157810
159336
|
if (!current || current.state === "slacking") {
|
|
157811
|
-
officeManager.setAgentStarting(officeId, agentId);
|
|
159337
|
+
officeManager.setAgentStarting(officeId, agentId, "preload");
|
|
157812
159338
|
}
|
|
157813
159339
|
} else if (status === "ready") {
|
|
157814
|
-
officeManager.setAgentReady(officeId, agentId);
|
|
159340
|
+
officeManager.setAgentReady(officeId, agentId, "preload_ready");
|
|
157815
159341
|
const agentTools = getCurrentAgentTools();
|
|
157816
159342
|
if (agentTools.has(agentId)) {
|
|
157817
159343
|
agentTools.set(agentId, []);
|
|
@@ -157819,7 +159345,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
157819
159345
|
notifyAgent(agentId, "sessionReady");
|
|
157820
159346
|
} else if (status === "failed") {
|
|
157821
159347
|
console.warn(`[Office] Preload FAILED for ${agentId}`);
|
|
157822
|
-
officeManager.setAgentError(officeId, agentId, "Preload failed");
|
|
159348
|
+
officeManager.setAgentError(officeId, agentId, "Preload failed", "preload_failed");
|
|
157823
159349
|
notifyAgent(agentId, "sessionError");
|
|
157824
159350
|
}
|
|
157825
159351
|
}
|
|
@@ -157877,9 +159403,24 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
157877
159403
|
const staleInTurnThinking = Boolean(
|
|
157878
159404
|
current?.subState === "thinking" && thinkingSince && now - thinkingSince > STALE_IN_TURN_THINKING_TIMEOUT_MS && activeTools.length === 0
|
|
157879
159405
|
);
|
|
157880
|
-
|
|
159406
|
+
const decision = decideStartupTimeoutTransition({
|
|
159407
|
+
subState: current?.subState,
|
|
159408
|
+
activityStartTime: current?.activityStartTime,
|
|
159409
|
+
now,
|
|
159410
|
+
timeoutMs: STARTING_TIMEOUT_MS,
|
|
159411
|
+
serverAlive: serverStatus?.alive
|
|
159412
|
+
});
|
|
159413
|
+
if (decision.kind === "recover-to-ready") {
|
|
159414
|
+
console.warn(
|
|
159415
|
+
`[Office] Agent ${agent.id} stuck in starting past timeout but PTY alive \u2014 recovering to ready`
|
|
159416
|
+
);
|
|
159417
|
+
officeManager.setAgentReady(officeId, agent.id);
|
|
159418
|
+
changed = true;
|
|
159419
|
+
continue;
|
|
159420
|
+
}
|
|
159421
|
+
if (decision.kind === "transition-to-error") {
|
|
157881
159422
|
console.warn(`[Office] Agent ${agent.id} stuck in starting for >${STARTING_TIMEOUT_MS / 1e3}s \u2014 transitioning to error`);
|
|
157882
|
-
officeManager.setAgentError(officeId, agent.id,
|
|
159423
|
+
officeManager.setAgentError(officeId, agent.id, decision.reason);
|
|
157883
159424
|
changed = true;
|
|
157884
159425
|
continue;
|
|
157885
159426
|
}
|
|
@@ -158081,7 +159622,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
158081
159622
|
setupTerminalClickHandler();
|
|
158082
159623
|
function onAgentSessionClosed(agentId) {
|
|
158083
159624
|
const officeId = officeManager.currentOfficeId;
|
|
158084
|
-
if (officeId) officeManager.setAgentSlacking(officeId, agentId);
|
|
159625
|
+
if (officeId) officeManager.setAgentSlacking(officeId, agentId, "session_closed");
|
|
158085
159626
|
phaserGameRef?.events.emit("agent:status:changed", agentId);
|
|
158086
159627
|
updateTerminalContent();
|
|
158087
159628
|
updateStatusBar();
|
|
@@ -158098,7 +159639,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
158098
159639
|
console.log(`[Office] Fleet V-Team office created: ${officeId} (source: ${sourceOfficeId ?? "none"})`);
|
|
158099
159640
|
if (sourceOfficeId && window.copilotBridge?.transferSession) {
|
|
158100
159641
|
try {
|
|
158101
|
-
const result = await window.copilotBridge.transferSession(sourceOfficeId, officeId,
|
|
159642
|
+
const result = await window.copilotBridge.transferSession(sourceOfficeId, officeId, ARCHITECT_AGENT_ID);
|
|
158102
159643
|
console.log(`[Office] Arthur session transfer: ${result.success ? "OK" : result.error ?? "failed"}`);
|
|
158103
159644
|
} catch (e) {
|
|
158104
159645
|
console.warn("[Office] Failed to transfer Arthur session:", e);
|
|
@@ -158116,7 +159657,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
158116
159657
|
console.log(`[Fleet] Created fleet office: ${officeId}`);
|
|
158117
159658
|
if (window.copilotBridge?.transferSession) {
|
|
158118
159659
|
try {
|
|
158119
|
-
const result = await window.copilotBridge.transferSession(data.sourceOfficeId, officeId,
|
|
159660
|
+
const result = await window.copilotBridge.transferSession(data.sourceOfficeId, officeId, ARCHITECT_AGENT_ID);
|
|
158120
159661
|
console.log(`[Fleet] Arthur session transfer: ${result.success ? "OK" : "failed"}`, result);
|
|
158121
159662
|
} catch (e) {
|
|
158122
159663
|
console.warn("[Fleet] Failed to transfer Arthur session:", e);
|
|
@@ -158190,6 +159731,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
158190
159731
|
scene: [BootScene, OfficeScene, MeetingScene]
|
|
158191
159732
|
});
|
|
158192
159733
|
phaserGameRef = game;
|
|
159734
|
+
window.__phaserGame = game;
|
|
158193
159735
|
bindPhaserEventListeners(game);
|
|
158194
159736
|
}
|
|
158195
159737
|
function teardownPhaserGame() {
|
|
@@ -158201,9 +159743,18 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
158201
159743
|
} catch (error) {
|
|
158202
159744
|
console.warn("[main] Failed to destroy Phaser game cleanly:", error);
|
|
158203
159745
|
}
|
|
159746
|
+
delete window.__phaserGame;
|
|
158204
159747
|
officePanel.innerHTML = "";
|
|
158205
159748
|
}
|
|
158206
159749
|
bindOfficePanelListeners();
|
|
159750
|
+
officeManager.onOfficesUpdated = () => {
|
|
159751
|
+
syncActiveRosterForCurrentOffice();
|
|
159752
|
+
renderOfficeTabs();
|
|
159753
|
+
fetchSessionMeta();
|
|
159754
|
+
updateTerminalContent();
|
|
159755
|
+
updateStatusBar();
|
|
159756
|
+
void autoStartCoordinator.tryWarmCurrentOffice();
|
|
159757
|
+
};
|
|
158207
159758
|
window.addEventListener("focus", () => {
|
|
158208
159759
|
catchUpStatusViews("window focus");
|
|
158209
159760
|
});
|