copilotoffice 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +225 -192
- package/bin/copilotoffice.js +39 -39
- package/dist/electron/main.js +599 -126
- package/dist/electron/terminal/events-watcher.js +53 -2
- package/dist/electron/terminal/ipc-relay.js +49 -1
- package/dist/electron/terminal/preload.js +57 -13
- package/dist/electron/terminal/server.js +6125 -940
- package/dist/game.bundle.js +611 -206
- package/package.json +62 -58
- package/src/index.html +44 -44
package/dist/game.bundle.js
CHANGED
|
@@ -141772,23 +141772,173 @@ var CopilotOffice = (() => {
|
|
|
141772
141772
|
}
|
|
141773
141773
|
});
|
|
141774
141774
|
|
|
141775
|
+
// src/config/agentStatusPresentation.ts
|
|
141776
|
+
function resolveStatusKey(status) {
|
|
141777
|
+
if (!status || status.state === "slacking") return "slacking";
|
|
141778
|
+
switch (status.subState) {
|
|
141779
|
+
case "starting":
|
|
141780
|
+
return "starting";
|
|
141781
|
+
case "ready":
|
|
141782
|
+
return status.completionPendingAck ? "done" : "ready";
|
|
141783
|
+
case "waiting":
|
|
141784
|
+
return "waiting";
|
|
141785
|
+
case "thinking":
|
|
141786
|
+
return "thinking";
|
|
141787
|
+
case "error":
|
|
141788
|
+
return "error";
|
|
141789
|
+
default:
|
|
141790
|
+
return "slacking";
|
|
141791
|
+
}
|
|
141792
|
+
}
|
|
141793
|
+
function computeStall(status, now = Date.now()) {
|
|
141794
|
+
if (!status || !status.activityStartTime) return NOT_STALLED;
|
|
141795
|
+
const key = resolveStatusKey(status);
|
|
141796
|
+
const pres = STATUS_PRESENTATION[key];
|
|
141797
|
+
if (!pres.isActive || key === "error") return NOT_STALLED;
|
|
141798
|
+
if (now - status.activityStartTime < STALL_THRESHOLD_MS) return NOT_STALLED;
|
|
141799
|
+
return {
|
|
141800
|
+
isStalled: true,
|
|
141801
|
+
stallColorHex: STALL_COLOR_HEX,
|
|
141802
|
+
stallColorNum: STALL_COLOR_NUM,
|
|
141803
|
+
stallStrokeNum: STALL_STROKE_NUM
|
|
141804
|
+
};
|
|
141805
|
+
}
|
|
141806
|
+
function describeActivity(status) {
|
|
141807
|
+
if (!status) return "";
|
|
141808
|
+
const key = resolveStatusKey(status);
|
|
141809
|
+
if (key !== "waiting" && key !== "starting") return "";
|
|
141810
|
+
const detail = status.thinkingDetail?.trim();
|
|
141811
|
+
if (detail) return detail;
|
|
141812
|
+
const tool = status.currentTool?.trim();
|
|
141813
|
+
if (tool) return friendlyToolName(tool);
|
|
141814
|
+
return key === "waiting" ? "Waiting for your answer" : "Working\u2026";
|
|
141815
|
+
}
|
|
141816
|
+
function friendlyToolName(tool) {
|
|
141817
|
+
const normalized = tool.trim().toLowerCase();
|
|
141818
|
+
const map = {
|
|
141819
|
+
ask_user: "Waiting for your answer",
|
|
141820
|
+
edit: "Editing a file",
|
|
141821
|
+
create: "Creating a file",
|
|
141822
|
+
view: "Reading a file",
|
|
141823
|
+
grep: "Searching",
|
|
141824
|
+
glob: "Finding files",
|
|
141825
|
+
powershell: "Running a command",
|
|
141826
|
+
bash: "Running a command"
|
|
141827
|
+
};
|
|
141828
|
+
return map[normalized] ?? tool;
|
|
141829
|
+
}
|
|
141830
|
+
function formatElapsedMmSs(startTime, now = Date.now()) {
|
|
141831
|
+
if (!startTime) return "";
|
|
141832
|
+
const totalSeconds = Math.max(0, Math.floor((now - startTime) / 1e3));
|
|
141833
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
141834
|
+
const seconds = totalSeconds % 60;
|
|
141835
|
+
return `${minutes}:${seconds.toString().padStart(2, "0")}`;
|
|
141836
|
+
}
|
|
141837
|
+
var STATUS_PRESENTATION, STALL_THRESHOLD_MS, STALL_COLOR_HEX, STALL_COLOR_NUM, STALL_STROKE_NUM, NOT_STALLED;
|
|
141838
|
+
var init_agentStatusPresentation = __esm({
|
|
141839
|
+
"src/config/agentStatusPresentation.ts"() {
|
|
141840
|
+
"use strict";
|
|
141841
|
+
STATUS_PRESENTATION = {
|
|
141842
|
+
slacking: {
|
|
141843
|
+
key: "slacking",
|
|
141844
|
+
label: "Slacking",
|
|
141845
|
+
shortLabel: "Slacking",
|
|
141846
|
+
colorHex: "#555555",
|
|
141847
|
+
colorNum: 5592405,
|
|
141848
|
+
strokeNum: 6710886,
|
|
141849
|
+
icon: "\u{1F4A4}",
|
|
141850
|
+
badgeAnimation: "none",
|
|
141851
|
+
isActive: false
|
|
141852
|
+
},
|
|
141853
|
+
starting: {
|
|
141854
|
+
key: "starting",
|
|
141855
|
+
label: "Starting\u2026",
|
|
141856
|
+
shortLabel: "Starting",
|
|
141857
|
+
colorHex: "#ff9944",
|
|
141858
|
+
colorNum: 16750916,
|
|
141859
|
+
strokeNum: 16759654,
|
|
141860
|
+
icon: "\u{1F680}",
|
|
141861
|
+
badgeAnimation: "pulse",
|
|
141862
|
+
isActive: true
|
|
141863
|
+
},
|
|
141864
|
+
ready: {
|
|
141865
|
+
key: "ready",
|
|
141866
|
+
label: "Ready",
|
|
141867
|
+
shortLabel: "Ready",
|
|
141868
|
+
colorHex: "#ffffff",
|
|
141869
|
+
colorNum: 16777215,
|
|
141870
|
+
strokeNum: 14540253,
|
|
141871
|
+
icon: "\u{1F4ED}",
|
|
141872
|
+
badgeAnimation: "none",
|
|
141873
|
+
isActive: false
|
|
141874
|
+
},
|
|
141875
|
+
done: {
|
|
141876
|
+
key: "done",
|
|
141877
|
+
label: "Done",
|
|
141878
|
+
shortLabel: "Done",
|
|
141879
|
+
colorHex: "#4a78ff",
|
|
141880
|
+
colorNum: 4880639,
|
|
141881
|
+
strokeNum: 7049471,
|
|
141882
|
+
icon: "\u{1F4EC}",
|
|
141883
|
+
badgeAnimation: "none",
|
|
141884
|
+
isActive: false
|
|
141885
|
+
},
|
|
141886
|
+
waiting: {
|
|
141887
|
+
key: "waiting",
|
|
141888
|
+
label: "Waiting for input",
|
|
141889
|
+
shortLabel: "Waiting",
|
|
141890
|
+
colorHex: "#ffb86c",
|
|
141891
|
+
colorNum: 16758892,
|
|
141892
|
+
strokeNum: 16764040,
|
|
141893
|
+
icon: "\u23F3",
|
|
141894
|
+
badgeAnimation: "none",
|
|
141895
|
+
isActive: true
|
|
141896
|
+
},
|
|
141897
|
+
thinking: {
|
|
141898
|
+
key: "thinking",
|
|
141899
|
+
label: "Thinking\u2026",
|
|
141900
|
+
shortLabel: "Thinking\u2026",
|
|
141901
|
+
colorHex: "#50fa7b",
|
|
141902
|
+
colorNum: 5307003,
|
|
141903
|
+
strokeNum: 6750105,
|
|
141904
|
+
icon: "\u{1F9E0}",
|
|
141905
|
+
badgeAnimation: "pulse",
|
|
141906
|
+
isActive: true
|
|
141907
|
+
},
|
|
141908
|
+
error: {
|
|
141909
|
+
key: "error",
|
|
141910
|
+
label: "Error",
|
|
141911
|
+
shortLabel: "Error",
|
|
141912
|
+
colorHex: "#ff4444",
|
|
141913
|
+
colorNum: 16729156,
|
|
141914
|
+
strokeNum: 16737894,
|
|
141915
|
+
icon: "\u274C",
|
|
141916
|
+
badgeAnimation: "none",
|
|
141917
|
+
isActive: true
|
|
141918
|
+
}
|
|
141919
|
+
};
|
|
141920
|
+
STALL_THRESHOLD_MS = 6e4;
|
|
141921
|
+
STALL_COLOR_HEX = "#ffb020";
|
|
141922
|
+
STALL_COLOR_NUM = 16756768;
|
|
141923
|
+
STALL_STROKE_NUM = 16762967;
|
|
141924
|
+
NOT_STALLED = {
|
|
141925
|
+
isStalled: false,
|
|
141926
|
+
stallColorHex: STALL_COLOR_HEX,
|
|
141927
|
+
stallColorNum: STALL_COLOR_NUM,
|
|
141928
|
+
stallStrokeNum: STALL_STROKE_NUM
|
|
141929
|
+
};
|
|
141930
|
+
}
|
|
141931
|
+
});
|
|
141932
|
+
|
|
141775
141933
|
// src/entities/NPC.ts
|
|
141776
|
-
var import_phaser3,
|
|
141934
|
+
var import_phaser3, NPC;
|
|
141777
141935
|
var init_NPC = __esm({
|
|
141778
141936
|
"src/entities/NPC.ts"() {
|
|
141779
141937
|
"use strict";
|
|
141780
141938
|
import_phaser3 = __toESM(require_phaser());
|
|
141781
141939
|
init_depths();
|
|
141940
|
+
init_agentStatusPresentation();
|
|
141782
141941
|
init_DirectionalSprite();
|
|
141783
|
-
BADGE_COLORS = {
|
|
141784
|
-
slacking: { fill: 5592405, stroke: 6710886 },
|
|
141785
|
-
starting: { fill: 16750916, stroke: 16759654 },
|
|
141786
|
-
ready: { fill: 16777215, stroke: 14540253 },
|
|
141787
|
-
done: { fill: 4880639, stroke: 7049471 },
|
|
141788
|
-
waiting: { fill: 16758892, stroke: 16764040 },
|
|
141789
|
-
thinking: { fill: 5307003, stroke: 6750105 },
|
|
141790
|
-
error: { fill: 16729156, stroke: 16737894 }
|
|
141791
|
-
};
|
|
141792
141942
|
NPC = class extends import_phaser3.default.Physics.Arcade.Sprite {
|
|
141793
141943
|
constructor(scene, config, tileSize, spriteScale = 1) {
|
|
141794
141944
|
const x = config.position.x * tileSize + tileSize / 2;
|
|
@@ -141797,6 +141947,8 @@ var CopilotOffice = (() => {
|
|
|
141797
141947
|
this._isHighlighted = false;
|
|
141798
141948
|
this.highlightTween = null;
|
|
141799
141949
|
this.badgePulseTween = null;
|
|
141950
|
+
this.stallTween = null;
|
|
141951
|
+
this.isStalled = false;
|
|
141800
141952
|
this.isNearPlayer = false;
|
|
141801
141953
|
this.hasActiveSession = false;
|
|
141802
141954
|
this.currentBadgeState = "slacking";
|
|
@@ -141862,13 +142014,19 @@ var CopilotOffice = (() => {
|
|
|
141862
142014
|
this.sessionBadge.setPosition(x + 16 * spriteScale, y - 24 * spriteScale);
|
|
141863
142015
|
this.sessionBadge.setDepth(Depths.BADGES);
|
|
141864
142016
|
this.updateSessionBadge(spriteScale);
|
|
141865
|
-
this.sessionText = scene.add.text(x + 16 * spriteScale, y - 24 * spriteScale,
|
|
142017
|
+
this.sessionText = scene.add.text(x + 16 * spriteScale, y - 24 * spriteScale, STATUS_PRESENTATION.slacking.icon, {
|
|
141866
142018
|
font: `bold ${badgeFontSize * 4}px monospace`,
|
|
141867
142019
|
color: "#ffffff"
|
|
141868
142020
|
});
|
|
141869
142021
|
this.sessionText.setOrigin(0.5, 0.5);
|
|
141870
142022
|
this.sessionText.setVisible(true);
|
|
141871
142023
|
this.sessionText.setDepth(Depths.BADGES + 1);
|
|
142024
|
+
this.stallRing = scene.add.graphics();
|
|
142025
|
+
this.stallRing.setPosition(x + 16 * spriteScale, y - 24 * spriteScale);
|
|
142026
|
+
this.stallRing.setDepth(Depths.BADGES + 2);
|
|
142027
|
+
this.stallRing.setVisible(false);
|
|
142028
|
+
this.stallRing.lineStyle(2.5, 16756768, 0.95);
|
|
142029
|
+
this.stallRing.strokeCircle(0, 0, 20 * spriteScale);
|
|
141872
142030
|
this.indicator = scene.add.sprite(x, y - 48 * spriteScale, "indicator");
|
|
141873
142031
|
this.indicator.setScale(0.6 * spriteScale);
|
|
141874
142032
|
this.indicator.setVisible(false);
|
|
@@ -141887,10 +142045,11 @@ var CopilotOffice = (() => {
|
|
|
141887
142045
|
updateSessionBadge(scale = 1) {
|
|
141888
142046
|
this.sessionBadge.clear();
|
|
141889
142047
|
const stateKey = this.currentBadgeState;
|
|
141890
|
-
const
|
|
141891
|
-
|
|
142048
|
+
const pres = STATUS_PRESENTATION[stateKey] ?? STATUS_PRESENTATION.slacking;
|
|
142049
|
+
const isSlacking = stateKey === "slacking";
|
|
142050
|
+
this.sessionBadge.fillStyle(pres.colorNum, isSlacking ? 0.7 : 1);
|
|
141892
142051
|
this.sessionBadge.fillCircle(0, 0, 16 * scale);
|
|
141893
|
-
this.sessionBadge.lineStyle(2,
|
|
142052
|
+
this.sessionBadge.lineStyle(2, pres.strokeNum, isSlacking ? 0.5 : 1);
|
|
141894
142053
|
this.sessionBadge.strokeCircle(0, 0, 16 * scale);
|
|
141895
142054
|
}
|
|
141896
142055
|
_drawHighlightRing(color, scale) {
|
|
@@ -141957,8 +142116,9 @@ var CopilotOffice = (() => {
|
|
|
141957
142116
|
setHasActiveSession(hasSession, messageCount) {
|
|
141958
142117
|
this.hasActiveSession = hasSession;
|
|
141959
142118
|
if (!hasSession) {
|
|
142119
|
+
this.setStalled(false);
|
|
141960
142120
|
this.updateBadgeForState("slacking");
|
|
141961
|
-
this.sessionText.setText(
|
|
142121
|
+
this.sessionText.setText(STATUS_PRESENTATION.slacking.icon);
|
|
141962
142122
|
if (!this.badgeHidden) {
|
|
141963
142123
|
this.sessionText.setVisible(true);
|
|
141964
142124
|
}
|
|
@@ -141978,6 +142138,7 @@ var CopilotOffice = (() => {
|
|
|
141978
142138
|
this.badgeHidden = !visible;
|
|
141979
142139
|
this.sessionBadge.setVisible(visible);
|
|
141980
142140
|
this.sessionText.setVisible(visible);
|
|
142141
|
+
this.stallRing.setVisible(visible && this.isStalled);
|
|
141981
142142
|
}
|
|
141982
142143
|
/** Toggle visibility of name and description labels. */
|
|
141983
142144
|
setLabelsVisible(visible) {
|
|
@@ -141988,29 +142149,57 @@ var CopilotOffice = (() => {
|
|
|
141988
142149
|
updateAgentStatus(status) {
|
|
141989
142150
|
if (!status || status.state === "slacking") {
|
|
141990
142151
|
this.hasActiveSession = false;
|
|
142152
|
+
this.setStalled(false);
|
|
141991
142153
|
this.updateBadgeForState("slacking");
|
|
141992
|
-
this.sessionText.setText(
|
|
142154
|
+
this.sessionText.setText(STATUS_PRESENTATION.slacking.icon);
|
|
141993
142155
|
if (!this.badgeHidden) {
|
|
141994
142156
|
this.sessionText.setVisible(true);
|
|
141995
142157
|
}
|
|
141996
142158
|
return;
|
|
141997
142159
|
}
|
|
141998
142160
|
this.hasActiveSession = true;
|
|
141999
|
-
const stateKey = status
|
|
142161
|
+
const stateKey = resolveStatusKey(status);
|
|
142000
142162
|
this.updateBadgeForState(stateKey);
|
|
142001
|
-
|
|
142002
|
-
starting: "\u{1F680}",
|
|
142003
|
-
ready: "\u{1F4ED}",
|
|
142004
|
-
done: "\u{1F4EC}",
|
|
142005
|
-
waiting: "\u23F3",
|
|
142006
|
-
thinking: "\u{1F9E0}",
|
|
142007
|
-
error: "\u274C"
|
|
142008
|
-
};
|
|
142009
|
-
this.sessionText.setText(icons[stateKey] || "");
|
|
142163
|
+
this.sessionText.setText(STATUS_PRESENTATION[stateKey].icon || "");
|
|
142010
142164
|
if (!this.badgeHidden) {
|
|
142011
142165
|
this.sessionText.setVisible(stateKey !== "slacking");
|
|
142012
142166
|
}
|
|
142013
142167
|
}
|
|
142168
|
+
/**
|
|
142169
|
+
* FR-013: toggle the ~60s stall treatment. Shows an amber ring on a slower,
|
|
142170
|
+
* "laboring" pulse cadence (distinct from the normal in-progress pulse and
|
|
142171
|
+
* from the error state). Clearing it restores the badge to normal. Idempotent.
|
|
142172
|
+
*/
|
|
142173
|
+
setStalled(on2) {
|
|
142174
|
+
if (this.isStalled === on2) return;
|
|
142175
|
+
this.isStalled = on2;
|
|
142176
|
+
if (this.stallTween) {
|
|
142177
|
+
this.stallTween.stop();
|
|
142178
|
+
this.stallTween = null;
|
|
142179
|
+
}
|
|
142180
|
+
if (on2) {
|
|
142181
|
+
this.stallRing.setScale(1);
|
|
142182
|
+
this.stallRing.setAlpha(1);
|
|
142183
|
+
this.stallRing.setVisible(!this.badgeHidden);
|
|
142184
|
+
this.stallTween = this.scene.tweens.add({
|
|
142185
|
+
targets: this.stallRing,
|
|
142186
|
+
scaleX: { from: 0.85, to: 1.18 },
|
|
142187
|
+
scaleY: { from: 0.85, to: 1.18 },
|
|
142188
|
+
alpha: { from: 0.55, to: 1 },
|
|
142189
|
+
duration: 1100,
|
|
142190
|
+
yoyo: true,
|
|
142191
|
+
repeat: -1,
|
|
142192
|
+
ease: "Sine.easeInOut"
|
|
142193
|
+
});
|
|
142194
|
+
} else {
|
|
142195
|
+
this.stallRing.setScale(1);
|
|
142196
|
+
this.stallRing.setVisible(false);
|
|
142197
|
+
}
|
|
142198
|
+
}
|
|
142199
|
+
/** True while the stall treatment is active (test/inspection aid). */
|
|
142200
|
+
get stalled() {
|
|
142201
|
+
return this.isStalled;
|
|
142202
|
+
}
|
|
142014
142203
|
updateBadgeForState(stateKey) {
|
|
142015
142204
|
if (this.currentBadgeState === stateKey) return;
|
|
142016
142205
|
this.currentBadgeState = stateKey;
|
|
@@ -142020,7 +142209,8 @@ var CopilotOffice = (() => {
|
|
|
142020
142209
|
}
|
|
142021
142210
|
this.sessionBadge.setScale(1);
|
|
142022
142211
|
this.updateSessionBadge(this.spriteScale);
|
|
142023
|
-
|
|
142212
|
+
const pres = STATUS_PRESENTATION[stateKey];
|
|
142213
|
+
if (pres?.badgeAnimation === "pulse") {
|
|
142024
142214
|
this.badgePulseTween = this.scene.tweens.add({
|
|
142025
142215
|
targets: this.sessionBadge,
|
|
142026
142216
|
scaleX: { from: 0.925, to: 1.075 },
|
|
@@ -142084,6 +142274,7 @@ var CopilotOffice = (() => {
|
|
|
142084
142274
|
this.descriptionLabel.setPosition(x, y - 28 * s15);
|
|
142085
142275
|
this.sessionBadge.setPosition(x + 16 * s15, y - 24 * s15);
|
|
142086
142276
|
this.sessionText.setPosition(x + 16 * s15, y - 24 * s15);
|
|
142277
|
+
this.stallRing.setPosition(x + 16 * s15, y - 24 * s15);
|
|
142087
142278
|
this.indicator.setPosition(x, this.indicator.y);
|
|
142088
142279
|
this.highlightGlow.setPosition(x, y);
|
|
142089
142280
|
this.highlightRing.setPosition(x, y);
|
|
@@ -142096,6 +142287,7 @@ var CopilotOffice = (() => {
|
|
|
142096
142287
|
this.highlightRing.destroy();
|
|
142097
142288
|
this.sessionBadge.destroy();
|
|
142098
142289
|
this.sessionText.destroy();
|
|
142290
|
+
this.stallRing.destroy();
|
|
142099
142291
|
super.destroy(fromScene);
|
|
142100
142292
|
}
|
|
142101
142293
|
};
|
|
@@ -151349,6 +151541,12 @@ ${h2.join(`
|
|
|
151349
151541
|
if (cfg.teamsChannelUrl !== void 0) {
|
|
151350
151542
|
normalized.teamsChannelUrl = cfg.teamsChannelUrl;
|
|
151351
151543
|
}
|
|
151544
|
+
if (cfg.teamsMentionType !== void 0) {
|
|
151545
|
+
normalized.teamsMentionType = cfg.teamsMentionType;
|
|
151546
|
+
}
|
|
151547
|
+
if (cfg.teamsMentionValue !== void 0) {
|
|
151548
|
+
normalized.teamsMentionValue = cfg.teamsMentionValue;
|
|
151549
|
+
}
|
|
151352
151550
|
offices.push(normalized);
|
|
151353
151551
|
}
|
|
151354
151552
|
let currentOfficeId = null;
|
|
@@ -151536,6 +151734,8 @@ ${h2.join(`
|
|
|
151536
151734
|
if (updates.workingDirectory !== void 0) office.config.workingDirectory = updates.workingDirectory;
|
|
151537
151735
|
if (updates.layout !== void 0) office.config.layout = updates.layout;
|
|
151538
151736
|
if (updates.teamsChannelUrl !== void 0) office.config.teamsChannelUrl = updates.teamsChannelUrl;
|
|
151737
|
+
if (updates.teamsMentionType !== void 0) office.config.teamsMentionType = updates.teamsMentionType;
|
|
151738
|
+
if (updates.teamsMentionValue !== void 0) office.config.teamsMentionValue = updates.teamsMentionValue;
|
|
151539
151739
|
this.saveToStorage();
|
|
151540
151740
|
this.onOfficesUpdated?.();
|
|
151541
151741
|
return true;
|
|
@@ -151637,7 +151837,7 @@ ${h2.join(`
|
|
|
151637
151837
|
if (currentOfficeId && this.offices.has(currentOfficeId)) {
|
|
151638
151838
|
this._currentOfficeId = currentOfficeId;
|
|
151639
151839
|
} else if (this.offices.size > 0) {
|
|
151640
|
-
this._currentOfficeId = this.offices.keys().next().value;
|
|
151840
|
+
this._currentOfficeId = this.offices.keys().next().value ?? null;
|
|
151641
151841
|
}
|
|
151642
151842
|
}
|
|
151643
151843
|
// Agent status helpers
|
|
@@ -151768,7 +151968,7 @@ ${h2.join(`
|
|
|
151768
151968
|
status.thinkingDetail = detail;
|
|
151769
151969
|
const office = this.offices.get(officeId);
|
|
151770
151970
|
const tools = office?.agentTools.get(agentId);
|
|
151771
|
-
status.currentTool = tools?.length ? tools[tools.length - 1].name : null;
|
|
151971
|
+
status.currentTool = tools?.length ? tools[tools.length - 1].name ?? null : null;
|
|
151772
151972
|
status.completionPendingAck = false;
|
|
151773
151973
|
if (!status.activityStartTime) status.activityStartTime = Date.now();
|
|
151774
151974
|
this.emitLifecycleTransition(officeId, agentId, status, from, reason, detail ?? void 0);
|
|
@@ -151867,7 +152067,7 @@ ${h2.join(`
|
|
|
151867
152067
|
document.body.appendChild(el2);
|
|
151868
152068
|
return el2;
|
|
151869
152069
|
}
|
|
151870
|
-
function showClipboardToast(message, kind = "info") {
|
|
152070
|
+
function showClipboardToast(message, kind = "info", durationMs = TOAST_DURATION_MS) {
|
|
151871
152071
|
const el2 = ensureToastElement();
|
|
151872
152072
|
if (!el2) return;
|
|
151873
152073
|
el2.textContent = message;
|
|
@@ -151876,7 +152076,7 @@ ${h2.join(`
|
|
|
151876
152076
|
if (dismissTimer) clearTimeout(dismissTimer);
|
|
151877
152077
|
dismissTimer = setTimeout(() => {
|
|
151878
152078
|
el2.style.opacity = "0";
|
|
151879
|
-
},
|
|
152079
|
+
}, durationMs);
|
|
151880
152080
|
}
|
|
151881
152081
|
var TOAST_ID, TOAST_DURATION_MS, dismissTimer, KIND_BG;
|
|
151882
152082
|
var init_clipboardToast = __esm({
|
|
@@ -152539,6 +152739,7 @@ ${h2.join(`
|
|
|
152539
152739
|
this.wheelPager = new WheelPager();
|
|
152540
152740
|
this.resizeObserver = null;
|
|
152541
152741
|
this.refitTimers = [];
|
|
152742
|
+
this.refitRaf = null;
|
|
152542
152743
|
this.refitGeneration = 0;
|
|
152543
152744
|
this.attachedOfficeId = null;
|
|
152544
152745
|
this.isReadOnly = false;
|
|
@@ -152554,6 +152755,14 @@ ${h2.join(`
|
|
|
152554
152755
|
// Disposable returned by xterm.terminal.onData(...). Re-registered per show()
|
|
152555
152756
|
// so the handler's closure captures the new agent id (feature 002, C3/V6).
|
|
152556
152757
|
this.onDataDisposable = null;
|
|
152758
|
+
// Unsubscribe functions for the bridge IPC listeners this overlay owns
|
|
152759
|
+
// (terminal-data, terminal-exit, session-meta-updated). Disposed and
|
|
152760
|
+
// re-created on every setupTerminalListeners() call so an overlay can never
|
|
152761
|
+
// accumulate duplicate listeners — duplicates would write each PTY byte to
|
|
152762
|
+
// xterm more than once (the "double characters" bug).
|
|
152763
|
+
this.bridgeListenerDisposers = [];
|
|
152764
|
+
// Teams status listener has no disposer on the bridge; bind it at most once.
|
|
152765
|
+
this.teamsListenerBound = false;
|
|
152557
152766
|
// Toggled while show() is awaiting detach/attach so onData cannot fire input
|
|
152558
152767
|
// against a half-attached agent (feature 002, V5).
|
|
152559
152768
|
this.isSwitchingAgent = false;
|
|
@@ -152582,35 +152791,50 @@ ${h2.join(`
|
|
|
152582
152791
|
}
|
|
152583
152792
|
setupTerminalListeners() {
|
|
152584
152793
|
if (typeof window !== "undefined" && window.copilotBridge) {
|
|
152585
|
-
|
|
152586
|
-
|
|
152587
|
-
|
|
152588
|
-
|
|
152794
|
+
for (const dispose of this.bridgeListenerDisposers) {
|
|
152795
|
+
try {
|
|
152796
|
+
dispose();
|
|
152797
|
+
} catch {
|
|
152589
152798
|
}
|
|
152590
|
-
}
|
|
152591
|
-
|
|
152592
|
-
|
|
152593
|
-
|
|
152799
|
+
}
|
|
152800
|
+
this.bridgeListenerDisposers = [];
|
|
152801
|
+
this.bridgeListenerDisposers.push(
|
|
152802
|
+
window.copilotBridge.onTerminalData((agentId, data) => {
|
|
152803
|
+
if (this.isReplaying) return;
|
|
152804
|
+
if (agentId === this.currentAgentId && this.terminal) {
|
|
152805
|
+
this.terminal.write(data);
|
|
152806
|
+
}
|
|
152807
|
+
})
|
|
152808
|
+
);
|
|
152809
|
+
this.bridgeListenerDisposers.push(
|
|
152810
|
+
window.copilotBridge.onTerminalExit((agentId, exitCode) => {
|
|
152811
|
+
if (agentId === this.currentAgentId && this.terminal) {
|
|
152812
|
+
this.terminal.writeln(`\r
|
|
152594
152813
|
[Process exited with code ${exitCode}]`);
|
|
152595
|
-
|
|
152596
|
-
|
|
152597
|
-
|
|
152598
|
-
|
|
152599
|
-
|
|
152600
|
-
|
|
152601
|
-
|
|
152602
|
-
|
|
152603
|
-
|
|
152604
|
-
|
|
152605
|
-
|
|
152606
|
-
|
|
152814
|
+
}
|
|
152815
|
+
})
|
|
152816
|
+
);
|
|
152817
|
+
this.bridgeListenerDisposers.push(
|
|
152818
|
+
window.copilotBridge.onSessionMetaUpdated((agentId, meta) => {
|
|
152819
|
+
if (agentId === this.currentAgentId) {
|
|
152820
|
+
this.updateSessionTitleDisplay(meta?.title || null);
|
|
152821
|
+
}
|
|
152822
|
+
})
|
|
152823
|
+
);
|
|
152824
|
+
if (!this.teamsListenerBound) {
|
|
152825
|
+
window.copilotBridge.onTeamsStatusChanged?.((status) => {
|
|
152826
|
+
if (status?.agentId === this.currentAgentId) {
|
|
152827
|
+
this.setTeamsButtonState(!!status.online);
|
|
152828
|
+
}
|
|
152829
|
+
});
|
|
152830
|
+
this.teamsListenerBound = true;
|
|
152831
|
+
}
|
|
152607
152832
|
}
|
|
152608
152833
|
}
|
|
152609
152834
|
/**
|
|
152610
|
-
* Re-register IPC listeners
|
|
152611
|
-
*
|
|
152612
|
-
*
|
|
152613
|
-
* all guard on `this.currentAgentId`.
|
|
152835
|
+
* Re-register this overlay's IPC listeners. setupTerminalListeners() is
|
|
152836
|
+
* idempotent (it disposes prior registrations first), so calling this after
|
|
152837
|
+
* returning from another scene cannot create duplicate listeners.
|
|
152614
152838
|
*/
|
|
152615
152839
|
reattachListeners() {
|
|
152616
152840
|
this.setupTerminalListeners();
|
|
@@ -152626,6 +152850,10 @@ ${h2.join(`
|
|
|
152626
152850
|
return this.attachedOfficeId ?? this.getOfficeId();
|
|
152627
152851
|
}
|
|
152628
152852
|
clearRefitTimers() {
|
|
152853
|
+
if (this.refitRaf !== null) {
|
|
152854
|
+
cancelAnimationFrame(this.refitRaf);
|
|
152855
|
+
this.refitRaf = null;
|
|
152856
|
+
}
|
|
152629
152857
|
for (const timer of this.refitTimers) {
|
|
152630
152858
|
clearTimeout(timer);
|
|
152631
152859
|
}
|
|
@@ -152724,7 +152952,7 @@ ${h2.join(`
|
|
|
152724
152952
|
const dims = this.resolveTerminalDimensions();
|
|
152725
152953
|
if (!dims) return null;
|
|
152726
152954
|
const agentId = options?.agentId ?? this.currentAgentId;
|
|
152727
|
-
if (!agentId || !window.copilotBridge) return dims;
|
|
152955
|
+
if (!agentId || typeof window === "undefined" || !window.copilotBridge) return dims;
|
|
152728
152956
|
const officeId = options?.officeId ?? this.getActiveOfficeId();
|
|
152729
152957
|
void window.copilotBridge.terminalResize(officeId, agentId, dims.cols, dims.rows).catch(() => {
|
|
152730
152958
|
});
|
|
@@ -152837,6 +153065,7 @@ ${h2.join(`
|
|
|
152837
153065
|
if (previousAgentId && previousAgentId !== agent.id) {
|
|
152838
153066
|
this.acknowledgeCompletedWork(previousOfficeId, previousAgentId);
|
|
152839
153067
|
}
|
|
153068
|
+
this.acknowledgeCompletedWork(nextOfficeId, agent.id);
|
|
152840
153069
|
if (isSwitchingAgent && previousAgentId && window.copilotBridge) {
|
|
152841
153070
|
this.isSwitchingAgent = true;
|
|
152842
153071
|
this.onDataDisposable?.dispose();
|
|
@@ -152948,7 +153177,7 @@ ${h2.join(`
|
|
|
152948
153177
|
} else {
|
|
152949
153178
|
this.fitAndResizeTerminal({ officeId, agentId: agent.id });
|
|
152950
153179
|
const attachResult = await withTimeout(
|
|
152951
|
-
window.copilotBridge.terminalAttach(officeId, agent.id),
|
|
153180
|
+
window.copilotBridge.terminalAttach(officeId, agent.id, true),
|
|
152952
153181
|
IPC_TIMEOUT,
|
|
152953
153182
|
"terminalAttach"
|
|
152954
153183
|
);
|
|
@@ -153385,14 +153614,17 @@ ${h2.join(`
|
|
|
153385
153614
|
return;
|
|
153386
153615
|
}
|
|
153387
153616
|
this.setTeamsButtonState(false, true);
|
|
153388
|
-
const
|
|
153617
|
+
const office = officeManager.getOffice(officeId)?.config;
|
|
153618
|
+
const officeChannelUrl = office?.teamsChannelUrl;
|
|
153389
153619
|
const workingDir = this.currentAgent.workingDir || officeManager.getCurrentWorkingDirectory();
|
|
153390
153620
|
const res = await window.copilotBridge.teamsRegister({
|
|
153391
153621
|
officeId,
|
|
153392
153622
|
agentId,
|
|
153393
153623
|
displayName: this.currentAgent.name,
|
|
153394
153624
|
workingDir,
|
|
153395
|
-
officeChannelUrl
|
|
153625
|
+
officeChannelUrl,
|
|
153626
|
+
officeMentionType: office?.teamsMentionType,
|
|
153627
|
+
officeMentionValue: office?.teamsMentionValue
|
|
153396
153628
|
});
|
|
153397
153629
|
if (res?.success) {
|
|
153398
153630
|
this.setTeamsButtonState(true);
|
|
@@ -153923,7 +154155,8 @@ ${h2.join(`
|
|
|
153923
154155
|
if (this.getActiveOfficeId() !== officeId) return;
|
|
153924
154156
|
this.fitAndResizeTerminal({ officeId, agentId });
|
|
153925
154157
|
};
|
|
153926
|
-
requestAnimationFrame(() => {
|
|
154158
|
+
this.refitRaf = requestAnimationFrame(() => {
|
|
154159
|
+
this.refitRaf = null;
|
|
153927
154160
|
doFit();
|
|
153928
154161
|
this.refitTimers.push(setTimeout(() => {
|
|
153929
154162
|
doFit();
|
|
@@ -154107,9 +154340,13 @@ ${h2.join(`
|
|
|
154107
154340
|
} catch {
|
|
154108
154341
|
}
|
|
154109
154342
|
this.spriteCardElement = null;
|
|
154110
|
-
|
|
154111
|
-
|
|
154343
|
+
for (const dispose of this.bridgeListenerDisposers) {
|
|
154344
|
+
try {
|
|
154345
|
+
dispose();
|
|
154346
|
+
} catch {
|
|
154347
|
+
}
|
|
154112
154348
|
}
|
|
154349
|
+
this.bridgeListenerDisposers = [];
|
|
154113
154350
|
}
|
|
154114
154351
|
};
|
|
154115
154352
|
}
|
|
@@ -155095,6 +155332,7 @@ ${h2.join(`
|
|
|
155095
155332
|
"src/layouts/default/DefaultDashboard.ts"() {
|
|
155096
155333
|
"use strict";
|
|
155097
155334
|
init_types();
|
|
155335
|
+
init_agentStatusPresentation();
|
|
155098
155336
|
defaultDashboard = {
|
|
155099
155337
|
renderCards(ctx) {
|
|
155100
155338
|
const { agents, office, selectedAgentId, cachedSessionMeta, agentTools, formatElapsed, formatRelativeTime } = ctx;
|
|
@@ -155143,46 +155381,12 @@ ${h2.join(`
|
|
|
155143
155381
|
for (const agent of agents) {
|
|
155144
155382
|
const liveStatus = office?.agents.get(agent.id);
|
|
155145
155383
|
const tools = agentTools.get(agent.id) || [];
|
|
155146
|
-
|
|
155147
|
-
|
|
155148
|
-
|
|
155149
|
-
|
|
155150
|
-
|
|
155151
|
-
|
|
155152
|
-
case "starting":
|
|
155153
|
-
statusDot = "#ff9944";
|
|
155154
|
-
statusLabel = "Starting...";
|
|
155155
|
-
statusIcon = "\u{1F680}";
|
|
155156
|
-
break;
|
|
155157
|
-
case "ready":
|
|
155158
|
-
if (liveStatus.completionPendingAck) {
|
|
155159
|
-
statusDot = "#4a78ff";
|
|
155160
|
-
statusLabel = "Done";
|
|
155161
|
-
statusIcon = "\u{1F4EC}";
|
|
155162
|
-
} else {
|
|
155163
|
-
statusDot = "#ffffff";
|
|
155164
|
-
statusLabel = "Ready";
|
|
155165
|
-
statusIcon = "\u{1F4ED}";
|
|
155166
|
-
}
|
|
155167
|
-
break;
|
|
155168
|
-
case "waiting":
|
|
155169
|
-
statusDot = "#ffb86c";
|
|
155170
|
-
statusLabel = "Waiting for input";
|
|
155171
|
-
statusIcon = "\u23F3";
|
|
155172
|
-
break;
|
|
155173
|
-
case "thinking":
|
|
155174
|
-
statusDot = "#50fa7b";
|
|
155175
|
-
statusLabel = liveStatus.thinkingDetail ? `Thinking: ${liveStatus.thinkingDetail}` : "Thinking...";
|
|
155176
|
-
statusIcon = "\u26A1";
|
|
155177
|
-
break;
|
|
155178
|
-
case "error":
|
|
155179
|
-
statusDot = "#f44";
|
|
155180
|
-
statusLabel = liveStatus.thinkingDetail ? `Error: ${liveStatus.thinkingDetail}` : "Error";
|
|
155181
|
-
statusIcon = "\u274C";
|
|
155182
|
-
break;
|
|
155183
|
-
}
|
|
155184
|
-
}
|
|
155185
|
-
}
|
|
155384
|
+
const statusPres = STATUS_PRESENTATION[resolveStatusKey(liveStatus)];
|
|
155385
|
+
const statusDot = statusPres.colorHex;
|
|
155386
|
+
const statusLabel = statusPres.label;
|
|
155387
|
+
const statusIcon = statusPres.icon;
|
|
155388
|
+
const activityDetail = describeActivity(liveStatus);
|
|
155389
|
+
const activityDetailEsc = activityDetail.replace(/"/g, """);
|
|
155186
155390
|
const colorHex = "#" + agent.color.toString(16).padStart(6, "0");
|
|
155187
155391
|
const isSelected = agent.id === selectedAgentId;
|
|
155188
155392
|
const borderColor = isSelected ? "#6677ff" : "#252540";
|
|
@@ -155211,13 +155415,13 @@ ${h2.join(`
|
|
|
155211
155415
|
">${toolCount} tools queued</div>` : "";
|
|
155212
155416
|
let toolPipelineHtml = "";
|
|
155213
155417
|
if (tools.length > 0) {
|
|
155214
|
-
const toolRows = tools.map((
|
|
155418
|
+
const toolRows = tools.map((tool, i) => {
|
|
155215
155419
|
const isLast = i === tools.length - 1;
|
|
155216
155420
|
const icon = isLast ? "\u25B8" : "\u25E6";
|
|
155217
155421
|
const color = isLast ? "#8af" : "#556";
|
|
155218
|
-
const statusText = isLast ?
|
|
155219
|
-
return `<div style="font-size: ${
|
|
155220
|
-
${icon} <span style="color: #9ab;">${
|
|
155422
|
+
const statusText = isLast ? tool.status : "(queued)";
|
|
155423
|
+
return `<div style="font-size: ${t.toolRow}; color: ${color}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 1px 0;">
|
|
155424
|
+
${icon} <span style="color: #9ab;">${tool.name}</span> <span style="color: #556;">\u2014 ${statusText}</span>
|
|
155221
155425
|
</div>`;
|
|
155222
155426
|
}).join("");
|
|
155223
155427
|
toolPipelineHtml = `
|
|
@@ -155388,6 +155592,11 @@ ${h2.join(`
|
|
|
155388
155592
|
<div style="font-weight: bold; color: #dde; font-size: ${t.cardTitleLg};">${agent.name}</div>
|
|
155389
155593
|
<div style="color: #778; font-size: ${t.cardDescription}; margin-top: 3px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;">${agent.description}</div>
|
|
155390
155594
|
</div>
|
|
155595
|
+
<div data-activity-detail-agent="${agent.id}" style="
|
|
155596
|
+
height: 18px; line-height: 18px;
|
|
155597
|
+
font-size: ${t.taskSummary}; color: #7f88b0;
|
|
155598
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
155599
|
+
" title="${activityDetailEsc}">${activityDetail}</div>
|
|
155391
155600
|
<div>
|
|
155392
155601
|
${taskSummaryHtml}
|
|
155393
155602
|
</div>
|
|
@@ -155446,6 +155655,7 @@ ${h2.join(`
|
|
|
155446
155655
|
"use strict";
|
|
155447
155656
|
init_types();
|
|
155448
155657
|
init_agents();
|
|
155658
|
+
init_agentStatusPresentation();
|
|
155449
155659
|
fleetDashboard = {
|
|
155450
155660
|
renderCards(ctx) {
|
|
155451
155661
|
const { agents, office, selectedAgentId, formatElapsed, formatRelativeTime } = ctx;
|
|
@@ -155453,46 +155663,12 @@ ${h2.join(`
|
|
|
155453
155663
|
let html = "";
|
|
155454
155664
|
for (const agent of agents) {
|
|
155455
155665
|
const liveStatus = office?.agents.get(agent.id);
|
|
155456
|
-
|
|
155457
|
-
|
|
155458
|
-
|
|
155459
|
-
|
|
155460
|
-
|
|
155461
|
-
|
|
155462
|
-
case "starting":
|
|
155463
|
-
statusDot = "#ff9944";
|
|
155464
|
-
statusLabel = "Starting...";
|
|
155465
|
-
statusIcon = "\u{1F680}";
|
|
155466
|
-
break;
|
|
155467
|
-
case "ready":
|
|
155468
|
-
if (liveStatus.completionPendingAck) {
|
|
155469
|
-
statusDot = "#4a78ff";
|
|
155470
|
-
statusLabel = "Done";
|
|
155471
|
-
statusIcon = "\u{1F4EC}";
|
|
155472
|
-
} else {
|
|
155473
|
-
statusDot = "#ffffff";
|
|
155474
|
-
statusLabel = "Ready";
|
|
155475
|
-
statusIcon = "\u{1F4ED}";
|
|
155476
|
-
}
|
|
155477
|
-
break;
|
|
155478
|
-
case "waiting":
|
|
155479
|
-
statusDot = "#ffb86c";
|
|
155480
|
-
statusLabel = "Waiting for input";
|
|
155481
|
-
statusIcon = "\u23F3";
|
|
155482
|
-
break;
|
|
155483
|
-
case "thinking":
|
|
155484
|
-
statusDot = "#50fa7b";
|
|
155485
|
-
statusLabel = liveStatus.thinkingDetail ? `Thinking: ${liveStatus.thinkingDetail}` : "Thinking...";
|
|
155486
|
-
statusIcon = "\u26A1";
|
|
155487
|
-
break;
|
|
155488
|
-
case "error":
|
|
155489
|
-
statusDot = "#f44";
|
|
155490
|
-
statusLabel = liveStatus.thinkingDetail ? `Error: ${liveStatus.thinkingDetail}` : "Error";
|
|
155491
|
-
statusIcon = "\u274C";
|
|
155492
|
-
break;
|
|
155493
|
-
}
|
|
155494
|
-
}
|
|
155495
|
-
}
|
|
155666
|
+
const statusPres = STATUS_PRESENTATION[resolveStatusKey(liveStatus)];
|
|
155667
|
+
const statusDot = statusPres.colorHex;
|
|
155668
|
+
const statusLabel = statusPres.label;
|
|
155669
|
+
const statusIcon = statusPres.icon;
|
|
155670
|
+
const activityDetail = describeActivity(liveStatus);
|
|
155671
|
+
const activityDetailEsc = activityDetail.replace(/"/g, """);
|
|
155496
155672
|
const colorHex = "#" + agent.color.toString(16).padStart(6, "0");
|
|
155497
155673
|
const isSelected = agent.id === selectedAgentId;
|
|
155498
155674
|
const isArthur = agent.id === ARCHITECT_AGENT_ID;
|
|
@@ -155567,6 +155743,11 @@ ${h2.join(`
|
|
|
155567
155743
|
<div style="font-weight: bold; color: #dde; font-size: ${t.cardTitle};">${agent.name}</div>
|
|
155568
155744
|
<div style="color: #778; font-size: ${t.cardDescription}; margin-top: 2px;">${agent.description}</div>
|
|
155569
155745
|
</div>
|
|
155746
|
+
<div data-activity-detail-agent="${agent.id}" style="
|
|
155747
|
+
height: 16px; line-height: 16px;
|
|
155748
|
+
font-size: ${t.taskSummary}; color: #7f88b0;
|
|
155749
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
155750
|
+
" title="${activityDetailEsc}">${activityDetail}</div>
|
|
155570
155751
|
<div>
|
|
155571
155752
|
<div style="display: flex; align-items: center; flex-wrap: wrap; margin-top: 3px;">
|
|
155572
155753
|
<div style="
|
|
@@ -157031,6 +157212,10 @@ ${h2.join(`
|
|
|
157031
157212
|
this.game.events.on("agent:status:changed", () => {
|
|
157032
157213
|
this.updateSessionBadges();
|
|
157033
157214
|
}, this);
|
|
157215
|
+
this.game.events.on("agent:stall", (agentId, stalled) => {
|
|
157216
|
+
const npc = this.npcs.find((n) => n.config.id === agentId);
|
|
157217
|
+
npc?.setStalled(stalled);
|
|
157218
|
+
}, this);
|
|
157034
157219
|
this.updateSessionBadges();
|
|
157035
157220
|
this.game.events.on("office:switch", (officeId, _workingDir) => {
|
|
157036
157221
|
if (this.animating) {
|
|
@@ -158503,7 +158688,7 @@ ${h2.join(`
|
|
|
158503
158688
|
let nearestNPCDist = interactionDistance;
|
|
158504
158689
|
let nearestDesk = null;
|
|
158505
158690
|
let nearestDeskDist = interactionDistance;
|
|
158506
|
-
this.npcs
|
|
158691
|
+
for (const npc of this.npcs) {
|
|
158507
158692
|
const dist = import_phaser8.default.Math.Distance.Between(
|
|
158508
158693
|
this.player.x,
|
|
158509
158694
|
this.player.y,
|
|
@@ -158515,7 +158700,7 @@ ${h2.join(`
|
|
|
158515
158700
|
nearestNPC = npc;
|
|
158516
158701
|
}
|
|
158517
158702
|
npc.setNearPlayer(false);
|
|
158518
|
-
}
|
|
158703
|
+
}
|
|
158519
158704
|
this.desks.forEach((desk) => {
|
|
158520
158705
|
const dist = import_phaser8.default.Math.Distance.Between(
|
|
158521
158706
|
this.player.x,
|
|
@@ -159385,12 +159570,13 @@ ${h2.join(`
|
|
|
159385
159570
|
while (this.toasts.length >= MAX_VISIBLE) {
|
|
159386
159571
|
this.dismiss(this.toasts[0]);
|
|
159387
159572
|
}
|
|
159573
|
+
const accentColor = options.statusColorHex ?? options.agentColor;
|
|
159388
159574
|
const el2 = document.createElement("div");
|
|
159389
159575
|
el2.style.cssText = `
|
|
159390
159576
|
pointer-events: auto;
|
|
159391
159577
|
background: #1e1e3a;
|
|
159392
|
-
border: 1.5px solid ${
|
|
159393
|
-
border-left: 4px solid ${
|
|
159578
|
+
border: 1.5px solid ${accentColor}66;
|
|
159579
|
+
border-left: 4px solid ${accentColor};
|
|
159394
159580
|
border-radius: 8px;
|
|
159395
159581
|
padding: 12px 16px;
|
|
159396
159582
|
display: flex;
|
|
@@ -159403,13 +159589,14 @@ ${h2.join(`
|
|
|
159403
159589
|
opacity: 0;
|
|
159404
159590
|
transition: transform ${ANIMATION_MS}ms ease, opacity ${ANIMATION_MS}ms ease;
|
|
159405
159591
|
`;
|
|
159592
|
+
const markerHtml = options.statusIcon ? `<div style="font-size: 16px; line-height: 1; flex-shrink: 0;">${options.statusIcon}</div>` : `<div style="
|
|
159593
|
+
width: 8px; height: 8px;
|
|
159594
|
+
border-radius: 50%;
|
|
159595
|
+
background: ${accentColor};
|
|
159596
|
+
flex-shrink: 0;
|
|
159597
|
+
"></div>`;
|
|
159406
159598
|
el2.innerHTML = `
|
|
159407
|
-
|
|
159408
|
-
width: 8px; height: 8px;
|
|
159409
|
-
border-radius: 50%;
|
|
159410
|
-
background: ${options.agentColor};
|
|
159411
|
-
flex-shrink: 0;
|
|
159412
|
-
"></div>
|
|
159599
|
+
${markerHtml}
|
|
159413
159600
|
<div style="flex: 1; min-width: 0;">
|
|
159414
159601
|
<div style="font-size: 12px; font-weight: bold; color: #dde;">${options.agentName}</div>
|
|
159415
159602
|
<div style="font-size: 11px; color: #889; margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">${options.message}</div>
|
|
@@ -159555,11 +159742,21 @@ ${h2.join(`
|
|
|
159555
159742
|
});
|
|
159556
159743
|
|
|
159557
159744
|
// src/ui/NotificationService.ts
|
|
159558
|
-
var NotificationService;
|
|
159745
|
+
var EVENT_STATUS_KEY, NotificationService;
|
|
159559
159746
|
var init_NotificationService = __esm({
|
|
159560
159747
|
"src/ui/NotificationService.ts"() {
|
|
159561
159748
|
"use strict";
|
|
159562
159749
|
init_notifications();
|
|
159750
|
+
init_agentStatusPresentation();
|
|
159751
|
+
EVENT_STATUS_KEY = {
|
|
159752
|
+
turnEnd: "done",
|
|
159753
|
+
askUser: "waiting",
|
|
159754
|
+
turnStart: "thinking",
|
|
159755
|
+
toolStart: "thinking",
|
|
159756
|
+
toolComplete: null,
|
|
159757
|
+
sessionReady: "ready",
|
|
159758
|
+
sessionError: "error"
|
|
159759
|
+
};
|
|
159563
159760
|
NotificationService = class {
|
|
159564
159761
|
constructor(toastManager, resolveAgent, onClickAgent) {
|
|
159565
159762
|
this.dedupeMap = /* @__PURE__ */ new Map();
|
|
@@ -159603,18 +159800,23 @@ ${h2.join(`
|
|
|
159603
159800
|
if (!agent) return;
|
|
159604
159801
|
const message = this.formatMessage(eventConfig.message, agent.name, context);
|
|
159605
159802
|
const colorHex = "#" + agent.color.toString(16).padStart(6, "0");
|
|
159803
|
+
const statusKey = EVENT_STATUS_KEY[eventType];
|
|
159804
|
+
const statusPres = statusKey ? STATUS_PRESENTATION[statusKey] : void 0;
|
|
159606
159805
|
if (eventConfig.toast) {
|
|
159607
159806
|
this.toastManager.show({
|
|
159608
159807
|
agentId,
|
|
159609
159808
|
agentName: agent.name,
|
|
159610
159809
|
agentColor: colorHex,
|
|
159611
159810
|
message,
|
|
159612
|
-
onClick: () => this.onClickAgent?.(agentId)
|
|
159811
|
+
onClick: () => this.onClickAgent?.(agentId),
|
|
159812
|
+
statusIcon: statusPres?.icon,
|
|
159813
|
+
statusColorHex: statusPres?.colorHex
|
|
159613
159814
|
});
|
|
159614
159815
|
}
|
|
159615
159816
|
if (eventConfig.osNotification) {
|
|
159817
|
+
const titlePrefix = statusPres?.icon ?? "\u{1F3E2}";
|
|
159616
159818
|
window.copilotBridge?.showNativeNotification(
|
|
159617
|
-
|
|
159819
|
+
`${titlePrefix} ${agent.name}`,
|
|
159618
159820
|
message
|
|
159619
159821
|
);
|
|
159620
159822
|
}
|
|
@@ -160844,7 +161046,7 @@ Failed to start terminal: ${startResult.error || "unknown error"}`);
|
|
|
160844
161046
|
this.updateSessionIdDisplay();
|
|
160845
161047
|
}
|
|
160846
161048
|
}
|
|
160847
|
-
const attachResult = await window.copilotBridge.terminalAttach(options.officeId, options.agentId);
|
|
161049
|
+
const attachResult = await window.copilotBridge.terminalAttach(options.officeId, options.agentId, true);
|
|
160848
161050
|
if (!attachResult.success) {
|
|
160849
161051
|
this.terminal.writeln("\r\nFailed to attach terminal session.");
|
|
160850
161052
|
this.setStatus("Attach failed");
|
|
@@ -161061,14 +161263,17 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
161061
161263
|
return;
|
|
161062
161264
|
}
|
|
161063
161265
|
this.setTeamsButtonState(false, true);
|
|
161064
|
-
const
|
|
161266
|
+
const office = officeManager.getOffice(officeId)?.config;
|
|
161267
|
+
const officeChannelUrl = office?.teamsChannelUrl;
|
|
161065
161268
|
const workingDir = this.activeOptions.workingDir || officeManager.getCurrentWorkingDirectory();
|
|
161066
161269
|
const res = await window.copilotBridge.teamsRegister({
|
|
161067
161270
|
officeId,
|
|
161068
161271
|
agentId,
|
|
161069
161272
|
displayName: this.activeOptions.name,
|
|
161070
161273
|
workingDir,
|
|
161071
|
-
officeChannelUrl
|
|
161274
|
+
officeChannelUrl,
|
|
161275
|
+
officeMentionType: office?.teamsMentionType,
|
|
161276
|
+
officeMentionValue: office?.teamsMentionValue
|
|
161072
161277
|
});
|
|
161073
161278
|
if (res?.success) {
|
|
161074
161279
|
this.setTeamsButtonState(true);
|
|
@@ -161539,6 +161744,17 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
161539
161744
|
const last = remainingTools[remainingTools.length - 1];
|
|
161540
161745
|
return { kind: "thinking", detail: String(last.name ?? "") };
|
|
161541
161746
|
}
|
|
161747
|
+
function addActiveTool(tools, entry) {
|
|
161748
|
+
if (tools.some((t) => t.toolId === entry.toolId)) {
|
|
161749
|
+
return { tools: tools.slice(), added: false };
|
|
161750
|
+
}
|
|
161751
|
+
return { tools: [...tools, entry], added: true };
|
|
161752
|
+
}
|
|
161753
|
+
function removeCompletedTool(tools, toolId) {
|
|
161754
|
+
const completed = tools.find((t) => t.toolId === toolId) ?? null;
|
|
161755
|
+
if (!completed) return { tools: tools.slice(), completed: null };
|
|
161756
|
+
return { tools: tools.filter((t) => t.toolId !== toolId), completed };
|
|
161757
|
+
}
|
|
161542
161758
|
var init_toolStatus = __esm({
|
|
161543
161759
|
"src/util/toolStatus.ts"() {
|
|
161544
161760
|
"use strict";
|
|
@@ -161584,6 +161800,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
161584
161800
|
init_SeriousTerminalController();
|
|
161585
161801
|
init_SpriteGenerator();
|
|
161586
161802
|
init_toolStatus();
|
|
161803
|
+
init_agentStatusPresentation();
|
|
161587
161804
|
init_startupTimeoutGuard();
|
|
161588
161805
|
init_AutoStartCoordinator();
|
|
161589
161806
|
init_agentAutoStart();
|
|
@@ -161597,6 +161814,22 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
161597
161814
|
function getCurrentAgents() {
|
|
161598
161815
|
return getLayout(getCurrentLayout()).agents;
|
|
161599
161816
|
}
|
|
161817
|
+
function sortAgentsByMode(agents, office) {
|
|
161818
|
+
if (agentSortMode !== "recent" || !office) return agents;
|
|
161819
|
+
const persisted = getOfficeAgentActivityTimes(office.config.id);
|
|
161820
|
+
const recency = (id) => {
|
|
161821
|
+
let t = persisted[id] ?? 0;
|
|
161822
|
+
const status = office.agents.get(id);
|
|
161823
|
+
if (status) {
|
|
161824
|
+
if ((status.activityStartTime ?? 0) > t) t = status.activityStartTime;
|
|
161825
|
+
for (const action of status.recentActions) {
|
|
161826
|
+
if (action.timestamp > t) t = action.timestamp;
|
|
161827
|
+
}
|
|
161828
|
+
}
|
|
161829
|
+
return t;
|
|
161830
|
+
};
|
|
161831
|
+
return [...agents].sort((a, b2) => recency(b2.id) - recency(a.id));
|
|
161832
|
+
}
|
|
161600
161833
|
function getCurrentAgentTools() {
|
|
161601
161834
|
return officeManager.currentOffice?.agentTools || /* @__PURE__ */ new Map();
|
|
161602
161835
|
}
|
|
@@ -161621,9 +161854,32 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
161621
161854
|
var SESSION_META_CACHE_STORAGE_KEY = "agencyOffice:sessionMetaCacheByOffice";
|
|
161622
161855
|
var OVERVIEW_SPRITE_CACHE_STORAGE_KEY = "agencyOffice:overviewSpriteCache";
|
|
161623
161856
|
var PC_TERMINAL_ID2 = "pc-terminal";
|
|
161624
|
-
var
|
|
161857
|
+
var AGENT_SORT_STORAGE_KEY = "agencyOffice:agentSortMode";
|
|
161625
161858
|
var OFFICE_ACCESS_TIMES_KEY = "agencyOffice:officeAccessTimes";
|
|
161626
|
-
var
|
|
161859
|
+
var AGENT_ACTIVITY_TIMES_KEY = "agencyOffice:agentActivityTimes";
|
|
161860
|
+
var agentSortMode = localStorage.getItem(AGENT_SORT_STORAGE_KEY) || "default";
|
|
161861
|
+
function getAgentActivityTimes() {
|
|
161862
|
+
try {
|
|
161863
|
+
const raw = localStorage.getItem(AGENT_ACTIVITY_TIMES_KEY);
|
|
161864
|
+
return raw ? JSON.parse(raw) : {};
|
|
161865
|
+
} catch {
|
|
161866
|
+
return {};
|
|
161867
|
+
}
|
|
161868
|
+
}
|
|
161869
|
+
function getOfficeAgentActivityTimes(officeId) {
|
|
161870
|
+
return getAgentActivityTimes()[officeId] ?? {};
|
|
161871
|
+
}
|
|
161872
|
+
function recordAgentActivity(officeId, agentId) {
|
|
161873
|
+
if (!officeId) return;
|
|
161874
|
+
const all = getAgentActivityTimes();
|
|
161875
|
+
const office = all[officeId] ?? {};
|
|
161876
|
+
office[agentId] = Date.now();
|
|
161877
|
+
all[officeId] = office;
|
|
161878
|
+
try {
|
|
161879
|
+
localStorage.setItem(AGENT_ACTIVITY_TIMES_KEY, JSON.stringify(all));
|
|
161880
|
+
} catch {
|
|
161881
|
+
}
|
|
161882
|
+
}
|
|
161627
161883
|
function getOfficeAccessTimes() {
|
|
161628
161884
|
try {
|
|
161629
161885
|
const raw = localStorage.getItem(OFFICE_ACCESS_TIMES_KEY);
|
|
@@ -161633,6 +161889,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
161633
161889
|
}
|
|
161634
161890
|
}
|
|
161635
161891
|
function recordOfficeAccess(officeId) {
|
|
161892
|
+
if (!officeId) return;
|
|
161636
161893
|
const times = getOfficeAccessTimes();
|
|
161637
161894
|
times[officeId] = Date.now();
|
|
161638
161895
|
try {
|
|
@@ -161929,8 +162186,8 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
161929
162186
|
return getCurrentAgents().map((a) => ({
|
|
161930
162187
|
id: a.id,
|
|
161931
162188
|
name: a.name,
|
|
161932
|
-
tileX: a.
|
|
161933
|
-
tileY: a.
|
|
162189
|
+
tileX: a.position.x,
|
|
162190
|
+
tileY: a.position.y
|
|
161934
162191
|
}));
|
|
161935
162192
|
},
|
|
161936
162193
|
getActiveTerminalAgentId: () => {
|
|
@@ -161988,12 +162245,8 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
161988
162245
|
console.log("[main] Spec 008-smoke: __copilotOfficeDebug installed");
|
|
161989
162246
|
}
|
|
161990
162247
|
function renderOfficeTabs() {
|
|
161991
|
-
|
|
162248
|
+
const offices = officeManager.getAllOffices();
|
|
161992
162249
|
const currentId = officeManager.currentOfficeId;
|
|
161993
|
-
if (officeSortMode === "recent") {
|
|
161994
|
-
const accessTimes = getOfficeAccessTimes();
|
|
161995
|
-
offices = [...offices].sort((a, b2) => (accessTimes[b2.id] || 0) - (accessTimes[a.id] || 0));
|
|
161996
|
-
}
|
|
161997
162250
|
let html = "";
|
|
161998
162251
|
for (const office of offices) {
|
|
161999
162252
|
const isActive = office.id === currentId;
|
|
@@ -162358,6 +162611,21 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
162358
162611
|
width: 100%; padding: 6px 8px; margin-bottom: 14px; background: #12121f; border: 1px solid #333;
|
|
162359
162612
|
border-radius: 5px; color: #899; font-family: inherit; font-size: 11px; box-sizing: border-box;
|
|
162360
162613
|
" />
|
|
162614
|
+
<label style="display: block; margin-bottom: 3px; color: #889; font-size: 11px;">Teams Mention Override <span style="color:#667;">(optional)</span></label>
|
|
162615
|
+
<div style="display: flex; gap: 6px; margin-bottom: 14px;">
|
|
162616
|
+
<select class="osp-teams-mention-type" style="
|
|
162617
|
+
padding: 6px 8px; background: #12121f; border: 1px solid #333; border-radius: 5px;
|
|
162618
|
+
color: #899; font-family: inherit; font-size: 11px; box-sizing: border-box;
|
|
162619
|
+
">
|
|
162620
|
+
<option value="none"${(office.config.teamsMentionType ?? "none") === "none" ? " selected" : ""}>Default</option>
|
|
162621
|
+
<option value="tag"${office.config.teamsMentionType === "tag" ? " selected" : ""}>Tag</option>
|
|
162622
|
+
<option value="user"${office.config.teamsMentionType === "user" ? " selected" : ""}>User</option>
|
|
162623
|
+
</select>
|
|
162624
|
+
<input class="osp-teams-mention-value" type="text" value="${escapeHtml(office.config.teamsMentionValue ?? "")}" placeholder="Tag name / user (empty = use default)" style="
|
|
162625
|
+
flex: 1; padding: 6px 8px; background: #12121f; border: 1px solid #333; border-radius: 5px;
|
|
162626
|
+
color: #899; font-family: inherit; font-size: 11px; box-sizing: border-box;
|
|
162627
|
+
" />
|
|
162628
|
+
</div>
|
|
162361
162629
|
<div style="display: flex; gap: 8px; justify-content: flex-end;">
|
|
162362
162630
|
${canDelete ? `<button class="osp-delete" style="
|
|
162363
162631
|
padding: 5px 12px; background: #2a1a1a; border: 1px solid #633; border-radius: 5px;
|
|
@@ -162377,6 +162645,8 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
162377
162645
|
const nameInput = popover.querySelector(".osp-name");
|
|
162378
162646
|
const pathInput = popover.querySelector(".osp-path");
|
|
162379
162647
|
const teamsInput = popover.querySelector(".osp-teams");
|
|
162648
|
+
const teamsMentionTypeInput = popover.querySelector(".osp-teams-mention-type");
|
|
162649
|
+
const teamsMentionValueInput = popover.querySelector(".osp-teams-mention-value");
|
|
162380
162650
|
popover.querySelector(".osp-close")?.addEventListener("click", closeOfficePopover);
|
|
162381
162651
|
popover.querySelector(".osp-save")?.addEventListener("click", () => {
|
|
162382
162652
|
const newName = nameInput.value.trim();
|
|
@@ -162384,6 +162654,10 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
162384
162654
|
if (newName) officeManager.updateOffice(officeId, { name: newName });
|
|
162385
162655
|
if (newPath) officeManager.updateOffice(officeId, { workingDirectory: newPath });
|
|
162386
162656
|
officeManager.updateOffice(officeId, { teamsChannelUrl: teamsInput.value.trim() });
|
|
162657
|
+
officeManager.updateOffice(officeId, {
|
|
162658
|
+
teamsMentionType: teamsMentionTypeInput.value,
|
|
162659
|
+
teamsMentionValue: teamsMentionValueInput.value.trim()
|
|
162660
|
+
});
|
|
162387
162661
|
renderOfficeTabs();
|
|
162388
162662
|
updateTerminalContent();
|
|
162389
162663
|
closeOfficePopover();
|
|
@@ -162431,18 +162705,18 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
162431
162705
|
<div id="terminal-subtitle" style="font-size: 12px; color: #555;"></div>
|
|
162432
162706
|
</div>
|
|
162433
162707
|
<div style="display: flex; align-items: center; gap: 8px;">
|
|
162434
|
-
<button id="
|
|
162708
|
+
<button id="agent-sort-btn" style="
|
|
162435
162709
|
padding: 6px 12px;
|
|
162436
|
-
background: ${
|
|
162437
|
-
color: ${
|
|
162438
|
-
border: 1px solid ${
|
|
162710
|
+
background: ${agentSortMode === "recent" ? "#2a3a5a" : "#252538"};
|
|
162711
|
+
color: ${agentSortMode === "recent" ? "#8af" : "#666"};
|
|
162712
|
+
border: 1px solid ${agentSortMode === "recent" ? "#4488ff" : "#444"};
|
|
162439
162713
|
border-radius: 4px;
|
|
162440
162714
|
font-family: 'Cascadia Code', Consolas, monospace;
|
|
162441
162715
|
font-size: 12px;
|
|
162442
162716
|
cursor: pointer;
|
|
162443
162717
|
white-space: nowrap;
|
|
162444
162718
|
transition: all 0.2s;
|
|
162445
|
-
" title="Sort office
|
|
162719
|
+
" title="Sort agents in this office">\u21C5 ${agentSortMode === "recent" ? "Recent" : "Default"}</button>
|
|
162446
162720
|
<button id="close-office-btn" style="
|
|
162447
162721
|
display: none;
|
|
162448
162722
|
padding: 6px 14px;
|
|
@@ -162458,19 +162732,19 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
162458
162732
|
</div>
|
|
162459
162733
|
`;
|
|
162460
162734
|
overviewHost.appendChild(overviewHeader);
|
|
162461
|
-
document.getElementById("
|
|
162462
|
-
|
|
162735
|
+
document.getElementById("agent-sort-btn").addEventListener("click", () => {
|
|
162736
|
+
agentSortMode = agentSortMode === "default" ? "recent" : "default";
|
|
162463
162737
|
try {
|
|
162464
|
-
localStorage.setItem(
|
|
162738
|
+
localStorage.setItem(AGENT_SORT_STORAGE_KEY, agentSortMode);
|
|
162465
162739
|
} catch {
|
|
162466
162740
|
}
|
|
162467
|
-
|
|
162468
|
-
const sortBtn = document.getElementById("
|
|
162741
|
+
updateTerminalContent();
|
|
162742
|
+
const sortBtn = document.getElementById("agent-sort-btn");
|
|
162469
162743
|
if (sortBtn) {
|
|
162470
|
-
sortBtn.textContent = `\u21C5 ${
|
|
162471
|
-
sortBtn.style.background =
|
|
162472
|
-
sortBtn.style.color =
|
|
162473
|
-
sortBtn.style.borderColor =
|
|
162744
|
+
sortBtn.textContent = `\u21C5 ${agentSortMode === "recent" ? "Recent" : "Default"}`;
|
|
162745
|
+
sortBtn.style.background = agentSortMode === "recent" ? "#2a3a5a" : "#252538";
|
|
162746
|
+
sortBtn.style.color = agentSortMode === "recent" ? "#8af" : "#666";
|
|
162747
|
+
sortBtn.style.borderColor = agentSortMode === "recent" ? "#4488ff" : "#444";
|
|
162474
162748
|
}
|
|
162475
162749
|
});
|
|
162476
162750
|
document.getElementById("close-office-btn").addEventListener("click", () => {
|
|
@@ -162522,11 +162796,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
162522
162796
|
var toastManager = new ToastNotificationManager(document.body);
|
|
162523
162797
|
function formatElapsed(startTime) {
|
|
162524
162798
|
if (!startTime) return "";
|
|
162525
|
-
|
|
162526
|
-
if (seconds < 60) return `${seconds}s`;
|
|
162527
|
-
const mins = Math.floor(seconds / 60);
|
|
162528
|
-
const secs = seconds % 60;
|
|
162529
|
-
return `${mins}m ${secs}s`;
|
|
162799
|
+
return formatElapsedMmSs(startTime);
|
|
162530
162800
|
}
|
|
162531
162801
|
function formatRelativeTime(timestamp) {
|
|
162532
162802
|
const seconds = Math.floor((Date.now() - timestamp) / 1e3);
|
|
@@ -162589,8 +162859,18 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
162589
162859
|
terminalHost.style.display = "none";
|
|
162590
162860
|
seriousPlaceholder.style.display = "none";
|
|
162591
162861
|
}
|
|
162862
|
+
function clearCompletionAck(agentId) {
|
|
162863
|
+
const officeId = officeManager.currentOfficeId;
|
|
162864
|
+
if (!officeId) return;
|
|
162865
|
+
if (officeManager.acknowledgeAgentCompletion(officeId, agentId)) {
|
|
162866
|
+
phaserGameRef?.events.emit("agent:status:changed", agentId);
|
|
162867
|
+
updateStatusBar();
|
|
162868
|
+
updateTerminalContent();
|
|
162869
|
+
}
|
|
162870
|
+
}
|
|
162592
162871
|
async function openAgentTerminal(agentId) {
|
|
162593
162872
|
selectedAgentId = agentId;
|
|
162873
|
+
clearCompletionAck(agentId);
|
|
162594
162874
|
if (appMode === "game") {
|
|
162595
162875
|
phaserGameRef?.events.emit("open:agent:terminal", agentId);
|
|
162596
162876
|
return;
|
|
@@ -162627,12 +162907,13 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
162627
162907
|
}
|
|
162628
162908
|
});
|
|
162629
162909
|
var autoStartTerminalStartCount = 0;
|
|
162630
|
-
async function warmAgentSession(officeId, agentId) {
|
|
162631
|
-
if (!window.copilotBridge) return;
|
|
162632
|
-
const
|
|
162633
|
-
|
|
162634
|
-
const workingDir = launchConfig
|
|
162635
|
-
const launchMode = launchConfig
|
|
162910
|
+
async function warmAgentSession(officeId, agentId, fallback) {
|
|
162911
|
+
if (!window.copilotBridge) return false;
|
|
162912
|
+
const isCurrentOffice = officeId === officeManager.currentOfficeId;
|
|
162913
|
+
const launchConfig = isCurrentOffice ? getSeriousLaunchConfig(agentId) : null;
|
|
162914
|
+
const workingDir = launchConfig?.workingDir ?? fallback?.workingDir;
|
|
162915
|
+
const launchMode = launchConfig?.launchMode ?? fallback?.launchMode ?? "copilot";
|
|
162916
|
+
if (!workingDir) return false;
|
|
162636
162917
|
const officeStatus = officeManager.getAgentStatus(officeId, agentId);
|
|
162637
162918
|
if (officeStatus?.state === "slacking") {
|
|
162638
162919
|
officeManager.setAgentStarting(officeId, agentId);
|
|
@@ -162641,7 +162922,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
162641
162922
|
updateTerminalContent();
|
|
162642
162923
|
}
|
|
162643
162924
|
autoStartTerminalStartCount += 1;
|
|
162644
|
-
await window.copilotBridge.terminalStart(
|
|
162925
|
+
const res = await window.copilotBridge.terminalStart(
|
|
162645
162926
|
officeId,
|
|
162646
162927
|
agentId,
|
|
162647
162928
|
workingDir,
|
|
@@ -162650,6 +162931,74 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
162650
162931
|
void 0,
|
|
162651
162932
|
launchMode
|
|
162652
162933
|
);
|
|
162934
|
+
return res?.success !== false;
|
|
162935
|
+
}
|
|
162936
|
+
var teamsColdWarmDone = false;
|
|
162937
|
+
var teamsColdWarmInFlight = false;
|
|
162938
|
+
var teamsColdWarmAttempts = 0;
|
|
162939
|
+
var TEAMS_COLD_WARM_MAX_ATTEMPTS = 5;
|
|
162940
|
+
var TEAMS_COLD_WARM_RETRY_MS = 1500;
|
|
162941
|
+
function scheduleTeamsColdWarmRetry() {
|
|
162942
|
+
if (teamsColdWarmDone) return;
|
|
162943
|
+
if (teamsColdWarmAttempts >= TEAMS_COLD_WARM_MAX_ATTEMPTS) return;
|
|
162944
|
+
setTimeout(() => {
|
|
162945
|
+
void warmAllTeamsBoundAgents();
|
|
162946
|
+
}, TEAMS_COLD_WARM_RETRY_MS);
|
|
162947
|
+
}
|
|
162948
|
+
async function warmAllTeamsBoundAgents() {
|
|
162949
|
+
if (teamsColdWarmDone || teamsColdWarmInFlight) return;
|
|
162950
|
+
if (!window.copilotBridge?.teamsStatus) return;
|
|
162951
|
+
teamsColdWarmInFlight = true;
|
|
162952
|
+
teamsColdWarmAttempts += 1;
|
|
162953
|
+
try {
|
|
162954
|
+
const teamsRes = await window.copilotBridge.teamsStatus();
|
|
162955
|
+
if (!teamsRes?.success || !Array.isArray(teamsRes.bindings)) {
|
|
162956
|
+
scheduleTeamsColdWarmRetry();
|
|
162957
|
+
return;
|
|
162958
|
+
}
|
|
162959
|
+
const bindings = teamsRes.bindings;
|
|
162960
|
+
if (bindings.length === 0) {
|
|
162961
|
+
scheduleTeamsColdWarmRetry();
|
|
162962
|
+
return;
|
|
162963
|
+
}
|
|
162964
|
+
const results = await Promise.all(
|
|
162965
|
+
bindings.map(async (b2) => {
|
|
162966
|
+
try {
|
|
162967
|
+
return await warmAgentSession(
|
|
162968
|
+
b2.officeId,
|
|
162969
|
+
b2.agentId,
|
|
162970
|
+
b2.workingDir ? {
|
|
162971
|
+
workingDir: b2.workingDir,
|
|
162972
|
+
// A raw shell can't be Teams-bound (nothing to resume), but
|
|
162973
|
+
// guard defensively so PC_TERMINAL never resumes as copilot.
|
|
162974
|
+
launchMode: b2.agentId === PC_TERMINAL_ID2 ? "shell" : "copilot"
|
|
162975
|
+
} : void 0
|
|
162976
|
+
);
|
|
162977
|
+
} catch (err) {
|
|
162978
|
+
console.warn(
|
|
162979
|
+
`[Teams] cold-launch warm failed for ${b2.officeId}/${b2.agentId}:`,
|
|
162980
|
+
err
|
|
162981
|
+
);
|
|
162982
|
+
return false;
|
|
162983
|
+
}
|
|
162984
|
+
})
|
|
162985
|
+
);
|
|
162986
|
+
if (!results.some(Boolean)) {
|
|
162987
|
+
scheduleTeamsColdWarmRetry();
|
|
162988
|
+
return;
|
|
162989
|
+
}
|
|
162990
|
+
teamsColdWarmDone = true;
|
|
162991
|
+
try {
|
|
162992
|
+
await window.copilotBridge.teamsReconcile?.();
|
|
162993
|
+
} catch {
|
|
162994
|
+
}
|
|
162995
|
+
void refreshTeamsDashboardState();
|
|
162996
|
+
} catch (e) {
|
|
162997
|
+
console.warn("[Teams] warmAllTeamsBoundAgents failed:", e);
|
|
162998
|
+
scheduleTeamsColdWarmRetry();
|
|
162999
|
+
} finally {
|
|
163000
|
+
teamsColdWarmInFlight = false;
|
|
163001
|
+
}
|
|
162653
163002
|
}
|
|
162654
163003
|
function buildCanonicalAgentIdsForOffice(officeId) {
|
|
162655
163004
|
const office = officeManager.currentOfficeId === officeId ? officeManager.currentOffice : null;
|
|
@@ -162696,7 +163045,9 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
162696
163045
|
if (!window.copilotBridge) return;
|
|
162697
163046
|
await window.copilotBridge.resetSession(oid, aid);
|
|
162698
163047
|
},
|
|
162699
|
-
warmAgentSession: (oid, aid) =>
|
|
163048
|
+
warmAgentSession: async (oid, aid) => {
|
|
163049
|
+
await warmAgentSession(oid, aid);
|
|
163050
|
+
},
|
|
162700
163051
|
getSettings: () => getAgentAutoStartSettings()
|
|
162701
163052
|
});
|
|
162702
163053
|
setAutoStartCoordinator(autoStartCoordinator);
|
|
@@ -162828,13 +163179,16 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
162828
163179
|
}
|
|
162829
163180
|
const agent = getSeriousLaunchConfig(agentId);
|
|
162830
163181
|
if (!agent) return;
|
|
162831
|
-
const
|
|
163182
|
+
const office = officeManager.getOffice(officeId)?.config;
|
|
163183
|
+
const officeChannelUrl = office?.teamsChannelUrl;
|
|
162832
163184
|
const res = await window.copilotBridge.teamsRegister({
|
|
162833
163185
|
officeId,
|
|
162834
163186
|
agentId,
|
|
162835
163187
|
displayName: agent.name,
|
|
162836
163188
|
workingDir: agent.workingDir || officeManager.getCurrentWorkingDirectory(),
|
|
162837
|
-
officeChannelUrl
|
|
163189
|
+
officeChannelUrl,
|
|
163190
|
+
officeMentionType: office?.teamsMentionType,
|
|
163191
|
+
officeMentionValue: office?.teamsMentionValue
|
|
162838
163192
|
});
|
|
162839
163193
|
if (res?.success) {
|
|
162840
163194
|
teamsOnlineAgentIds.add(agentId);
|
|
@@ -162879,7 +163233,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
162879
163233
|
}
|
|
162880
163234
|
const layout = getLayout(getCurrentLayout());
|
|
162881
163235
|
const html = layout.dashboard.renderCards({
|
|
162882
|
-
agents: layout.agents,
|
|
163236
|
+
agents: sortAgentsByMode(layout.agents, office || null),
|
|
162883
163237
|
office: office || null,
|
|
162884
163238
|
selectedAgentId,
|
|
162885
163239
|
cachedSessionMeta,
|
|
@@ -163200,8 +163554,14 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
163200
163554
|
if (!agentTools.has(agentId)) {
|
|
163201
163555
|
agentTools.set(agentId, []);
|
|
163202
163556
|
}
|
|
163203
|
-
agentTools.get(agentId)
|
|
163557
|
+
const startResult = addActiveTool(agentTools.get(agentId), { toolId, name: toolName, status });
|
|
163558
|
+
if (!startResult.added) {
|
|
163559
|
+
console.log(`[Office] Ignoring duplicate tool_start for ${agentId} \u2014 toolId ${toolId} already active`);
|
|
163560
|
+
return;
|
|
163561
|
+
}
|
|
163562
|
+
agentTools.set(agentId, startResult.tools);
|
|
163204
163563
|
officeManager.pushRecentAction(officeId, agentId, toolName, "started");
|
|
163564
|
+
recordAgentActivity(officeId, agentId);
|
|
163205
163565
|
if (status) {
|
|
163206
163566
|
officeManager.setTaskSummary(officeId, agentId, status);
|
|
163207
163567
|
}
|
|
@@ -163225,9 +163585,13 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
163225
163585
|
const agentTools = getCurrentAgentTools();
|
|
163226
163586
|
const tools = agentTools.get(agentId);
|
|
163227
163587
|
if (tools) {
|
|
163228
|
-
const
|
|
163229
|
-
|
|
163230
|
-
|
|
163588
|
+
const completeResult = removeCompletedTool(tools, toolId);
|
|
163589
|
+
if (!completeResult.completed) {
|
|
163590
|
+
console.log(`[Office] Ignoring tool_complete for ${agentId} \u2014 unknown toolId ${toolId}`);
|
|
163591
|
+
return;
|
|
163592
|
+
}
|
|
163593
|
+
const completedToolName = completeResult.completed.name || "tool";
|
|
163594
|
+
const remaining = completeResult.tools;
|
|
163231
163595
|
agentTools.set(agentId, remaining);
|
|
163232
163596
|
officeManager.setLastCompletedAction(officeId, agentId, completedToolName);
|
|
163233
163597
|
officeManager.pushRecentAction(officeId, agentId, completedToolName, "completed");
|
|
@@ -163254,6 +163618,11 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
163254
163618
|
console.log(`[Office] Turn end: ${agentId}`);
|
|
163255
163619
|
const officeId = officeManager.currentOfficeId;
|
|
163256
163620
|
if (officeId) {
|
|
163621
|
+
const current = officeManager.getAgentStatus(officeId, agentId);
|
|
163622
|
+
if (current?.subState === "starting") {
|
|
163623
|
+
console.log(`[Office] Ignoring turn_end for ${agentId} \u2014 still in starting state`);
|
|
163624
|
+
return;
|
|
163625
|
+
}
|
|
163257
163626
|
const agentTools = getCurrentAgentTools();
|
|
163258
163627
|
const activeTools = agentTools.get(agentId) || [];
|
|
163259
163628
|
const waitingToolActive = activeTools.some((t) => isAskUserTool(t.name, t.status));
|
|
@@ -163282,6 +163651,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
163282
163651
|
return;
|
|
163283
163652
|
}
|
|
163284
163653
|
officeManager.setTaskSummary(officeId, agentId, "Processing...");
|
|
163654
|
+
recordAgentActivity(officeId, agentId);
|
|
163285
163655
|
officeManager.setAgentThinking(officeId, agentId, "Processing...");
|
|
163286
163656
|
console.log(`[Office] Status: ${agentId} \u2192 thinking (turn start)`);
|
|
163287
163657
|
notifyAgent(agentId, "turnStart");
|
|
@@ -163313,7 +163683,29 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
163313
163683
|
window.copilotBridge.onTeamsToast?.((toast) => {
|
|
163314
163684
|
if (!toast?.message) return;
|
|
163315
163685
|
const kind = toast.level === "error" ? "error" : toast.level === "warn" ? "error" : "info";
|
|
163316
|
-
|
|
163686
|
+
if (typeof toast.durationMs === "number" && toast.durationMs > 0) {
|
|
163687
|
+
showClipboardToast(toast.message, kind, toast.durationMs);
|
|
163688
|
+
} else {
|
|
163689
|
+
showClipboardToast(toast.message, kind);
|
|
163690
|
+
}
|
|
163691
|
+
});
|
|
163692
|
+
let backendFallbackToastShown = false;
|
|
163693
|
+
const showBackendFallbackToast = (info) => {
|
|
163694
|
+
if (!info || !info.fellBack || backendFallbackToastShown) return;
|
|
163695
|
+
backendFallbackToastShown = true;
|
|
163696
|
+
const detail = info.reason ? ` (${info.reason})` : "";
|
|
163697
|
+
showClipboardToast(`Terminal: ${info.requested} unavailable \u2014 using ${info.name}${detail}`, "error", 1e4);
|
|
163698
|
+
};
|
|
163699
|
+
window.copilotBridge.onBackendFallback?.((info) => showBackendFallbackToast(info));
|
|
163700
|
+
void window.copilotBridge.getBackendInfo?.().then((info) => showBackendFallbackToast(info));
|
|
163701
|
+
window.copilotBridge.onBackendOnline?.((officeId, _backend) => {
|
|
163702
|
+
const officeName = officeManager.getOffice(officeId)?.config.name ?? officeId;
|
|
163703
|
+
showClipboardToast(`GitHub Copilot SDK server online for ${officeName}`, "success", 1e4);
|
|
163704
|
+
});
|
|
163705
|
+
window.copilotBridge.onBackendSessionFallback?.((_officeId, agentId, reason) => {
|
|
163706
|
+
const agentName = getAgentConfig(agentId)?.name ?? agentId;
|
|
163707
|
+
const detail = reason ? ` (${reason})` : "";
|
|
163708
|
+
showClipboardToast(`${agentName}: UI-server unavailable \u2014 using node-pty${detail}`, "error", 1e4);
|
|
163317
163709
|
});
|
|
163318
163710
|
window.copilotBridge.onTeamsStatusChanged?.((status) => {
|
|
163319
163711
|
if (!status?.agentId) return;
|
|
@@ -163534,9 +163926,11 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
163534
163926
|
await syncAgentStatuses(true);
|
|
163535
163927
|
}
|
|
163536
163928
|
var ELAPSED_TICK_MS = 1e3;
|
|
163929
|
+
var lastStalledState = /* @__PURE__ */ new Map();
|
|
163537
163930
|
setInterval(() => {
|
|
163538
163931
|
const office = officeManager.currentOffice;
|
|
163539
163932
|
if (!office) return;
|
|
163933
|
+
const now = Date.now();
|
|
163540
163934
|
for (const agent of getCurrentAgents()) {
|
|
163541
163935
|
const status = office.agents.get(agent.id);
|
|
163542
163936
|
if (status?.activityStartTime) {
|
|
@@ -163547,6 +163941,16 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
163547
163941
|
}
|
|
163548
163942
|
}
|
|
163549
163943
|
}
|
|
163944
|
+
const stalled = computeStall(status, now).isStalled;
|
|
163945
|
+
const card = document.querySelector(`.agent-card[data-agent="${agent.id}"]`);
|
|
163946
|
+
if (card) {
|
|
163947
|
+
card.classList.toggle("agent-stalled", stalled);
|
|
163948
|
+
card.dataset.stalled = stalled ? "true" : "false";
|
|
163949
|
+
}
|
|
163950
|
+
if ((lastStalledState.get(agent.id) ?? false) !== stalled) {
|
|
163951
|
+
lastStalledState.set(agent.id, stalled);
|
|
163952
|
+
phaserGameRef?.events.emit("agent:stall", agent.id, stalled);
|
|
163953
|
+
}
|
|
163550
163954
|
const actionEls = document.querySelectorAll(`.agent-card[data-agent="${agent.id}"] [data-action-ts]`);
|
|
163551
163955
|
actionEls.forEach((el2) => {
|
|
163552
163956
|
const ts2 = parseInt(el2.dataset.actionTs || "0", 10);
|
|
@@ -163771,6 +164175,7 @@ Terminal error: ${error?.message || String(error)}`);
|
|
|
163771
164175
|
updateTerminalContent();
|
|
163772
164176
|
updateStatusBar();
|
|
163773
164177
|
void autoStartCoordinator.tryWarmCurrentOffice();
|
|
164178
|
+
void warmAllTeamsBoundAgents();
|
|
163774
164179
|
};
|
|
163775
164180
|
window.addEventListener("focus", () => {
|
|
163776
164181
|
catchUpStatusViews("window focus");
|