@octelium/console-agent 0.1.0-b-ca02.1.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.
Files changed (97) hide show
  1. package/LICENSE +267 -0
  2. package/README.md +207 -0
  3. package/apis/octelium.binpb +0 -0
  4. package/dist/agent/pi/auth.d.ts +32 -0
  5. package/dist/agent/pi/auth.js +279 -0
  6. package/dist/agent/pi/auth.js.map +1 -0
  7. package/dist/agent/pi/backend.d.ts +77 -0
  8. package/dist/agent/pi/backend.js +518 -0
  9. package/dist/agent/pi/backend.js.map +1 -0
  10. package/dist/agent/pi/mapper.d.ts +33 -0
  11. package/dist/agent/pi/mapper.js +386 -0
  12. package/dist/agent/pi/mapper.js.map +1 -0
  13. package/dist/agent/pi/model.d.ts +47 -0
  14. package/dist/agent/pi/model.js +199 -0
  15. package/dist/agent/pi/model.js.map +1 -0
  16. package/dist/agent/prompt.d.ts +22 -0
  17. package/dist/agent/prompt.js +75 -0
  18. package/dist/agent/prompt.js.map +1 -0
  19. package/dist/agent/resources.d.ts +13 -0
  20. package/dist/agent/resources.js +78 -0
  21. package/dist/agent/resources.js.map +1 -0
  22. package/dist/agent/tools/builtin.d.ts +13 -0
  23. package/dist/agent/tools/builtin.js +80 -0
  24. package/dist/agent/tools/builtin.js.map +1 -0
  25. package/dist/agent/tools/octelium.d.ts +28 -0
  26. package/dist/agent/tools/octelium.js +236 -0
  27. package/dist/agent/tools/octelium.js.map +1 -0
  28. package/dist/agent/tools/present.d.ts +61 -0
  29. package/dist/agent/tools/present.js +273 -0
  30. package/dist/agent/tools/present.js.map +1 -0
  31. package/dist/agent/tools/util.d.ts +19 -0
  32. package/dist/agent/tools/util.js +103 -0
  33. package/dist/agent/tools/util.js.map +1 -0
  34. package/dist/agent/tools/web.d.ts +24 -0
  35. package/dist/agent/tools/web.js +237 -0
  36. package/dist/agent/tools/web.js.map +1 -0
  37. package/dist/agent/types.d.ts +60 -0
  38. package/dist/agent/types.js +2 -0
  39. package/dist/agent/types.js.map +1 -0
  40. package/dist/app.d.ts +36 -0
  41. package/dist/app.js +126 -0
  42. package/dist/app.js.map +1 -0
  43. package/dist/cli.d.ts +2 -0
  44. package/dist/cli.js +249 -0
  45. package/dist/cli.js.map +1 -0
  46. package/dist/config.d.ts +159 -0
  47. package/dist/config.js +251 -0
  48. package/dist/config.js.map +1 -0
  49. package/dist/errors.d.ts +13 -0
  50. package/dist/errors.js +18 -0
  51. package/dist/errors.js.map +1 -0
  52. package/dist/index.d.ts +6 -0
  53. package/dist/index.js +6 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/log.d.ts +11 -0
  56. package/dist/log.js +41 -0
  57. package/dist/log.js.map +1 -0
  58. package/dist/octelium/catalog.d.ts +61 -0
  59. package/dist/octelium/catalog.js +595 -0
  60. package/dist/octelium/catalog.js.map +1 -0
  61. package/dist/octelium/client.d.ts +53 -0
  62. package/dist/octelium/client.js +201 -0
  63. package/dist/octelium/client.js.map +1 -0
  64. package/dist/octelium/search.d.ts +24 -0
  65. package/dist/octelium/search.js +211 -0
  66. package/dist/octelium/search.js.map +1 -0
  67. package/dist/protocol/index.d.ts +432 -0
  68. package/dist/protocol/index.js +44 -0
  69. package/dist/protocol/index.js.map +1 -0
  70. package/dist/runs/builder.d.ts +17 -0
  71. package/dist/runs/builder.js +81 -0
  72. package/dist/runs/builder.js.map +1 -0
  73. package/dist/runs/manager.d.ts +52 -0
  74. package/dist/runs/manager.js +536 -0
  75. package/dist/runs/manager.js.map +1 -0
  76. package/dist/server/http.d.ts +9 -0
  77. package/dist/server/http.js +100 -0
  78. package/dist/server/http.js.map +1 -0
  79. package/dist/server/server.d.ts +48 -0
  80. package/dist/server/server.js +483 -0
  81. package/dist/server/server.js.map +1 -0
  82. package/dist/skills.d.ts +4 -0
  83. package/dist/skills.js +69 -0
  84. package/dist/skills.js.map +1 -0
  85. package/dist/store/conversations.d.ts +26 -0
  86. package/dist/store/conversations.js +183 -0
  87. package/dist/store/conversations.js.map +1 -0
  88. package/dist/store/files.d.ts +27 -0
  89. package/dist/store/files.js +161 -0
  90. package/dist/store/files.js.map +1 -0
  91. package/dist/store/settings.d.ts +14 -0
  92. package/dist/store/settings.js +48 -0
  93. package/dist/store/settings.js.map +1 -0
  94. package/dist/version.d.ts +1 -0
  95. package/dist/version.js +11 -0
  96. package/dist/version.js.map +1 -0
  97. package/package.json +57 -0
package/LICENSE ADDED
@@ -0,0 +1,267 @@
1
+ OCTELIUM ENTERPRISE SOURCE-AVAILABLE LICENSE
2
+ Version 1.0
3
+ Copyright (c) 2025-present Octelium Labs, LLC. All rights reserved.
4
+
5
+ By accessing, copying, modifying, or using the Software, you agree to be bound
6
+ by this License. If you do not agree, do not access or use the Software.
7
+
8
+ 1. DEFINITIONS
9
+
10
+ 1.1 "Licensor" means Octelium Labs, LLC.
11
+
12
+ 1.2 "Software" means all source code, compiled code, configuration files,
13
+ documentation, and associated materials made available in this repository,
14
+ including any Modifications (as defined in Section 1.7) whether or not
15
+ such Modifications have been submitted to Licensor.
16
+
17
+ 1.3 "Commercial Agreement" means a valid, fully executed written agreement
18
+ between you (or your Organization) and Licensor that expressly grants
19
+ rights beyond those in this License.
20
+
21
+ 1.4 "Production Environment" means any system, infrastructure, or deployment
22
+ that (a) serves external users or customers, (b) processes live or real
23
+ business data, (c) is part of a revenue-generating activity, (d) acts as
24
+ a staging, pre-production, testing, or continuous integration/continuous
25
+ deployment (CI/CD) environment supporting or intended to support the
26
+ foregoing, or (e) provides network access to or otherwise directly
27
+ supports systems that meet criteria (a)–(d).
28
+
29
+ 1.5 "Personal Use" means use solely by a natural person on systems that
30
+ person personally owns or controls, exclusively for that individual's
31
+ own non-commercial, non-professional purposes, and not (a) on behalf of
32
+ or for the benefit of any Organization, employer, or client; (b) in
33
+ connection with any consulting, contracting, or freelance activity;
34
+ or (c) to provide services or functionality to any other person or entity.
35
+ For the avoidance of doubt, any use that is conducted through, on behalf
36
+ of, or for the benefit of an Organization does not qualify as Personal
37
+ Use, regardless of whether the individual is the sole owner or operator
38
+ of that Organization.
39
+
40
+ 1.6 "Compete" means to develop, market, or operate a commercial product or
41
+ service that provides functionality substantially similar to the core
42
+ functionality of the Software, including but not limited to zero-trust
43
+ network access (ZTNA). This includes using, analyzing, or benchmarking
44
+ the Software for the purpose of developing such a product or service,
45
+ whether or not the resulting product contains any code derived from
46
+ the Software.
47
+
48
+ 1.7 "Modification" means any work, including source code, patches, bug fixes,
49
+ improvements, or derivative works, that is based on or derived from the
50
+ Software or that modifies any file of the Software.
51
+
52
+ 1.8 "Organization" means any legal entity, including without limitation
53
+ corporations, partnerships, non-profits, sole proprietorships, and
54
+ any other form of business, government, or professional enterprise.
55
+
56
+ 1.9 Commercial Agreement Supersession. If you or your Organization have
57
+ entered into a Commercial Agreement with Licensor covering the Software,
58
+ the terms of that Commercial Agreement shall govern your use of the
59
+ Software and supersede this License to the extent of any conflict.
60
+
61
+ 2. LICENSE GRANT — PERSONAL USE
62
+
63
+ Subject to your compliance with this License, Licensor grants natural persons
64
+ a perpetual, limited, non-exclusive, non-transferable, non-sublicensable,
65
+ revocable license to:
66
+
67
+ (a) access, reproduce, and modify the Software solely to create Modifications
68
+ for Personal Use; and
69
+ (b) run the Software and Modifications on systems you personally own or
70
+ control;
71
+
72
+ solely for Personal Use as defined in Section 1.5. This grant does not
73
+ expire provided your use remains within the Personal Use definition.
74
+ If your use at any point exceeds Personal Use, this Section 2 grant
75
+ terminates immediately and Section 3 (or a Commercial Agreement) governs.
76
+
77
+ For the avoidance of doubt, any Modification you create under this Section
78
+ remains subject to this License in its entirety. You may not exercise any
79
+ rights in your Modification beyond those granted in this Section 2.
80
+
81
+ 3. LICENSE GRANT — ORGANIZATIONAL EVALUATION
82
+
83
+ Subject to your compliance with this License, Licensor grants Organizations
84
+ a limited, non-exclusive, non-transferable, non-sublicensable, revocable
85
+ license to:
86
+
87
+ (a) access, reproduce, and modify the Software solely to create Modifications
88
+ for internal evaluation purposes; and
89
+ (b) run the Software and Modifications on systems you own or control;
90
+
91
+ solely for internal, non-production evaluation, testing, and proof-of-concept
92
+ purposes within your Organization.
93
+
94
+ For the avoidance of doubt, any Modification you create under this Section
95
+ remains subject to this License in its entirety. You may not exercise any
96
+ rights in your Modification beyond those granted in this Section 3.
97
+
98
+ 4. RESTRICTIONS
99
+
100
+ Unless you have a valid Commercial Agreement with Licensor expressly
101
+ permitting the activity, you shall not:
102
+
103
+ 4.1 Production and Commercial Use. Deploy or use the Software or any
104
+ Modification in a Production Environment, in connection with a commercial
105
+ offering, or to generate revenue directly or indirectly.
106
+
107
+ 4.2 External Provision. Make the Software's or any Modification's
108
+ functionality available to any third party, including without limitation
109
+ through a hosted service, software-as-a-service offering, API, or managed
110
+ service, regardless of whether any copy of the Software or Modification
111
+ is distributed or transferred.
112
+
113
+ 4.3 Competitive Use. Use the Software or any Modification, in whole or in
114
+ part, to Compete with Licensor or to assist any third party in competing
115
+ with Licensor.
116
+
117
+ 4.4 Distribution. Copy, distribute, publish, transmit, or make the Software
118
+ or any Modification available to any third party. For clarity, this
119
+ prohibits hosting the Software or any Modification in a public repository
120
+ (e.g., a public GitHub fork), though hosting in a strictly private
121
+ repository accessible only to individuals authorized under this License
122
+ for Personal Use or internal Organizational evaluation is permitted.
123
+
124
+ 4.5 Bypass of License Controls. Remove, alter, or obscure any copyright
125
+ notice, license notice, or other proprietary marking in the Software
126
+ or any Modification.
127
+
128
+ 4.6 Transfer. Assign, sublicense, sell, rent, lease, or otherwise transfer
129
+ rights in the Software or any Modification without Licensor's prior
130
+ written consent.
131
+
132
+ For the avoidance of doubt, the restrictions in this Section 4 apply to
133
+ Personal Use licensees to the extent not inconsistent with Section 2.
134
+ Personal Use does not permit any activity listed in Sections 4.1 through 4.6.
135
+
136
+ 5. MODIFICATIONS — OWNERSHIP AND LICENSE-BACK
137
+
138
+ 5.1 Your Ownership. As between you and Licensor, you retain copyright
139
+ ownership of the original creative expression in any Modification you
140
+ author, subject to Licensor's underlying ownership of the Software from
141
+ which the Modification is derived.
142
+
143
+ 5.2 License-Back to Licensor. By creating any Modification, you hereby
144
+ grant Licensor a perpetual, irrevocable, worldwide, royalty-free,
145
+ fully paid-up, transferable, sublicensable license under all of your
146
+ intellectual property rights (including copyright and patent rights)
147
+ to use, reproduce, prepare derivative works of, distribute, perform,
148
+ display, and otherwise exploit such Modification in any form and for
149
+ any purpose, including without limitation incorporation into Licensor's
150
+ products and services, without any obligation of attribution,
151
+ compensation, or consent.
152
+
153
+ 5.3 Moral Rights Waiver. To the extent permitted by applicable law, you
154
+ hereby irrevocably waive any moral rights or rights of attribution in
155
+ any Modification you create.
156
+
157
+ 5.4 Contributor License Agreement. If you wish to formally submit a
158
+ Modification to Licensor for potential inclusion in the Software,
159
+ you must first execute Licensor's Contributor License Agreement
160
+ ("CLA"), available at https://octelium.com/cla. Submissions made without
161
+ executing the CLA will not be considered. The license-back in
162
+ Section 5.2 applies regardless of whether a CLA is executed and
163
+ regardless of whether a Modification is formally submitted.
164
+
165
+ 5.5 Representation. By creating a Modification, you represent that:
166
+ (a) you are the sole author of the Modification or have the right
167
+ to grant the license in Section 5.2; (b) the Modification does not
168
+ infringe the intellectual property rights of any third party; and
169
+ (c) if you created the Modification in the course of employment or
170
+ under contract, you have obtained all necessary permissions from
171
+ your employer or client to grant the rights in Section 5.2.
172
+
173
+ 6. OWNERSHIP AND RESERVATION OF RIGHTS
174
+
175
+ The Software is proprietary to Licensor. All right, title, and interest in
176
+ and to the Software, including all patent rights, copyright rights, trade
177
+ secret rights, and other intellectual property rights, are and shall remain
178
+ the exclusive property of Licensor. No rights are granted to you except as
179
+ expressly stated in Sections 2 and 3. All rights not expressly granted are
180
+ reserved by Licensor.
181
+
182
+ 7. FEEDBACK
183
+
184
+ If you provide Licensor with suggestions, ideas, bug reports, or other
185
+ feedback regarding the Software that does not constitute a Modification
186
+ ("Feedback"), you hereby grant Licensor a perpetual, irrevocable,
187
+ worldwide, royalty-free license to use, reproduce, modify, and incorporate
188
+ such Feedback into its products and services without any obligation to you.
189
+ You retain ownership of your Feedback, but Licensor may use it without
190
+ restriction or compensation. Feedback that constitutes a Modification is
191
+ governed by Section 5, not this Section 7.
192
+
193
+ 8. TERMINATION
194
+
195
+ 8.1 Automatic Termination. This License terminates automatically, without
196
+ notice, upon your breach of any provision of this License.
197
+
198
+ 8.2 Effect of Termination. Upon termination: (a) all rights granted
199
+ hereunder cease immediately; (b) you must promptly destroy or return
200
+ all copies of the Software and all Modifications in your possession
201
+ or control; and (c) you must certify such destruction in writing
202
+ upon Licensor's request.
203
+
204
+ 8.3 Survival. Sections 5, 6, 7, 8.2, 9, 10, and 11 survive termination.
205
+
206
+ 9. DISCLAIMER OF WARRANTIES
207
+
208
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
209
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
210
+ FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. TO THE MAXIMUM
211
+ EXTENT PERMITTED BY APPLICABLE LAW, OCTELIUM LABS, LLC FURTHER DISCLAIMS
212
+ ALL STATUTORY WARRANTIES. IN NO EVENT SHALL OCTELIUM LABS, LLC OR ITS
213
+ CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY,
214
+ WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM,
215
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
216
+ IN THE SOFTWARE.
217
+
218
+ 10. LIMITATION OF LIABILITY
219
+
220
+ TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
221
+ OCTELIUM LABS, LLC BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
222
+ EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL DAMAGES (INCLUDING LOSS OF PROFITS,
223
+ LOSS OF DATA, LOSS OF GOODWILL, BUSINESS INTERRUPTION, OR COST OF
224
+ SUBSTITUTE GOODS OR SERVICES), HOWEVER CAUSED AND UNDER ANY THEORY OF
225
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, TORT, OR OTHERWISE,
226
+ ARISING OUT OF OR RELATING TO THIS LICENSE OR THE SOFTWARE, EVEN IF
227
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. OCTELIUM LABS, LLC'S TOTAL
228
+ CUMULATIVE LIABILITY ARISING OUT OF OR RELATING TO THIS LICENSE SHALL
229
+ NOT EXCEED ONE HUNDRED U.S. DOLLARS ($100.00). THE FOREGOING LIMITATIONS
230
+ SHALL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, REGARDLESS
231
+ OF WHETHER LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES,
232
+ BUT SHALL NOT APPLY TO DAMAGES CAUSED BY LICENSOR'S GROSS NEGLIGENCE OR
233
+ WILLFUL MISCONDUCT.
234
+
235
+ 11. GENERAL
236
+
237
+ 11.1 Governing Law. This License is governed by the laws of the State of
238
+ Delaware, excluding its conflict-of-law rules.
239
+
240
+ 11.2 Jurisdiction. Each party irrevocably submits to the exclusive
241
+ jurisdiction of the state and federal courts located in Wilmington,
242
+ Delaware for resolution of any dispute arising out of this License.
243
+
244
+ 11.3 Export Compliance. You agree to comply with all applicable export
245
+ control laws and regulations in connection with your use of the Software.
246
+
247
+ 11.4 Entire Agreement. This License constitutes the entire agreement between
248
+ you and Licensor with respect to evaluation and personal use of the
249
+ Software and supersedes all prior agreements on that subject.
250
+
251
+ 11.5 Severability. If any provision of this License is found unenforceable,
252
+ that provision shall be modified to the minimum extent necessary to make
253
+ it enforceable, and the remainder of the License shall continue in
254
+ full force.
255
+
256
+ 11.6 Waiver. Licensor's failure to enforce any provision of this License
257
+ shall not constitute a waiver of its right to do so in the future.
258
+
259
+ 11.7 Amendment. Licensor may update this License for future versions of the
260
+ Software. Your continued use of a version after a license update does
261
+ not bind you to the updated terms for that version.
262
+
263
+ THIRD-PARTY COMPONENTS
264
+
265
+ Certain components of the Software are subject to third-party licenses identified
266
+ in the NOTICES file or within the relevant source files. Such third-party licenses
267
+ govern those components and are not superseded by this License.
package/README.md ADDED
@@ -0,0 +1,207 @@
1
+ # @octelium/console-agent
2
+
3
+ The AI agent behind the chat of the Octelium web console. It runs as an ordinary process inside a Cordium Workspace, uses the Workspace's own Octelium identity and exposes an HTTP/JSON + SSE API that is served as the Workspace's default Application.
4
+
5
+ ```text
6
+ Web console (chat UI)
7
+ │ HTTP/JSON + SSE (via the Cordium portal, authenticated as the Workspace owner)
8
+ ▼
9
+ octelium-console-agent ───────────── Cordium Workspace ──────────────────────────────
10
+ ├─ Pi (agent loop, sessions, compaction, retries, skills)
11
+ ├─ tools
12
+ │ ├─ octelium_api_search / octelium_api_describe / octelium_api_call
13
+ │ │ └─ gRPC over OCTELIUM_AUTH_PROXY_SOCKET (h2c) ──► Octelium APIs
14
+ │ ├─ present_table / present_chart / present_resources / publish_artifact
15
+ │ ├─ read / bash / edit / write / grep / find / ls (the Workspace is the agent's computer)
16
+ │ └─ web_fetch / web_search
17
+ └─ LLM ──► Octelium LLM Service (via `octelium connect`), or any Pi provider
18
+ ```
19
+
20
+ ## Design
21
+
22
+ - **Execution.** The agent is a Node.js process inside the Workspace. Everything that the agent does (shell commands, `octelium`/`octeliumctl`, `psql`, `curl`, `kubectl`, scripts) runs with the Workspace's network and filesystem, so the protected Services are reachable by name through the Workspace's `octelium connect`.
23
+ - **Identity.** The Octelium APIs are called through the supervisor's auth proxy socket (`OCTELIUM_AUTH_PROXY_SOCKET`), exactly like the `octelium` CLI does inside a Workspace. Every call is authorized server-side by the Cluster's Policies for the Workspace owner. The model never sees a credential.
24
+ - **API discovery.** The agent embeds a protobuf descriptor set of the Octelium APIs (`apis/octelium.binpb`, generated from the `.proto` files with their doc comments). It powers a BM25 search over ~350 methods, schema rendering with the field documentation, and dynamic invocation: the model sends proto3 JSON, the agent validates it against the descriptors (unknown fields and wrong types are rejected with precise errors), encodes it and calls the method over gRPC. A model can only call a method that exists in the catalog. A compact index of all the methods is part of the system prompt so that common calls need no search.
25
+ - **Approvals.** Methods are classified by risk (`read`, `write`, `destructive`, `sensitive`). Depending on `approvals.octeliumAPI`, non-read calls pause until the User approves them in the UI (and shell commands too if `approvals.bash` is set). Approvals are a UX safety net, not the security boundary: authorization is always enforced by the Cluster.
26
+ - **Model.** By default the model is served by an Octelium LLM Service (`llm.provider: "octelium"`), reached through `octelium connect`, so no provider secret is stored in the Workspace. Any provider supported by Pi (e.g. `anthropic`, `openai`, `google`, `openrouter`) or any compatible endpoint (`custom`) can be used instead.
27
+ - **Backend abstraction.** The HTTP protocol knows nothing about Pi: runs go through the `AgentBackend` interface (`src/agent/types.ts`), so other harnesses (e.g. Codex or Claude as delegated sub-agents) can be added without changing the protocol.
28
+ - **Persistence.** Conversations, finalized messages, Pi sessions, uploads and artifacts are stored in the data directory. An in-flight message is checkpointed and recovered as `interrupted` if the process dies. Restarting the agent resumes the conversations with their full context.
29
+
30
+ ## Running inside a Cordium Workspace
31
+
32
+ The enterprise `AgentService` (`octelium.api.main.enterprise.v1.AgentService`) provisions the agent of every User on demand: `InitializeAgent` creates the User's personal `octelium.<user>` Cordium Space, its `default` Template and a primary Workspace that serves the agent as its default Application on port `8080`. The Template installs Node.js upon the first start of a Workspace if the image lacks it (`ON_CREATE`) and starts `npx --yes --prefer-online @octelium/console-agent@<version> serve` on every start (`POST_START`). Development builds use their Git branch as the npm tag, falling back to `dev` when build branch metadata is absent. Production uses the Go build's semver, removing a leading `v`, and falls back to `latest` when no valid semver is available. The Template is generated from the `spec.agent` section of the enterprise ClusterConfig:
33
+
34
+ | Field | Description |
35
+ | --- | --- |
36
+ | `isDisabled` | Disables the `AgentService` |
37
+ | `llm.service`, `llm.model` | The default LLM Service and model (i.e. `llm.service` and `llm.model` below) |
38
+ | `version` | Development override for the `@octelium/console-agent` npm tag or version; production uses the Go build's semver or `latest` |
39
+ | `image`, `limit` | The Workspace image and compute resources |
40
+ | `config` | Any additional configuration (same structure as `config.json`), passed via `OCTELIUM_CONSOLE_AGENT_CONFIG_JSON` |
41
+
42
+ The Workspaces themselves are started, stopped, watched and deleted via the Cordium `MainService` (the web console does so from its `/agent` page). The agent can also run in any other Workspace whose image has Node.js 22.19+ and `git`, for example with such a Template:
43
+
44
+ ```yaml
45
+ spec:
46
+ runtime:
47
+ envVars:
48
+ - key: OCTELIUM_CONSOLE_AGENT_CONFIG_JSON
49
+ value: '{"llm":{"service":"llm.default","model":"gpt-5.1"}}'
50
+ tasks:
51
+ - name: console-agent
52
+ type: POST_START
53
+ isBackground: true
54
+ run: npx --yes --prefer-online @octelium/console-agent@latest serve
55
+ applications:
56
+ - name: agent
57
+ displayName: Octelium Agent
58
+ port: 8080
59
+ isDefault: true
60
+ ```
61
+
62
+ `npx … doctor` checks the configuration, the Octelium API access and the LLM access.
63
+
64
+ `make build-apiserver` embeds the current Git branch and release tag in the API server. Production checks the build's `SemVer` first, then its `GitTag`, and uses `latest` if neither contains a valid semver. The Cluster's usual development/production detection selects the agent version; `OCTELIUM_DEV=true` forces development and `OCTELIUM_PRODUCTION=true` forces production. The npm tag or version must already be published. Branches outside `main`, `dev` and `b-*` can be published manually with their branch name as the npm tag, or use `spec.agent.version: dev` during development.
65
+
66
+ The `--prefer-online` flag checks for tag updates at every Workspace start. After changing the Cluster's agent configuration or upgrading from the fixed-version launcher, call `InitializeAgent` to reconcile its Template, then restart the Workspace to run the selected package version.
67
+
68
+ ## Configuration
69
+
70
+ The configuration is read, in increasing precedence, from the defaults, a JSON file (`--config`, `OCTELIUM_CONSOLE_AGENT_CONFIG` or `<dataDir>/config.json`), the `OCTELIUM_CONSOLE_AGENT_CONFIG_JSON` environment variable (convenient for Workspace env vars and Secrets) and the CLI flags. Unknown fields are rejected. See `config.example.json`.
71
+
72
+ | Field | Default | Description |
73
+ | --- | --- | --- |
74
+ | `dataDir` | `~/.octelium-console-agent` | Conversations, sessions, uploads, artifacts, skills |
75
+ | `workDir` | `/workspace` if it exists, else `$HOME` | The agent's working directory |
76
+ | `logLevel` | `info` | `debug`, `info`, `warn`, `error` |
77
+ | `server.host`, `server.port` | `0.0.0.0`, `8080` | Listen address (`8080` is the portal's default Application port) |
78
+ | `server.allowedOrigins` | `https://console.octelium.<domain>`, `https://$CORDIUM_HOSTNAME` | Accepted `Origin` headers (plus the request's own origin) |
79
+ | `server.cors` | `false` | Emit CORS headers. Keep it off when the Cluster ingress already handles CORS |
80
+ | `server.authToken` | | Optional bearer token (or `?access_token=`) required for `/v1/*` |
81
+ | `server.maxUploadBytes` | 100 MiB | Upload limit |
82
+ | `octelium.mode` | `auto` | `proxy` (auth proxy socket), `direct` (`OCTELIUM_DOMAIN` + `OCTELIUM_ACCESS_TOKEN`, for development), `disabled` |
83
+ | `octelium.domain` | `OCTELIUM_DOMAIN` | Cluster domain |
84
+ | `octelium.timeoutSeconds` | `30` | Per-call deadline |
85
+ | `llm.provider` | `octelium` | `octelium`, `custom` or any Pi provider ID |
86
+ | `llm.service` | | The LLM Service (`name` or `name.namespace`). Its URL is resolved via the User API |
87
+ | `llm.baseUrl` | | Overrides the endpoint (required for `custom`) |
88
+ | `llm.api` | `openai-completions` | Pi API of the endpoint, e.g. `openai-responses`, `anthropic-messages`, `google-generative-ai` |
89
+ | `llm.model` | | Model ID. Discovered from the endpoint's model list if unset (`octelium`/`custom`) |
90
+ | `llm.apiKey`, `llm.apiKeyEnv` | | Provider credentials. Not needed with an Octelium LLM Service |
91
+ | `llm.thinkingLevel` | `medium` | `off` … `max` |
92
+ | `llm.contextWindow`, `llm.maxTokens`, `llm.reasoning`, `llm.input` | from Pi's catalog | Model metadata for unknown model IDs |
93
+ | `llm.loginProviders` | `anthropic`, `openai` | The Pi providers that the Users can sign in to with their own subscriptions (Claude Pro/Max, ChatGPT) |
94
+ | `agent.tools` | all | Pi built-in tools: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls` (`grep`/`find` are dropped if `rg`/`fd` are missing) |
95
+ | `agent.systemPromptAppend` | | Extra instructions |
96
+ | `agent.loadContextFiles` | `false` | Load `AGENTS.md`-style files from the working directory |
97
+ | `agent.maxConcurrentRuns` | `4` | Across conversations |
98
+ | `agent.sessionIdleTimeoutSeconds` | `1800` | Idle Pi sessions are disposed (and transparently reopened) |
99
+ | `agent.compaction`, `agent.maxRetries` | `true`, `3` | Context compaction and LLM retries |
100
+ | `agent.generateTitles` | `true` | Generate conversation titles with the LLM |
101
+ | `approvals.octeliumAPI` | `write` | `never`, `destructive` or `write` (writes, deletions and sensitive calls) |
102
+ | `approvals.bash` | `false` | Require an approval for every shell command |
103
+ | `skills.repositories` | `octelium/octelium-skills@main` | Agent Skills repositories, cloned/updated at startup (best effort) |
104
+ | `skills.paths` | | Local skill directories |
105
+ | `webSearch` | | `{"provider": "brave" \| "tavily" \| "searxng", "baseUrl", "apiKey" \| "apiKeyEnv"}`. `baseUrl` can point to an Octelium Service for secretless access |
106
+
107
+ ### Models and subscriptions
108
+
109
+ The model can be switched at runtime (`PUT /v1/model`). The selection is saved in `<dataDir>/settings.json` and takes precedence over `llm.*` as long as its provider stays configured.
110
+
111
+ A User can also sign in with their own Claude or ChatGPT subscription from the web console. The OAuth flows run inside the agent (`/v1/auth/logins`): the console shows the provider's sign-in link and then sends back what the provider shows after signing in (the code, or the URL of the page it redirected to, which never needs to load since it points to the Workspace's `localhost`). The tokens are stored and refreshed by Pi in `<dataDir>/pi/auth.json` inside the Workspace and never leave it. Once signed in, the agent switches to the provider's default model.
112
+
113
+ ## HTTP API
114
+
115
+ All the types are exported from `@octelium/console-agent/protocol` (`src/protocol/index.ts`), which has no runtime dependencies and is meant to be imported by the web console.
116
+
117
+ | Method | Path | Description |
118
+ | --- | --- | --- |
119
+ | `GET` | `/healthz` | Liveness |
120
+ | `GET` | `/v1/info` | Version, protocol version, model, identity, capabilities, issues |
121
+ | `GET` | `/v1/conversations` | List the conversations |
122
+ | `POST` | `/v1/conversations` | Create a conversation, optionally starting a run: `{"title"?, "input"?: {"text", "attachments"?}}` |
123
+ | `GET` | `/v1/conversations/{id}` | The conversation, its messages and the snapshot of its active run |
124
+ | `PATCH` | `/v1/conversations/{id}` | Rename: `{"title"}` |
125
+ | `DELETE` | `/v1/conversations/{id}` | Cancel its run and delete it |
126
+ | `POST` | `/v1/conversations/{id}/runs` | Start a run: `{"input": {"text", "attachments"?}}` (`409` if a run is active) |
127
+ | `GET` | `/v1/runs/{id}` | Run snapshot (run + in-progress assistant message) |
128
+ | `GET` | `/v1/runs/{id}/events` | SSE stream of the run's events |
129
+ | `POST` | `/v1/runs/{id}/cancel` | Cancel the run |
130
+ | `POST` | `/v1/runs/{id}/approvals/{approvalId}` | `{"decision": "approve" \| "reject", "reason"?}` |
131
+ | `POST` | `/v1/files?name=<file name>` | Upload a file (raw body). Returns a `FileInfo` whose `id` can be attached to a run |
132
+ | `GET` | `/v1/artifacts/{id}` | Artifact metadata |
133
+ | `GET` | `/v1/artifacts/{id}/content` | Download an artifact (`attachment`, sandboxed CSP; `?inline=1` for safe types) |
134
+ | `GET` | `/v1/models` | The current model, the thinking level and the available models |
135
+ | `PUT` | `/v1/model` | Switch the model: `{"provider", "id", "thinkingLevel"?}` |
136
+ | `GET` | `/v1/auth/providers` | The subscription providers and whether they are signed in |
137
+ | `DELETE` | `/v1/auth/providers/{id}` | Sign out |
138
+ | `POST` | `/v1/auth/logins` | Start signing in: `{"provider", "selectModel"?}`. Returns a `LoginSession` |
139
+ | `GET` | `/v1/auth/logins/{id}` | Poll a `LoginSession` (`events` such as `auth_url`, the pending `prompt`, `status`) |
140
+ | `POST` | `/v1/auth/logins/{id}/prompts/{promptId}` | Answer the pending prompt: `{"value"}` |
141
+ | `DELETE` | `/v1/auth/logins/{id}` | Cancel signing in |
142
+
143
+ Errors are `{"error": {"code", "message"}}`. `POST`/`PUT`/`PATCH` bodies must be `application/json`.
144
+
145
+ ### Messages and blocks
146
+
147
+ A run appends one user message and one assistant message to the conversation. A message is an ordered list of typed blocks:
148
+
149
+ | Block | Content |
150
+ | --- | --- |
151
+ | `markdown` | GitHub-flavored Markdown (streamed). Resources are linked as `octelium://resource/<apiVersion>/<Kind>/<name>` (see `formatResourceURI`/`parseResourceURI`) |
152
+ | `thinking` | The model's reasoning (streamed), possibly `redacted` |
153
+ | `tool` | A tool call: `name`, human `title`, `status` (`pending`, `running`, `awaiting_approval`, `completed`, `failed`, `rejected`, `cancelled`), `input`, truncated `output` and structured `details` (`octelium_api` with the method, risk, request, response and the referenced resources; `command`; `file` with diffs) |
154
+ | `approval` | A pending/decided approval with its risk and a preview of the request or command |
155
+ | `table` | Columns (with types and units) and rows |
156
+ | `chart` | `line`, `area`, `bar`, `pie` or `scatter` with an x key, series and rows |
157
+ | `resources` | Resource references with their console URIs and, when known, a snapshot |
158
+ | `artifact` | A downloadable file published by the agent |
159
+ | `notice`, `error` | Informational notices (e.g. context compaction) and errors |
160
+
161
+ Clients must ignore unknown block types and unknown fields, which is how new block types are added without breaking older consoles. `PROTOCOL_VERSION` is bumped for incompatible changes only.
162
+
163
+ ### Events
164
+
165
+ `GET /v1/runs/{id}/events` streams `AgentEvent`s as SSE (`id` is the event's `seq`, `event` its `type`). The events of a run are replayed from the start, or after `Last-Event-ID` / `?after=<seq>`, so a client can reconnect or attach to a run in progress after loading `GET /v1/conversations/{id}`. The stream ends after a terminal run event; a finished run with nothing left to replay returns `204`, which stops `EventSource` from reconnecting.
166
+
167
+ | Event | Payload |
168
+ | --- | --- |
169
+ | `run.started`, `run.updated`, `run.completed`, `run.failed`, `run.cancelled` | `run` (status, `activity` such as retrying/compacting, usage, error) |
170
+ | `message.created`, `message.completed` | `message` (the completed message is authoritative) |
171
+ | `block.created`, `block.updated` | `messageId`, `block` (full block) |
172
+ | `block.delta` | `messageId`, `blockId`, `text` to append to a `markdown`/`thinking` block |
173
+ | `conversation.updated` | `conversation` (e.g. its generated title) |
174
+
175
+ ## Requirements on the Cluster side
176
+
177
+ - The Workspace owner must be authorized to access the LLM Service, which is reached through the Workspace's `octelium connect`.
178
+ - The web console calls the agent at the Workspace's hostname through the Cordium portal. Since that is a different origin than the console's, the portal Service allows exactly the console's origin (`https://console.octelium.<domain>`) with credentials. `allowClusterServices` is deliberately not used since it would let any Workspace Application in the Cluster read the agents of other Users.
179
+ - Do not share the agent's Application with other Users: the agent acts with the Workspace owner's identity.
180
+
181
+ ## Publishing
182
+
183
+ `.github/workflows/publish-console-agent.yaml` publishes the package using npm trusted publishing (GitHub OIDC). Configure the package's trusted publisher on npmjs.com with GitHub organization `octelium`, repository `octelium-ee`, workflow filename `publish-console-agent.yaml`, no environment, and permission to run `npm publish`. No npm token secret is required.
184
+
185
+ Every push to `main`, `dev` or `b-*` publishes a unique prerelease under the branch's npm dist-tag. For example, workflow run `123`, attempt `1`, on `dev` publishes `0.1.0-dev.123.1` as `@octelium/console-agent@dev`. The base version comes from `package.json`; retries receive a new version because npm versions cannot be overwritten.
186
+
187
+ Pushing a `v*.*.*` Git tag or publishing a GitHub release publishes the tag's semver, removing the leading `v`. Stable releases use `latest`; semver prereleases and GitHub prereleases use `next`. Tag pushes also cover releases created by the repository's release workflow using `GITHUB_TOKEN`. Automatic runs skip versions already published by another event or an earlier run.
188
+
189
+ To publish manually, run the workflow from GitHub Actions, select the branch or Git tag and supply the npm `tag`. An optional `version` sets an explicit semver. Without it, a selected Git tag supplies the version, while a selected branch produces a unique prerelease containing the manual npm tag. An explicit version must not already exist on npm.
190
+
191
+ Run `npm run test:publish` to check publishing version resolution.
192
+
193
+ ## Development
194
+
195
+ ```bash
196
+ npm ci
197
+ npm test # node:test, no network needed (faux LLM + mock gRPC server)
198
+ npm run typecheck
199
+ npm run build # dist/
200
+ npm run dev # node src/cli.ts serve
201
+ node src/cli.ts api search "workspace snapshot"
202
+ node src/cli.ts api describe core.v1.MainService/CreateService
203
+ ```
204
+
205
+ Outside a Workspace, set `OCTELIUM_DOMAIN` and `OCTELIUM_ACCESS_TOKEN` to use the direct mode.
206
+
207
+ `apis/octelium.binpb` is regenerated by `make gen-api` (or `make gen-api-console-agent` after `make cp-pb`).
Binary file
@@ -0,0 +1,32 @@
1
+ import type { AuthEvent } from "@earendil-works/pi-ai";
2
+ import type { ModelRuntime } from "@earendil-works/pi-coding-agent";
3
+ import type { Logger } from "../../log.ts";
4
+ import type { AuthProvider, LoginEvent, LoginSession, ModelInfo, StartLoginRequest } from "../../protocol/index.ts";
5
+ import type { AuthController } from "../types.ts";
6
+ export interface AuthManagerOptions {
7
+ modelRuntime: ModelRuntime;
8
+ dataDir: string;
9
+ logger: Logger;
10
+ providers: string[];
11
+ onLogin?(provider: string, selectModel: boolean): Promise<ModelInfo | undefined>;
12
+ onLogout?(provider: string): Promise<void>;
13
+ }
14
+ export declare const toLoginEvent: (event: AuthEvent) => LoginEvent;
15
+ export declare class AuthManager implements AuthController {
16
+ private opts;
17
+ private providers;
18
+ private logins;
19
+ constructor(opts: AuthManagerOptions);
20
+ getDeviceId(): string;
21
+ listProviders(): Promise<AuthProvider[]>;
22
+ startLogin(req: StartLoginRequest): LoginSession;
23
+ getLogin(id: string): LoginSession | undefined;
24
+ answerLogin(id: string, promptId: string, value: string): LoginSession;
25
+ cancelLogin(id: string): LoginSession;
26
+ logout(provider: string): Promise<void>;
27
+ dispose(): void;
28
+ private touch;
29
+ private expire;
30
+ private runLogin;
31
+ private prompt;
32
+ }