Files
log/my-blog/content/posts/2025-11-18-aicard.md
2025-11-21 05:13:23 +09:00

152 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "claude code webを使い切った"
slug: "aicard"
date: "2025-11-18"
tags: ["react", "ios"]
language: ["ja", "en"]
draft: false
---
11/18までの無料配布のtokenがあります。今回はギリギリ使い切れました。`anthropic`に感謝。
[https://support.claude.com/en/articles/12690958-claude-code-promotion](https://support.claude.com/en/articles/12690958-claude-code-promotion)
[msg type="info" content="claudeは性能劣化、limitの多発、突然動かなくなる現象が多発した時期があり、plan:maxでもほとんど使えない期間がありました。1ヶ月間、ほとんど使わなかったのにplan:maxは無駄だったという経験から、それ以降はplan:proに切り替えています。claudeが使えなくなった期間は他のサービスを使っていました。"]
今回は、特に印象的だったことを紹介。
## 色々作っていた
全部自分で作っていたものをベースにclaudeに書き直してもらったり、あるいは、一緒に最初から設計を考え直したりといった作業でした。
```json
{
"ai" : ["gpt", "shell", "os", "app", "bot", "card"]
}
```
## aicard for ios
`ai.card`, つまり、`aicard for ios`に関しては、ueで書いていたものを全部作り直しました。
今回は`react + expo`という構成ですが、あのままueで作り続けていたら、やばかった。
<iframe width="100%" height="415" src="https://www.youtube.com/embed/KIwzBlluVKc?rel=0&showinfo=0&controls=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
### build
```sh
nvm use 24
npm i
npx expo prebuild --clean
# CocoaPodsのPATH問題を解決
# echo 'export PATH="/opt/homebrew/lib/ruby/gems/3.4.0/bin:$PATH"' >> ~/.zshrc;source ~/.zshrc
cd ios;pod install;cd ..
open ios/Aicard.xcodeproj
# - Signing & Capabilities タブを開く
# - Team idを指定(Apple Developer アカウント)
# - Xcodeは開いたまま次へ
npx expo run:ios --device --configuration Release
# apple store用の.xcarchiveを作ります。
xcodebuild -workspace ios/Aicard.xcworkspace \
-scheme Aicard \
-configuration Release \
-archivePath build/Aicard.xcarchive \
-allowProvisioningUpdates \
archive
open ./build/Aicard.xcarchive
# Distribute App ボタンをクリック
# App Store Connect を選択
```
### atproto oauth
1. PKCE生成 → PAR → Authorization → Callback
2. Token ExchangeDPoP nonce自動リトライ
3. Profile取得DPoP + ath
4. Session保存
`Universal Links`
```json:apple-app-site-association.json
{
"applinks": {
"apps": [],
"details": [{
"appID": "{apple-dev}.{id}",
"paths": ["/oauth/callback"]
}]
}
}
```
#### 1. ellipticへの移行
**解決策**: ES256署名を`elliptic`ライブラリで実装
```js
import elliptic from 'elliptic';
const EC = elliptic.ec;
const ec = new EC('p256');
const key = ec.genKeyPair();
```
**成功**: DPoP proof JWTの生成に成功
#### 2. DPoP nonce対応
**問題**: トークン交換時に`use_dpop_nonce`エラー
**解決策**: 自動リトライロジック実装
```js
// 1回目失敗 → DPoP-Nonceヘッダー取得 → 2回目成功
if (errorData.error === 'use_dpop_nonce') {
const nonce = response.headers.get('DPoP-Nonce');
// nonceを含めてリトライ
}
```
#### 3. プロファイル取得エラー
**問題**: `DPoP "ath" mismatch`エラー
```
{"error":"invalid_dpop_proof","message":"DPoP \"ath\" mismatch"}
```
**原因**: プロファイル取得時のDPoPプルーフにaccess token hash (`ath`) が欠落
**解決策**: `generateDPoPProof`に`accessToken`パラメータ追加
```js
// アクセストークンのSHA-256ハッシュを計算
if (accessToken) {
const tokenHash = await Crypto.digestStringAsync(
Crypto.CryptoDigestAlgorithm.SHA256,
accessToken,
{ encoding: Crypto.CryptoEncoding.BASE64 }
);
payload.ath = base64UrlEncode(tokenHash);
}
```
### glb
結論から言うと、`react-native-filament`を使います。
`three`でやる通常の方法ではうまくテクスチャが表示されませんでした。
```diff
+ react-native-filament
- expo-three, expo-gl
```