{"id":50412301,"url":"https://github.com/cskwork/website-ai-call-center-skill","last_synced_at":"2026-05-31T04:04:53.367Z","repository":{"id":359996577,"uuid":"1248269100","full_name":"cskwork/website-ai-call-center-skill","owner":"cskwork","description":"Framework-agnostic AI call-center overlay template - GitHub Pages: https://cskwork.github.io/website-ai-call-center-skill/","archived":false,"fork":false,"pushed_at":"2026-05-24T13:43:38.000Z","size":116,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-24T15:20:26.341Z","etag":null,"topics":["ai-call-center","browser-ai","codex-skill","local-first","technical-support","wasm-stt","wasm-tts"],"latest_commit_sha":null,"homepage":"https://cskwork.github.io/website-ai-call-center-skill/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cskwork.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-24T12:21:10.000Z","updated_at":"2026-05-24T13:43:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cskwork/website-ai-call-center-skill","commit_stats":null,"previous_names":["cskwork/website-ai-call-center-skill"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/cskwork/website-ai-call-center-skill","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cskwork%2Fwebsite-ai-call-center-skill","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cskwork%2Fwebsite-ai-call-center-skill/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cskwork%2Fwebsite-ai-call-center-skill/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cskwork%2Fwebsite-ai-call-center-skill/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cskwork","download_url":"https://codeload.github.com/cskwork/website-ai-call-center-skill/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cskwork%2Fwebsite-ai-call-center-skill/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33718495,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-call-center","browser-ai","codex-skill","local-first","technical-support","wasm-stt","wasm-tts"],"created_at":"2026-05-31T04:04:52.426Z","updated_at":"2026-05-31T04:04:53.361Z","avatar_url":"https://github.com/cskwork.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Website AI Call Center Skill\n\nA framework-agnostic skill and template for adding an AI technical-support call center to any website.\n\nThe default shape is static and minimal-infra: a browser overlay, a local scenario engine, safe page actions, browser WASM STT, Piper WASM TTS, and optional HTTP AI adapter when you want a real backend.\n\nLive landing page target: `https://cskwork.github.io/website-ai-call-center-skill/`\n\n## Why use it\n\n- Works with static HTML, CMS pages, SPAs, and framework apps.\n- No mandatory speech backend: STT/TTS adapters run in the browser when available.\n- User guidance is safe by default: AI can suggest registered actions, not arbitrary DOM scripts.\n- Performance posture: lazy model load, worker offload, progress events, browser cache/OPFS where supported.\n- Reusable skill packaging for Codex, Claude Code, and other coding agents.\n\n## Quick start\n\n```bash\nnpm install\nnpm run build\npython3 -m http.server 4173\n# open http://127.0.0.1:4173/examples/vanilla/\n```\n\nGitHub Pages landing site:\n\n```bash\nnpm run site:build\npython3 -m http.server 4173 -d _site\n# open http://127.0.0.1:4173/\n```\n\nScript-tag integration:\n\n```html\n\u003clink rel=\"stylesheet\" href=\"/dist/website-ai-call-center.css\"\u003e\n\u003cscript src=\"/dist/website-ai-call-center.iife.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  const sdk = window.WebsiteAICallCenter;\n  const center = sdk.createWebsiteCallCenter({\n    engine: sdk.createLocalRuleEngine({ scenarios: [] }),\n    stt: sdk.createWasmSttAdapter(),\n    tts: sdk.createPiperTtsAdapter({ fallback: sdk.createNoopTtsAdapter() })\n  });\n\u003c/script\u003e\n```\n\nESM integration:\n\n```js\nimport {\n  createWebsiteCallCenter,\n  createWasmSttAdapter,\n  createPiperTtsAdapter,\n  createNoopTtsAdapter,\n  createHttpEngineAdapter,\n  createSafeActionRegistry,\n} from 'website-ai-call-center-skill';\n\nconst actions = createSafeActionRegistry({\n  'open-help': () =\u003e document.querySelector('#help')?.scrollIntoView({ block: 'center' }),\n});\n\nconst center = createWebsiteCallCenter({\n  locale: 'ko', // optional; defaults to 'en'. Accepts BCP-47-ish tags ('ko-KR' -\u003e 'ko').\n  actionRegistry: actions,\n  stt: createWasmSttAdapter({ modelId: 'onnx-community/distil-small.en', dtype: 'q4' }),\n  tts: createPiperTtsAdapter({ fallback: createNoopTtsAdapter() }),\n  engine: createHttpEngineAdapter({ endpoint: '/api/support-call' }),\n});\n```\n\n## Internationalization (i18n)\n\nThe overlay UI ships built-in English (`en`, default) and Korean (`ko`) strings. English is the\nfallback for any missing value. There are no i18n libraries or runtime dependencies; localization\nis plain frozen string maps.\n\n### SDK options: `locale` and `strings`\n\nBoth options are optional and backward compatible. With neither set, behavior is unchanged English.\n\n```js\nconst center = createWebsiteCallCenter({\n  locale: 'ko',          // matched against ['en','ko']; region/case-insensitive; falls back to 'en'.\n  strings: {             // optional deep-merge overrides on top of the resolved locale.\n    title: 'Help desk',\n    status: { listening: 'Listening now' },\n  },\n  engine,\n});\n```\n\n- `locale` is resolved with `resolveLocale(requested)` (`'ko-KR'` -\u003e `'ko'`, unknown -\u003e `'en'`).\n- `strings` deep-merges over the locale dictionary; unspecified keys keep the locale default.\n- If `options.title` is provided it overrides the localized `title` (caller-localized title wins).\n- Strings are built with `createUiStrings(locale, overrides)` and returned deeply frozen.\n\n### Live language switching\n\nThe returned center exposes `setLocale(locale)` and `setStrings(overrides)`; both recompute the\noverlay strings and re-render the status pill and footer controls live with no reload:\n\n```js\ncenter.setLocale('ko');               // swap to Korean live\ncenter.setStrings({ send: 'Submit' }); // override individual keys in the current locale\n```\n\nExposed i18n primitives (also available on `window.WebsiteAICallCenter` in the IIFE build):\n`createUiStrings`, `resolveLocale`, `UI_STRINGS`, `UI_LOCALES`, `DEFAULT_LOCALE`, `controlsForState`.\n\n### Landing page language toggle\n\nThe landing page (`site/index.html` + `site/landing.js` + `site/i18n.js`) renders an `EN | KO`\ntoggle (`#lang-toggle`) next to the theme toggle. Initial locale precedence:\n`?lang=` URL param -\u003e `localStorage['waicc-locale']` -\u003e `navigator.language` -\u003e `'en'`. The choice\npersists to `localStorage`, syncs `\u003chtml lang\u003e`, swaps every `[data-i18n]` text node via\n`textContent`, re-renders the phrase buttons and scenario catalog in the active locale, and calls\n`center.setLocale(locale)` so the overlay follows. English text stays inline in the HTML as the\nno-JS default. All localized landing strings live in `site/i18n.js` (`LANDING_STRINGS.en` / `.ko`).\n\n\n## Worker assets\n\nThe IIFE build resolves workers relative to the script URL when `dist/workers/**` is copied beside the JS bundle. ESM and bundler users should pass explicit worker URLs:\n\n```js\nimport { createWorkerAssetUrls, createWasmSttAdapter, createPiperTtsAdapter } from 'website-ai-call-center-skill';\n\nconst { sttWorkerUrl, ttsWorkerUrl } = createWorkerAssetUrls(new URL('/dist/', location.href));\nconst stt = createWasmSttAdapter({ workerUrl: sttWorkerUrl });\nconst tts = createPiperTtsAdapter({ workerUrl: ttsWorkerUrl });\n```\n\nPiper TTS cache behavior is runtime-managed by the Piper/ONNX stack. `preferOpfsCache` controls backend reporting and preference only; pass `createNoopTtsAdapter()` as the fallback when you want to avoid the browser Speech API entirely.\n\n## Adapter contract\n\n- STT adapter: `prepare(onProgress)`, `start(onTranscript)`, `stop()`.\n- TTS adapter: `prepare(onProgress)`, `speak(text)`, `stop()`.\n- Engine adapter: `startSession()`, `sendUserText(text, context)`, `endSession()`.\n- Action registry: register allowed callbacks and execute by id only.\n\n## Scenario management\n\nThe landing page keeps human-managed call flows in YAML files under `scenarios/`.\n`scripts/build-scenarios.mjs` validates those files against `schemas/call-scenario.schema.json`\nand generates `site/generated/scenarios.js` for the browser runtime.\n\nEach scenario has:\n\n- `id` and `title` for the visible catalog.\n- `catalog_order` for stable display order.\n- `scenario_intent` for the resolved user intent.\n- `utterances` for example phrases and the demo button.\n- `match.keywords` for local deterministic matching.\n- `reply.text` for the assistant response.\n- `frontend_actions` for registered safe page actions.\n- `workflow.issue_type` for downstream routing or handoff.\n\n```yaml\nid: audio\ncatalog_order: 10\nscenario_intent: audio_issue\ntitle: Audio setup\nutterances:\n  - I cannot hear audio during a support call\nmatch:\n  keywords: [audio, hear, speaker]\nreply:\n  text: I can guide audio setup.\nfrontend_actions:\n  - id: show-audio\n    label: Show audio setup\nworkflow:\n  issue_type: technical_support\n```\n\nAdd, remove, or edit scenarios in `scenarios/*.yml`, then run:\n\n```bash\nnpm run scenarios:build\n```\n\n`site/landing.js` renders the phrase buttons and visible scenario catalog from the generated runtime file.\n\n### Scenario localization (`i18n.ko`)\n\nEach scenario may carry an optional top-level `i18n.ko` block to localize the catalog, demo phrase,\nreply, and action labels for Korean. Every field is optional and falls back field-by-field to the\nEnglish (top-level) values, so partial translations are safe. Action `id`s may not be invented in\n`i18n.ko`: every `frontend_actions[].id` under `i18n.ko` must already exist in the English\n`frontend_actions` (only the `label` is localized). The build throws a clear error otherwise.\n\n```yaml\nid: audio\ncatalog_order: 10\nscenario_intent: audio_issue\ntitle: Audio setup\nutterances:\n  - I cannot hear audio during a support call\nmatch:\n  keywords: [audio, hear, speaker]\nreply:\n  text: I can guide audio setup.\nfrontend_actions:\n  - id: show-audio\n    label: Show audio setup\nworkflow:\n  issue_type: technical_support\ni18n:\n  ko:\n    title: 오디오 설정\n    button_label: 소리가 안 나와요\n    summary: 헤드셋, 스피커, 음소거, 브라우저 권한을 점검하도록 안내합니다.\n    utterances: [상담 중에 소리가 안 들려요, 스피커가 음소거됐어요, 소리가 안 나와요]\n    reply:\n      text: 오디오 설정을 안내해 드릴게요. 헤드셋 패널부터 확인하세요.\n    frontend_actions:\n      - id: show-audio\n        label: 오디오 설정 보기\n    match:\n      keywords: [소리, 오디오, 스피커, 음소거]\n```\n\nThe generator emits a `localized: { en, ko }` map per scenario alongside the flat English fields\n(kept for back-compat). Keyword matching is locale-agnostic: `terms` is the deduped **union** of the\nEnglish and Korean `match.keywords`, so Korean input matches even when the UI is English and vice\nversa. At runtime, `getScenarioReply(text, locale)` and `getScenarioReplyForIntent(intent, locale)`\nreturn the reply text and action labels for the requested locale (English fallback);\n`localizedScenario(scenario, locale)` returns the per-locale catalog view used by the landing page.\n\n## Intent detection\n\nThe current static demo detects intent with deterministic keyword scoring:\n\n1. Normalize the user's text.\n2. Score each YAML scenario by matching `match.keywords`.\n3. Select the highest-scoring scenario.\n4. Return its `scenario_intent`, `workflow.issue_type`, reply text, and approved `frontend_actions`.\n\nFor production call centers, replace only the intent resolver. An LLM, classifier, or contact-center workflow can return a `scenario_intent` such as `audio_issue`; the runtime should then call `getScenarioReplyForIntent(intent)` and execute only the scenario's approved `frontend_actions`. Keep these concepts separate:\n\n- `scenario_intent`: what the user wants.\n- `scenario`: the approved response/action plan for that intent.\n- `workflow.issue_type`: backend routing or handoff category.\n- `frontend_actions`: safe page callbacks registered by the website.\n\n## Verification\n\n```bash\nnpm run scenarios:build\nnpm test\nnpm run build\nnpm run site:build\nnpm run smoke:browser\nnpm run smoke:site\nnpm pack --dry-run --json\n```\n\n## GitHub Pages\n\nThis repository includes `.github/workflows/pages.yml`. On pushes to `main`, GitHub Actions runs tests, builds the SDK bundles, and copies `site/`, `dist/`, `examples/`, and `docs/` into `_site/`.\n\nDeployment is guarded while the repo is private. GitHub Pages for private repositories requires a supported GitHub plan; when the repo is public or Pages is enabled on a supported private plan, the same workflow uploads and deploys the `_site/` artifact.\n\nNotes for static hosting:\n\n- All landing-page links use relative paths so project Pages works under `/website-ai-call-center-skill/`.\n- The landing text path does not preload speech models.\n- Voice mode remains WASM-based: Transformers.js STT and Piper TTS load lazily after the user clicks Prepare.\n- GitHub Pages cannot add cross-origin isolation headers, so the template uses non-threaded/browser-safe WASM paths.\n\nSee `docs/integration.md`, `docs/privacy.md`, `docs/compliance.md`, and `docs/browser-support.md` before production use.\n\n`examples/vanilla/` is intentionally self-contained: it implements page actions, a scenario engine, Transformers.js WASM STT, Piper WASM TTS, and a text path that does not preload speech models until Prepare is clicked.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcskwork%2Fwebsite-ai-call-center-skill","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcskwork%2Fwebsite-ai-call-center-skill","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcskwork%2Fwebsite-ai-call-center-skill/lists"}