claude-code-controller 0.5.1 → 0.6.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/api/index.cjs +170 -14
- package/dist/api/index.cjs.map +1 -1
- package/dist/api/index.d.cts +1 -1
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.js +170 -14
- package/dist/api/index.js.map +1 -1
- package/dist/{claude-0cg912ch.d.cts → claude-B7-oBjuE.d.cts} +47 -1
- package/dist/{claude-0cg912ch.d.ts → claude-B7-oBjuE.d.ts} +47 -1
- package/dist/index.cjs +180 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +60 -4
- package/dist/index.d.ts +60 -4
- package/dist/index.js +175 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -102,6 +102,48 @@ interface PlainTextMessage {
|
|
|
102
102
|
type: "plain_text";
|
|
103
103
|
text: string;
|
|
104
104
|
}
|
|
105
|
+
/** JSON data sent by Claude Code to the statusLine command via stdin. */
|
|
106
|
+
interface StatusLineData {
|
|
107
|
+
model?: {
|
|
108
|
+
id?: string;
|
|
109
|
+
display_name?: string;
|
|
110
|
+
};
|
|
111
|
+
session_id?: string;
|
|
112
|
+
context_window?: {
|
|
113
|
+
used_percentage?: number;
|
|
114
|
+
remaining_percentage?: number;
|
|
115
|
+
total_input_tokens?: number;
|
|
116
|
+
total_output_tokens?: number;
|
|
117
|
+
context_window_size?: number;
|
|
118
|
+
current_usage?: {
|
|
119
|
+
input_tokens?: number;
|
|
120
|
+
output_tokens?: number;
|
|
121
|
+
cache_creation_input_tokens?: number;
|
|
122
|
+
cache_read_input_tokens?: number;
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
cost?: {
|
|
126
|
+
total_cost_usd?: number;
|
|
127
|
+
total_duration_ms?: number;
|
|
128
|
+
total_api_duration_ms?: number;
|
|
129
|
+
total_lines_added?: number;
|
|
130
|
+
total_lines_removed?: number;
|
|
131
|
+
};
|
|
132
|
+
workspace?: {
|
|
133
|
+
current_dir?: string;
|
|
134
|
+
project_dir?: string;
|
|
135
|
+
};
|
|
136
|
+
cwd?: string;
|
|
137
|
+
agent?: {
|
|
138
|
+
name?: string;
|
|
139
|
+
};
|
|
140
|
+
vim?: {
|
|
141
|
+
mode?: string;
|
|
142
|
+
};
|
|
143
|
+
output_style?: {
|
|
144
|
+
name?: string;
|
|
145
|
+
};
|
|
146
|
+
}
|
|
105
147
|
interface TeamConfig {
|
|
106
148
|
name: string;
|
|
107
149
|
description?: string;
|
|
@@ -172,6 +214,7 @@ interface ControllerEvents {
|
|
|
172
214
|
"task:completed": [task: TaskFile];
|
|
173
215
|
"agent:spawned": [agentName: string, pid: number];
|
|
174
216
|
"agent:exited": [agentName: string, code: number | null];
|
|
217
|
+
"agent:statusline": [agentName: string, data: StatusLineData];
|
|
175
218
|
error: [error: Error];
|
|
176
219
|
}
|
|
177
220
|
type LogLevel = "debug" | "info" | "warn" | "error" | "silent";
|
|
@@ -326,6 +369,7 @@ declare class ClaudeCodeController extends EventEmitter<ControllerEvents> implem
|
|
|
326
369
|
readonly tasks: TaskManager;
|
|
327
370
|
private processes;
|
|
328
371
|
private poller;
|
|
372
|
+
private statusLineWatcher;
|
|
329
373
|
private log;
|
|
330
374
|
private cwd;
|
|
331
375
|
private claudeBinary;
|
|
@@ -427,6 +471,7 @@ declare class ClaudeCodeController extends EventEmitter<ControllerEvents> implem
|
|
|
427
471
|
/**
|
|
428
472
|
* Ensure the agent's cwd has a .claude/settings.local.json so the
|
|
429
473
|
* CLI skips the interactive workspace trust prompt.
|
|
474
|
+
* Also injects statusLine capture configuration.
|
|
430
475
|
*/
|
|
431
476
|
private ensureWorkspaceTrusted;
|
|
432
477
|
private ensureInitialized;
|
|
@@ -562,6 +607,7 @@ interface PlanRequestInfo {
|
|
|
562
607
|
interface AgentEvents {
|
|
563
608
|
message: [text: string];
|
|
564
609
|
idle: [];
|
|
610
|
+
statusline: [data: StatusLineData];
|
|
565
611
|
permission: [request: PermissionRequestInfo];
|
|
566
612
|
plan: [request: PlanRequestInfo];
|
|
567
613
|
exit: [code: number | null];
|
|
@@ -668,4 +714,4 @@ declare const claude: typeof claudeCall & {
|
|
|
668
714
|
session: (opts?: SessionOptions) => Promise<Session>;
|
|
669
715
|
};
|
|
670
716
|
|
|
671
|
-
export { Agent as A, type
|
|
717
|
+
export { Agent as A, type TaskCompletedMessage as B, ClaudeCodeController as C, type TaskFile as D, TaskManager as E, type TaskStatus as F, type TeamConfig as G, TeamManager as H, type InboxMessage as I, type TeamMember as J, claude as K, type Logger as L, type PermissionMode as P, type ReceiveOptions as R, type StructuredMessage as S, type TaskAssignmentMessage as T, type StatusLineData as a, type LogLevel as b, type AgentEvents as c, AgentHandle as d, type AgentType as e, type AskOptions as f, type ClaudeOptions as g, type ControllerEvents as h, type ControllerOptions as i, type IdleNotificationMessage as j, type PermissionPreset as k, type PermissionRequestInfo as l, type PermissionRequestMessage as m, type PermissionResponseMessage as n, type PlainTextMessage as o, type PlanApprovalRequestMessage as p, type PlanApprovalResponseMessage as q, type PlanRequestInfo as r, type SandboxPermissionRequestMessage as s, type SandboxPermissionResponseMessage as t, Session as u, type SessionAgentOptions as v, type SessionOptions as w, type ShutdownApprovedMessage as x, type ShutdownRequestMessage as y, type SpawnAgentOptions as z };
|
|
@@ -102,6 +102,48 @@ interface PlainTextMessage {
|
|
|
102
102
|
type: "plain_text";
|
|
103
103
|
text: string;
|
|
104
104
|
}
|
|
105
|
+
/** JSON data sent by Claude Code to the statusLine command via stdin. */
|
|
106
|
+
interface StatusLineData {
|
|
107
|
+
model?: {
|
|
108
|
+
id?: string;
|
|
109
|
+
display_name?: string;
|
|
110
|
+
};
|
|
111
|
+
session_id?: string;
|
|
112
|
+
context_window?: {
|
|
113
|
+
used_percentage?: number;
|
|
114
|
+
remaining_percentage?: number;
|
|
115
|
+
total_input_tokens?: number;
|
|
116
|
+
total_output_tokens?: number;
|
|
117
|
+
context_window_size?: number;
|
|
118
|
+
current_usage?: {
|
|
119
|
+
input_tokens?: number;
|
|
120
|
+
output_tokens?: number;
|
|
121
|
+
cache_creation_input_tokens?: number;
|
|
122
|
+
cache_read_input_tokens?: number;
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
cost?: {
|
|
126
|
+
total_cost_usd?: number;
|
|
127
|
+
total_duration_ms?: number;
|
|
128
|
+
total_api_duration_ms?: number;
|
|
129
|
+
total_lines_added?: number;
|
|
130
|
+
total_lines_removed?: number;
|
|
131
|
+
};
|
|
132
|
+
workspace?: {
|
|
133
|
+
current_dir?: string;
|
|
134
|
+
project_dir?: string;
|
|
135
|
+
};
|
|
136
|
+
cwd?: string;
|
|
137
|
+
agent?: {
|
|
138
|
+
name?: string;
|
|
139
|
+
};
|
|
140
|
+
vim?: {
|
|
141
|
+
mode?: string;
|
|
142
|
+
};
|
|
143
|
+
output_style?: {
|
|
144
|
+
name?: string;
|
|
145
|
+
};
|
|
146
|
+
}
|
|
105
147
|
interface TeamConfig {
|
|
106
148
|
name: string;
|
|
107
149
|
description?: string;
|
|
@@ -172,6 +214,7 @@ interface ControllerEvents {
|
|
|
172
214
|
"task:completed": [task: TaskFile];
|
|
173
215
|
"agent:spawned": [agentName: string, pid: number];
|
|
174
216
|
"agent:exited": [agentName: string, code: number | null];
|
|
217
|
+
"agent:statusline": [agentName: string, data: StatusLineData];
|
|
175
218
|
error: [error: Error];
|
|
176
219
|
}
|
|
177
220
|
type LogLevel = "debug" | "info" | "warn" | "error" | "silent";
|
|
@@ -326,6 +369,7 @@ declare class ClaudeCodeController extends EventEmitter<ControllerEvents> implem
|
|
|
326
369
|
readonly tasks: TaskManager;
|
|
327
370
|
private processes;
|
|
328
371
|
private poller;
|
|
372
|
+
private statusLineWatcher;
|
|
329
373
|
private log;
|
|
330
374
|
private cwd;
|
|
331
375
|
private claudeBinary;
|
|
@@ -427,6 +471,7 @@ declare class ClaudeCodeController extends EventEmitter<ControllerEvents> implem
|
|
|
427
471
|
/**
|
|
428
472
|
* Ensure the agent's cwd has a .claude/settings.local.json so the
|
|
429
473
|
* CLI skips the interactive workspace trust prompt.
|
|
474
|
+
* Also injects statusLine capture configuration.
|
|
430
475
|
*/
|
|
431
476
|
private ensureWorkspaceTrusted;
|
|
432
477
|
private ensureInitialized;
|
|
@@ -562,6 +607,7 @@ interface PlanRequestInfo {
|
|
|
562
607
|
interface AgentEvents {
|
|
563
608
|
message: [text: string];
|
|
564
609
|
idle: [];
|
|
610
|
+
statusline: [data: StatusLineData];
|
|
565
611
|
permission: [request: PermissionRequestInfo];
|
|
566
612
|
plan: [request: PlanRequestInfo];
|
|
567
613
|
exit: [code: number | null];
|
|
@@ -668,4 +714,4 @@ declare const claude: typeof claudeCall & {
|
|
|
668
714
|
session: (opts?: SessionOptions) => Promise<Session>;
|
|
669
715
|
};
|
|
670
716
|
|
|
671
|
-
export { Agent as A, type
|
|
717
|
+
export { Agent as A, type TaskCompletedMessage as B, ClaudeCodeController as C, type TaskFile as D, TaskManager as E, type TaskStatus as F, type TeamConfig as G, TeamManager as H, type InboxMessage as I, type TeamMember as J, claude as K, type Logger as L, type PermissionMode as P, type ReceiveOptions as R, type StructuredMessage as S, type TaskAssignmentMessage as T, type StatusLineData as a, type LogLevel as b, type AgentEvents as c, AgentHandle as d, type AgentType as e, type AskOptions as f, type ClaudeOptions as g, type ControllerEvents as h, type ControllerOptions as i, type IdleNotificationMessage as j, type PermissionPreset as k, type PermissionRequestInfo as l, type PermissionRequestMessage as m, type PermissionResponseMessage as n, type PlainTextMessage as o, type PlanApprovalRequestMessage as p, type PlanApprovalResponseMessage as q, type PlanRequestInfo as r, type SandboxPermissionRequestMessage as s, type SandboxPermissionResponseMessage as t, Session as u, type SessionAgentOptions as v, type SessionOptions as w, type ShutdownApprovedMessage as x, type ShutdownRequestMessage as y, type SpawnAgentOptions as z };
|
package/dist/index.cjs
CHANGED
|
@@ -26,8 +26,11 @@ __export(index_exports, {
|
|
|
26
26
|
InboxPoller: () => InboxPoller,
|
|
27
27
|
ProcessManager: () => ProcessManager,
|
|
28
28
|
Session: () => Session,
|
|
29
|
+
StatusLineWatcher: () => StatusLineWatcher,
|
|
29
30
|
TaskManager: () => TaskManager,
|
|
30
31
|
TeamManager: () => TeamManager,
|
|
32
|
+
buildStatusLineCommand: () => buildStatusLineCommand,
|
|
33
|
+
buildStatusLineSettings: () => buildStatusLineSettings,
|
|
31
34
|
claude: () => claude,
|
|
32
35
|
createLogger: () => createLogger,
|
|
33
36
|
inboxPath: () => inboxPath,
|
|
@@ -36,6 +39,8 @@ __export(index_exports, {
|
|
|
36
39
|
readInbox: () => readInbox,
|
|
37
40
|
readUnread: () => readUnread,
|
|
38
41
|
silentLogger: () => silentLogger,
|
|
42
|
+
statusLineDir: () => statusLineDir,
|
|
43
|
+
statusLineLogPath: () => statusLineLogPath,
|
|
39
44
|
taskPath: () => taskPath,
|
|
40
45
|
tasksBaseDir: () => tasksBaseDir,
|
|
41
46
|
tasksDir: () => tasksDir,
|
|
@@ -47,15 +52,15 @@ __export(index_exports, {
|
|
|
47
52
|
module.exports = __toCommonJS(index_exports);
|
|
48
53
|
|
|
49
54
|
// src/claude.ts
|
|
50
|
-
var
|
|
55
|
+
var import_node_events3 = require("events");
|
|
51
56
|
var import_node_crypto3 = require("crypto");
|
|
52
57
|
|
|
53
58
|
// src/controller.ts
|
|
54
|
-
var
|
|
59
|
+
var import_node_events2 = require("events");
|
|
55
60
|
var import_node_child_process3 = require("child_process");
|
|
56
61
|
var import_node_crypto2 = require("crypto");
|
|
57
|
-
var
|
|
58
|
-
var
|
|
62
|
+
var import_node_fs5 = require("fs");
|
|
63
|
+
var import_node_path4 = require("path");
|
|
59
64
|
|
|
60
65
|
// src/team-manager.ts
|
|
61
66
|
var import_promises = require("fs/promises");
|
|
@@ -760,6 +765,135 @@ var silentLogger = {
|
|
|
760
765
|
}
|
|
761
766
|
};
|
|
762
767
|
|
|
768
|
+
// src/statusline-capture.ts
|
|
769
|
+
var import_node_events = require("events");
|
|
770
|
+
var import_node_fs4 = require("fs");
|
|
771
|
+
var import_node_path3 = require("path");
|
|
772
|
+
function statusLineDir(teamName) {
|
|
773
|
+
return (0, import_node_path3.join)(teamDir(teamName), "statusline");
|
|
774
|
+
}
|
|
775
|
+
function statusLineLogPath(teamName, agentName) {
|
|
776
|
+
return (0, import_node_path3.join)(statusLineDir(teamName), `${agentName}.jsonl`);
|
|
777
|
+
}
|
|
778
|
+
function buildStatusLineCommand(logFilePath) {
|
|
779
|
+
const escapedPath = logFilePath.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
780
|
+
return [
|
|
781
|
+
"python3 -c",
|
|
782
|
+
`'import sys,json;`,
|
|
783
|
+
`d=json.load(sys.stdin);`,
|
|
784
|
+
`open("${escapedPath}","a").write(json.dumps(d)+"\\n");`,
|
|
785
|
+
`print(d.get("model",{}).get("display_name",""))'`
|
|
786
|
+
].join(" ");
|
|
787
|
+
}
|
|
788
|
+
function buildStatusLineSettings(logFilePath) {
|
|
789
|
+
return {
|
|
790
|
+
statusLine: {
|
|
791
|
+
type: "command",
|
|
792
|
+
command: buildStatusLineCommand(logFilePath)
|
|
793
|
+
}
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
var StatusLineWatcher = class extends import_node_events.EventEmitter {
|
|
797
|
+
teamName;
|
|
798
|
+
log;
|
|
799
|
+
watchers = /* @__PURE__ */ new Map();
|
|
800
|
+
fileOffsets = /* @__PURE__ */ new Map();
|
|
801
|
+
stopped = false;
|
|
802
|
+
constructor(teamName, logger) {
|
|
803
|
+
super();
|
|
804
|
+
this.teamName = teamName;
|
|
805
|
+
this.log = logger;
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* Ensure the statusline directory exists.
|
|
809
|
+
*/
|
|
810
|
+
ensureDir() {
|
|
811
|
+
const dir = statusLineDir(this.teamName);
|
|
812
|
+
if (!(0, import_node_fs4.existsSync)(dir)) {
|
|
813
|
+
(0, import_node_fs4.mkdirSync)(dir, { recursive: true });
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* Start watching a specific agent's statusLine log file.
|
|
818
|
+
*/
|
|
819
|
+
watchAgent(agentName) {
|
|
820
|
+
if (this.stopped) return;
|
|
821
|
+
const filePath = statusLineLogPath(this.teamName, agentName);
|
|
822
|
+
if (!(0, import_node_fs4.existsSync)(filePath)) {
|
|
823
|
+
(0, import_node_fs4.writeFileSync)(filePath, "");
|
|
824
|
+
}
|
|
825
|
+
try {
|
|
826
|
+
const stats = (0, import_node_fs4.readFileSync)(filePath);
|
|
827
|
+
this.fileOffsets.set(filePath, stats.length);
|
|
828
|
+
} catch {
|
|
829
|
+
this.fileOffsets.set(filePath, 0);
|
|
830
|
+
}
|
|
831
|
+
try {
|
|
832
|
+
const watcher = (0, import_node_fs4.watch)(filePath, (eventType) => {
|
|
833
|
+
if (eventType === "change") {
|
|
834
|
+
this.readNewLines(agentName, filePath);
|
|
835
|
+
}
|
|
836
|
+
});
|
|
837
|
+
this.watchers.set(agentName, watcher);
|
|
838
|
+
this.log.debug(`Watching statusLine for agent "${agentName}" at ${filePath}`);
|
|
839
|
+
} catch (err) {
|
|
840
|
+
this.log.error(`Failed to watch statusLine for "${agentName}": ${err}`);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* Stop watching a specific agent.
|
|
845
|
+
*/
|
|
846
|
+
unwatchAgent(agentName) {
|
|
847
|
+
const watcher = this.watchers.get(agentName);
|
|
848
|
+
if (watcher) {
|
|
849
|
+
watcher.close();
|
|
850
|
+
this.watchers.delete(agentName);
|
|
851
|
+
}
|
|
852
|
+
const filePath = statusLineLogPath(this.teamName, agentName);
|
|
853
|
+
this.fileOffsets.delete(filePath);
|
|
854
|
+
}
|
|
855
|
+
/**
|
|
856
|
+
* Stop all watchers.
|
|
857
|
+
*/
|
|
858
|
+
stop() {
|
|
859
|
+
this.stopped = true;
|
|
860
|
+
for (const [, watcher] of this.watchers) {
|
|
861
|
+
watcher.close();
|
|
862
|
+
}
|
|
863
|
+
this.watchers.clear();
|
|
864
|
+
this.fileOffsets.clear();
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Read new lines appended to the log file since last read.
|
|
868
|
+
*/
|
|
869
|
+
readNewLines(agentName, filePath) {
|
|
870
|
+
try {
|
|
871
|
+
const content = (0, import_node_fs4.readFileSync)(filePath, "utf-8");
|
|
872
|
+
const offset = this.fileOffsets.get(filePath) ?? 0;
|
|
873
|
+
const newContent = content.slice(offset);
|
|
874
|
+
this.fileOffsets.set(filePath, content.length);
|
|
875
|
+
if (!newContent.trim()) return;
|
|
876
|
+
const lines = newContent.trim().split("\n");
|
|
877
|
+
for (const line of lines) {
|
|
878
|
+
if (!line.trim()) continue;
|
|
879
|
+
try {
|
|
880
|
+
const data = JSON.parse(line);
|
|
881
|
+
const event = {
|
|
882
|
+
agentName,
|
|
883
|
+
data,
|
|
884
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
885
|
+
};
|
|
886
|
+
this.emit("update", event);
|
|
887
|
+
} catch (parseErr) {
|
|
888
|
+
this.log.debug(`Failed to parse statusLine JSON: ${line}`);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
} catch (err) {
|
|
892
|
+
this.log.debug(`Error reading statusLine file: ${err}`);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
};
|
|
896
|
+
|
|
763
897
|
// src/controller.ts
|
|
764
898
|
var PROTOCOL_ONLY_TYPES = /* @__PURE__ */ new Set([
|
|
765
899
|
"shutdown_approved",
|
|
@@ -779,12 +913,13 @@ var AGENT_COLORS = [
|
|
|
779
913
|
"#FF69B4",
|
|
780
914
|
"#7B68EE"
|
|
781
915
|
];
|
|
782
|
-
var ClaudeCodeController = class extends
|
|
916
|
+
var ClaudeCodeController = class extends import_node_events2.EventEmitter {
|
|
783
917
|
teamName;
|
|
784
918
|
team;
|
|
785
919
|
tasks;
|
|
786
920
|
processes;
|
|
787
921
|
poller;
|
|
922
|
+
statusLineWatcher;
|
|
788
923
|
log;
|
|
789
924
|
cwd;
|
|
790
925
|
claudeBinary;
|
|
@@ -806,7 +941,11 @@ var ClaudeCodeController = class extends import_node_events.EventEmitter {
|
|
|
806
941
|
"controller",
|
|
807
942
|
this.log
|
|
808
943
|
);
|
|
944
|
+
this.statusLineWatcher = new StatusLineWatcher(this.teamName, this.log);
|
|
809
945
|
this.poller.onMessages((events) => this.handlePollEvents(events));
|
|
946
|
+
this.statusLineWatcher.on("update", (event) => {
|
|
947
|
+
this.emit("agent:statusline", event.agentName, event.data);
|
|
948
|
+
});
|
|
810
949
|
}
|
|
811
950
|
// ─── Lifecycle ───────────────────────────────────────────────────────
|
|
812
951
|
/**
|
|
@@ -817,6 +956,7 @@ var ClaudeCodeController = class extends import_node_events.EventEmitter {
|
|
|
817
956
|
if (this.initialized) return this;
|
|
818
957
|
await this.team.create({ cwd: this.cwd });
|
|
819
958
|
await this.tasks.init();
|
|
959
|
+
this.statusLineWatcher.ensureDir();
|
|
820
960
|
this.poller.start();
|
|
821
961
|
this.initialized = true;
|
|
822
962
|
this.log.info(
|
|
@@ -857,6 +997,7 @@ var ClaudeCodeController = class extends import_node_events.EventEmitter {
|
|
|
857
997
|
}
|
|
858
998
|
await this.processes.killAll();
|
|
859
999
|
this.poller.stop();
|
|
1000
|
+
this.statusLineWatcher.stop();
|
|
860
1001
|
await this.team.destroy();
|
|
861
1002
|
this.initialized = false;
|
|
862
1003
|
this.log.info("Controller shut down");
|
|
@@ -885,7 +1026,8 @@ var ClaudeCodeController = class extends import_node_events.EventEmitter {
|
|
|
885
1026
|
subscriptions: []
|
|
886
1027
|
};
|
|
887
1028
|
await this.team.addMember(member);
|
|
888
|
-
this.ensureWorkspaceTrusted(cwd);
|
|
1029
|
+
this.ensureWorkspaceTrusted(cwd, opts.name);
|
|
1030
|
+
this.statusLineWatcher.watchAgent(opts.name);
|
|
889
1031
|
const env = Object.keys(this.defaultEnv).length > 0 || opts.env ? { ...this.defaultEnv, ...opts.env } : void 0;
|
|
890
1032
|
const proc = this.processes.spawn({
|
|
891
1033
|
teamName: this.teamName,
|
|
@@ -1092,6 +1234,7 @@ var ClaudeCodeController = class extends import_node_events.EventEmitter {
|
|
|
1092
1234
|
* Kill a specific agent.
|
|
1093
1235
|
*/
|
|
1094
1236
|
async killAgent(name) {
|
|
1237
|
+
this.statusLineWatcher.unwatchAgent(name);
|
|
1095
1238
|
await this.processes.kill(name);
|
|
1096
1239
|
await this.team.removeMember(name);
|
|
1097
1240
|
}
|
|
@@ -1156,15 +1299,28 @@ var ClaudeCodeController = class extends import_node_events.EventEmitter {
|
|
|
1156
1299
|
/**
|
|
1157
1300
|
* Ensure the agent's cwd has a .claude/settings.local.json so the
|
|
1158
1301
|
* CLI skips the interactive workspace trust prompt.
|
|
1302
|
+
* Also injects statusLine capture configuration.
|
|
1159
1303
|
*/
|
|
1160
|
-
ensureWorkspaceTrusted(cwd) {
|
|
1161
|
-
const claudeDir = (0,
|
|
1162
|
-
const settingsPath = (0,
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1304
|
+
ensureWorkspaceTrusted(cwd, agentName) {
|
|
1305
|
+
const claudeDir = (0, import_node_path4.join)(cwd, ".claude");
|
|
1306
|
+
const settingsPath = (0, import_node_path4.join)(claudeDir, "settings.local.json");
|
|
1307
|
+
(0, import_node_fs5.mkdirSync)(claudeDir, { recursive: true });
|
|
1308
|
+
let settings = {};
|
|
1309
|
+
if ((0, import_node_fs5.existsSync)(settingsPath)) {
|
|
1310
|
+
try {
|
|
1311
|
+
settings = JSON.parse((0, import_node_fs5.readFileSync)(settingsPath, "utf-8"));
|
|
1312
|
+
} catch {
|
|
1313
|
+
settings = {};
|
|
1314
|
+
}
|
|
1167
1315
|
}
|
|
1316
|
+
if (agentName && !settings.statusLine) {
|
|
1317
|
+
const logPath = statusLineLogPath(this.teamName, agentName);
|
|
1318
|
+
const statusLineSettings = buildStatusLineSettings(logPath);
|
|
1319
|
+
settings = { ...settings, ...statusLineSettings };
|
|
1320
|
+
this.log.debug(`Injected statusLine capture for "${agentName}"`);
|
|
1321
|
+
}
|
|
1322
|
+
(0, import_node_fs5.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
1323
|
+
this.log.debug(`Updated ${settingsPath}`);
|
|
1168
1324
|
}
|
|
1169
1325
|
ensureInitialized() {
|
|
1170
1326
|
if (!this.initialized) {
|
|
@@ -1250,7 +1406,7 @@ function waitForReady(controller, agentName, timeoutMs = 15e3) {
|
|
|
1250
1406
|
controller.on("agent:exited", onExit);
|
|
1251
1407
|
});
|
|
1252
1408
|
}
|
|
1253
|
-
var Agent = class _Agent extends
|
|
1409
|
+
var Agent = class _Agent extends import_node_events3.EventEmitter {
|
|
1254
1410
|
controller;
|
|
1255
1411
|
handle;
|
|
1256
1412
|
ownsController;
|
|
@@ -1450,6 +1606,9 @@ IMPORTANT: You MUST send your complete answer back using the SendMessage tool. D
|
|
|
1450
1606
|
const onIdle = (name, _details) => {
|
|
1451
1607
|
if (name === agentName) this.emit("idle");
|
|
1452
1608
|
};
|
|
1609
|
+
const onStatusLine = (name, data) => {
|
|
1610
|
+
if (name === agentName) this.emit("statusline", data);
|
|
1611
|
+
};
|
|
1453
1612
|
const onPermission = (name, parsed) => {
|
|
1454
1613
|
if (name !== agentName) return;
|
|
1455
1614
|
let handled = false;
|
|
@@ -1498,6 +1657,7 @@ IMPORTANT: You MUST send your complete answer back using the SendMessage tool. D
|
|
|
1498
1657
|
};
|
|
1499
1658
|
this.controller.on("message", onMessage);
|
|
1500
1659
|
this.controller.on("idle", onIdle);
|
|
1660
|
+
this.controller.on("agent:statusline", onStatusLine);
|
|
1501
1661
|
this.controller.on("permission:request", onPermission);
|
|
1502
1662
|
this.controller.on("plan:approval_request", onPlan);
|
|
1503
1663
|
this.controller.on("agent:exited", onExit);
|
|
@@ -1505,6 +1665,7 @@ IMPORTANT: You MUST send your complete answer back using the SendMessage tool. D
|
|
|
1505
1665
|
this.boundListeners = [
|
|
1506
1666
|
{ event: "message", fn: onMessage },
|
|
1507
1667
|
{ event: "idle", fn: onIdle },
|
|
1668
|
+
{ event: "agent:statusline", fn: onStatusLine },
|
|
1508
1669
|
{ event: "permission:request", fn: onPermission },
|
|
1509
1670
|
{ event: "plan:approval_request", fn: onPlan },
|
|
1510
1671
|
{ event: "agent:exited", fn: onExit },
|
|
@@ -1651,8 +1812,11 @@ var claude = Object.assign(claudeCall, {
|
|
|
1651
1812
|
InboxPoller,
|
|
1652
1813
|
ProcessManager,
|
|
1653
1814
|
Session,
|
|
1815
|
+
StatusLineWatcher,
|
|
1654
1816
|
TaskManager,
|
|
1655
1817
|
TeamManager,
|
|
1818
|
+
buildStatusLineCommand,
|
|
1819
|
+
buildStatusLineSettings,
|
|
1656
1820
|
claude,
|
|
1657
1821
|
createLogger,
|
|
1658
1822
|
inboxPath,
|
|
@@ -1661,6 +1825,8 @@ var claude = Object.assign(claudeCall, {
|
|
|
1661
1825
|
readInbox,
|
|
1662
1826
|
readUnread,
|
|
1663
1827
|
silentLogger,
|
|
1828
|
+
statusLineDir,
|
|
1829
|
+
statusLineLogPath,
|
|
1664
1830
|
taskPath,
|
|
1665
1831
|
tasksBaseDir,
|
|
1666
1832
|
tasksDir,
|