@mawaru/sdk 0.9.0 → 0.11.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.
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from "vitest"
2
- import { aiManifestSchema } from "./ai-manifest.js"
2
+ import { AI_MODELS, aiManifestSchema } from "./ai-manifest.js"
3
3
  import { envelopeSchemaOf, instructionSchema } from "./port-spec.js"
4
4
 
5
5
  const envelope = envelopeSchemaOf({ type: "string" })
@@ -32,11 +32,18 @@ describe("aiManifestSchema", () => {
32
32
  outputs: { main: envelope },
33
33
  })
34
34
  expect(manifest.name).toBeUndefined()
35
- expect(manifest.model).toBe("claude-opus-4-8")
35
+ expect(manifest.model).toBe("claude-opus-5")
36
36
  expect(manifest.skills).toEqual([])
37
37
  expect(manifest.env).toEqual([])
38
38
  })
39
39
 
40
+ it("model は AI_MODELS の enum(バージョン固定。外の値は拒否)", () => {
41
+ for (const model of AI_MODELS) {
42
+ expect(aiManifestSchema.parse({ ...valid, model }).model).toBe(model)
43
+ }
44
+ expect(() => aiManifestSchema.parse({ ...valid, model: "opus" })).toThrow()
45
+ })
46
+
40
47
  it("prompt は必須・非空(repo に置く時点で完成品)", () => {
41
48
  expect(() => aiManifestSchema.parse({ ...valid, prompt: "" })).toThrow()
42
49
  const { prompt: _prompt, ...rest } = valid
@@ -2,15 +2,18 @@ import { z } from "zod"
2
2
  import { jsonSchemaSchema } from "./node.js"
3
3
  import { isAiEnvelopeSchema, manifestInKeysViolation } from "./port-spec.js"
4
4
 
5
- // AI ノードのモデル選択肢(既定は Opus:下書き品質が価値の中心。費用はユーザー持ち)
5
+ // AI ノードのモデル選択肢(既定は Opus:下書き品質が価値の中心。費用はユーザー持ち)。
6
+ // エイリアス("opus" 等)は採らずバージョンを固定する:実行のたびに黙って別モデルへ
7
+ // 乗り換わると品質も費用も再現しないため。新モデルが出たらこの配列を足して SDK を publish する
6
8
  export const AI_MODELS = [
9
+ "claude-opus-5",
7
10
  "claude-opus-4-8",
8
11
  "claude-sonnet-5",
9
12
  "claude-haiku-4-5",
10
13
  ] as const
11
14
  export const aiModelSchema = z.enum(AI_MODELS)
12
15
  export type AiModel = z.infer<typeof aiModelSchema>
13
- export const DEFAULT_AI_MODEL = "claude-opus-4-8" satisfies AiModel
16
+ export const DEFAULT_AI_MODEL = "claude-opus-5" satisfies AiModel
14
17
 
15
18
  // nodes/ai/<dir>/config.json(実行repoの構造見直し)。AI ノードの定義(prompt/model/skills/
16
19
  // 入出力スキーマ/env)は repo 側が正で、エディタが取り込んで ports を自動生成する
@@ -1,17 +1,19 @@
1
1
  import { z } from "zod";
2
- export declare const AI_MODELS: readonly ["claude-opus-4-8", "claude-sonnet-5", "claude-haiku-4-5"];
2
+ export declare const AI_MODELS: readonly ["claude-opus-5", "claude-opus-4-8", "claude-sonnet-5", "claude-haiku-4-5"];
3
3
  export declare const aiModelSchema: z.ZodEnum<{
4
+ "claude-opus-5": "claude-opus-5";
4
5
  "claude-opus-4-8": "claude-opus-4-8";
5
6
  "claude-sonnet-5": "claude-sonnet-5";
6
7
  "claude-haiku-4-5": "claude-haiku-4-5";
7
8
  }>;
8
9
  export type AiModel = z.infer<typeof aiModelSchema>;
9
- export declare const DEFAULT_AI_MODEL = "claude-opus-4-8";
10
+ export declare const DEFAULT_AI_MODEL = "claude-opus-5";
10
11
  export declare const aiManifestSchema: z.ZodObject<{
11
12
  name: z.ZodOptional<z.ZodString>;
12
13
  description: z.ZodOptional<z.ZodString>;
13
14
  prompt: z.ZodString;
14
15
  model: z.ZodDefault<z.ZodEnum<{
16
+ "claude-opus-5": "claude-opus-5";
15
17
  "claude-opus-4-8": "claude-opus-4-8";
16
18
  "claude-sonnet-5": "claude-sonnet-5";
17
19
  "claude-haiku-4-5": "claude-haiku-4-5";
@@ -1,14 +1,17 @@
1
1
  import { z } from "zod";
2
2
  import { jsonSchemaSchema } from "./node.js";
3
3
  import { isAiEnvelopeSchema, manifestInKeysViolation } from "./port-spec.js";
4
- // AI ノードのモデル選択肢(既定は Opus:下書き品質が価値の中心。費用はユーザー持ち)
4
+ // AI ノードのモデル選択肢(既定は Opus:下書き品質が価値の中心。費用はユーザー持ち)。
5
+ // エイリアス("opus" 等)は採らずバージョンを固定する:実行のたびに黙って別モデルへ
6
+ // 乗り換わると品質も費用も再現しないため。新モデルが出たらこの配列を足して SDK を publish する
5
7
  export const AI_MODELS = [
8
+ "claude-opus-5",
6
9
  "claude-opus-4-8",
7
10
  "claude-sonnet-5",
8
11
  "claude-haiku-4-5",
9
12
  ];
10
13
  export const aiModelSchema = z.enum(AI_MODELS);
11
- export const DEFAULT_AI_MODEL = "claude-opus-4-8";
14
+ export const DEFAULT_AI_MODEL = "claude-opus-5";
12
15
  // nodes/ai/<dir>/config.json(実行repoの構造見直し)。AI ノードの定義(prompt/model/skills/
13
16
  // 入出力スキーマ/env)は repo 側が正で、エディタが取り込んで ports を自動生成する
14
17
  // (実行時の正は ports テーブルのまま。プログラム規約 v2 と同じ関係)。
package/dist/cli.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,15 +1,20 @@
1
1
  {
2
2
  "name": "@mawaru/sdk",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "mawaru 実行 repo の開発 SDK。契約スキーマ(config.json 規約・ループ graph API)の正 + typegen / validate CLI",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "mawaru": "dist/cli.js"
8
8
  },
9
9
  "exports": {
10
- ".": {
11
- "types": "./dist/index.d.ts",
12
- "default": "./dist/index.js"
10
+ ".": "./index.ts"
11
+ },
12
+ "publishConfig": {
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
13
18
  }
14
19
  },
15
20
  "files": [
@@ -23,6 +28,14 @@
23
28
  "engines": {
24
29
  "node": ">=20"
25
30
  },
31
+ "scripts": {
32
+ "build": "tsc -p tsconfig.build.json",
33
+ "prepack": "pnpm build",
34
+ "typecheck": "tsc --noEmit",
35
+ "test": "vitest run",
36
+ "test:watch": "vitest",
37
+ "release": "sh -c 'pnpm typecheck && pnpm test && npm version --no-git-tag-version ${1:-minor} && npm publish --access public' release"
38
+ },
26
39
  "dependencies": {
27
40
  "zod": "^4.4.3",
28
41
  "zod-from-json-schema": "^0.5.3"
@@ -31,11 +44,5 @@
31
44
  "@types/node": "^26.1.0",
32
45
  "typescript": "^6.0.3",
33
46
  "vitest": "^4.1.9"
34
- },
35
- "scripts": {
36
- "build": "tsc -p tsconfig.build.json",
37
- "typecheck": "tsc --noEmit",
38
- "test": "vitest run",
39
- "test:watch": "vitest"
40
47
  }
41
- }
48
+ }
@@ -14,19 +14,33 @@ repo ルートの `.env` に以下の4変数が揃っているか確認する。
14
14
  セットアップまで面倒を見る**(ユーザーに手作業のセットアップを求めない):
15
15
 
16
16
  1. `.gitignore` に `.env` が入っていることを確認する。無ければ追加する(API キーをコミットさせない)。
17
- 2. `.env` を作成・追記する:
17
+ 2. `.env` を作成・追記する。**足りない変数は推測で埋めず、その場でユーザーに聞く**(下の
18
+ 「環境変数が足りないとき」の原則に従う):
18
19
  - `MAWARU_API_URL` — API のベース URL(例: `https://api.mawaru.ai`。ローカル開発は `http://localhost:9000`)
19
20
  - `MAWARU_APP_URL` — フロントの URL(例: `https://app.mawaru.ai`。ローカル開発は `http://localhost:3000`)
20
21
  - `MAWARU_TENANT_ID` — tenant の ID
21
22
  - `MAWARU_API_KEY` — tenant の API キー
22
- 接続先が本番かローカルかはユーザーに確認する。API キーは mawaru のテナント設定画面
23
- (`{MAWARU_APP_URL}/settings` の「API キー」。admin のみ)で発行・コピーできるので、
24
- ユーザーに案内して値を入力してもらう。**キーの値をチャット・ログ・コミットに出さない。**
23
+ 接続先が本番かローカルかはユーザーに確認する(URL 2つはこれで決まる)。API キーは mawaru
24
+ テナント設定画面(`{MAWARU_APP_URL}/settings` の「API キー」。admin のみ)で発行・コピーできるので、
25
+ 発行手順を案内したうえで `.env` に入れてもらう。**キーの値をチャット・ログ・コミットに出さない。**
25
26
  3. 疎通確認:`GET {MAWARU_API_URL}/tenants/{MAWARU_TENANT_ID}/loops` が 200 を返せば完了。
26
27
  401 なら API キー、404 なら tenant ID を疑う。
27
28
 
28
29
  認証は全リクエスト共通でヘッダ `x-api-key: $MAWARU_API_KEY`。
29
30
 
31
+ ## 環境変数が足りないとき(全体の原則)
32
+
33
+ このスキルの `.env` でも、ノードの `env` 宣言(program / ai の handler・setup.sh・prompt が使う
34
+ secret)でも、**足りない値を推測・生成・空文字で代用しない。作業を止めてユーザーに対話的に聞く。**
35
+
36
+ - 足りないものは**まとめて1回で聞く**:変数名・何に使う値か・どこで取れるか(画面・発行手順)・
37
+ 形式の例を添える。答えを待ってから作業を再開する(タイムアウトを承認扱いにしない)。
38
+ - **秘密の値はチャットに書かせない・出力しない**。`.env` へはユーザー自身の手で追記してもらう
39
+ (例: `echo 'MAWARU_API_KEY=xxxx' >> .env` を実行してもらう)。ノードの `env` 宣言分は
40
+ 実行 repo の Settings → Secrets and variables → Actions に登録してもらい、こちらは**名前だけ**扱う。
41
+ - 受け取ったら「効いていること」まで確かめてから次へ進む(`.env` なら疎通確認、
42
+ Actions secrets なら名前が config.json の `env` と一致していること)。
43
+
30
44
  ## 契約の読み方(最重要)
31
45
 
32
46
  **API のボディ形をこの文書は説明しない。正はこのパッケージ内の Zod スキーマなので、必ずソースを読むこと**:
@@ -62,6 +76,7 @@ repo との矛盾・使用中ノードの削除は 409。**graph PUT は冪等
62
76
  1. **設計**:要件から必要なノード(program / ai / human / wait)と流れを決め、ユーザーに一言で確認する。
63
77
  2. **repo 側の準備**:足りない program / ai は `nodes/program/<dir>/` / `nodes/ai/<dir>/` に作る
64
78
  (config.json → `npx mawaru typegen` → main.ts 実装 → `npx mawaru validate`)。
79
+ **AI ノードの決定論的な処理は prompt ではなく `setup.sh` に書く**(下記)。
65
80
  **作った・変えたものは GitHub へ push してから次へ進む**(mawaru は repo を GitHub 経由で
66
81
  読むため、未 push だと graph 保存の検証・書き戻しと食い違って 409 になる)。
67
82
  3. **ループ作成**:`POST loops`。
@@ -78,6 +93,35 @@ repo との矛盾・使用中ノードの削除は 409。**graph PUT は冪等
78
93
  6. **報告**:エディタ URL `{MAWARU_APP_URL}/loops/{loopId}/edit` をユーザーに渡し、
79
94
  見た目の確認と run はユーザーに委ねる。
80
95
 
96
+ ## AI ノード:決定論的な処理は prompt でなく setup.sh に書く
97
+
98
+ やることが決まっている準備=**外部 repo の clone / skill の持ち込み / 認証キーのファイル化 /
99
+ ツールの用意**は、prompt で AI にやらせず `nodes/ai/<dir>/setup.sh` に書く。prompt には
100
+ 「どこに何が置いてあるか」と、そこから先の判断だけを書く。
101
+
102
+ 理由:LLM にやらせるとトークンを食い flaky で、失敗が「セットアップの失敗」として明瞭に出ない。
103
+ skill の配置は Claude Code 起動前に完了している必要もある。
104
+
105
+ 規約(実行 repo 側。config.json への宣言は不要、ファイルの存在が正):
106
+
107
+ ```bash
108
+ # nodes/ai/<dir>/setup.sh
109
+ set -euo pipefail
110
+ git clone --depth 1 "https://x-access-token:${SOME_REPO_TOKEN}@github.com/owner/repo.git" workspace/repo
111
+ cp -r workspace/repo/.claude/skills/some-skill skills/ # copySkills の前に走るので自動発見に乗る
112
+ printf '%s' "$SOME_SA_KEY" > workspace/key.json
113
+ ```
114
+
115
+ - 実行順は `env 注入 → input.json 書き出し → setup.sh → copySkills → 本体(Claude Code)`。
116
+ `bash nodes/ai/<dir>/setup.sh "$INPUT_JSON"`(実行ビット不要)、cwd は checkout ルート。
117
+ - **入力は `$1`(JSON 文字列)か `input.json`** で参照できる(`jq` はランナー同梱)。
118
+ - **環境変数は config.json の `env` 宣言分だけ**が注入される。必要な secret は `env` に宣言し、
119
+ 実行 repo の Actions secrets に登録してもらう(→「環境変数が足りないとき」)。
120
+ - **受け渡しはファイルで**。別プロセスなので `export` は本体に引き継がれない。clone 先・キーは
121
+ ワークスペース内の既知パス(`workspace/` 配下を推奨)に置き、prompt / skill はそのパスを参照する。
122
+ - **非 0 exit は step failed**(本体は実行されない)。`set -euo pipefail` を付ける。
123
+ - program ノードにも同じ規約が効く(`nodes/program/<dir>/setup.sh`)。
124
+
81
125
  ## 注意
82
126
 
83
127
  - **graph PUT は全量置換**。既存ループを更新するときは、必ず先に `GET loops/{loopId}` で