clilinkapi 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 +161 -0
- package/clilinkapi.example.json +12 -0
- package/dist/src/auth.js +9 -0
- package/dist/src/cli.js +229 -0
- package/dist/src/config.js +98 -0
- package/dist/src/errors.js +24 -0
- package/dist/src/permissions.js +64 -0
- package/dist/src/providers/codex.js +201 -0
- package/dist/src/providers/registry.js +3 -0
- package/dist/src/providers/rpc.js +171 -0
- package/dist/src/providers/runtime.js +98 -0
- package/dist/src/providers/types.js +2 -0
- package/dist/src/redaction.js +37 -0
- package/dist/src/requests.js +76 -0
- package/dist/src/sandbox.js +63 -0
- package/dist/src/server.js +164 -0
- package/dist/src/sessions.js +19 -0
- package/dist/src/startup.js +46 -0
- package/dist/src/tool-sessions.js +54 -0
- package/docs/architecture.md +13 -0
- package/docs/configuration.md +463 -0
- package/docs/n8n.md +43 -0
- package/docs/security.md +32 -0
- package/docs/verification.md +28 -0
- package/examples/client.mjs +13 -0
- package/package.json +22 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
# CliLinkAPI configuration guide
|
|
2
|
+
|
|
3
|
+
This guide describes the configuration accepted by the current application. Commands run from the CliLinkAPI repository unless stated otherwise.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- [First-time setup](#first-time-setup)
|
|
8
|
+
- [Complete configuration template](#complete-configuration-template)
|
|
9
|
+
- [Settings reference](#settings-reference)
|
|
10
|
+
- [Workspace selection and paths](#workspace-selection-and-paths)
|
|
11
|
+
- [Project skills and symbolic links](#project-skills-and-symbolic-links)
|
|
12
|
+
- [Windows execution mode](#windows-execution-mode)
|
|
13
|
+
- [Local and network access](#local-and-network-access)
|
|
14
|
+
- [Configure n8n](#configure-n8n)
|
|
15
|
+
- [Verify the connection](#verify-the-connection)
|
|
16
|
+
- [Maintenance commands](#maintenance-commands)
|
|
17
|
+
- [Troubleshooting](#troubleshooting)
|
|
18
|
+
|
|
19
|
+
## First-time setup
|
|
20
|
+
|
|
21
|
+
CliLinkAPI uses two different credentials:
|
|
22
|
+
|
|
23
|
+
| Credential | Purpose | How to configure it |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| CliLinkAPI API key | Authenticates n8n and other HTTP clients to this gateway | Generated by `setup`; stored in `auth.apiKey` |
|
|
26
|
+
| Codex ChatGPT sign-in | Authenticates the gateway's Codex runtime | Run `login` using the dedicated Codex home |
|
|
27
|
+
|
|
28
|
+
An OpenAI API key is not a replacement for either step. A desktop Codex login is not automatically shared with the dedicated service home.
|
|
29
|
+
|
|
30
|
+
### 1. Install dependencies
|
|
31
|
+
|
|
32
|
+
Use Node.js 22 or newer, then run:
|
|
33
|
+
|
|
34
|
+
```powershell
|
|
35
|
+
npm ci
|
|
36
|
+
npm run build
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The repository pins the official Codex runtime to version `0.155.0`. A global Codex installation is not needed.
|
|
40
|
+
|
|
41
|
+
To register the standalone `clilinkapi` command, run once from this repository after building:
|
|
42
|
+
|
|
43
|
+
```powershell
|
|
44
|
+
npm.cmd link
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
You can then run these commands from any directory:
|
|
48
|
+
|
|
49
|
+
```powershell
|
|
50
|
+
clilinkapi serve
|
|
51
|
+
clilinkapi serve "C:/WORKSPACE/CliLinkAPI/workspaces/clilinkapi.json"
|
|
52
|
+
clilinkapi doctor
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Use `clilinkapi serve`, without npm's `--` separator. Running `clilinkapi` alone displays help. Omitting the configuration path uses the runtime user's `~/.clilinkapi/clilinkapi.json`; it does not search the current directory. All commands shown below as `npm run clilinkapi -- COMMAND` can also be run as `clilinkapi COMMAND`.
|
|
56
|
+
|
|
57
|
+
This is a Node.js CLI, so Node.js must remain installed. `npm link` points to this checkout: keep its path, dependencies, and compiled `dist` files available, and rebuild with `npm run build` after source changes. If PowerShell blocks the generated script, use `clilinkapi.cmd`. If the command is not found, ensure the directory reported by `npm prefix -g` is on your Windows `PATH`, then reopen the terminal. On Linux/macOS, use `npm link`; the command is installed under the global prefix's `bin` directory.
|
|
58
|
+
|
|
59
|
+
### 2. Prepare workspace folders and a template
|
|
60
|
+
|
|
61
|
+
Create the folders that the agent may use. For example, on Windows:
|
|
62
|
+
|
|
63
|
+
```powershell
|
|
64
|
+
New-Item -ItemType Directory -Force -Path C:/Projects/project-a
|
|
65
|
+
New-Item -ItemType Directory -Force -Path C:/Documents/reference
|
|
66
|
+
Copy-Item ./clilinkapi.example.json ./clilinkapi.setup.json
|
|
67
|
+
notepad ./clilinkapi.setup.json
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Edit the template's username and paths. Keep only workspaces you need. The template contains a placeholder key; `setup` replaces it with a securely generated key. Do not put a real key into this repository template.
|
|
71
|
+
|
|
72
|
+
### 3. Create the private configuration
|
|
73
|
+
|
|
74
|
+
```powershell
|
|
75
|
+
npm run clilinkapi -- setup "~/.clilinkapi/clilinkapi.json" ./clilinkapi.setup.json
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Setup creates private configuration and Codex-home directories, generates a key, and checks workspace boundaries. It never overwrites an existing configuration. If you already have a configuration, edit it instead of running setup again.
|
|
79
|
+
|
|
80
|
+
The default configuration location is the runtime user's home directory plus `.clilinkapi/clilinkapi.json`, for example:
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
C:/Users/geron/.clilinkapi/clilinkapi.json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Run setup, login, and serve under the same OS account. Configuration permissions are checked at startup.
|
|
87
|
+
|
|
88
|
+
### 4. Sign in and check the runtime
|
|
89
|
+
|
|
90
|
+
```powershell
|
|
91
|
+
npm run clilinkapi -- login "~/.clilinkapi/clilinkapi.json"
|
|
92
|
+
npm run clilinkapi -- doctor "~/.clilinkapi/clilinkapi.json"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Follow the official ChatGPT sign-in flow. If browser login is unavailable and your account supports device authentication:
|
|
96
|
+
|
|
97
|
+
```powershell
|
|
98
|
+
npm run clilinkapi -- login "~/.clilinkapi/clilinkapi.json" --device-auth
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`doctor` checks platform eligibility and authenticated model discovery. It does not establish that a real generation or every sandbox operation will succeed.
|
|
102
|
+
|
|
103
|
+
### 5. Start the server
|
|
104
|
+
|
|
105
|
+
```powershell
|
|
106
|
+
npm run clilinkapi -- serve "~/.clilinkapi/clilinkapi.json"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The banner shows the actual listening address, port, hostname, process ID, URLs, endpoints, and request settings. `LISTENING` means the HTTP server started; it is not a successful generation test. Stop with Ctrl+C.
|
|
110
|
+
|
|
111
|
+
For compiled execution after `npm run build`:
|
|
112
|
+
|
|
113
|
+
```powershell
|
|
114
|
+
npm start -- "~/.clilinkapi/clilinkapi.json"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
These CLI commands also work in a native Linux/macOS shell. Use native absolute JSON paths, such as `/home/service/.clilinkapi/codex` or `/Users/service/.clilinkapi/codex`, and existing workspace folders on that host. Linux/macOS generation still requires passing native isolation probes; see the [platform prerequisites](../README.md#install-natively).
|
|
118
|
+
|
|
119
|
+
## Complete configuration template
|
|
120
|
+
|
|
121
|
+
This is a setup template, not a ready-to-serve credential file. Replace `YOUR_USER` and workspace paths before running `setup`. When editing an existing private file, preserve its actual `auth.apiKey` instead of replacing it with this placeholder.
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"server": {
|
|
126
|
+
"host": "127.0.0.1",
|
|
127
|
+
"port": 3000,
|
|
128
|
+
"timeoutMs": 180000,
|
|
129
|
+
"maxConcurrency": 2,
|
|
130
|
+
"maxBodyBytes": 262144
|
|
131
|
+
},
|
|
132
|
+
"auth": {
|
|
133
|
+
"apiKey": "REPLACE_WITH_A_SECURE_RANDOM_KEY"
|
|
134
|
+
},
|
|
135
|
+
"compatibility": {
|
|
136
|
+
"defaultWorkspace": "project-a",
|
|
137
|
+
"toolTimeoutMs": 300000,
|
|
138
|
+
"maxPendingTools": 8
|
|
139
|
+
},
|
|
140
|
+
"provider": {
|
|
141
|
+
"type": "codex",
|
|
142
|
+
"authentication": "chatgpt",
|
|
143
|
+
"codexHome": "C:/Users/YOUR_USER/.clilinkapi/codex",
|
|
144
|
+
"allowedModels": [],
|
|
145
|
+
"allowUnqualifiedWindowsExecution": true,
|
|
146
|
+
"allowProjectSkills": true,
|
|
147
|
+
"allowSymbolicLinks": true
|
|
148
|
+
},
|
|
149
|
+
"workspaces": {
|
|
150
|
+
"project-a": {
|
|
151
|
+
"path": "C:/Projects/project-a",
|
|
152
|
+
"access": "read-write"
|
|
153
|
+
},
|
|
154
|
+
"reference-docs": {
|
|
155
|
+
"path": "C:/Documents/reference",
|
|
156
|
+
"access": "read-only"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Use valid JSON: double-quoted keys and strings, no comments, no trailing commas. Windows paths can use forward slashes as above or escaped backslashes (`C:\\Projects\\project-a`). Unknown configuration fields are rejected. Defaults apply to omitted fields, not to `null`.
|
|
163
|
+
|
|
164
|
+
## Settings reference
|
|
165
|
+
|
|
166
|
+
### Server
|
|
167
|
+
|
|
168
|
+
The entire `server` object may be omitted to use its defaults.
|
|
169
|
+
|
|
170
|
+
| Setting | Default | Accepted values and behavior |
|
|
171
|
+
| --- | --- | --- |
|
|
172
|
+
| `server.host` | `127.0.0.1` | Nonempty bind address or resolvable hostname. Use `0.0.0.0` for all IPv4 interfaces. |
|
|
173
|
+
| `server.port` | `3000` | Integer from 1 to 65535. Must be available. |
|
|
174
|
+
| `server.timeoutMs` | `180000` | Integer from 1000 to 3600000; maximum request duration in milliseconds. Timeout cancels execution, but prior side effects are not rolled back. |
|
|
175
|
+
| `server.maxConcurrency` | `2` | Integer from 1 to 16. Limits generation requests; model discovery has a separate pool of the same size. A workspace permits one active generation at a time. |
|
|
176
|
+
| `server.maxBodyBytes` | `262144` | Integer from 1024 to 1048576. Maximum POST body size in bytes; default is 256 KiB. |
|
|
177
|
+
|
|
178
|
+
### Authentication
|
|
179
|
+
|
|
180
|
+
| Setting | Default | Accepted values and behavior |
|
|
181
|
+
| --- | --- | --- |
|
|
182
|
+
| `auth.apiKey` | Required | String of 43–256 characters, with at least 16 distinct characters. Common placeholder strings are rejected. Use `setup` or `rotate-key` to generate it. |
|
|
183
|
+
|
|
184
|
+
All endpoints require `Authorization: Bearer <key>`. One shared key grants access to all configured workspaces; workspace IDs are not separate user permissions. Never paste real keys into support messages, source control, or screenshots.
|
|
185
|
+
|
|
186
|
+
### Compatibility
|
|
187
|
+
|
|
188
|
+
The entire `compatibility` object may be omitted.
|
|
189
|
+
|
|
190
|
+
| Setting | Default | Accepted values and behavior |
|
|
191
|
+
| --- | --- | --- |
|
|
192
|
+
| `compatibility.defaultWorkspace` | Unset | Must exactly match a configured workspace ID. Used when a POST request has no `X-Workspace-ID` header. |
|
|
193
|
+
| `compatibility.toolTimeoutMs` | `300000` | Integer from 1000 to 1800000. How long an external tool continuation can wait for the client to return its result. |
|
|
194
|
+
| `compatibility.maxPendingTools` | `8` | Integer from 1 to 64. Maximum retained external tool continuations. |
|
|
195
|
+
|
|
196
|
+
An explicit workspace header overrides the default. An invalid header is rejected even when the default is valid. Pending tool continuations are held in memory and are lost on restart; they reserve their workspace until consumed or expired.
|
|
197
|
+
|
|
198
|
+
### Provider
|
|
199
|
+
|
|
200
|
+
| Setting | Default | Accepted values and behavior |
|
|
201
|
+
| --- | --- | --- |
|
|
202
|
+
| `provider.type` | Required | Must be `"codex"`. |
|
|
203
|
+
| `provider.authentication` | Required | Must be `"chatgpt"`. |
|
|
204
|
+
| `provider.codexHome` | Required | Absolute native path to dedicated, private Codex storage. Setup can create it; normal startup requires it to exist. |
|
|
205
|
+
| `provider.allowedModels` | `[]` | Exact model IDs to allow. An empty array exposes all visible models discovered from Codex. Nonempty IDs may contain letters, digits, `.`, `_`, and `-`. |
|
|
206
|
+
| `provider.defaultModel` | Unset | Exact model ID used when the request omits `model`. It must be present in the available, filtered catalog when used. |
|
|
207
|
+
| `provider.defaultReasoning` | Unset | Effort used when the request omits `reasoning_effort`. Must be supported by the chosen model. |
|
|
208
|
+
| `provider.allowUnqualifiedWindowsExecution` | `true` | Boolean. On Windows, permits execution attempts without qualification probes. Explicit `false` blocks Windows generation. Does not bypass Linux/macOS probes. |
|
|
209
|
+
| `provider.allowProjectSkills` | `true` | Boolean. Allows discovery and use of project skills. Set to `false` to explicitly disable skills found by the workspace scan. Project configuration remains ignored and bundled runtime skills remain disabled. |
|
|
210
|
+
| `provider.allowSymbolicLinks` | `true` | Boolean. Allows existing symbolic links and Windows junctions whose resolved targets stay inside the same workspace. Set to `false` to reject them. External targets, broken links, directory cycles, and hard-linked files remain rejected. |
|
|
211
|
+
|
|
212
|
+
Model selection order is request `model`, configured `defaultModel`, catalog default, then first available model. An explicitly requested/configured unavailable model fails instead of silently falling back.
|
|
213
|
+
|
|
214
|
+
Effort selection order is request `reasoning_effort`, configured `defaultReasoning`, then the selected model's default. `Light`, `Medium`, and `Strong` map to `low`, `medium`, and `high`; these are valid only when the model supports the resulting value. Query `GET /v1/models` for actual IDs and `reasoning_efforts` before adding model defaults. Do not assume a fixed catalog.
|
|
215
|
+
|
|
216
|
+
The dedicated home cannot contain custom `config.toml`, `AGENTS.md`, `AGENTS.override.md`, hooks, rules, plugins, or custom skills. The pinned runtime's generated `skills/.system` directories are permitted, but those bundled skills are disabled. Do not point this setting at your personalized desktop Codex home.
|
|
217
|
+
|
|
218
|
+
## Workspace selection and paths
|
|
219
|
+
|
|
220
|
+
`workspaces` must contain at least one entry. Each entry has:
|
|
221
|
+
|
|
222
|
+
| Field | Requirement |
|
|
223
|
+
| --- | --- |
|
|
224
|
+
| Workspace ID | 1–64 letters, digits, underscores, or hyphens; case-sensitive. |
|
|
225
|
+
| `path` | Existing absolute native directory path. |
|
|
226
|
+
| `access` | Exactly `"read-only"` or `"read-write"`; defines requested native filesystem permissions. |
|
|
227
|
+
|
|
228
|
+
For a text-generation-only n8n workflow, an existing empty `read-only` workspace can be used. A workspace is still required even when the prompt does not ask to read files.
|
|
229
|
+
|
|
230
|
+
Folder rules:
|
|
231
|
+
|
|
232
|
+
- Workspaces cannot be filesystem roots, overlap, or alias each other.
|
|
233
|
+
- The configuration file and Codex home must be outside every workspace; workspaces cannot be inside the Codex home.
|
|
234
|
+
- Workspace trees are inspected before new generation. Project folders and internal symbolic links follow the [project skills and symbolic links settings](#project-skills-and-symbolic-links).
|
|
235
|
+
- Parent directories may contain `.codex`, `.agents`, `AGENTS.md`, or `AGENTS.override.md`; these entries do not block workspace validation.
|
|
236
|
+
- Paths inside JSON are literal. `~`, `$HOME`, and `%USERPROFILE%` are not expanded there. Home shorthand is expanded only in the CLI configuration filename.
|
|
237
|
+
|
|
238
|
+
Choose a workspace through a default:
|
|
239
|
+
|
|
240
|
+
```json
|
|
241
|
+
{
|
|
242
|
+
"compatibility": {
|
|
243
|
+
"defaultWorkspace": "project-a"
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
The fragment above belongs in the full configuration; it is not a standalone config. Alternatively, send `X-Workspace-ID: project-a`. If an existing configuration uses `WORKSPACE`, use that exact ID rather than copying `project-a` from this guide.
|
|
249
|
+
|
|
250
|
+
## Project skills and symbolic links
|
|
251
|
+
|
|
252
|
+
Both settings default to `true`, including in existing configurations that omit them. They belong under `provider` and apply to all configured workspaces. Use JSON booleans (`true` or `false`), not quoted strings.
|
|
253
|
+
|
|
254
|
+
To allow project skills and internal links, merge these fields into your existing `provider` object:
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"allowProjectSkills": true,
|
|
259
|
+
"allowSymbolicLinks": true
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
To restrict both, use:
|
|
264
|
+
|
|
265
|
+
```json
|
|
266
|
+
{
|
|
267
|
+
"allowProjectSkills": false,
|
|
268
|
+
"allowSymbolicLinks": false
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
These are provider fragments, not complete configuration files. Preserve the other provider fields and your existing API key. The settings are independent: for example, you can allow skills while rejecting symbolic links. Stop and restart the server after editing the private configuration. For compiled execution, run `npm run build` after updating application source, then restart with `npm start -- "~/.clilinkapi/clilinkapi.json"`.
|
|
273
|
+
|
|
274
|
+
### Project skills
|
|
275
|
+
|
|
276
|
+
Place project skills in `<workspace>/.agents/skills/<skill-name>/SKILL.md`. With `allowProjectSkills: true`, the runtime can discover and use them. With `false`, CliLinkAPI explicitly disables the skill files found in the workspace scan; their folders can remain in place.
|
|
277
|
+
|
|
278
|
+
Allowing skills does not load project `.codex/config.toml`: the runtime still treats the workspace as untrusted for project configuration. Custom configuration and skills in the dedicated `provider.codexHome` remain rejected, and bundled runtime skills remain disabled. Parent-directory configuration and instructions no longer cause a workspace-validation error. This change removes the presence check; it does not guarantee that the runtime ignores ancestor instructions or skills.
|
|
279
|
+
|
|
280
|
+
### Symbolic links and Windows junctions
|
|
281
|
+
|
|
282
|
+
With `allowSymbolicLinks: true`, the workspace scan resolves existing links and checks the final target. Directory contents are inspected through link aliases as well.
|
|
283
|
+
|
|
284
|
+
| Link in `C:/Projects/project-a` | Result |
|
|
285
|
+
| --- | --- |
|
|
286
|
+
| A file link to `C:/Projects/project-a/data/input.txt` | Allowed if the target exists. |
|
|
287
|
+
| A directory link or junction to `C:/Projects/project-a/shared` | Allowed if it does not create a directory cycle. |
|
|
288
|
+
| A chain of links ending inside `C:/Projects/project-a` | Allowed if all inspected links resolve within the workspace and no directory cycle is introduced. |
|
|
289
|
+
| A link to `C:/Projects/project-b` or another external location | Rejected, even if that location is another configured workspace. |
|
|
290
|
+
| A missing target, link loop, or directory link back to an ancestor | Rejected. |
|
|
291
|
+
| A hard-linked file | Rejected regardless of this setting. |
|
|
292
|
+
|
|
293
|
+
With `allowSymbolicLinks: false`, existing symbolic links and junctions in the workspace are rejected with `403 workspace_link`. The setting does not change operating-system privileges for creating links, configuration-file link restrictions, or the dedicated Codex home's rules. Native sandbox enforcement still governs operations during execution; see [security boundaries](security.md).
|
|
294
|
+
|
|
295
|
+
## Windows execution mode
|
|
296
|
+
|
|
297
|
+
Omitting `allowUnqualifiedWindowsExecution` is equivalent to setting it to `true`. This skips CliLinkAPI's Windows platform refusal and its per-generation qualification probes. The startup banner and `doctor` identify this mode.
|
|
298
|
+
|
|
299
|
+
The native permission profile is still requested. Authentication, configuration ACL checks, workspace validation, runtime version checks, and dedicated-home validation also remain active. This setting does not repair `CreateRestrictedToken` failures or an unavailable elevated sandbox backend, and it does not switch to unrestricted execution.
|
|
300
|
+
|
|
301
|
+
Read, ACL, descendant-process, and network confinement are not certified in this mode. To restore the Windows block, set this inside `provider` and restart:
|
|
302
|
+
|
|
303
|
+
```json
|
|
304
|
+
"allowUnqualifiedWindowsExecution": false
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
On Linux/macOS, native probes remain mandatory regardless of this setting. See [security boundaries](security.md) for the exact limits and trust assumptions.
|
|
308
|
+
|
|
309
|
+
## Local and network access
|
|
310
|
+
|
|
311
|
+
| Client location | Server bind | Client Base URL |
|
|
312
|
+
| --- | --- | --- |
|
|
313
|
+
| Same computer, native process | `127.0.0.1` | `http://127.0.0.1:3000/v1` |
|
|
314
|
+
| Another LAN computer | `0.0.0.0` or the server's LAN IPv4 address | `http://SERVER_LAN_IP:3000/v1` |
|
|
315
|
+
| Docker Desktop on the server computer | Interface reachable from Docker | `http://host.docker.internal:3000/v1` |
|
|
316
|
+
| Remote network/cloud | Reachable deployment behind HTTPS | Your authenticated HTTPS gateway URL ending in `/v1` |
|
|
317
|
+
|
|
318
|
+
For the LAN setup discussed in this project, an example is `http://192.168.0.96:3000/v1`. Substitute the server's current LAN address. A DHCP reservation can keep that address stable. `0.0.0.0` is a bind address, not the URL clients should use. Binding to it does not advertise a hostname or configure DNS.
|
|
319
|
+
|
|
320
|
+
Change `server.host` to `0.0.0.0`, restart the gateway, and allow inbound TCP on the configured port through the server firewall. If an inbound Windows Firewall rule is needed, an administrator can use this private-network, local-subnet rule:
|
|
321
|
+
|
|
322
|
+
```powershell
|
|
323
|
+
New-NetFirewallRule -DisplayName "CliLinkAPI TCP 3000 (Private LAN)" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 3000 -Profile Private -RemoteAddress LocalSubnet
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Run that only on the gateway host and adapt it to your network policy and chosen port. It does not apply to a network classified as Public. Do not disable the firewall to diagnose connectivity.
|
|
327
|
+
|
|
328
|
+
From the client computer:
|
|
329
|
+
|
|
330
|
+
```powershell
|
|
331
|
+
Test-NetConnection dengero -Port 3000
|
|
332
|
+
Test-NetConnection 192.168.0.96 -Port 3000
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Ping alone does not test port 3000. If a hostname selects IPv6 and that connection fails while IPv4 succeeds, use the IPv4 URL. A listener bound to `0.0.0.0` listens on IPv4. Test from the actual n8n runtime environment; a container can have different connectivity from its host shell.
|
|
336
|
+
|
|
337
|
+
Use plain HTTP only on a trusted network. The application does not terminate TLS itself; for remote access, use an HTTPS reverse proxy, restrict direct port access, and disable proxy buffering for SSE. Proxy/client timeouts should allow for the configured request duration.
|
|
338
|
+
|
|
339
|
+
## Configure n8n
|
|
340
|
+
|
|
341
|
+
In the OpenAI credential used by your **OpenAI Chat Model** node:
|
|
342
|
+
|
|
343
|
+
| n8n field | Value |
|
|
344
|
+
| --- | --- |
|
|
345
|
+
| API Key | The gateway's `auth.apiKey`, with no `Bearer ` prefix in this field |
|
|
346
|
+
| Organization ID | Empty |
|
|
347
|
+
| Base URL | For example, `http://192.168.0.96:3000/v1` |
|
|
348
|
+
| Custom header | Optional if a default workspace exists; otherwise `X-Workspace-ID` with an actual workspace ID |
|
|
349
|
+
|
|
350
|
+
Enter the URL as plain text, not Markdown link syntax. Do not append `/chat/completions` to the credential Base URL. Remove stale custom workspace headers when switching to a default workspace.
|
|
351
|
+
|
|
352
|
+
In the **OpenAI Chat Model** node attached to the AI Agent:
|
|
353
|
+
|
|
354
|
+
1. Select the gateway credential and a model returned by its catalog.
|
|
355
|
+
2. Turn **Use Responses API** off. The gateway implements Chat Completions, not `/v1/responses`.
|
|
356
|
+
3. Set **Max Retries** to `0`; a retry could repeat an action already performed.
|
|
357
|
+
4. Set **Timeout** to `180000` or match your gateway configuration.
|
|
358
|
+
5. Leave temperature, Top P, maximum token settings, and penalties unset. Use text output; do not enable strict structured output or forced tool selection.
|
|
359
|
+
6. Start with a simple user prompt before adding tools or a larger workflow.
|
|
360
|
+
|
|
361
|
+
A green credential test confirms discovery connectivity/authentication, not successful generation. The AI Agent can still encounter workspace, request-validation, runtime, or sandbox failures afterward. See [n8n integration](n8n.md) for tool continuations and supported behavior.
|
|
362
|
+
|
|
363
|
+
## Verify the connection
|
|
364
|
+
|
|
365
|
+
The application currently exposes exactly these routes:
|
|
366
|
+
|
|
367
|
+
| Method | Endpoint | Requirements |
|
|
368
|
+
| --- | --- | --- |
|
|
369
|
+
| GET | `/v1/models` | Bearer key; returns discovered models and supported reasoning efforts |
|
|
370
|
+
| POST | `/v1/chat/completions` | Bearer key, JSON body, and a valid workspace header or configured default |
|
|
371
|
+
|
|
372
|
+
There is no unauthenticated health route, root-page UI, Responses API, or embeddings endpoint. Use the exact route paths without query strings or trailing slashes.
|
|
373
|
+
|
|
374
|
+
For a local test under the runtime account, this PowerShell example reads the key without printing it:
|
|
375
|
+
|
|
376
|
+
```powershell
|
|
377
|
+
$configFile = Join-Path $HOME '.clilinkapi/clilinkapi.json'
|
|
378
|
+
$gatewayConfig = Get-Content -LiteralPath $configFile -Raw | ConvertFrom-Json
|
|
379
|
+
$gatewayBase = 'http://127.0.0.1:3000/v1'
|
|
380
|
+
$requestHeaders = @{ Authorization = 'Bearer ' + $gatewayConfig.auth.apiKey }
|
|
381
|
+
$catalog = Invoke-RestMethod -Uri "$gatewayBase/models" -Headers $requestHeaders
|
|
382
|
+
$catalog.data | Select-Object id, reasoning_efforts
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Then send a minimal generation request. Select an existing workspace ID if you changed the template:
|
|
386
|
+
|
|
387
|
+
```powershell
|
|
388
|
+
if (-not $catalog.data.Count) { throw 'No available models; check allowedModels and login.' }
|
|
389
|
+
$requestHeaders['X-Workspace-ID'] = 'project-a'
|
|
390
|
+
$payload = @{
|
|
391
|
+
model = $catalog.data[0].id
|
|
392
|
+
stream = $false
|
|
393
|
+
messages = @(@{ role = 'user'; content = 'Reply with a short greeting. Do not read files or run commands.' })
|
|
394
|
+
} | ConvertTo-Json -Depth 10
|
|
395
|
+
$reply = Invoke-RestMethod -Method Post -Uri "$gatewayBase/chat/completions" -Headers $requestHeaders -ContentType 'application/json' -Body $payload -TimeoutSec 190
|
|
396
|
+
$reply.choices[0].message.content
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
This second request performs a real model call and can consume account usage. Do not distribute the full private configuration to a remote n8n host; enter only the client API key into its credential store.
|
|
400
|
+
|
|
401
|
+
## Maintenance commands
|
|
402
|
+
|
|
403
|
+
| Command | Purpose |
|
|
404
|
+
| --- | --- |
|
|
405
|
+
| `setup CONFIG TEMPLATE` | Create a new private configuration and generated key; refuses overwrite |
|
|
406
|
+
| `secure-config CONFIG` | Repair permissions without rotating the key or changing configuration content |
|
|
407
|
+
| `login CONFIG [--device-auth]` | Sign the dedicated runtime into ChatGPT |
|
|
408
|
+
| `doctor CONFIG` | Report platform mode and query the authenticated model catalog |
|
|
409
|
+
| `serve CONFIG` | Start the gateway until stopped |
|
|
410
|
+
| `rotate-key CONFIG` | Generate and atomically store a replacement gateway key |
|
|
411
|
+
|
|
412
|
+
Prefix each with `npm run clilinkapi --`. Except for setup's template argument, the CLI can use its default configuration path when `CONFIG` is omitted.
|
|
413
|
+
|
|
414
|
+
Configuration does not hot-reload. Stop the server, edit its private file, and restart. If using `npm start`, rebuild after source changes; `npm run clilinkapi -- serve` runs TypeScript source directly.
|
|
415
|
+
|
|
416
|
+
To rotate a key:
|
|
417
|
+
|
|
418
|
+
```powershell
|
|
419
|
+
npm run clilinkapi -- rotate-key "~/.clilinkapi/clilinkapi.json"
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Restart the server and update n8n's stored key. A running process continues using its old in-memory configuration until restarted.
|
|
423
|
+
|
|
424
|
+
For permission repair:
|
|
425
|
+
|
|
426
|
+
```powershell
|
|
427
|
+
npm run clilinkapi -- secure-config "~/.clilinkapi/clilinkapi.json"
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
The configuration directory must be dedicated and contain only the config file and its configured `codex` child folder. This command refuses unrelated entries, symlinks, filesystem roots, and the user's home directory itself. A Codex home elsewhere must be secured separately. Preserve backups in a private location outside this dedicated directory and outside every workspace.
|
|
431
|
+
|
|
432
|
+
## Troubleshooting
|
|
433
|
+
|
|
434
|
+
| Symptom | Meaning and next step |
|
|
435
|
+
| --- | --- |
|
|
436
|
+
| `ECONNREFUSED` | No reachable listener at the selected address/port. Check that serve is running, its bind address, firewall, and the client runtime's network. Try the LAN IPv4 address if hostname IPv6 fails. |
|
|
437
|
+
| `EADDRINUSE` on startup | Another process already uses the port. Stop the appropriate existing instance or select a different port and update clients. |
|
|
438
|
+
| `401` | Missing or incorrect gateway Bearer key. Use `auth.apiKey`, not a ChatGPT token or OpenAI API key. Restart after key rotation. An unauthenticated test returning 401 does establish HTTP reachability. |
|
|
439
|
+
| `404 Endpoint not found` | Check the exact Base URL and route. In n8n, turn off Use Responses API. |
|
|
440
|
+
| `400 A configured X-Workspace-ID header is required` | Configure `compatibility.defaultWorkspace` or send a valid header. IDs are case-sensitive; an invalid explicit header overrides a valid default. |
|
|
441
|
+
| `400 unsupported_request` | Remove unsupported sampling, token, strict-schema, or output-format options. Use text messages and Chat Completions. |
|
|
442
|
+
| `400 unsupported_model` | Query `/v1/models`; use an available ID allowed by the filter. Review `defaultModel` too. |
|
|
443
|
+
| `400 unsupported_reasoning_effort` | Use an effort listed for the selected model or omit the setting. |
|
|
444
|
+
| `403 workspace_link` | Check `provider.allowSymbolicLinks`. When enabled, link targets must exist and resolve inside the same workspace without directory cycles. Hard-linked files remain blocked. Restart after changing the setting. |
|
|
445
|
+
| Old `403 ancestor_configuration` message | The ancestor-directory restriction has been removed. Rebuild and restart the gateway to use the updated code. Configuration-directory permissions are a separate check and still apply. |
|
|
446
|
+
| Old `403 workspace_config` message | Current code permits project `.codex` and `.agents` folders. Rebuild and restart the running gateway to pick up the update; these folders no longer cause this error merely by existing. |
|
|
447
|
+
| Project skill unavailable | Check `provider.allowProjectSkills`, the project's `.agents/skills/<name>/SKILL.md` layout, and that the server was restarted. Custom skills in the dedicated Codex home are still rejected. |
|
|
448
|
+
| `409 workspace_busy` | A request or external tool continuation holds the workspace. Wait for completion/expiry; avoid concurrent workflows against the same workspace. |
|
|
449
|
+
| `409 tool_session_expired` | A tool continuation expired or was lost on restart. Check whether the external action ran before deliberately restarting the workflow. |
|
|
450
|
+
| `413 request_too_large` | Reduce the request body or raise `maxBodyBytes` within its allowed range. |
|
|
451
|
+
| `429` | Check the error code: local capacity and upstream usage limits require different remedies. Reduce concurrency or wait for account limits as appropriate. |
|
|
452
|
+
| `503 native_isolation_unavailable` | On Windows, check for explicit `allowUnqualifiedWindowsExecution: false`. On Linux/macOS, inspect native sandbox prerequisites/probes. Turning the Windows flag on does not fix native backend failures. |
|
|
453
|
+
| Restricted-token/elevated sandbox error | The runtime cannot initialize the requested Windows permissions. The unqualified-execution flag skips qualification only; it does not remove the native permission profile. |
|
|
454
|
+
| `503 upstream_authentication` | Run `login` again as the service account using the same config and dedicated home. |
|
|
455
|
+
| `502 upstream_error` or `upstream_closed` | Check the pinned runtime, service account, login, and sandbox availability with `doctor`. A green model test alone does not verify generation. |
|
|
456
|
+
| `502 stream_unavailable` | Codex supplied buffered final output without real deltas. Retry deliberately with `stream: false` if appropriate. |
|
|
457
|
+
| `504` | Review timeout, runtime availability, and workload. A cancelled request can already have performed actions; do not blindly retry. |
|
|
458
|
+
| Dedicated Codex home rejection | Relocate the specific custom entry identified by the error, or configure a clean dedicated home and log in there. Keep credentials private. |
|
|
459
|
+
| Invalid configuration / permissions error | Check JSON syntax, exact field names, value ranges, absolute paths, existing folders, and owner/private permissions. Use `secure-config` only for its supported dedicated layout. |
|
|
460
|
+
|
|
461
|
+
For diagnosis, share the error code, status, relevant setting names, and sanitized terminal output. Do not share the full credential file. Normal request logs include request IDs, status, duration, and error codes rather than prompts or keys.
|
|
462
|
+
|
|
463
|
+
Run one gateway process per set of workspace folders: locks and tool continuations are process-local. See [architecture](architecture.md) and [security boundaries](security.md) for operational limits.
|
package/docs/n8n.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# n8n AI Agent integration
|
|
2
|
+
|
|
3
|
+
For initial setup, all configuration fields, network access, and troubleshooting, see the [configuration guide](configuration.md).
|
|
4
|
+
|
|
5
|
+
CliLinkAPI implements the text Chat Completions and function-tool subset used by n8n's OpenAI Chat Model. It is not a complete implementation of every OpenAI API.
|
|
6
|
+
|
|
7
|
+
**Runtime limitation:** Windows generation is attempted without isolation qualification by default. The adapter and HTTP tests do not establish a working live n8n/Codex run. Linux/macOS generation requires successful native isolation probes and ChatGPT login. `provider.allowUnqualifiedWindowsExecution` defaults to `true`; set it to `false` and restart to block Windows generation. This skips Windows qualification probes but still requests native permission profiles; runtime sandbox failures remain possible.
|
|
8
|
+
|
|
9
|
+
## Gateway configuration
|
|
10
|
+
|
|
11
|
+
Add this top-level object to your private `clilinkapi.json`, replacing `project-a` with an existing workspace ID, then restart the gateway:
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
"compatibility": {
|
|
15
|
+
"defaultWorkspace": "project-a",
|
|
16
|
+
"toolTimeoutMs": 300000,
|
|
17
|
+
"maxPendingTools": 8
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The default allows n8n requests without a custom `X-Workspace-ID` header. An explicit header overrides it and must name a configured workspace. Every holder of the shared gateway key can access configured workspaces; this setting is not tenant isolation.
|
|
22
|
+
|
|
23
|
+
## n8n settings
|
|
24
|
+
|
|
25
|
+
1. Connect an **OpenAI Chat Model** node to your **AI Agent** node.
|
|
26
|
+
2. Create an OpenAI credential using your **CliLinkAPI API key**, from `auth.apiKey`. Leave Organization ID empty. Set its Base URL to `http://127.0.0.1:3000/v1` when n8n runs directly on the same machine. Older node versions also expose Base URL under Options.
|
|
27
|
+
3. Set **Use Responses API** to **off**. Select a model returned by the gateway's `/v1/models`, or enter its exact ID.
|
|
28
|
+
4. Set **Max Retries** to `0` and **Timeout** to `180000` (or match the gateway timeout). Leave Sampling Temperature, Top P, Maximum Number of Tokens, and penalties unset. Use Text response format. Do not enable structured output or forced tool selection.
|
|
29
|
+
5. Attach a simple n8n tool, such as Calculator, to the agent. Ask it to use that tool and report the result. Inspect the workflow execution to verify the tool actually ran.
|
|
30
|
+
|
|
31
|
+
For Docker Desktop n8n, the host URL is `http://host.docker.internal:3000/v1`; the gateway must listen on an interface reachable from Docker and the firewall must allow it. The default loopback binding may not be reachable. For remote or cloud n8n, localhost refers to that remote server: use a reachable, authenticated HTTPS endpoint instead.
|
|
32
|
+
|
|
33
|
+
These settings follow the [n8n OpenAI Chat Model documentation](https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.lmchatopenai/) and its [node implementation](https://github.com/n8n-io/n8n/blob/master/packages/%40n8n/nodes-langchain/nodes/llms/LMChatOpenAi/LmChatOpenAi.node.ts). The upstream version can change; a live imported workflow has not been tested here.
|
|
34
|
+
|
|
35
|
+
## Tool-call behavior
|
|
36
|
+
|
|
37
|
+
The gateway registers client function definitions as Codex dynamic tools. A native `item/tool/call` becomes an OpenAI `tool_calls` response with `finish_reason: "tool_calls"`. n8n executes the tool. Its next request must contain the unchanged conversation, assistant tool call, and matching `role: "tool"` result. The gateway delivers the result to the same waiting Codex turn. Tool arguments are emitted as a complete JSON object, including in SSE; argument tokens are not simulated.
|
|
38
|
+
|
|
39
|
+
Continuations are process-local, expire after five minutes by default, and are consumed once. The workspace is reserved while waiting. Restarting the gateway loses pending calls. On `409 tool_session_expired`, restart the conversation after checking whether the tool already performed side effects; do not replay automatically. Tool definitions, model, workspace, reasoning effort and earlier history must remain unchanged across a continuation. One tool is returned per response; concurrent tool execution is not promised.
|
|
40
|
+
|
|
41
|
+
Supported: text messages, function tools, automatic/no tool choice, JSON and SSE responses, `n: 1`, and observed usage. Unsupported: Responses API, images/audio, embeddings, forced/required tools, strict schema guarantees, sampling controls and token caps. Unsupported behavior returns a clear error instead of silently ignoring it. Tools execute in n8n with n8n's own credentials and permissions.
|
|
42
|
+
|
|
43
|
+
|
package/docs/security.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Security boundaries and release limitations
|
|
2
|
+
|
|
3
|
+
**Windows coding-agent execution is attempted without qualification probes by default. Linux/macOS remain unqualified on this build host and require passing probes.** Set `provider.allowUnqualifiedWindowsExecution=false` to block Windows execution. Passing application tests is not evidence that an OS sandbox denies arbitrary reads.
|
|
4
|
+
|
|
5
|
+
| Platform | Native mechanism | This release |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| Windows | Codex restricted tokens/ACLs; strongest documented mode uses dedicated lower-privilege users and firewall rules | Initial probe failed `CreateRestrictedToken failed: 87`; the actual restricted-read profile reports `Restricted read-only access requires the elevated Windows sandbox backend`. No claim of read confinement, network confinement or process-tree isolation. Generation is attempted without qualification probes by default; login/catalog remain usable. |
|
|
8
|
+
| Linux | Codex bubblewrap/seccomp; kernel/user namespace and system policy dependent | Eligible only after per-execution native probes pass; not executed on the Windows build host. No container/VM fallback and no unrestricted execution. |
|
|
9
|
+
| macOS | Codex Seatbelt | Eligible only after per-execution native probes pass; not executed on the Windows build host. |
|
|
10
|
+
|
|
11
|
+
The custom profile grants `:minimal` runtime reads, the selected workspace's configured read/write access and the Node executable used by probes. It denies all other filesystem reads by default, explicitly denies clilinkapi configuration and Codex home, and disables command network access. Runtime code and authentication remain in the trusted Codex parent; commands must not read credentials. `:minimal` is the pinned Codex platform runtime allowlist, not an arbitrary directory supplied by a client. Protected project metadata is read-only. There is no approval escalation path; server-initiated approvals and interactive questions are refused. Registered dynamic function calls are returned to n8n for execution under its own permissions, with results bound to the original workspace, model, tool definitions and conversation. Web search, browser/computer tools, apps, plugins, hooks, memories, image tools, multi-agent, host skill discovery and workspace-dependency tools are disabled.
|
|
12
|
+
|
|
13
|
+
Do not confuse Codex's legacy `read-only` mode (primarily write protection) with workspace-only read protection. This clilinkapi uses named filesystem permission profiles. Before a turn, the real app-server `command/exec` probes selected-workspace reading, allowed/denied writing according to access mode, denied reading/writing of harmless sentinels outside the workspace, symlink escape denial, and read denial in a child process. On Linux/macOS, a failed or unparseable probe prevents any model turn. Windows does not run the eligible-platform probes; a refusal test is separate from actual enforcement tests.
|
|
14
|
+
|
|
15
|
+
Configuration paths are canonicalized. Root workspaces, overlaps and known secret-containing workspaces are rejected. Existing symbolic links and junctions are allowed when their resolved targets remain inside the same workspace. `provider.allowSymbolicLinks=false` rejects them. Broken links, directory cycles, external targets and hard-linked files are rejected. This scan is only defense in depth: the native profile must enforce paths for shell commands, newly created links, traversal and descendants at execution time. The clilinkapi does not accept arbitrary filesystem APIs from clients. A trusted operator must not replace workspace directories, alter OS policies, add secrets, or install host configuration while the clilinkapi runs. Use a dedicated OS account with no unrelated project access as additional protection. This is not a hardened hostile-local-user service.
|
|
16
|
+
|
|
17
|
+
Outstanding qualification limits:
|
|
18
|
+
|
|
19
|
+
- No successful authenticated end-to-end execution was possible on the available host. Real model phase events, quota handling and live edits still need qualification with that runtime login.
|
|
20
|
+
- Built-in tool enforcement, runtime-resource allowlists, every escape vector, external filesystem mounts, and process cleanup must be reviewed on each supported OS. The included native probes sample critical boundaries; they are not a proof against all sandbox vulnerabilities. Do not deploy to untrusted tenants based on unit tests.
|
|
21
|
+
- Native Windows restricted-token failure is not worked around. The default `provider.allowUnqualifiedWindowsExecution=true` setting skips the platform gate and Windows probes without claiming qualification. Permission profiles remain requested, with no unrestricted fallback. Qualifying Windows still requires separate read/write, ACL, junction, subprocess and network verification, plus complete tool-surface qualification.
|
|
22
|
+
- The lock is per process. Run only one clilinkapi instance for a set of workspaces. Separate instances/external editors can conflict; no distributed lock or persistent queue exists. Both read-only and read-write requests take the workspace lock. Disjoint workspaces may execute concurrently.
|
|
23
|
+
- An authenticated caller may request destructive edits inside a read-write workspace. There is no transactional rollback on timeout, cancellation or upstream failure. No automatic retries are safe for such operations.
|
|
24
|
+
- No persistent conversation API: process restarts, session resumption and cross-workspace session sharing are intentionally unsupported.
|
|
25
|
+
- Token usage is omitted when absent, and streaming excludes usage chunks because `stream_options` is unsupported. Model discovery reflects the runtime's visible catalog, not a quota reservation.
|
|
26
|
+
- Output redaction removes known local paths, absolute path-like strings and known clilinkapi secrets, including split deltas. This changes affected final text and can over-redact path-like prose. It is not a substitute for preventing credential access. Never place secrets in prompts or projects.
|
|
27
|
+
- Default logs exclude content, but Codex may keep its own operational logs under the private Codex home. Ephemeral threads reduce session persistence; this is not a promise that Codex leaves no logs or caches. Protect and manage that directory.
|
|
28
|
+
- OS administrators, the trusted clilinkapi/Codex parent processes, npm dependencies, configured runtime resources and the Codex service are trusted. Filesystem probes never read actual credential contents. Broader system-managed Codex policy can reject operation; it must not be weakened to make this clilinkapi run.
|
|
29
|
+
|
|
30
|
+
The clilinkapi key uses timing-safe SHA-256 digest comparison; all `/v1/*` requests authenticate before request workspace access or Codex invocation. Strict config validation rejects empty/placeholder keys. Setup uses 256 bits of entropy, exclusive creation and private file permissions; rotation is explicit. The real config is gitignored and must be stored outside any allowed workspace. It must also be kept out of repositories generally, logs, shared backups, screenshots and shell history.
|
|
31
|
+
|
|
32
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Verification record
|
|
2
|
+
|
|
3
|
+
Build host: native Windows, Node 24.16.0, npm 11.13.0, Codex CLI/SDK 0.155.0. Date: 2026-09-18.
|
|
4
|
+
|
|
5
|
+
Executed during implementation:
|
|
6
|
+
|
|
7
|
+
- Strict TypeScript type check and production build: passed.
|
|
8
|
+
- Final unit/HTTP/setup suite: **18 tests passed**. Windows isolation refusal: **1 passed**; native Unix probes: **2 skipped on Windows**.
|
|
9
|
+
- Unit and HTTP integration tests against test-only providers, covering authentication before invocation, configuration validation, message translation, final extraction, reported usage, SSE success/error termination, supported model/reasoning validation, unknown workspace/session/path rejection, junction escape detection, cancellation, timeout, concurrency, normalized errors and split-delta redaction.
|
|
10
|
+
- Native Windows fail-closed isolation test. Linux/macOS read-only/read-write sandbox probes are explicitly skipped on Windows.
|
|
11
|
+
- Official runtime login status check: **Not logged in** in the available runtime context. No browser credentials or desktop login material was extracted.
|
|
12
|
+
- Initial native sandbox initialization: **CreateRestrictedToken failed: 87**. Agent execution remains disabled on Windows.
|
|
13
|
+
- The subsequent probe with the clilinkapi's actual restricted-read profile failed with **Restricted read-only access requires the elevated Windows sandbox backend**. The real app-server handshake succeeded and a fresh dedicated home reported no account. Setup and rotation passed real Windows ACL verification after correcting unnecessary owner reassignment.
|
|
14
|
+
- `npm run test:live`: **BLOCKED**, because no private `CLILINKAPI_CONFIG` and ChatGPT-authenticated runtime were supplied. No successful live response, workspace modification or external-read denial is claimed.
|
|
15
|
+
|
|
16
|
+
Additional reproducible commands:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
npx tsx scripts/diagnose-runtime.ts
|
|
20
|
+
npm test
|
|
21
|
+
npm run test:isolation
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The diagnostic uses a fresh empty Codex home, checks the official app-server handshake/account shape, and on Windows attempts a harmless native sandbox process. It never reads existing authentication files or prints credentials. Setup/rotation tests check generated key entropy, refusal to overwrite, private Unix modes/Windows ACLs, and explicit key rotation.
|
|
25
|
+
|
|
26
|
+
CI is configured for native Ubuntu/macOS/Windows with Node 22 and 24. CI has not been dispatched from this local workspace. The two Unix native probe tests are required there, not silently replaced by mocks. CI does not perform interactive ChatGPT login.
|
|
27
|
+
|
|
28
|
+
Remaining acceptance work: obtain a supported ChatGPT login in a dedicated runtime home, qualify native Linux/macOS isolation on those hosts, then run `test:live` and real permitted-edit/denied-read cases through HTTP. Native Windows execution additionally requires implementation/qualification beyond the current platform refusal. A live test failure must be reported as failure, not converted to a fixture response.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// npm install openai in your client project. Do not log the private config.
|
|
2
|
+
import OpenAI from 'openai';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
const config = JSON.parse(await readFile(process.env.CLILINKAPI_CONFIG, 'utf8'));
|
|
5
|
+
const client = new OpenAI({ baseURL: 'http://127.0.0.1:3000/v1', apiKey: config.auth.apiKey, maxRetries: 0 });
|
|
6
|
+
const catalog = await client.models.list();
|
|
7
|
+
const model = catalog.data[0]?.id;
|
|
8
|
+
if (!model) throw new Error('No available Codex models');
|
|
9
|
+
const result = await client.chat.completions.create({
|
|
10
|
+
model, reasoning_effort: 'low',
|
|
11
|
+
messages: [{ role: 'user', content: 'Summarize the project without modifying files.' }]
|
|
12
|
+
}, { headers: { 'X-Workspace-ID': 'project-a' } });
|
|
13
|
+
console.log(result.choices[0].message.content);
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "clilinkapi",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Native CLI gateway for a ChatGPT-authenticated Codex runtime.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": { "clilinkapi": "dist/src/cli.js" },
|
|
7
|
+
"files": ["dist/src/**/*.js", "docs/*.md", "examples/client.mjs", "clilinkapi.example.json"],
|
|
8
|
+
"publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" },
|
|
9
|
+
"engines": { "node": ">=22" },
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"prepack": "npm run build",
|
|
13
|
+
"check": "tsc --noEmit",
|
|
14
|
+
"test": "tsx --test test/*.test.ts",
|
|
15
|
+
"test:isolation": "tsx --test test/isolation.integration.ts",
|
|
16
|
+
"start": "node dist/src/cli.js serve",
|
|
17
|
+
"clilinkapi": "tsx src/cli.ts",
|
|
18
|
+
"test:live": "tsx scripts/live.ts"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": { "@openai/codex": "0.155.0", "@openai/codex-sdk": "0.155.0", "zod": "^4.0.0" },
|
|
21
|
+
"devDependencies": { "@types/node": "^22.0.0", "tsx": "^4.20.0", "typescript": "^5.9.0" }
|
|
22
|
+
}
|