agent_sessions 0.3.0 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +71 -3
- data/doc/Agent/Sessions/Adapters/Amp.md +91 -0
- data/doc/Agent/Sessions/Adapters/Base.md +198 -0
- data/doc/Agent/Sessions/Adapters/Claude.md +63 -0
- data/doc/Agent/Sessions/Adapters/Codex.md +79 -0
- data/doc/Agent/Sessions/Adapters/Copilot.md +38 -0
- data/doc/Agent/Sessions/Adapters/Cursor.md +54 -0
- data/doc/Agent/Sessions/Adapters/CursorIde.md +49 -0
- data/doc/Agent/Sessions/Adapters/Enumeration.md +135 -0
- data/doc/Agent/Sessions/Adapters/Gemini.md +67 -0
- data/doc/Agent/Sessions/Adapters/Grok.md +64 -0
- data/doc/Agent/Sessions/Adapters/Opencode.md +93 -0
- data/doc/Agent/Sessions/Adapters/Pi.md +137 -0
- data/doc/Agent/Sessions/Adapters/Qwen.md +32 -0
- data/doc/Agent/Sessions/Adapters.md +5 -0
- data/doc/Agent/Sessions/Audit/Finding.md +27 -0
- data/doc/Agent/Sessions/Audit.md +21 -0
- data/doc/Agent/Sessions/CLI.md +36 -0
- data/doc/Agent/Sessions/Check.md +27 -0
- data/doc/Agent/Sessions/Compaction.md +23 -0
- data/doc/Agent/Sessions/EnvOverride.md +19 -0
- data/doc/Agent/Sessions/Error.md +6 -0
- data/doc/Agent/Sessions/HomeExpansion.md +11 -0
- data/doc/Agent/Sessions/Location.md +60 -0
- data/doc/Agent/Sessions/Message.md +59 -0
- data/doc/Agent/Sessions/MissingDependency.md +6 -0
- data/doc/Agent/Sessions/Node.md +24 -0
- data/doc/Agent/Sessions/Part.md +41 -0
- data/doc/Agent/Sessions/Readers/Amp.md +41 -0
- data/doc/Agent/Sessions/Readers/Base.md +91 -0
- data/doc/Agent/Sessions/Readers/Claude.md +77 -0
- data/doc/Agent/Sessions/Readers/Codex.md +81 -0
- data/doc/Agent/Sessions/Readers/Copilot.md +31 -0
- data/doc/Agent/Sessions/Readers/Gemini.md +38 -0
- data/doc/Agent/Sessions/Readers/Grok.md +45 -0
- data/doc/Agent/Sessions/Readers/Opencode.md +37 -0
- data/doc/Agent/Sessions/Readers/Pi.md +38 -0
- data/doc/Agent/Sessions/Readers/Qwen.md +30 -0
- data/doc/Agent/Sessions/Readers.md +5 -0
- data/doc/Agent/Sessions/Session.md +73 -0
- data/doc/Agent/Sessions/Sqlite.md +43 -0
- data/doc/Agent/Sessions/Store.md +57 -0
- data/doc/Agent/Sessions/UnknownAgent.md +6 -0
- data/doc/Agent/Sessions/UnreadableStore.md +6 -0
- data/doc/Agent/Sessions/UnsupportedFormat.md +6 -0
- data/doc/Agent/Sessions/Usage.md +56 -0
- data/doc/Agent/Sessions.md +177 -0
- data/doc/Agent.md +5 -0
- data/doc/CHANGELOG.md +69 -0
- data/doc/README.md +162 -0
- data/doc/index.csv +316 -0
- data/exe/agent-sessions +0 -2
- data/lib/agent/sessions/adapters/cursor.rb +3 -3
- data/lib/agent/sessions/cli.rb +2 -2
- data/lib/agent/sessions/message.rb +1 -2
- data/lib/agent/sessions/part.rb +1 -2
- data/lib/agent/sessions/version.rb +1 -1
- data/llm.txt +177 -0
- metadata +54 -2
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Class Agent::Sessions::Audit::Finding <a id="class-Agent-Sessions-Audit-Finding"></a>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Inherits** | Data |
|
|
6
|
+
| **Defined in** | lib/agent/sessions/audit.rb |
|
|
7
|
+
|
|
8
|
+
## Attributes
|
|
9
|
+
### `agent` [R] <a id="attribute-i-agent"></a> <a id="agent-instance_method"></a>
|
|
10
|
+
Returns the value of attribute agent
|
|
11
|
+
- **@return** [Object] the current value of agent
|
|
12
|
+
|
|
13
|
+
### `bytes` [R] <a id="attribute-i-bytes"></a> <a id="bytes-instance_method"></a>
|
|
14
|
+
Returns the value of attribute bytes
|
|
15
|
+
- **@return** [Object] the current value of bytes
|
|
16
|
+
|
|
17
|
+
### `kind` [R] <a id="attribute-i-kind"></a> <a id="kind-instance_method"></a>
|
|
18
|
+
Returns the value of attribute kind
|
|
19
|
+
- **@return** [Object] the current value of kind
|
|
20
|
+
|
|
21
|
+
### `path` [R] <a id="attribute-i-path"></a> <a id="path-instance_method"></a>
|
|
22
|
+
Returns the value of attribute path
|
|
23
|
+
- **@return** [Object] the current value of path
|
|
24
|
+
|
|
25
|
+
### `synced_to` [R] <a id="attribute-i-synced_to"></a> <a id="synced_to-instance_method"></a>
|
|
26
|
+
Returns the value of attribute synced_to
|
|
27
|
+
- **@return** [Object] the current value of synced_to
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Class Agent::Sessions::Audit <a id="class-Agent-Sessions-Audit"></a>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Inherits** | Object |
|
|
6
|
+
| **Includes** | [Agent::Sessions::HomeExpansion](HomeExpansion.md) |
|
|
7
|
+
| **Defined in** | lib/agent/sessions/audit.rb |
|
|
8
|
+
|
|
9
|
+
Answers: are these plaintext transcripts inside anything that syncs? Needs
|
|
10
|
+
only Layer 1. Time Machine exclusion status is a planned addition.
|
|
11
|
+
|
|
12
|
+
## Constants
|
|
13
|
+
### `SYNC_ROOTS` <a id="constant-SYNC_ROOTS"></a> <a id="SYNC_ROOTS-constant"></a>
|
|
14
|
+
Not documented.
|
|
15
|
+
|
|
16
|
+
## Public Instance Methods
|
|
17
|
+
### `initialize(stores, env: ENV)` <a id="method-i-initialize"></a> <a id="initialize-instance_method"></a>
|
|
18
|
+
- **@return** [Audit] a new instance of Audit
|
|
19
|
+
|
|
20
|
+
### `report()` <a id="method-i-report"></a> <a id="report-instance_method"></a>
|
|
21
|
+
Not documented.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Class Agent::Sessions::CLI <a id="class-Agent-Sessions-CLI"></a>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Inherits** | Object |
|
|
6
|
+
| **Defined in** | lib/agent/sessions/cli.rb |
|
|
7
|
+
|
|
8
|
+
## Constants
|
|
9
|
+
### `GROUP_COLUMN_MAX` <a id="constant-GROUP_COLUMN_MAX"></a> <a id="GROUP_COLUMN_MAX-constant"></a>
|
|
10
|
+
Group names in `du --by project` are the same shape of problem one cap wider:
|
|
11
|
+
a real project path on this machine ran 169 characters, wrapping every row
|
|
12
|
+
across three lines on an 80-column terminal (list's own id column tops out at
|
|
13
|
+
72 total). Wider than ID_COLUMN_MAX because a path's head (which user, which
|
|
14
|
+
drive) and tail (the actual project directory) are both worth keeping, and
|
|
15
|
+
both need more room than a bare uuid does.
|
|
16
|
+
|
|
17
|
+
### `ID_COLUMN_MAX` <a id="constant-ID_COLUMN_MAX"></a> <a id="ID_COLUMN_MAX-constant"></a>
|
|
18
|
+
Cap the id column. Cursor's ids are two nested uuids joined by "/" (36 + 1 +
|
|
19
|
+
36 = 73 chars) where every other agent needs a bare uuid (36) or less, so one
|
|
20
|
+
Cursor row makes the global id_width 73 — padding every other row with ~35
|
|
21
|
+
spaces and pushing the line past 100 chars, which wraps on an 80-column
|
|
22
|
+
terminal. Elide the middle and keep both ends, since the ends are what a human
|
|
23
|
+
matches against a directory name.
|
|
24
|
+
|
|
25
|
+
### `SINCE_UNITS` <a id="constant-SINCE_UNITS"></a> <a id="SINCE_UNITS-constant"></a>
|
|
26
|
+
Not documented.
|
|
27
|
+
|
|
28
|
+
### `STATUS_MARKS` <a id="constant-STATUS_MARKS"></a> <a id="STATUS_MARKS-constant"></a>
|
|
29
|
+
Not documented.
|
|
30
|
+
|
|
31
|
+
## Public Instance Methods
|
|
32
|
+
### `initialize(argv, env: ENV, stdout: $stdout, stderr: $stderr, now: Time.now)` <a id="method-i-initialize"></a> <a id="initialize-instance_method"></a>
|
|
33
|
+
- **@return** [CLI] a new instance of CLI
|
|
34
|
+
|
|
35
|
+
### `run()` <a id="method-i-run"></a> <a id="run-instance_method"></a>
|
|
36
|
+
Not documented.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Class Agent::Sessions::Check <a id="class-Agent-Sessions-Check"></a>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Inherits** | Data |
|
|
6
|
+
| **Defined in** | lib/agent/sessions/check.rb |
|
|
7
|
+
|
|
8
|
+
## Attributes
|
|
9
|
+
### `agent` [R] <a id="attribute-i-agent"></a> <a id="agent-instance_method"></a>
|
|
10
|
+
Returns the value of attribute agent
|
|
11
|
+
- **@return** [Object] the current value of agent
|
|
12
|
+
|
|
13
|
+
### `claim` [R] <a id="attribute-i-claim"></a> <a id="claim-instance_method"></a>
|
|
14
|
+
Returns the value of attribute claim
|
|
15
|
+
- **@return** [Object] the current value of claim
|
|
16
|
+
|
|
17
|
+
### `detail` [R] <a id="attribute-i-detail"></a> <a id="detail-instance_method"></a>
|
|
18
|
+
Returns the value of attribute detail
|
|
19
|
+
- **@return** [Object] the current value of detail
|
|
20
|
+
|
|
21
|
+
### `status` [R] <a id="attribute-i-status"></a> <a id="status-instance_method"></a>
|
|
22
|
+
Returns the value of attribute status
|
|
23
|
+
- **@return** [Object] the current value of status
|
|
24
|
+
|
|
25
|
+
## Public Instance Methods
|
|
26
|
+
### `pass?()` <a id="method-i-pass-3F"></a> <a id="pass?-instance_method"></a>
|
|
27
|
+
- **@return** [Boolean]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Class Agent::Sessions::Compaction <a id="class-Agent-Sessions-Compaction"></a>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Inherits** | Data |
|
|
6
|
+
| **Defined in** | lib/agent/sessions/compaction.rb |
|
|
7
|
+
|
|
8
|
+
A point where the agent replaced earlier turns with a summary. Not a message:
|
|
9
|
+
its own payload restates turns already yielded, so anyone counting would count
|
|
10
|
+
them twice. replaced_count is how many turns it stood in for.
|
|
11
|
+
|
|
12
|
+
## Attributes
|
|
13
|
+
### `at` [R] <a id="attribute-i-at"></a> <a id="at-instance_method"></a>
|
|
14
|
+
Returns the value of attribute at
|
|
15
|
+
- **@return** [Object] the current value of at
|
|
16
|
+
|
|
17
|
+
### `raw` [R] <a id="attribute-i-raw"></a> <a id="raw-instance_method"></a>
|
|
18
|
+
Returns the value of attribute raw
|
|
19
|
+
- **@return** [Object] the current value of raw
|
|
20
|
+
|
|
21
|
+
### `replaced_count` [R] <a id="attribute-i-replaced_count"></a> <a id="replaced_count-instance_method"></a>
|
|
22
|
+
Returns the value of attribute replaced_count
|
|
23
|
+
- **@return** [Object] the current value of replaced_count
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Class Agent::Sessions::EnvOverride <a id="class-Agent-Sessions-EnvOverride"></a>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Inherits** | Data |
|
|
6
|
+
| **Defined in** | lib/agent/sessions/env_override.rb |
|
|
7
|
+
|
|
8
|
+
## Attributes
|
|
9
|
+
### `name` [R] <a id="attribute-i-name"></a> <a id="name-instance_method"></a>
|
|
10
|
+
Returns the value of attribute name
|
|
11
|
+
- **@return** [Object] the current value of name
|
|
12
|
+
|
|
13
|
+
### `value` [R] <a id="attribute-i-value"></a> <a id="value-instance_method"></a>
|
|
14
|
+
Returns the value of attribute value
|
|
15
|
+
- **@return** [Object] the current value of value
|
|
16
|
+
|
|
17
|
+
## Public Instance Methods
|
|
18
|
+
### `active?()` <a id="method-i-active-3F"></a> <a id="active?-instance_method"></a>
|
|
19
|
+
- **@return** [Boolean]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Module Agent::Sessions::HomeExpansion <a id="module-Agent-Sessions-HomeExpansion"></a>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Defined in** | lib/agent/sessions/home_expansion.rb |
|
|
6
|
+
|
|
7
|
+
Shared path expansion for Adapters::Base and Audit. Expands "~" against the
|
|
8
|
+
injected env so callers can resolve paths for a machine that is not their own;
|
|
9
|
+
joins relative paths (including "~user"-looking strings that are not a real
|
|
10
|
+
shell lookup here) under that same home; and treats an explicitly empty HOME
|
|
11
|
+
the same as an absent one.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Class Agent::Sessions::Location <a id="class-Agent-Sessions-Location"></a>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Inherits** | Data |
|
|
6
|
+
| **Defined in** | lib/agent/sessions/location.rb |
|
|
7
|
+
|
|
8
|
+
One resolved layer of an agent's store.
|
|
9
|
+
|
|
10
|
+
A location is one of three shapes, and `files` answers each differently:
|
|
11
|
+
|
|
12
|
+
glob a directory plus a pattern -> the pattern's matches
|
|
13
|
+
single_file one file (a `path:` store) -> itself, if it is there
|
|
14
|
+
directory a directory with no known shape -> nothing, and enumerable? is false
|
|
15
|
+
|
|
16
|
+
The third shape is a store whose internal layout this gem has not learned yet
|
|
17
|
+
(opencode's pre-1.2.0 storage/ tree, Cursor's acp-sessions/). It returns [] so
|
|
18
|
+
a caller sweeping every layer does not blow up, and answers enumerable? false
|
|
19
|
+
so that caller can tell "nothing here to enumerate" apart from "enumerated,
|
|
20
|
+
found none".
|
|
21
|
+
|
|
22
|
+
single_file comes from the adapter's store DSL: <code>path:</code> means one
|
|
23
|
+
file, <code>dir:</code> means a directory. Resolution used to discard that
|
|
24
|
+
distinction, which made a Layer 2 enumerator written as
|
|
25
|
+
layers.flat_map(&:files) silently skip history.jsonl, session_index.jsonl and
|
|
26
|
+
secrets.json — a missing-session bug, not a visible error.
|
|
27
|
+
|
|
28
|
+
## Attributes
|
|
29
|
+
### `format` [R] <a id="attribute-i-format"></a> <a id="format-instance_method"></a>
|
|
30
|
+
Returns the value of attribute format
|
|
31
|
+
- **@return** [Object] the current value of format
|
|
32
|
+
|
|
33
|
+
### `glob` [R] <a id="attribute-i-glob"></a> <a id="glob-instance_method"></a>
|
|
34
|
+
Returns the value of attribute glob
|
|
35
|
+
- **@return** [Object] the current value of glob
|
|
36
|
+
|
|
37
|
+
### `kind` [R] <a id="attribute-i-kind"></a> <a id="kind-instance_method"></a>
|
|
38
|
+
Returns the value of attribute kind
|
|
39
|
+
- **@return** [Object] the current value of kind
|
|
40
|
+
|
|
41
|
+
### `path` [R] <a id="attribute-i-path"></a> <a id="path-instance_method"></a>
|
|
42
|
+
Returns the value of attribute path
|
|
43
|
+
- **@return** [Object] the current value of path
|
|
44
|
+
|
|
45
|
+
### `single_file` [R] <a id="attribute-i-single_file"></a> <a id="single_file-instance_method"></a>
|
|
46
|
+
Returns the value of attribute single_file
|
|
47
|
+
- **@return** [Object] the current value of single_file
|
|
48
|
+
|
|
49
|
+
## Public Instance Methods
|
|
50
|
+
### `enumerable?()` <a id="method-i-enumerable-3F"></a> <a id="enumerable?-instance_method"></a>
|
|
51
|
+
- **@return** [Boolean]
|
|
52
|
+
|
|
53
|
+
### `exists?()` <a id="method-i-exists-3F"></a> <a id="exists?-instance_method"></a>
|
|
54
|
+
- **@return** [Boolean]
|
|
55
|
+
|
|
56
|
+
### `files()` <a id="method-i-files"></a> <a id="files-instance_method"></a>
|
|
57
|
+
Not documented.
|
|
58
|
+
|
|
59
|
+
### `initialize(kind:, path:, format:, glob: nil, single_file: false)` <a id="method-i-initialize"></a> <a id="initialize-instance_method"></a>
|
|
60
|
+
- **@return** [Location] a new instance of Location
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Class Agent::Sessions::Message <a id="class-Agent-Sessions-Message"></a>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Inherits** | Data |
|
|
6
|
+
| **Defined in** | lib/agent/sessions/message.rb |
|
|
7
|
+
|
|
8
|
+
One turn. `role` is normalized to :user, :assistant, :system or :tool, with
|
|
9
|
+
:unknown for a role the adapter did not recognize — the four the spec names
|
|
10
|
+
were written before any real corpus was read, and Codex promptly said
|
|
11
|
+
"developer".
|
|
12
|
+
|
|
13
|
+
raw is never dropped (Layer 3 rule 1): when this normalization is wrong or
|
|
14
|
+
incomplete, a caller escapes the abstraction instead of forking the gem.
|
|
15
|
+
|
|
16
|
+
usage and model are nil wherever the format does not put them on the message
|
|
17
|
+
itself — Codex records tokens in separate event records and the model in its
|
|
18
|
+
session header, so its messages carry neither; the reader's session-level
|
|
19
|
+
`usage` is where those formats answer. A nil here means "not recorded on this
|
|
20
|
+
message", never "zero tokens".
|
|
21
|
+
|
|
22
|
+
## Constants
|
|
23
|
+
### `ROLES` <a id="constant-ROLES"></a> <a id="ROLES-constant"></a>
|
|
24
|
+
Not documented.
|
|
25
|
+
|
|
26
|
+
## Attributes
|
|
27
|
+
### `at` [R] <a id="attribute-i-at"></a> <a id="at-instance_method"></a>
|
|
28
|
+
Returns the value of attribute at
|
|
29
|
+
- **@return** [Object] the current value of at
|
|
30
|
+
|
|
31
|
+
### `model` [R] <a id="attribute-i-model"></a> <a id="model-instance_method"></a>
|
|
32
|
+
Returns the value of attribute model
|
|
33
|
+
- **@return** [Object] the current value of model
|
|
34
|
+
|
|
35
|
+
### `parts` [R] <a id="attribute-i-parts"></a> <a id="parts-instance_method"></a>
|
|
36
|
+
Returns the value of attribute parts
|
|
37
|
+
- **@return** [Object] the current value of parts
|
|
38
|
+
|
|
39
|
+
### `raw` [R] <a id="attribute-i-raw"></a> <a id="raw-instance_method"></a>
|
|
40
|
+
Returns the value of attribute raw
|
|
41
|
+
- **@return** [Object] the current value of raw
|
|
42
|
+
|
|
43
|
+
### `role` [R] <a id="attribute-i-role"></a> <a id="role-instance_method"></a>
|
|
44
|
+
Returns the value of attribute role
|
|
45
|
+
- **@return** [Object] the current value of role
|
|
46
|
+
|
|
47
|
+
### `usage` [R] <a id="attribute-i-usage"></a> <a id="usage-instance_method"></a>
|
|
48
|
+
Returns the value of attribute usage
|
|
49
|
+
- **@return** [Object] the current value of usage
|
|
50
|
+
|
|
51
|
+
## Public Instance Methods
|
|
52
|
+
### `initialize(role:, at:, parts:, raw:, usage: nil, model: nil)` <a id="method-i-initialize"></a> <a id="initialize-instance_method"></a>
|
|
53
|
+
- **@raise** [ArgumentError]
|
|
54
|
+
- **@return** [Message] a new instance of Message
|
|
55
|
+
|
|
56
|
+
### `text()` <a id="method-i-text"></a> <a id="text-instance_method"></a>
|
|
57
|
+
Concatenated :text parts, as the design doc specifies — no separator inserted,
|
|
58
|
+
because a separator is a formatting decision this layer has no business
|
|
59
|
+
making. A caller that needs the boundaries has `parts`.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Class Agent::Sessions::Node <a id="class-Agent-Sessions-Node"></a>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Inherits** | Data |
|
|
6
|
+
| **Defined in** | lib/agent/sessions/node.rb |
|
|
7
|
+
|
|
8
|
+
One message in a branching conversation, with the messages that follow it.
|
|
9
|
+
Agents that let a turn be edited and re-run record two children under one
|
|
10
|
+
parent: 380 such branch points sit across 85 of 151 real Claude transcripts,
|
|
11
|
+
so a caller reading `messages` in file order is reading two alternative
|
|
12
|
+
histories interleaved without being told.
|
|
13
|
+
|
|
14
|
+
children is a plain Array and the Node is frozen, so the shape is settled
|
|
15
|
+
before anyone sees it.
|
|
16
|
+
|
|
17
|
+
## Attributes
|
|
18
|
+
### `children` [R] <a id="attribute-i-children"></a> <a id="children-instance_method"></a>
|
|
19
|
+
Returns the value of attribute children
|
|
20
|
+
- **@return** [Object] the current value of children
|
|
21
|
+
|
|
22
|
+
### `message` [R] <a id="attribute-i-message"></a> <a id="message-instance_method"></a>
|
|
23
|
+
Returns the value of attribute message
|
|
24
|
+
- **@return** [Object] the current value of message
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Class Agent::Sessions::Part <a id="class-Agent-Sessions-Part"></a>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Inherits** | Data |
|
|
6
|
+
| **Defined in** | lib/agent/sessions/part.rb |
|
|
7
|
+
|
|
8
|
+
One piece of a message. `type` is the normalized vocabulary (design doc §5);
|
|
9
|
+
everything an agent said that this gem could not classify arrives as :unknown
|
|
10
|
+
rather than as an exception, and the message's `raw` still holds it.
|
|
11
|
+
|
|
12
|
+
text carries the readable content for :text, :thinking and :tool_result. name
|
|
13
|
+
and call_id are tool plumbing, nil elsewhere. An :image part has neither — its
|
|
14
|
+
URL or payload stays in raw, because normalizing an image would mean deciding
|
|
15
|
+
whether to load it, and reading is stat-cheap by design.
|
|
16
|
+
|
|
17
|
+
## Constants
|
|
18
|
+
### `TYPES` <a id="constant-TYPES"></a> <a id="TYPES-constant"></a>
|
|
19
|
+
Not documented.
|
|
20
|
+
|
|
21
|
+
## Attributes
|
|
22
|
+
### `call_id` [R] <a id="attribute-i-call_id"></a> <a id="call_id-instance_method"></a>
|
|
23
|
+
Returns the value of attribute call_id
|
|
24
|
+
- **@return** [Object] the current value of call_id
|
|
25
|
+
|
|
26
|
+
### `name` [R] <a id="attribute-i-name"></a> <a id="name-instance_method"></a>
|
|
27
|
+
Returns the value of attribute name
|
|
28
|
+
- **@return** [Object] the current value of name
|
|
29
|
+
|
|
30
|
+
### `text` [R] <a id="attribute-i-text"></a> <a id="text-instance_method"></a>
|
|
31
|
+
Returns the value of attribute text
|
|
32
|
+
- **@return** [Object] the current value of text
|
|
33
|
+
|
|
34
|
+
### `type` [R] <a id="attribute-i-type"></a> <a id="type-instance_method"></a>
|
|
35
|
+
Returns the value of attribute type
|
|
36
|
+
- **@return** [Object] the current value of type
|
|
37
|
+
|
|
38
|
+
## Public Instance Methods
|
|
39
|
+
### `initialize(type:, text: nil, name: nil, call_id: nil)` <a id="method-i-initialize"></a> <a id="initialize-instance_method"></a>
|
|
40
|
+
- **@raise** [ArgumentError]
|
|
41
|
+
- **@return** [Part] a new instance of Part
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Class Agent::Sessions::Readers::Amp <a id="class-Agent-Sessions-Readers-Amp"></a>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Inherits** | [Agent::Sessions::Readers::Base](Base.md) |
|
|
6
|
+
| **Defined in** | lib/agent/sessions/readers/amp.rb |
|
|
7
|
+
|
|
8
|
+
Amp threads. Written against the one real thread available (2026-08-14): 24
|
|
9
|
+
messages, content parts tool_use 14, tool_result 14, text 2, thinking 1. One
|
|
10
|
+
thread is thin evidence beside Codex's 415 files, and this reader says so
|
|
11
|
+
through partial? rather than pretending otherwise.
|
|
12
|
+
|
|
13
|
+
Two things make Amp unlike the JSONL readers:
|
|
14
|
+
|
|
15
|
+
A thread is ONE JSON document, so it cannot be streamed a record at a time.
|
|
16
|
+
Reading any of it means holding all of it, which is the gem's one unbounded
|
|
17
|
+
read (0.2 follow-up 8). each_record below is where that bound finally lives.
|
|
18
|
+
|
|
19
|
+
And its tool results are spelled its own way — toolUseID rather than
|
|
20
|
+
tool_use_id, the payload under run.result rather than content. A mapper copied
|
|
21
|
+
from Claude's would produce empty tool results and no warning, which is why
|
|
22
|
+
each reader maps its own agent rather than sharing one.
|
|
23
|
+
|
|
24
|
+
## Constants
|
|
25
|
+
### `CONTENT_PARTS` <a id="constant-CONTENT_PARTS"></a> <a id="CONTENT_PARTS-constant"></a>
|
|
26
|
+
Not documented.
|
|
27
|
+
|
|
28
|
+
### `MAX_DOCUMENT_BYTES` <a id="constant-MAX_DOCUMENT_BYTES"></a> <a id="MAX_DOCUMENT_BYTES-constant"></a>
|
|
29
|
+
150x the observed thread. A cap has to exist because nothing about a thread
|
|
30
|
+
file announces its size before it is opened, and JSON.parse of a 200 MB
|
|
31
|
+
document costs several times that in live objects. Refused and reported beats
|
|
32
|
+
NoMemoryError, and beats silence either way.
|
|
33
|
+
|
|
34
|
+
### `ROLES` <a id="constant-ROLES"></a> <a id="ROLES-constant"></a>
|
|
35
|
+
Not documented.
|
|
36
|
+
|
|
37
|
+
## Public Instance Methods
|
|
38
|
+
### `partial?()` <a id="method-i-partial-3F"></a> <a id="partial?-instance_method"></a>
|
|
39
|
+
The server holds the canonical copy; a local thread may be a mirror of part of
|
|
40
|
+
the conversation. The adapter carries the same warning.
|
|
41
|
+
- **@return** [Boolean]
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Class Agent::Sessions::Readers::Base <a id="class-Agent-Sessions-Readers-Base"></a>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Inherits** | Object |
|
|
6
|
+
| **Defined in** | lib/agent/sessions/readers/base.rb |
|
|
7
|
+
|
|
8
|
+
Layer 3: turning one session file into messages. Subclasses supply the
|
|
9
|
+
mapping; everything about *how the file is read* lives here, because the three
|
|
10
|
+
rules that make this layer survivable (design doc §5) are properties of the
|
|
11
|
+
reading, not of any one agent's format:
|
|
12
|
+
|
|
13
|
+
1. raw is never dropped.
|
|
14
|
+
2. Unknown records become :unknown parts and warnings, never exceptions.
|
|
15
|
+
3. Reading streams. No code path may assume a file fits in memory.
|
|
16
|
+
|
|
17
|
+
Rule 3 is why this does not use File.foreach without a chunk size. A truncated
|
|
18
|
+
log can hold no newline at all, and "read one line" would then mean "read 2.6
|
|
19
|
+
GB into a String" — the file the article that started this gem found on a real
|
|
20
|
+
machine.
|
|
21
|
+
|
|
22
|
+
## Constants
|
|
23
|
+
### `MAX_RECORD_BYTES` <a id="constant-MAX_RECORD_BYTES"></a> <a id="MAX_RECORD_BYTES-constant"></a>
|
|
24
|
+
Chunk size, and so the largest record that can be read whole. Measured against
|
|
25
|
+
415 real Codex rollout files (128,987 records, 2026-08-12): 14 records exceed
|
|
26
|
+
1 MB and the largest is 2.41 MB, so Layer 2's MAX_LINE_BYTES of 1 MB would
|
|
27
|
+
silently drop real messages. 8 MB is ~3.3x the observed maximum. A record
|
|
28
|
+
beyond it is reported, never dropped in silence, because a missing message is
|
|
29
|
+
this gem's worst failure mode.
|
|
30
|
+
|
|
31
|
+
## Attributes
|
|
32
|
+
### `session` [R] <a id="attribute-i-session"></a> <a id="session-instance_method"></a>
|
|
33
|
+
Returns the value of attribute session.
|
|
34
|
+
|
|
35
|
+
## Public Instance Methods
|
|
36
|
+
### `branching?()` <a id="method-i-branching-3F"></a> <a id="branching?-instance_method"></a>
|
|
37
|
+
Whether this agent records which turn each turn followed. False here: most
|
|
38
|
+
stores are an append-only list and a tree would have to be invented.
|
|
39
|
+
- **@return** [Boolean]
|
|
40
|
+
|
|
41
|
+
### `compactions()` <a id="method-i-compactions"></a> <a id="compactions-instance_method"></a>
|
|
42
|
+
Boundaries where the agent replaced earlier turns with a summary. Its own
|
|
43
|
+
pass: a caller asking only for compactions should not have to materialize
|
|
44
|
+
every message to get them.
|
|
45
|
+
|
|
46
|
+
### `each_message()` <a id="method-i-each_message"></a> <a id="each_message-instance_method"></a>
|
|
47
|
+
Streams. Yields each message as it is parsed; a caller that breaks after one
|
|
48
|
+
has read one record, not the file.
|
|
49
|
+
|
|
50
|
+
### `fidelity()` <a id="method-i-fidelity"></a> <a id="fidelity-instance_method"></a>
|
|
51
|
+
Not documented.
|
|
52
|
+
|
|
53
|
+
### `initialize(session, include_events: false)` <a id="method-i-initialize"></a> <a id="initialize-instance_method"></a>
|
|
54
|
+
- **@return** [Base] a new instance of Base
|
|
55
|
+
|
|
56
|
+
### `messages()` <a id="method-i-messages"></a> <a id="messages-instance_method"></a>
|
|
57
|
+
Eager, for sessions small enough to hold. The design doc offers both and names
|
|
58
|
+
this the convenience: `messages` is what a script wants, and `each_message` is
|
|
59
|
+
what a 2.6 GB file requires.
|
|
60
|
+
|
|
61
|
+
### `partial?()` <a id="method-i-partial-3F"></a> <a id="partial?-instance_method"></a>
|
|
62
|
+
True where the local file is not the whole story — Amp, whose server holds the
|
|
63
|
+
canonical copy. Overridden there, false everywhere else.
|
|
64
|
+
- **@return** [Boolean]
|
|
65
|
+
|
|
66
|
+
### `tree()` <a id="method-i-tree"></a> <a id="tree-instance_method"></a>
|
|
67
|
+
The conversation as roots and their continuations, for an agent that records
|
|
68
|
+
parent links. Unlike every other method here this cannot stream — a tree is
|
|
69
|
+
not knowable until the last record is read — so it holds one session's
|
|
70
|
+
messages at once and says so rather than pretending otherwise.
|
|
71
|
+
|
|
72
|
+
Raises rather than returning an empty list or nil for a store with no parent
|
|
73
|
+
links, for the reason Agent::Sessions.read raises: "this format does not
|
|
74
|
+
record that" must never read as "this session has none".
|
|
75
|
+
|
|
76
|
+
### `usage()` <a id="method-i-usage"></a> <a id="usage-instance_method"></a>
|
|
77
|
+
This session's token totals as a Usage, or nil where the format does not
|
|
78
|
+
record them (Amp) or this reader has not learned where they live. nil, not an
|
|
79
|
+
empty Usage: "this store does not say" must never read as "this session cost
|
|
80
|
+
nothing" — the same rule tree() enforces by raising.
|
|
81
|
+
|
|
82
|
+
Each reader that overrides this also decides its own summation rule, because
|
|
83
|
+
that rule is format knowledge: Claude repeats one API response's usage across
|
|
84
|
+
several records (94 of 124 message ids in one real transcript), Codex writes a
|
|
85
|
+
running total where only the last record counts. A base-class sum would get
|
|
86
|
+
both wrong.
|
|
87
|
+
|
|
88
|
+
### `warnings()` <a id="method-i-warnings"></a> <a id="warnings-instance_method"></a>
|
|
89
|
+
Populated as records are read, so this answers for whatever has been consumed
|
|
90
|
+
so far. uniq because a second pass over the same file would otherwise repeat
|
|
91
|
+
every warning it already reported.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Class Agent::Sessions::Readers::Claude <a id="class-Agent-Sessions-Readers-Claude"></a>
|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| **Inherits** | [Agent::Sessions::Readers::Base](Base.md) |
|
|
6
|
+
| **Defined in** | lib/agent/sessions/readers/claude.rb |
|
|
7
|
+
|
|
8
|
+
Claude Code transcripts. Written against 142 real transcripts, 29,688 records,
|
|
9
|
+
inventoried 2026-08-12.
|
|
10
|
+
|
|
11
|
+
The content vocabulary is a straight match for this gem's: text, thinking,
|
|
12
|
+
tool_use, tool_result and image are exactly the five part types the design doc
|
|
13
|
+
names, so nothing here has to invent a mapping. What Claude adds is everything
|
|
14
|
+
**around** the conversation — a third of all records are session state, and
|
|
15
|
+
two more kinds carry context the model saw without being a turn anyone took.
|
|
16
|
+
|
|
17
|
+
## Constants
|
|
18
|
+
### `CONTENT_PARTS` <a id="constant-CONTENT_PARTS"></a> <a id="CONTENT_PARTS-constant"></a>
|
|
19
|
+
Not documented.
|
|
20
|
+
|
|
21
|
+
### `EVENT_TYPES` <a id="constant-EVENT_TYPES"></a> <a id="EVENT_TYPES-constant"></a>
|
|
22
|
+
Context the model saw, but not a turn: `system` is turn_duration,
|
|
23
|
+
stop_hook_summary, away_summary, local_command; `attachment` is hook output,
|
|
24
|
+
skill listings, task reminders, pasted files. Same judgement Codex's event_msg
|
|
25
|
+
gets — available on request, never on by default.
|
|
26
|
+
|
|
27
|
+
### `MAX_SPILL_BYTES` <a id="constant-MAX_SPILL_BYTES"></a> <a id="MAX_SPILL_BYTES-constant"></a>
|
|
28
|
+
A spilled file is read whole. The largest observed is well under this; the cap
|
|
29
|
+
exists because the pointer says nothing about the size.
|
|
30
|
+
|
|
31
|
+
### `NON_MESSAGE_TYPES` <a id="constant-NON_MESSAGE_TYPES"></a> <a id="NON_MESSAGE_TYPES-constant"></a>
|
|
32
|
+
State, not conversation, and together 11,000+ of the records written. Skipped
|
|
33
|
+
in silence: warning about a record deliberately classified would teach a
|
|
34
|
+
caller that warnings are noise.
|
|
35
|
+
|
|
36
|
+
atis-latch and bridge-session postdate the corpus above — found by running
|
|
37
|
+
this reader over a live 2026-08-24 transcript and reading its own warnings (23
|
|
38
|
+
and 17 records), the same way Codex's tool list grew. Both are session
|
|
39
|
+
plumbing: a latch marker, and the record tying a local transcript to its cloud
|
|
40
|
+
session id (bridgeSessionId, owner uuids). Neither is a turn anyone took.
|
|
41
|
+
|
|
42
|
+
### `SPILL` <a id="constant-SPILL"></a> <a id="SPILL-constant"></a>
|
|
43
|
+
How Claude Code points at output too large to inline. It is prose, not a
|
|
44
|
+
structured field — 24 real tool_result parts and 149 attachments carry this
|
|
45
|
+
sentence — so the path has to be matched out of the text.
|
|
46
|
+
|
|
47
|
+
## Public Instance Methods
|
|
48
|
+
### `branching?()` <a id="method-i-branching-3F"></a> <a id="branching?-instance_method"></a>
|
|
49
|
+
Every uuid-bearing record names the record it followed, and 380 branch points
|
|
50
|
+
sit across 85 of 151 real transcripts — a turn edited and re-run leaves two
|
|
51
|
+
children under one parent. Exactly one root per file and no orphaned parent
|
|
52
|
+
link was found in that corpus, so the links are trustworthy enough to build a
|
|
53
|
+
tree from.
|
|
54
|
+
- **@return** [Boolean]
|
|
55
|
+
|
|
56
|
+
### `initialize(session, resolve_spills: true, **rest)` <a id="method-i-initialize"></a> <a id="initialize-instance_method"></a>
|
|
57
|
+
- **@return** [Claude] a new instance of Claude
|
|
58
|
+
|
|
59
|
+
### `subagents()` <a id="method-i-subagents"></a> <a id="subagents-instance_method"></a>
|
|
60
|
+
The transcripts of agents this session spawned, as readers of their own.
|
|
61
|
+
Exposed rather than inlined, per design doc 8.1: a subagent's turns are not
|
|
62
|
+
the parent's turns, and merging them would break every count taken from this
|
|
63
|
+
reader. 124 of these sit beside real sessions on this machine.
|
|
64
|
+
|
|
65
|
+
isSidechain is false on all 22,072 records in the main transcripts, so there
|
|
66
|
+
is nothing to filter out there — the separation is already how Claude Code
|
|
67
|
+
writes them.
|
|
68
|
+
|
|
69
|
+
### `usage()` <a id="method-i-usage"></a> <a id="usage-instance_method"></a>
|
|
70
|
+
Session totals, summed over assistant records but deduplicated by message.id
|
|
71
|
+
first — and the dedup is most of the number. One API response streams into one
|
|
72
|
+
record PER CONTENT BLOCK, each carrying the same message.id and the same
|
|
73
|
+
usage: in one real transcript on this machine (2026-08-24), 260 assistant
|
|
74
|
+
records share 124 message ids, 94 of which repeat with byte-identical usage. A
|
|
75
|
+
naive sum reports roughly double what Anthropic billed. An id-less record (not
|
|
76
|
+
observed, but rule 2 says formats drift) is counted rather than dropped:
|
|
77
|
+
overcounting a novelty beats silently ignoring it.
|