@traice/codex-collector 0.1.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 +151 -0
- package/cli.mjs +26 -0
- package/collector.mjs +932 -0
- package/install.mjs +469 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Internal Spend Codex Collector
|
|
2
|
+
|
|
3
|
+
This installs a local bridge from Codex developer-agent usage into trAIce
|
|
4
|
+
Internal Spend.
|
|
5
|
+
|
|
6
|
+
Internal Spend is intentionally separate from product-runtime LLM attribution:
|
|
7
|
+
collector data goes to `/api/v1/internal-usage`, not `/api/v1/events`.
|
|
8
|
+
|
|
9
|
+
## What It Collects
|
|
10
|
+
|
|
11
|
+
- Codex token-count rows from `~/.codex/sessions/**/*.jsonl`
|
|
12
|
+
- Codex OTel `response.completed` token events from `127.0.0.1:4318/v1/logs`
|
|
13
|
+
- local install identity: employee email/name, team name, device principal
|
|
14
|
+
- Codex context metadata: repo/cwd, model, thread id, sandbox/approval mode
|
|
15
|
+
- optional monthly seat/subscription commitment, e.g. `--seat-monthly-usd 200`
|
|
16
|
+
|
|
17
|
+
Prompts are not sent. Codex OTel is configured with `log_user_prompt = false`.
|
|
18
|
+
|
|
19
|
+
## Install On This Device
|
|
20
|
+
|
|
21
|
+
Published install shape:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
read -rsp "trAIce API key: " TRAICE_API_KEY; echo
|
|
25
|
+
export TRAICE_API_KEY
|
|
26
|
+
npx @traice/codex-collector@latest install \
|
|
27
|
+
--server-url https://app.runtraice.com \
|
|
28
|
+
--employee-email you@company.com \
|
|
29
|
+
--employee-name "Your Name" \
|
|
30
|
+
--team-name Engineering \
|
|
31
|
+
--seat-monthly-usd 200
|
|
32
|
+
unset TRAICE_API_KEY
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Local repo development can still run:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
node tools/internal-spend-codex/install.mjs \
|
|
39
|
+
--employee-email you@company.com \
|
|
40
|
+
--employee-name "Your Name" \
|
|
41
|
+
--team-name Engineering \
|
|
42
|
+
--seat-monthly-usd 200
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The installer:
|
|
46
|
+
|
|
47
|
+
- creates or reuses the `internal-spend-poc` workspace in local dev
|
|
48
|
+
- enables the workspace `internalSpendEnabled` flag
|
|
49
|
+
- creates a real API key for `/api/v1/internal-usage`
|
|
50
|
+
- writes private collector config to `~/.traice/internal-spend-codex/install.json`
|
|
51
|
+
- appends an idempotent trAIce `[otel]` block to user-level
|
|
52
|
+
`~/.codex/config.toml`
|
|
53
|
+
|
|
54
|
+
Codex ignores telemetry settings in project `.codex/config.toml`, so the user
|
|
55
|
+
config patch is intentional.
|
|
56
|
+
|
|
57
|
+
## Start The Collector
|
|
58
|
+
|
|
59
|
+
Foreground:
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
npx @traice/codex-collector@latest collect
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Local repo development can use `node tools/internal-spend-codex/collector.mjs`.
|
|
66
|
+
|
|
67
|
+
macOS LaunchAgent:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
read -rsp "trAIce API key: " TRAICE_API_KEY; echo
|
|
71
|
+
export TRAICE_API_KEY
|
|
72
|
+
npx @traice/codex-collector@latest install \
|
|
73
|
+
--server-url https://app.runtraice.com \
|
|
74
|
+
--employee-email you@company.com \
|
|
75
|
+
--team-name Engineering \
|
|
76
|
+
--seat-monthly-usd 200 \
|
|
77
|
+
--launch-agent
|
|
78
|
+
unset TRAICE_API_KEY
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The collector listens on:
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
http://127.0.0.1:4318/v1/logs
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
and forwards normalized internal usage rows to:
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
http://127.0.0.1:3003/api/v1/internal-usage
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
View the module at:
|
|
94
|
+
|
|
95
|
+
```text
|
|
96
|
+
http://127.0.0.1:3003/dashboard?tab=internal
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Employee And Team Mapping
|
|
100
|
+
|
|
101
|
+
For this local collector, identity comes from install flags:
|
|
102
|
+
|
|
103
|
+
- `--employee-email`
|
|
104
|
+
- `--employee-name`
|
|
105
|
+
- `--team-name`
|
|
106
|
+
- `--source-principal`
|
|
107
|
+
- `--seat-monthly-usd`
|
|
108
|
+
|
|
109
|
+
If omitted, the installer falls back to global git identity and local OS user.
|
|
110
|
+
Future org-wide installs should feed the same fields from MDM/SSO/directory
|
|
111
|
+
data. CSV and vendor connectors should use the same `/api/v1/internal-usage`
|
|
112
|
+
contract and fill employee/team fields directly or via identity mapping.
|
|
113
|
+
|
|
114
|
+
The API key can be provided with `TRAICE_API_KEY`, `--api-key-stdin`, or
|
|
115
|
+
`--api-key`. Prefer `TRAICE_API_KEY` or `--api-key-stdin` for user installs so
|
|
116
|
+
keys do not end up in shell history.
|
|
117
|
+
|
|
118
|
+
Private config and collector state default to `~/.traice/internal-spend-codex`.
|
|
119
|
+
Use `--out /path/to/private-dir` only when an org installer manages that
|
|
120
|
+
directory and permissions explicitly.
|
|
121
|
+
|
|
122
|
+
`--seat-monthly-usd` records a monthly subscription commitment for the
|
|
123
|
+
employee/source pair. It is shown separately from per-request usage cost because
|
|
124
|
+
Codex token logs do not include provider invoice amounts.
|
|
125
|
+
|
|
126
|
+
## Current Open Codex Agents
|
|
127
|
+
|
|
128
|
+
Existing Codex processes usually will not reload new user-level OTel config in
|
|
129
|
+
place. To cover already-open agents, the collector tails
|
|
130
|
+
`~/.codex/sessions/**/*.jsonl` and ingests `token_count` events appended by
|
|
131
|
+
running Codex sessions.
|
|
132
|
+
|
|
133
|
+
New or restarted Codex agents use native OTel export through the installed
|
|
134
|
+
`[otel]` config. Already-open agents are covered by session JSONL token-count
|
|
135
|
+
tailing where those files are available.
|
|
136
|
+
|
|
137
|
+
## One-Shot Backfill
|
|
138
|
+
|
|
139
|
+
Run a single session-file scan without opening the OTel listener:
|
|
140
|
+
|
|
141
|
+
```sh
|
|
142
|
+
npx @traice/codex-collector@latest collect --once
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The collector keeps local dedupe state in:
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
~/.traice/internal-spend-codex/collector-state.json
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
so restarting it should not intentionally duplicate historical rows.
|
package/cli.mjs
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { dirname, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const dir = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const [command = 'collect', ...args] = process.argv.slice(2);
|
|
8
|
+
const script = command === 'install'
|
|
9
|
+
? 'install.mjs'
|
|
10
|
+
: command === 'collect' || command === 'collector'
|
|
11
|
+
? 'collector.mjs'
|
|
12
|
+
: null;
|
|
13
|
+
|
|
14
|
+
if (!script) {
|
|
15
|
+
console.error('Usage: traice-codex-collector <install|collect> [options]');
|
|
16
|
+
process.exit(2);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const result = spawnSync(process.execPath, [resolve(dir, script), ...args], {
|
|
20
|
+
stdio: 'inherit',
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
if (result.signal) {
|
|
24
|
+
process.kill(process.pid, result.signal);
|
|
25
|
+
}
|
|
26
|
+
process.exit(result.status ?? 1);
|