Spaces:
Sleeping
Sleeping
bigwolfe
commited on
Commit
·
31b3b17
1
Parent(s):
ffcd038
init
Browse files
specs/003-chatgpt-app-integration/checklists/requirements.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Specification Quality Checklist: ChatGPT App Integration
|
| 2 |
+
|
| 3 |
+
**Purpose**: Validate specification completeness and quality before proceeding to planning
|
| 4 |
+
**Created**: 2025-11-26
|
| 5 |
+
**Feature**: [spec.md](../spec.md)
|
| 6 |
+
|
| 7 |
+
## Content Quality
|
| 8 |
+
|
| 9 |
+
- [x] No implementation details (languages, frameworks, APIs)
|
| 10 |
+
- [x] Focused on user value and business needs
|
| 11 |
+
- [x] Written for non-technical stakeholders
|
| 12 |
+
- [x] All mandatory sections completed
|
| 13 |
+
|
| 14 |
+
## Requirement Completeness
|
| 15 |
+
|
| 16 |
+
- [x] No [NEEDS CLARIFICATION] markers remain
|
| 17 |
+
- [x] Requirements are testable and unambiguous
|
| 18 |
+
- [x] Success criteria are measurable
|
| 19 |
+
- [x] Success criteria are technology-agnostic (no implementation details)
|
| 20 |
+
- [x] All acceptance scenarios are defined
|
| 21 |
+
- [x] Edge cases are identified
|
| 22 |
+
- [x] Scope is clearly bounded
|
| 23 |
+
- [x] Dependencies and assumptions identified
|
| 24 |
+
|
| 25 |
+
## Feature Readiness
|
| 26 |
+
|
| 27 |
+
- [x] All functional requirements have clear acceptance criteria
|
| 28 |
+
- [x] User scenarios cover primary flows
|
| 29 |
+
- [x] Feature meets measurable outcomes defined in Success Criteria
|
| 30 |
+
- [x] No implementation details leak into specification
|
| 31 |
+
|
| 32 |
+
## Notes
|
| 33 |
+
|
| 34 |
+
- Spec is solid. It clearly delineates the scope (Widget vs App) and addresses the key integration points (Auth, Metadata) identified in the investigation.
|
specs/003-chatgpt-app-integration/data-model.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Data Model: ChatGPT Integration
|
| 2 |
+
|
| 3 |
+
## Auth Entities
|
| 4 |
+
|
| 5 |
+
### ServiceTokenStrategy
|
| 6 |
+
Strategy for validating static service tokens.
|
| 7 |
+
|
| 8 |
+
| Field | Type | Description |
|
| 9 |
+
|-------|------|-------------|
|
| 10 |
+
| `token` | `str` | The static token to match against. |
|
| 11 |
+
| `user_id` | `str` | The user ID to impersonate (e.g. "demo-user"). |
|
| 12 |
+
|
| 13 |
+
## Configuration
|
| 14 |
+
|
| 15 |
+
### AppConfig Updates
|
| 16 |
+
New fields added to `AppConfig`.
|
| 17 |
+
|
| 18 |
+
| Field | Type | Description |
|
| 19 |
+
|-------|------|-------------|
|
| 20 |
+
| `chatgpt_service_token` | `Optional[str]` | Static token for Apps SDK auth. |
|
| 21 |
+
| `chatgpt_cors_origin` | `str` | Allowed CORS origin (default: `https://chatgpt.com`). |
|
| 22 |
+
|
| 23 |
+
## Tool Responses
|
| 24 |
+
|
| 25 |
+
### WidgetMeta
|
| 26 |
+
Structure of the `_meta` field in `CallToolResult`.
|
| 27 |
+
|
| 28 |
+
```json
|
| 29 |
+
{
|
| 30 |
+
"openai": {
|
| 31 |
+
"outputTemplate": "https://your-space.hf.space/widget",
|
| 32 |
+
"toolInvocation": {
|
| 33 |
+
"invoking": "Searching notes...",
|
| 34 |
+
"invoked": "Found 3 notes."
|
| 35 |
+
}
|
| 36 |
+
}
|
| 37 |
+
}
|
| 38 |
+
```
|
specs/003-chatgpt-app-integration/plan.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Implementation Plan: [FEATURE]
|
| 2 |
+
|
| 3 |
+
**Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link]
|
| 4 |
+
**Input**: Feature specification from `/specs/[###-feature-name]/spec.md`
|
| 5 |
+
|
| 6 |
+
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/commands/plan.md` for the execution workflow.
|
| 7 |
+
|
| 8 |
+
## Summary
|
| 9 |
+
|
| 10 |
+
[Extract from feature spec: primary requirement + technical approach from research]
|
| 11 |
+
|
| 12 |
+
## Technical Context
|
| 13 |
+
|
| 14 |
+
<!--
|
| 15 |
+
ACTION REQUIRED: Replace the content in this section with the technical details
|
| 16 |
+
for the project. The structure here is presented in advisory capacity to guide
|
| 17 |
+
the iteration process.
|
| 18 |
+
-->
|
| 19 |
+
|
| 20 |
+
**Language/Version**: [e.g., Python 3.11, Swift 5.9, Rust 1.75 or NEEDS CLARIFICATION]
|
| 21 |
+
**Primary Dependencies**: [e.g., FastAPI, UIKit, LLVM or NEEDS CLARIFICATION]
|
| 22 |
+
**Storage**: [if applicable, e.g., PostgreSQL, CoreData, files or N/A]
|
| 23 |
+
**Testing**: [e.g., pytest, XCTest, cargo test or NEEDS CLARIFICATION]
|
| 24 |
+
**Target Platform**: [e.g., Linux server, iOS 15+, WASM or NEEDS CLARIFICATION]
|
| 25 |
+
**Project Type**: [single/web/mobile - determines source structure]
|
| 26 |
+
**Performance Goals**: [domain-specific, e.g., 1000 req/s, 10k lines/sec, 60 fps or NEEDS CLARIFICATION]
|
| 27 |
+
**Constraints**: [domain-specific, e.g., <200ms p95, <100MB memory, offline-capable or NEEDS CLARIFICATION]
|
| 28 |
+
**Scale/Scope**: [domain-specific, e.g., 10k users, 1M LOC, 50 screens or NEEDS CLARIFICATION]
|
| 29 |
+
|
| 30 |
+
## Constitution Check
|
| 31 |
+
|
| 32 |
+
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
| 33 |
+
|
| 34 |
+
[Gates determined based on constitution file]
|
| 35 |
+
|
| 36 |
+
## Project Structure
|
| 37 |
+
|
| 38 |
+
### Documentation (this feature)
|
| 39 |
+
|
| 40 |
+
```text
|
| 41 |
+
specs/[###-feature]/
|
| 42 |
+
├── plan.md # This file (/speckit.plan command output)
|
| 43 |
+
├── research.md # Phase 0 output (/speckit.plan command)
|
| 44 |
+
├── data-model.md # Phase 1 output (/speckit.plan command)
|
| 45 |
+
├── quickstart.md # Phase 1 output (/speckit.plan command)
|
| 46 |
+
├── contracts/ # Phase 1 output (/speckit.plan command)
|
| 47 |
+
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
|
| 48 |
+
```
|
| 49 |
+
|
| 50 |
+
### Source Code (repository root)
|
| 51 |
+
<!--
|
| 52 |
+
ACTION REQUIRED: Replace the placeholder tree below with the concrete layout
|
| 53 |
+
for this feature. Delete unused options and expand the chosen structure with
|
| 54 |
+
real paths (e.g., apps/admin, packages/something). The delivered plan must
|
| 55 |
+
not include Option labels.
|
| 56 |
+
-->
|
| 57 |
+
|
| 58 |
+
```text
|
| 59 |
+
# [REMOVE IF UNUSED] Option 1: Single project (DEFAULT)
|
| 60 |
+
src/
|
| 61 |
+
├── models/
|
| 62 |
+
├── services/
|
| 63 |
+
├── cli/
|
| 64 |
+
└── lib/
|
| 65 |
+
|
| 66 |
+
tests/
|
| 67 |
+
├── contract/
|
| 68 |
+
├── integration/
|
| 69 |
+
└── unit/
|
| 70 |
+
|
| 71 |
+
# [REMOVE IF UNUSED] Option 2: Web application (when "frontend" + "backend" detected)
|
| 72 |
+
backend/
|
| 73 |
+
├── src/
|
| 74 |
+
│ ├── models/
|
| 75 |
+
│ ├── services/
|
| 76 |
+
│ └── api/
|
| 77 |
+
└── tests/
|
| 78 |
+
|
| 79 |
+
frontend/
|
| 80 |
+
├── src/
|
| 81 |
+
│ ├── components/
|
| 82 |
+
│ ├── pages/
|
| 83 |
+
│ └── services/
|
| 84 |
+
└── tests/
|
| 85 |
+
|
| 86 |
+
# [REMOVE IF UNUSED] Option 3: Mobile + API (when "iOS/Android" detected)
|
| 87 |
+
api/
|
| 88 |
+
└── [same as backend above]
|
| 89 |
+
|
| 90 |
+
ios/ or android/
|
| 91 |
+
└── [platform-specific structure: feature modules, UI flows, platform tests]
|
| 92 |
+
```
|
| 93 |
+
|
| 94 |
+
**Structure Decision**: [Document the selected structure and reference the real
|
| 95 |
+
directories captured above]
|
| 96 |
+
|
| 97 |
+
## Complexity Tracking
|
| 98 |
+
|
| 99 |
+
> **Fill ONLY if Constitution Check has violations that must be justified**
|
| 100 |
+
|
| 101 |
+
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
| 102 |
+
|-----------|------------|-------------------------------------|
|
| 103 |
+
| [e.g., 4th project] | [current need] | [why 3 projects insufficient] |
|
| 104 |
+
| [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] |
|
specs/003-chatgpt-app-integration/research.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Phase 0: Research & Technical Decisions
|
| 2 |
+
|
| 3 |
+
## 1. FastMCP Metadata Injection
|
| 4 |
+
|
| 5 |
+
**Decision**: Return `CallToolResult` with `_meta` for UI tools.
|
| 6 |
+
|
| 7 |
+
**Strategy**:
|
| 8 |
+
- We will stop returning pure Pydantic models from tools that need to trigger widgets (`read_note`, `search_notes`).
|
| 9 |
+
- Instead, these tools will instantiate the Pydantic model, dump it to a dictionary, and wrap it in a `CallToolResult` object.
|
| 10 |
+
- The `_meta` field will contain `openai: { outputTemplate: "..." }`.
|
| 11 |
+
- Non-UI tools (e.g., `list_notes`, `delete_note`) will continue to return Pydantic models or simple text to keep them lightweight.
|
| 12 |
+
|
| 13 |
+
**Rationale**: This aligns with the OpenAI Apps SDK pattern and allows us to trigger widgets without breaking the existing schema validation (since `structuredContent` will still match the Pydantic schema).
|
| 14 |
+
|
| 15 |
+
## 2. React Widget Strategy
|
| 16 |
+
|
| 17 |
+
**Decision**: Use a separate Vite entry point (`widget.html` + `widget.tsx`).
|
| 18 |
+
|
| 19 |
+
**Strategy**:
|
| 20 |
+
- Create `frontend/widget.html` as a lightweight entry point.
|
| 21 |
+
- Create `frontend/src/widget.tsx` to render the widget application.
|
| 22 |
+
- Refactor `NoteViewer.tsx` into a "pure" component (if it isn't already) that can be imported by both `App.tsx` and `widget.tsx`.
|
| 23 |
+
- Use `vite-plugin-html` or manual rollup config to output multiple HTML files.
|
| 24 |
+
|
| 25 |
+
**Rationale**:
|
| 26 |
+
- **Isolation**: Prevents the main app's router, sidebar, and heavy layout styles from leaking into the iframe.
|
| 27 |
+
- **Performance**: The widget bundle will be smaller.
|
| 28 |
+
- **Simplicity**: Easier to reason about "widget state" when it's a fresh React mount rather than a route transition in a complex SPA.
|
| 29 |
+
|
| 30 |
+
## 3. Authentication
|
| 31 |
+
|
| 32 |
+
**Decision**: Use a configurable "Service Token" strategy.
|
| 33 |
+
|
| 34 |
+
**Strategy**:
|
| 35 |
+
- Refactor `AuthService` to support a `TokenValidator` interface or strategy.
|
| 36 |
+
- Implement `JWTValidator` (existing) and `StaticTokenValidator` (new).
|
| 37 |
+
- Add `CHATGPT_SERVICE_TOKEN` to `AppConfig`.
|
| 38 |
+
- If `CHATGPT_SERVICE_TOKEN` is set, the backend will accept it as a valid Bearer token for any user context (or a specific "chatgpt-bot" user).
|
| 39 |
+
|
| 40 |
+
**Rationale**:
|
| 41 |
+
- Hugging Face OAuth is not compatible with the Apps SDK OIDC flow.
|
| 42 |
+
- Implementing a full OIDC provider is out of scope for the hackathon.
|
| 43 |
+
- A static service token is secure enough for a demo/hackathon submission and easy to configure in the OpenAI Developer Platform.
|
| 44 |
+
|
| 45 |
+
## 4. Infrastructure & Hosting
|
| 46 |
+
|
| 47 |
+
**Decision**: Serve `widget.html` via FastAPI static mount with Skybridge MIME type.
|
| 48 |
+
|
| 49 |
+
**Strategy**:
|
| 50 |
+
- Update `backend/src/api/main.py` to serve `frontend/dist/widget.html` on a specific route (e.g., `/widget`).
|
| 51 |
+
- Ensure the Content-Type header is `text/html+skybridge` (or whatever the specific requirement is, usually just serving it is enough, but we will double-check if OpenAI needs specific headers). *Correction: The expert mentioned `text/html+skybridge` media type for `FileResponse`.*
|
| 52 |
+
- Update CORS to allow `https://chatgpt.com` (and `https://*.chatgpt.com`).
|
| 53 |
+
|
| 54 |
+
**Rationale**: Required for the widget to load inside the ChatGPT iframe.
|
specs/003-chatgpt-app-integration/spec.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Feature Specification: ChatGPT App Integration
|
| 2 |
+
|
| 3 |
+
**Feature**: 003-chatgpt-app-integration
|
| 4 |
+
**Status**: Draft
|
| 5 |
+
**Created**: 2025-11-26
|
| 6 |
+
|
| 7 |
+
## 1. Summary
|
| 8 |
+
|
| 9 |
+
Transform the Document-MCP project into a "ChatGPT App" compatible with the OpenAI Apps SDK. This integration enables ChatGPT users to interact with their document vault using native-feeling UI widgets (Note Viewer, Search Results) embedded directly in the chat interface, powered by the existing FastMCP server.
|
| 10 |
+
|
| 11 |
+
## 2. Problem Statement
|
| 12 |
+
|
| 13 |
+
**Context**: Currently, the Document-MCP project works as a standalone web app or a standard MCP server.
|
| 14 |
+
**Problem**: ChatGPT users accessing the vault via standard MCP tools receive raw markdown text in the chat stream, which is verbose and lacks interactivity. They cannot easily visualize the vault or navigate links without leaving the chat context.
|
| 15 |
+
**Impact**: Limits the "AI Knowledge Assistant" experience by forcing users to context-switch between ChatGPT and a separate tab, or suffer through poor readability of raw text responses.
|
| 16 |
+
|
| 17 |
+
## 3. Goals & Non-Goals
|
| 18 |
+
|
| 19 |
+
### Goals
|
| 20 |
+
- **Seamless Integration**: Enable users to search, view, and edit notes entirely within the ChatGPT interface.
|
| 21 |
+
- **Visual Widgets**: Replace raw text responses with interactive UI widgets for:
|
| 22 |
+
- Note Viewing (with Markdown rendering and Wikilink support)
|
| 23 |
+
- Search Results (clean list with snippets)
|
| 24 |
+
- **Dual-Mode Operation**: Ensure the application continues to function as a standalone web app and standard MCP server while supporting the ChatGPT App mode.
|
| 25 |
+
- **Hackathon Readiness**: Prioritize a functional "demo user" or "service token" auth flow to ensure valid submission for the "Best ChatGPT App" category.
|
| 26 |
+
|
| 27 |
+
### Non-Goals
|
| 28 |
+
- **Full Obsidian UI in Chat**: We will not iframe the entire application (sidebar, graph view, settings) into ChatGPT.
|
| 29 |
+
- **Production OAuth**: We will not implement a full OIDC provider for multi-tenant public access at this stage; a simplified auth strategy is sufficient for the hackathon.
|
| 30 |
+
- **Complex Graph Viz**: The Graph View widget is out of scope for the initial V1 integration.
|
| 31 |
+
|
| 32 |
+
## 4. User Scenarios
|
| 33 |
+
|
| 34 |
+
### Scenario 1: The Recall Loop
|
| 35 |
+
**User**: A developer brainstorming in ChatGPT.
|
| 36 |
+
**Action**: User asks, "What did I note about the authentication API?"
|
| 37 |
+
**System**: ChatGPT calls `search_notes("authentication API")`.
|
| 38 |
+
**Result**: Instead of a JSON dump, a **Search Results Widget** appears in the chat, listing matching notes. The user clicks "API Documentation" in the widget.
|
| 39 |
+
**Follow-up**: The widget transitions to a **Note Viewer Widget**, displaying the rendered markdown of "API Documentation".
|
| 40 |
+
|
| 41 |
+
### Scenario 2: In-Context Editing
|
| 42 |
+
**User**: Reading the "API Documentation" note in the widget.
|
| 43 |
+
**Action**: User tells ChatGPT, "Update the Auth section to mention we use RS256 now."
|
| 44 |
+
**System**: ChatGPT calls `read_note` (invisible to user), generates the diff, calls `write_note`, and confirms.
|
| 45 |
+
**Result**: The Note Viewer widget refreshes (or a status widget appears) showing the updated content directly in the thread.
|
| 46 |
+
|
| 47 |
+
## 5. Functional Requirements
|
| 48 |
+
|
| 49 |
+
### 5.1 Backend & MCP
|
| 50 |
+
- **Metadata Injection**: The `read_note` and `search_notes` tools must return a `CallToolResult` containing the `_meta.openai.outputTemplate` field to trigger widgets.
|
| 51 |
+
- **CORS**: The API must allow requests from `https://chatgpt.com` to support iframe loading.
|
| 52 |
+
- **Service Token**: The backend must support a configured `CHATGPT_SERVICE_TOKEN` to allow the OpenAI Apps SDK to authenticate without full user-facing OAuth.
|
| 53 |
+
|
| 54 |
+
### 5.2 Frontend Widgets
|
| 55 |
+
- **Widget Entry Point**: A new build target (`widget.html` + `widget.tsx`) must be created to serve simplified UI components.
|
| 56 |
+
- **Note Viewer Widget**: A lightweight version of the `NoteViewer` component that:
|
| 57 |
+
- Renders Markdown.
|
| 58 |
+
- Handles Wikilink clicks (by requesting ChatGPT to navigate or loading the new note within the widget).
|
| 59 |
+
- Hides the sidebar and app chrome.
|
| 60 |
+
- **Search Widget**: A simple list view for search results that triggers note navigation on click.
|
| 61 |
+
|
| 62 |
+
### 5.3 Infrastructure
|
| 63 |
+
- **Static Serving**: The FastAPI server must serve `widget.html` with the correct `text/html+skybridge` MIME type when requested.
|
| 64 |
+
- **Build Pipeline**: The Vite configuration must output both the main SPA (`index.html`) and the widget bundle (`widget.html`).
|
| 65 |
+
|
| 66 |
+
## 6. Success Criteria
|
| 67 |
+
|
| 68 |
+
1. **Widget Rendering**: A `read_note` tool call successfully renders the custom HTML widget inside the ChatGPT Developer Mode interface.
|
| 69 |
+
2. **Navigation**: Clicking a Wikilink in the widget successfully loads the target note (either by refreshing the widget or triggering a new tool call).
|
| 70 |
+
3. **Zero Regression**: The existing standalone web app (`/`) continues to function normally for local development.
|
| 71 |
+
4. **Performance**: Widget load time < 500ms (leveraging the lightweight bundle).
|
| 72 |
+
|
| 73 |
+
## 7. Assumptions & Dependencies
|
| 74 |
+
|
| 75 |
+
- **Host**: Hugging Face Spaces or Localhost (tunneled) will be used for hosting.
|
| 76 |
+
- **Apps SDK**: We rely on the OpenAI Apps SDK beta features; behavior may be subject to platform changes.
|
| 77 |
+
- **Auth**: We assume a single-tenant or shared-tenant "demo" mode is acceptable for the hackathon submission.
|
| 78 |
+
|
| 79 |
+
## 8. Questions & Clarifications
|
| 80 |
+
|
| 81 |
+
1. **Widget Navigation**: When a user clicks a link in the widget, should it trigger a client-side router push (staying in the same iframe) or ask ChatGPT to "open note X"?
|
| 82 |
+
* *Assumption*: Client-side navigation within the widget is smoother for "browsing", while asking ChatGPT is better for "contextualizing". We will prioritize **client-side navigation** for V1 to keep the UI snappy.
|
| 83 |
+
|
| 84 |
+
2. **Auth Header**: Will ChatGPT send the service token in the `Authorization` header?
|
| 85 |
+
* *Assumption*: Yes, we will configure the Custom API Action or App definition with the static Bearer token.
|