@oneciel-ai/ciel-runtime 0.2.22 → 0.2.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +108 -0
- package/README.md +150 -57
- package/ciel-runtime-stop.cmd +1 -0
- package/ciel-runtime.cmd +1 -0
- package/ciel-runtimectl.cmd +1 -0
- package/ciel_runtime.py +56 -53
- package/ciel_runtime_support/anthropic_tool_turns.py +81 -0
- package/ciel_runtime_support/architecture.py +17 -0
- package/ciel_runtime_support/channel_injection.py +113 -3
- package/ciel_runtime_support/channel_message_prompt.py +15 -0
- package/ciel_runtime_support/channel_pending_injection.py +28 -4
- package/ciel_runtime_support/channel_pending_poll.py +2 -0
- package/ciel_runtime_support/channel_terminal_context.py +6 -0
- package/ciel_runtime_support/channel_terminal_dispatch.py +2 -0
- package/ciel_runtime_support/channel_terminal_proxy.py +8 -2
- package/ciel_runtime_support/channel_wake_claim_repository.py +7 -0
- package/ciel_runtime_support/channel_wake_context.py +7 -3
- package/ciel_runtime_support/cli_parser.py +6 -0
- package/ciel_runtime_support/codex_backend_context.py +4 -0
- package/ciel_runtime_support/codex_turn_recovery.py +75 -12
- package/ciel_runtime_support/config_migrations.py +102 -10
- package/ciel_runtime_support/config_repository.py +9 -0
- package/ciel_runtime_support/event_settings_cli.py +284 -2
- package/ciel_runtime_support/openai_chat_passthrough.py +2 -0
- package/ciel_runtime_support/protocols/openai_responses.py +22 -18
- package/ciel_runtime_support/provider_adapters.py +7 -0
- package/ciel_runtime_support/provider_policy.py +10 -1
- package/ciel_runtime_support/provider_request_builder.py +9 -2
- package/ciel_runtime_support/provider_responses_passthrough.py +4 -0
- package/ciel_runtime_support/providers/__init__.py +2 -0
- package/ciel_runtime_support/providers/alibaba.py +33 -10
- package/ciel_runtime_support/providers/constants.py +1 -0
- package/ciel_runtime_support/providers/opencode.py +25 -5
- package/ciel_runtime_support/providers/opencode_go.py +3 -3
- package/ciel_runtime_support/providers/openrouter.py +76 -3
- package/ciel_runtime_support/providers/tabitoken.py +130 -0
- package/ciel_runtime_support/remote_instructions.py +20 -6
- package/ciel_runtime_support/remote_memory.py +515 -55
- package/ciel_runtime_support/responses_input_compatibility.py +14 -0
- package/ciel_runtime_support/router_http.py +5 -0
- package/ciel_runtime_support/runtime_constants.py +1 -1
- package/ciel_runtime_support/runtime_launch.py +9 -2
- package/ciel_runtime_support/runtime_paths.py +2 -0
- package/ciel_runtime_support/tool_side_effect_dedupe.py +7 -4
- package/ciel_runtime_support/transcript_delta_delivery.py +333 -0
- package/ciel_runtime_support/usage_events.py +45 -3
- package/ciel_runtime_support/usage_service.py +871 -0
- package/ciel_runtime_support/windows_conpty.py +108 -2
- package/ciel_runtime_support/workspace_mcp.py +4 -0
- package/docs/CLI-Reference.md +11 -0
- package/docs/Configuration.md +7 -2
- package/docs/MCP-Channels.md +7 -3
- package/docs/Module-Map.md +4 -0
- package/docs/Providers.md +32 -0
- package/docs/Remote-Memory.md +29 -10
- package/docs/Test-Suite.md +1 -0
- package/docs/journal/2026/08/20/kevin-wake-orphan-tool-repair.md +161 -0
- package/docs/journal/2026/08/20/nightly-push-local-deployment.md +59 -2
- package/docs/journal/2026/08/20/wing-remote-memory-replication-verification.md +107 -0
- package/docs/journal/2026/08/21/alibaba-singapore-qwen38-official-alignment.md +64 -0
- package/docs/journal/2026/08/21/codex-visible-sse-wake-submit-regression.md +85 -0
- package/docs/journal/2026/08/21/external-sse-wake-only-change-analysis.md +131 -0
- package/docs/journal/2026/08/21/hyundai-invalid-replayed-tool-name-repair.okf +88 -0
- package/docs/journal/2026/08/21/local-stale-temporary-runtime-pin-repair.okf +118 -0
- package/docs/journal/2026/08/21/transcript-compaction-external-events.okf +131 -0
- package/docs/journal/2026/08/21/wing-ai-net-mcp-boundary-diagnosis.okf +129 -0
- package/docs/journal/2026/08/21/wing-cold-start-wake-submit-repair.okf +161 -0
- package/docs/journal/2026/08/21/wing-powershell-memory-runaway.okf +101 -0
- package/docs/journal/2026/08/21/wing-repeated-reasoning-tool-turn-repair.okf +112 -0
- package/docs/journal/2026/08/21/wing-repeated-tool-guard-finalization.okf +81 -0
- package/docs/journal/2026/08/21/wing-working-directory-memory-deployment.md +110 -0
- package/docs/journal/2026/08/21/wing-workspace-state-memory-prompt-injection.md +88 -0
- package/docs/journal/2026/08/22/alibaba-singapore-dual-endpoint-wire-alignment.okf +142 -0
- package/docs/journal/2026/08/22/delluhiold-claude-compaction-empty-tool-name.okf +168 -0
- package/docs/journal/2026/08/22/remote-memory-relative-prompt-paths.okf +79 -0
- package/docs/journal/2026/08/22/remote-memory-root-system-prompt.okf +121 -0
- package/docs/journal/2026/08/23/claude-web-chat-stateless-mcp-repair.okf +97 -0
- package/docs/journal/2026/08/23/cross-runtime-token-usage-interfaces-research.okf +378 -0
- package/docs/journal/2026/08/23/main-0.2.23-readme-release.okf +81 -0
- package/docs/journal/2026/08/23/mia-openrouter-ox-alpha-latency-diagnosis.okf +146 -0
- package/docs/journal/2026/08/23/openrouter-opencode-ox-alpha-support.okf +114 -0
- package/docs/journal/2026/08/23/tabitoken-provider-model-catalog.okf +97 -0
- package/docs/journal/2026/08/23/usage-stream-snapshot-implementation.okf +134 -0
- package/docs/usage-observability.md +141 -0
- package/install.ps1 +24 -3
- package/package.json +2 -1
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
okf_version: "1.0"
|
|
2
|
+
knowledge:
|
|
3
|
+
task:
|
|
4
|
+
id: mia-openrouter-ox-alpha-latency-diagnosis-20260823
|
|
5
|
+
date: "2026-08-23"
|
|
6
|
+
objective: >-
|
|
7
|
+
Determine from live host, runtime, source, and provider evidence why the
|
|
8
|
+
Mia Codex session using OpenRouter Ox Alpha is slow.
|
|
9
|
+
status: diagnosis_complete
|
|
10
|
+
|
|
11
|
+
scope:
|
|
12
|
+
host: aap-pool-hera
|
|
13
|
+
user: mia
|
|
14
|
+
session_id: 01a02d19-baff-7410-9d91-dc7b932aee82
|
|
15
|
+
runtime_version: 0.2.22-nightly.20260823-070606.65e69f1
|
|
16
|
+
provider: openrouter
|
|
17
|
+
model: stealth/ox-alpha
|
|
18
|
+
|
|
19
|
+
confirmed_evidence:
|
|
20
|
+
reasoning_projection:
|
|
21
|
+
codex_log_effort: low
|
|
22
|
+
installed_openrouter_adapter_override_present: false
|
|
23
|
+
projection_probe:
|
|
24
|
+
requested_effort: low
|
|
25
|
+
projected_effort: null
|
|
26
|
+
provider_request_builder_behavior: >-
|
|
27
|
+
Adds reasoning_effort only when the provider adapter returns a
|
|
28
|
+
non-empty normalized effort.
|
|
29
|
+
openrouter_model_metadata:
|
|
30
|
+
reasoning_mandatory: true
|
|
31
|
+
reasoning_default_enabled: true
|
|
32
|
+
reasoning_default_effort: max
|
|
33
|
+
supported_efforts: [max, high, low]
|
|
34
|
+
conclusion: >-
|
|
35
|
+
The Mia UI/Codex request selected low, but ciel-runtime omitted the
|
|
36
|
+
reasoning_effort field on the OpenRouter Chat Completions wire. Ox
|
|
37
|
+
Alpha therefore used its documented default max reasoning effort.
|
|
38
|
+
|
|
39
|
+
observed_latency:
|
|
40
|
+
first_ox_task:
|
|
41
|
+
model_calls: 19
|
|
42
|
+
minimum_seconds: 8.470
|
|
43
|
+
median_seconds: 19.171
|
|
44
|
+
maximum_seconds: 119.111
|
|
45
|
+
following_ox_task:
|
|
46
|
+
observed_model_calls: 17
|
|
47
|
+
minimum_seconds: 4.855
|
|
48
|
+
median_seconds: 11.076
|
|
49
|
+
maximum_seconds: 28.510
|
|
50
|
+
|
|
51
|
+
rate_limit:
|
|
52
|
+
observed_at_utc: "2026-08-23T07:45:46.900Z"
|
|
53
|
+
result: "429 Too Many Requests"
|
|
54
|
+
task_result: "exceeded retry limit"
|
|
55
|
+
local_rate_limit_rpm: 0
|
|
56
|
+
local_rate_limit_status: false
|
|
57
|
+
openrouter_key_is_free_tier: false
|
|
58
|
+
openrouter_key_limit: null
|
|
59
|
+
|
|
60
|
+
request_shape:
|
|
61
|
+
messages: 193
|
|
62
|
+
tools: 12
|
|
63
|
+
context_estimate_tokens: 112445
|
|
64
|
+
observed_router_request_tokens_range: [131060, 146479]
|
|
65
|
+
observed_router_request_bytes_range: [595898, 672272]
|
|
66
|
+
note: >-
|
|
67
|
+
This is a substantial repeated request load, but its independent share
|
|
68
|
+
of total latency was not isolated in this diagnosis.
|
|
69
|
+
|
|
70
|
+
network_and_host:
|
|
71
|
+
openrouter_models_http_samples: 5
|
|
72
|
+
openrouter_models_http_total_seconds_range: [0.137942, 0.156657]
|
|
73
|
+
router_process_cpu_percent: 0.7
|
|
74
|
+
router_process_rss_kib: 69680
|
|
75
|
+
conclusion: >-
|
|
76
|
+
No evidence was observed that Mia-to-OpenRouter network round-trip or
|
|
77
|
+
Mia host CPU saturation explains the multi-second model waits.
|
|
78
|
+
|
|
79
|
+
upstream_endpoint:
|
|
80
|
+
endpoint_count: 1
|
|
81
|
+
provider_name: Stealth
|
|
82
|
+
uptime_last_5m_percent: 99.98009342817709
|
|
83
|
+
latency_last_30m: null
|
|
84
|
+
throughput_last_30m: null
|
|
85
|
+
|
|
86
|
+
diagnosis:
|
|
87
|
+
primary_confirmed_cause: >-
|
|
88
|
+
ciel-runtime drops Codex's low reasoning effort for OpenRouter Ox Alpha,
|
|
89
|
+
causing the mandatory-reasoning model to fall back to max effort.
|
|
90
|
+
additional_confirmed_degradation:
|
|
91
|
+
- "The live session received an upstream 429 and the turn ended after the configured zero Codex retries."
|
|
92
|
+
- "Large 0.60-0.67 MB agent-history requests are sent on successive tool steps."
|
|
93
|
+
not_supported_by_evidence:
|
|
94
|
+
- "Mia host CPU saturation"
|
|
95
|
+
- "Mia-to-OpenRouter network latency"
|
|
96
|
+
- "A local Ollama bottleneck in this OpenRouter session"
|
|
97
|
+
|
|
98
|
+
mutations:
|
|
99
|
+
runtime_config_changed: false
|
|
100
|
+
process_restarted: false
|
|
101
|
+
source_code_changed: true
|
|
102
|
+
source_fix:
|
|
103
|
+
behavior: >-
|
|
104
|
+
OpenRouter now forwards the explicit request effort or the preserved
|
|
105
|
+
ciel_runtime_reasoning_effort metadata value on Chat Completions wires.
|
|
106
|
+
scope: provider-wide
|
|
107
|
+
mia_specific_exception: false
|
|
108
|
+
|
|
109
|
+
fix_verification:
|
|
110
|
+
projected_request:
|
|
111
|
+
requested_effort: low
|
|
112
|
+
forwarded_effort: low
|
|
113
|
+
live_openrouter_request:
|
|
114
|
+
http_status: 200
|
|
115
|
+
elapsed_seconds: 2.713
|
|
116
|
+
prompt_tokens: 91
|
|
117
|
+
completion_tokens: 3
|
|
118
|
+
cost: 0
|
|
119
|
+
focused_tests: "61 passed"
|
|
120
|
+
full_suite:
|
|
121
|
+
total: "2698 passed, 136 skipped"
|
|
122
|
+
unit: "1148 passed, 44 skipped"
|
|
123
|
+
router: "917 passed"
|
|
124
|
+
channel: "381 passed, 80 skipped"
|
|
125
|
+
runtime: "252 passed, 12 skipped"
|
|
126
|
+
quality:
|
|
127
|
+
ruff: passed
|
|
128
|
+
documentation_metadata: passed
|
|
129
|
+
package_dry_run: "passed; 404 entries"
|
|
130
|
+
local_install:
|
|
131
|
+
status: passed
|
|
132
|
+
path: C:/Users/djlov/.local/share/ciel-runtime
|
|
133
|
+
source_hash_matched: true
|
|
134
|
+
installed_projected_effort: low
|
|
135
|
+
nightly_publish:
|
|
136
|
+
status: passed
|
|
137
|
+
commit: c243e753eb9ba3d9a3471611421751a37806972a
|
|
138
|
+
version: 0.2.22-nightly.20260823-082018.c243e75
|
|
139
|
+
ci_run: 32627887859
|
|
140
|
+
publish_run: 32627887878
|
|
141
|
+
registry_git_head_matched: true
|
|
142
|
+
tarball_verified: true
|
|
143
|
+
npm_global_install:
|
|
144
|
+
status: passed
|
|
145
|
+
version: 0.2.22-nightly.20260823-082018.c243e75
|
|
146
|
+
installed_projected_effort: low
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
okf_version: "1.0"
|
|
2
|
+
knowledge:
|
|
3
|
+
task:
|
|
4
|
+
id: openrouter-opencode-ox-alpha-support-20260823
|
|
5
|
+
date: "2026-08-23"
|
|
6
|
+
objective: >-
|
|
7
|
+
Add verified Ox Alpha model identities and wire-protocol routing for
|
|
8
|
+
OpenRouter, OpenCode Zen, and OpenCode Go.
|
|
9
|
+
|
|
10
|
+
official_evidence:
|
|
11
|
+
openrouter:
|
|
12
|
+
model_id: stealth/ox-alpha
|
|
13
|
+
models_api: https://openrouter.ai/api/v1/models
|
|
14
|
+
context_window: 1048576
|
|
15
|
+
max_output_tokens: 131072
|
|
16
|
+
input_modalities: [text, image, video]
|
|
17
|
+
output_modalities: [text]
|
|
18
|
+
supported_parameters:
|
|
19
|
+
- reasoning
|
|
20
|
+
- reasoning_effort
|
|
21
|
+
- tool_choice
|
|
22
|
+
- tools
|
|
23
|
+
openai_sdk_base_url: https://openrouter.ai/api/v1
|
|
24
|
+
anthropic_sdk_base_url: https://openrouter.ai/api
|
|
25
|
+
opencode_zen:
|
|
26
|
+
models_api: https://opencode.ai/zen/v1/models
|
|
27
|
+
model_id: x-preview-f-free
|
|
28
|
+
endpoint: https://opencode.ai/zen/v1/chat/completions
|
|
29
|
+
live_catalog_count: 64
|
|
30
|
+
retired_managed_fallback: qwen3.6-plus-free
|
|
31
|
+
opencode_go:
|
|
32
|
+
models_api: https://opencode.ai/zen/go/v1/models
|
|
33
|
+
model_id: ox-alpha-free
|
|
34
|
+
endpoint: https://opencode.ai/zen/go/v1/chat/completions
|
|
35
|
+
live_catalog_count: 29
|
|
36
|
+
|
|
37
|
+
implementation:
|
|
38
|
+
openrouter:
|
|
39
|
+
behavior:
|
|
40
|
+
- Adds stealth/ox-alpha to the configured model fallback catalog.
|
|
41
|
+
- Uses OpenAI Chat Completions for OpenAI/Codex requests.
|
|
42
|
+
- Uses OpenRouter's Anthropic Messages compatibility endpoint for Claude requests.
|
|
43
|
+
- Applies the verified 1,048,576 context and 131,072 output profile on selection.
|
|
44
|
+
opencode:
|
|
45
|
+
behavior:
|
|
46
|
+
- Adds the exact public Zen and Go model IDs to each provider catalog.
|
|
47
|
+
- Routes both aliases through their documented Chat Completions endpoints.
|
|
48
|
+
- Removes the retired qwen3.6-plus-free Zen fallback from new and migrated configs.
|
|
49
|
+
- Routes Zen GPT/Grok/Muse models through Responses and Gemini through Google Generative.
|
|
50
|
+
- Routes Zen DeepSeek/GLM/Hy3/Kimi/Laguna/MiMo/MiniMax/Nemotron models through Chat Completions.
|
|
51
|
+
- Routes Go GPT/Grok/Muse models through Responses, MiniMax/Qwen through Messages, and the remaining documented open models through Chat Completions.
|
|
52
|
+
migration:
|
|
53
|
+
behavior:
|
|
54
|
+
- Merges models into existing custom model lists.
|
|
55
|
+
- Preserves existing user-defined endpoint overrides.
|
|
56
|
+
|
|
57
|
+
verification:
|
|
58
|
+
public_model_api:
|
|
59
|
+
status: passed
|
|
60
|
+
observations:
|
|
61
|
+
- "OpenRouter returned HTTP 200 and contained stealth/ox-alpha."
|
|
62
|
+
- "OpenCode Zen returned HTTP 200 and contained x-preview-f-free."
|
|
63
|
+
- "OpenCode Go returned HTTP 200 and contained ox-alpha-free."
|
|
64
|
+
request_projection:
|
|
65
|
+
status: passed
|
|
66
|
+
openrouter_openai: https://openrouter.ai/api/v1/chat/completions
|
|
67
|
+
openrouter_anthropic: https://openrouter.ai/api/v1/messages
|
|
68
|
+
opencode_zen: https://opencode.ai/zen/v1/chat/completions
|
|
69
|
+
opencode_go: https://opencode.ai/zen/go/v1/chat/completions
|
|
70
|
+
live_catalog_route_matrix:
|
|
71
|
+
status: passed
|
|
72
|
+
opencode: "64 models checked; 0 protocol mismatches"
|
|
73
|
+
opencode_go: "29 models checked; 0 protocol mismatches"
|
|
74
|
+
retired_qwen_free_present: false
|
|
75
|
+
focused_tests: "114 passed"
|
|
76
|
+
full_suite:
|
|
77
|
+
total: "2696 passed, 136 skipped"
|
|
78
|
+
unit: "1148 passed, 44 skipped"
|
|
79
|
+
router: "915 passed"
|
|
80
|
+
channel: "381 passed, 80 skipped"
|
|
81
|
+
runtime: "252 passed, 12 skipped"
|
|
82
|
+
quality:
|
|
83
|
+
ruff: passed
|
|
84
|
+
documentation_metadata: passed
|
|
85
|
+
diff_check: passed
|
|
86
|
+
package_dry_run: "passed; 403 entries"
|
|
87
|
+
local_install:
|
|
88
|
+
status: passed
|
|
89
|
+
path: C:/Users/djlov/.local/share/ciel-runtime
|
|
90
|
+
version_output: ciel-runtime 0.2.22
|
|
91
|
+
source_hashes_matched: true
|
|
92
|
+
installed_catalog_and_route_check: passed
|
|
93
|
+
installed_live_catalog_matrix:
|
|
94
|
+
opencode: "64 models checked; 0 protocol mismatches"
|
|
95
|
+
opencode_go: "29 models checked; 0 protocol mismatches"
|
|
96
|
+
live_generation:
|
|
97
|
+
status: not_run
|
|
98
|
+
reason: >-
|
|
99
|
+
No OpenRouter, OpenCode Zen, or OpenCode Go API key was configured in
|
|
100
|
+
the process environment or local ciel-runtime provider configuration.
|
|
101
|
+
nightly_publish:
|
|
102
|
+
status: passed
|
|
103
|
+
workflow_run: 32624300464
|
|
104
|
+
workflow_url: https://github.com/OneCielAI/ciel-runtime/actions/runs/32624300464
|
|
105
|
+
commit: 70c5d32ece7636b0a61a43c38742b92ce2ea91a0
|
|
106
|
+
version: 0.2.22-nightly.20260823-070025.70c5d32
|
|
107
|
+
registry_git_head_matched: true
|
|
108
|
+
npm_global_install:
|
|
109
|
+
status: passed
|
|
110
|
+
version: 0.2.22-nightly.20260823-070025.70c5d32
|
|
111
|
+
path: C:/Users/djlov/AppData/Roaming/npm/node_modules/@oneciel-ai/ciel-runtime
|
|
112
|
+
installed_live_catalog_matrix:
|
|
113
|
+
opencode: "64 models checked; 0 protocol mismatches"
|
|
114
|
+
opencode_go: "29 models checked; 0 protocol mismatches"
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
okf_version: "1.0"
|
|
2
|
+
knowledge:
|
|
3
|
+
task:
|
|
4
|
+
id: tabitoken-provider-model-catalog-20260823
|
|
5
|
+
date: "2026-08-23"
|
|
6
|
+
objective: >-
|
|
7
|
+
Determine whether ciel-runtime supports tabitoken.com and implement its
|
|
8
|
+
currently published provider endpoints and model catalog.
|
|
9
|
+
status: complete
|
|
10
|
+
|
|
11
|
+
official_evidence:
|
|
12
|
+
pricing_page:
|
|
13
|
+
url: https://tabitoken.com/pricing
|
|
14
|
+
observed_enabled_models: 4
|
|
15
|
+
models:
|
|
16
|
+
- claude-opus-4-8
|
|
17
|
+
- claude-opus-4-8-thinking
|
|
18
|
+
- claude-opus-5
|
|
19
|
+
- claude-opus-5-thinking
|
|
20
|
+
endpoint_badges: [anthropic, openai]
|
|
21
|
+
displayed_context_tag: 1M
|
|
22
|
+
pricing_api:
|
|
23
|
+
url: https://tabitoken.com/api/pricing
|
|
24
|
+
status: 200
|
|
25
|
+
success: true
|
|
26
|
+
anthropic: "POST /v1/messages"
|
|
27
|
+
openai: "POST /v1/chat/completions"
|
|
28
|
+
api_detail:
|
|
29
|
+
base_url: https://tabitoken.com
|
|
30
|
+
authentication: "Authorization: Bearer <TOKEN> for all endpoints"
|
|
31
|
+
anthropic_alternative_authentication: x-api-key
|
|
32
|
+
thinking_models_parameter: reasoning_effort
|
|
33
|
+
thinking_models_default_effort: medium
|
|
34
|
+
non_thinking_models_parameter: temperature
|
|
35
|
+
shared_parameters_include: [stream, tools, tool_choice]
|
|
36
|
+
|
|
37
|
+
prior_support_audit:
|
|
38
|
+
repository_search: >-
|
|
39
|
+
A case-insensitive search for tabitoken and tabi-token returned no source,
|
|
40
|
+
test, documentation, alias, or provider registration match.
|
|
41
|
+
result: unsupported_before_this_change
|
|
42
|
+
|
|
43
|
+
implementation:
|
|
44
|
+
provider_id: tabitoken
|
|
45
|
+
aliases: [tabi, tabiai, tabi-token]
|
|
46
|
+
adapter: ciel_runtime_support/providers/tabitoken.py
|
|
47
|
+
protocols: [anthropic_messages, openai_chat]
|
|
48
|
+
authentication: bearer
|
|
49
|
+
context_window: 1000000
|
|
50
|
+
reasoning_scope: "Only model IDs ending in -thinking"
|
|
51
|
+
fallback_models_source: https://tabitoken.com/api/pricing
|
|
52
|
+
|
|
53
|
+
verification:
|
|
54
|
+
focused_tests: "57 passed"
|
|
55
|
+
full_suite:
|
|
56
|
+
total: "2704 passed, 136 skipped"
|
|
57
|
+
unit: "1148 passed, 44 skipped"
|
|
58
|
+
router: "923 passed"
|
|
59
|
+
channel: "381 passed, 80 skipped"
|
|
60
|
+
runtime: "252 passed, 12 skipped"
|
|
61
|
+
ruff: passed
|
|
62
|
+
documentation_metadata: "passed; 22 Markdown files"
|
|
63
|
+
package_dry_run: "passed; 406 entries"
|
|
64
|
+
live_unauthenticated_route_probe:
|
|
65
|
+
/v1/models: 403
|
|
66
|
+
/v1/chat/completions: 403
|
|
67
|
+
/v1/messages: 403
|
|
68
|
+
interpretation: >-
|
|
69
|
+
The public host protected all three configured routes. No Tabitoken API
|
|
70
|
+
key was available, so authenticated model inference was not performed.
|
|
71
|
+
runtime_projection:
|
|
72
|
+
normalized_alias: tabitoken
|
|
73
|
+
openai_url: https://tabitoken.com/v1/chat/completions
|
|
74
|
+
anthropic_url: https://tabitoken.com/v1/messages
|
|
75
|
+
models: 4
|
|
76
|
+
|
|
77
|
+
deployment:
|
|
78
|
+
local:
|
|
79
|
+
status: passed
|
|
80
|
+
path: C:/Users/djlov/.local/share/ciel-runtime
|
|
81
|
+
source_hash_matched: true
|
|
82
|
+
installed_models: 4
|
|
83
|
+
installed_openai_url: https://tabitoken.com/v1/chat/completions
|
|
84
|
+
installed_anthropic_url: https://tabitoken.com/v1/messages
|
|
85
|
+
nightly:
|
|
86
|
+
status: passed
|
|
87
|
+
source_commit: d81eb003b7896d55b91588fbcf020fc364ef8c5b
|
|
88
|
+
version: 0.2.22-nightly.20260823-085017.d81eb00
|
|
89
|
+
ci_run: 32629221468
|
|
90
|
+
publish_run: 32629221482
|
|
91
|
+
registry_git_head_matched: true
|
|
92
|
+
published_tarball_verified: true
|
|
93
|
+
npm_global_install:
|
|
94
|
+
status: passed
|
|
95
|
+
installed_version: 0.2.22-nightly.20260823-085017.d81eb00
|
|
96
|
+
source_hash_matched: true
|
|
97
|
+
installed_models: 4
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
okf_version: "1.0"
|
|
2
|
+
knowledge:
|
|
3
|
+
task:
|
|
4
|
+
id: usage-stream-snapshot-implementation-20260823
|
|
5
|
+
date: "2026-08-23"
|
|
6
|
+
objective: >-
|
|
7
|
+
Implement workspace-scoped token usage capture, authenticated real-time
|
|
8
|
+
delivery, time-range snapshots, retry-safe per-key cursors, daily audit
|
|
9
|
+
delivery, legacy backfill, startup environment configuration, and the
|
|
10
|
+
equivalent ciel-runtimectl configuration surface.
|
|
11
|
+
status: implementation-complete
|
|
12
|
+
|
|
13
|
+
architecture:
|
|
14
|
+
storage:
|
|
15
|
+
kind: sqlite
|
|
16
|
+
workspace_scoped: true
|
|
17
|
+
relative_path: usage/usage.sqlite3
|
|
18
|
+
immutable_event_sequence: true
|
|
19
|
+
inbound_interfaces:
|
|
20
|
+
events: GET /ca/usage/events
|
|
21
|
+
stream: GET /ca/usage/stream
|
|
22
|
+
snapshot: GET /ca/usage/snapshot
|
|
23
|
+
key_administration: /ca/usage/keys
|
|
24
|
+
outbound_interfaces:
|
|
25
|
+
event_type: ai.oneciel.ciel-runtime.usage.recorded
|
|
26
|
+
audit_type: ai.oneciel.ciel-runtime.usage.audit
|
|
27
|
+
envelope: CloudEvents-1.0
|
|
28
|
+
retry_rule: cursor advances only after HTTP 2xx
|
|
29
|
+
idempotency_rule: event ID and Idempotency-Key remain stable across retry
|
|
30
|
+
cursor_identity: endpoint ID plus URL plus expanded authorization fingerprint
|
|
31
|
+
audit:
|
|
32
|
+
default_interval_seconds: 86400
|
|
33
|
+
contains: [period, totals, rates, groups, sequence_coverage]
|
|
34
|
+
backfill:
|
|
35
|
+
inputs: [workspace-owned usage-events.jsonl, usage-events.jsonl.1, explicit paths]
|
|
36
|
+
cursor: per-source-byte-offset
|
|
37
|
+
rotation_deduplication: deterministic legacy event ID
|
|
38
|
+
incomplete_trailing_line: deferred
|
|
39
|
+
|
|
40
|
+
configuration:
|
|
41
|
+
startup_environment:
|
|
42
|
+
- CIEL_RUNTIME_USAGE_API_KEY
|
|
43
|
+
- CIEL_RUNTIME_USAGE_API_KEYS
|
|
44
|
+
- CIEL_RUNTIME_USAGE_PUSH_ID
|
|
45
|
+
- CIEL_RUNTIME_USAGE_PUSH_URL
|
|
46
|
+
- CIEL_RUNTIME_USAGE_PUSH_AUTHORIZATION
|
|
47
|
+
- CIEL_RUNTIME_USAGE_PUSH_API_KEY
|
|
48
|
+
- CIEL_RUNTIME_USAGE_PUSH_ENDPOINTS
|
|
49
|
+
- CIEL_RUNTIME_USAGE_AUDIT_INTERVAL_SECONDS
|
|
50
|
+
- CIEL_RUNTIME_USAGE_BACKFILL_PATHS
|
|
51
|
+
- CIEL_RUNTIME_USAGE_LOG
|
|
52
|
+
ctl:
|
|
53
|
+
usage_events:
|
|
54
|
+
command: ciel-runtimectl usage-events
|
|
55
|
+
values:
|
|
56
|
+
- endpoint_id
|
|
57
|
+
- enabled
|
|
58
|
+
- url
|
|
59
|
+
- authorization
|
|
60
|
+
- api_key
|
|
61
|
+
- timeout_seconds
|
|
62
|
+
- poll_interval_seconds
|
|
63
|
+
- start_mode
|
|
64
|
+
- audit_interval_seconds
|
|
65
|
+
- audit_emit_on_start
|
|
66
|
+
- jsonl_enabled
|
|
67
|
+
- backfill_paths
|
|
68
|
+
usage_api_key:
|
|
69
|
+
command: ciel-runtimectl usage-api-key
|
|
70
|
+
actions: [issue, list, revoke]
|
|
71
|
+
exact_environment_equivalents: [key_id, api_key, name, scopes, expires_at]
|
|
72
|
+
persistence: workspace config plus keyed-digest API-key repository
|
|
73
|
+
shell_environment_mutation: false
|
|
74
|
+
|
|
75
|
+
confirmed_limits:
|
|
76
|
+
native_direct_runtime_usage: >-
|
|
77
|
+
Requests that bypass the Ciel router are not observed by the router ledger.
|
|
78
|
+
unrecoverable_history: >-
|
|
79
|
+
A historical period with no Ciel JSONL record and no native CLI usage
|
|
80
|
+
record cannot be reconstructed.
|
|
81
|
+
unowned_global_jsonl: >-
|
|
82
|
+
A legacy global JSONL file with no workspace identity is not assigned
|
|
83
|
+
automatically and requires an explicit backfill path.
|
|
84
|
+
|
|
85
|
+
verification:
|
|
86
|
+
focused_usage_service: "8 passed"
|
|
87
|
+
focused_event_settings_cli: "34 passed"
|
|
88
|
+
architecture_contracts: "261 passed, 42 skipped"
|
|
89
|
+
ruff: passed
|
|
90
|
+
diff_check: passed
|
|
91
|
+
main_module_lines: 4980
|
|
92
|
+
ctl_wrapper_probe:
|
|
93
|
+
destination_saved: true
|
|
94
|
+
destination_report_masked_authorization: true
|
|
95
|
+
daily_interval_seconds: 86400
|
|
96
|
+
jsonl_enabled: false
|
|
97
|
+
backfill_path_count: 1
|
|
98
|
+
exact_api_key_id: env_auditor
|
|
99
|
+
key_metadata_listed: true
|
|
100
|
+
ledger_created: true
|
|
101
|
+
pepper_created: true
|
|
102
|
+
full_suite:
|
|
103
|
+
unit: "1164 passed, 44 skipped"
|
|
104
|
+
router: "923 passed"
|
|
105
|
+
channel: "381 passed, 80 skipped"
|
|
106
|
+
runtime: "252 passed, 12 skipped"
|
|
107
|
+
documentation_metadata: "passed; 23 Markdown files"
|
|
108
|
+
package_dry_run: "passed; 411 files"
|
|
109
|
+
|
|
110
|
+
deployment:
|
|
111
|
+
local:
|
|
112
|
+
status: passed
|
|
113
|
+
path: C:/Users/djlov/.local/share/ciel-runtime
|
|
114
|
+
source_hash_matched: true
|
|
115
|
+
installed_version: 0.2.22
|
|
116
|
+
nightly:
|
|
117
|
+
status: passed
|
|
118
|
+
source_commit: 45a9456ffaa554598e5196bae3df18a936f3c88b
|
|
119
|
+
version: 0.2.22-nightly.20260823-234610.45a9456
|
|
120
|
+
ci_run: 32674465612
|
|
121
|
+
publish_run: 32674465609
|
|
122
|
+
registry_git_head_matched: true
|
|
123
|
+
published_tarball_verified: true
|
|
124
|
+
clean_registry_install:
|
|
125
|
+
status: passed
|
|
126
|
+
installed_version: 0.2.22-nightly.20260823-234610.45a9456
|
|
127
|
+
source_hash_matched: true
|
|
128
|
+
first_publish_attempt:
|
|
129
|
+
run: 32674354694
|
|
130
|
+
status: failed
|
|
131
|
+
confirmed_cause: >-
|
|
132
|
+
A Windows-specific test fixture used drive-letter paths while the
|
|
133
|
+
Linux runner used ':' as os.pathsep, producing four parts instead of
|
|
134
|
+
two. The fixture now constructs platform-native paths.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Usage observability
|
|
2
|
+
|
|
3
|
+
Ciel Runtime stores routed model usage in a workspace-scoped SQLite ledger and
|
|
4
|
+
exposes authenticated event, stream, and period-snapshot interfaces.
|
|
5
|
+
|
|
6
|
+
## Startup environment
|
|
7
|
+
|
|
8
|
+
The first router start can provision consumer keys and outbound delivery without
|
|
9
|
+
writing secrets into `config.json`.
|
|
10
|
+
|
|
11
|
+
```powershell
|
|
12
|
+
$env:CIEL_RUNTIME_USAGE_API_KEYS = '[{"id":"auditor","key":"replace-me","scopes":["usage:read","usage:stream"]}]'
|
|
13
|
+
$env:CIEL_RUNTIME_USAGE_PUSH_ENDPOINTS = '[{"id":"audit-service","url":"https://audit.example/v1/ciel-usage","authorization":"Bearer ${AUDIT_SERVICE_API_KEY}","start_mode":"tail","audit_interval_seconds":86400}]'
|
|
14
|
+
$env:AUDIT_SERVICE_API_KEY = 'replace-me'
|
|
15
|
+
ciel-runtime
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Single-destination variables are also supported:
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
CIEL_RUNTIME_USAGE_API_KEY
|
|
22
|
+
CIEL_RUNTIME_USAGE_PUSH_ID
|
|
23
|
+
CIEL_RUNTIME_USAGE_PUSH_URL
|
|
24
|
+
CIEL_RUNTIME_USAGE_PUSH_AUTHORIZATION
|
|
25
|
+
CIEL_RUNTIME_USAGE_PUSH_API_KEY
|
|
26
|
+
CIEL_RUNTIME_USAGE_AUDIT_INTERVAL_SECONDS
|
|
27
|
+
CIEL_RUNTIME_USAGE_BACKFILL_PATHS
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The same persistent workspace settings can be injected with
|
|
31
|
+
`ciel-runtimectl`. This writes the workspace `config.json`; it does not mutate
|
|
32
|
+
the parent shell's environment:
|
|
33
|
+
|
|
34
|
+
```powershell
|
|
35
|
+
ciel-runtimectl usage-events endpoint_id=audit enabled=true url=https://audit.example/v1/ciel-usage 'authorization=Bearer ${AUDIT_SERVICE_API_KEY}' start_mode=tail audit_interval_seconds=86400
|
|
36
|
+
ciel-runtimectl usage-events endpoint_id=audit
|
|
37
|
+
ciel-runtimectl usage-api-key issue name=auditor 'scopes=read,stream' ttl_seconds=2592000
|
|
38
|
+
ciel-runtimectl usage-api-key list
|
|
39
|
+
ciel-runtimectl usage-api-key revoke key_id=uk_replace_me
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`usage-events` accepts `endpoint_id`, `enabled`, `url`, `authorization`,
|
|
43
|
+
`api_key`, `timeout_seconds`, `poll_interval_seconds`, `start_mode`,
|
|
44
|
+
`audit_interval_seconds`, `audit_emit_on_start`, `jsonl_enabled`, and
|
|
45
|
+
`backfill_paths`. On
|
|
46
|
+
Windows, delimit multiple `backfill_paths` with `;`; on POSIX systems use `:`.
|
|
47
|
+
The issued usage API key is displayed once, while only its keyed digest is
|
|
48
|
+
persisted. A running router reloads outbound destinations on its next poll;
|
|
49
|
+
new `backfill_paths` are scanned on the next router start.
|
|
50
|
+
|
|
51
|
+
To provision the exact identity and secret supplied through
|
|
52
|
+
`CIEL_RUNTIME_USAGE_API_KEYS`, pass `key_id=... api_key=... expires_at=...` to
|
|
53
|
+
`usage-api-key issue`. Omitting those values generates a new ID and secret.
|
|
54
|
+
|
|
55
|
+
`CIEL_RUNTIME_USAGE_PUSH_ENDPOINTS` is a JSON array. It replaces configured
|
|
56
|
+
`usage.push_endpoints` for that process. Each item supports `id`, `url`,
|
|
57
|
+
`authorization` or `api_key`, `timeout_seconds`, `poll_interval_seconds`,
|
|
58
|
+
`start_mode` (`tail` or `beginning`), `audit_interval_seconds`, and
|
|
59
|
+
`audit_emit_on_start`.
|
|
60
|
+
|
|
61
|
+
Authorization values may contain `${ENVIRONMENT_VARIABLE}` references. A
|
|
62
|
+
missing reference prevents delivery and does not advance the cursor.
|
|
63
|
+
|
|
64
|
+
## Consumer keys
|
|
65
|
+
|
|
66
|
+
Consumer keys are distinct from upstream provider credentials and the router's
|
|
67
|
+
external administration token. Only a keyed digest is stored. The plaintext is
|
|
68
|
+
returned once when a key is issued.
|
|
69
|
+
|
|
70
|
+
Issue a key locally, or externally with the router administration token:
|
|
71
|
+
|
|
72
|
+
```http
|
|
73
|
+
POST /ca/usage/keys
|
|
74
|
+
Content-Type: application/json
|
|
75
|
+
Authorization: Bearer <router-administration-token>
|
|
76
|
+
|
|
77
|
+
{"name":"auditor","scopes":["usage:read","usage:stream"]}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
List key metadata with `GET /ca/usage/keys`. Revoke a key with:
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{"action":"revoke","key_id":"uk_..."}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
sent to `POST /ca/usage/keys` under router administration authentication.
|
|
87
|
+
|
|
88
|
+
## Interfaces
|
|
89
|
+
|
|
90
|
+
All consumer routes accept `Authorization: Bearer <usage-api-key>` or
|
|
91
|
+
`x-ciel-usage-key: <usage-api-key>`.
|
|
92
|
+
|
|
93
|
+
- `GET /ca/usage/events?from=<RFC3339-or-epoch>&to=<...>&after=<seq>&limit=200`
|
|
94
|
+
returns immutable events. Optional filters are `runtime`, `provider`, and
|
|
95
|
+
`model`.
|
|
96
|
+
- `GET /ca/usage/stream?after=<seq>` streams durable events with the SQLite
|
|
97
|
+
sequence as the SSE `id`. Reconnect with the last acknowledged sequence.
|
|
98
|
+
- `GET /ca/usage/snapshot?from=<RFC3339-or-epoch>&to=<...>` returns totals,
|
|
99
|
+
provider/model/runtime groups, sequence coverage, estimated/incomplete event
|
|
100
|
+
counts, requests per hour, tokens per hour, and cache-read ratio.
|
|
101
|
+
|
|
102
|
+
When `from` and `to` are omitted, snapshot and event queries cover the previous
|
|
103
|
+
24 hours.
|
|
104
|
+
|
|
105
|
+
## Outbound delivery and audit
|
|
106
|
+
|
|
107
|
+
Each configured receiver gets two CloudEvents:
|
|
108
|
+
|
|
109
|
+
- `ai.oneciel.ciel-runtime.usage.recorded` for each new usage event.
|
|
110
|
+
- `ai.oneciel.ciel-runtime.usage.audit` for each configured audit interval.
|
|
111
|
+
|
|
112
|
+
The audit event contains the exact period boundaries, first and last ledger
|
|
113
|
+
sequence, totals, rates, and provider/model/runtime groups. A percentage of a
|
|
114
|
+
provider quota is not fabricated when the provider does not expose that quota.
|
|
115
|
+
|
|
116
|
+
Delivery state is keyed by endpoint ID, URL, and authorization-key fingerprint.
|
|
117
|
+
HTTP failure leaves both the event cursor and audit-period cursor unchanged.
|
|
118
|
+
Retries reuse the same CloudEvent ID and `Idempotency-Key`; a cursor advances
|
|
119
|
+
only after a 2xx response.
|
|
120
|
+
|
|
121
|
+
The ledger is stored under the current workspace state directory at
|
|
122
|
+
`usage/usage.sqlite3`, so different workspaces do not share usage data.
|
|
123
|
+
|
|
124
|
+
## Pre-deployment backfill
|
|
125
|
+
|
|
126
|
+
At router startup Ciel imports workspace-owned `usage-events.jsonl` files and
|
|
127
|
+
their `.1` rotation into the SQLite ledger. Each source has a durable byte
|
|
128
|
+
cursor, incomplete trailing records are left for the next startup, and legacy
|
|
129
|
+
records without an event ID receive a deterministic content ID so rotation does
|
|
130
|
+
not duplicate them.
|
|
131
|
+
|
|
132
|
+
Older global files cannot be assigned to a workspace from their contents. They
|
|
133
|
+
are therefore imported only when explicitly named:
|
|
134
|
+
|
|
135
|
+
```powershell
|
|
136
|
+
$env:CIEL_RUNTIME_USAGE_BACKFILL_PATHS = '["C:\\Users\\me\\AppData\\Roaming\\ciel-runtime\\usage-events.jsonl"]'
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Backfilled legacy rows without cache/reasoning fields are marked
|
|
140
|
+
`is_incomplete=true`. A period in which neither Ciel nor the native CLI stored a
|
|
141
|
+
usage record cannot be reconstructed by this importer.
|
package/install.ps1
CHANGED
|
@@ -37,13 +37,34 @@ $prefix = if ($env:PREFIX) { $env:PREFIX } else { Join-Path $HOME ".local" }
|
|
|
37
37
|
$defaultShareDir = Join-Path $prefix "share\ciel-runtime"
|
|
38
38
|
$runtimeHome = [string]$env:CIEL_RUNTIME_HOME
|
|
39
39
|
$snapshotHome = $runtimeHome -and ((Split-Path -Leaf $runtimeHome) -match '^ciel-runtime-[0-9a-f]{7,40}$')
|
|
40
|
+
$expandedRuntimeHome = if ($runtimeHome) {
|
|
41
|
+
[System.IO.Path]::GetFullPath(
|
|
42
|
+
[Environment]::ExpandEnvironmentVariables($runtimeHome)
|
|
43
|
+
).TrimEnd('\')
|
|
44
|
+
} else {
|
|
45
|
+
""
|
|
46
|
+
}
|
|
47
|
+
$expandedTempHome = [System.IO.Path]::GetFullPath(
|
|
48
|
+
[System.IO.Path]::GetTempPath()
|
|
49
|
+
).TrimEnd(
|
|
50
|
+
[System.IO.Path]::DirectorySeparatorChar,
|
|
51
|
+
[System.IO.Path]::AltDirectorySeparatorChar
|
|
52
|
+
) + [System.IO.Path]::DirectorySeparatorChar
|
|
53
|
+
$temporaryRuntimeHome = (
|
|
54
|
+
$expandedRuntimeHome -and
|
|
55
|
+
$expandedRuntimeHome.StartsWith(
|
|
56
|
+
$expandedTempHome,
|
|
57
|
+
[System.StringComparison]::OrdinalIgnoreCase
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
$ephemeralRuntimeHome = $snapshotHome -or $temporaryRuntimeHome
|
|
40
61
|
$shareDir = if ($env:CIEL_RUNTIME_INSTALL_HOME) {
|
|
41
62
|
$env:CIEL_RUNTIME_INSTALL_HOME
|
|
42
|
-
} elseif ($runtimeHome -and -not $
|
|
63
|
+
} elseif ($runtimeHome -and -not $ephemeralRuntimeHome) {
|
|
43
64
|
$runtimeHome
|
|
44
65
|
} else {
|
|
45
|
-
if ($
|
|
46
|
-
Write-Warning "Ignoring
|
|
66
|
+
if ($ephemeralRuntimeHome) {
|
|
67
|
+
Write-Warning "Ignoring ephemeral CIEL_RUNTIME_HOME during install: $runtimeHome"
|
|
47
68
|
}
|
|
48
69
|
$defaultShareDir
|
|
49
70
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oneciel-ai/ciel-runtime",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.23",
|
|
4
4
|
"description": "Universal AI coding-agent runtime and model-routing layer for Claude, Codex, AGY, and compatible runtimes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "One Ciel LLC",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"install.sh",
|
|
43
43
|
"install.ps1",
|
|
44
44
|
"README.md",
|
|
45
|
+
"CHANGELOG.md",
|
|
45
46
|
"LICENSE",
|
|
46
47
|
"NOTICE",
|
|
47
48
|
"docs/"
|