feat(office): Hanzo AI add-in for Word, Excel & PowerPoint

The surface a non-developer actually uses — a Microsoft Office task-pane
add-in that puts Hanzo AI inside the document. Select text or a range,
ask, insert. Distinct from the browser extension and the IDE extensions;
same backend as everything else: model calls through api.hanzo.ai/v1
(OpenAI-compatible), sign-in via Hanzo IAM (hanzo.id, auth-code + PKCE,
HIP-0111). No new API surface.

Decomplected so the logic is pure and unit-tested (26 tests), Office.js
glue kept thin:
- chat.ts — request/response shaping (buildMessages fences the selection
  as data; extractContent tolerates the gateway's response shapes)
- pkce.ts — PKCE + authorize URL, verified against the RFC 7636 S256 test
  vector
- host.ts — per-host read/insert; Excel range↔text helpers tested
- config.ts — canonical endpoints pinned (api.hanzo.ai, /v1/iam/oauth/*)
- taskpane/auth/commands — the Office.js + Dialog-API glue

manifest.xml passes `office-addin-manifest validate` ("The manifest is
valid" — Word/Excel/PowerPoint on web, Windows, Mac). build.js stamps the
hosting base URL (office.hanzo.ai, override for localhost dev) into a
sideloadable/AppSource-submittable dist/manifest.xml.

CI runs the tests and builds+zips a sideloadable artifact. Publishing to
AppSource needs the dist hosted at office.hanzo.ai + a hanzo-office IAM
client + a Partner Center submission (documented in the README).
This commit is contained in:
hanzo-dev
2026-07-03 14:43:29 -07:00
parent 8051256382
commit 9032801deb
27 changed files with 1239 additions and 0 deletions
+13
View File
@@ -30,6 +30,9 @@ jobs:
- name: Test AI package
run: pnpm --filter @hanzo/ai test
- name: Test Office add-in
run: pnpm --filter @hanzo/office-addin test
- name: Test tools package
run: pnpm --filter @hanzo/cli-tools test
@@ -161,6 +164,16 @@ jobs:
VER="${{ steps.version.outputs.ver }}"
cp dist/hanzoai-*.dxt /tmp/hanzo-ai-claude-v${VER}.dxt 2>/dev/null || true
# ── Microsoft Office add-in (Word/Excel/PowerPoint) ──
- name: Build Office add-in
run: |
pnpm --filter @hanzo/office-addin build
VER="${{ steps.version.outputs.ver }}"
# Bundle dist/ (manifest.xml + taskpane + assets) into a sideloadable
# zip with node-based bestzip — the arc image has no `zip` binary.
cd packages/office/dist && npx --yes bestzip /tmp/hanzo-ai-office-v${VER}.zip .
continue-on-error: true
# ── MCP npm package ──
- name: Build MCP server
run: pnpm --filter @hanzo/mcp run build