@xnetjs/plugins 0.0.3 → 0.1.0

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +148 -7
  2. package/dist/index.js +232 -110
  3. package/package.json +5 -5
package/dist/index.d.ts CHANGED
@@ -2819,10 +2819,8 @@ declare function runAction(action: DefinedAction, event: ActionEvent, ports: Run
2819
2819
  * private RFC-1918 range — to exfiltrate credentials or reach internal
2820
2820
  * services. {@link assertPublicUrl} rejects those before the request leaves.
2821
2821
  *
2822
- * This is a *literal-host* guard (scheme + hostname/IP inspection), not a
2823
- * post-DNS-resolution guard: a hostname that resolves to a private IP at
2824
- * request time is not caught here. That deeper check belongs in the fetch
2825
- * implementation; this closes the common, cheap holes by construction.
2822
+ * The literal-host check itself lives in `@xnetjs/core`; this module keeps the
2823
+ * action-specific {@link ActionSsrfError} contract that callers/tests depend on.
2826
2824
  */
2827
2825
  declare class ActionSsrfError extends Error {
2828
2826
  readonly url: string;
@@ -4534,6 +4532,13 @@ declare class ManagedProvider implements AIProvider {
4534
4532
  getCapabilities(): AIModelCapabilities;
4535
4533
  generate(prompt: string): Promise<string>;
4536
4534
  generateWithTools(request: AIGenerateRequest): Promise<AIGenerateResponse>;
4535
+ /**
4536
+ * Stream the managed completion over SSE (`/ai/chat/stream`). Yields a `text`
4537
+ * chunk per delta, then `usage` + `done`; emits the live budget from the terminal
4538
+ * `done` event. A `402` (pre-stream) or an `ai_budget_exceeded` error event
4539
+ * becomes an {@link AiBudgetError} (exploration 0244).
4540
+ */
4541
+ stream(request: AIGenerateRequest): AsyncIterable<AIStreamChunk>;
4537
4542
  private emitBudget;
4538
4543
  }
4539
4544
  /** Build a {@link ManagedProvider} (parallels `createPromptApiProvider`). */
@@ -4672,6 +4677,15 @@ declare function generateScript(provider: AIProvider, request: AIScriptRequest):
4672
4677
  */
4673
4678
 
4674
4679
  type AiAgentOrchestratorMode = 'custom' | 'codex-app-server' | 'hybrid';
4680
+ /**
4681
+ * How the assistant relates to the user's work (xNet Humane Internet Charter
4682
+ * §Agency). `scaffold` — the default — keeps the human as the author: the model
4683
+ * proposes and cites, the user writes and owns. It is a guard against the
4684
+ * cognitive-debt / deskilling effect of LLM-authored work (MIT Media Lab,
4685
+ * arXiv:2506.08872). `draft`, where the model produces finished prose, must be
4686
+ * opted into explicitly. Either way the resulting turn is tagged `ai-generated`.
4687
+ */
4688
+ type AiAssistMode = 'scaffold' | 'draft';
4675
4689
  type AiAgentThreadStatus = 'idle' | 'running' | 'waiting-approval' | 'cancelled' | 'failed';
4676
4690
  type AiAgentTurnRole = 'system' | 'user' | 'assistant' | 'tool';
4677
4691
  type AiAgentTurnStatus = 'pending' | 'streaming' | 'completed' | 'cancelled' | 'failed';
@@ -4783,6 +4797,13 @@ type AiAgentRuntimeConfig = {
4783
4797
  systemPrompt?: string;
4784
4798
  /** Optional hook injecting grounding context messages before the history. */
4785
4799
  contextProvider?: AiAgentContextProvider;
4800
+ /**
4801
+ * Assist mode (default `scaffold`). Tags every assistant turn's provenance and
4802
+ * is exposed via {@link AiAgentRuntime.getAssistMode}; apps compose the
4803
+ * scaffold guard into their system prompt with {@link composeAssistSystemPrompt}.
4804
+ * `draft` is never the default — it must be set explicitly.
4805
+ */
4806
+ assistMode?: AiAssistMode;
4786
4807
  };
4787
4808
  type AiAgentThreadCreateInput = {
4788
4809
  title: string;
@@ -4851,6 +4872,7 @@ declare class AiAgentRuntime {
4851
4872
  private readonly storage;
4852
4873
  private readonly clock;
4853
4874
  private readonly mode;
4875
+ private readonly assistMode;
4854
4876
  private readonly maxEvents;
4855
4877
  private sequence;
4856
4878
  private loaded;
@@ -4858,6 +4880,8 @@ declare class AiAgentRuntime {
4858
4880
  private readonly activeRuns;
4859
4881
  private readonly activeJobs;
4860
4882
  constructor(config: AiAgentRuntimeConfig);
4883
+ /** The active assist mode (`scaffold` by default; `draft` is opt-in only). */
4884
+ getAssistMode(): AiAssistMode;
4861
4885
  load(): Promise<AiAgentRuntimeSnapshot>;
4862
4886
  getSnapshot(): AiAgentRuntimeSnapshot;
4863
4887
  subscribe(listener: AiAgentRuntimeListener): () => void;
@@ -4905,6 +4929,26 @@ declare function createAiAgentRuntime(config: AiAgentRuntimeConfig): AiAgentRunt
4905
4929
  declare function createMemoryAiAgentRuntimeStorage(initial?: AiAgentRuntimeSnapshot): AiAgentRuntimeStorage & {
4906
4930
  snapshot(): AiAgentRuntimeSnapshot;
4907
4931
  };
4932
+ /** Provenance tag stamped on every assistant turn (xNet trust tiers). */
4933
+ declare const AI_GENERATED_PROVENANCE: "ai-generated";
4934
+ /**
4935
+ * The cognitive-debt guard appended to the system prompt in scaffold mode. It
4936
+ * asks the model to help the user think rather than think for them — an answer
4937
+ * to the deskilling effect of LLM-authored work (MIT, arXiv:2506.08872).
4938
+ */
4939
+ declare const SCAFFOLD_SYSTEM_GUARD: string;
4940
+ /**
4941
+ * Compose the system prompt for an assist mode. In `scaffold` mode the guard is
4942
+ * appended so the assistant scaffolds rather than substitutes; in `draft` mode
4943
+ * the base prompt passes through unchanged. Returned to apps so the runtime's
4944
+ * own message composition stays backward-compatible.
4945
+ */
4946
+ declare function composeAssistSystemPrompt(base: string | undefined, mode: AiAssistMode): string | undefined;
4947
+ /** Metadata stamped on an assistant turn so its provenance is always legible. */
4948
+ declare function assistTurnProvenance(mode: AiAssistMode): {
4949
+ provenance: typeof AI_GENERATED_PROVENANCE;
4950
+ assistMode: AiAssistMode;
4951
+ };
4908
4952
  declare function renderSelectionPrompt(instruction: string, selection: AiAgentSelectionContext): string;
4909
4953
  declare function classifyAiAgentDisplayState(input: {
4910
4954
  plan?: AiMutationPlan;
@@ -4947,7 +4991,20 @@ interface ConnectorEnv {
4947
4991
  managedUrl?: string;
4948
4992
  /** WebGPU present (enables in-tab models). Default: `navigator.gpu` check. */
4949
4993
  hasWebGpu?: () => boolean | Promise<boolean>;
4950
- /** Chrome built-in `LanguageModel` present. Default: global check. */
4994
+ /**
4995
+ * Whether the host can actually build an in-tab WebLLM engine (the heavy
4996
+ * `@mlc-ai/web-llm` import is host-supplied, see the panel). The `webllm` tier
4997
+ * is reported available only when this AND {@link hasWebGpu} are true —
4998
+ * detecting WebGPU alone would advertise a tier the host can't instantiate,
4999
+ * leaving the composer silently disabled. Default: `false` (no engine wired).
5000
+ */
5001
+ hasWebLLMEngine?: () => boolean | Promise<boolean>;
5002
+ /**
5003
+ * Chrome built-in `LanguageModel` is present *and the model is ready to use*.
5004
+ * Default: probes `LanguageModel.availability()` and reports ready only for
5005
+ * `'available'` — mere API presence (`'downloadable'`) means a session can't
5006
+ * be created without a user-gesture download first (see the panel's gesture).
5007
+ */
4951
5008
  hasPromptApi?: () => boolean | Promise<boolean>;
4952
5009
  /** Local model endpoints to probe, in priority order. Default: Ollama, LM Studio. */
4953
5010
  localServerProbes?: readonly LocalServerProbe[];
@@ -5110,14 +5167,24 @@ interface LanguageModelSessionLike {
5110
5167
  prompt(input: string): Promise<string>;
5111
5168
  promptStreaming(input: string): AsyncIterable<string>;
5112
5169
  }
5170
+ /** The four states Chrome's `LanguageModel.availability()` can report. */
5171
+ type PromptApiAvailability = 'unavailable' | 'downloadable' | 'downloading' | 'available';
5172
+ /** A download-progress monitor passed to `create({ monitor })`. */
5173
+ interface LanguageModelMonitor {
5174
+ addEventListener(type: 'downloadprogress', listener: (event: {
5175
+ loaded: number;
5176
+ }) => void): void;
5177
+ }
5113
5178
  /** Minimal shape of the global `LanguageModel` factory. */
5114
5179
  interface LanguageModelLike {
5115
- availability(): Promise<'unavailable' | 'downloadable' | 'downloading' | 'available'>;
5180
+ availability(): Promise<PromptApiAvailability>;
5116
5181
  create(options?: {
5117
5182
  initialPrompts?: Array<{
5118
5183
  role: string;
5119
5184
  content: string;
5120
5185
  }>;
5186
+ /** Observe the on-device model download (fires `downloadprogress`). */
5187
+ monitor?: (monitor: LanguageModelMonitor) => void;
5121
5188
  }): Promise<LanguageModelSessionLike>;
5122
5189
  }
5123
5190
  interface PromptApiProviderOptions {
@@ -5138,6 +5205,22 @@ declare class PromptApiProvider implements AIProvider {
5138
5205
  * needed. Returns null if the API is unavailable (not Chrome, or no model).
5139
5206
  */
5140
5207
  declare function createPromptApiProvider(factory?: LanguageModelLike): Promise<PromptApiProvider | null>;
5208
+ /**
5209
+ * Raw availability of the on-device model, or `'unavailable'` when the API is
5210
+ * absent (not Chrome) or the probe throws. Unlike `createPromptApiProvider`,
5211
+ * this distinguishes `'downloadable'`/`'downloading'` from `'available'` so the
5212
+ * UI can offer a download gesture instead of silently reporting "unavailable".
5213
+ */
5214
+ declare function promptApiAvailability(factory?: LanguageModelLike): Promise<PromptApiAvailability>;
5215
+ /**
5216
+ * Trigger the on-device model download from a **user gesture**, reporting
5217
+ * progress as a fraction in [0, 1]. Chrome gates the download behind a user
5218
+ * activation, so this must be called from a click handler — not an effect.
5219
+ * Resolves `true` once a session is creatable; the runtime rebuilds its own
5220
+ * session once detection re-flips to `'available'`. Returns `false` when the
5221
+ * API is absent; throws (for the caller to `.catch`) if `create()` rejects.
5222
+ */
5223
+ declare function downloadPromptApiModel(onProgress?: (fraction: number) => void, factory?: LanguageModelLike): Promise<boolean>;
5141
5224
 
5142
5225
  /**
5143
5226
  * Service Plugin Types
@@ -5630,4 +5713,62 @@ interface MCPServerConfig {
5630
5713
  version?: string;
5631
5714
  }
5632
5715
 
5633
- export { type AIComplexityLevel, type AICostModel, type AIGenerateRequest, type AIGenerateResponse, AIGenerationError, type AIMessage, type AIMessageRole, type AIModelCapabilities, type AIModelQuality, type AIPrivacyLevel, type AIProvider, type AIProviderConfig, type AIProviderOptions, AIProviderRouter, type AIProviderRouterOptions, type AIProviderType, type AIProviderUsage, AIRTABLE_CONNECTOR_ID, type AIRiskLevel, type AIScriptRequest, type AIScriptResponse, type AIStreamChunk, type AIToolCall, type AIToolSpec, type AIUsage, AI_RISK_LEVELS, AI_SCOPES, AI_TARGET_KINDS, ALLOWED_PLUGIN_LICENSES, type ActionContext, type ActionDefinition, ActionDefinitionError, ActionDispatchError, type ActionEvent, ActionSsrfError, type ActionTrigger, type AgentToolContribution, type AgentToolInputSchema, type AiAgentApproval, type AiAgentApprovalRequestInput, type AiAgentApprovalResolveInput, type AiAgentApprovalStatus, type AiAgentBackgroundJob, type AiAgentBackgroundJobInput, type AiAgentBackgroundJobRunner, type AiAgentBackgroundJobStatus, type AiAgentDisplayState, type AiAgentDisplayStateKind, type AiAgentEvent, type AiAgentEventType, type AiAgentOrchestratorMode, type AiAgentRunSelectionTurnInput, type AiAgentRunTurnInput, type AiAgentRunTurnResult, AiAgentRuntime, type AiAgentRuntimeConfig, type AiAgentRuntimeListener, type AiAgentRuntimeSnapshot, type AiAgentRuntimeStorage, type AiAgentSelectionContext, type AiAgentSelectionKind, type AiAgentTelemetrySnapshot, type AiAgentThread, type AiAgentThreadCreateInput, type AiAgentThreadStatus, type AiAgentTurn, type AiAgentTurnRole, type AiAgentTurnStatus, type AiAuditEvent, type AiAuthoredPlugin, AiAuthoringError, AiBudgetError, type AiCallableTool, type AiChangeSet, type AiCommandExposure, type AiContextPack, type AiContextPackResource, type AiContextRetriever, type AiContextSeed, type AiDatabaseMutationApplyResult, type AiExtraTool, type AiJsonSchema, type AiJsonSchemaType, type AiMutationPlan, type AiMutationPlanStatus, type AiOperation, type AiPageMarkdownApplyAdapter, type AiPageMarkdownApplyAdapterInput, type AiPageMarkdownApplyAdapterResult, type AiPageMarkdownApplyResult, type AiPageMarkdownRollbackResult, type AiPluginPipelineInput, type AiPluginPipelinePorts, type AiPluginPipelineResult, type AiResource, type AiResourceContent, type AiRetrievedNode, type AiRiskLevel, type AiScope, type AiSearchOptions, type AiSearchResult, type AiSurfaceLimits, AiSurfaceService, type AiSurfaceServiceConfig, type AiTargetKind, type AiToolCallResult, type AiToolDefinition, type AiValidationResult, type AirtableConnectorOptions, type AllowedPluginLicense, AnthropicProvider, type ArrayHelpers, type BlockContribution, type BlockProps, CANVAS_PLUGIN_FIXTURES, CHANNEL_SCHEMA, CHAT_MESSAGE_SCHEMA, CONNECTOR_CATEGORY, CONNECTOR_META, CRM_CANVAS_PLUGIN_FIXTURE, type CanvasCardContribution, type CanvasContribution, type CanvasContributionBase, type CanvasContributionPermission, type CanvasEdgeContribution, type CanvasErpPrototypeAuditEntry, type CanvasErpPrototypeAuditOperation, type CanvasErpPrototypeAuditSource, type CanvasErpPrototypeCard, type CanvasErpPrototypeCommand, type CanvasErpPrototypeEdge, type CanvasErpPrototypeEntityKind, type CanvasErpPrototypeLayoutKind, type CanvasErpPrototypeQueryFrame, type CanvasErpPrototypeQueryPredicate, type CanvasErpPrototypeRect, type CanvasErpPrototypeRisk, type CanvasErpPrototypeRiskSummary, type CanvasErpPrototypeScenario, type CanvasErpPrototypeStatus, type CanvasIngestInputKind, type CanvasIngestorContribution, type CanvasInspectorContribution, type CanvasInspectorPlacement, type CanvasLayoutContribution, type CanvasLayoutScope, type CanvasPluginFixture, type CanvasPluginFixtureCardSample, type CanvasPluginFixtureKind, type CanvasPluginPermissionDecisionStatus, type CanvasPluginPermissionGateDecision, type CanvasPluginPermissionGateInput, type CanvasPluginPermissionPrompt, type CanvasPluginPermissionPromptOption, type CanvasPluginPromptMode, type CanvasPluginSandboxDecision, type CanvasPluginSandboxDomAccess, type CanvasPluginSandboxKind, type CanvasPluginSandboxMutationAccess, type CanvasPluginSandboxNetworkAccess, type CanvasPluginSandboxOutput, type CanvasPluginSandboxOutputKind, type CanvasPluginSandboxOutputValidation, type CanvasPluginSandboxPolicy, type CanvasPluginSandboxRequest, type CanvasPluginWorkspacePolicy, type CanvasPreviewTier, type CanvasRendererSandboxContribution, type CanvasTemplateCategory, type CanvasTemplateContribution, type CanvasToolContribution, type CanvasToolGroup, CapabilityError, type CommandContext, type CommandContribution, CommandRegistry, type CommandScope, type ConnectorArtifacts, type ConnectorCadence, type ConnectorDefinition, ConnectorDefinitionError, type ConnectorDetection, type ConnectorEnv, type ConnectorFetch, type ConnectorInstallGate, type ConnectorStore, type ConnectorSyncContext, ConnectorSyncError, type ConnectorSyncResult, type ConnectorSyncSpec, type ConnectorTier, type ConnectorToolDescriptor, type ConsentDecision, type ConsentLine, ContributionRegistry, DEFAULT_PLUGIN_LICENSE, type DefinedAction, type DefinedConnector, type DeliveryResult, DependencyCycleError, type DependencyNode, type Disposable$1 as Disposable, ERP_CANVAS_PLUGIN_FIXTURE, EXTERNAL_ITEM_SCHEMA, type EditorContribution, type EditorSchemaRisk, type EmailActionOptions, type ExtensionContext, type ExtensionStorage, FEED_ITEM_SCHEMA, type FeatureModule, type FeedEntry, type FetchJson, type FetchLike, type FlatNode, type FormatHelpers, GITHUB_CONNECTOR_ID, type GeneratedScript, type GithubConnectorOptions, type GuardableConnectorStore, type IProcessManager, type ImporterContribution, type InstallOptions, LINEAR_CONNECTOR_ID, type LabRunOutcome, type LadderRuntimeTier, type LanguageModelLike, type LanguageModelSessionLike, type LicenseCheckResult, LicenseRequiredError, type LinearConnectorOptions, type LocalAPIConfig, type LocalAPITokenConfig, type LocalAPITokenScope, type LocalAPITokenSummary, type LocalServerProbe, MARKETPLACE_PROVENANCE, type MCPPropertySchema, type MCPRequest, type MCPResource, type MCPResponse, type MCPServerConfig, type MCPTool, MEDIA_PROVIDER_CANVAS_PLUGIN_FIXTURE, type ManagedBudgetSnapshot, ManagedProvider, type ManagedProviderOptions, MarketplaceClient, type MarketplaceClientOptions, type MarketplaceEntry, type MarketplaceSort, type MathHelpers, type MentionProviderContribution, type MentionSuggestion, MiddlewareChain, type MissingDependency, type ModuleCapabilities, NOTION_CONNECTOR_ID, type NodeChangeEvent, type NodeChangeEventData, type NodeData, type NodeStoreAPI, type NodeStoreMiddleware, type NotionConnectorOptions, OllamaProvider, OpenAICompatibleProvider, type OpenAICompatibleProviderOptions, OpenAIProvider, type PendingChange, type Platform, type PlatformCapabilities, type PluginContributions, PluginError, type PluginNode, type PluginNodeChangeEvent, type PluginNodeChangeListener, type PluginPermissions, type PluginPricing, type PluginRating, PluginRegistry, type PluginRunInput, type PluginRunResult, PluginRuntimeError, type PluginRuntimeLadder, PluginSchema, type PluginStatus, PluginValidationError, type ProcessManagerEvents, PromptApiProvider, type PromptApiProviderOptions, type PropertyCellProps, type PropertyEditorProps, type PropertyHandler, type PropertyHandlerContribution, type Provenance, type ProvenanceResult, type ProvenanceVerifier, type QueryFilter, RSS_CONNECTOR_ID, type RatingSummary, type RecommendOptions, type RegisteredPlugin, type ResolveMentionOptions, type RssConnectorOptions, type RunActionPorts, type RunConnectorSyncPorts, type RunPluginCodeInput, SERVICE_IPC_CHANNELS, SLACK_CONNECTOR_ID, type SandboxOptions, ScaffoldError, type ScaffoldResult, type ScaffoldSpec, type ScaffoldTemplate, type SchemaContribution, type SchemaData, type SchemaDefinition, type SchemaProperty, type SchemaRegistryAPI, type ScriptContext, ScriptError, type ScriptExecutionResult, type ScriptExecutor, ScriptGenerationError, ScriptGenerator, type ScriptGeneratorOptions, type ScriptNode, type ScriptNodeChangeEvent, type ScriptOutputType, ScriptRunner, type ScriptRunnerOptions, ScriptSandbox, ScriptSchema, type ScriptStore, ScriptTimeoutError, type ScriptToManifestInput, type ScriptTriggerType, ScriptValidationError, type SemVer, type ServiceClient, type ServiceCommunication, type ServiceDefinition, type ServiceHealthCheck, type ServiceLifecycle, type ServiceOutputEvent, type ServiceProcessConfig, type ServiceProvides, type ServiceState, type ServiceStatus, type ServiceStatusEvent, type SettingContribution, type SettingsPanelProps, ShortcutManager, type SidebarContribution, type SlackConnectorOptions, type SlashCommandContext, type SlashCommandContribution, type StatusBarContribution, type TelemetryReporter, type TestHarnessOptions, type TestNodeStore, type TestPluginHarness, type TextHelpers, type ToolCallingFidelity, type ToolbarContribution, TypedRegistry, type UsageSignal, type ValidationResult, type VerifyProvenanceInput, type ViewContribution, type ViewProps, type WebLLMEngineLike, WebLLMProvider, type WebLLMProviderOptions, type WebhookConfig, WebhookEmitter, type WebhookOutOptions, type WebhookPayload, type WidgetContribution, type WidgetContributionConfigField, type WidgetContributionProps, type WorkspaceCommand, type WrapCliConnectorOptions, type WriteMode, XNET_MARKDOWN_DIRECTIVE_SPECS, type XNetExtension, type XNetMarkdownDiffLine, type XNetMarkdownDiffLineKind, type XNetMarkdownDirective, type XNetMarkdownDirectiveSpec, type XNetMarkdownReviewDiff, type XNetPageMarkdownFrontmatter, type XNetPageMarkdownValidation, type XNetPageMarkdownValidationOptions, agentToolToExtraTool, agentToolsAsExtraTools, aggregateRatings, assertNetwork, assertPublicUrl, assertSchemaWrite, attachAiPlanValidation, buildAirtableConnector, buildDiscordAction, buildEmailAction, buildGithubConnector, buildLinearConnector, buildNotionConnector, buildRetryPrompt, buildRssConnector, buildScriptPrompt, buildSlackConnector, buildSlackWebhookAction, buildTelegramAction, buildWebhookOutAction, classifyAiAgentDisplayState, compareVersions, connectorAsImporter, connectorMarketplaceEntry, contributionsAsAiTools, createAIProvider, createAIProviderRouter, createAiAgentRuntime, createAiChangeSet, createAiOperation, createAiSurfaceService, createAiValidationResult, createCanvasErpPrototypeRiskSummary, createCanvasErpPrototypeScenario, createCanvasPluginFixtureCards, createCanvasPluginFixtureManifests, createCanvasPluginPermissionPrompt, createCanvasPluginSandboxPolicy, createCanvasPreviewSandboxRequest, createCanvasRendererSandboxRequest, createExtensionContext, createExtensionStorage, createManagedProvider, createMemoryAiAgentRuntimeStorage, createPromptApiProvider, createScriptContext, createServiceClient, createTestNodeStore, createTestPluginHarness, createWebLLMProvider, createWebhookEmitter, defaultLocalServerProbes, defineAction, defineConnector, defineExtension, defineFeatureModule, describeCapabilities, detectConnectors, emitConnectorArtifacts, evaluateCanvasPluginPermissionGate, evaluateCanvasPluginSandboxRequest, evaluateConnectorInstall, evaluateInstallConsent, executeScript, failClosedVerifier, filterByCategory, findEditorSchemaRisks, findMissingDependencies, generateScript, getCanvasErpPrototypeAuditEntriesForCard, getCanvasErpPrototypeCardsForFrame, getCanvasPluginFixture, getCommandRegistry, getPlatformCapabilities, getShortcutManager, getXNetMarkdownDirectiveSpecs, guardStore, guardedActionFetch, guardedFetch, hasUpdate, importerAdapters, installCommandHandler, installShortcutHandler, isAiRiskLevel, isAiScope, isAiTargetKind, isAllowedPluginLicense, isHostCompatible, isNetworkAllowed, isOllamaAvailable, isPaidPricing, isSchemaDefiningExtension, isSchemaReadAllowed, isSchemaWriteAllowed, isScriptNode, isServiceClientAvailable, ladderTierForTrust, listOllamaModels, matchSchemaIri, normalizeCanvasPluginWorkspacePolicy, packageName, parseAiMutationPlan, parseFeed, parseVersion, parseXNetPageFrontmatter, pascalCase, pickBestConnector, pluginLicenseText, probeOpenAiCompatible, quickSafetyCheck, recommendExtensions, renderEvent, renderMarkdownLineDiff, renderMarkdownReviewDiff, renderSelectionPrompt, resolveImporters, resolveInstallOrder, resolveMentionProviders, runAction, runAiPluginPipeline, runConnectorSync, runPluginCode, satisfiesRange, scaffoldPlugin, scriptToPluginManifest, searchMarketplace, serializeAiMutationPlan, shortSchemaName, shouldDispatch, sortMarketplace, stripXNetPageFrontmatter, summarizeProvenance, validateAiMutationPlan, validateCanvasPluginSandboxOutput, validateManifest, validateScript, validateScriptAST, validateXNetPageMarkdown, verifyProvenance, warnOnEditorSchemaRisks, wrapCliConnector, writeModeFor };
5716
+ /**
5717
+ * Right to Leave (xNet Humane Internet Charter §Exit, exploration 0234).
5718
+ *
5719
+ * Leaving is a right, not a retention funnel. `leaveWithEverything` bundles
5720
+ * everything you'd need to recreate yourself elsewhere — your whole workspace,
5721
+ * your portable identity, and a README on how to re-import — into one archive.
5722
+ * `deleteDay` is the honest, irreversible version: stop feeding the system.
5723
+ *
5724
+ * This module is the orchestration; the app injects the real capabilities
5725
+ * (AiWorkspaceExporter for the workspace, the identity keystore, hub purge, OPFS
5726
+ * destroy, consent-gated telemetry). Keeping them as ports makes the policy —
5727
+ * "no confirmshaming, take everything, the local copy is yours" — testable in
5728
+ * isolation.
5729
+ */
5730
+ /** The capabilities the app wires in. Only `exportWorkspace`/`exportIdentity` are required. */
5731
+ interface RightToLeavePorts {
5732
+ /** The full workspace as relative-path → file-content (e.g. via AiWorkspaceExporter). */
5733
+ exportWorkspace(): Promise<Record<string, string>>;
5734
+ /** The portable identity bundle (did:key + recovery), JSON-serializable. */
5735
+ exportIdentity(): Promise<unknown>;
5736
+ /** Tombstone the user's copies on every connected hub. Absent ⇒ offline-only user. */
5737
+ purgeRemoteCopies?(): Promise<void>;
5738
+ /** Wipe the local master copy (OPFS/SQLite). Absent ⇒ nothing local to wipe. */
5739
+ destroyLocal?(): Promise<void>;
5740
+ /** Record a non-identifying `account.left` signal (consent-gated). */
5741
+ recordLeft?(): void;
5742
+ }
5743
+ interface LeaveBundle {
5744
+ /** relative path → file content; a complete, portable copy of you. */
5745
+ files: Record<string, string>;
5746
+ exportedAt: string;
5747
+ }
5748
+ interface DeleteDayOptions {
5749
+ /** Keep the local master copy on this device (export-and-go) vs. full wipe. */
5750
+ keepLocal: boolean;
5751
+ /** Injected timestamp (ISO) — no implicit clock, so the result is deterministic. */
5752
+ now: string;
5753
+ }
5754
+ interface DeleteDayResult {
5755
+ remotePurged: boolean;
5756
+ localWiped: boolean;
5757
+ recordedLeft: boolean;
5758
+ }
5759
+ declare const LEAVE_README = "# Your xNet data \u2014 yours to keep\n\nThis archive is a complete, portable copy of your workspace.\n\n- `workspace/` \u2014 every page, database, canvas, and node, plus a manifest.\n- `identity.did.json` \u2014 your portable did:key identity and recovery material.\n\nTo continue elsewhere: run your own hub (`xnet-hub start`) or any xNet-compatible\nbackend, then import this archive. Your did:key works on any hub \u2014 there is no\naccount to transfer and nothing held back. You don't need our permission to leave.\n";
5760
+ /**
5761
+ * Everything you'd need to recreate yourself elsewhere, in one bundle. There is
5762
+ * deliberately no "are you sure you'll miss out?" — this is a right, not a funnel.
5763
+ */
5764
+ declare function leaveWithEverything(ports: RightToLeavePorts, opts: {
5765
+ now: string;
5766
+ }): Promise<LeaveBundle>;
5767
+ /**
5768
+ * Delete Day: stop feeding the system, for real. Tombstones remote copies on
5769
+ * every hub and (unless `keepLocal`) wipes the local master too. The only signal
5770
+ * emitted is an anonymous `account.left` — never anything that identifies who.
5771
+ */
5772
+ declare function deleteDay(ports: RightToLeavePorts, opts: DeleteDayOptions): Promise<DeleteDayResult>;
5773
+
5774
+ export { type AIComplexityLevel, type AICostModel, type AIGenerateRequest, type AIGenerateResponse, AIGenerationError, type AIMessage, type AIMessageRole, type AIModelCapabilities, type AIModelQuality, type AIPrivacyLevel, type AIProvider, type AIProviderConfig, type AIProviderOptions, AIProviderRouter, type AIProviderRouterOptions, type AIProviderType, type AIProviderUsage, AIRTABLE_CONNECTOR_ID, type AIRiskLevel, type AIScriptRequest, type AIScriptResponse, type AIStreamChunk, type AIToolCall, type AIToolSpec, type AIUsage, AI_GENERATED_PROVENANCE, AI_RISK_LEVELS, AI_SCOPES, AI_TARGET_KINDS, ALLOWED_PLUGIN_LICENSES, type ActionContext, type ActionDefinition, ActionDefinitionError, ActionDispatchError, type ActionEvent, ActionSsrfError, type ActionTrigger, type AgentToolContribution, type AgentToolInputSchema, type AiAgentApproval, type AiAgentApprovalRequestInput, type AiAgentApprovalResolveInput, type AiAgentApprovalStatus, type AiAgentBackgroundJob, type AiAgentBackgroundJobInput, type AiAgentBackgroundJobRunner, type AiAgentBackgroundJobStatus, type AiAgentDisplayState, type AiAgentDisplayStateKind, type AiAgentEvent, type AiAgentEventType, type AiAgentOrchestratorMode, type AiAgentRunSelectionTurnInput, type AiAgentRunTurnInput, type AiAgentRunTurnResult, AiAgentRuntime, type AiAgentRuntimeConfig, type AiAgentRuntimeListener, type AiAgentRuntimeSnapshot, type AiAgentRuntimeStorage, type AiAgentSelectionContext, type AiAgentSelectionKind, type AiAgentTelemetrySnapshot, type AiAgentThread, type AiAgentThreadCreateInput, type AiAgentThreadStatus, type AiAgentTurn, type AiAgentTurnRole, type AiAgentTurnStatus, type AiAssistMode, type AiAuditEvent, type AiAuthoredPlugin, AiAuthoringError, AiBudgetError, type AiCallableTool, type AiChangeSet, type AiCommandExposure, type AiContextPack, type AiContextPackResource, type AiContextRetriever, type AiContextSeed, type AiDatabaseMutationApplyResult, type AiExtraTool, type AiJsonSchema, type AiJsonSchemaType, type AiMutationPlan, type AiMutationPlanStatus, type AiOperation, type AiPageMarkdownApplyAdapter, type AiPageMarkdownApplyAdapterInput, type AiPageMarkdownApplyAdapterResult, type AiPageMarkdownApplyResult, type AiPageMarkdownRollbackResult, type AiPluginPipelineInput, type AiPluginPipelinePorts, type AiPluginPipelineResult, type AiResource, type AiResourceContent, type AiRetrievedNode, type AiRiskLevel, type AiScope, type AiSearchOptions, type AiSearchResult, type AiSurfaceLimits, AiSurfaceService, type AiSurfaceServiceConfig, type AiTargetKind, type AiToolCallResult, type AiToolDefinition, type AiValidationResult, type AirtableConnectorOptions, type AllowedPluginLicense, AnthropicProvider, type ArrayHelpers, type BlockContribution, type BlockProps, CANVAS_PLUGIN_FIXTURES, CHANNEL_SCHEMA, CHAT_MESSAGE_SCHEMA, CONNECTOR_CATEGORY, CONNECTOR_META, CRM_CANVAS_PLUGIN_FIXTURE, type CanvasCardContribution, type CanvasContribution, type CanvasContributionBase, type CanvasContributionPermission, type CanvasEdgeContribution, type CanvasErpPrototypeAuditEntry, type CanvasErpPrototypeAuditOperation, type CanvasErpPrototypeAuditSource, type CanvasErpPrototypeCard, type CanvasErpPrototypeCommand, type CanvasErpPrototypeEdge, type CanvasErpPrototypeEntityKind, type CanvasErpPrototypeLayoutKind, type CanvasErpPrototypeQueryFrame, type CanvasErpPrototypeQueryPredicate, type CanvasErpPrototypeRect, type CanvasErpPrototypeRisk, type CanvasErpPrototypeRiskSummary, type CanvasErpPrototypeScenario, type CanvasErpPrototypeStatus, type CanvasIngestInputKind, type CanvasIngestorContribution, type CanvasInspectorContribution, type CanvasInspectorPlacement, type CanvasLayoutContribution, type CanvasLayoutScope, type CanvasPluginFixture, type CanvasPluginFixtureCardSample, type CanvasPluginFixtureKind, type CanvasPluginPermissionDecisionStatus, type CanvasPluginPermissionGateDecision, type CanvasPluginPermissionGateInput, type CanvasPluginPermissionPrompt, type CanvasPluginPermissionPromptOption, type CanvasPluginPromptMode, type CanvasPluginSandboxDecision, type CanvasPluginSandboxDomAccess, type CanvasPluginSandboxKind, type CanvasPluginSandboxMutationAccess, type CanvasPluginSandboxNetworkAccess, type CanvasPluginSandboxOutput, type CanvasPluginSandboxOutputKind, type CanvasPluginSandboxOutputValidation, type CanvasPluginSandboxPolicy, type CanvasPluginSandboxRequest, type CanvasPluginWorkspacePolicy, type CanvasPreviewTier, type CanvasRendererSandboxContribution, type CanvasTemplateCategory, type CanvasTemplateContribution, type CanvasToolContribution, type CanvasToolGroup, CapabilityError, type CommandContext, type CommandContribution, CommandRegistry, type CommandScope, type ConnectorArtifacts, type ConnectorCadence, type ConnectorDefinition, ConnectorDefinitionError, type ConnectorDetection, type ConnectorEnv, type ConnectorFetch, type ConnectorInstallGate, type ConnectorStore, type ConnectorSyncContext, ConnectorSyncError, type ConnectorSyncResult, type ConnectorSyncSpec, type ConnectorTier, type ConnectorToolDescriptor, type ConsentDecision, type ConsentLine, ContributionRegistry, DEFAULT_PLUGIN_LICENSE, type DefinedAction, type DefinedConnector, type DeleteDayOptions, type DeleteDayResult, type DeliveryResult, DependencyCycleError, type DependencyNode, type Disposable$1 as Disposable, ERP_CANVAS_PLUGIN_FIXTURE, EXTERNAL_ITEM_SCHEMA, type EditorContribution, type EditorSchemaRisk, type EmailActionOptions, type ExtensionContext, type ExtensionStorage, FEED_ITEM_SCHEMA, type FeatureModule, type FeedEntry, type FetchJson, type FetchLike, type FlatNode, type FormatHelpers, GITHUB_CONNECTOR_ID, type GeneratedScript, type GithubConnectorOptions, type GuardableConnectorStore, type IProcessManager, type ImporterContribution, type InstallOptions, LEAVE_README, LINEAR_CONNECTOR_ID, type LabRunOutcome, type LadderRuntimeTier, type LanguageModelLike, type LanguageModelMonitor, type LanguageModelSessionLike, type LeaveBundle, type LicenseCheckResult, LicenseRequiredError, type LinearConnectorOptions, type LocalAPIConfig, type LocalAPITokenConfig, type LocalAPITokenScope, type LocalAPITokenSummary, type LocalServerProbe, MARKETPLACE_PROVENANCE, type MCPPropertySchema, type MCPRequest, type MCPResource, type MCPResponse, type MCPServerConfig, type MCPTool, MEDIA_PROVIDER_CANVAS_PLUGIN_FIXTURE, type ManagedBudgetSnapshot, ManagedProvider, type ManagedProviderOptions, MarketplaceClient, type MarketplaceClientOptions, type MarketplaceEntry, type MarketplaceSort, type MathHelpers, type MentionProviderContribution, type MentionSuggestion, MiddlewareChain, type MissingDependency, type ModuleCapabilities, NOTION_CONNECTOR_ID, type NodeChangeEvent, type NodeChangeEventData, type NodeData, type NodeStoreAPI, type NodeStoreMiddleware, type NotionConnectorOptions, OllamaProvider, OpenAICompatibleProvider, type OpenAICompatibleProviderOptions, OpenAIProvider, type PendingChange, type Platform, type PlatformCapabilities, type PluginContributions, PluginError, type PluginNode, type PluginNodeChangeEvent, type PluginNodeChangeListener, type PluginPermissions, type PluginPricing, type PluginRating, PluginRegistry, type PluginRunInput, type PluginRunResult, PluginRuntimeError, type PluginRuntimeLadder, PluginSchema, type PluginStatus, PluginValidationError, type ProcessManagerEvents, type PromptApiAvailability, PromptApiProvider, type PromptApiProviderOptions, type PropertyCellProps, type PropertyEditorProps, type PropertyHandler, type PropertyHandlerContribution, type Provenance, type ProvenanceResult, type ProvenanceVerifier, type QueryFilter, RSS_CONNECTOR_ID, type RatingSummary, type RecommendOptions, type RegisteredPlugin, type ResolveMentionOptions, type RightToLeavePorts, type RssConnectorOptions, type RunActionPorts, type RunConnectorSyncPorts, type RunPluginCodeInput, SCAFFOLD_SYSTEM_GUARD, SERVICE_IPC_CHANNELS, SLACK_CONNECTOR_ID, type SandboxOptions, ScaffoldError, type ScaffoldResult, type ScaffoldSpec, type ScaffoldTemplate, type SchemaContribution, type SchemaData, type SchemaDefinition, type SchemaProperty, type SchemaRegistryAPI, type ScriptContext, ScriptError, type ScriptExecutionResult, type ScriptExecutor, ScriptGenerationError, ScriptGenerator, type ScriptGeneratorOptions, type ScriptNode, type ScriptNodeChangeEvent, type ScriptOutputType, ScriptRunner, type ScriptRunnerOptions, ScriptSandbox, ScriptSchema, type ScriptStore, ScriptTimeoutError, type ScriptToManifestInput, type ScriptTriggerType, ScriptValidationError, type SemVer, type ServiceClient, type ServiceCommunication, type ServiceDefinition, type ServiceHealthCheck, type ServiceLifecycle, type ServiceOutputEvent, type ServiceProcessConfig, type ServiceProvides, type ServiceState, type ServiceStatus, type ServiceStatusEvent, type SettingContribution, type SettingsPanelProps, ShortcutManager, type SidebarContribution, type SlackConnectorOptions, type SlashCommandContext, type SlashCommandContribution, type StatusBarContribution, type TelemetryReporter, type TestHarnessOptions, type TestNodeStore, type TestPluginHarness, type TextHelpers, type ToolCallingFidelity, type ToolbarContribution, TypedRegistry, type UsageSignal, type ValidationResult, type VerifyProvenanceInput, type ViewContribution, type ViewProps, type WebLLMEngineLike, WebLLMProvider, type WebLLMProviderOptions, type WebhookConfig, WebhookEmitter, type WebhookOutOptions, type WebhookPayload, type WidgetContribution, type WidgetContributionConfigField, type WidgetContributionProps, type WorkspaceCommand, type WrapCliConnectorOptions, type WriteMode, XNET_MARKDOWN_DIRECTIVE_SPECS, type XNetExtension, type XNetMarkdownDiffLine, type XNetMarkdownDiffLineKind, type XNetMarkdownDirective, type XNetMarkdownDirectiveSpec, type XNetMarkdownReviewDiff, type XNetPageMarkdownFrontmatter, type XNetPageMarkdownValidation, type XNetPageMarkdownValidationOptions, agentToolToExtraTool, agentToolsAsExtraTools, aggregateRatings, assertNetwork, assertPublicUrl, assertSchemaWrite, assistTurnProvenance, attachAiPlanValidation, buildAirtableConnector, buildDiscordAction, buildEmailAction, buildGithubConnector, buildLinearConnector, buildNotionConnector, buildRetryPrompt, buildRssConnector, buildScriptPrompt, buildSlackConnector, buildSlackWebhookAction, buildTelegramAction, buildWebhookOutAction, classifyAiAgentDisplayState, compareVersions, composeAssistSystemPrompt, connectorAsImporter, connectorMarketplaceEntry, contributionsAsAiTools, createAIProvider, createAIProviderRouter, createAiAgentRuntime, createAiChangeSet, createAiOperation, createAiSurfaceService, createAiValidationResult, createCanvasErpPrototypeRiskSummary, createCanvasErpPrototypeScenario, createCanvasPluginFixtureCards, createCanvasPluginFixtureManifests, createCanvasPluginPermissionPrompt, createCanvasPluginSandboxPolicy, createCanvasPreviewSandboxRequest, createCanvasRendererSandboxRequest, createExtensionContext, createExtensionStorage, createManagedProvider, createMemoryAiAgentRuntimeStorage, createPromptApiProvider, createScriptContext, createServiceClient, createTestNodeStore, createTestPluginHarness, createWebLLMProvider, createWebhookEmitter, defaultLocalServerProbes, defineAction, defineConnector, defineExtension, defineFeatureModule, deleteDay, describeCapabilities, detectConnectors, downloadPromptApiModel, emitConnectorArtifacts, evaluateCanvasPluginPermissionGate, evaluateCanvasPluginSandboxRequest, evaluateConnectorInstall, evaluateInstallConsent, executeScript, failClosedVerifier, filterByCategory, findEditorSchemaRisks, findMissingDependencies, generateScript, getCanvasErpPrototypeAuditEntriesForCard, getCanvasErpPrototypeCardsForFrame, getCanvasPluginFixture, getCommandRegistry, getPlatformCapabilities, getShortcutManager, getXNetMarkdownDirectiveSpecs, guardStore, guardedActionFetch, guardedFetch, hasUpdate, importerAdapters, installCommandHandler, installShortcutHandler, isAiRiskLevel, isAiScope, isAiTargetKind, isAllowedPluginLicense, isHostCompatible, isNetworkAllowed, isOllamaAvailable, isPaidPricing, isSchemaDefiningExtension, isSchemaReadAllowed, isSchemaWriteAllowed, isScriptNode, isServiceClientAvailable, ladderTierForTrust, leaveWithEverything, listOllamaModels, matchSchemaIri, normalizeCanvasPluginWorkspacePolicy, packageName, parseAiMutationPlan, parseFeed, parseVersion, parseXNetPageFrontmatter, pascalCase, pickBestConnector, pluginLicenseText, probeOpenAiCompatible, promptApiAvailability, quickSafetyCheck, recommendExtensions, renderEvent, renderMarkdownLineDiff, renderMarkdownReviewDiff, renderSelectionPrompt, resolveImporters, resolveInstallOrder, resolveMentionProviders, runAction, runAiPluginPipeline, runConnectorSync, runPluginCode, satisfiesRange, scaffoldPlugin, scriptToPluginManifest, searchMarketplace, serializeAiMutationPlan, shortSchemaName, shouldDispatch, sortMarketplace, stripXNetPageFrontmatter, summarizeProvenance, validateAiMutationPlan, validateCanvasPluginSandboxOutput, validateManifest, validateScript, validateScriptAST, validateXNetPageMarkdown, verifyProvenance, warnOnEditorSchemaRisks, wrapCliConnector, writeModeFor };
package/dist/index.js CHANGED
@@ -2851,6 +2851,7 @@ function defineAction(def) {
2851
2851
  }
2852
2852
 
2853
2853
  // src/actions/ssrf.ts
2854
+ import { validateExternalUrl } from "@xnetjs/core";
2854
2855
  var ActionSsrfError = class extends Error {
2855
2856
  constructor(message, url) {
2856
2857
  super(message);
@@ -2858,58 +2859,13 @@ var ActionSsrfError = class extends Error {
2858
2859
  this.name = "ActionSsrfError";
2859
2860
  }
2860
2861
  };
2861
- function parseIpv4(host) {
2862
- const parts = host.split(".");
2863
- if (parts.length !== 4) return null;
2864
- let value = 0;
2865
- for (const part of parts) {
2866
- if (!/^\d{1,3}$/.test(part)) return null;
2867
- const octet = Number(part);
2868
- if (octet > 255) return null;
2869
- value = value * 256 + octet;
2870
- }
2871
- return value >>> 0;
2872
- }
2873
- function isPrivateIpv4(host) {
2874
- const ip = parseIpv4(host);
2875
- if (ip === null) return false;
2876
- const inRange = (base, bits) => {
2877
- const baseIp = parseIpv4(base);
2878
- const mask = bits === 0 ? 0 : 4294967295 << 32 - bits >>> 0;
2879
- return (ip & mask) === (baseIp & mask);
2880
- };
2881
- return inRange("0.0.0.0", 8) || // "this" network / 0.0.0.0
2882
- inRange("10.0.0.0", 8) || // private
2883
- inRange("127.0.0.0", 8) || // loopback
2884
- inRange("169.254.0.0", 16) || // link-local + cloud metadata (169.254.169.254)
2885
- inRange("172.16.0.0", 12) || // private
2886
- inRange("192.168.0.0", 16) || // private
2887
- inRange("100.64.0.0", 10);
2888
- }
2889
- function isBlockedIpv6(host) {
2890
- const h = host.replace(/^\[|\]$/g, "").toLowerCase();
2891
- if (h === "::1" || h === "::") return true;
2892
- if (h.startsWith("fc") || h.startsWith("fd")) return true;
2893
- if (h.startsWith("::ffff:") || h.startsWith("64:ff9b::")) return true;
2894
- const firstHextet = parseInt(h.split(":")[0] || "0", 16);
2895
- if (Number.isFinite(firstHextet) && (firstHextet & 65472) === 65152) return true;
2896
- return false;
2897
- }
2898
- var BLOCKED_HOSTNAMES = /* @__PURE__ */ new Set(["localhost", "metadata.google.internal"]);
2899
2862
  function assertPublicUrl(rawUrl) {
2900
- let url;
2901
- try {
2902
- url = new URL(rawUrl);
2903
- } catch {
2904
- throw new ActionSsrfError(`outbound action URL is not a valid URL: ${rawUrl}`, rawUrl);
2905
- }
2906
- if (url.protocol !== "http:" && url.protocol !== "https:") {
2907
- throw new ActionSsrfError(`outbound action URL must be http(s): ${rawUrl}`, rawUrl);
2908
- }
2909
- const host = url.hostname.toLowerCase().replace(/\.$/, "");
2910
- const blocked = BLOCKED_HOSTNAMES.has(host) || host.endsWith(".localhost") || host.endsWith(".local") || host.endsWith(".internal") || (host.startsWith("[") ? isBlockedIpv6(host) : isPrivateIpv4(host));
2911
- if (blocked) {
2912
- throw new ActionSsrfError(`outbound action URL targets a non-public host: ${host}`, rawUrl);
2863
+ const result = validateExternalUrl(rawUrl);
2864
+ if (!result.valid) {
2865
+ throw new ActionSsrfError(
2866
+ result.error ?? `outbound action URL targets a non-public host: ${rawUrl}`,
2867
+ rawUrl
2868
+ );
2913
2869
  }
2914
2870
  }
2915
2871
 
@@ -10234,7 +10190,7 @@ var ManagedProvider = class {
10234
10190
  return createCapabilities({
10235
10191
  tools: true,
10236
10192
  structuredOutputs: true,
10237
- streaming: false,
10193
+ streaming: true,
10238
10194
  contextWindow: 2e5,
10239
10195
  local: false,
10240
10196
  privacy: "proxy",
@@ -10277,6 +10233,82 @@ var ManagedProvider = class {
10277
10233
  } : {}
10278
10234
  };
10279
10235
  }
10236
+ /**
10237
+ * Stream the managed completion over SSE (`/ai/chat/stream`). Yields a `text`
10238
+ * chunk per delta, then `usage` + `done`; emits the live budget from the terminal
10239
+ * `done` event. A `402` (pre-stream) or an `ai_budget_exceeded` error event
10240
+ * becomes an {@link AiBudgetError} (exploration 0244).
10241
+ */
10242
+ async *stream(request) {
10243
+ const reqModel = this.model ?? "openrouter/auto";
10244
+ const res = await this.fetchImpl(`${this.baseUrl}/ai/chat/stream`, {
10245
+ method: "POST",
10246
+ headers: { "content-type": "application/json", accept: "text/event-stream" },
10247
+ credentials: "include",
10248
+ body: JSON.stringify({ model: reqModel, messages: requestToMessages(request) })
10249
+ });
10250
+ if (res.status === 402) {
10251
+ const data = await res.json().catch(() => ({}));
10252
+ throw new AiBudgetError(data.spentUsd ?? 0, data.budgetUsd ?? 0);
10253
+ }
10254
+ if (!res.ok || !res.body) {
10255
+ const data = await res.json().catch(() => ({}));
10256
+ throw new AIGenerationError(
10257
+ `Managed AI stream error: ${res.status} ${data.error ?? ""}`.trim(),
10258
+ this.name
10259
+ );
10260
+ }
10261
+ const reader = res.body.getReader();
10262
+ const decoder = new TextDecoder();
10263
+ let buffer = "";
10264
+ let event = "message";
10265
+ let model = reqModel;
10266
+ const handle = (ev, payload) => {
10267
+ if (!payload) return null;
10268
+ const data = JSON.parse(payload);
10269
+ if (ev === "delta" && typeof data.text === "string") {
10270
+ return { chunk: { type: "text", text: data.text, provider: this.name, model } };
10271
+ }
10272
+ if (ev === "done") {
10273
+ model = data.model ?? model;
10274
+ this.emitBudget(data);
10275
+ return { done: true };
10276
+ }
10277
+ if (ev === "error") {
10278
+ if (data.error === "ai_budget_exceeded") {
10279
+ throw new AiBudgetError(data.spentUsd ?? 0, data.budgetUsd ?? 0);
10280
+ }
10281
+ throw new AIGenerationError(
10282
+ `Managed AI stream error: ${data.error ?? ""}`.trim(),
10283
+ this.name
10284
+ );
10285
+ }
10286
+ return null;
10287
+ };
10288
+ for (; ; ) {
10289
+ const { value, done } = await reader.read();
10290
+ if (done) break;
10291
+ buffer += decoder.decode(value, { stream: true });
10292
+ let nl;
10293
+ while ((nl = buffer.indexOf("\n")) !== -1) {
10294
+ const line = buffer.slice(0, nl).trimEnd();
10295
+ buffer = buffer.slice(nl + 1);
10296
+ if (line === "") {
10297
+ event = "message";
10298
+ continue;
10299
+ }
10300
+ if (line.startsWith("event:")) {
10301
+ event = line.slice(6).trim();
10302
+ continue;
10303
+ }
10304
+ if (line.startsWith("data:")) {
10305
+ const out = handle(event, line.slice(5).trim());
10306
+ if (out?.chunk) yield out.chunk;
10307
+ }
10308
+ }
10309
+ }
10310
+ yield { type: "done", provider: this.name, model };
10311
+ }
10280
10312
  emitBudget(data) {
10281
10313
  if (!this.onBudget) return;
10282
10314
  if (typeof data.spendThisPeriodUsd !== "number" || typeof data.budgetUsd !== "number") return;
@@ -10510,18 +10542,24 @@ var AiAgentRuntime = class {
10510
10542
  this.storage = config.storage ?? createMemoryAiAgentRuntimeStorage();
10511
10543
  this.clock = config.clock ?? (() => /* @__PURE__ */ new Date());
10512
10544
  this.mode = config.mode ?? "hybrid";
10545
+ this.assistMode = config.assistMode ?? "scaffold";
10513
10546
  this.maxEvents = config.maxEvents ?? DEFAULT_MAX_EVENTS;
10514
10547
  }
10515
10548
  snapshot = createEmptySnapshot();
10516
10549
  storage;
10517
10550
  clock;
10518
10551
  mode;
10552
+ assistMode;
10519
10553
  maxEvents;
10520
10554
  sequence = 0;
10521
10555
  loaded = false;
10522
10556
  listeners = /* @__PURE__ */ new Set();
10523
10557
  activeRuns = /* @__PURE__ */ new Map();
10524
10558
  activeJobs = /* @__PURE__ */ new Map();
10559
+ /** The active assist mode (`scaffold` by default; `draft` is opt-in only). */
10560
+ getAssistMode() {
10561
+ return this.assistMode;
10562
+ }
10525
10563
  async load() {
10526
10564
  const stored = await this.storage.load();
10527
10565
  this.snapshot = normalizeSnapshot(stored);
@@ -10578,7 +10616,10 @@ var AiAgentRuntime = class {
10578
10616
  content: "",
10579
10617
  createdAt: now,
10580
10618
  updatedAt: now,
10581
- metadata: { runId }
10619
+ // Provenance is always legible: every assistant turn is marked
10620
+ // ai-generated and carries the assist mode it was produced under, so a
10621
+ // surface can show an `ai-generated` badge (Charter §Agency).
10622
+ metadata: { runId, ...assistTurnProvenance(this.assistMode) }
10582
10623
  });
10583
10624
  this.activeRuns.set(runId, controller);
10584
10625
  this.snapshot = {
@@ -11048,6 +11089,17 @@ function createMemoryAiAgentRuntimeStorage(initial) {
11048
11089
  snapshot: () => cloneSnapshot(current)
11049
11090
  };
11050
11091
  }
11092
+ var AI_GENERATED_PROVENANCE = "ai-generated";
11093
+ var SCAFFOLD_SYSTEM_GUARD = "Work in scaffold mode: help the user think, do not think for them. Prefer an outline, options, and cited sources over finished prose, and leave the writing \u2014 and the authorship \u2014 to the user. Mark anything you author as AI-generated.";
11094
+ function composeAssistSystemPrompt(base, mode) {
11095
+ if (mode !== "scaffold") return base;
11096
+ return base ? `${base}
11097
+
11098
+ ${SCAFFOLD_SYSTEM_GUARD}` : SCAFFOLD_SYSTEM_GUARD;
11099
+ }
11100
+ function assistTurnProvenance(mode) {
11101
+ return { provenance: AI_GENERATED_PROVENANCE, assistMode: mode };
11102
+ }
11051
11103
  function renderSelectionPrompt(instruction, selection) {
11052
11104
  const lines = [
11053
11105
  instruction.trim(),
@@ -11162,6 +11214,75 @@ function writeModeFor(toolCalling) {
11162
11214
  return toolCalling === "reliable" ? "agentic" : "propose-only";
11163
11215
  }
11164
11216
 
11217
+ // src/ai/connectors/prompt-api-provider.ts
11218
+ var PromptApiProvider = class {
11219
+ name = "prompt-api";
11220
+ session;
11221
+ model;
11222
+ constructor(options) {
11223
+ this.session = options.session;
11224
+ this.model = options.model ?? "gemini-nano";
11225
+ }
11226
+ async generate(prompt) {
11227
+ return this.session.prompt(prompt);
11228
+ }
11229
+ async *stream(request) {
11230
+ const input = toPromptInput(request);
11231
+ for await (const text3 of this.session.promptStreaming(input)) {
11232
+ if (text3) yield { type: "text", text: text3, provider: this.name, model: this.model };
11233
+ }
11234
+ yield { type: "done", provider: this.name, model: this.model };
11235
+ }
11236
+ getCapabilities() {
11237
+ return {
11238
+ tools: false,
11239
+ // no tool calling in the Prompt API yet
11240
+ structuredOutputs: true,
11241
+ // via responseConstraint, not modeled here
11242
+ streaming: true,
11243
+ contextWindow: 4096,
11244
+ local: true,
11245
+ privacy: "local",
11246
+ quality: "local"
11247
+ };
11248
+ }
11249
+ };
11250
+ async function createPromptApiProvider(factory) {
11251
+ const lm = factory ?? getGlobalLanguageModel();
11252
+ if (!lm) return null;
11253
+ const availability = await lm.availability();
11254
+ if (availability === "unavailable") return null;
11255
+ const session = await lm.create();
11256
+ return new PromptApiProvider({ session });
11257
+ }
11258
+ async function promptApiAvailability(factory) {
11259
+ const lm = factory ?? getGlobalLanguageModel();
11260
+ if (!lm) return "unavailable";
11261
+ try {
11262
+ return await lm.availability();
11263
+ } catch {
11264
+ return "unavailable";
11265
+ }
11266
+ }
11267
+ async function downloadPromptApiModel(onProgress, factory) {
11268
+ const lm = factory ?? getGlobalLanguageModel();
11269
+ if (!lm) return false;
11270
+ await lm.create({
11271
+ monitor: (monitor) => monitor.addEventListener("downloadprogress", (event) => onProgress?.(event.loaded))
11272
+ });
11273
+ return true;
11274
+ }
11275
+ function getGlobalLanguageModel() {
11276
+ const candidate = globalThis.LanguageModel;
11277
+ return candidate ?? null;
11278
+ }
11279
+ function toPromptInput(request) {
11280
+ if (request.messages && request.messages.length > 0) {
11281
+ return request.messages.map((m) => `${m.role}: ${m.content}`).join("\n");
11282
+ }
11283
+ return request.prompt ?? "";
11284
+ }
11285
+
11165
11286
  // src/ai/connectors/detect.ts
11166
11287
  var CONNECTOR_META = {
11167
11288
  // Preferred when available: no key to paste, metered + budget-capped, switchable
@@ -11247,14 +11368,16 @@ async function detectConnectors(env = {}) {
11247
11368
  const probeBridge = env.probeBridge ?? defaultProbeBridge;
11248
11369
  const managedUrl = env.managedUrl ?? "";
11249
11370
  const probeManaged = env.probeManaged ?? defaultProbeManaged;
11250
- const [webgpu, promptApi, localServer, cloudKey, bridge, managed] = await Promise.all([
11371
+ const [webgpu, webllmEngine, promptApi, localServer, cloudKey, bridge, managed] = await Promise.all([
11251
11372
  resolveBool(env.hasWebGpu, defaultHasWebGpu),
11373
+ resolveBool(env.hasWebLLMEngine, () => false),
11252
11374
  resolveBool(env.hasPromptApi, defaultHasPromptApi),
11253
11375
  detectLocalServer(localServerProbes),
11254
11376
  resolveBool(env.hasCloudKey, () => false),
11255
11377
  probeBridge(bridgeUrl),
11256
11378
  probeManaged(managedUrl).catch(() => false)
11257
11379
  ]);
11380
+ const webllm = webgpu && webllmEngine;
11258
11381
  const base = [
11259
11382
  {
11260
11383
  tier: "managed",
@@ -11280,8 +11403,10 @@ async function detectConnectors(env = {}) {
11280
11403
  },
11281
11404
  {
11282
11405
  tier: "webllm",
11283
- available: webgpu,
11284
- ...webgpu ? {} : { setupHint: "WebGPU unavailable; use a Chromium browser or Safari 26+." }
11406
+ available: webllm,
11407
+ ...webllm ? {} : {
11408
+ setupHint: webgpu ? "In-browser model not enabled in this build yet." : "WebGPU unavailable; use a Chromium browser or Safari 26+."
11409
+ }
11285
11410
  },
11286
11411
  {
11287
11412
  tier: "prompt-api",
@@ -11319,8 +11444,8 @@ async function resolveBool(fn, fallback) {
11319
11444
  function defaultHasWebGpu() {
11320
11445
  return typeof navigator !== "undefined" && "gpu" in navigator;
11321
11446
  }
11322
- function defaultHasPromptApi() {
11323
- return typeof globalThis !== "undefined" && "LanguageModel" in globalThis;
11447
+ async function defaultHasPromptApi() {
11448
+ return await promptApiAvailability() === "available";
11324
11449
  }
11325
11450
 
11326
11451
  // src/ai/connectors/webllm-provider.ts
@@ -11391,58 +11516,6 @@ function toWebLLMMessages(request) {
11391
11516
  return [{ role: "user", content: request.prompt ?? "" }];
11392
11517
  }
11393
11518
 
11394
- // src/ai/connectors/prompt-api-provider.ts
11395
- var PromptApiProvider = class {
11396
- name = "prompt-api";
11397
- session;
11398
- model;
11399
- constructor(options) {
11400
- this.session = options.session;
11401
- this.model = options.model ?? "gemini-nano";
11402
- }
11403
- async generate(prompt) {
11404
- return this.session.prompt(prompt);
11405
- }
11406
- async *stream(request) {
11407
- const input = toPromptInput(request);
11408
- for await (const text3 of this.session.promptStreaming(input)) {
11409
- if (text3) yield { type: "text", text: text3, provider: this.name, model: this.model };
11410
- }
11411
- yield { type: "done", provider: this.name, model: this.model };
11412
- }
11413
- getCapabilities() {
11414
- return {
11415
- tools: false,
11416
- // no tool calling in the Prompt API yet
11417
- structuredOutputs: true,
11418
- // via responseConstraint, not modeled here
11419
- streaming: true,
11420
- contextWindow: 4096,
11421
- local: true,
11422
- privacy: "local",
11423
- quality: "local"
11424
- };
11425
- }
11426
- };
11427
- async function createPromptApiProvider(factory) {
11428
- const lm = factory ?? getGlobalLanguageModel();
11429
- if (!lm) return null;
11430
- const availability = await lm.availability();
11431
- if (availability === "unavailable") return null;
11432
- const session = await lm.create();
11433
- return new PromptApiProvider({ session });
11434
- }
11435
- function getGlobalLanguageModel() {
11436
- const candidate = globalThis.LanguageModel;
11437
- return candidate ?? null;
11438
- }
11439
- function toPromptInput(request) {
11440
- if (request.messages && request.messages.length > 0) {
11441
- return request.messages.map((m) => `${m.role}: ${m.content}`).join("\n");
11442
- }
11443
- return request.prompt ?? "";
11444
- }
11445
-
11446
11519
  // src/services/client.ts
11447
11520
  var SERVICE_IPC_CHANNELS = {
11448
11521
  START: "xnet:service:start",
@@ -11697,10 +11770,51 @@ var WebhookEmitter = class {
11697
11770
  function createWebhookEmitter(store) {
11698
11771
  return new WebhookEmitter(store);
11699
11772
  }
11773
+
11774
+ // src/services/right-to-leave.ts
11775
+ var LEAVE_README = `# Your xNet data \u2014 yours to keep
11776
+
11777
+ This archive is a complete, portable copy of your workspace.
11778
+
11779
+ - \`workspace/\` \u2014 every page, database, canvas, and node, plus a manifest.
11780
+ - \`identity.did.json\` \u2014 your portable did:key identity and recovery material.
11781
+
11782
+ To continue elsewhere: run your own hub (\`xnet-hub start\`) or any xNet-compatible
11783
+ backend, then import this archive. Your did:key works on any hub \u2014 there is no
11784
+ account to transfer and nothing held back. You don't need our permission to leave.
11785
+ `;
11786
+ function underFolder(folder, files) {
11787
+ const out = {};
11788
+ for (const [path, content] of Object.entries(files)) out[`${folder}${path}`] = content;
11789
+ return out;
11790
+ }
11791
+ async function leaveWithEverything(ports, opts) {
11792
+ const [workspace, identity] = await Promise.all([ports.exportWorkspace(), ports.exportIdentity()]);
11793
+ const files = {
11794
+ ...underFolder("workspace/", workspace),
11795
+ "identity.did.json": `${JSON.stringify(identity, null, 2)}
11796
+ `,
11797
+ "README.md": LEAVE_README
11798
+ };
11799
+ return { files, exportedAt: opts.now };
11800
+ }
11801
+ async function ran(fn) {
11802
+ if (!fn) return false;
11803
+ await fn();
11804
+ return true;
11805
+ }
11806
+ async function deleteDay(ports, opts) {
11807
+ return {
11808
+ remotePurged: await ran(ports.purgeRemoteCopies),
11809
+ localWiped: opts.keepLocal ? false : await ran(ports.destroyLocal),
11810
+ recordedLeft: await ran(ports.recordLeft)
11811
+ };
11812
+ }
11700
11813
  export {
11701
11814
  AIGenerationError,
11702
11815
  AIProviderRouter,
11703
11816
  AIRTABLE_CONNECTOR_ID,
11817
+ AI_GENERATED_PROVENANCE,
11704
11818
  AI_RISK_LEVELS,
11705
11819
  AI_SCOPES,
11706
11820
  AI_TARGET_KINDS,
@@ -11730,6 +11844,7 @@ export {
11730
11844
  EXTERNAL_ITEM_SCHEMA,
11731
11845
  FEED_ITEM_SCHEMA,
11732
11846
  GITHUB_CONNECTOR_ID,
11847
+ LEAVE_README,
11733
11848
  LINEAR_CONNECTOR_ID,
11734
11849
  LicenseRequiredError,
11735
11850
  MARKETPLACE_PROVENANCE,
@@ -11748,6 +11863,7 @@ export {
11748
11863
  PluginValidationError,
11749
11864
  PromptApiProvider,
11750
11865
  RSS_CONNECTOR_ID,
11866
+ SCAFFOLD_SYSTEM_GUARD,
11751
11867
  SERVICE_IPC_CHANNELS,
11752
11868
  SLACK_CONNECTOR_ID,
11753
11869
  ScaffoldError,
@@ -11770,6 +11886,7 @@ export {
11770
11886
  assertNetwork,
11771
11887
  assertPublicUrl,
11772
11888
  assertSchemaWrite,
11889
+ assistTurnProvenance,
11773
11890
  attachAiPlanValidation,
11774
11891
  buildAirtableConnector,
11775
11892
  buildDiscordAction,
@@ -11786,6 +11903,7 @@ export {
11786
11903
  buildWebhookOutAction,
11787
11904
  classifyAiAgentDisplayState,
11788
11905
  compareVersions,
11906
+ composeAssistSystemPrompt,
11789
11907
  connectorAsImporter,
11790
11908
  connectorMarketplaceEntry,
11791
11909
  contributionsAsAiTools,
@@ -11820,9 +11938,11 @@ export {
11820
11938
  defineConnector,
11821
11939
  defineExtension,
11822
11940
  defineFeatureModule,
11941
+ deleteDay,
11823
11942
  deriveTrustTier,
11824
11943
  describeCapabilities,
11825
11944
  detectConnectors,
11945
+ downloadPromptApiModel,
11826
11946
  emitConnectorArtifacts,
11827
11947
  evaluateCanvasPluginPermissionGate,
11828
11948
  evaluateCanvasPluginSandboxRequest,
@@ -11862,6 +11982,7 @@ export {
11862
11982
  isScriptNode,
11863
11983
  isServiceClientAvailable,
11864
11984
  ladderTierForTrust,
11985
+ leaveWithEverything,
11865
11986
  listOllamaModels,
11866
11987
  matchSchemaIri,
11867
11988
  normalizeCanvasPluginWorkspacePolicy,
@@ -11874,6 +11995,7 @@ export {
11874
11995
  pickBestConnector,
11875
11996
  pluginLicenseText,
11876
11997
  probeOpenAiCompatible,
11998
+ promptApiAvailability,
11877
11999
  quickSafetyCheck,
11878
12000
  recommendExtensions,
11879
12001
  renderEvent,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xnetjs/plugins",
3
- "version": "0.0.3",
3
+ "version": "0.1.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -30,10 +30,10 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "acorn": "^8.15.0",
33
- "@xnetjs/core": "0.0.3",
34
- "@xnetjs/abuse": "0.0.3",
33
+ "@xnetjs/abuse": "0.1.0",
34
+ "@xnetjs/core": "0.1.0",
35
35
  "@xnetjs/trust": "0.0.2",
36
- "@xnetjs/data": "0.0.3",
36
+ "@xnetjs/data": "0.1.0",
37
37
  "@xnetjs/slack-compat": "0.0.2"
38
38
  },
39
39
  "peerDependencies": {
@@ -48,7 +48,7 @@
48
48
  "tsup": "^8.0.0",
49
49
  "typescript": "^5.4.0",
50
50
  "vitest": "^4.0.0",
51
- "@xnetjs/licenses": "0.0.2"
51
+ "@xnetjs/licenses": "0.0.3"
52
52
  },
53
53
  "scripts": {
54
54
  "build": "tsup",