# Báo cáo phân tích sâu: pi-commandcode-provider v0.4.3

> Phân tích READ-ONLY bởi pi-crew research team (explorer → analyst → writer).
> Mọi line reference đã verify trực tiếp bằng `read`. Không chạy `npm test` (read-only, không install deps).

## 1. Tổng quan

| Hạng mục      | Giá trị                                                                  |
| ------------- | ------------------------------------------------------------------------ |
| Package       | `pi-commandcode-provider` v0.4.3 (CHANGELOG đã release 0.4.4 — mismatch) |
| Loại          | pi custom provider extension (tương thích Oh My Pi)                      |
| Kết nối       | Command Code API (`api.commandcode.ai/provider/v1`)                      |
| Quy mô        | 8 file source (~1.893 dòng TS) + 12 file test (~2.968 dòng) + 4 docs     |
| Runtime deps  | **0** (chỉ peer: `pi-ai`, `pi-coding-agent` optional)                    |
| Điểm tổng thể | **8.4/10** — kiến trúc sạch, DI toàn diện, test xuất sắc                 |

## 2. Kiến trúc

```
┌─────────────────────────────────────────────────────────────┐
│                   HOST (pi / OMP)                            │
│   ExtensionAPI.registerProvider("commandcode", { ... })      │
└──────────────────────────┬──────────────────────────────────┘
                           │
                    ┌──────▼──────┐
                    │  index.ts   │  Entry — provider registration
                    │  (119 dòng) │  + MODEL_COSTS static pricing (25 entries)
                    └──────┬──────┘
                           │
          ┌────────────────┼─────────────────┐
          │                │                 │
   ┌──────▼──────┐  ┌──────▼──────┐  ┌───────▼───────┐
   │  models.ts  │  │  oauth.ts   │  │   core.ts     │
   │ Discovery   │  │ Login flow  │  │ Stream engine │
   │ + cache     │  │ + refresh   │  │ + retry/abort │
   └──────┬──────┘  └──────┬──────┘  └───────┬───────┘
          │         ┌──────▼──────┐          │
          │         │auth-server  │          ▼
          │         │Local HTTP   │  ┌───────────────┐
          │         │127.0.0.1    │  │ converters.ts │ ← Pure (zero I/O)
          │         │ :5959-5968  │  └───────┬───────┘
          │         └─────────────┘          │
          └──────────┬───────────────────────┘
              ┌──────▼──────┐ ┌─────────────┐
              │  cost.ts    │ │  types.ts   │
              │ (19 dòng)   │ │ (183 dòng)  │
              └─────────────┘ └─────────────┘
```

**Luồng dữ liệu end-to-end:**

1. **LOGIN** `/login` → `oauth.login()` → `startAuthServer()` (127.0.0.1:5959) → state token 32-byte → browser mở `commandcode.ai/studio/auth/cli` → POST `/callback` (CSRF validate) → store `{access=refresh=apiKey, expires=now+10y}`. **Fallback** `promptForApiKey()` nếu timeout/server-fail.
2. **LOAD EXTENSION** `loadCommandCodeModels()` → GET `/provider/v1/models` → write cache (atomic, mode 0o600) → **fallback** read cache → empty + warning.
3. **CHAT** `streamCommandCode()` → resolve apiKey (hostKey → env → auth files → error) → build body `{config, memory:null, taste:null, skills:null, params, threadId}` → `onPayload` hook → retry loop (per-attempt AbortController + timeout) → SSE parse → event mapping → done/error.

## 3. Phân tích module chính

### 3.1 `core.ts` (669 dòng) — Stream engine

- **Factory + DI toàn diện** qua `CoreDependencies` (`types.ts:149-162`): injectable `createStream`, `calculateCost`, `fetchImpl`, `now`, `uuid`, `delay`, `env`, `authPaths`.
- **Constants** (`core.ts:43-49`): `DEFAULT_GENERATE_MAX_TOKENS = 64_000`; `DEFAULT_MAX_RETRIES = 0`; `DEFAULT_MAX_RETRY_DELAY_MS = 60_000`.
- **Retry** (`core.ts:51-73`): retryable = 429/5xx; `Retry-After` header ưu tiên, fallback exp `500*2^n + 20% jitter`.
- **Request body** (`core.ts:438-455`): `config` chứa nhiều placeholder rỗng (`structure:[]`, `isGitRepo:false`, `gitStatus:""`, `recentCommits:[]`); `params.temperature: 0.3` hardcode; `threadId` = UUID mới mỗi request.
- **Retry loop** (`core.ts:458-588`): per-attempt AbortController + timeout; HTTP retry trước khi đọc body; **stream retry chỉ khi `output.content.length === 0`** (`core.ts:556`) — không retry khi user đã thấy output. Cleanup triệt để (removeEventListener, reader.cancel, releaseLock).
- **Event mapping** (`core.ts:214-369`): text-delta/reasoning-*/tool-call/finish/error. Usage derive uncached input khi `noCacheTokens` missing.

### 3.2 `converters.ts` (317 dòng) — Pure functions

- `getApiKey()` (`converters.ts:50-89`): env → auth files. **4 định dạng credential**: `{apiKey}`, `{commandcode}`, `{commandcode:{type:oauth,access}}`, `{"command-code":{type:api,key}}`.
- `messagesToCC()` (`converters.ts:208-272`): **orphaned tool-call filtering** (`converters.ts:185-203`) — loại tool call thiếu result thay vì gửi data incomplete. `thinking→reasoning`, `toolCall→tool-call`.
- `toJsonSchema()` (`converters.ts:80-173`): recursive pi schema → JSON Schema, depth guard.
- `parseStreamEventLine()` (`converters.ts:294-306`): SSE parse, skip comments, `[DONE]` handling.

### 3.3 `oauth.ts` (167 dòng) — Browser-assisted auth

- **KHÔNG phải OAuth2 PKCE thực** — là "browser-assisted API key retrieval". Command Code keys không expire → store dạng OAuth với expiry 10 năm (`oauth.ts:20,74`).
- `login()` (`oauth.ts:91-141`): startAuthServer → state token → browser → `withTimeout(waitForCallback, 15_000)` → CSRF validate.
- `sanitizeApiKey()` (`oauth.ts:56-68`): strip bracketed-paste markers + control chars.
- `refreshToken` (`oauth.ts:147-151`): no-op, trả lại key + expiry mới.

### 3.4 `auth-server.ts` (214 dòng) — Local callback server

- Bind **127.0.0.1 only** (`auth-server.ts:63`); port 5959 → fallback 5960-5968 → port 0.
- Body limit **10KB** → `req.destroy()` (`auth-server.ts:144`); one-shot close sau valid callback.
- CORS allowlist 3 origins (`auth-server.ts:74-79`); **default = `allowedOrigins[0]` cho unknown origin** (`auth-server.ts:80`).

### 3.5 `models.ts` (205 dòng) — Discovery + cache

- `fetchCommandCodeModels()` → parse → **`reasoning:true` hardcode cho mọi model** (`models.ts:105`).
- Cache atomic (temp+rename, mode 0o600, versioned). `loadCommandCodeModels()`: 3-stage fallback live → cache → empty.

### 3.6 `cost.ts` (19 dòng) & `index.ts` (119 dòng)

- `calculateCommandCodeCost()`: per-million-token arithmetic. Lưu ý inconsistency cosmetic: `cacheWrite` dùng `(cost*usage)/1M` vs khác dùng `(cost/1M)*usage` — tương đương toán học.
- `MODEL_COSTS` static 25 entries trong `index.ts:35-77`; model thiếu → `ZERO_MODEL_COST` → hiển thị $0 (≠ Command Code không tính phí).

## 4. Đánh giá rủi ro (verified)

### ⚠️ Cần chú ý

| #   | Rủi ro                                            | Mức                           | Evidence                                                       | Mitigation                                                     |
| --- | ------------------------------------------------- | ----------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------- |
| R1  | **Per-request `threadId` break session tracking** | **CAO** nếu API dùng threadId | `core.ts:434`                                                  | Verify API behavior; persist threadId per conversation nếu cần |
| R2  | **CORS default-origin permissive**                | TB                            | `auth-server.ts:80` — mọi origin nhận CORS header hợp lệ       | Reject unknown origins thay vì default                         |
| R3  | **Pricing staleness**                             | TB                            | `index.ts:35-77` — 25 entries tĩnh                             | Auto-sync hoặc warning khi model thiếu                         |
| R4  | **`config` placeholders rỗng**                    | TB                            | `core.ts:438-445`                                              | Verify API có cần project context thực không                   |
| R5  | **`temperature: 0.3` hardcode**                   | Thấp                          | `core.ts:449` — không có override                              | Thêm `StreamOptions.temperature`                               |
| R6  | **`reasoning:true` cho mọi model**                | Thấp                          | `models.ts:105` — áp cả flash/lite                             | Per-model flag                                                 |
| R7  | **Version mismatch**                              | Thấp                          | `package.json:4` (0.4.3) vs `CHANGELOG.md:7` (0.4.4)           | Bump version                                                   |
| R8  | **15s auth timeout ngắn**                         | Thấp                          | `oauth.ts:39` — env `COMMANDCODE_AUTH_TIMEOUT_MS` (không docs) | Document env var                                               |
| R9  | **`x-taste-learning:true` / `x-co-flag:false`**   | Thấp                          | `core.ts:470-471` — mục đích không rõ, gửi unconditionally     | Document purpose                                               |
| R10 | **`test-pricing.ts` regex parse source**          | Thấp                          | `test-pricing.ts:22-43` — fragile                              | Tách `MODEL_COSTS` ra `src/pricing.ts`                         |
| R11 | **`getApiKey` name collision**                    | Thấp                          | `oauth.ts:154` vs `converters.ts:50`                           | Rename                                                         |

### 🔒 Security — đánh giá tốt

| Kiểm tra                                                         | Trạng thái         |
| ---------------------------------------------------------------- | ------------------ |
| Auth server binds localhost only (`127.0.0.1`)                   | ✅                 |
| CSRF state token 32-byte random + validated                      | ✅                 |
| Body size limit 10KB                                             | ✅                 |
| Cache file `0o600`                                               | ✅                 |
| API key trong `Authorization: Bearer` (không query string)       | ✅                 |
| Không leak key trong log/error                                   | ✅                 |
| Token storage plaintext JSON (chuẩn pi ecosystem, không encrypt) | ⚠️ chuẩn ecosystem |

## 5. Điểm mạnh / Điểm yếu

### ✅ Điểm mạnh

- **Kiến trúc DI toàn diện** — core.ts testable, mọi side-effect injectable (fetchImpl, now, uuid, delay, fs paths).
- **Test coverage xuất sắc** — mock HTTP server thật (không monkeypatch global); 12 file test ~2.968 dòng; 10 TS + 2 E2E `.mjs` (SKIP graceful nếu pi/omp không trên PATH).
- **Auth flow bảo mật** — localhost bind + CSRF state + body limit + bracketed-paste sanitize.
- **Resilience tốt** — 3-stage model fallback, retry với Retry-After + backoff+jitter, no-retry-after-output rule đúng (tránh duplicate).
- **Tuân thủ pi best practices** — `peerDependencies` optional, `registerProvider`, TS strict, node:test, 0 runtime deps, `.ts` imports, full docs suite.
- **Pure/IO separation** — `converters.ts` zero I/O → dễ test đơn vị.

### ❌ Điểm yếu

- **Hardcode nhiều**: `temperature 0.3`, `reasoning:true`, `maxTokens 64K`, `DEFAULT_MAX_RETRIES = 0` (retry dormant mặc định).
- **Pricing tĩnh** — 25 entries, dễ lạc hậu khi Command Code thêm model; model thiếu hiển thị $0 gây hiểu lầm.
- **Version mismatch** package.json vs CHANGELOG.
- **Header mystery** (`x-taste-learning`, `x-co-flag`) không document.
- **CORS default** permissive cho unknown origin.

## 6. Khuyến nghị ưu tiên

| Priority | Item                                                                                     | Effort              | Impact  |
| -------- | ---------------------------------------------------------------------------------------- | ------------------- | ------- |
| **P0**   | Verify `threadId` behavior — nếu API dùng nó, đây là **bug** (mỗi request = new session) | Thấp (test thực tế) | Cao     |
| **P1**   | Tách `MODEL_COSTS` ra `src/pricing.ts` — fix fragile `test-pricing.ts` regex             | ~30 min             | TB      |
| **P1**   | Document `COMMANDCODE_AUTH_TIMEOUT_MS` + tất cả env vars trong README                    | ~15 min             | TB      |
| **P1**   | Bump `package.json` → 0.4.4 match CHANGELOG                                              | ~5 min              | Thấp    |
| **P2**   | Thêm `StreamOptions.temperature` override                                                | ~30 min             | TB      |
| **P2**   | Verify `config` object: có cần project context thực?                                     | TB (API docs)       | Cao     |
| **P2**   | CORS: reject unknown origins                                                             | ~15 min             | Thấp-TB |
| **P3**   | Per-model `reasoning` flag (thay hardcode true)                                          | TB                  | Thấp    |
| **P3**   | Document `x-taste-learning` / `x-co-flag` headers                                        | Thấp                | Thấp    |
| **P3**   | Rename `getApiKey` collision                                                             | Thấp                | Thấp    |

## 7. Câu hỏi mở (cần Command Code team / test thực tế)

1. API có dùng `threadId` cho session tracking không?
2. `config` object có cần project context thực (git status, structure, recent commits) không?
3. `x-taste-learning` / `x-co-flag` ảnh hưởng gì?
4. API có kế hoạch trả pricing trong catalog không?
5. `reasoning:true` cho non-reasoning model có gây degraded behavior không?
6. pi host có truyền `maxRetries` qua `StreamOptions` không? (default=0 → retry dormant)
7. pi host có dùng `onPayload` hook để inject real config không?

---

_Nguồn: pi-crew run `team_20260806102256_368eb2ddf4e6f7df` (research team). Artifact đầy đủ: `.crew/artifacts/<runId>/transcripts/`._
