@knpkv/jira-clockify 1.2.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +254 -3
- package/dist/package.json +36 -12
- package/dist/src/agent/agentSettings.d.ts +18 -0
- package/dist/src/agent/agentSettings.d.ts.map +1 -0
- package/dist/src/agent/agentSettings.js +23 -0
- package/dist/src/agent/agentSettings.js.map +1 -0
- package/dist/src/agent/schedule.d.ts +20 -0
- package/dist/src/agent/schedule.d.ts.map +1 -0
- package/dist/src/agent/schedule.js +189 -0
- package/dist/src/agent/schedule.js.map +1 -0
- package/dist/src/agent/sessions.d.ts +427 -0
- package/dist/src/agent/sessions.d.ts.map +1 -0
- package/dist/src/agent/sessions.js +868 -0
- package/dist/src/agent/sessions.js.map +1 -0
- package/dist/src/agent/sourceConsumption.d.ts +79 -0
- package/dist/src/agent/sourceConsumption.d.ts.map +1 -0
- package/dist/src/agent/sourceConsumption.js +191 -0
- package/dist/src/agent/sourceConsumption.js.map +1 -0
- package/dist/src/agent/watch.d.ts +76 -0
- package/dist/src/agent/watch.d.ts.map +1 -0
- package/dist/src/agent/watch.js +45 -0
- package/dist/src/agent/watch.js.map +1 -0
- package/dist/src/agent/writePlanning.d.ts +154 -0
- package/dist/src/agent/writePlanning.d.ts.map +1 -0
- package/dist/src/agent/writePlanning.js +210 -0
- package/dist/src/agent/writePlanning.js.map +1 -0
- package/dist/src/bin.d.ts +3 -0
- package/dist/src/bin.d.ts.map +1 -0
- package/dist/src/bin.js +9 -3
- package/dist/src/bin.js.map +1 -1
- package/dist/src/cli/agentWrite.d.ts +164 -0
- package/dist/src/cli/agentWrite.d.ts.map +1 -0
- package/dist/src/cli/agentWrite.js +362 -0
- package/dist/src/cli/agentWrite.js.map +1 -0
- package/dist/src/cli/auth.d.ts +8 -0
- package/dist/src/cli/auth.d.ts.map +1 -0
- package/dist/src/cli/auth.js +10 -10
- package/dist/src/cli/auth.js.map +1 -1
- package/dist/src/cli/calendar.d.ts +42 -0
- package/dist/src/cli/calendar.d.ts.map +1 -0
- package/dist/src/cli/calendar.js +189 -0
- package/dist/src/cli/calendar.js.map +1 -0
- package/dist/src/cli/config.d.ts +12 -0
- package/dist/src/cli/config.d.ts.map +1 -0
- package/dist/src/cli/config.js +163 -21
- package/dist/src/cli/config.js.map +1 -1
- package/dist/src/cli/fetchTicket.d.ts +51 -0
- package/dist/src/cli/fetchTicket.d.ts.map +1 -0
- package/dist/src/cli/fetchTicket.js +18 -2
- package/dist/src/cli/fetchTicket.js.map +1 -1
- package/dist/src/cli/fuzzySelect.d.ts +24 -0
- package/dist/src/cli/fuzzySelect.d.ts.map +1 -0
- package/dist/src/cli/layers.d.ts +40 -0
- package/dist/src/cli/layers.d.ts.map +1 -0
- package/dist/src/cli/layers.js +56 -12
- package/dist/src/cli/layers.js.map +1 -1
- package/dist/src/cli/list.d.ts +8 -0
- package/dist/src/cli/list.d.ts.map +1 -0
- package/dist/src/cli/list.js +2 -2
- package/dist/src/cli/list.js.map +1 -1
- package/dist/src/cli/reconcile.d.ts +129 -0
- package/dist/src/cli/reconcile.d.ts.map +1 -0
- package/dist/src/cli/reconcile.js +635 -46
- package/dist/src/cli/reconcile.js.map +1 -1
- package/dist/src/cli/root.d.ts +15 -0
- package/dist/src/cli/root.d.ts.map +1 -0
- package/dist/src/cli/root.js +4 -3
- package/dist/src/cli/root.js.map +1 -1
- package/dist/src/cli/runtimeFailure.d.ts +10 -0
- package/dist/src/cli/runtimeFailure.d.ts.map +1 -0
- package/dist/src/cli/runtimeFailure.js +17 -0
- package/dist/src/cli/runtimeFailure.js.map +1 -0
- package/dist/src/cli/setup.d.ts +10 -0
- package/dist/src/cli/setup.d.ts.map +1 -0
- package/dist/src/cli/setup.js +7 -7
- package/dist/src/cli/setup.js.map +1 -1
- package/dist/src/cli/timer/discard.d.ts +4 -0
- package/dist/src/cli/timer/discard.d.ts.map +1 -0
- package/dist/src/cli/timer/discard.js +2 -2
- package/dist/src/cli/timer/discard.js.map +1 -1
- package/dist/src/cli/timer/edit.d.ts +22 -0
- package/dist/src/cli/timer/edit.d.ts.map +1 -0
- package/dist/src/cli/timer/edit.js +62 -42
- package/dist/src/cli/timer/edit.js.map +1 -1
- package/dist/src/cli/timer/index.d.ts +12 -0
- package/dist/src/cli/timer/index.d.ts.map +1 -0
- package/dist/src/cli/timer/log.d.ts +16 -0
- package/dist/src/cli/timer/log.d.ts.map +1 -0
- package/dist/src/cli/timer/log.js +6 -6
- package/dist/src/cli/timer/log.js.map +1 -1
- package/dist/src/cli/timer/start.d.ts +21 -0
- package/dist/src/cli/timer/start.d.ts.map +1 -0
- package/dist/src/cli/timer/start.js +9 -9
- package/dist/src/cli/timer/start.js.map +1 -1
- package/dist/src/cli/timer/status.d.ts +22 -0
- package/dist/src/cli/timer/status.d.ts.map +1 -0
- package/dist/src/cli/timer/status.js +110 -71
- package/dist/src/cli/timer/status.js.map +1 -1
- package/dist/src/cli/timer/stop.d.ts +48 -0
- package/dist/src/cli/timer/stop.d.ts.map +1 -0
- package/dist/src/cli/timer/stop.js +19 -19
- package/dist/src/cli/timer/stop.js.map +1 -1
- package/dist/src/cli/timer.d.ts +11 -0
- package/dist/src/cli/timer.d.ts.map +1 -0
- package/dist/src/cli/timer.js +1 -1
- package/dist/src/cli/timer.js.map +1 -1
- package/dist/src/cli/watch.d.ts +54 -0
- package/dist/src/cli/watch.d.ts.map +1 -0
- package/dist/src/cli/watch.js +412 -0
- package/dist/src/cli/watch.js.map +1 -0
- package/dist/src/cli/watchLease.d.ts +99 -0
- package/dist/src/cli/watchLease.d.ts.map +1 -0
- package/dist/src/cli/watchLease.js +204 -0
- package/dist/src/cli/watchLease.js.map +1 -0
- package/dist/src/cli/writerGuard.d.ts +37 -0
- package/dist/src/cli/writerGuard.d.ts.map +1 -0
- package/dist/src/cli/writerGuard.js +92 -0
- package/dist/src/cli/writerGuard.js.map +1 -0
- package/dist/src/index.d.ts +46 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +46 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/main.d.ts +4 -0
- package/dist/src/main.d.ts.map +1 -0
- package/dist/src/services/AgentSessionReader.d.ts +121 -0
- package/dist/src/services/AgentSessionReader.d.ts.map +1 -0
- package/dist/src/services/AgentSessionReader.js +392 -0
- package/dist/src/services/AgentSessionReader.js.map +1 -0
- package/dist/src/services/ClockifyAuth.d.ts +47 -0
- package/dist/src/services/ClockifyAuth.d.ts.map +1 -0
- package/dist/src/services/ClockifyAuth.js +2 -2
- package/dist/src/services/ClockifyAuth.js.map +1 -1
- package/dist/src/services/CodexTranscript.d.ts +112 -0
- package/dist/src/services/CodexTranscript.d.ts.map +1 -0
- package/dist/src/services/CodexTranscript.js +96 -0
- package/dist/src/services/CodexTranscript.js.map +1 -0
- package/dist/src/services/ConfigService.d.ts +99 -0
- package/dist/src/services/ConfigService.d.ts.map +1 -0
- package/dist/src/services/ConfigService.js +79 -7
- package/dist/src/services/ConfigService.js.map +1 -1
- package/dist/src/services/HomeDirectory.d.ts +17 -0
- package/dist/src/services/HomeDirectory.d.ts.map +1 -0
- package/dist/src/services/HomeDirectory.js +1 -1
- package/dist/src/services/IssueFacts.d.ts +127 -0
- package/dist/src/services/IssueFacts.d.ts.map +1 -0
- package/dist/src/services/IssueFacts.js +277 -0
- package/dist/src/services/IssueFacts.js.map +1 -0
- package/dist/src/services/ProviderDeletion.d.ts +19 -0
- package/dist/src/services/ProviderDeletion.d.ts.map +1 -0
- package/dist/src/services/ProviderDeletion.js +37 -0
- package/dist/src/services/ProviderDeletion.js.map +1 -0
- package/dist/src/services/ReconcileService.d.ts +378 -0
- package/dist/src/services/ReconcileService.d.ts.map +1 -0
- package/dist/src/services/ReconcileService.js +1270 -79
- package/dist/src/services/ReconcileService.js.map +1 -1
- package/dist/src/services/SavedEntries.d.ts +40 -0
- package/dist/src/services/SavedEntries.d.ts.map +1 -0
- package/dist/src/services/SavedEntries.js +209 -0
- package/dist/src/services/SavedEntries.js.map +1 -0
- package/dist/src/services/SessionAttributor.d.ts +114 -0
- package/dist/src/services/SessionAttributor.d.ts.map +1 -0
- package/dist/src/services/SessionAttributor.js +240 -0
- package/dist/src/services/SessionAttributor.js.map +1 -0
- package/dist/src/services/SourceLedger.d.ts +104 -0
- package/dist/src/services/SourceLedger.d.ts.map +1 -0
- package/dist/src/services/SourceLedger.js +302 -0
- package/dist/src/services/SourceLedger.js.map +1 -0
- package/dist/src/services/StateWriter.d.ts +39 -0
- package/dist/src/services/StateWriter.d.ts.map +1 -0
- package/dist/src/services/TicketService.d.ts +63 -0
- package/dist/src/services/TicketService.d.ts.map +1 -0
- package/dist/src/services/TimerService.d.ts +145 -0
- package/dist/src/services/TimerService.d.ts.map +1 -0
- package/dist/src/services/TimerService.js +113 -80
- package/dist/src/services/TimerService.js.map +1 -1
- package/dist/src/services/internal/JiraWorklogPost.d.ts +7 -0
- package/dist/src/services/internal/JiraWorklogPost.d.ts.map +1 -0
- package/dist/src/services/internal/JiraWorklogPost.js +32 -0
- package/dist/src/services/internal/JiraWorklogPost.js.map +1 -0
- package/dist/src/testing/fakeHeadless.d.ts +318 -0
- package/dist/src/testing/fakeHeadless.d.ts.map +1 -0
- package/dist/src/testing/fakeHeadless.js +1149 -0
- package/dist/src/testing/fakeHeadless.js.map +1 -0
- package/dist/src/tui/App.d.ts +6 -0
- package/dist/src/tui/App.d.ts.map +1 -0
- package/dist/src/tui/App.js +1 -1
- package/dist/src/tui/App.js.map +1 -1
- package/dist/src/tui/atoms/runtime.d.ts +8 -0
- package/dist/src/tui/atoms/runtime.d.ts.map +1 -0
- package/dist/src/tui/atoms/runtime.js +1 -1
- package/dist/src/tui/atoms/runtime.js.map +1 -1
- package/dist/src/tui/atoms/tickets.d.ts +3 -0
- package/dist/src/tui/atoms/tickets.d.ts.map +1 -0
- package/dist/src/tui/atoms/timer.d.ts +11 -0
- package/dist/src/tui/atoms/timer.d.ts.map +1 -0
- package/dist/src/tui/atoms/timer.js +1 -1
- package/dist/src/tui/atoms/timer.js.map +1 -1
- package/dist/src/tui/atoms/ui.d.ts +11 -0
- package/dist/src/tui/atoms/ui.d.ts.map +1 -0
- package/dist/src/tui/atoms/ui.js +1 -1
- package/dist/src/tui/atoms/ui.js.map +1 -1
- package/dist/src/tui/components/BigTimer.d.ts +2 -0
- package/dist/src/tui/components/BigTimer.d.ts.map +1 -0
- package/dist/src/tui/components/Footer.d.ts +2 -0
- package/dist/src/tui/components/Footer.d.ts.map +1 -0
- package/dist/src/tui/components/Header.d.ts +2 -0
- package/dist/src/tui/components/Header.d.ts.map +1 -0
- package/dist/src/tui/components/Header.js +1 -1
- package/dist/src/tui/components/Header.js.map +1 -1
- package/dist/src/tui/components/PopupInput.d.ts +18 -0
- package/dist/src/tui/components/PopupInput.d.ts.map +1 -0
- package/dist/src/tui/components/PopupMessage.d.ts +20 -0
- package/dist/src/tui/components/PopupMessage.d.ts.map +1 -0
- package/dist/src/tui/components/TicketList.d.ts +2 -0
- package/dist/src/tui/components/TicketList.d.ts.map +1 -0
- package/dist/src/tui/components/TicketList.js +1 -1
- package/dist/src/tui/components/TicketList.js.map +1 -1
- package/dist/src/tui/components/TicketRow.d.ts +8 -0
- package/dist/src/tui/components/TicketRow.d.ts.map +1 -0
- package/dist/src/tui/components/TimerDisplay.d.ts +2 -0
- package/dist/src/tui/components/TimerDisplay.d.ts.map +1 -0
- package/dist/src/tui/components/index.d.ts +12 -0
- package/dist/src/tui/components/index.d.ts.map +1 -0
- package/dist/src/tui/context/theme.d.ts +15 -0
- package/dist/src/tui/context/theme.d.ts.map +1 -0
- package/dist/src/tui/hooks/useElapsedTimer.d.ts +6 -0
- package/dist/src/tui/hooks/useElapsedTimer.d.ts.map +1 -0
- package/dist/src/tui/hooks/useElapsedTimer.js +1 -1
- package/dist/src/tui/hooks/useElapsedTimer.js.map +1 -1
- package/dist/src/tui/hooks/useTerminalSize.d.ts +5 -0
- package/dist/src/tui/hooks/useTerminalSize.d.ts.map +1 -0
- package/dist/src/utils/hints.d.ts +12 -0
- package/dist/src/utils/hints.d.ts.map +1 -0
- package/dist/src/utils/hints.js +12 -0
- package/dist/src/utils/hints.js.map +1 -0
- package/dist/src/utils/time.d.ts +104 -0
- package/dist/src/utils/time.d.ts.map +1 -0
- package/dist/src/utils/time.js +74 -8
- package/dist/src/utils/time.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/nvim/lua/jcf/state.lua +191 -13
- package/package.json +36 -18
- package/skills/jcf/SKILL.md +93 -1
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read local Claude Code and Codex Agent Sessions as reconciliation evidence.
|
|
3
|
+
*
|
|
4
|
+
* **Mental model**
|
|
5
|
+
*
|
|
6
|
+
* - **Read-only evidence**: transcripts are never written, moved, or modified. This service only
|
|
7
|
+
* reports what a session touched, when, and where — see ADR-0006.
|
|
8
|
+
* - **Opt-in scope**: a session becomes evidence only when its working directory sits inside a
|
|
9
|
+
* configured Session Root. Claude project names allow a pre-read filter; Codex date directories
|
|
10
|
+
* do not, so Codex working directories are checked after local decoding. Out-of-scope text never
|
|
11
|
+
* reaches ticket mining, a Coding Agent or a proposal.
|
|
12
|
+
* - **Tolerant decoding**: the transcript layout is an external contract that changes without
|
|
13
|
+
* notice. Unrecognised and malformed lines are skipped; a session survives on the lines it can
|
|
14
|
+
* decode rather than failing the whole run.
|
|
15
|
+
* - **Presence, not busy-ness**: only messages the *person* typed count as Session Activity. A
|
|
16
|
+
* transcript is overwhelmingly the agent's own output — measured on one real day, 1641 events of
|
|
17
|
+
* which 66 were human — so counting every event measures how long the agent was busy, which is
|
|
18
|
+
* not the same as how long anyone was working.
|
|
19
|
+
*
|
|
20
|
+
* **Gotchas**
|
|
21
|
+
*
|
|
22
|
+
* - A `user` line is not necessarily a person. Tool results come back as `user` messages whose
|
|
23
|
+
* content is `tool_result` blocks, and they outnumber real prompts roughly ten to one. Only text
|
|
24
|
+
* content counts.
|
|
25
|
+
* - Assistant output, sidechain turns, and tool results still feed the candidate Issue Keys and the
|
|
26
|
+
* digest: they say nothing about presence, but plenty about *what* the session was for.
|
|
27
|
+
* - The working directory and branch are taken from the session's last in-window line of any kind —
|
|
28
|
+
* the state the credited work actually ran under.
|
|
29
|
+
*
|
|
30
|
+
* @module
|
|
31
|
+
*/
|
|
32
|
+
import * as Context from "effect/Context";
|
|
33
|
+
import * as Data from "effect/Data";
|
|
34
|
+
import * as Effect from "effect/Effect";
|
|
35
|
+
import * as FileSystem from "effect/FileSystem";
|
|
36
|
+
import * as Layer from "effect/Layer";
|
|
37
|
+
import * as Option from "effect/Option";
|
|
38
|
+
import * as Path from "effect/Path";
|
|
39
|
+
import * as Predicate from "effect/Predicate";
|
|
40
|
+
import * as Schema from "effect/Schema";
|
|
41
|
+
import * as Stream from "effect/Stream";
|
|
42
|
+
import { buildSessionDigest, expandHomePath, isWithinSessionRoots, mineTicketKeys } from "../agent/sessions.js";
|
|
43
|
+
import { codexTranscriptLines, decodeCodexLine } from "./CodexTranscript.js";
|
|
44
|
+
import { ConfigService } from "./ConfigService.js";
|
|
45
|
+
import { HomeDirectory } from "./HomeDirectory.js";
|
|
46
|
+
export class AgentSessionError extends Data.TaggedError("AgentSessionError") {
|
|
47
|
+
}
|
|
48
|
+
export class AgentSessionReader extends Context.Service()("jcf/AgentSessionReader") {
|
|
49
|
+
}
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Transcript decoding
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
/**
|
|
54
|
+
* The subset of a transcript line jcf depends on. Everything is optional because every field is
|
|
55
|
+
* outside our control; a line missing `timestamp`, `sessionId`, or `cwd` simply is not activity.
|
|
56
|
+
*/
|
|
57
|
+
const TranscriptLine = Schema.Struct({
|
|
58
|
+
type: Schema.optional(Schema.String),
|
|
59
|
+
sessionId: Schema.optional(Schema.String),
|
|
60
|
+
timestamp: Schema.optional(Schema.String),
|
|
61
|
+
cwd: Schema.optional(Schema.String),
|
|
62
|
+
gitBranch: Schema.optional(Schema.NullOr(Schema.String)),
|
|
63
|
+
isSidechain: Schema.optional(Schema.NullOr(Schema.Boolean)),
|
|
64
|
+
message: Schema.optional(Schema.Unknown)
|
|
65
|
+
});
|
|
66
|
+
const TextBlock = Schema.Struct({
|
|
67
|
+
type: Schema.optional(Schema.String),
|
|
68
|
+
text: Schema.optional(Schema.String)
|
|
69
|
+
});
|
|
70
|
+
/**
|
|
71
|
+
* A `tool_result` carries its output in `content`. It is decoded on its own, so an output shape we
|
|
72
|
+
* do not understand loses only that output, never the rest of the message.
|
|
73
|
+
*/
|
|
74
|
+
const ContentBlock = Schema.Struct({
|
|
75
|
+
type: Schema.optional(Schema.String),
|
|
76
|
+
text: Schema.optional(Schema.String),
|
|
77
|
+
content: Schema.optional(Schema.Unknown)
|
|
78
|
+
});
|
|
79
|
+
const decodeToolOutput = Schema.decodeUnknownOption(Schema.Union([Schema.String, Schema.Array(TextBlock)]));
|
|
80
|
+
/** Message content is either a bare string or a list of blocks, only some of which carry text. */
|
|
81
|
+
const MessageContent = Schema.Struct({
|
|
82
|
+
content: Schema.optional(Schema.Union([Schema.String, Schema.Array(ContentBlock)]))
|
|
83
|
+
});
|
|
84
|
+
const JsonValue = Schema.fromJsonString(Schema.Json);
|
|
85
|
+
const decodeJson = Schema.decodeUnknownOption(JsonValue);
|
|
86
|
+
const decodeLine = Schema.decodeUnknownOption(TranscriptLine);
|
|
87
|
+
const decodeContent = Schema.decodeUnknownOption(MessageContent);
|
|
88
|
+
/** Line types that carry a timestamp and a message. Everything else is session metadata. */
|
|
89
|
+
const ACTIVITY_TYPES = ["user", "assistant"];
|
|
90
|
+
/** Block types that are the agent's own machinery rather than anything a person wrote. */
|
|
91
|
+
const MACHINE_BLOCK_TYPES = ["tool_result", "tool_use", "thinking"];
|
|
92
|
+
/**
|
|
93
|
+
* How much of one tool result is kept as evidence. Command output can be megabytes; an Issue Key a
|
|
94
|
+
* command printed sits near the top, and the digest only needs a hint of what the output was.
|
|
95
|
+
*/
|
|
96
|
+
const TOOL_RESULT_TEXT_LIMIT = 2_000;
|
|
97
|
+
/** The textual output of a tool result, bounded; non-text parts such as images are ignored. */
|
|
98
|
+
const toolResultText = (output) => {
|
|
99
|
+
const decoded = decodeToolOutput(output);
|
|
100
|
+
if (Option.isNone(decoded))
|
|
101
|
+
return [];
|
|
102
|
+
const content = decoded.value;
|
|
103
|
+
const text = Predicate.isString(content)
|
|
104
|
+
? content
|
|
105
|
+
: content.flatMap((block) => (block.text === undefined ? [] : [block.text])).join("\n");
|
|
106
|
+
return text.length === 0 ? [] : [text.slice(0, TOOL_RESULT_TEXT_LIMIT)];
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* The readable text of a message, or `""` when it carries none we understand.
|
|
110
|
+
*
|
|
111
|
+
* Includes tool-result output: it is attribution and description evidence, never presence, which
|
|
112
|
+
* {@link isHumanPrompt} decides separately.
|
|
113
|
+
*/
|
|
114
|
+
const messageText = (message) => {
|
|
115
|
+
const decoded = decodeContent(message);
|
|
116
|
+
if (Option.isNone(decoded))
|
|
117
|
+
return "";
|
|
118
|
+
const content = decoded.value.content;
|
|
119
|
+
if (content === undefined)
|
|
120
|
+
return "";
|
|
121
|
+
if (Predicate.isString(content))
|
|
122
|
+
return content;
|
|
123
|
+
return content.flatMap((block) => block.type === "tool_result"
|
|
124
|
+
? toolResultText(block.content)
|
|
125
|
+
: block.text === undefined
|
|
126
|
+
? []
|
|
127
|
+
: [block.text]).join("\n");
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* True when a line is a message the person typed — the only thing that evidences their presence.
|
|
131
|
+
*
|
|
132
|
+
* A bare string is a person only on the main thread. A block list is a person only if it contains
|
|
133
|
+
* none of the agent's machinery: tool results in particular arrive as `user` messages and are far
|
|
134
|
+
* more numerous than real prompts, so counting them would measure the agent's throughput as if it
|
|
135
|
+
* were attention.
|
|
136
|
+
*
|
|
137
|
+
* A sidechain line is the agent talking to its own subagent. It has the exact shape of a typed
|
|
138
|
+
* prompt — `type: "user"`, plain string content — so nothing else here would exclude it, and a run
|
|
139
|
+
* that fans out to many subagents would manufacture a stream of "prompts" dense enough to bridge
|
|
140
|
+
* every Idle Cap gap. That is the one thing the Idle Cap exists to stop, and under `jcf watch` the
|
|
141
|
+
* result would be written unattended.
|
|
142
|
+
*/
|
|
143
|
+
const isHumanPrompt = (line, message) => {
|
|
144
|
+
if (line.type !== "user" || line.isSidechain === true)
|
|
145
|
+
return false;
|
|
146
|
+
const decoded = decodeContent(message);
|
|
147
|
+
if (Option.isNone(decoded))
|
|
148
|
+
return false;
|
|
149
|
+
const content = decoded.value.content;
|
|
150
|
+
if (content === undefined)
|
|
151
|
+
return false;
|
|
152
|
+
if (Predicate.isString(content))
|
|
153
|
+
return content.trim().length > 0;
|
|
154
|
+
return (content.length > 0 &&
|
|
155
|
+
content.every((block) => block.type === undefined || !MACHINE_BLOCK_TYPES.includes(block.type)));
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Decode one transcript into the evidence it holds, keeping only activity inside `[from, to)`.
|
|
159
|
+
*
|
|
160
|
+
* Returns one entry per *segment* — a stretch of the transcript that ran under one working
|
|
161
|
+
* directory and one branch. A session that switches branch mid-run is two pieces of work, and
|
|
162
|
+
* taking the last line's branch for all of it would credit the morning's prompts to the afternoon's
|
|
163
|
+
* ticket. Under `jcf watch` that is worse than a misattribution: the morning can already have been
|
|
164
|
+
* written under the first ticket before the switch, and would then be derived again under the
|
|
165
|
+
* second, putting the same wall clock on two tickets.
|
|
166
|
+
*
|
|
167
|
+
* Segments that resolve to the same Issue Key are unioned again downstream, so splitting costs
|
|
168
|
+
* nothing when a branch change does not change the work. What it does cost is the gap *across* a
|
|
169
|
+
* switch, which is no longer bridged — an under-count of at most one Idle Cap, which is the
|
|
170
|
+
* direction this design prefers to be wrong in.
|
|
171
|
+
*
|
|
172
|
+
* Pure and total: a malformed line, an unparseable timestamp, or a file of pure noise yields no
|
|
173
|
+
* segments rather than an error.
|
|
174
|
+
*/
|
|
175
|
+
export const decodeTranscript = (content, period) => decodeTranscriptLines(claudeTranscriptLines(content), period);
|
|
176
|
+
/** Skip malformed external lines before the common segmenter sees them. */
|
|
177
|
+
function* claudeTranscriptLines(content) {
|
|
178
|
+
for (const rawLine of content.split("\n")) {
|
|
179
|
+
const json = decodeJson(rawLine);
|
|
180
|
+
if (Option.isNone(json))
|
|
181
|
+
continue;
|
|
182
|
+
const decoded = decodeLine(json.value);
|
|
183
|
+
if (Option.isSome(decoded))
|
|
184
|
+
yield decoded.value;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/** Both providers share presence accounting and per-directory evidence boundaries. */
|
|
188
|
+
const decodeTranscriptLines = (lines, period) => {
|
|
189
|
+
const segments = [];
|
|
190
|
+
let promptTimes = [];
|
|
191
|
+
let texts = [];
|
|
192
|
+
let sessionId = null;
|
|
193
|
+
let cwd = null;
|
|
194
|
+
let gitBranch = null;
|
|
195
|
+
// One segment per `(cwd, branch)`. The id carries the segment index so windows, attributions and
|
|
196
|
+
// digests all key on the same thing — they are looked up from three different places.
|
|
197
|
+
const closeSegment = (endedAtMs) => {
|
|
198
|
+
if (sessionId !== null && cwd !== null && promptTimes.length > 0) {
|
|
199
|
+
const id = segments.length === 0 ? sessionId : `${sessionId}#${String(segments.length)}`;
|
|
200
|
+
segments.push({
|
|
201
|
+
sessionId: id,
|
|
202
|
+
cwd,
|
|
203
|
+
gitBranch,
|
|
204
|
+
// Where the segment gives way to the next. Presence after its final prompt ends there, not
|
|
205
|
+
// one whole Idle Cap later: the same person carried straight on under a different branch, so
|
|
206
|
+
// crediting the tail to both would put the switch's minutes on two tickets at once.
|
|
207
|
+
boundedAtMs: endedAtMs,
|
|
208
|
+
activity: promptTimes.map((atMs) => ({ sessionId: id, atMs })),
|
|
209
|
+
texts
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
// Reset unconditionally. A stretch with no typed prompt still has text, and leaving it behind
|
|
213
|
+
// leaks it into the next segment — including text from a directory that was never opted in.
|
|
214
|
+
promptTimes = [];
|
|
215
|
+
texts = [];
|
|
216
|
+
};
|
|
217
|
+
for (const line of lines) {
|
|
218
|
+
if (line.type === undefined || !ACTIVITY_TYPES.includes(line.type))
|
|
219
|
+
continue;
|
|
220
|
+
if (line.sessionId === undefined || line.timestamp === undefined || line.cwd === undefined)
|
|
221
|
+
continue;
|
|
222
|
+
const atMs = Date.parse(line.timestamp);
|
|
223
|
+
if (Number.isNaN(atMs))
|
|
224
|
+
continue;
|
|
225
|
+
if (atMs < period.fromMs || atMs >= period.toMs)
|
|
226
|
+
continue;
|
|
227
|
+
// Closed *before* this line contributes anything: the first line under the new branch is
|
|
228
|
+
// evidence about the new segment, and appending it first put it in the old segment's digest and
|
|
229
|
+
// left it out of the new one's.
|
|
230
|
+
const branch = line.gitBranch ?? null;
|
|
231
|
+
if (cwd !== null && (cwd !== line.cwd || gitBranch !== branch))
|
|
232
|
+
closeSegment(atMs);
|
|
233
|
+
sessionId = line.sessionId;
|
|
234
|
+
cwd = line.cwd;
|
|
235
|
+
gitBranch = branch;
|
|
236
|
+
// Inside the window only, and every kind of line: a key mentioned solely in the agent's own
|
|
237
|
+
// output is still a candidate, but a prompt written after the window is not evidence about it.
|
|
238
|
+
// A resumed session that moved on to something else would otherwise attribute — and describe —
|
|
239
|
+
// yesterday's hours from today's work, and could carry text from a directory that was never
|
|
240
|
+
// opted in to a Coding Agent.
|
|
241
|
+
const text = messageText(line.message);
|
|
242
|
+
if (text !== "")
|
|
243
|
+
texts.push(text);
|
|
244
|
+
if (isHumanPrompt(line, line.message))
|
|
245
|
+
promptTimes.push(atMs);
|
|
246
|
+
}
|
|
247
|
+
closeSegment(null);
|
|
248
|
+
return segments;
|
|
249
|
+
};
|
|
250
|
+
// ---------------------------------------------------------------------------
|
|
251
|
+
// Service
|
|
252
|
+
// ---------------------------------------------------------------------------
|
|
253
|
+
/** Where the Claude CLI keeps its transcripts, one directory per project. */
|
|
254
|
+
const CLAUDE_TRANSCRIPT_DIR = [".claude", "projects"];
|
|
255
|
+
const TRANSCRIPT_SUFFIX = ".jsonl";
|
|
256
|
+
/**
|
|
257
|
+
* A working directory as the Claude CLI names the project directory holding its transcripts:
|
|
258
|
+
* `/`, `.`, and the Windows drive colon become `-`, so `C:/Work/Repo` becomes `C--Work-Repo`.
|
|
259
|
+
*/
|
|
260
|
+
const encodeProjectDir = (cwd) => cwd.replace(/[/:.]/g, "-");
|
|
261
|
+
/**
|
|
262
|
+
* True when a project directory could hold a session inside one of the Session Roots.
|
|
263
|
+
*
|
|
264
|
+
* A *filter*, not a decision. The encoding is many-to-one — a root `/a/b-c` and an out-of-root
|
|
265
|
+
* `/a/b/c` both become `-a-b-c` — so a directory it admits may still turn out to be elsewhere, and
|
|
266
|
+
* the authoritative check on the decoded `cwd` runs afterwards regardless. What it cannot do is
|
|
267
|
+
* exclude one wrongly: separators encode character-by-character after a trailing root separator
|
|
268
|
+
* is removed, and Windows root spelling is folded. The decoded `cwd` still decides scope.
|
|
269
|
+
*
|
|
270
|
+
* So the guarantee is bounded, and worth stating exactly: a transcript whose project directory
|
|
271
|
+
* cannot encode from any Session Root is never opened, which in a working set of any size is nearly
|
|
272
|
+
* all of them. A transcript that collides with a root's encoding is opened and then discarded
|
|
273
|
+
* unread — the honest limit of deciding scope from a lossy directory name.
|
|
274
|
+
*/
|
|
275
|
+
export const mayHoldSessionRoot = (projectDir, roots) => roots.some((root) => {
|
|
276
|
+
const windows = /^[A-Za-z]:[\\/]/.test(root) || /^[\\/]{2}[^\\/]+[\\/][^\\/]+/.test(root);
|
|
277
|
+
const canonicalRoot = (windows ? root.replaceAll("\\", "/") : root).replace(/\/+$/, "");
|
|
278
|
+
const encoded = encodeProjectDir(canonicalRoot);
|
|
279
|
+
const candidate = windows ? projectDir.toLowerCase() : projectDir;
|
|
280
|
+
const prefix = windows ? encoded.toLowerCase() : encoded;
|
|
281
|
+
return prefix.length > 0 && (candidate === prefix || candidate.startsWith(`${prefix}-`));
|
|
282
|
+
});
|
|
283
|
+
export const layer = Layer.effect(AgentSessionReader, Effect.gen(function* () {
|
|
284
|
+
const fs = yield* FileSystem.FileSystem;
|
|
285
|
+
const path = yield* Path.Path;
|
|
286
|
+
const home = (yield* HomeDirectory).path;
|
|
287
|
+
const config = yield* ConfigService;
|
|
288
|
+
const transcriptRoot = path.join(home, ...CLAUDE_TRANSCRIPT_DIR);
|
|
289
|
+
const codexRoot = path.join(home, ".codex", "sessions");
|
|
290
|
+
const asAgentSessionError = (message) => (cause) => Effect.fail(new AgentSessionError({ message: `${message}: ${cause.message}`, cause }));
|
|
291
|
+
/**
|
|
292
|
+
* Every `*.jsonl` transcript under the Claude project directories.
|
|
293
|
+
*
|
|
294
|
+
* A *missing* transcript root is an empty result — the user may simply never have run Claude.
|
|
295
|
+
* A root that exists but cannot be read is an error, because reporting "no sessions" for a
|
|
296
|
+
* permission problem would look exactly like having nothing to log.
|
|
297
|
+
*/
|
|
298
|
+
const transcriptPaths = (roots) => Effect.gen(function* () {
|
|
299
|
+
const exists = yield* fs
|
|
300
|
+
.exists(transcriptRoot)
|
|
301
|
+
.pipe(Effect.catch(asAgentSessionError("Checking for Claude transcripts failed")));
|
|
302
|
+
if (!exists)
|
|
303
|
+
return [];
|
|
304
|
+
const projectDirs = yield* fs
|
|
305
|
+
.readDirectory(transcriptRoot)
|
|
306
|
+
.pipe(Effect.catch(asAgentSessionError("Listing Claude projects failed")));
|
|
307
|
+
const paths = [];
|
|
308
|
+
for (const projectDir of projectDirs) {
|
|
309
|
+
// Before the directory is even listed: a project outside every Session Root is not opened.
|
|
310
|
+
if (!mayHoldSessionRoot(projectDir, roots))
|
|
311
|
+
continue;
|
|
312
|
+
const dir = path.join(transcriptRoot, projectDir);
|
|
313
|
+
const entries = yield* fs
|
|
314
|
+
.readDirectory(dir)
|
|
315
|
+
.pipe(Effect.catch(asAgentSessionError(`Listing Claude project ${projectDir} failed`)));
|
|
316
|
+
for (const entry of entries) {
|
|
317
|
+
if (entry.endsWith(TRANSCRIPT_SUFFIX))
|
|
318
|
+
paths.push(path.join(dir, entry));
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return paths;
|
|
322
|
+
});
|
|
323
|
+
/**
|
|
324
|
+
* True when a file could hold activity in the window. A transcript's last write is at or
|
|
325
|
+
* after its last activity, so an older mtime is a sound reason to skip reading it at all —
|
|
326
|
+
* which matters because a working directory accumulates hundreds of transcripts.
|
|
327
|
+
*/
|
|
328
|
+
const mayHoldActivity = (filePath, fromMs) => fs.stat(filePath).pipe(Effect.map((info) => Option.isNone(info.mtime) || info.mtime.value.getTime() >= fromMs), Effect.catch((error) => Effect.logDebug(`Transcript stat failed, reading anyway: ${error.message}`).pipe(Effect.as(true))));
|
|
329
|
+
const read = (period) => Effect.gen(function* () {
|
|
330
|
+
const cfg = yield* config.get;
|
|
331
|
+
const roots = cfg.sessionRoots.map((root) => expandHomePath(root, home));
|
|
332
|
+
// No Session Root means nothing is opted in, so there is nothing to read.
|
|
333
|
+
if (roots.length === 0)
|
|
334
|
+
return [];
|
|
335
|
+
const fromMs = period.from.getTime();
|
|
336
|
+
const toMs = period.to.getTime();
|
|
337
|
+
const paths = yield* transcriptPaths(roots);
|
|
338
|
+
const records = [];
|
|
339
|
+
const addSegments = (segments) => {
|
|
340
|
+
for (const segment of segments) {
|
|
341
|
+
// Scope precedes key mining and digest construction, including moved Codex sessions.
|
|
342
|
+
if (!isWithinSessionRoots(segment.cwd, roots))
|
|
343
|
+
continue;
|
|
344
|
+
records.push({
|
|
345
|
+
sessionId: segment.sessionId,
|
|
346
|
+
cwd: segment.cwd,
|
|
347
|
+
gitBranch: segment.gitBranch,
|
|
348
|
+
candidateKeys: mineTicketKeys(segment.texts.join("\n")),
|
|
349
|
+
digest: buildSessionDigest(segment.texts),
|
|
350
|
+
activity: segment.activity,
|
|
351
|
+
boundedAtMs: segment.boundedAtMs
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
for (const filePath of paths) {
|
|
356
|
+
if (!(yield* mayHoldActivity(filePath, fromMs)))
|
|
357
|
+
continue;
|
|
358
|
+
// Fails the run rather than skipping the file. An in-scope transcript that cannot be read
|
|
359
|
+
// is not an absent one: it may overlap a readable session on another ticket, and dropping
|
|
360
|
+
// it takes that ticket out of the overlap sharing — so the interval it should have halved
|
|
361
|
+
// is credited whole to whichever session happened to be readable, and `watch` writes it.
|
|
362
|
+
// An out-of-scope path never reaches here; `transcriptPaths` has already excluded it.
|
|
363
|
+
const content = yield* fs.readFileString(filePath).pipe(Effect.mapError((error) => new AgentSessionError({
|
|
364
|
+
message: `Could not read the session transcript ${filePath}: ${error.message}`,
|
|
365
|
+
cause: error
|
|
366
|
+
})));
|
|
367
|
+
addSegments(decodeTranscript(content, { fromMs, toMs }));
|
|
368
|
+
}
|
|
369
|
+
const hasCodex = yield* fs
|
|
370
|
+
.exists(codexRoot)
|
|
371
|
+
.pipe(Effect.catch(asAgentSessionError("Checking Codex sessions failed")));
|
|
372
|
+
if (hasCodex) {
|
|
373
|
+
// Date directories name creation time, not last activity: resumed old rollouts still count.
|
|
374
|
+
const entries = yield* fs
|
|
375
|
+
.readDirectory(codexRoot, { recursive: true })
|
|
376
|
+
.pipe(Effect.catch(asAgentSessionError("Listing Codex sessions failed")));
|
|
377
|
+
for (const entry of entries) {
|
|
378
|
+
if (!entry.endsWith(TRANSCRIPT_SUFFIX))
|
|
379
|
+
continue;
|
|
380
|
+
const filePath = path.join(codexRoot, entry);
|
|
381
|
+
if (!(yield* mayHoldActivity(filePath, fromMs)))
|
|
382
|
+
continue;
|
|
383
|
+
// Rollouts can be hundreds of MB; discard tool data before retaining decoded messages.
|
|
384
|
+
const lines = yield* fs.stream(filePath).pipe(Stream.decodeText(), Stream.splitLines, Stream.map((line) => decodeCodexLine(line)), Stream.filter(Option.isSome), Stream.map((decoded) => decoded.value), Stream.runCollect, Effect.catch(asAgentSessionError("Reading Codex session failed")));
|
|
385
|
+
addSegments(decodeTranscriptLines(codexTranscriptLines(lines), { fromMs, toMs }));
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return records;
|
|
389
|
+
});
|
|
390
|
+
return { read };
|
|
391
|
+
}));
|
|
392
|
+
//# sourceMappingURL=AgentSessionReader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentSessionReader.js","sourceRoot":"","sources":["../../../src/services/AgentSessionReader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-based Clockify API key storage with schema-validated reads.
|
|
3
|
+
*
|
|
4
|
+
* **Mental model**
|
|
5
|
+
*
|
|
6
|
+
* - **Credential file**: Reads/writes `~/.jcf/clockify.json` containing API key, workspace ID,
|
|
7
|
+
* user ID, and base URL. The API key is wrapped in `Redacted` on read.
|
|
8
|
+
* - **Schema-gated**: JSON is parsed then validated via `Schema.decodeUnknownEffect(StoredAuth)` —
|
|
9
|
+
* corrupt data yields {@link ClockifyAuthMissingError} instead of a crash.
|
|
10
|
+
* - **Config-based home dir**: Uses Effect `Config.String("HOME")` for testable env access.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import type { ClockifyApiConfigContract } from "@knpkv/clockify-api-client";
|
|
15
|
+
import * as Context from "effect/Context";
|
|
16
|
+
import * as Effect from "effect/Effect";
|
|
17
|
+
import * as FileSystem from "effect/FileSystem";
|
|
18
|
+
import * as Layer from "effect/Layer";
|
|
19
|
+
import * as Path from "effect/Path";
|
|
20
|
+
import * as Schema from "effect/Schema";
|
|
21
|
+
import { HomeDirectory } from "./HomeDirectory.js";
|
|
22
|
+
declare const ClockifyAuthMissingError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
23
|
+
readonly _tag: "ClockifyAuthMissingError";
|
|
24
|
+
} & Readonly<A>;
|
|
25
|
+
export declare class ClockifyAuthMissingError extends ClockifyAuthMissingError_base<{
|
|
26
|
+
readonly message: string;
|
|
27
|
+
}> {
|
|
28
|
+
}
|
|
29
|
+
declare const StoredAuth: Schema.Struct<{
|
|
30
|
+
readonly apiKey: Schema.String;
|
|
31
|
+
readonly workspaceId: Schema.String;
|
|
32
|
+
readonly userId: Schema.String;
|
|
33
|
+
readonly baseUrl: Schema.optional<Schema.String>;
|
|
34
|
+
}>;
|
|
35
|
+
interface StoredAuth extends Schema.Schema.Type<typeof StoredAuth> {
|
|
36
|
+
}
|
|
37
|
+
export interface ClockifyAuthContract {
|
|
38
|
+
readonly getConfig: Effect.Effect<ClockifyApiConfigContract, ClockifyAuthMissingError>;
|
|
39
|
+
readonly save: (auth: StoredAuth) => Effect.Effect<void>;
|
|
40
|
+
readonly isConfigured: Effect.Effect<boolean>;
|
|
41
|
+
}
|
|
42
|
+
declare const ClockifyAuth_base: Context.ServiceClass<ClockifyAuth, "jcf/ClockifyAuth", ClockifyAuthContract>;
|
|
43
|
+
export declare class ClockifyAuth extends ClockifyAuth_base {
|
|
44
|
+
}
|
|
45
|
+
export declare const layer: Layer.Layer<ClockifyAuth, never, FileSystem.FileSystem | HomeDirectory | Path.Path>;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=ClockifyAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClockifyAuth.d.ts","sourceRoot":"","sources":["../../../src/services/ClockifyAuth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAA;AAC3E,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AAEzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,IAAI,MAAM,aAAa,CAAA;AAGnC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;;;;AAElD,qBAAa,wBAAyB,SAAQ,8BAA6C;IACzF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB,CAAC;CAAG;AAEL,QAAA,MAAM,UAAU;;;;;EAKd,CAAA;AACF,UAAU,UAAW,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,UAAU,CAAC;CAAG;AAErE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,yBAAyB,EAAE,wBAAwB,CAAC,CAAA;IACtF,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACxD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;CAC9C;;AAED,qBAAa,YAAa,SAAQ,iBAAyE;CAAG;AAM9G,eAAO,MAAM,KAAK,qFA0DjB,CAAA"}
|
|
@@ -37,9 +37,9 @@ export const layer = Layer.effect(ClockifyAuth, Effect.gen(function* () {
|
|
|
37
37
|
getConfig: Effect.gen(function* () {
|
|
38
38
|
const exists = yield* fs.exists(filePath);
|
|
39
39
|
if (!exists) {
|
|
40
|
-
return yield*
|
|
40
|
+
return yield* new ClockifyAuthMissingError({
|
|
41
41
|
message: "Clockify not configured. Run: jcf auth clockify setup"
|
|
42
|
-
})
|
|
42
|
+
});
|
|
43
43
|
}
|
|
44
44
|
const content = yield* fs.readFileString(filePath).pipe(Effect.mapError(() => new ClockifyAuthMissingError({ message: "Failed to read Clockify auth file" })));
|
|
45
45
|
const json = yield* Effect.try({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClockifyAuth.js","sourceRoot":"","sources":["../../../src/services/ClockifyAuth.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,IAAI,MAAM,aAAa,CAAA;AACnC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,IAAI,MAAM,aAAa,CAAA;AACnC,OAAO,KAAK,SAAS,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,MAAM,OAAO,wBAAyB,SAAQ,IAAI,CAAC,WAAW,CAAC,0BAA0B,CAEvF;CAAG;AAEL,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM;IACrB,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CACxC,CAAC,CAAA;AASF,MAAM,OAAO,YAAa,SAAQ,OAAO,CAAC,OAAO,EAAsC,CAAC,kBAAkB,CAAC;CAAG;AAE9G,MAAM,QAAQ,GAAG,MAAM,CAAA;AACvB,MAAM,SAAS,GAAG,eAAe,CAAA;AACjC,MAAM,gBAAgB,GAAG,6BAA6B,CAAA;AAEtD,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAC/B,YAAY,EACZ,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAA;IACvC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAA;IAC7B,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAA;IACxC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;IAE1C,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACpC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACpC,IAAI,CAAC,MAAM;YAAE,KAAK,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAChE,CAAC,CAAC,CAAA;IAEF,MAAM,gBAAgB,GAAG,MAAM,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAA;IAE/D,OAAO;QACL,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC7B,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;YACzC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,KAAK,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"ClockifyAuth.js","sourceRoot":"","sources":["../../../src/services/ClockifyAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize Codex rollouts into session messages. Only authoritative user events count as
|
|
3
|
+
* presence: response-item copies also contain injected instructions and replayed compacted history.
|
|
4
|
+
* Metadata and turn contexts supply the directory; native subagent rollouts supply no human time.
|
|
5
|
+
*/
|
|
6
|
+
import * as Schema from "effect/Schema";
|
|
7
|
+
declare const CodexLine: Schema.Union<readonly [Schema.Struct<{
|
|
8
|
+
readonly type: Schema.Literal<"session_meta">;
|
|
9
|
+
readonly payload: Schema.Struct<{
|
|
10
|
+
readonly id: Schema.String;
|
|
11
|
+
readonly cwd: Schema.String;
|
|
12
|
+
readonly source: Schema.optional<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
|
|
13
|
+
readonly git: Schema.optional<Schema.Struct<{
|
|
14
|
+
readonly branch: Schema.optional<Schema.String>;
|
|
15
|
+
}>>;
|
|
16
|
+
}>;
|
|
17
|
+
}>, Schema.Struct<{
|
|
18
|
+
readonly type: Schema.Literal<"turn_context">;
|
|
19
|
+
readonly timestamp: Schema.String;
|
|
20
|
+
readonly payload: Schema.Struct<{
|
|
21
|
+
readonly cwd: Schema.String;
|
|
22
|
+
}>;
|
|
23
|
+
}>, Schema.Struct<{
|
|
24
|
+
readonly type: Schema.Literal<"event_msg">;
|
|
25
|
+
readonly timestamp: Schema.String;
|
|
26
|
+
readonly payload: Schema.Union<readonly [Schema.Struct<{
|
|
27
|
+
readonly type: Schema.Literal<"user_message">;
|
|
28
|
+
readonly message: Schema.String;
|
|
29
|
+
}>, Schema.Struct<{
|
|
30
|
+
readonly type: Schema.Literal<"item_completed">;
|
|
31
|
+
readonly started_at_ms: Schema.optional<Schema.Number>;
|
|
32
|
+
readonly item: Schema.Struct<{
|
|
33
|
+
readonly type: Schema.Literal<"UserMessage">;
|
|
34
|
+
readonly id: Schema.optional<Schema.String>;
|
|
35
|
+
readonly content: Schema.$Array<Schema.Struct<{
|
|
36
|
+
readonly type: Schema.String;
|
|
37
|
+
readonly text: Schema.optional<Schema.String>;
|
|
38
|
+
}>>;
|
|
39
|
+
}>;
|
|
40
|
+
}>]>;
|
|
41
|
+
}>, Schema.Struct<{
|
|
42
|
+
readonly type: Schema.Literal<"response_item">;
|
|
43
|
+
readonly timestamp: Schema.String;
|
|
44
|
+
readonly payload: Schema.Struct<{
|
|
45
|
+
readonly type: Schema.Literal<"message">;
|
|
46
|
+
readonly role: Schema.Literal<"assistant">;
|
|
47
|
+
readonly content: Schema.$Array<Schema.Struct<{
|
|
48
|
+
readonly type: Schema.String;
|
|
49
|
+
readonly text: Schema.optional<Schema.String>;
|
|
50
|
+
}>>;
|
|
51
|
+
}>;
|
|
52
|
+
}>]>;
|
|
53
|
+
/** Discard tool payloads and malformed lines before retaining a rollout in memory. */
|
|
54
|
+
export declare const decodeCodexLine: (input: unknown, options?: import("effect/SchemaAST").ParseOptions) => import("effect/Option").Option<{
|
|
55
|
+
readonly type: "session_meta";
|
|
56
|
+
readonly payload: {
|
|
57
|
+
readonly id: string;
|
|
58
|
+
readonly cwd: string;
|
|
59
|
+
readonly source?: Schema.Json | undefined;
|
|
60
|
+
readonly git?: {
|
|
61
|
+
readonly branch?: string | undefined;
|
|
62
|
+
} | undefined;
|
|
63
|
+
};
|
|
64
|
+
} | {
|
|
65
|
+
readonly type: "turn_context";
|
|
66
|
+
readonly timestamp: string;
|
|
67
|
+
readonly payload: {
|
|
68
|
+
readonly cwd: string;
|
|
69
|
+
};
|
|
70
|
+
} | {
|
|
71
|
+
readonly type: "event_msg";
|
|
72
|
+
readonly timestamp: string;
|
|
73
|
+
readonly payload: {
|
|
74
|
+
readonly type: "user_message";
|
|
75
|
+
readonly message: string;
|
|
76
|
+
} | {
|
|
77
|
+
readonly type: "item_completed";
|
|
78
|
+
readonly started_at_ms?: number | undefined;
|
|
79
|
+
readonly item: {
|
|
80
|
+
readonly type: "UserMessage";
|
|
81
|
+
readonly id?: string | undefined;
|
|
82
|
+
readonly content: readonly {
|
|
83
|
+
readonly type: string;
|
|
84
|
+
readonly text?: string | undefined;
|
|
85
|
+
}[];
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
} | {
|
|
89
|
+
readonly type: "response_item";
|
|
90
|
+
readonly timestamp: string;
|
|
91
|
+
readonly payload: {
|
|
92
|
+
readonly type: "message";
|
|
93
|
+
readonly role: "assistant";
|
|
94
|
+
readonly content: readonly {
|
|
95
|
+
readonly type: string;
|
|
96
|
+
readonly text?: string | undefined;
|
|
97
|
+
}[];
|
|
98
|
+
};
|
|
99
|
+
}>;
|
|
100
|
+
/** The shared transcript segmenter handles time windows, branch changes and directory isolation. */
|
|
101
|
+
export declare function codexTranscriptLines(lines: Iterable<typeof CodexLine.Type>): Generator<{
|
|
102
|
+
type: string;
|
|
103
|
+
sessionId: string;
|
|
104
|
+
cwd: string;
|
|
105
|
+
gitBranch: string | null;
|
|
106
|
+
timestamp: string;
|
|
107
|
+
message: {
|
|
108
|
+
content: string;
|
|
109
|
+
};
|
|
110
|
+
}, void, unknown>;
|
|
111
|
+
export {};
|
|
112
|
+
//# sourceMappingURL=CodexTranscript.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodexTranscript.d.ts","sourceRoot":"","sources":["../../../src/services/CodexTranscript.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAoBvC,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAiBb,CAAA;AAEF,sFAAsF;AACtF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAA+D,CAAA;AAE3F,oGAAoG;AACpG,wBAAiB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,OAAO,SAAS,CAAC,IAAI,CAAC;;;;;;;QAmBsB,OAAO;;kBAyBxG"}
|