Archipelago — open-source initial import
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* AIUI ↔ Archy postMessage Protocol
|
||||
*
|
||||
* AIUI (iframe) communicates with Archy (host) via structured messages.
|
||||
* Archy acts as a context broker — AIUI never directly accesses node data.
|
||||
*/
|
||||
|
||||
/** Data categories that AIUI can request access to */
|
||||
export type AIContextCategory =
|
||||
| 'apps'
|
||||
| 'system'
|
||||
| 'network'
|
||||
| 'wallet'
|
||||
| 'files'
|
||||
| 'media'
|
||||
| 'search'
|
||||
| 'ai-local'
|
||||
| 'notes'
|
||||
| 'bitcoin'
|
||||
|
||||
/** Actions AIUI can request Archy to perform */
|
||||
export type AIActionType = 'install-app' | 'open-app' | 'navigate' | 'launch-app' | 'search-web' | 'read-file' | 'tail-logs'
|
||||
|
||||
// ─── AIUI → Archy (Requests) ───────────────────────────────────────────────
|
||||
|
||||
export interface AIUIContextRequest {
|
||||
type: 'context:request'
|
||||
id: string
|
||||
category: AIContextCategory
|
||||
query?: string
|
||||
}
|
||||
|
||||
export interface AIUIActionRequest {
|
||||
type: 'action:request'
|
||||
id: string
|
||||
action: AIActionType
|
||||
params: Record<string, string>
|
||||
}
|
||||
|
||||
export interface AIUIReadyMessage {
|
||||
type: 'ready'
|
||||
}
|
||||
|
||||
export interface AIUIThemeRequest {
|
||||
type: 'theme:request'
|
||||
}
|
||||
|
||||
export type AIUIRequest =
|
||||
| AIUIContextRequest
|
||||
| AIUIActionRequest
|
||||
| AIUIReadyMessage
|
||||
| AIUIThemeRequest
|
||||
|
||||
// ─── Archy → AIUI (Responses) ──────────────────────────────────────────────
|
||||
|
||||
export interface ArchyContextResponse {
|
||||
type: 'context:response'
|
||||
id: string
|
||||
data: unknown
|
||||
permitted: boolean
|
||||
}
|
||||
|
||||
export interface ArchyActionResponse {
|
||||
type: 'action:response'
|
||||
id: string
|
||||
success: boolean
|
||||
error?: string
|
||||
data?: unknown
|
||||
}
|
||||
|
||||
export interface ArchyThemeResponse {
|
||||
type: 'theme:response'
|
||||
theme: {
|
||||
accent: string
|
||||
mode: 'dark'
|
||||
}
|
||||
}
|
||||
|
||||
export interface ArchyPermissionsUpdate {
|
||||
type: 'permissions:update'
|
||||
categories: AIContextCategory[]
|
||||
}
|
||||
|
||||
export type ArchyResponse =
|
||||
| ArchyContextResponse
|
||||
| ArchyActionResponse
|
||||
| ArchyThemeResponse
|
||||
| ArchyPermissionsUpdate
|
||||
|
||||
// ─── All messages ───────────────────────────────────────────────────────────
|
||||
|
||||
export type AIUIMessage = AIUIRequest | ArchyResponse
|
||||
|
||||
/** Protocol version for compatibility checks */
|
||||
export const AIUI_PROTOCOL_VERSION = '1.0.0'
|
||||
|
||||
/** Message origin prefix used for validation */
|
||||
export const AIUI_MESSAGE_PREFIX = 'aiui:'
|
||||
@@ -0,0 +1,299 @@
|
||||
// API Types ported from Angular codebase
|
||||
|
||||
export interface DataModel {
|
||||
'server-info': ServerInfo
|
||||
'package-data': { [id: string]: PackageDataEntry }
|
||||
'peer-health'?: { [onion: string]: boolean }
|
||||
notifications?: AppNotification[]
|
||||
ui: UIData
|
||||
}
|
||||
|
||||
export interface AppNotification {
|
||||
id: string
|
||||
level: 'info' | 'warning' | 'error'
|
||||
title: string
|
||||
message: string
|
||||
timestamp: string
|
||||
app_id?: string
|
||||
}
|
||||
|
||||
export interface ServerInfo {
|
||||
id: string
|
||||
version: string
|
||||
name: string | null
|
||||
pubkey: string
|
||||
'status-info': StatusInfo
|
||||
'lan-address': string | null
|
||||
'tor-address': string | null
|
||||
'node-address'?: string
|
||||
unread: number
|
||||
'wifi-ssids': string[]
|
||||
'zram-enabled': boolean
|
||||
'seed-backed': boolean
|
||||
lat?: number | null
|
||||
lon?: number | null
|
||||
'share-location'?: boolean
|
||||
}
|
||||
|
||||
export interface StatusInfo {
|
||||
restarting: boolean
|
||||
'shutting-down': boolean
|
||||
'updated': boolean
|
||||
'backup-progress': number | null
|
||||
'update-progress': number | null
|
||||
'containers-scanned'?: boolean
|
||||
}
|
||||
|
||||
export type UIMode = 'gamer' | 'easy' | 'chat'
|
||||
|
||||
export interface UIData {
|
||||
name: string | null
|
||||
'ack-welcome': string
|
||||
marketplace: UIMarketplaceData
|
||||
theme: string
|
||||
mode?: UIMode
|
||||
}
|
||||
|
||||
export interface UIMarketplaceData {
|
||||
'selected-hosts': string[]
|
||||
'known-hosts': Record<string, MarketplaceHost>
|
||||
}
|
||||
|
||||
export interface MarketplaceHost {
|
||||
name: string
|
||||
url: string
|
||||
}
|
||||
|
||||
export const PackageState = {
|
||||
Installing: 'installing',
|
||||
Installed: 'installed',
|
||||
Stopping: 'stopping',
|
||||
Stopped: 'stopped',
|
||||
Exited: 'exited',
|
||||
Starting: 'starting',
|
||||
Running: 'running',
|
||||
Restarting: 'restarting',
|
||||
Creating: 'creating-backup',
|
||||
Restoring: 'restoring-backup',
|
||||
Removing: 'removing',
|
||||
BackingUp: 'backing-up',
|
||||
Updating: 'updating',
|
||||
} as const
|
||||
|
||||
export type PackageState = typeof PackageState[keyof typeof PackageState]
|
||||
|
||||
export interface PackageDataEntry {
|
||||
state: PackageState
|
||||
health?: string | null // "healthy", "unhealthy", "starting", or null
|
||||
'exit-code'?: number | null // container exit code: 0 = clean stop, non-zero = crash
|
||||
'static-files'?: {
|
||||
license: string
|
||||
instructions: string
|
||||
icon: string
|
||||
screenshots?: AppScreenshot[]
|
||||
}
|
||||
manifest: Manifest
|
||||
installed?: InstalledPackageDataEntry
|
||||
'install-progress'?: InstallProgress
|
||||
/** Live label for the current uninstall step ("Stopping containers (2/5)", …). */
|
||||
'uninstall-stage'?: string | null
|
||||
'available-update'?: string | null
|
||||
}
|
||||
|
||||
export interface Manifest {
|
||||
id: string
|
||||
title: string
|
||||
version: string
|
||||
description: {
|
||||
short: string
|
||||
long: string
|
||||
}
|
||||
'release-notes': string
|
||||
license: string
|
||||
'wrapper-repo': string
|
||||
'upstream-repo': string
|
||||
'support-site': string
|
||||
'marketing-site': string
|
||||
'donation-url': string | null
|
||||
author?: string
|
||||
website?: string
|
||||
tier?: string
|
||||
interfaces?: {
|
||||
main?: {
|
||||
ui?: string
|
||||
'tor-config'?: string
|
||||
'lan-config'?: string
|
||||
}
|
||||
}
|
||||
screenshots?: AppScreenshot[]
|
||||
}
|
||||
|
||||
export type AppScreenshot = string | {
|
||||
src: string
|
||||
alt?: string
|
||||
}
|
||||
|
||||
export interface InstalledPackageDataEntry {
|
||||
'current-dependents': Record<string, CurrentDependencyInfo>
|
||||
'current-dependencies': Record<string, CurrentDependencyInfo>
|
||||
'last-backup': string | null
|
||||
'interface-addresses': Record<string, InterfaceAddress>
|
||||
status: ServiceStatus
|
||||
}
|
||||
|
||||
export interface CurrentDependencyInfo {
|
||||
'health-checks': string[]
|
||||
}
|
||||
|
||||
export interface InterfaceAddress {
|
||||
'tor-address': string
|
||||
'lan-address': string | null
|
||||
}
|
||||
|
||||
export interface AppCredential {
|
||||
label: string
|
||||
value: string
|
||||
sensitive?: boolean
|
||||
}
|
||||
|
||||
export interface AppCredentialsResponse {
|
||||
title?: string
|
||||
description?: string
|
||||
credentials: AppCredential[]
|
||||
}
|
||||
|
||||
export const ServiceStatus = {
|
||||
Stopped: 'stopped',
|
||||
Starting: 'starting',
|
||||
Running: 'running',
|
||||
Stopping: 'stopping',
|
||||
Restarting: 'restarting',
|
||||
} as const
|
||||
|
||||
export type ServiceStatus = typeof ServiceStatus[keyof typeof ServiceStatus]
|
||||
|
||||
export type InstallPhase =
|
||||
| 'preparing'
|
||||
| 'pulling-image'
|
||||
| 'creating-container'
|
||||
| 'starting-container'
|
||||
| 'waiting-healthy'
|
||||
| 'post-install'
|
||||
| 'done'
|
||||
|
||||
export interface InstallProgress {
|
||||
size: number
|
||||
downloaded: number
|
||||
/** High-level pipeline phase. Preferred by the UI over the byte
|
||||
* counters — podman pull doesn't emit parseable progress when
|
||||
* stderr is piped, so byte counters are usually (0,0). */
|
||||
phase?: InstallPhase
|
||||
/** Optional explicit message — surfaced on install failures so the
|
||||
* UI can show what went wrong instead of silently removing the card. */
|
||||
message?: string
|
||||
}
|
||||
|
||||
// RPC Request/Response types
|
||||
export namespace RR {
|
||||
// Auth
|
||||
export interface LoginReq {
|
||||
password: string
|
||||
metadata: SessionMetadata
|
||||
}
|
||||
export type LoginRes = null
|
||||
|
||||
export interface SessionMetadata {
|
||||
// Add session metadata fields
|
||||
}
|
||||
|
||||
export interface LogoutReq {}
|
||||
export type LogoutRes = null
|
||||
|
||||
export interface ResetPasswordReq {
|
||||
'old-password': string
|
||||
'new-password': string
|
||||
}
|
||||
export type ResetPasswordRes = null
|
||||
|
||||
// Server
|
||||
export interface EchoReq {
|
||||
message: string
|
||||
timeout?: number
|
||||
}
|
||||
export type EchoRes = string
|
||||
|
||||
export interface GetSystemTimeReq {}
|
||||
export interface GetSystemTimeRes {
|
||||
now: string
|
||||
uptime: number
|
||||
}
|
||||
|
||||
export interface GetServerMetricsReq {}
|
||||
export interface GetServerMetricsRes {
|
||||
cpu: number
|
||||
disk: DiskInfo
|
||||
memory: MemoryInfo
|
||||
}
|
||||
|
||||
export interface DiskInfo {
|
||||
used: number
|
||||
total: number
|
||||
}
|
||||
|
||||
export interface MemoryInfo {
|
||||
used: number
|
||||
total: number
|
||||
}
|
||||
|
||||
export interface UpdateServerReq {
|
||||
'marketplace-url': string
|
||||
}
|
||||
export type UpdateServerRes = 'updating' | 'no-updates'
|
||||
|
||||
export interface RestartServerReq {}
|
||||
export type RestartServerRes = null
|
||||
|
||||
export interface ShutdownServerReq {}
|
||||
export type ShutdownServerRes = null
|
||||
|
||||
// Packages
|
||||
export interface InstallPackageReq {
|
||||
id: string
|
||||
'marketplace-url': string
|
||||
version: string
|
||||
}
|
||||
export type InstallPackageRes = string // guid
|
||||
|
||||
export interface UninstallPackageReq {
|
||||
id: string
|
||||
}
|
||||
export type UninstallPackageRes = null
|
||||
|
||||
export interface StartPackageReq {
|
||||
id: string
|
||||
}
|
||||
export type StartPackageRes = null
|
||||
|
||||
export interface StopPackageReq {
|
||||
id: string
|
||||
}
|
||||
export type StopPackageRes = null
|
||||
|
||||
export interface RestartPackageReq {
|
||||
id: string
|
||||
}
|
||||
export type RestartPackageRes = null
|
||||
}
|
||||
|
||||
// JSON Patch types
|
||||
export interface PatchOperation {
|
||||
op: 'add' | 'remove' | 'replace' | 'move' | 'copy' | 'test'
|
||||
path: string
|
||||
value?: unknown
|
||||
from?: string
|
||||
}
|
||||
|
||||
export interface Update {
|
||||
sequence: number
|
||||
patch: PatchOperation[]
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// Goal-based workflow types for Easy mode
|
||||
|
||||
export interface GoalDefinition {
|
||||
id: string
|
||||
title: string
|
||||
subtitle: string
|
||||
icon: string
|
||||
category: 'commerce' | 'payments' | 'storage' | 'identity' | 'network' | 'backup' | 'community'
|
||||
requiredApps: string[]
|
||||
steps: GoalStep[]
|
||||
estimatedTime: string
|
||||
difficulty: 'beginner' | 'intermediate'
|
||||
}
|
||||
|
||||
export interface GoalStep {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
appId?: string
|
||||
/**
|
||||
* 'fund' renders the bitcoin-wallet funding UI: gated on IBD completion
|
||||
* (with a live sync timer), then a "Fund Wallet" receive flow.
|
||||
*/
|
||||
action: 'install' | 'configure' | 'verify' | 'info' | 'fund'
|
||||
isAutomatic: boolean
|
||||
/** Custom step icon (e.g. the Zeus logo) — overrides the appId-derived icon */
|
||||
icon?: string
|
||||
/** Custom label for the step's CTA button (configure steps) */
|
||||
ctaLabel?: string
|
||||
}
|
||||
|
||||
export type GoalStatus = 'not-started' | 'in-progress' | 'completed' | 'error'
|
||||
|
||||
export interface GoalProgress {
|
||||
goalId: string
|
||||
status: GoalStatus
|
||||
currentStepIndex: number
|
||||
completedSteps: string[]
|
||||
startedAt?: number
|
||||
}
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
declare module 'qrloop' {
|
||||
export type FramesState = unknown
|
||||
export function parseFramesReducer(state: FramesState | null, frame: string): FramesState
|
||||
export function areFramesComplete(state: FramesState): boolean
|
||||
export function framesToData(state: FramesState): { toString(encoding: string): string }
|
||||
export function totalNumberOfFrames(state: FramesState): number
|
||||
export function currentNumberOfFrames(state: FramesState): number
|
||||
export function progressOfFrames(state: FramesState): number
|
||||
}
|
||||
Reference in New Issue
Block a user