agkan 3.4.0 → 3.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/README.ja.md +64 -0
- package/README.md +64 -0
- package/dist/board/BulkRunService.d.ts +33 -0
- package/dist/board/BulkRunService.d.ts.map +1 -0
- package/dist/board/BulkRunService.js +134 -0
- package/dist/board/BulkRunService.js.map +1 -0
- package/dist/board/boardRenderer.d.ts.map +1 -1
- package/dist/board/boardRenderer.js +13 -22
- package/dist/board/boardRenderer.js.map +1 -1
- package/dist/board/boardRoutes.d.ts +15 -2
- package/dist/board/boardRoutes.d.ts.map +1 -1
- package/dist/board/boardRoutes.js +260 -38
- package/dist/board/boardRoutes.js.map +1 -1
- package/dist/board/boardStyles.d.ts +1 -1
- package/dist/board/boardStyles.d.ts.map +1 -1
- package/dist/board/boardStyles.js +25 -0
- package/dist/board/boardStyles.js.map +1 -1
- package/dist/board/client/board.js +35 -36
- package/dist/board/client/main.css +252 -0
- package/dist/board/client/main.js +12063 -0
- package/dist/board/server.d.ts +2 -2
- package/dist/board/server.d.ts.map +1 -1
- package/dist/board/server.js +44 -8
- package/dist/board/server.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +13 -0
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/db/config.d.ts +10 -0
- package/dist/db/config.d.ts.map +1 -1
- package/dist/db/config.js.map +1 -1
- package/dist/hooks/claudeHookSettings.d.ts +2 -0
- package/dist/hooks/claudeHookSettings.d.ts.map +1 -0
- package/dist/hooks/claudeHookSettings.js +54 -0
- package/dist/hooks/claudeHookSettings.js.map +1 -0
- package/dist/hooks/hook-attention.mjs +54 -0
- package/dist/hooks/hook-stop.mjs +111 -0
- package/dist/services/AttentionStateService.d.ts +16 -0
- package/dist/services/AttentionStateService.d.ts.map +1 -0
- package/dist/services/AttentionStateService.js +42 -0
- package/dist/services/AttentionStateService.js.map +1 -0
- package/dist/services/ClaudeProcessService.d.ts +8 -1
- package/dist/services/ClaudeProcessService.d.ts.map +1 -1
- package/dist/services/ClaudeProcessService.js +25 -8
- package/dist/services/ClaudeProcessService.js.map +1 -1
- package/dist/terminal/PtySessionService.d.ts +50 -0
- package/dist/terminal/PtySessionService.d.ts.map +1 -0
- package/dist/terminal/PtySessionService.js +310 -0
- package/dist/terminal/PtySessionService.js.map +1 -0
- package/dist/terminal/wsTerminalServer.d.ts +7 -0
- package/dist/terminal/wsTerminalServer.d.ts.map +1 -0
- package/dist/terminal/wsTerminalServer.js +81 -0
- package/dist/terminal/wsTerminalServer.js.map +1 -0
- package/dist/utils/hookToken.d.ts +3 -0
- package/dist/utils/hookToken.d.ts.map +1 -0
- package/dist/utils/hookToken.js +24 -0
- package/dist/utils/hookToken.js.map +1 -0
- package/package.json +11 -5
package/dist/board/server.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ import { TagService } from '../services/TagService';
|
|
|
5
5
|
import { MetadataService } from '../services/MetadataService';
|
|
6
6
|
import { CommentService } from '../services/CommentService';
|
|
7
7
|
import { TaskBlockService } from '../services/TaskBlockService';
|
|
8
|
-
import {
|
|
8
|
+
import { PtySessionService } from '../terminal/PtySessionService';
|
|
9
9
|
import { StorageBackend } from '../db/types/repository';
|
|
10
|
-
export declare function createBoardApp(taskService?: TaskService, taskTagService?: TaskTagService, metadataService?: MetadataService, db?: StorageBackend, boardTitle?: string, tagService?: TagService, configDir?: string, commentService?: CommentService, taskBlockService?: TaskBlockService,
|
|
10
|
+
export declare function createBoardApp(taskService?: TaskService, taskTagService?: TaskTagService, metadataService?: MetadataService, db?: StorageBackend, boardTitle?: string, tagService?: TagService, configDir?: string, commentService?: CommentService, taskBlockService?: TaskBlockService, ptySessionService?: PtySessionService): Hono;
|
|
11
11
|
export declare function startBoardServer(port: number, boardTitle?: string): void;
|
|
12
12
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/board/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/board/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAM5B,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAIlE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAUxD,wBAAgB,cAAc,CAC5B,WAAW,CAAC,EAAE,WAAW,EACzB,cAAc,CAAC,EAAE,cAAc,EAC/B,eAAe,CAAC,EAAE,eAAe,EACjC,EAAE,CAAC,EAAE,cAAc,EACnB,UAAU,CAAC,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,UAAU,EACvB,SAAS,CAAC,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,cAAc,EAC/B,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,iBAAiB,CAAC,EAAE,iBAAiB,GACpC,IAAI,CAkBN;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CA8CxE"}
|
package/dist/board/server.js
CHANGED
|
@@ -8,17 +8,21 @@ exports.startBoardServer = startBoardServer;
|
|
|
8
8
|
const hono_1 = require("hono");
|
|
9
9
|
const node_server_1 = require("@hono/node-server");
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const os_1 = require("os");
|
|
12
|
+
const path_2 = require("path");
|
|
11
13
|
const TaskService_1 = require("../services/TaskService");
|
|
12
14
|
const TaskTagService_1 = require("../services/TaskTagService");
|
|
13
15
|
const TagService_1 = require("../services/TagService");
|
|
14
16
|
const MetadataService_1 = require("../services/MetadataService");
|
|
15
17
|
const CommentService_1 = require("../services/CommentService");
|
|
16
18
|
const TaskBlockService_1 = require("../services/TaskBlockService");
|
|
17
|
-
const
|
|
19
|
+
const PtySessionService_1 = require("../terminal/PtySessionService");
|
|
20
|
+
const AttentionStateService_1 = require("../services/AttentionStateService");
|
|
21
|
+
const wsTerminalServer_1 = require("../terminal/wsTerminalServer");
|
|
18
22
|
const connection_1 = require("../db/connection");
|
|
19
23
|
const config_1 = require("../db/config");
|
|
20
24
|
const boardRoutes_1 = require("./boardRoutes");
|
|
21
|
-
function createBoardApp(taskService, taskTagService, metadataService, db, boardTitle, tagService, configDir, commentService, taskBlockService,
|
|
25
|
+
function createBoardApp(taskService, taskTagService, metadataService, db, boardTitle, tagService, configDir, commentService, taskBlockService, ptySessionService) {
|
|
22
26
|
const app = new hono_1.Hono();
|
|
23
27
|
const resolvedConfigDir = configDir ?? path_1.default.join(process.cwd(), (0, config_1.getDefaultDirName)());
|
|
24
28
|
const resolvedDb = db ?? (0, connection_1.getStorageBackend)();
|
|
@@ -32,18 +36,50 @@ function createBoardApp(taskService, taskTagService, metadataService, db, boardT
|
|
|
32
36
|
database: resolvedDb,
|
|
33
37
|
boardTitle,
|
|
34
38
|
configDir: resolvedConfigDir,
|
|
35
|
-
|
|
39
|
+
ptySessionService,
|
|
36
40
|
};
|
|
37
41
|
(0, boardRoutes_1.registerBoardRoutes)(app, services);
|
|
38
42
|
return app;
|
|
39
43
|
}
|
|
40
44
|
function startBoardServer(port, boardTitle) {
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
const resolvedDb = (0, connection_1.getStorageBackend)();
|
|
46
|
+
const attentionStateService = new AttentionStateService_1.AttentionStateService();
|
|
47
|
+
const hookSettingsDataDir = process.env.AGKAN_DATA_DIR
|
|
48
|
+
? (0, path_2.join)(process.env.AGKAN_DATA_DIR, 'board-hooks')
|
|
49
|
+
: (0, path_2.join)((0, os_1.homedir)(), '.agkan', 'board-hooks');
|
|
50
|
+
const app = new hono_1.Hono();
|
|
51
|
+
const resolvedConfigDir = path_1.default.join(process.cwd(), (0, config_1.getDefaultDirName)());
|
|
52
|
+
const ptyService = new PtySessionService_1.PtySessionService(resolvedDb, {
|
|
53
|
+
boardApiUrl: '',
|
|
54
|
+
attentionStateService,
|
|
55
|
+
hookSettingsDataDir,
|
|
56
|
+
});
|
|
57
|
+
const services = {
|
|
58
|
+
ts: new TaskService_1.TaskService(resolvedDb),
|
|
59
|
+
tts: new TaskTagService_1.TaskTagService(resolvedDb),
|
|
60
|
+
tags: new TagService_1.TagService(resolvedDb),
|
|
61
|
+
ms: new MetadataService_1.MetadataService(resolvedDb),
|
|
62
|
+
cs: new CommentService_1.CommentService(resolvedDb),
|
|
63
|
+
tbs: new TaskBlockService_1.TaskBlockService(resolvedDb),
|
|
64
|
+
database: resolvedDb,
|
|
65
|
+
boardTitle,
|
|
66
|
+
configDir: resolvedConfigDir,
|
|
67
|
+
ptySessionService: ptyService,
|
|
68
|
+
};
|
|
69
|
+
(0, boardRoutes_1.registerBoardRoutes)(app, services);
|
|
70
|
+
(0, boardRoutes_1.registerAttentionStreamRoute)(app, { attentionStateService });
|
|
71
|
+
(0, boardRoutes_1.registerHookRoutes)(app, { attentionStateService, ptySessionService: ptyService });
|
|
72
|
+
(0, boardRoutes_1.registerTestHookTokenRoute)(app);
|
|
73
|
+
const server = (0, node_server_1.serve)({ fetch: app.fetch, port }, (info) => {
|
|
74
|
+
const boardApiUrl = `http://127.0.0.1:${info.port}`;
|
|
46
75
|
console.log(`Server is running on http://localhost:${info.port}`);
|
|
76
|
+
ptyService.setBoardApiUrl(boardApiUrl);
|
|
77
|
+
const { handleUpgrade } = (0, wsTerminalServer_1.createTerminalWsServer)(ptyService);
|
|
78
|
+
server.on('upgrade', (req, socket, head) => {
|
|
79
|
+
if (req.url?.startsWith('/api/terminal/')) {
|
|
80
|
+
handleUpgrade(req, socket, head);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
47
83
|
});
|
|
48
84
|
}
|
|
49
85
|
//# sourceMappingURL=server.js.map
|
package/dist/board/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/board/server.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/board/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8DpC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqCvD"}
|
|
@@ -32,6 +32,19 @@ const DEFAULT_CONFIG_CONTENT = `# agkan configuration file
|
|
|
32
32
|
#
|
|
33
33
|
# # Title displayed in the board UI
|
|
34
34
|
# title: Agent Kanban
|
|
35
|
+
|
|
36
|
+
# Model configuration
|
|
37
|
+
# Claude model used when executing planning and run commands via the board.
|
|
38
|
+
# Accepts full model names (e.g. claude-opus-4-7) or aliases (e.g. opus, sonnet, haiku).
|
|
39
|
+
# Valid effort values: low | medium | high | xhigh | max
|
|
40
|
+
# If omitted, the Claude CLI's default model is used.
|
|
41
|
+
# models:
|
|
42
|
+
# planning:
|
|
43
|
+
# model: opus
|
|
44
|
+
# effort: low
|
|
45
|
+
# run:
|
|
46
|
+
# model: sonnet
|
|
47
|
+
# effort: low
|
|
35
48
|
`;
|
|
36
49
|
const DEFAULT_TAGS = ['bug', 'security', 'improvement', 'test', 'performance', 'refactor', 'docs'];
|
|
37
50
|
function createDefaultTags() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;AAgEH,4CAqCC;AAlGD,4CAAoB;AACpB,gDAAwB;AACxB,4CAAuE;AACvE,6CAA4C;AAE5C,MAAM,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkC9B,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;AAEnG,SAAS,iBAAiB;IACxB,MAAM,UAAU,GAAG,IAAI,qBAAU,EAAE,CAAC;IAEpC,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,2CAA2C;YAC3C,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;gBACtC,UAAU,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,kEAAkE;YAClE,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBAC3E,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAgB,gBAAgB,CAAC,OAAgB;IAC/C,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,mDAAmD,CAAC;SAChE,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC1B,MAAM,cAAc,GAAG,IAAA,0BAAiB,GAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAA,0BAAiB,GAAE,CAAC;QACpC,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAExC,qBAAqB;QACrB,IAAI,YAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,YAAY,cAAc,iBAAiB,CAAC,CAAC;QAC3D,CAAC;aAAM,CAAC;YACN,YAAE,CAAC,aAAa,CAAC,UAAU,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAC;YAC7D,OAAO,CAAC,GAAG,CAAC,YAAY,cAAc,EAAE,CAAC,CAAC;QAC5C,CAAC;QAED,wBAAwB;QACxB,IAAI,YAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,4BAA4B,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,YAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,aAAa,CAAC,CAAC;QAChD,CAAC;QAED,sBAAsB;QACtB,IAAI,CAAC;YACH,iBAAiB,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,+DAA+D;YAC/D,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,OAAO,CAAC,KAAK,CAAC,2CAA2C,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/dist/db/config.d.ts
CHANGED
|
@@ -7,6 +7,16 @@ export interface Config {
|
|
|
7
7
|
port?: number;
|
|
8
8
|
title?: string;
|
|
9
9
|
};
|
|
10
|
+
models?: {
|
|
11
|
+
planning?: {
|
|
12
|
+
model?: string;
|
|
13
|
+
effort?: string;
|
|
14
|
+
};
|
|
15
|
+
run?: {
|
|
16
|
+
model?: string;
|
|
17
|
+
effort?: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
10
20
|
}
|
|
11
21
|
/**
|
|
12
22
|
* Load and parse the configuration file.
|
package/dist/db/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/db/config.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QACN,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAcnC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAIxC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAkBD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAmF5C"}
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/db/config.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QACN,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,MAAM,CAAC,EAAE;QACP,QAAQ,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/C,GAAG,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAC3C,CAAC;CACH;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAcnC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAIxC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAkBD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAmF5C"}
|
package/dist/db/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/db/config.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/db/config.ts"],"names":[],"mappings":";;;;;AAuBA,gCAcC;AAKD,gCAEC;AAKD,8CAEC;AAMD,0CAIC;AAKD,8CAEC;AAyBD,kDAmFC;AAhLD,4CAAoB;AACpB,gDAAwB;AACxB,sDAA2B;AAiB3B;;;GAGG;AACH,SAAgB,UAAU;IACxB,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;IAC3C,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC,CAAC;IAE5D,IAAI,YAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,YAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAC1D,OAAQ,iBAAI,CAAC,IAAI,CAAC,aAAa,CAAY,IAAI,EAAE,CAAC;QACpD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,SAAgB,UAAU;IACxB,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB;IAC/B,OAAO,UAAU,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,YAAY,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,SAAgB,eAAe;IAC7B,IAAI,CAAC,UAAU,EAAE;QAAE,OAAO,EAAE,CAAC;IAC7B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC9C,OAAO,QAAQ,CAAC,CAAC,CAAC,WAAW,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB;IAC/B,OAAO,UAAU,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB;IAC9B,OAAO,UAAU,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,WAAW,CAAC;AACvD,CAAC;AAED;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,MAAc;IACtC,OAAO,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;AACtE,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,mBAAmB;IACjC,yCAAyC;IACzC,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;QACjD,wDAAwD;QACxD,MAAM,YAAY,GAAG,cAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;QAE5F,gEAAgE;QAChE,IAAI,UAAU,EAAE,IAAI,gBAAgB,CAAC,YAAY,CAAC,EAAE,CAAC;YACnD,OAAO,CAAC,IAAI,CACV,wFAAwF,YAAY,IAAI;gBACtG,2DAA2D,CAC9D,CAAC;QACJ,CAAC;QAED,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,uCAAuC;IACvC,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;IAC3C,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC,CAAC;IAE5D,IAAI,YAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,YAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAC1D,MAAM,MAAM,GAAG,iBAAI,CAAC,IAAI,CAAC,aAAa,CAAW,CAAC;YAElD,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBAChB,wDAAwD;gBACxD,MAAM,MAAM,GAAG,cAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;gBAElG,gEAAgE;gBAChE,IAAI,UAAU,EAAE,IAAI,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC7C,OAAO,CAAC,IAAI,CACV,+EAA+E,MAAM,IAAI;wBACvF,2DAA2D,CAC9D,CAAC;gBACJ,CAAC;gBAED,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,2DAA2D;YAC3D,4DAA4D;QAC9D,CAAC;IACH,CAAC;SAAM,CAAC;QACN,2EAA2E;QAC3E,MAAM,oBAAoB,GAAG,uBAAuB,EAAE,CAAC;QACvD,MAAM,gBAAgB,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,oBAAoB,CAAC,CAAC;QAExE,IAAI,YAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CACV,iCAAiC,oBAAoB,WAAW;gBAC9D,wBAAwB,cAAc,6BAA6B,CACtE,CAAC;YAEF,IAAI,CAAC;gBACH,MAAM,aAAa,GAAG,YAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;gBAChE,MAAM,MAAM,GAAG,iBAAI,CAAC,IAAI,CAAC,aAAa,CAAW,CAAC;gBAElD,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;oBAChB,MAAM,MAAM,GAAG,cAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;oBAElG,IAAI,UAAU,EAAE,IAAI,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;wBAC7C,OAAO,CAAC,IAAI,CACV,+EAA+E,MAAM,IAAI;4BACvF,2DAA2D,CAC9D,CAAC;oBACJ,CAAC;oBAED,OAAO,MAAM,CAAC;gBAChB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,kBAAkB;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED,2BAA2B;IAC3B,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC9C,MAAM,UAAU,GAAG,UAAU,EAAE,IAAI,QAAQ,CAAC,CAAC,CAAC,QAAQ,QAAQ,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAChF,OAAO,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudeHookSettings.d.ts","sourceRoot":"","sources":["../../src/hooks/claudeHookSettings.ts"],"names":[],"mappings":"AAsCA,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAc9E"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ensureBoardHookSettings = ensureBoardHookSettings;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const ATTENTION_HOOK = (0, path_1.resolve)(__dirname, 'hook-attention.mjs');
|
|
7
|
+
const SESSION_START_HOOK = (0, path_1.resolve)(__dirname, 'hook-session-start.mjs');
|
|
8
|
+
const STOP_HOOK = (0, path_1.resolve)(__dirname, 'hook-stop.mjs');
|
|
9
|
+
const SETTINGS_FILE = 'board-hook-settings.json';
|
|
10
|
+
function buildSettings() {
|
|
11
|
+
return {
|
|
12
|
+
hooks: {
|
|
13
|
+
SessionStart: [
|
|
14
|
+
{
|
|
15
|
+
hooks: [{ type: 'command', command: `node ${SESSION_START_HOOK}` }],
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
PreToolUse: [
|
|
19
|
+
{
|
|
20
|
+
matcher: 'AskUserQuestion',
|
|
21
|
+
hooks: [{ type: 'command', command: `node ${ATTENTION_HOOK} pre` }],
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
PostToolUse: [
|
|
25
|
+
{
|
|
26
|
+
matcher: 'AskUserQuestion',
|
|
27
|
+
hooks: [{ type: 'command', command: `node ${ATTENTION_HOOK} post` }],
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
Stop: [
|
|
31
|
+
{
|
|
32
|
+
hooks: [{ type: 'command', command: `node ${STOP_HOOK}` }],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async function ensureBoardHookSettings(dataDir) {
|
|
39
|
+
await fs_1.promises.mkdir(dataDir, { recursive: true });
|
|
40
|
+
const path = (0, path_1.join)(dataDir, SETTINGS_FILE);
|
|
41
|
+
const desired = JSON.stringify(buildSettings(), null, 2);
|
|
42
|
+
let existing = null;
|
|
43
|
+
try {
|
|
44
|
+
existing = await fs_1.promises.readFile(path, 'utf-8');
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// ignore - file does not exist yet
|
|
48
|
+
}
|
|
49
|
+
if (existing !== desired) {
|
|
50
|
+
await fs_1.promises.writeFile(path, desired, 'utf-8');
|
|
51
|
+
}
|
|
52
|
+
return path;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=claudeHookSettings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudeHookSettings.js","sourceRoot":"","sources":["../../src/hooks/claudeHookSettings.ts"],"names":[],"mappings":";;AAsCA,0DAcC;AApDD,2BAAoC;AACpC,+BAAqC;AAErC,MAAM,cAAc,GAAG,IAAA,cAAO,EAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;AAChE,MAAM,kBAAkB,GAAG,IAAA,cAAO,EAAC,SAAS,EAAE,wBAAwB,CAAC,CAAC;AACxE,MAAM,SAAS,GAAG,IAAA,cAAO,EAAC,SAAS,EAAE,eAAe,CAAC,CAAC;AAEtD,MAAM,aAAa,GAAG,0BAA0B,CAAC;AAEjD,SAAS,aAAa;IACpB,OAAO;QACL,KAAK,EAAE;YACL,YAAY,EAAE;gBACZ;oBACE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,kBAAkB,EAAE,EAAE,CAAC;iBACpE;aACF;YACD,UAAU,EAAE;gBACV;oBACE,OAAO,EAAE,iBAAiB;oBAC1B,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,cAAc,MAAM,EAAE,CAAC;iBACpE;aACF;YACD,WAAW,EAAE;gBACX;oBACE,OAAO,EAAE,iBAAiB;oBAC1B,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,cAAc,OAAO,EAAE,CAAC;iBACrE;aACF;YACD,IAAI,EAAE;gBACJ;oBACE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,SAAS,EAAE,EAAE,CAAC;iBAC3D;aACF;SACF;KACF,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,uBAAuB,CAAC,OAAe;IAC3D,MAAM,aAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAA,WAAI,EAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACzD,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,aAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;IACrC,CAAC;IACD,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,aAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
|
|
4
|
+
const argSubcmd = process.argv[2];
|
|
5
|
+
const taskIdRaw = process.env.BOARD_TASK_ID;
|
|
6
|
+
const apiUrl = process.env.BOARD_API_URL;
|
|
7
|
+
const token = process.env.BOARD_HOOK_TOKEN;
|
|
8
|
+
|
|
9
|
+
if (!taskIdRaw || !apiUrl || !token) {
|
|
10
|
+
process.exit(0);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const taskId = Number(taskIdRaw);
|
|
14
|
+
|
|
15
|
+
if (!Number.isFinite(taskId)) {
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Ignore events from subagents — only the main session should trigger attention.
|
|
20
|
+
try {
|
|
21
|
+
const mainSessionId = readFileSync(`/tmp/board-main-session-${taskIdRaw}`, 'utf-8').trim();
|
|
22
|
+
if (mainSessionId) {
|
|
23
|
+
const chunks = [];
|
|
24
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
25
|
+
const payload = JSON.parse(Buffer.concat(chunks).toString('utf-8'));
|
|
26
|
+
const currentSessionId = payload?.session_id;
|
|
27
|
+
// Skip if no session_id or if it doesn't match the main session (subagent).
|
|
28
|
+
if (!currentSessionId || currentSessionId !== mainSessionId) {
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
} catch {
|
|
33
|
+
// If the session file doesn't exist or stdin can't be parsed, proceed normally.
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const state = argSubcmd === 'post' ? 'answered' : 'needs';
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const res = await fetch(`${apiUrl}/api/internal/hooks/attention`, {
|
|
40
|
+
method: 'POST',
|
|
41
|
+
headers: {
|
|
42
|
+
'content-type': 'application/json',
|
|
43
|
+
'x-hook-token': token,
|
|
44
|
+
},
|
|
45
|
+
body: JSON.stringify({ taskId, state }),
|
|
46
|
+
});
|
|
47
|
+
if (!res.ok) {
|
|
48
|
+
process.stderr.write(`hook-attention: API responded ${res.status}\n`);
|
|
49
|
+
}
|
|
50
|
+
} catch (err) {
|
|
51
|
+
process.stderr.write(`hook-attention: ${(err && err.message) || err}\n`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
process.exit(0);
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { promises as fs } from 'fs';
|
|
3
|
+
|
|
4
|
+
async function readStdin() {
|
|
5
|
+
const chunks = [];
|
|
6
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
7
|
+
return Buffer.concat(chunks).toString('utf-8');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function findLastToolUse(jsonl) {
|
|
11
|
+
const lines = jsonl.split('\n').filter((l) => l.trim().length > 0);
|
|
12
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
13
|
+
let entry;
|
|
14
|
+
try {
|
|
15
|
+
entry = JSON.parse(lines[i]);
|
|
16
|
+
} catch {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
const content = entry?.message?.content;
|
|
20
|
+
if (!Array.isArray(content)) continue;
|
|
21
|
+
for (let j = content.length - 1; j >= 0; j--) {
|
|
22
|
+
const item = content[j];
|
|
23
|
+
if (item && item.type === 'tool_use' && typeof item.name === 'string') {
|
|
24
|
+
return { name: item.name, input: item.input ?? {} };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function main() {
|
|
32
|
+
const taskIdRaw = process.env.BOARD_TASK_ID;
|
|
33
|
+
const apiUrl = process.env.BOARD_API_URL;
|
|
34
|
+
const token = process.env.BOARD_HOOK_TOKEN;
|
|
35
|
+
if (!taskIdRaw || !apiUrl || !token) return;
|
|
36
|
+
|
|
37
|
+
let payload;
|
|
38
|
+
try {
|
|
39
|
+
const stdin = await readStdin();
|
|
40
|
+
payload = JSON.parse(stdin);
|
|
41
|
+
} catch {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Avoid recursion: when the stop hook itself was the cause of the stop event,
|
|
46
|
+
// Claude sets stop_hook_active=true. We must not act again in that case.
|
|
47
|
+
if (payload?.stop_hook_active === true) return;
|
|
48
|
+
|
|
49
|
+
const transcriptPath = payload?.transcript_path;
|
|
50
|
+
if (typeof transcriptPath !== 'string') return;
|
|
51
|
+
|
|
52
|
+
let jsonl;
|
|
53
|
+
try {
|
|
54
|
+
jsonl = await fs.readFile(transcriptPath, 'utf-8');
|
|
55
|
+
} catch (err) {
|
|
56
|
+
process.stderr.write(`hook-stop: read transcript failed: ${err.message}\n`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const lastTool = findLastToolUse(jsonl);
|
|
61
|
+
if (lastTool?.name === 'AskUserQuestion') return;
|
|
62
|
+
// When Claude ends a turn with a backgrounded Bash still running,
|
|
63
|
+
// do not signal "complete" to the server: that would kill the PTY
|
|
64
|
+
// session and abort the still-running background job.
|
|
65
|
+
if (
|
|
66
|
+
lastTool?.name === 'Bash' &&
|
|
67
|
+
lastTool.input &&
|
|
68
|
+
typeof lastTool.input === 'object' &&
|
|
69
|
+
lastTool.input.run_in_background === true
|
|
70
|
+
) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
// Monitor is always waiting for streamed events from a background process.
|
|
74
|
+
// Signalling "complete" while Monitor is active would abort the wait.
|
|
75
|
+
if (lastTool?.name === 'Monitor') {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const taskId = Number(taskIdRaw);
|
|
80
|
+
if (!Number.isFinite(taskId)) return;
|
|
81
|
+
|
|
82
|
+
// Clean up the main-session file so stale IDs don't persist across task restarts.
|
|
83
|
+
const sessionFile = `/tmp/board-main-session-${taskIdRaw}`;
|
|
84
|
+
try {
|
|
85
|
+
const mainSessionId = (await fs.readFile(sessionFile, 'utf-8')).trim();
|
|
86
|
+
if (mainSessionId && mainSessionId === payload?.session_id) {
|
|
87
|
+
await fs.unlink(sessionFile).catch(() => {});
|
|
88
|
+
}
|
|
89
|
+
} catch {
|
|
90
|
+
// file may not exist; ignore
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const res = await fetch(`${apiUrl}/api/internal/hooks/stop`, {
|
|
95
|
+
method: 'POST',
|
|
96
|
+
headers: {
|
|
97
|
+
'content-type': 'application/json',
|
|
98
|
+
'x-hook-token': token,
|
|
99
|
+
},
|
|
100
|
+
body: JSON.stringify({ taskId, reason: 'complete' }),
|
|
101
|
+
});
|
|
102
|
+
if (!res.ok) {
|
|
103
|
+
process.stderr.write(`hook-stop: API responded ${res.status}\n`);
|
|
104
|
+
}
|
|
105
|
+
} catch (err) {
|
|
106
|
+
process.stderr.write(`hook-stop: ${(err && err.message) || err}\n`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
await main();
|
|
111
|
+
process.exit(0);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type AttentionUpdate = {
|
|
2
|
+
taskId: number;
|
|
3
|
+
needsAttention: boolean;
|
|
4
|
+
};
|
|
5
|
+
export type AttentionSubscriber = (update: AttentionUpdate) => void;
|
|
6
|
+
export declare class AttentionStateService {
|
|
7
|
+
private state;
|
|
8
|
+
private subscribers;
|
|
9
|
+
setAttention(taskId: number, needs: boolean): void;
|
|
10
|
+
getAttention(taskId: number): boolean;
|
|
11
|
+
listAttentionTasks(): number[];
|
|
12
|
+
clearTask(taskId: number): void;
|
|
13
|
+
subscribe(cb: AttentionSubscriber): () => void;
|
|
14
|
+
private notify;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=AttentionStateService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AttentionStateService.d.ts","sourceRoot":"","sources":["../../src/services/AttentionStateService.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,OAAO,CAAA;CAAE,CAAC;AAC1E,MAAM,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;AAEpE,qBAAa,qBAAqB;IAChC,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,WAAW,CAAkC;IAErD,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAOlD,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIrC,kBAAkB,IAAI,MAAM,EAAE;IAI9B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAS/B,SAAS,CAAC,EAAE,EAAE,mBAAmB,GAAG,MAAM,IAAI;IAO9C,OAAO,CAAC,MAAM;CAKf"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AttentionStateService = void 0;
|
|
4
|
+
class AttentionStateService {
|
|
5
|
+
state = new Map();
|
|
6
|
+
subscribers = new Set();
|
|
7
|
+
setAttention(taskId, needs) {
|
|
8
|
+
const prev = this.state.get(taskId) ?? false;
|
|
9
|
+
if (prev === needs)
|
|
10
|
+
return;
|
|
11
|
+
this.state.set(taskId, needs);
|
|
12
|
+
this.notify({ taskId, needsAttention: needs });
|
|
13
|
+
}
|
|
14
|
+
getAttention(taskId) {
|
|
15
|
+
return this.state.get(taskId) ?? false;
|
|
16
|
+
}
|
|
17
|
+
listAttentionTasks() {
|
|
18
|
+
return [...this.state.entries()].filter(([, v]) => v).map(([k]) => k);
|
|
19
|
+
}
|
|
20
|
+
clearTask(taskId) {
|
|
21
|
+
const prev = this.state.get(taskId);
|
|
22
|
+
if (prev === undefined)
|
|
23
|
+
return;
|
|
24
|
+
this.state.delete(taskId);
|
|
25
|
+
if (prev) {
|
|
26
|
+
this.notify({ taskId, needsAttention: false });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
subscribe(cb) {
|
|
30
|
+
this.subscribers.add(cb);
|
|
31
|
+
return () => {
|
|
32
|
+
this.subscribers.delete(cb);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
notify(update) {
|
|
36
|
+
for (const cb of this.subscribers) {
|
|
37
|
+
cb(update);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.AttentionStateService = AttentionStateService;
|
|
42
|
+
//# sourceMappingURL=AttentionStateService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AttentionStateService.js","sourceRoot":"","sources":["../../src/services/AttentionStateService.ts"],"names":[],"mappings":";;;AAGA,MAAa,qBAAqB;IACxB,KAAK,GAAG,IAAI,GAAG,EAAmB,CAAC;IACnC,WAAW,GAAG,IAAI,GAAG,EAAuB,CAAC;IAErD,YAAY,CAAC,MAAc,EAAE,KAAc;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC;QAC7C,IAAI,IAAI,KAAK,KAAK;YAAE,OAAO;QAC3B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,YAAY,CAAC,MAAc;QACzB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC;IACzC,CAAC;IAED,kBAAkB;QAChB,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,SAAS,CAAC,MAAc;QACtB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO;QAC/B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED,SAAS,CAAC,EAAuB;QAC/B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACzB,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC9B,CAAC,CAAC;IACJ,CAAC;IAEO,MAAM,CAAC,MAAuB;QACpC,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAClC,EAAE,CAAC,MAAM,CAAC,CAAC;QACb,CAAC;IACH,CAAC;CACF;AAxCD,sDAwCC"}
|
|
@@ -58,18 +58,25 @@ export interface RunLog {
|
|
|
58
58
|
* Manages claude CLI processes running in stream-json mode.
|
|
59
59
|
* Keyed by taskId, supports start/stop/subscribe/list operations.
|
|
60
60
|
*/
|
|
61
|
+
export type CompletionConfirmCallback = (taskId: number, targetStatus: string) => void;
|
|
61
62
|
export declare class ClaudeProcessService {
|
|
62
63
|
private processes;
|
|
63
64
|
private db;
|
|
64
65
|
private runningTasksChangeSubscribers;
|
|
66
|
+
private userStoppedTasks;
|
|
67
|
+
private completionConfirmSubscribers;
|
|
65
68
|
constructor(db?: StorageBackend | null);
|
|
66
69
|
subscribeRunningTasksChange(callback: () => void): () => void;
|
|
70
|
+
subscribeCompletionConfirm(callback: CompletionConfirmCallback): () => void;
|
|
71
|
+
notifyCompletionConfirm(taskId: number, targetStatus: string): void;
|
|
72
|
+
isUserStopped(taskId: number): boolean;
|
|
73
|
+
private clearUserStopped;
|
|
67
74
|
private notifyRunningTasksChange;
|
|
68
75
|
/**
|
|
69
76
|
* Start a claude process for the given taskId and prompt.
|
|
70
77
|
* Prevents duplicate processes for the same taskId.
|
|
71
78
|
*/
|
|
72
|
-
startProcess(taskId: number, prompt: string, command?: string): void;
|
|
79
|
+
startProcess(taskId: number, prompt: string, command?: string, model?: string, effort?: string): void;
|
|
73
80
|
/**
|
|
74
81
|
* Stop the process for the given taskId.
|
|
75
82
|
* Returns true if the process was found and signalled, false otherwise.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClaudeProcessService.d.ts","sourceRoot":"","sources":["../../src/services/ClaudeProcessService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAmB7D,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GAChF;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE;QACP,OAAO,EAAE,KAAK,CACV;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,GAC9B;YAAE,IAAI,EAAE,UAAU,CAAC;YAAC,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAAE,CACjF,CAAC;QACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,GACD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GAClG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAE7C,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvC,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;AAE7D,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAiBD;;;;GAIG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,SAAS,CAAuC;IACxD,OAAO,CAAC,EAAE,CAAwB;IAClC,OAAO,CAAC,6BAA6B,CAA8B;
|
|
1
|
+
{"version":3,"file":"ClaudeProcessService.d.ts","sourceRoot":"","sources":["../../src/services/ClaudeProcessService.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,16 +16,12 @@ function resolveClaudePath() {
|
|
|
16
16
|
return 'claude';
|
|
17
17
|
}
|
|
18
18
|
const CLAUDE_BIN = resolveClaudePath();
|
|
19
|
-
// ---- ClaudeProcessService ----
|
|
20
|
-
/**
|
|
21
|
-
* ClaudeProcessService
|
|
22
|
-
* Manages claude CLI processes running in stream-json mode.
|
|
23
|
-
* Keyed by taskId, supports start/stop/subscribe/list operations.
|
|
24
|
-
*/
|
|
25
19
|
class ClaudeProcessService {
|
|
26
20
|
processes = new Map();
|
|
27
21
|
db;
|
|
28
22
|
runningTasksChangeSubscribers = new Set();
|
|
23
|
+
userStoppedTasks = new Set();
|
|
24
|
+
completionConfirmSubscribers = new Set();
|
|
29
25
|
constructor(db) {
|
|
30
26
|
this.db = db ?? null;
|
|
31
27
|
}
|
|
@@ -35,6 +31,21 @@ class ClaudeProcessService {
|
|
|
35
31
|
this.runningTasksChangeSubscribers.delete(callback);
|
|
36
32
|
};
|
|
37
33
|
}
|
|
34
|
+
subscribeCompletionConfirm(callback) {
|
|
35
|
+
this.completionConfirmSubscribers.add(callback);
|
|
36
|
+
return () => {
|
|
37
|
+
this.completionConfirmSubscribers.delete(callback);
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
notifyCompletionConfirm(taskId, targetStatus) {
|
|
41
|
+
this.completionConfirmSubscribers.forEach((cb) => cb(taskId, targetStatus));
|
|
42
|
+
}
|
|
43
|
+
isUserStopped(taskId) {
|
|
44
|
+
return this.userStoppedTasks.has(taskId);
|
|
45
|
+
}
|
|
46
|
+
clearUserStopped(taskId) {
|
|
47
|
+
this.userStoppedTasks.delete(taskId);
|
|
48
|
+
}
|
|
38
49
|
notifyRunningTasksChange() {
|
|
39
50
|
this.runningTasksChangeSubscribers.forEach((cb) => cb());
|
|
40
51
|
}
|
|
@@ -42,7 +53,7 @@ class ClaudeProcessService {
|
|
|
42
53
|
* Start a claude process for the given taskId and prompt.
|
|
43
54
|
* Prevents duplicate processes for the same taskId.
|
|
44
55
|
*/
|
|
45
|
-
startProcess(taskId, prompt, command = 'run') {
|
|
56
|
+
startProcess(taskId, prompt, command = 'run', model, effort) {
|
|
46
57
|
if (this.processes.has(taskId)) {
|
|
47
58
|
const existing = this.processes.get(taskId);
|
|
48
59
|
const pid = existing.process.pid;
|
|
@@ -54,7 +65,11 @@ class ClaudeProcessService {
|
|
|
54
65
|
throw new errors_1.ConflictError(`Process for taskId ${taskId} is already running`);
|
|
55
66
|
}
|
|
56
67
|
(0, logger_1.verboseLog)(`[ClaudeProcessService] startProcess taskId=${taskId} command=${command}`);
|
|
57
|
-
const
|
|
68
|
+
const baseArgs = ['--output-format', 'stream-json', '--verbose', '--dangerously-skip-permissions', '-p', prompt];
|
|
69
|
+
const effortArgs = effort ? ['--effort', effort] : [];
|
|
70
|
+
const modelArgs = model ? ['--model', model] : [];
|
|
71
|
+
const args = [...modelArgs, ...effortArgs, ...baseArgs];
|
|
72
|
+
const child = (0, child_process_1.spawn)(CLAUDE_BIN, args, {
|
|
58
73
|
cwd: process.cwd(),
|
|
59
74
|
env: process.env,
|
|
60
75
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
@@ -177,6 +192,7 @@ class ClaudeProcessService {
|
|
|
177
192
|
else {
|
|
178
193
|
(0, logger_1.verboseLog)(`[ClaudeProcessService] process close skipped map delete (stale entry) taskId=${taskId}`);
|
|
179
194
|
}
|
|
195
|
+
this.clearUserStopped(taskId);
|
|
180
196
|
});
|
|
181
197
|
}
|
|
182
198
|
/**
|
|
@@ -190,6 +206,7 @@ class ClaudeProcessService {
|
|
|
190
206
|
return false;
|
|
191
207
|
}
|
|
192
208
|
(0, logger_1.verboseLog)(`[ClaudeProcessService] stopProcess taskId=${taskId} sending SIGTERM`);
|
|
209
|
+
this.userStoppedTasks.add(taskId);
|
|
193
210
|
info.process.kill('SIGTERM');
|
|
194
211
|
this.processes.delete(taskId);
|
|
195
212
|
(0, logger_1.verboseLog)(`[ClaudeProcessService] process removed from map (stop) taskId=${taskId} total=${this.processes.size}`);
|