github-issue-tower-defence-management 1.113.0 → 1.114.1
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/CHANGELOG.md +14 -0
- package/README.md +2 -2
- package/bin/adapter/entry-points/console/consoleReadApi.js +11 -1
- package/bin/adapter/entry-points/console/consoleReadApi.js.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/{index-CEJmPNRK.css → index-Blb_xqIx.css} +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-DQyZ8KpG.js +101 -0
- package/bin/adapter/entry-points/console/ui-dist/index.html +2 -2
- package/bin/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.js +36 -27
- package/bin/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.js.map +1 -1
- package/bin/adapter/repositories/FileSystemSessionRecordReader.js +69 -0
- package/bin/adapter/repositories/FileSystemSessionRecordReader.js.map +1 -0
- package/bin/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.js +9 -2
- package/bin/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.js.map +1 -1
- package/bin/domain/usecases/ResolveInteractiveLiveSessionsUseCase.js +15 -0
- package/bin/domain/usecases/ResolveInteractiveLiveSessionsUseCase.js.map +1 -1
- package/bin/domain/usecases/adapter-interfaces/SessionRecordReader.js +3 -0
- package/bin/domain/usecases/adapter-interfaces/SessionRecordReader.js.map +1 -0
- package/package.json +1 -1
- package/src/adapter/entry-points/console/consoleReadApi.test.ts +82 -0
- package/src/adapter/entry-points/console/consoleReadApi.ts +21 -1
- package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMarkdownContent.stories.tsx +16 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMarkdownContent.test.tsx +61 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMarkdownContent.tsx +59 -5
- package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleReferenceLink.stories.tsx +76 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleReferenceLink.test.tsx +56 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleReferenceLink.tsx +39 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCommentList.tsx +4 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.stories.tsx +24 -4
- package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.test.tsx +13 -3
- package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.tsx +6 -0
- package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsolePullRequestDetail.tsx +4 -0
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleItemDetailData.test.ts +1 -0
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleItemDetailData.ts +1 -0
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleReferenceLink.test.ts +48 -0
- package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleReferenceLink.ts +39 -0
- package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.test.ts +25 -2
- package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.ts +2 -1
- package/src/adapter/entry-points/console/ui/src/features/console/logic/references.test.ts +80 -0
- package/src/adapter/entry-points/console/ui/src/features/console/logic/references.ts +44 -0
- package/src/adapter/entry-points/console/ui/src/features/console/logic/types.ts +1 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.test.tsx +1 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.tsx +12 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleReferenceLinkContainer.tsx +25 -0
- package/src/adapter/entry-points/console/ui/src/features/console/testing/fixtures.ts +40 -0
- package/src/adapter/entry-points/console/ui/src/index.css +23 -0
- package/src/adapter/entry-points/console/ui-dist/assets/{index-CEJmPNRK.css → index-Blb_xqIx.css} +1 -1
- package/src/adapter/entry-points/console/ui-dist/assets/index-DQyZ8KpG.js +101 -0
- package/src/adapter/entry-points/console/ui-dist/index.html +2 -2
- package/src/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.test.ts +107 -26
- package/src/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.ts +49 -29
- package/src/adapter/repositories/FileSystemSessionRecordReader.test.ts +59 -0
- package/src/adapter/repositories/FileSystemSessionRecordReader.ts +31 -0
- package/src/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.test.ts +51 -0
- package/src/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.ts +10 -1
- package/src/domain/entities/InteractiveLiveSession.ts +1 -0
- package/src/domain/entities/LiveSessionProcessSnapshot.ts +1 -0
- package/src/domain/usecases/NotifySilentLiveSessionsUseCase.test.ts +4 -0
- package/src/domain/usecases/ResolveInteractiveLiveSessionsUseCase.test.ts +66 -59
- package/src/domain/usecases/ResolveInteractiveLiveSessionsUseCase.ts +19 -0
- package/src/domain/usecases/adapter-interfaces/SessionRecordReader.ts +3 -0
- package/types/adapter/entry-points/console/consoleReadApi.d.ts +1 -0
- package/types/adapter/entry-points/console/consoleReadApi.d.ts.map +1 -1
- package/types/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.d.ts +4 -11
- package/types/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.d.ts.map +1 -1
- package/types/adapter/repositories/FileSystemSessionRecordReader.d.ts +5 -0
- package/types/adapter/repositories/FileSystemSessionRecordReader.d.ts.map +1 -0
- package/types/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.d.ts +3 -1
- package/types/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.d.ts.map +1 -1
- package/types/domain/entities/InteractiveLiveSession.d.ts +1 -0
- package/types/domain/entities/InteractiveLiveSession.d.ts.map +1 -1
- package/types/domain/entities/LiveSessionProcessSnapshot.d.ts +1 -0
- package/types/domain/entities/LiveSessionProcessSnapshot.d.ts.map +1 -1
- package/types/domain/usecases/ResolveInteractiveLiveSessionsUseCase.d.ts +1 -0
- package/types/domain/usecases/ResolveInteractiveLiveSessionsUseCase.d.ts.map +1 -1
- package/types/domain/usecases/adapter-interfaces/SessionRecordReader.d.ts +4 -0
- package/types/domain/usecases/adapter-interfaces/SessionRecordReader.d.ts.map +1 -0
- package/bin/adapter/entry-points/console/ui-dist/assets/index-DfNrA5uV.js +0 -101
- package/src/adapter/entry-points/console/ui-dist/assets/index-DfNrA5uV.js +0 -101
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>TDPM Console</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-DQyZ8KpG.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-Blb_xqIx.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.FileSystemInteractiveLiveSessionTranscriptResolver = void 0;
|
|
37
37
|
const fs = __importStar(require("fs"));
|
|
38
|
+
const os = __importStar(require("os"));
|
|
38
39
|
const path = __importStar(require("path"));
|
|
39
40
|
const modifiedEpochMs = (filePath) => {
|
|
40
41
|
try {
|
|
@@ -45,19 +46,10 @@ const modifiedEpochMs = (filePath) => {
|
|
|
45
46
|
return null;
|
|
46
47
|
}
|
|
47
48
|
};
|
|
48
|
-
|
|
49
|
-
* Resolves the real transcript path of an interactive Claude Code session from
|
|
50
|
-
* the session id and config directory taken from the session's process
|
|
51
|
-
* environment. The transcript lives at
|
|
52
|
-
* `<configDir>/projects/<cwd-slug>/<sessionId>.jsonl`; this resolver scans the
|
|
53
|
-
* `projects` subdirectories for a file named `<sessionId>.jsonl` and returns the
|
|
54
|
-
* most recently modified match. Because resolution is keyed on the process
|
|
55
|
-
* session id rather than on a session name or issue URL, a plain-named session
|
|
56
|
-
* (for example one named `workbench`) resolves just as well as an issue-url
|
|
57
|
-
* named one.
|
|
58
|
-
*/
|
|
49
|
+
const defaultSharedProjectsDirectory = () => path.join(os.homedir(), '.claude', 'projects');
|
|
59
50
|
class FileSystemInteractiveLiveSessionTranscriptResolver {
|
|
60
|
-
constructor() {
|
|
51
|
+
constructor(sharedProjectsDirectory = defaultSharedProjectsDirectory()) {
|
|
52
|
+
this.sharedProjectsDirectory = sharedProjectsDirectory;
|
|
61
53
|
this.resolveTranscriptPaths = (sessions) => {
|
|
62
54
|
const resolved = new Map();
|
|
63
55
|
for (const session of sessions) {
|
|
@@ -69,7 +61,34 @@ class FileSystemInteractiveLiveSessionTranscriptResolver {
|
|
|
69
61
|
return resolved;
|
|
70
62
|
};
|
|
71
63
|
this.resolveTranscriptPath = (session) => {
|
|
72
|
-
const
|
|
64
|
+
const projectsDirectories = this.listProjectsDirectories(session.configDir);
|
|
65
|
+
let latestPath = null;
|
|
66
|
+
let latestEpochMs = -Infinity;
|
|
67
|
+
for (const candidateSessionId of session.candidateSessionIds) {
|
|
68
|
+
const fileName = `${candidateSessionId}.jsonl`;
|
|
69
|
+
for (const projectsDirectory of projectsDirectories) {
|
|
70
|
+
for (const candidate of this.listCandidatePaths(projectsDirectory, fileName)) {
|
|
71
|
+
const epochMs = modifiedEpochMs(candidate);
|
|
72
|
+
if (epochMs === null) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (epochMs > latestEpochMs) {
|
|
76
|
+
latestEpochMs = epochMs;
|
|
77
|
+
latestPath = candidate;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return latestPath;
|
|
83
|
+
};
|
|
84
|
+
this.listProjectsDirectories = (configDir) => {
|
|
85
|
+
const perSessionProjectsDirectory = path.join(configDir, 'projects');
|
|
86
|
+
if (perSessionProjectsDirectory === this.sharedProjectsDirectory) {
|
|
87
|
+
return [perSessionProjectsDirectory];
|
|
88
|
+
}
|
|
89
|
+
return [perSessionProjectsDirectory, this.sharedProjectsDirectory];
|
|
90
|
+
};
|
|
91
|
+
this.listCandidatePaths = (projectsDirectory, fileName) => {
|
|
73
92
|
let projectEntries;
|
|
74
93
|
try {
|
|
75
94
|
projectEntries = fs.readdirSync(projectsDirectory, {
|
|
@@ -77,26 +96,16 @@ class FileSystemInteractiveLiveSessionTranscriptResolver {
|
|
|
77
96
|
});
|
|
78
97
|
}
|
|
79
98
|
catch {
|
|
80
|
-
return
|
|
99
|
+
return [];
|
|
81
100
|
}
|
|
82
|
-
const
|
|
83
|
-
let latestPath = null;
|
|
84
|
-
let latestEpochMs = -Infinity;
|
|
101
|
+
const candidatePaths = [];
|
|
85
102
|
for (const projectEntry of projectEntries) {
|
|
86
103
|
if (!projectEntry.isDirectory()) {
|
|
87
104
|
continue;
|
|
88
105
|
}
|
|
89
|
-
|
|
90
|
-
const epochMs = modifiedEpochMs(candidate);
|
|
91
|
-
if (epochMs === null) {
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
if (epochMs > latestEpochMs) {
|
|
95
|
-
latestEpochMs = epochMs;
|
|
96
|
-
latestPath = candidate;
|
|
97
|
-
}
|
|
106
|
+
candidatePaths.push(path.join(projectsDirectory, projectEntry.name, fileName));
|
|
98
107
|
}
|
|
99
|
-
return
|
|
108
|
+
return candidatePaths;
|
|
100
109
|
};
|
|
101
110
|
}
|
|
102
111
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileSystemInteractiveLiveSessionTranscriptResolver.js","sourceRoot":"","sources":["../../../src/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,2CAA6B;AAI7B,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAiB,EAAE;IAC1D,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"FileSystemInteractiveLiveSessionTranscriptResolver.js","sourceRoot":"","sources":["../../../src/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.FileSystemSessionRecordReader = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const isRecord = (value) => typeof value === 'object' && value !== null;
|
|
40
|
+
class FileSystemSessionRecordReader {
|
|
41
|
+
constructor() {
|
|
42
|
+
this.readCurrentSessionId = (configDir, pid) => {
|
|
43
|
+
const recordPath = path.join(configDir, 'sessions', `${pid}.json`);
|
|
44
|
+
let content;
|
|
45
|
+
try {
|
|
46
|
+
content = fs.readFileSync(recordPath, 'utf8');
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
let parsed;
|
|
52
|
+
try {
|
|
53
|
+
parsed = JSON.parse(content);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
if (!isRecord(parsed)) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const sessionId = parsed.sessionId;
|
|
62
|
+
return typeof sessionId === 'string' && sessionId.length > 0
|
|
63
|
+
? sessionId
|
|
64
|
+
: null;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.FileSystemSessionRecordReader = FileSystemSessionRecordReader;
|
|
69
|
+
//# sourceMappingURL=FileSystemSessionRecordReader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileSystemSessionRecordReader.js","sourceRoot":"","sources":["../../../src/adapter/repositories/FileSystemSessionRecordReader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,2CAA6B;AAG7B,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CACpE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AAE9C,MAAa,6BAA6B;IAA1C;QACE,yBAAoB,GAAG,CAAC,SAAiB,EAAE,GAAW,EAAiB,EAAE;YACvE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC;YACnE,IAAI,OAAe,CAAC;YACpB,IAAI,CAAC;gBACH,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAChD,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IAAI,MAAe,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC/B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACtB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;YACnC,OAAO,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;gBAC1D,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,IAAI,CAAC;QACX,CAAC,CAAC;IACJ,CAAC;CAAA;AAvBD,sEAuBC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.LocalProcessLiveSessionProcessSnapshotProvider = void 0;
|
|
4
|
+
const FileSystemSessionRecordReader_1 = require("./FileSystemSessionRecordReader");
|
|
4
5
|
const SESSION_ID_ENV_KEY = 'CLAUDE_CODE_SESSION_ID';
|
|
5
6
|
const CONFIG_DIR_ENV_KEY = 'CLAUDE_CONFIG_DIR';
|
|
6
7
|
/**
|
|
@@ -11,9 +12,10 @@ const CONFIG_DIR_ENV_KEY = 'CLAUDE_CONFIG_DIR';
|
|
|
11
12
|
* pure resolver, so all host access is contained in this adapter.
|
|
12
13
|
*/
|
|
13
14
|
class LocalProcessLiveSessionProcessSnapshotProvider {
|
|
14
|
-
constructor(localCommandRunner, environReader) {
|
|
15
|
+
constructor(localCommandRunner, environReader, sessionRecordReader = new FileSystemSessionRecordReader_1.FileSystemSessionRecordReader()) {
|
|
15
16
|
this.localCommandRunner = localCommandRunner;
|
|
16
17
|
this.environReader = environReader;
|
|
18
|
+
this.sessionRecordReader = sessionRecordReader;
|
|
17
19
|
this.getSnapshot = async () => {
|
|
18
20
|
const sessionNames = await this.listSessionNames();
|
|
19
21
|
const sessions = [];
|
|
@@ -59,12 +61,17 @@ class LocalProcessLiveSessionProcessSnapshotProvider {
|
|
|
59
61
|
const ppid = Number(match[2]);
|
|
60
62
|
const commandLine = match[3].trim();
|
|
61
63
|
const environ = this.environReader.readEnviron(pid);
|
|
64
|
+
const configDir = environ?.[CONFIG_DIR_ENV_KEY] ?? null;
|
|
65
|
+
const currentSessionId = configDir === null
|
|
66
|
+
? null
|
|
67
|
+
: this.sessionRecordReader.readCurrentSessionId(configDir, pid);
|
|
62
68
|
processes.push({
|
|
63
69
|
pid,
|
|
64
70
|
ppid,
|
|
65
71
|
commandLine,
|
|
66
72
|
sessionId: environ?.[SESSION_ID_ENV_KEY] ?? null,
|
|
67
|
-
|
|
73
|
+
currentSessionId,
|
|
74
|
+
configDir,
|
|
68
75
|
});
|
|
69
76
|
}
|
|
70
77
|
return processes;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalProcessLiveSessionProcessSnapshotProvider.js","sourceRoot":"","sources":["../../../src/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.ts"],"names":[],"mappings":";;;AASA,MAAM,kBAAkB,GAAG,wBAAwB,CAAC;AACpD,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AAE/C;;;;;;GAMG;AACH,MAAa,8CAA8C;IACzD,YACmB,kBAAsC,EACtC,aAAmC;
|
|
1
|
+
{"version":3,"file":"LocalProcessLiveSessionProcessSnapshotProvider.js","sourceRoot":"","sources":["../../../src/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -55,11 +55,26 @@ class ResolveInteractiveLiveSessionsUseCase {
|
|
|
55
55
|
sessions.push({
|
|
56
56
|
sessionName: session.sessionName,
|
|
57
57
|
sessionId: interactiveProcess.sessionId,
|
|
58
|
+
candidateSessionIds: this.collectCandidateSessionIds(interactiveProcess),
|
|
58
59
|
configDir: interactiveProcess.configDir,
|
|
59
60
|
});
|
|
60
61
|
}
|
|
61
62
|
return sessions;
|
|
62
63
|
};
|
|
64
|
+
this.collectCandidateSessionIds = (interactiveProcess) => {
|
|
65
|
+
const candidateSessionIds = [];
|
|
66
|
+
const seenSessionIds = new Set();
|
|
67
|
+
for (const sessionId of [
|
|
68
|
+
interactiveProcess.currentSessionId,
|
|
69
|
+
interactiveProcess.sessionId,
|
|
70
|
+
]) {
|
|
71
|
+
if (sessionId !== null && !seenSessionIds.has(sessionId)) {
|
|
72
|
+
seenSessionIds.add(sessionId);
|
|
73
|
+
candidateSessionIds.push(sessionId);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return candidateSessionIds;
|
|
77
|
+
};
|
|
63
78
|
this.findInteractiveProcess = (panePids, processByPid, childrenByPpid) => {
|
|
64
79
|
const visited = new Set();
|
|
65
80
|
const queue = [...panePids];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResolveInteractiveLiveSessionsUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/ResolveInteractiveLiveSessionsUseCase.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ResolveInteractiveLiveSessionsUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/ResolveInteractiveLiveSessionsUseCase.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionRecordReader.js","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/SessionRecordReader.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
import { mock } from 'jest-mock-extended';
|
|
2
|
+
import { Issue } from '../../../domain/entities/Issue';
|
|
2
3
|
import { IssueRepository } from '../../../domain/usecases/adapter-interfaces/IssueRepository';
|
|
4
|
+
|
|
5
|
+
const buildIssueFixture = (title: string): Issue => ({
|
|
6
|
+
nameWithOwner: 'o/r',
|
|
7
|
+
number: 1,
|
|
8
|
+
title,
|
|
9
|
+
state: 'OPEN',
|
|
10
|
+
status: null,
|
|
11
|
+
story: null,
|
|
12
|
+
nextActionDate: null,
|
|
13
|
+
nextActionHour: null,
|
|
14
|
+
estimationMinutes: null,
|
|
15
|
+
dependedIssueUrls: [],
|
|
16
|
+
completionDate50PercentConfidence: null,
|
|
17
|
+
url: 'https://github.com/o/r/issues/1',
|
|
18
|
+
assignees: [],
|
|
19
|
+
labels: [],
|
|
20
|
+
org: 'o',
|
|
21
|
+
repo: 'r',
|
|
22
|
+
body: '',
|
|
23
|
+
itemId: 'itemId',
|
|
24
|
+
isPr: false,
|
|
25
|
+
isInProgress: false,
|
|
26
|
+
isClosed: false,
|
|
27
|
+
createdAt: new Date('2026-01-01T00:00:00Z'),
|
|
28
|
+
author: 'octocat',
|
|
29
|
+
closingIssueReferenceUrls: [],
|
|
30
|
+
});
|
|
3
31
|
import {
|
|
4
32
|
ISSUE_TITLE_CACHE_TTL_MS,
|
|
5
33
|
IssueTitleStateCache,
|
|
@@ -241,6 +269,9 @@ describe('consoleReadApi', () => {
|
|
|
241
269
|
merged: false,
|
|
242
270
|
isPullRequest: false,
|
|
243
271
|
});
|
|
272
|
+
issueRepository.getIssueByUrl.mockResolvedValue(
|
|
273
|
+
buildIssueFixture('Issue title from repository'),
|
|
274
|
+
);
|
|
244
275
|
const cache = new IssueTitleStateCache(() => 0);
|
|
245
276
|
const url = 'https://github.com/o/r/issues/1';
|
|
246
277
|
const first = await handleIssueTitle(issueRepository, cache, url);
|
|
@@ -248,12 +279,63 @@ describe('consoleReadApi', () => {
|
|
|
248
279
|
state: 'OPEN',
|
|
249
280
|
merged: false,
|
|
250
281
|
isPullRequest: false,
|
|
282
|
+
title: 'Issue title from repository',
|
|
251
283
|
});
|
|
252
284
|
const second = await handleIssueTitle(issueRepository, cache, url);
|
|
253
285
|
expect(second.body).toEqual(first.body);
|
|
254
286
|
expect(issueRepository.getIssueOrPullRequestState).toHaveBeenCalledTimes(
|
|
255
287
|
1,
|
|
256
288
|
);
|
|
289
|
+
expect(issueRepository.getIssueByUrl).toHaveBeenCalledTimes(1);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('returns the pull request title from the summary for pull request urls', async () => {
|
|
293
|
+
const issueRepository = mock<IssueRepository>();
|
|
294
|
+
issueRepository.getIssueOrPullRequestState.mockResolvedValue({
|
|
295
|
+
state: 'CLOSED',
|
|
296
|
+
merged: true,
|
|
297
|
+
isPullRequest: true,
|
|
298
|
+
});
|
|
299
|
+
issueRepository.getPullRequestSummary.mockResolvedValue({
|
|
300
|
+
title: 'Pull request title from summary',
|
|
301
|
+
body: 'body',
|
|
302
|
+
additions: 1,
|
|
303
|
+
deletions: 0,
|
|
304
|
+
changedFiles: 1,
|
|
305
|
+
});
|
|
306
|
+
const cache = new IssueTitleStateCache(() => 0);
|
|
307
|
+
const url = 'https://github.com/o/r/pull/2';
|
|
308
|
+
const response = await handleIssueTitle(issueRepository, cache, url);
|
|
309
|
+
expect(response.body).toEqual({
|
|
310
|
+
state: 'CLOSED',
|
|
311
|
+
merged: true,
|
|
312
|
+
isPullRequest: true,
|
|
313
|
+
title: 'Pull request title from summary',
|
|
314
|
+
});
|
|
315
|
+
expect(issueRepository.getPullRequestSummary).toHaveBeenCalledWith(url);
|
|
316
|
+
expect(issueRepository.getIssueByUrl).not.toHaveBeenCalled();
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it('falls back to an empty title when the title source returns nothing', async () => {
|
|
320
|
+
const issueRepository = mock<IssueRepository>();
|
|
321
|
+
issueRepository.getIssueOrPullRequestState.mockResolvedValue({
|
|
322
|
+
state: 'OPEN',
|
|
323
|
+
merged: false,
|
|
324
|
+
isPullRequest: false,
|
|
325
|
+
});
|
|
326
|
+
issueRepository.getIssueByUrl.mockResolvedValue(null);
|
|
327
|
+
const cache = new IssueTitleStateCache(() => 0);
|
|
328
|
+
const response = await handleIssueTitle(
|
|
329
|
+
issueRepository,
|
|
330
|
+
cache,
|
|
331
|
+
'https://github.com/o/r/issues/3',
|
|
332
|
+
);
|
|
333
|
+
expect(response.body).toEqual({
|
|
334
|
+
state: 'OPEN',
|
|
335
|
+
merged: false,
|
|
336
|
+
isPullRequest: false,
|
|
337
|
+
title: '',
|
|
338
|
+
});
|
|
257
339
|
});
|
|
258
340
|
|
|
259
341
|
it('re-fetches a non-merged result after the TTL elapses', async () => {
|
|
@@ -12,6 +12,7 @@ export type IssueOrPullRequestState = {
|
|
|
12
12
|
state: string;
|
|
13
13
|
merged: boolean;
|
|
14
14
|
isPullRequest: boolean;
|
|
15
|
+
title: string;
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
export type PullRequestStatus = {
|
|
@@ -215,6 +216,19 @@ export const handleRelatedPrs = async (
|
|
|
215
216
|
return ok({ relatedPullRequests: withSummaries });
|
|
216
217
|
};
|
|
217
218
|
|
|
219
|
+
const resolveIssueOrPullRequestTitle = async (
|
|
220
|
+
issueRepository: IssueRepository,
|
|
221
|
+
url: string,
|
|
222
|
+
isPullRequest: boolean,
|
|
223
|
+
): Promise<string> => {
|
|
224
|
+
if (isPullRequest) {
|
|
225
|
+
const summary = await issueRepository.getPullRequestSummary(url);
|
|
226
|
+
return summary?.title ?? '';
|
|
227
|
+
}
|
|
228
|
+
const issue = await issueRepository.getIssueByUrl(url);
|
|
229
|
+
return issue?.title ?? '';
|
|
230
|
+
};
|
|
231
|
+
|
|
218
232
|
export const handleIssueTitle = async (
|
|
219
233
|
issueRepository: IssueRepository,
|
|
220
234
|
cache: IssueTitleStateCache,
|
|
@@ -227,7 +241,13 @@ export const handleIssueTitle = async (
|
|
|
227
241
|
if (cached !== null) {
|
|
228
242
|
return ok(cached);
|
|
229
243
|
}
|
|
230
|
-
const
|
|
244
|
+
const baseState = await issueRepository.getIssueOrPullRequestState(url);
|
|
245
|
+
const title = await resolveIssueOrPullRequestTitle(
|
|
246
|
+
issueRepository,
|
|
247
|
+
url,
|
|
248
|
+
baseState.isPullRequest,
|
|
249
|
+
);
|
|
250
|
+
const state: IssueOrPullRequestState = { ...baseState, title };
|
|
231
251
|
cache.set(url, state);
|
|
232
252
|
return ok(state);
|
|
233
253
|
};
|
|
@@ -4,9 +4,12 @@ import {
|
|
|
4
4
|
consoleCodeFenceBodyFixture,
|
|
5
5
|
consoleMarkdownBodyFixture,
|
|
6
6
|
consoleMarkdownImageBodyFixture,
|
|
7
|
+
consoleMarkdownReferenceBodyFixture,
|
|
7
8
|
consoleMermaidBodyFixture,
|
|
9
|
+
consoleReferenceStatesFixture,
|
|
8
10
|
} from '../../testing/fixtures';
|
|
9
11
|
import { ConsoleMarkdownContent } from './ConsoleMarkdownContent';
|
|
12
|
+
import { ConsoleReferenceLink } from './ConsoleReferenceLink';
|
|
10
13
|
|
|
11
14
|
const meta: Meta<typeof ConsoleMarkdownContent> = {
|
|
12
15
|
title: 'Console/ConsoleMarkdownContent',
|
|
@@ -37,6 +40,19 @@ export const WithProxiedGitHubImages: Story = {
|
|
|
37
40
|
},
|
|
38
41
|
};
|
|
39
42
|
|
|
43
|
+
export const WithDecoratedReferenceLinks: Story = {
|
|
44
|
+
args: {
|
|
45
|
+
body: consoleMarkdownReferenceBodyFixture,
|
|
46
|
+
renderReferenceLink: (href, fallbackText) => (
|
|
47
|
+
<ConsoleReferenceLink
|
|
48
|
+
href={href}
|
|
49
|
+
fallbackText={fallbackText}
|
|
50
|
+
state={consoleReferenceStatesFixture[href] ?? null}
|
|
51
|
+
/>
|
|
52
|
+
),
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
40
56
|
export const Empty: Story = {
|
|
41
57
|
args: { body: '' },
|
|
42
58
|
};
|
|
@@ -33,4 +33,65 @@ describe('ConsoleMarkdownContent', () => {
|
|
|
33
33
|
).not.toBeNull();
|
|
34
34
|
});
|
|
35
35
|
});
|
|
36
|
+
|
|
37
|
+
it('decorates pull request and issue links via the reference renderer', async () => {
|
|
38
|
+
const body =
|
|
39
|
+
'See https://github.com/octo/repo/pull/7 and https://github.com/octo/repo/issues/9 for details.';
|
|
40
|
+
const renderReferenceLink = jest.fn((href: string) => (
|
|
41
|
+
<span className="decorated-reference" data-href={href}>
|
|
42
|
+
decorated:{href}
|
|
43
|
+
</span>
|
|
44
|
+
));
|
|
45
|
+
const { container } = render(
|
|
46
|
+
<ConsoleMarkdownContent
|
|
47
|
+
body={body}
|
|
48
|
+
renderReferenceLink={renderReferenceLink}
|
|
49
|
+
/>,
|
|
50
|
+
);
|
|
51
|
+
await waitFor(() => {
|
|
52
|
+
expect(container.querySelectorAll('.decorated-reference').length).toBe(2);
|
|
53
|
+
});
|
|
54
|
+
const decoratedHrefs = Array.from(
|
|
55
|
+
container.querySelectorAll('.decorated-reference'),
|
|
56
|
+
).map((node) => node.getAttribute('data-href'));
|
|
57
|
+
expect(decoratedHrefs).toEqual([
|
|
58
|
+
'https://github.com/octo/repo/pull/7',
|
|
59
|
+
'https://github.com/octo/repo/issues/9',
|
|
60
|
+
]);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('leaves non-issue links untouched', async () => {
|
|
64
|
+
const body =
|
|
65
|
+
'Docs at https://example.com/page and source https://github.com/octo/repo/blob/main/file.ts';
|
|
66
|
+
const renderReferenceLink = jest.fn(() => (
|
|
67
|
+
<span className="decorated-reference">decorated</span>
|
|
68
|
+
));
|
|
69
|
+
const { container } = render(
|
|
70
|
+
<ConsoleMarkdownContent
|
|
71
|
+
body={body}
|
|
72
|
+
renderReferenceLink={renderReferenceLink}
|
|
73
|
+
/>,
|
|
74
|
+
);
|
|
75
|
+
await waitFor(() => {
|
|
76
|
+
const anchors = container.querySelectorAll('a[href]');
|
|
77
|
+
expect(anchors.length).toBe(2);
|
|
78
|
+
});
|
|
79
|
+
expect(renderReferenceLink).not.toHaveBeenCalled();
|
|
80
|
+
expect(container.querySelector('.decorated-reference')).toBeNull();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('keeps reference links as plain anchors when no renderer is provided', () => {
|
|
84
|
+
const { container } = render(
|
|
85
|
+
<ConsoleMarkdownContent
|
|
86
|
+
body={'See https://github.com/octo/repo/pull/7 now.'}
|
|
87
|
+
/>,
|
|
88
|
+
);
|
|
89
|
+
const anchor = container.querySelector('a[href]');
|
|
90
|
+
expect(anchor?.getAttribute('href')).toBe(
|
|
91
|
+
'https://github.com/octo/repo/pull/7',
|
|
92
|
+
);
|
|
93
|
+
expect(
|
|
94
|
+
container.querySelector('.console-markdown-reference-host'),
|
|
95
|
+
).toBeNull();
|
|
96
|
+
});
|
|
36
97
|
});
|