@sanqianx/ai-coding-event-bridge-console 0.7.2 → 0.7.3
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/LICENSE +21 -21
- package/README.md +81 -81
- package/console/index.html +953 -953
- package/package.json +26 -26
- package/src/agent-detect.js +128 -128
- package/src/bin.js +80 -80
- package/src/bridge/bin/commit-boundary.js +64 -64
- package/src/bridge/connectors/capture-guard.js +24 -24
- package/src/bridge/connectors/claude-code/hook-entry.js +45 -45
- package/src/bridge/connectors/claude-code/notify.js +57 -57
- package/src/bridge/connectors/codex/cursor-store.js +83 -83
- package/src/bridge/connectors/codex/hook-entry.js +215 -215
- package/src/bridge/connectors/codex/session-parser.js +100 -100
- package/src/bridge/connectors/opencode/hook-entry.js +55 -55
- package/src/bridge/core/bridge.js +249 -246
- package/src/bridge/core/commit-projection.js +288 -288
- package/src/bridge/core/compaction.js +23 -23
- package/src/bridge/core/consumer-registry.js +111 -111
- package/src/bridge/core/event-schema.js +127 -127
- package/src/bridge/core/fs-utils.js +81 -81
- package/src/bridge/core/journal-router.js +39 -39
- package/src/bridge/core/journal.js +507 -507
- package/src/bridge/core/lock.js +96 -96
- package/src/bridge/core/normalizer.js +114 -114
- package/src/bridge/core/paths.js +12 -12
- package/src/bridge/core/project-registry.js +176 -176
- package/src/bridge/core/repo-context.js +191 -191
- package/src/bridge/core/runtime-home.js +189 -189
- package/src/bridge/core/semver.js +23 -23
- package/src/bridge/core/turn-identity.js +127 -127
- package/src/bridge/index.js +86 -86
- package/src/bridge/installers/claude-code/installer.js +181 -181
- package/src/bridge/installers/codex/installer.js +114 -114
- package/src/bridge/installers/opencode/installer.js +96 -96
- package/src/bridge/installers/zcode/installer.js +200 -200
- package/src/bridge/query/conversation-query.js +194 -194
- package/src/server.js +825 -825
|
@@ -1,127 +1,127 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// F-024: DevTask-Radar used to synthesize '(No captured user prompt for this
|
|
4
|
-
// turn)' as fake user text. Synthetic evidence is forbidden anywhere downstream.
|
|
5
|
-
const SYNTHETIC_PROMPT_MARKERS = [
|
|
6
|
-
'(no captured user prompt for this turn)',
|
|
7
|
-
'(no user prompt captured)',
|
|
8
|
-
'unknown-session'
|
|
9
|
-
];
|
|
10
|
-
|
|
11
|
-
function isSyntheticPrompt(content) {
|
|
12
|
-
if (typeof content !== 'string') return false;
|
|
13
|
-
const trimmed = content.trim().toLowerCase();
|
|
14
|
-
return SYNTHETIC_PROMPT_MARKERS.includes(trimmed);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function orderBySequence(events) {
|
|
18
|
-
return [...events].sort((a, b) => {
|
|
19
|
-
if (a.sequence !== b.sequence) return a.sequence - b.sequence;
|
|
20
|
-
return String(a.eventId || '').localeCompare(String(b.eventId || ''));
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function isDuplicateEvent(a, b) {
|
|
25
|
-
if (!a || !b) return false;
|
|
26
|
-
if (a.eventKey && b.eventKey && a.eventKey === b.eventKey) return true;
|
|
27
|
-
return (
|
|
28
|
-
a.source === b.source &&
|
|
29
|
-
a.eventType === b.eventType &&
|
|
30
|
-
(a.sessionId || null) === (b.sessionId || null) &&
|
|
31
|
-
(a.turnId || null) === (b.turnId || null) &&
|
|
32
|
-
a.content === b.content &&
|
|
33
|
-
a.eventId !== undefined &&
|
|
34
|
-
a.eventId === b.eventId
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Deterministic turn projection over ordered events. Mirrors the journal's
|
|
40
|
-
* durable projection: user_prompt opens a turn; assistant_response closes the
|
|
41
|
-
* matching open turn (by turnId, or by sessionId when the client did not
|
|
42
|
-
* provide a turn id). Assistant events that cannot be tied to an open turn are
|
|
43
|
-
* orphan evidence — they are kept, never turned into fake prompts.
|
|
44
|
-
*/
|
|
45
|
-
function deriveTurnState(events) {
|
|
46
|
-
const ordered = orderBySequence(events.filter((e) => e && typeof e === 'object'));
|
|
47
|
-
const openTurns = new Map();
|
|
48
|
-
const closedTurns = new Map();
|
|
49
|
-
const orphanAssistantEvents = [];
|
|
50
|
-
|
|
51
|
-
const findOpenTurnForAssistant = (event) => {
|
|
52
|
-
if (event.turnId && openTurns.has(event.turnId)) return openTurns.get(event.turnId);
|
|
53
|
-
if (event.turnId) return null;
|
|
54
|
-
if (!event.sessionId) return null;
|
|
55
|
-
const matches = [...openTurns.values()].filter((t) => t.sessionId === event.sessionId);
|
|
56
|
-
if (matches.length === 1) return matches[0];
|
|
57
|
-
return null;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
for (const event of ordered) {
|
|
61
|
-
if (event.eventType === 'user_prompt') {
|
|
62
|
-
if (!event.turnId) continue; // unverifiable prompt: identity layer marks it, no fake turn
|
|
63
|
-
if (openTurns.has(event.turnId) || closedTurns.has(event.turnId)) {
|
|
64
|
-
const turn = openTurns.get(event.turnId) || closedTurns.get(event.turnId);
|
|
65
|
-
turn.userEvents.push(event);
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
openTurns.set(event.turnId, {
|
|
69
|
-
turnId: event.turnId,
|
|
70
|
-
sessionId: event.sessionId || null,
|
|
71
|
-
source: event.source,
|
|
72
|
-
startSequence: event.sequence,
|
|
73
|
-
endSequence: null,
|
|
74
|
-
userEvents: [event],
|
|
75
|
-
assistantEvents: []
|
|
76
|
-
});
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
if (event.eventType === 'assistant_response') {
|
|
80
|
-
const turn = findOpenTurnForAssistant(event);
|
|
81
|
-
if (!turn) {
|
|
82
|
-
orphanAssistantEvents.push(event);
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
turn.assistantEvents.push(event);
|
|
86
|
-
turn.endSequence = event.sequence;
|
|
87
|
-
openTurns.delete(turn.turnId);
|
|
88
|
-
closedTurns.set(turn.turnId, turn);
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
if (event.eventType === 'session_end' && event.sessionId) {
|
|
92
|
-
for (const turn of [...openTurns.values()]) {
|
|
93
|
-
if (turn.sessionId === event.sessionId) {
|
|
94
|
-
turn.endSequence = event.sequence;
|
|
95
|
-
openTurns.delete(turn.turnId);
|
|
96
|
-
closedTurns.set(turn.turnId, turn);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return {
|
|
103
|
-
openTurns: [...openTurns.values()],
|
|
104
|
-
closedTurns: [...closedTurns.values()],
|
|
105
|
-
orphanAssistantEvents
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function assertNoSyntheticEvidence(events) {
|
|
110
|
-
for (const event of events) {
|
|
111
|
-
if (event && event.role === 'user' && isSyntheticPrompt(event.content)) {
|
|
112
|
-
throw new Error(`synthetic user prompt is forbidden: ${String(event.content).slice(0, 60)}`);
|
|
113
|
-
}
|
|
114
|
-
if (event && typeof event.sessionId === 'string' && event.sessionId.toLowerCase() === 'unknown-session') {
|
|
115
|
-
throw new Error('unknown-session is forbidden');
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return true;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
module.exports = {
|
|
122
|
-
isSyntheticPrompt,
|
|
123
|
-
orderBySequence,
|
|
124
|
-
isDuplicateEvent,
|
|
125
|
-
deriveTurnState,
|
|
126
|
-
assertNoSyntheticEvidence
|
|
127
|
-
};
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// F-024: DevTask-Radar used to synthesize '(No captured user prompt for this
|
|
4
|
+
// turn)' as fake user text. Synthetic evidence is forbidden anywhere downstream.
|
|
5
|
+
const SYNTHETIC_PROMPT_MARKERS = [
|
|
6
|
+
'(no captured user prompt for this turn)',
|
|
7
|
+
'(no user prompt captured)',
|
|
8
|
+
'unknown-session'
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
function isSyntheticPrompt(content) {
|
|
12
|
+
if (typeof content !== 'string') return false;
|
|
13
|
+
const trimmed = content.trim().toLowerCase();
|
|
14
|
+
return SYNTHETIC_PROMPT_MARKERS.includes(trimmed);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function orderBySequence(events) {
|
|
18
|
+
return [...events].sort((a, b) => {
|
|
19
|
+
if (a.sequence !== b.sequence) return a.sequence - b.sequence;
|
|
20
|
+
return String(a.eventId || '').localeCompare(String(b.eventId || ''));
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function isDuplicateEvent(a, b) {
|
|
25
|
+
if (!a || !b) return false;
|
|
26
|
+
if (a.eventKey && b.eventKey && a.eventKey === b.eventKey) return true;
|
|
27
|
+
return (
|
|
28
|
+
a.source === b.source &&
|
|
29
|
+
a.eventType === b.eventType &&
|
|
30
|
+
(a.sessionId || null) === (b.sessionId || null) &&
|
|
31
|
+
(a.turnId || null) === (b.turnId || null) &&
|
|
32
|
+
a.content === b.content &&
|
|
33
|
+
a.eventId !== undefined &&
|
|
34
|
+
a.eventId === b.eventId
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Deterministic turn projection over ordered events. Mirrors the journal's
|
|
40
|
+
* durable projection: user_prompt opens a turn; assistant_response closes the
|
|
41
|
+
* matching open turn (by turnId, or by sessionId when the client did not
|
|
42
|
+
* provide a turn id). Assistant events that cannot be tied to an open turn are
|
|
43
|
+
* orphan evidence — they are kept, never turned into fake prompts.
|
|
44
|
+
*/
|
|
45
|
+
function deriveTurnState(events) {
|
|
46
|
+
const ordered = orderBySequence(events.filter((e) => e && typeof e === 'object'));
|
|
47
|
+
const openTurns = new Map();
|
|
48
|
+
const closedTurns = new Map();
|
|
49
|
+
const orphanAssistantEvents = [];
|
|
50
|
+
|
|
51
|
+
const findOpenTurnForAssistant = (event) => {
|
|
52
|
+
if (event.turnId && openTurns.has(event.turnId)) return openTurns.get(event.turnId);
|
|
53
|
+
if (event.turnId) return null;
|
|
54
|
+
if (!event.sessionId) return null;
|
|
55
|
+
const matches = [...openTurns.values()].filter((t) => t.sessionId === event.sessionId);
|
|
56
|
+
if (matches.length === 1) return matches[0];
|
|
57
|
+
return null;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
for (const event of ordered) {
|
|
61
|
+
if (event.eventType === 'user_prompt') {
|
|
62
|
+
if (!event.turnId) continue; // unverifiable prompt: identity layer marks it, no fake turn
|
|
63
|
+
if (openTurns.has(event.turnId) || closedTurns.has(event.turnId)) {
|
|
64
|
+
const turn = openTurns.get(event.turnId) || closedTurns.get(event.turnId);
|
|
65
|
+
turn.userEvents.push(event);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
openTurns.set(event.turnId, {
|
|
69
|
+
turnId: event.turnId,
|
|
70
|
+
sessionId: event.sessionId || null,
|
|
71
|
+
source: event.source,
|
|
72
|
+
startSequence: event.sequence,
|
|
73
|
+
endSequence: null,
|
|
74
|
+
userEvents: [event],
|
|
75
|
+
assistantEvents: []
|
|
76
|
+
});
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (event.eventType === 'assistant_response') {
|
|
80
|
+
const turn = findOpenTurnForAssistant(event);
|
|
81
|
+
if (!turn) {
|
|
82
|
+
orphanAssistantEvents.push(event);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
turn.assistantEvents.push(event);
|
|
86
|
+
turn.endSequence = event.sequence;
|
|
87
|
+
openTurns.delete(turn.turnId);
|
|
88
|
+
closedTurns.set(turn.turnId, turn);
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (event.eventType === 'session_end' && event.sessionId) {
|
|
92
|
+
for (const turn of [...openTurns.values()]) {
|
|
93
|
+
if (turn.sessionId === event.sessionId) {
|
|
94
|
+
turn.endSequence = event.sequence;
|
|
95
|
+
openTurns.delete(turn.turnId);
|
|
96
|
+
closedTurns.set(turn.turnId, turn);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
openTurns: [...openTurns.values()],
|
|
104
|
+
closedTurns: [...closedTurns.values()],
|
|
105
|
+
orphanAssistantEvents
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function assertNoSyntheticEvidence(events) {
|
|
110
|
+
for (const event of events) {
|
|
111
|
+
if (event && event.role === 'user' && isSyntheticPrompt(event.content)) {
|
|
112
|
+
throw new Error(`synthetic user prompt is forbidden: ${String(event.content).slice(0, 60)}`);
|
|
113
|
+
}
|
|
114
|
+
if (event && typeof event.sessionId === 'string' && event.sessionId.toLowerCase() === 'unknown-session') {
|
|
115
|
+
throw new Error('unknown-session is forbidden');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports = {
|
|
122
|
+
isSyntheticPrompt,
|
|
123
|
+
orderBySequence,
|
|
124
|
+
isDuplicateEvent,
|
|
125
|
+
deriveTurnState,
|
|
126
|
+
assertNoSyntheticEvidence
|
|
127
|
+
};
|
package/src/bridge/index.js
CHANGED
|
@@ -1,86 +1,86 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const packageInfo = require('../../package.json');
|
|
4
|
-
const { bridgeHome } = require('./core/paths');
|
|
5
|
-
const { Journal, JournalValidationError, JournalCorruptError, EVENT_SCHEMA, BOUNDARY_SCHEMA } = require('./core/journal');
|
|
6
|
-
const { ConsumerRegistry } = require('./core/consumer-registry');
|
|
7
|
-
const { compactJournal } = require('./core/compaction');
|
|
8
|
-
const { ensureRuntimeHome } = require('./core/runtime-home');
|
|
9
|
-
const semver = require('./core/semver');
|
|
10
|
-
const { validateAndNormalizeEvent, EventSchemaError } = require('./core/event-schema');
|
|
11
|
-
const {
|
|
12
|
-
normalizeGitUrl,
|
|
13
|
-
resolveRepoContext,
|
|
14
|
-
REPO_IDENTITY_SCHEMA,
|
|
15
|
-
buildRepoIdentityV1,
|
|
16
|
-
isValidRepoIdentityV1,
|
|
17
|
-
repoIdentityKey,
|
|
18
|
-
sameRepoIdentity,
|
|
19
|
-
workspaceIdFor
|
|
20
|
-
} = require('./core/repo-context');
|
|
21
|
-
const {
|
|
22
|
-
isSyntheticPrompt,
|
|
23
|
-
orderBySequence,
|
|
24
|
-
isDuplicateEvent,
|
|
25
|
-
deriveTurnState,
|
|
26
|
-
assertNoSyntheticEvidence
|
|
27
|
-
} = require('./core/turn-identity');
|
|
28
|
-
const { normalizeClaudeCode, normalizeCodex, normalizeOpenCode } = require('./core/normalizer');
|
|
29
|
-
const projectRegistry = require('./core/project-registry');
|
|
30
|
-
const commitProjection = require('./core/commit-projection');
|
|
31
|
-
const { journalFor, globalJournalDir, projectJournalDir } = require('./core/journal-router');
|
|
32
|
-
const { ConversationQuery } = require('./query/conversation-query');
|
|
33
|
-
const claudeHookEntry = require('./connectors/claude-code/hook-entry');
|
|
34
|
-
const claudeInstaller = require('./installers/claude-code/installer');
|
|
35
|
-
const codexInstaller = require('./installers/codex/installer');
|
|
36
|
-
const openCodeInstaller = require('./installers/opencode/installer');
|
|
37
|
-
const zcodeInstaller = require('./installers/zcode/installer');
|
|
38
|
-
const { createBridge } = require('./core/bridge');
|
|
39
|
-
|
|
40
|
-
module.exports = {
|
|
41
|
-
packageName: packageInfo.name,
|
|
42
|
-
version: packageInfo.version,
|
|
43
|
-
bridgeHome,
|
|
44
|
-
Journal,
|
|
45
|
-
JournalValidationError,
|
|
46
|
-
JournalCorruptError,
|
|
47
|
-
EVENT_SCHEMA,
|
|
48
|
-
BOUNDARY_SCHEMA,
|
|
49
|
-
ConsumerRegistry,
|
|
50
|
-
compactJournal,
|
|
51
|
-
ensureRuntimeHome,
|
|
52
|
-
semver,
|
|
53
|
-
validateAndNormalizeEvent,
|
|
54
|
-
EventSchemaError,
|
|
55
|
-
normalizeGitUrl,
|
|
56
|
-
resolveRepoContext,
|
|
57
|
-
REPO_IDENTITY_SCHEMA,
|
|
58
|
-
buildRepoIdentityV1,
|
|
59
|
-
isValidRepoIdentityV1,
|
|
60
|
-
repoIdentityKey,
|
|
61
|
-
sameRepoIdentity,
|
|
62
|
-
workspaceIdFor,
|
|
63
|
-
isSyntheticPrompt,
|
|
64
|
-
orderBySequence,
|
|
65
|
-
isDuplicateEvent,
|
|
66
|
-
deriveTurnState,
|
|
67
|
-
assertNoSyntheticEvidence,
|
|
68
|
-
normalizeClaudeCode,
|
|
69
|
-
normalizeCodex,
|
|
70
|
-
normalizeOpenCode,
|
|
71
|
-
projectRegistry,
|
|
72
|
-
commitProjection,
|
|
73
|
-
journalFor,
|
|
74
|
-
globalJournalDir,
|
|
75
|
-
projectJournalDir,
|
|
76
|
-
ConversationQuery,
|
|
77
|
-
claudeHookEntry,
|
|
78
|
-
claudeInstaller,
|
|
79
|
-
createBridge,
|
|
80
|
-
installers: {
|
|
81
|
-
claudeCode: claudeInstaller,
|
|
82
|
-
codex: codexInstaller,
|
|
83
|
-
openCode: openCodeInstaller,
|
|
84
|
-
zcode: zcodeInstaller
|
|
85
|
-
}
|
|
86
|
-
};
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const packageInfo = require('../../package.json');
|
|
4
|
+
const { bridgeHome } = require('./core/paths');
|
|
5
|
+
const { Journal, JournalValidationError, JournalCorruptError, EVENT_SCHEMA, BOUNDARY_SCHEMA } = require('./core/journal');
|
|
6
|
+
const { ConsumerRegistry } = require('./core/consumer-registry');
|
|
7
|
+
const { compactJournal } = require('./core/compaction');
|
|
8
|
+
const { ensureRuntimeHome } = require('./core/runtime-home');
|
|
9
|
+
const semver = require('./core/semver');
|
|
10
|
+
const { validateAndNormalizeEvent, EventSchemaError } = require('./core/event-schema');
|
|
11
|
+
const {
|
|
12
|
+
normalizeGitUrl,
|
|
13
|
+
resolveRepoContext,
|
|
14
|
+
REPO_IDENTITY_SCHEMA,
|
|
15
|
+
buildRepoIdentityV1,
|
|
16
|
+
isValidRepoIdentityV1,
|
|
17
|
+
repoIdentityKey,
|
|
18
|
+
sameRepoIdentity,
|
|
19
|
+
workspaceIdFor
|
|
20
|
+
} = require('./core/repo-context');
|
|
21
|
+
const {
|
|
22
|
+
isSyntheticPrompt,
|
|
23
|
+
orderBySequence,
|
|
24
|
+
isDuplicateEvent,
|
|
25
|
+
deriveTurnState,
|
|
26
|
+
assertNoSyntheticEvidence
|
|
27
|
+
} = require('./core/turn-identity');
|
|
28
|
+
const { normalizeClaudeCode, normalizeCodex, normalizeOpenCode } = require('./core/normalizer');
|
|
29
|
+
const projectRegistry = require('./core/project-registry');
|
|
30
|
+
const commitProjection = require('./core/commit-projection');
|
|
31
|
+
const { journalFor, globalJournalDir, projectJournalDir } = require('./core/journal-router');
|
|
32
|
+
const { ConversationQuery } = require('./query/conversation-query');
|
|
33
|
+
const claudeHookEntry = require('./connectors/claude-code/hook-entry');
|
|
34
|
+
const claudeInstaller = require('./installers/claude-code/installer');
|
|
35
|
+
const codexInstaller = require('./installers/codex/installer');
|
|
36
|
+
const openCodeInstaller = require('./installers/opencode/installer');
|
|
37
|
+
const zcodeInstaller = require('./installers/zcode/installer');
|
|
38
|
+
const { createBridge } = require('./core/bridge');
|
|
39
|
+
|
|
40
|
+
module.exports = {
|
|
41
|
+
packageName: packageInfo.name,
|
|
42
|
+
version: packageInfo.version,
|
|
43
|
+
bridgeHome,
|
|
44
|
+
Journal,
|
|
45
|
+
JournalValidationError,
|
|
46
|
+
JournalCorruptError,
|
|
47
|
+
EVENT_SCHEMA,
|
|
48
|
+
BOUNDARY_SCHEMA,
|
|
49
|
+
ConsumerRegistry,
|
|
50
|
+
compactJournal,
|
|
51
|
+
ensureRuntimeHome,
|
|
52
|
+
semver,
|
|
53
|
+
validateAndNormalizeEvent,
|
|
54
|
+
EventSchemaError,
|
|
55
|
+
normalizeGitUrl,
|
|
56
|
+
resolveRepoContext,
|
|
57
|
+
REPO_IDENTITY_SCHEMA,
|
|
58
|
+
buildRepoIdentityV1,
|
|
59
|
+
isValidRepoIdentityV1,
|
|
60
|
+
repoIdentityKey,
|
|
61
|
+
sameRepoIdentity,
|
|
62
|
+
workspaceIdFor,
|
|
63
|
+
isSyntheticPrompt,
|
|
64
|
+
orderBySequence,
|
|
65
|
+
isDuplicateEvent,
|
|
66
|
+
deriveTurnState,
|
|
67
|
+
assertNoSyntheticEvidence,
|
|
68
|
+
normalizeClaudeCode,
|
|
69
|
+
normalizeCodex,
|
|
70
|
+
normalizeOpenCode,
|
|
71
|
+
projectRegistry,
|
|
72
|
+
commitProjection,
|
|
73
|
+
journalFor,
|
|
74
|
+
globalJournalDir,
|
|
75
|
+
projectJournalDir,
|
|
76
|
+
ConversationQuery,
|
|
77
|
+
claudeHookEntry,
|
|
78
|
+
claudeInstaller,
|
|
79
|
+
createBridge,
|
|
80
|
+
installers: {
|
|
81
|
+
claudeCode: claudeInstaller,
|
|
82
|
+
codex: codexInstaller,
|
|
83
|
+
openCode: openCodeInstaller,
|
|
84
|
+
zcode: zcodeInstaller
|
|
85
|
+
}
|
|
86
|
+
};
|