A highly modular and extensible web application framework for building IDE-like applications with a plugin architecture, AI integration, and comprehensive workspace management.
Appspace is a framework that provides a complete foundation for building modern web applications with:
- Modular Architecture: Extensible through a plugin system
- Application Loader: Dynamic app loading and lifecycle management
- Contribution System: Declarative UI and feature contributions
- Command System: Context-aware command execution
- AI Integration: Built-in AI system with agent support and tool execution
- Workspace Management: File system access and workspace handling
- Extension Marketplace: Install and manage extensions dynamically
┌─────────────────────────────────────────────────────────────┐
│ Application Layer │
│ (Apps built on the framework: geospace, custom apps) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ App Loader Service │
│ - App registration and lifecycle │
│ - Extension management │
│ - Contribution registration │
└─────────────────────────────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Extensions │ │ Contributions│ │ Commands │
│ Registry │ │ Registry │ │ Registry │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
└───────────────────┼───────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ Core Services Layer │
│ - Workspace Service - Editor Registry │
│ - Settings Service - Task Service │
│ - Event System - Dependency Injection │
│ - Logger - Python Service │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ UI Component Layer │
│ - Parts (k-part, k-container, k-tabs, k-toolbar) │
│ - Components (k-filebrowser, k-extensions, etc.) │
│ - Widgets (k-widget, k-icon, etc.) │
│ - Standard App Layout (k-standard-app) │
└─────────────────────────────────────────────────────────────┘
Applications are self-contained units that define their UI, extensions, and contributions. They implement the AppDefinition interface:
interface AppDefinition {
id: string;
name: string;
version: string;
description?: string;
extensions?: string[]; // Required framework extensions
contributions?: AppContributions; // UI and feature contributions
initialize?: () => void | Promise<void>;
render?: () => TemplateResult; // Custom root component
dispose?: () => void | Promise<void>;
}Key Features:
- Apps can be loaded dynamically from URLs
- Automatic extension lifecycle management
- Declarative contribution registration
- Custom initialization and cleanup
Extensions are modular plugins that add functionality to the framework. They can:
- Register commands, contributions, and services
- Add UI components and tabs
- Integrate with the AI system
- Provide new capabilities
Extension Structure:
interface Extension {
id: string;
name: string;
description?: string;
loader?: () => any; // Dynamic import function
url?: string; // URL to load from
dependencies?: string[]; // Other extensions required
experimental?: boolean;
version?: string;
}Built-in Extensions:
ai-system: AI chat interface, agents, and LLM integrationrag-system: Document indexing and semantic searchmonaco-editor: Code editor with syntax highlightingnotebook: Interactive notebook supportpyterminal: Python terminal integrationgit: Git integrationwebdav: WebDAV file system support- And more...
Contributions are declarative registrations that add UI elements or features to specific targets:
Contribution Types:
- Tab Contributions: Add tabs to sidebars or editor areas
- Command Contributions: Add buttons/menu items that execute commands
- Toolbar Contributions: Add items to toolbars
- Pane Contributions: Add resizable panes
- HTML Contributions: Add custom HTML content
Contribution Targets:
SIDEBAR_MAIN: Main left sidebarSIDEBAR_AUXILIARY: Right auxiliary sidebarEDITOR_AREA_MAIN: Main editor areaPANEL_BOTTOM: Bottom panelTOOLBAR_MAIN: Main toolbar- And more...
Commands are context-aware actions that can be executed by users or AI agents:
interface Command {
id: string;
name: string;
description: string;
parameters?: Parameter[];
output?: Variable[];
keyBinding?: string;
icon?: string;
}Command Execution:
- Commands can have multiple handlers with different priorities
- Handlers can check context (
canExecute) before execution - Commands are automatically exposed as AI tools
- Context-aware: different commands available based on active editor, selection, etc.
Parts (KPart): Base class for tabbed UI components
- Automatic dirty state management
- Toolbar integration
- Command stack support
- Lifecycle management
Components (KElement, KContainer): Base UI elements
- Built on Lit web components
- Reactive state with signals
- WebAwesome UI components
Standard App Layout (KStandardApp): Default application layout
- Three-column layout (sidebar, editor, auxiliary sidebar)
- Resizable panels
- Toolbar support
- Configurable bottom panels
- File system access via File System Access API
- Workspace persistence
- File watching and change detection
- Directory operations
- Persistent application settings
- Settings tree UI
- Settings change events
- File type to editor mapping
- Editor lifecycle management
- Multiple editor instances
- Editor state management
- Background task execution
- Progress monitoring
- Task cancellation
- UI integration
- Pub/sub event bus
- Type-safe events
- Framework-wide communication
- Service registration and lookup
- Context-based injection
- Root and scoped contexts
- Multi-provider LLM support (OpenAI, Anthropic, WebLLM, etc.)
- Agent system with custom prompts
- Tool execution for commands
- Streaming responses
- Workflow engine for complex operations
- Document indexing and storage
- Vector embeddings (Xenova transformers)
- Semantic search
- AI integration for document retrieval
- Registration: Extensions are registered with metadata
- Loading: Extensions are loaded on-demand or at startup
- Dependency Resolution: Dependencies are automatically loaded
- Execution: Extension module's default export function is called
- Enablement: Extensions can be enabled/disabled dynamically
// my-extension.ts
export default function(uiContext: UIContext) {
// Register commands
commandRegistry.registerCommand(new Command(
'my.command',
'My Command',
'Does something useful'
));
// Register command handler
commandRegistry.registerHandler('my.command', {
execute: (context) => {
// Execute command
}
});
// Register contributions
contributionRegistry.registerContribution(SIDEBAR_MAIN, {
name: 'my-tab',
label: 'My Tab',
icon: 'puzzle-piece',
component: (id) => html`<my-component id="${id}"></my-component>`
});
}- Browse and install extensions from remote catalogs
- External extension management
- Extension versioning
- Dependency resolution
The framework exposes a clean public API:
// Main API entry point
import {
appLoaderService, // App lifecycle management
commandRegistry, // Command system
contributionRegistry, // Contribution system
extensionRegistry, // Extension system
workspaceService, // File system access
editorRegistry, // Editor management
createLogger, // Logging
// ... and more
} from '@kispace-io/appspace';
// Base classes
import { KPart, KContainer, KStandardApp } from '@kispace-io/appspace';
// Extensions
import { /* AI system exports */ } from '@kispace-io/appspace/extensions/ai-system';
import { /* RAG system exports */ } from '@kispace-io/appspace/extensions/rag-system';import { appLoaderService, AppDefinition, SIDEBAR_MAIN } from '@kispace-io/appspace';
import { html } from 'lit';
const myApp: AppDefinition = {
id: 'my-app',
name: 'My Application',
version: '1.0.0',
extensions: ['system.monaco-editor', 'system.ai-system'],
contributions: {
ui: [
{
target: SIDEBAR_MAIN,
name: 'my-tab',
label: 'My Tab',
icon: 'folder',
component: (id) => html`<my-component id="${id}"></my-component>`
}
]
},
initialize: async () => {
// Custom initialization
}
};
appLoaderService.registerApp(myApp, { autoStart: true });- Lit: Web components framework
- TypeScript: Type safety
- WebAwesome: UI component library
- Monaco Editor: Code editing
- RxDB: Client-side database (for extensions like RAG)
- Pyodide: Python runtime in the browser
- WebLLM: Local LLM execution
- Xenova Transformers: ML models in the browser
The package provides multiple entry points:
.- Main API./api- Public API services./extensions/ai-system- AI system extension./extensions/rag-system- RAG system extension./widgets- Widget components./parts- Part components
EPL-2.0
https://github.com/kispace-io/appspace
This package is automatically published to npm when a tagged release is created on GitHub.
The easiest way to create a release is using the provided script:
# Patch release (1.2.3 -> 1.2.4)
./scripts/trigger-release.sh patch
# Minor release (1.2.3 -> 1.3.0)
./scripts/trigger-release.sh minor
# Major release (1.2.3 -> 2.0.0)
./scripts/trigger-release.sh major
# Dry run to preview what would happen
./scripts/trigger-release.sh --dry-run patchThe script will:
- Calculate the next version based on the latest tag
- Show changes since the last release
- Optionally generate an AI summary (if
OPENAI_API_KEYis set in.env) - Create an annotated tag with release notes
- Push the tag to trigger the CI workflow
You can also create a tag manually:
# Create and push a tag
git tag -a v1.2.3 -m "Release: v1.2.3" -m "Release notes here"
git push origin v1.2.3The GitHub Actions workflow will automatically:
- Extract the version from the tag (e.g.,
v1.2.3→1.2.3) - Update
package.jsonwith the tag version (CI only, not committed) - Build the package
- Publish to npm
Note: The version in package.json should remain at 0.0.0 in the repository. The CI workflow will update it automatically from the tag during the publish process.
If you need to publish manually:
npm run build
npm publishNote: You must be logged in to npm and have publish access to the @kispace-io organization.
This repository uses npm's trusted publishing (OIDC) for automated releases. No NPM_TOKEN secret is required.
Prerequisites:
- The package must exist in the npm registry (publish manually first if needed)
- The GitHub repository must be public (required for provenance)
- You must have publish access to the
@kispace-ioorganization on npm
Setup Steps:
- Go to npm organization settings: https://www.npmjs.com/org/kispace-io/settings
- Navigate to "Automation" → "Trusted Publishing"
- Click "Add GitHub Actions" or "Configure"
- Configure the trusted publisher with exact values:
- Repository Owner:
kispace-io(must match GitHub organization) - Repository Name:
appspace(must match exactly) - Workflow Filename:
.github/workflows/publish.yml(must include the.ymlextension) - Environment: (leave empty for default, or specify if using GitHub environments)
- Repository Owner:
- Save the configuration
Critical Requirements:
- Repository must be public (private repos don't support provenance)
- All values must match exactly (case-sensitive, including
.ymlextension) - The repository must be in the
kispace-ioGitHub organization - The workflow file must exist at
.github/workflows/publish.yml
Troubleshooting 404 Errors:
If you see a "404 Not Found" or "401 Unauthorized" error:
- Verify trusted publishing is configured: https://www.npmjs.com/org/kispace-io/settings → Automation → Trusted Publishing
- Check exact match: Repository must be exactly
kispace-io/appspace(noterdalkaraca/appspace) - Verify workflow path: Must be exactly
.github/workflows/publish.yml(with.ymlextension) - Check repository visibility: Must be public (not private)
- Verify permissions: Ensure
id-token: writeis in workflow permissions (already configured) - Test manually: Try
npm publish --access publiclocally to verify npm access
Once configured correctly, the GitHub Actions workflow will automatically authenticate using OIDC when publishing.