@lincyaw/kernel 1.0.0-rc.0 → 1.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/package.json +6 -2
- package/src/access.ts +18 -0
- package/src/anchors.ts +5 -1
- package/src/authoring.ts +56 -0
- package/src/blocks.ts +0 -8
- package/src/component-code.ts +6 -0
- package/src/contracts/agent.ts +5 -82
- package/src/contracts/anchors.ts +46 -0
- package/src/contracts/authoring-actions.ts +60 -0
- package/src/contracts/authoring-clients.ts +213 -0
- package/src/contracts/authoring.ts +180 -0
- package/src/contracts/checks.ts +29 -0
- package/src/contracts/classroom.ts +49 -0
- package/src/contracts/diagnostics.ts +37 -0
- package/src/contracts/document-audio.ts +150 -0
- package/src/contracts/document-comments.ts +31 -0
- package/src/contracts/document-history.ts +63 -0
- package/src/contracts/document-image.ts +32 -0
- package/src/contracts/document-reads.ts +57 -0
- package/src/contracts/document-voice.ts +44 -0
- package/src/contracts/document.ts +240 -0
- package/src/contracts/execution.ts +4 -5
- package/src/contracts/locale.ts +3 -0
- package/src/contracts/offline.ts +2 -0
- package/src/contracts/plugin.ts +183 -0
- package/src/contracts/presenter-panels.ts +17 -0
- package/src/contracts/preview.ts +305 -310
- package/src/contracts/production-assets.ts +61 -0
- package/src/contracts/production.ts +109 -0
- package/src/contracts/projects.ts +59 -0
- package/src/contracts/server.ts +1 -51
- package/src/contracts/speech-settings.ts +16 -0
- package/src/contracts/speech.ts +82 -70
- package/src/contracts/steps.ts +15 -0
- package/src/contracts/transcription-adoption.ts +79 -0
- package/src/contracts/transcription.ts +112 -0
- package/src/contracts/voice.ts +97 -0
- package/src/contracts/voiceover-execution.ts +68 -0
- package/src/contracts/workspace.ts +458 -0
- package/src/contracts.ts +28 -278
- package/src/diagnostics.ts +7 -0
- package/src/document-authoring-actions.ts +47 -0
- package/src/document-caption-timings.ts +64 -0
- package/src/document-colors.ts +25 -0
- package/src/document-comments.ts +118 -0
- package/src/document-components.ts +251 -0
- package/src/document-operations.ts +132 -0
- package/src/document-pages.ts +215 -0
- package/src/document-reads.ts +81 -0
- package/src/document-schema.ts +85 -0
- package/src/document-voices.ts +153 -0
- package/src/document.ts +252 -0
- package/src/durations.ts +7 -0
- package/src/errors.ts +8 -0
- package/src/execution.ts +5 -1
- package/src/fingerprint.ts +1 -1
- package/src/follow.ts +26 -30
- package/src/git.ts +1 -1
- package/src/index.ts +66 -13
- package/src/ir.ts +54 -5
- package/src/jupyter-kernel.ts +9 -0
- package/src/kernel.ts +38 -25
- package/src/keyboard.ts +43 -0
- package/src/locale.ts +13 -0
- package/src/lock.ts +4 -8
- package/src/logging.ts +1 -1
- package/src/{markdown.ts → lower-myst.ts} +2 -1
- package/src/node/assets.ts +23 -0
- package/src/node/authoring-actions.ts +50 -0
- package/src/node/authoring-clients.ts +14 -0
- package/src/node/document-audio.ts +22 -0
- package/src/node/document-history.ts +11 -0
- package/src/node/document-image.ts +8 -0
- package/src/node/document-reads.ts +10 -0
- package/src/node/document-voice.ts +7 -0
- package/src/node/ffmpeg.ts +29 -0
- package/src/node/file-version.ts +6 -0
- package/src/node/fonts.ts +22 -0
- package/src/node/index.ts +29 -133
- package/src/node/installed-packages.ts +11 -0
- package/src/node/lines.ts +24 -0
- package/src/node/locale.ts +7 -0
- package/src/node/network.ts +11 -0
- package/src/node/operator-speech.ts +91 -0
- package/src/node/packages.ts +74 -0
- package/src/node/paths.ts +7 -0
- package/src/node/projects.ts +7 -0
- package/src/node/resources.ts +86 -0
- package/src/node/revision.ts +6 -0
- package/src/node/run-directory.ts +70 -0
- package/src/node/transcription-adoption.ts +9 -0
- package/src/node/transcription.ts +10 -0
- package/src/node/voiceover-routes.ts +73 -0
- package/src/node/voiceover.ts +199 -0
- package/src/page-source.ts +359 -0
- package/src/parameters.ts +81 -0
- package/src/preview-edit.ts +18 -0
- package/src/preview-events.ts +57 -0
- package/src/preview-frame.ts +1220 -0
- package/src/props.ts +17 -0
- package/src/push-stream.ts +67 -0
- package/src/reading.ts +12 -7
- package/src/recording.ts +38 -0
- package/src/renderer-components.ts +30 -0
- package/src/responses.ts +49 -0
- package/src/run-outputs.ts +15 -0
- package/src/runner.py +3 -3
- package/src/services.ts +6 -6
- package/src/slides.ts +36 -0
- package/src/speech-words.ts +76 -0
- package/src/speech.ts +13 -0
- package/src/step-keys.ts +38 -0
- package/src/steps.ts +7 -0
- package/src/transcription-adoption.ts +105 -0
- package/src/uri-decoding.ts +8 -0
- package/src/urls.ts +13 -0
- package/src/views.ts +47 -0
- package/src/voice.ts +86 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { CanonicalSource } from '../ir.ts'
|
|
2
|
+
import type { Finding } from './checks.ts'
|
|
3
|
+
import type { Member } from './server.ts'
|
|
4
|
+
import type { SpeechEngineInfo } from './speech.ts'
|
|
5
|
+
import type { VoiceCatalogAnswer, VoiceoverCancellation } from './voice.ts'
|
|
6
|
+
import type { DocumentVoiceTasks, VoiceoverJobQuery, VoiceoverStart, VoicePreviewStart } from './voiceover-execution.ts'
|
|
7
|
+
|
|
8
|
+
export interface DocumentVoiceCapabilities {
|
|
9
|
+
document: string
|
|
10
|
+
source: CanonicalSource
|
|
11
|
+
/** Configuration discovery does not prove provider authentication or synthesis success. */
|
|
12
|
+
verification: 'configuration-only'
|
|
13
|
+
status: 'configured' | 'unavailable' | 'unknown'
|
|
14
|
+
reason?: 'not-configured' | 'services-unavailable'
|
|
15
|
+
voiceover: boolean
|
|
16
|
+
preview: boolean
|
|
17
|
+
engines: SpeechEngineInfo[]
|
|
18
|
+
defaultEngine?: string
|
|
19
|
+
actions: { status: boolean, list: true, get: true, start: boolean, cancel: true, quotePreview: boolean, preview: boolean, readPreview: true }
|
|
20
|
+
tasks: { idempotency: 'process', limits: { intents: number, recentJobs: number, concurrent: number, quotes: number, quoteLifetimeMs: number, previewBytes: number, previewResources: number, retainedPreviewBytes: number } }
|
|
21
|
+
findings?: Finding[]
|
|
22
|
+
}
|
|
23
|
+
export interface DocumentVoiceCatalogQuery { source?: CanonicalSource, engine?: string, lang?: string }
|
|
24
|
+
export interface DocumentVoiceCatalogAnswer extends VoiceCatalogAnswer { document: string, source: CanonicalSource, findings?: Finding[] }
|
|
25
|
+
|
|
26
|
+
/** Shared voice discovery and explicitly authorized tasks; discovery never compiles or synthesizes. */
|
|
27
|
+
export interface DocumentVoiceAuthoring extends DocumentVoiceTasks {
|
|
28
|
+
capabilities(document: string, member: Member, signal?: AbortSignal): Promise<DocumentVoiceCapabilities>
|
|
29
|
+
catalog(document: string, query: DocumentVoiceCatalogQuery, member: Member, signal?: AbortSignal): Promise<DocumentVoiceCatalogAnswer>
|
|
30
|
+
/** Checks a start or preview with the same path as the action, without synthesizing, so an agent asks only for one that would run. */
|
|
31
|
+
checkStart(document: string, request: VoiceoverStart, member: Member, signal?: AbortSignal): Promise<void>
|
|
32
|
+
checkPreview(document: string, request: VoicePreviewStart, member: Member, signal?: AbortSignal): Promise<void>
|
|
33
|
+
/** Undefined when there is something to cancel; otherwise the unchanged state that cancel would report. */
|
|
34
|
+
checkCancel(document: string, query: VoiceoverJobQuery, member: Member): Promise<VoiceoverCancellation | undefined>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const DOCUMENT_VOICE_CATALOG_SCHEMA = {
|
|
38
|
+
type: 'object', additionalProperties: false,
|
|
39
|
+
properties: {
|
|
40
|
+
source: { type: 'object', additionalProperties: false, properties: { documentId: { type: 'string', minLength: 1, maxLength: 200 }, version: { type: 'string', pattern: '^[a-f\\d]{20}$' }, fingerprint: { type: 'string', pattern: '^[a-f\\d]{16}$' } }, required: ['documentId', 'version', 'fingerprint'] },
|
|
41
|
+
engine: { type: 'string', minLength: 1, maxLength: 200 },
|
|
42
|
+
lang: { type: 'string', minLength: 1, maxLength: 100 },
|
|
43
|
+
},
|
|
44
|
+
} as const
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import type { ExecuteConfig } from './execution.ts'
|
|
2
|
+
import type { SpeechVoice } from './speech.ts'
|
|
3
|
+
|
|
4
|
+
export const DOCUMENT_SCHEMA_VERSION = 1 as const
|
|
5
|
+
export const DOCUMENT_ENTRY = 'lecture.json'
|
|
6
|
+
export const ASSET_TITLE_MAX_LENGTH = 200
|
|
7
|
+
|
|
8
|
+
export type JsonValue = null | boolean | number | string | JsonValue[] | JsonObject
|
|
9
|
+
export interface JsonObject { [key: string]: JsonValue }
|
|
10
|
+
export type JsonSchema = JsonObject | boolean
|
|
11
|
+
export type DocumentId = string
|
|
12
|
+
export type SectionId = string
|
|
13
|
+
export type BlockId = string
|
|
14
|
+
export type StepId = string
|
|
15
|
+
export type NarrationId = string
|
|
16
|
+
export type AssetId = string
|
|
17
|
+
export type DefinitionId = string
|
|
18
|
+
export type ClipId = string
|
|
19
|
+
|
|
20
|
+
export interface DocumentMetadata {
|
|
21
|
+
title: string
|
|
22
|
+
lang: string
|
|
23
|
+
description?: string
|
|
24
|
+
tags?: string[]
|
|
25
|
+
plugins?: string[]
|
|
26
|
+
presmium?: Record<string, JsonObject>
|
|
27
|
+
renderers?: Record<string, JsonObject>
|
|
28
|
+
execute?: ExecuteConfig
|
|
29
|
+
checks?: JsonObject
|
|
30
|
+
translations?: Record<string, string>
|
|
31
|
+
translationOf?: { entry: string, digest: string }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Canonical authoring data. Runtime positions, resolved assets and playback plans are derived. */
|
|
35
|
+
export interface TeachingDocument {
|
|
36
|
+
schemaVersion: typeof DOCUMENT_SCHEMA_VERSION
|
|
37
|
+
id: DocumentId
|
|
38
|
+
metadata: DocumentMetadata
|
|
39
|
+
sectionOrder: SectionId[]
|
|
40
|
+
sections: Record<SectionId, Section>
|
|
41
|
+
blocks: Record<BlockId, DocumentBlock>
|
|
42
|
+
steps: Record<StepId, Step>
|
|
43
|
+
narrations: Record<NarrationId, Narration>
|
|
44
|
+
assets: Record<AssetId, Asset>
|
|
45
|
+
definitions: Record<DefinitionId, Definition>
|
|
46
|
+
production: Production
|
|
47
|
+
comments?: Record<string, DocumentThread>
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface Layout {
|
|
51
|
+
type: 'stack' | 'columns' | 'canvas' | 'scrolly'
|
|
52
|
+
properties?: JsonObject
|
|
53
|
+
renderers?: Record<string, JsonObject>
|
|
54
|
+
}
|
|
55
|
+
export interface Section {
|
|
56
|
+
id: SectionId
|
|
57
|
+
title: string
|
|
58
|
+
level?: 1 | 2 | 3 | 4 | 5 | 6
|
|
59
|
+
children: BlockId[]
|
|
60
|
+
stepOrder: StepId[]
|
|
61
|
+
layout: Layout
|
|
62
|
+
audience?: string[]
|
|
63
|
+
config?: Record<string, JsonObject>
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export type TextAlignment = 'left' | 'center' | 'right' | 'justify'
|
|
67
|
+
export interface TextStyle { alignment?: TextAlignment, color?: string, background?: string }
|
|
68
|
+
export type TextMark =
|
|
69
|
+
| { type: 'bold' | 'italic' | 'underline' | 'strike' | 'code' }
|
|
70
|
+
| { type: 'color' | 'background', value: string }
|
|
71
|
+
export type InlineNode =
|
|
72
|
+
| { type: 'text', text: string, marks?: TextMark[] }
|
|
73
|
+
| { type: 'link', href: string, children: InlineNode[] }
|
|
74
|
+
| { type: 'math', value: string }
|
|
75
|
+
| { type: 'break' }
|
|
76
|
+
| InlineExtensionNode
|
|
77
|
+
|
|
78
|
+
/** A registered extension retains its own versioned semantics and an explicit readable fallback. */
|
|
79
|
+
export interface InlineExtensionNode { type: 'extension', kind: string, schemaVersion: number, data: JsonObject, fallback: string }
|
|
80
|
+
export interface RichTextExtensionNode { id: string, type: 'extension', kind: string, schemaVersion: number, data: JsonObject, fallback: RichTextNode[] }
|
|
81
|
+
|
|
82
|
+
export interface ParagraphNode { id: string, type: 'paragraph', children: InlineNode[], style?: TextStyle }
|
|
83
|
+
export interface HeadingNode { id: string, type: 'heading', level: 1 | 2 | 3 | 4 | 5 | 6, children: InlineNode[], style?: TextStyle }
|
|
84
|
+
export interface ListItemNode { id: string, type: 'listItem', children: RichTextNode[], checked?: boolean }
|
|
85
|
+
export interface ListNode { id: string, type: 'list', ordered: boolean, start?: number, children: ListItemNode[] }
|
|
86
|
+
export interface QuoteNode { id: string, type: 'blockquote', children: RichTextNode[] }
|
|
87
|
+
export interface CodeTextNode { id: string, type: 'code', language: string, value: string }
|
|
88
|
+
export interface MathTextNode { id: string, type: 'math', value: string }
|
|
89
|
+
export interface TableCellNode { id: string, type: 'tableCell', children: InlineNode[], style?: TextStyle, colspan?: number, rowspan?: number }
|
|
90
|
+
export interface TableRowNode { id: string, type: 'tableRow', children: TableCellNode[] }
|
|
91
|
+
export interface TableNode { id: string, type: 'table', children: TableRowNode[], headerRows?: number, headerColumns?: number, columnWidths?: number[] }
|
|
92
|
+
export type RichTextNode = ParagraphNode | HeadingNode | ListNode | QuoteNode | CodeTextNode | MathTextNode | TableNode | RichTextExtensionNode
|
|
93
|
+
|
|
94
|
+
export interface BlockScope { only?: string[], audience?: string[] }
|
|
95
|
+
export interface TextBlock extends BlockScope { id: BlockId, type: 'text', content: RichTextNode[], reveal?: { type: 'items', order: string[] } }
|
|
96
|
+
export interface ContainerProperties { title?: string, columnWidths?: number[], tabTitles?: string[] }
|
|
97
|
+
export interface ContainerBlock extends BlockScope { id: BlockId, type: 'container', layout: 'stack' | 'columns' | 'tabs', children: BlockId[], properties: ContainerProperties }
|
|
98
|
+
/** An image without an asset is an authored placeholder, not an asset with an empty location. */
|
|
99
|
+
export interface ImageBlock extends BlockScope { id: BlockId, type: 'image', assetId?: AssetId, alt: string, caption?: InlineNode[], width?: number, alignment?: TextAlignment }
|
|
100
|
+
export interface CodeReference { anchor: string, pin?: string, repo?: string, highlightRegions?: Record<StepId, string> }
|
|
101
|
+
export interface CodeExecution { args?: Record<string, string>, stdin?: string, timeoutMs?: number, executor?: string, when: 'compile' | 'live' | 'both', session?: string }
|
|
102
|
+
export interface CodeVariantSource { id: string, title: string, value?: string, origin?: Omit<CodeReference, 'highlightRegions'> }
|
|
103
|
+
export interface CodeBlock extends BlockScope {
|
|
104
|
+
id: BlockId
|
|
105
|
+
type: 'code'
|
|
106
|
+
language: string
|
|
107
|
+
value?: string
|
|
108
|
+
origin?: CodeReference
|
|
109
|
+
title?: string
|
|
110
|
+
execution?: CodeExecution
|
|
111
|
+
highlight?: Record<StepId, number[]>
|
|
112
|
+
variants?: CodeVariantSource[]
|
|
113
|
+
echo?: boolean
|
|
114
|
+
}
|
|
115
|
+
export interface ComponentBlock extends BlockScope { id: BlockId, type: 'component', definitionId: DefinitionId, parameters: JsonObject, children?: BlockId[] }
|
|
116
|
+
export type DocumentBlock = TextBlock | ContainerBlock | ImageBlock | CodeBlock | ComponentBlock
|
|
117
|
+
|
|
118
|
+
/** State is independent from ordering and production timing. Omitted blocks are invisible. */
|
|
119
|
+
export interface Step {
|
|
120
|
+
id: StepId
|
|
121
|
+
sectionId: SectionId
|
|
122
|
+
title?: string
|
|
123
|
+
visuals: VisualState[]
|
|
124
|
+
narrationIds: NarrationId[]
|
|
125
|
+
inherits?: StepId
|
|
126
|
+
}
|
|
127
|
+
export interface VisualState { blockId: BlockId, visible: boolean, state?: string, parameters?: JsonObject }
|
|
128
|
+
export type NarrationNode =
|
|
129
|
+
| { type: 'text', text: string }
|
|
130
|
+
| { type: 'pronunciation', display: string, spoken: string }
|
|
131
|
+
| { id: string, type: 'cue', action: string, target?: { blockId: BlockId, element?: string }, parameters?: JsonObject }
|
|
132
|
+
export interface Narration {
|
|
133
|
+
id: NarrationId
|
|
134
|
+
content: NarrationNode[]
|
|
135
|
+
/** Attribution of an explicit adoption; never a second caption or spoken-text source. */
|
|
136
|
+
provenance?: { type: 'transcription', transcriptionId: string, revision: string, assetId: AssetId, audioSha256: string, segmentIds: string[] }
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface Asset { id: AssetId, kind: 'image' | 'audio' | 'video' | 'file', location: string, title?: string, fingerprint?: string, mediaType?: string }
|
|
140
|
+
export type ImplementationRef =
|
|
141
|
+
| { type: 'file', path: string, exportName?: string, fingerprint?: string }
|
|
142
|
+
| { type: 'module', specifier: string, exportName?: string }
|
|
143
|
+
| { type: 'plugin', plugin: string, name: string }
|
|
144
|
+
export interface StateDescriptor {
|
|
145
|
+
id: string
|
|
146
|
+
title?: string
|
|
147
|
+
parameterSchema?: JsonSchema
|
|
148
|
+
/** A migration must retain numerical implementation bindings explicitly, never invent semantic names. */
|
|
149
|
+
legacyIndex?: number
|
|
150
|
+
}
|
|
151
|
+
export interface Definition {
|
|
152
|
+
id: DefinitionId
|
|
153
|
+
kind: string
|
|
154
|
+
schemaVersion: number
|
|
155
|
+
implementation: ImplementationRef
|
|
156
|
+
parameterSchema: JsonSchema
|
|
157
|
+
states: StateDescriptor[]
|
|
158
|
+
data?: JsonObject
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export type VoiceSource = { type: 'none' } | { type: 'tts', voice: SpeechVoice } | { type: 'recording', assetId: AssetId, sourceRange?: TimeRange }
|
|
162
|
+
export interface StepProduction {
|
|
163
|
+
narrationStart?: 'with-animation' | 'after-animation'
|
|
164
|
+
minimumHoldMs?: number
|
|
165
|
+
trailingPauseMs?: number
|
|
166
|
+
voiceSource?: VoiceSource
|
|
167
|
+
}
|
|
168
|
+
export interface ProductionDefaults extends StepProduction {}
|
|
169
|
+
export interface TimeRange { startMs: number, endMs: number }
|
|
170
|
+
/** Explicit author times; offsets partition the original ordered step narration display in UTF16. */
|
|
171
|
+
export interface CaptionTiming {
|
|
172
|
+
narrationIds: NarrationId[]
|
|
173
|
+
sourceFingerprint: string
|
|
174
|
+
playbackFingerprint: string
|
|
175
|
+
durationMs: number
|
|
176
|
+
segments: { id: string, from: number, to: number, startMs: number, endMs: number }[]
|
|
177
|
+
}
|
|
178
|
+
export interface MediaClip {
|
|
179
|
+
id: ClipId
|
|
180
|
+
assetId: AssetId
|
|
181
|
+
sourceRange: TimeRange
|
|
182
|
+
attachment: { stepId: StepId, offsetMs: number }
|
|
183
|
+
/** Output gain, from zero to one; muting does not replace this value. */
|
|
184
|
+
volume: number
|
|
185
|
+
muted?: boolean
|
|
186
|
+
}
|
|
187
|
+
export interface Production {
|
|
188
|
+
defaults: ProductionDefaults
|
|
189
|
+
sectionOverrides?: Record<SectionId, StepProduction>
|
|
190
|
+
stepOverrides: Record<StepId, StepProduction>
|
|
191
|
+
/** Migrated narration defaults: after page settings, before an explicit step override; shared narrations retain this source. */
|
|
192
|
+
narrationOverrides?: Record<NarrationId, { narrationStart: 'with-animation' | 'after-animation' }>
|
|
193
|
+
/** Cue placement is authored in narration; its delay is owned only here. */
|
|
194
|
+
cueTimings?: Record<string, { pauseMs: number }>
|
|
195
|
+
/** Stale mappings remain inspectable but never retime audio or replace changed narration. */
|
|
196
|
+
captionTimings?: Record<StepId, CaptionTiming>
|
|
197
|
+
mediaClips: MediaClip[]
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** A stable rich-text/code ID, or `page:${sectionId}` reserved for an existing section title. */
|
|
201
|
+
export interface DocumentTextPoint { blockId: string, offset: number }
|
|
202
|
+
export interface DocumentComment {
|
|
203
|
+
id: string
|
|
204
|
+
type: 'comment'
|
|
205
|
+
userId: string
|
|
206
|
+
createdAt: string
|
|
207
|
+
updatedAt: string
|
|
208
|
+
deletedAt?: string
|
|
209
|
+
content?: RichTextNode[]
|
|
210
|
+
metadata?: JsonObject
|
|
211
|
+
reactions: { emoji: string, createdAt: string, userIds: string[] }[]
|
|
212
|
+
}
|
|
213
|
+
export interface DocumentThread {
|
|
214
|
+
id: string
|
|
215
|
+
type: 'thread'
|
|
216
|
+
createdAt: string
|
|
217
|
+
updatedAt: string
|
|
218
|
+
resolved: boolean
|
|
219
|
+
resolvedUpdatedAt?: string
|
|
220
|
+
resolvedBy?: string
|
|
221
|
+
metadata?: JsonObject
|
|
222
|
+
deletedAt?: string
|
|
223
|
+
anchor?: { from: DocumentTextPoint, to: DocumentTextPoint }
|
|
224
|
+
comments: DocumentComment[]
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export interface DocumentIssue { path: string, code: string, message: string, severity: 'error' | 'warning' }
|
|
228
|
+
export interface DocumentValidation { document?: TeachingDocument, issues: DocumentIssue[] }
|
|
229
|
+
|
|
230
|
+
/** A source-document transaction. Its CAS version is unrelated to a compiled snapshot ID. */
|
|
231
|
+
export type DocumentEditOperation =
|
|
232
|
+
| { type: 'insertBlock', sectionId: SectionId, parentId?: BlockId, index: number, block: DocumentBlock }
|
|
233
|
+
| { type: 'moveBlock', blockId: BlockId, sectionId: SectionId, parentId?: BlockId, index: number }
|
|
234
|
+
| { type: 'deleteBlock', blockId: BlockId }
|
|
235
|
+
| { type: 'updateText', blockId: BlockId, content: RichTextNode[] }
|
|
236
|
+
| { type: 'updateSection', sectionId: SectionId, title?: string, layout?: Layout }
|
|
237
|
+
| { type: 'setStepState', stepId: StepId, visuals: VisualState[], inherits?: StepId }
|
|
238
|
+
| { type: 'setNarration', narration: Narration, stepId?: StepId, index?: number }
|
|
239
|
+
| { type: 'setTiming', stepId?: StepId, sectionId?: SectionId, value: StepProduction }
|
|
240
|
+
| { type: 'replaceAsset', asset: Asset }
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Logger, Unsubscribe } from '
|
|
1
|
+
import type { Logger, Unsubscribe } from './plugin.ts'
|
|
2
2
|
import { defineService } from './service.ts'
|
|
3
3
|
|
|
4
4
|
export interface RunRequest {
|
|
@@ -10,6 +10,7 @@ export interface RunRequest {
|
|
|
10
10
|
files?: Record<string, string>
|
|
11
11
|
executor?: string
|
|
12
12
|
session?: string
|
|
13
|
+
place?: { section: string, block: string }
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export type RunOutput =
|
|
@@ -91,6 +92,8 @@ export interface EnvironmentSpec {
|
|
|
91
92
|
kernel?: string
|
|
92
93
|
languages?: string[]
|
|
93
94
|
auth?: EnvironmentAuth
|
|
95
|
+
/** Operator-defined JupyterHub environment profile; images and resource limits stay on the Hub. */
|
|
96
|
+
profile?: string
|
|
94
97
|
image?: string
|
|
95
98
|
path?: string
|
|
96
99
|
[option: string]: unknown
|
|
@@ -102,10 +105,6 @@ export interface ExecuteConfig {
|
|
|
102
105
|
rerun?: 'environment'
|
|
103
106
|
}
|
|
104
107
|
|
|
105
|
-
export function environmentExecutor(name: string): string {
|
|
106
|
-
return `presmium.env.${name}`
|
|
107
|
-
}
|
|
108
|
-
|
|
109
108
|
export interface EnvironmentContext {
|
|
110
109
|
deckDir: string
|
|
111
110
|
workspaceRoot: string
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import type { CanonicalSource, DirectiveSpec, IRDocument, IRPass, Renderer, RendererContribution, RoleSpec } from '../ir.ts'
|
|
2
|
+
import type { AgentTool } from './agent.ts'
|
|
3
|
+
import type { AnchorResolver, AnchorString } from './anchors.ts'
|
|
4
|
+
import type { Check, CheckContext } from './checks.ts'
|
|
5
|
+
import type { EnvironmentProvider, EnvironmentSpec, Executor } from './execution.ts'
|
|
6
|
+
import type { NodeServiceContext, ServerContext, ServerContribution } from './server.ts'
|
|
7
|
+
import type { Locale } from './locale.ts'
|
|
8
|
+
import type { ServiceToken } from './service.ts'
|
|
9
|
+
|
|
10
|
+
export const KERNEL_VERSION = '1.0.0'
|
|
11
|
+
|
|
12
|
+
export type Capability = 'fs' | 'network' | 'exec' | 'git'
|
|
13
|
+
|
|
14
|
+
export interface ServiceRequirement {
|
|
15
|
+
token: ServiceToken<unknown>
|
|
16
|
+
optional?: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface PluginManifest {
|
|
20
|
+
id: string
|
|
21
|
+
/** The name readers and authors see (the startup report), in both interface languages; the id is never shown. */
|
|
22
|
+
name?: Record<Locale, string>
|
|
23
|
+
version: string
|
|
24
|
+
kernel: string
|
|
25
|
+
provides?: ServiceToken<unknown>[]
|
|
26
|
+
requires?: ServiceRequirement[]
|
|
27
|
+
capabilities?: Capability[]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type PresentationMode = 'slides' | 'document'
|
|
31
|
+
|
|
32
|
+
export interface Logger {
|
|
33
|
+
debug(...args: unknown[]): void
|
|
34
|
+
info(...args: unknown[]): void
|
|
35
|
+
warn(...args: unknown[]): void
|
|
36
|
+
error(...args: unknown[]): void
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type Unsubscribe = () => void
|
|
40
|
+
|
|
41
|
+
export interface DomainEvent<Type extends string = string, Payload = unknown> {
|
|
42
|
+
type: Type
|
|
43
|
+
payload: Payload
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface EventBus {
|
|
47
|
+
emit(event: DomainEvent): void
|
|
48
|
+
on<E extends DomainEvent>(type: E['type'], handler: (event: E) => void): Unsubscribe
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface PluginContext {
|
|
52
|
+
config: Record<string, unknown>
|
|
53
|
+
mode: PresentationMode
|
|
54
|
+
provide<T>(token: ServiceToken<T>, implementation: T): void
|
|
55
|
+
get<T>(token: ServiceToken<T>): T
|
|
56
|
+
tryGet<T>(token: ServiceToken<T>): T | undefined
|
|
57
|
+
events: EventBus
|
|
58
|
+
log: Logger
|
|
59
|
+
environments?: Readonly<Record<string, EnvironmentSpec>>
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface PluginDefinition {
|
|
63
|
+
manifest: PluginManifest
|
|
64
|
+
/** Opt in only when dispose stops every resource and this definition can run setup again. */
|
|
65
|
+
restartable?: boolean
|
|
66
|
+
setup(ctx: PluginContext): void | Promise<void>
|
|
67
|
+
/** Also called after setup fails; releases resources acquired during partial initialization. */
|
|
68
|
+
dispose?(): void | Promise<void>
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export type PluginStatus = 'started' | 'degraded' | 'disabled' | 'failed'
|
|
72
|
+
|
|
73
|
+
export interface PluginReport {
|
|
74
|
+
id: string
|
|
75
|
+
name?: Record<Locale, string>
|
|
76
|
+
status: PluginStatus
|
|
77
|
+
reason?: string
|
|
78
|
+
missing?: string[]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface StartReport {
|
|
82
|
+
order: string[]
|
|
83
|
+
plugins: PluginReport[]
|
|
84
|
+
cycles: string[][]
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type KernelEvent =
|
|
88
|
+
| DomainEvent<'kernel.plugin.started', { id: string }>
|
|
89
|
+
| DomainEvent<'kernel.plugin.degraded', { id: string; missing: string[] }>
|
|
90
|
+
| DomainEvent<'kernel.plugin.disabled', { id: string; reason: string }>
|
|
91
|
+
| DomainEvent<'kernel.plugin.failed', { id: string; error: string }>
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* A heavy output of a document that the plugin makes on request, as a job of the workspace service (the slides as a PDF,
|
|
95
|
+
* the lecture as a video): the job shows its progress and log, and keeps the files for the author and the AI.
|
|
96
|
+
*/
|
|
97
|
+
export interface Exporter {
|
|
98
|
+
/** Unique among the outputs of a document, renderers' ids included (e.g. `pdf`, `video`). */
|
|
99
|
+
id: string
|
|
100
|
+
/** What the author sees, by language (`zh-CN`, `en`). */
|
|
101
|
+
label: Record<string, string>
|
|
102
|
+
/** Whether the document can be exported so (e.g. it has the slides form); every document when left out. */
|
|
103
|
+
available?(doc: IRDocument, config: Record<string, unknown>): boolean
|
|
104
|
+
run(ctx: ExportContext): Promise<ExportOutput>
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface ExportContext {
|
|
108
|
+
deckDir: string
|
|
109
|
+
workspaceRoot: string
|
|
110
|
+
/** The exact canonical source from which the requested compilation was derived. */
|
|
111
|
+
source?: CanonicalSource
|
|
112
|
+
/** The plugin's configuration in the document (`presmium.<plugin id>`). */
|
|
113
|
+
config: Record<string, unknown>
|
|
114
|
+
/** An empty directory, the job's own, for the files. */
|
|
115
|
+
outDir: string
|
|
116
|
+
/** Aborted when the author cancels the job: the exporter stops its processes and rejects. */
|
|
117
|
+
signal: AbortSignal
|
|
118
|
+
/** Where the job is: a phase, and how far through it. */
|
|
119
|
+
progress(phase: string, done?: number, total?: number): void
|
|
120
|
+
/** A line of the job's log (a tool's output, a step). */
|
|
121
|
+
log(line: string): void
|
|
122
|
+
/** What the one who asked for the export chose, as the exporter documents it (`presmium-export`'s `--with-clicks`). */
|
|
123
|
+
options: Record<string, unknown>
|
|
124
|
+
/**
|
|
125
|
+
* Builds the document with renderer `renderer` (at the root path, with `config` over the document's configuration of
|
|
126
|
+
* the renderer) and gives the directory of its output, the job's own: an exporter of the slides prints them from it.
|
|
127
|
+
*/
|
|
128
|
+
build(renderer: string, config?: Record<string, unknown>): Promise<string>
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface ExportOutput {
|
|
132
|
+
/** The files made, below `outDir`, the one to show first. */
|
|
133
|
+
files: string[]
|
|
134
|
+
/** The WebVTT captions of the first file (a video), by language, among `files`. */
|
|
135
|
+
captions?: Record<string, string>
|
|
136
|
+
warnings?: string[]
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Files of an installed package that a plugin's browser code loads while it runs (Pyodide, the WASI runtimes): served
|
|
141
|
+
* below the document's site path at `<base><prefix><file>` and copied there into a built site.
|
|
142
|
+
*/
|
|
143
|
+
export interface RuntimeAssets {
|
|
144
|
+
name: string
|
|
145
|
+
/** The directory below the document's site path, e.g. `pyodide/`. */
|
|
146
|
+
prefix: string
|
|
147
|
+
/** The files that are served, with their content types. */
|
|
148
|
+
types: Readonly<Record<string, string>>
|
|
149
|
+
/** The files a build copies; default: all that are served. */
|
|
150
|
+
emitted?: readonly string[]
|
|
151
|
+
/** The path of a file on disk. */
|
|
152
|
+
source(file: string): string
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export interface PresmiumNodePlugin {
|
|
156
|
+
id: string
|
|
157
|
+
version?: string
|
|
158
|
+
kernel?: string
|
|
159
|
+
resolvers?: AnchorResolver[]
|
|
160
|
+
checks?: Check[]
|
|
161
|
+
anchors?(ctx: CheckContext): AnchorString[] | Promise<AnchorString[]>
|
|
162
|
+
directives?: DirectiveSpec[]
|
|
163
|
+
passes?: IRPass[]
|
|
164
|
+
executors?: Executor[]
|
|
165
|
+
renderer?: Renderer
|
|
166
|
+
rendererExtensions?: Record<string, RendererContribution>
|
|
167
|
+
/** The files the plugin's browser code loads while it runs (a language runtime), for the document's configuration of the plugin. */
|
|
168
|
+
assets?(ctx: { deckDir: string, workspaceRoot: string, config: Record<string, unknown> }): RuntimeAssets[]
|
|
169
|
+
/**
|
|
170
|
+
* The virtual modules of the plugin's browser code whose content depends on the document (e.g. the list of its scene
|
|
171
|
+
* files), by id, with their source. The viewer app, prebuilt once for all documents, gets them from the document's own
|
|
172
|
+
* bundle, built with this source. Only their default export is read there.
|
|
173
|
+
*/
|
|
174
|
+
documentModules?(ctx: { deckDir: string, workspaceRoot: string, config: Record<string, unknown> }): Record<string, string>
|
|
175
|
+
/** The heavy outputs the plugin makes on request, as jobs of the workspace service. */
|
|
176
|
+
exporters?: Exporter[]
|
|
177
|
+
services?(ctx: NodeServiceContext): [ServiceToken<unknown>, unknown][]
|
|
178
|
+
environments?: Record<string, EnvironmentProvider>
|
|
179
|
+
server?(ctx: ServerContext): ServerContribution | Promise<ServerContribution>
|
|
180
|
+
roles?: RoleSpec[]
|
|
181
|
+
tools?: AgentTool[]
|
|
182
|
+
operator?: boolean
|
|
183
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Unsubscribe } from './plugin.ts'
|
|
2
|
+
import { defineService } from './service.ts'
|
|
3
|
+
|
|
4
|
+
export interface PresenterPanel {
|
|
5
|
+
id: string
|
|
6
|
+
title: string
|
|
7
|
+
component: unknown
|
|
8
|
+
order?: number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface PresenterPanels {
|
|
12
|
+
register(panel: PresenterPanel): Unsubscribe
|
|
13
|
+
list(): PresenterPanel[]
|
|
14
|
+
subscribe(listener: () => void): Unsubscribe
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const PRESENTER_PANELS = defineService<PresenterPanels>('presmium.presenterPanels')
|