Files
log/my-blog/content/posts/2025-11-18-aicard.md
2025-11-19 06:39:10 +09:00

122 lines
3.5 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)
> 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>
### 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
```