Skip to content
cccskills
FreePublished on GitHub

kb-frontend-sse

SSEストリーミング処理のナレッジ。基本パターン/タイムアウト/リトライ/モック/PDF生成等

The English summary is being prepared. Showing the original description.

See how to install

Files included (1)

  • SKILL.md6.8 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

SSEストリーミング処理

SSE(Server-Sent Events)を使ったフロントエンドのストリーミング処理パターンを記録する。

基本パターン

const reader = response.body?.getReader();
const decoder = new TextDecoder();
let buffer = '';

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  buffer += decoder.decode(value, { stream: true });
  const lines = buffer.split('\n');
  buffer = lines.pop() || '';  // 不完全な行は次回に持ち越し

  for (const line of lines) {
    if (line.startsWith('data: ')) {
      const data = line.slice(6);
      if (data === '[DONE]') return;
      try {
        const event = JSON.parse(data);
        handleEvent(event);
      } catch {
        // JSONパースエラーは無視
      }
    }
  }
}

イベントハンドリング

function handleEvent(event) {
  // APIによってcontent/dataのどちらかにペイロードが入る
  const textValue = event.content || event.data;

  switch (event.type) {
    case 'text':
      onText(textValue);
      break;
    case 'tool_use':
      onToolUse(textValue);  // ツール名が返る
      break;
    case 'markdown':
      onMarkdown(textValue);
      break;
    case 'error':
      onError(new Error(event.error || event.message || textValue));
      break;
  }
}

エラーハンドリング

// ストリーミング中のエラー
case 'error':
  if (event.error || event.message) {
    callbacks.onError(new Error(event.error || event.message));
  }
  break;

// HTTPエラー
const response = await fetch(url, options);
if (!response.ok) {
  throw new Error(`API Error: ${response.status} ${response.statusText}`);
}

アイドルタイムアウト(2段構成)

SSEストリームに2段階のタイムアウトを設定し、接続障害と推論ハングの両方を検知するパターン:

async function readSSEStream(
  reader: ReadableStreamDefaultReader<Uint8Array>,
  onEvent: (event: Record<string, unknown>) => void,
  idleTimeoutMs?: number,          // 初回イベント受信前(短め: 10秒)
  ongoingIdleTimeoutMs?: number    // イベント間(長め: 60秒)
): Promise<void> {
  let firstEventReceived = false;

  while (true) {
    // フェーズに応じてタイムアウト値を切り替え
    const currentTimeout = firstEventReceived ? ongoingIdleTimeoutMs : idleTimeoutMs;
    if (currentTimeout) {
      const timeoutPromise = new Promise<never>((_, reject) => {
        setTimeout(() => reject(new SSEIdleTimeoutError(currentTimeout)), currentTimeout);
      });
      readResult = await Promise.race([reader.read(), timeoutPromise]);
    } else {
      readResult = await reader.read();
    }
    // ... イベント処理後に firstEventReceived = true
  }
}
フェーズタイムアウト検知対象
初回イベント受信前短め(10秒)スロットリング、接続エラー
イベント間(初回受信後)長め(60秒)推論ハング、モデル無応答

設計ポイント:

  • 初回タイムアウトは短く → ユーザーを素早くエラーに気づかせる
  • イベント間タイムアウトは長めに → 正常な推論やツール実行を妨げない

モック実装(ローカル開発用)

※ モックは既定ではない。実物のバックエンドへつないで作る実装ファーストが原則で、これは AWS 認証が無い環境で UI だけ確認する等の限定用途。

export async function invokeAgentMock(prompt, callbacks) {
  const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

  const thinkingText = `${prompt}について考えています...`;
  for (const char of thinkingText) {
    callbacks.onText(char);
    await sleep(20);
  }

  callbacks.onStatus('生成中...');
  await sleep(1000);

  callbacks.onMarkdown('# 生成結果\n\n...');
  callbacks.onComplete();
}

// 環境変数で切り替え
const useMock = import.meta.env.VITE_USE_MOCK === 'true';
const invoke = useMock ? invokeAgentMock : invokeAgent;

エクスポートのリトライパターン(ネットワーク耐性)

SSE経由のファイルエクスポート(PDF/PPTX等)は、不安定なネットワークでストリームが切断されることがある:

export async function exportSlide(
  markdown: string,
  format: ExportFormat,
  theme: string = 'border'
): Promise<Blob> {
  const MAX_RETRIES = 1;
  let lastError: Error | null = null;

  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
    try {
      return await _exportSlideOnce(markdown, format, theme);
    } catch (e) {
      lastError = e as Error;
      if (attempt < MAX_RETRIES) {
        console.warn(`Export failed (attempt ${attempt + 1}), retrying...`, e);
        await new Promise(r => setTimeout(r, 1000));
      }
    }
  }
  throw lastError!;
}

ポイント:

  • SSE reader.read() が done: true を返しても resultBlob が null = ストリーム切断
  • リトライは1回(計2回)で十分
  • バックエンド側のkeep-alive(5秒ごとの progress イベント)と組み合わせるとさらに効果的

PDF生成(Base64デコード・ダウンロード)

export async function exportPdf(markdown: string): Promise<Blob> {
  const response = await fetch(url, {
    method: 'POST',
    headers: { /* 認証ヘッダー等 */ },
    body: JSON.stringify({ action: 'export_pdf', markdown }),
  });

  const reader = response.body?.getReader();
  const decoder = new TextDecoder();
  let buffer = '';

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    buffer += decoder.decode(value, { stream: true });
    const lines = buffer.split('\n');
    buffer = lines.pop() || '';

    for (const line of lines) {
      if (line.startsWith('data: ')) {
        const event = JSON.parse(line.slice(6));
        if (event.type === 'pdf' && event.data) {
          const binaryString = atob(event.data);
          const bytes = new Uint8Array(binaryString.length);
          for (let i = 0; i < binaryString.length; i++) {
            bytes[i] = binaryString.charCodeAt(i);
          }
          return new Blob([bytes], { type: 'application/pdf' });
        }
      }
    }
  }
  throw new Error('PDF生成に失敗しました');
}

// ダウンロード処理
const blob = await exportPdf(markdown);
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'slide.pdf';
a.click();
URL.revokeObjectURL(url);

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Deploy, diff, bootstrap, inspect, roll back, or destroy AWS CDK applications with the community CDKD CLI while preserving safe production and state-management boundaries. Use when the user mentions cdkd or CDK Direct, asks for faster CDK deployments in development or test environments, or wants to evaluate whether an existing CDK app can use CDKD. Also use for CDKD import, export, state, events, and deployment troubleshooting. Prefer the upstream AWS CDK CLI for production and for existing CloudFormation-managed stacks unless the user explicitly approves a management migration.

The English summary is being prepared. Showing the original description.

minorun365/agent-builder-skills41Updated Oct 14, 2026

AIエージェントのWebアプリを「AWS CDK(デプロイはCDKD)+ S3 + CloudFront + AgentCore Runtime」で組むときの全体構成。画面は S3 から静的に配信し、サーバー側の処理が要るときだけ Lambda Web Adapter(または Lambda Web Functions)を足す判断基準。スタックの分け方、BucketDeployment での配置とキャッシュ指定、SPA の振り分け、runtime-config.json で環境値を渡す型、Lambda を足すときの Function URL と CloudFront OAC の権限、フロントから AgentCore を直接呼ぶ配線、ローカル開発、デプロイ前後の検証。新しくエージェントのWebアプリを作るとき、Amplify Hosting 以外の配信基盤を選ぶとき、画面の配信に Lambda が要るか迷ったとき、CloudFront 経由の Function URL が 403 になるときに読む。

The English summary is being prepared. Showing the original description.

minorun365/agent-builder-skills41Updated Oct 14, 2026

AgentCore CDK・デプロイ・ランタイム統合のナレッジ。Runtime作成、JWT認証、SSE、Dockerfile、コンテナ管理、Browser Tool等

The English summary is being prepared. Showing the original description.

minorun365/agent-builder-skills41Updated Oct 14, 2026

AgentCore Identity(アウトバウンド認証)のナレッジ。3LO/M2M/デコレータ分離/callback等

The English summary is being prepared. Showing the original description.

minorun365/agent-builder-skills41Updated Oct 14, 2026

AgentCore の Observability ナレッジ。OpenTelemetry 必須4点セット(OTEL_EXPORTER設定・StrandsTelemetry・traceable デコレータ・Langfuse連携)、EMF メトリクス、Jaeger/コンソールエクスポーターでのトレース確認、トレースが出ない・繋がらない場合のデバッグ手順等

The English summary is being prepared. Showing the original description.

minorun365/agent-builder-skills41Updated Oct 14, 2026

デモアプリ・Webアプリの Cognito 認証のおすすめ構成。「Googleで続ける」か「メール+パスキー(パスワードも併用可)」の2経路をCDKとフロントでどう組むか、パスキーが動かない設定の罠、Google client secret の置き場、ログイン画面のUX規約、Googleの同意画面に出るアプリ名の扱い。新しくデモアプリを作るとき、既存アプリの認証を作り直すとき、パスキーやGoogleログインが動かないときに読む。

The English summary is being prepared. Showing the original description.

minorun365/agent-builder-skills41Updated Oct 14, 2026

See all skills by minorun365

Report a problem with this skill