# dev-corp Pi Settings Guide

Pi를 dev-corp `gemma4:26b`로 사용하기 위한 최소 설치/설정 기준이다.

## 설치

Pi `0.80.3`은 Node.js `22.19.0` 이상이 필요하다.

```bash
node --version
npm --version
npm install -g @earendil-works/pi-coding-agent@0.80.3
pi --version
```

`pi --version`이 `0.80.3`이면 정상이다.

## 설정 파일

설정 위치:

```text
~/.pi/agent/settings.json
~/.pi/agent/models.json
```

디렉터리가 없으면 만든다.

```bash
mkdir -p ~/.pi/agent/extensions
```

## settings.json

```json
{
  "defaultProvider": "dev-corp",
  "defaultModel": "gemma4:26b",
  "defaultThinkingLevel": "high",
  "hideThinkingBlock": false,
  "httpIdleTimeoutMs": 0,
  "retry": {
    "provider": {
      "maxRetries": 0,
      "maxRetryDelayMs": 60000
    }
  },
  "enabledModels": [
    "dev-corp/*"
  ],
  "extensions": [
    "extensions/dev-corp-temperature.ts"
  ]
}
```

기존 `theme`, `lastChangelogVersion` 같은 개인 설정은 유지해도 된다.

## sampling parameter extension

Pi `0.80.3`의 `models.json` provider/model schema에는 고정 sampling parameter 필드가 없다. dev-corp Pi 호출의 `temperature`와 `top_p`는 전역 extension의 `before_provider_request` hook으로 적용한다.

파일 위치:

```text
~/.pi/agent/extensions/dev-corp-temperature.ts
```

내용:

```typescript
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";

const DEV_CORP_PROVIDER = "dev-corp";
const DEV_CORP_TEMPERATURE = 0.2;
const DEV_CORP_TOP_P = 0.9;

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

export default function (pi: ExtensionAPI) {
  pi.on("before_provider_request", (event, ctx) => {
    if (ctx.model?.provider !== DEV_CORP_PROVIDER) return;
    if (!isRecord(event.payload)) return;

    return {
      ...event.payload,
      temperature: DEV_CORP_TEMPERATURE,
      top_p: DEV_CORP_TOP_P,
    };
  });
}
```

이 extension은 provider가 `dev-corp`일 때만 요청 payload에 `temperature: 0.2`, `top_p: 0.9`를 추가한다. `dev-corp-direct`, `dev-corp-spark01` 같은 direct provider에는 적용하지 않는다.

반복 출력 loop를 피하기 위한 Pi dev-corp profile의 최소 기준은 `temperature: 0.2`, `top_p: 0.9`다. 그래도 repetition loop가 발생하면 extension의 `DEV_CORP_TEMPERATURE`는 조금씩 올리고 `DEV_CORP_TOP_P`는 조금씩 낮추는 방향으로 조정한다.

## models.json

`apiKey`에는 실제 토큰을 넣는다. 토큰은 문서, 로그, 공유 화면에 남기지 않는다.

```json
{
  "providers": {
    "dev-corp": {
      "baseUrl": "http://digitalplatform.iop.ai.kr:18086/v1",
      "api": "openai-completions",
      "apiKey": "<token>",
      "authHeader": true,
      "compat": {
        "supportsStore": false,
        "supportsDeveloperRole": false,
        "supportsReasoningEffort": false,
        "supportsUsageInStreaming": false,
        "maxTokensField": "max_tokens",
        "requiresToolResultName": true,
        "requiresAssistantAfterToolResult": true,
        "supportsStrictMode": false
      },
      "models": [
        {
          "id": "gemma4:26b",
          "name": "dev-corp gemma4:26b",
          "reasoning": true,
          "input": ["text"],
          "contextWindow": 262144,
          "maxTokens": 32768,
          "cost": {
            "input": 0,
            "output": 0,
            "cacheRead": 0,
            "cacheWrite": 0
          }
        }
      ]
    }
  }
}
```

## 주의

- `supportsReasoningEffort`는 `false`로 둔다.
- `think=false`, `reasoning_effort=none`, `thinking_token_budget`을 강제로 추가하지 않는다.
- dev-corp Pi 호출 sampling parameter는 `~/.pi/agent/extensions/dev-corp-temperature.ts`로 `temperature: 0.2`, `top_p: 0.9`를 주입한다.
- repetition loop가 계속 발생하면 extension에서 temperature는 올리고 top_p는 낮추는 방향으로 조정한다.
- Pi는 `openai-completions` 기준으로 streaming 호출을 기본 사용한다. non-stream이 필요한 경우는 Pi가 아니라 일반 OpenAI-compatible 호출에서 `stream:false`로 선택한다.
- reasoning 표시 여부는 Pi UI나 client 표시 정책에서 선택적으로 처리한다.
- 장시간 local inference를 위해 `httpIdleTimeoutMs`는 `0`으로 비활성화하고 `retry.provider.timeoutMs`는 설정하지 않는다.
- 이미 실행 중인 Pi session에는 `/reload` 또는 재시작 후 extension 변경을 반영한다.

## 확인

```bash
pi --version
jq '{
  defaultProvider,
  defaultModel,
  defaultThinkingLevel,
  hideThinkingBlock,
  httpIdleTimeoutMs,
  providerTimeoutPresent: (.retry.provider | has("timeoutMs")),
  extensions
}' ~/.pi/agent/settings.json
test -f ~/.pi/agent/extensions/dev-corp-temperature.ts
jq '.providers["dev-corp"] | {
  baseUrl,
  api,
  hasApiKey: has("apiKey"),
  authHeader,
  compat,
  models
}' ~/.pi/agent/models.json
```

## Codex/Claude 작업 프롬프트

```text
현재 호스트의 Pi를 dev-corp gemma4:26b 기준으로 설치/설정해줘.

수정 가능:
- Pi 설치
- ~/.pi/agent/settings.json
- ~/.pi/agent/models.json
- ~/.pi/agent/extensions/dev-corp-temperature.ts

수정 금지:
- 이 저장소 코드와 설정
- 서버/모델 실행 설정
- 토큰 원문 출력

설치:
- Node.js >=22.19.0 확인
- npm install -g @earendil-works/pi-coding-agent@0.80.3
- pi --version이 0.80.3인지 확인

settings.json:
- defaultProvider: dev-corp
- defaultModel: gemma4:26b
- defaultThinkingLevel: high
- hideThinkingBlock: false
- httpIdleTimeoutMs: 0
- retry.provider.timeoutMs: 제거하거나 설정하지 않음
- retry.provider.maxRetries: 0
- retry.provider.maxRetryDelayMs: 60000
- enabledModels: ["dev-corp/*"]
- extensions: ["extensions/dev-corp-temperature.ts"]

sampling parameter extension:
- 파일: ~/.pi/agent/extensions/dev-corp-temperature.ts
- before_provider_request hook에서 ctx.model.provider가 dev-corp일 때만 payload.temperature를 0.2, payload.top_p를 0.9로 설정
- dev-corp-direct, dev-corp-spark01에는 적용하지 않음

models.json:
- providers.dev-corp.baseUrl: http://digitalplatform.iop.ai.kr:18086/v1
- providers.dev-corp.api: openai-completions
- providers.dev-corp.apiKey: 기존 값이 있으면 보존하고, 없으면 사용자에게 토큰을 요청
- providers.dev-corp.authHeader: true
- compat.supportsStore: false
- compat.supportsDeveloperRole: false
- compat.supportsReasoningEffort: false
- compat.supportsUsageInStreaming: false
- compat.maxTokensField: max_tokens
- compat.requiresToolResultName: true
- compat.requiresAssistantAfterToolResult: true
- compat.supportsStrictMode: false
- model id: gemma4:26b
- model name: dev-corp gemma4:26b
- reasoning: true
- input: ["text"]
- contextWindow: 262144
- maxTokens: 32768

think=false, reasoning_effort=none, thinking_token_budget 설정은 추가하지 마.
검증 출력에는 apiKey 원문을 포함하지 말고 hasApiKey boolean만 보여줘.
이미 실행 중인 Pi session에는 /reload 또는 재시작이 필요하다고 안내해줘.
```
