源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s

This commit is contained in:
agent-radar
2026-09-01 20:17:27 +08:00
commit 2ed3415fb7
8018 changed files with 1936476 additions and 0 deletions
@@ -0,0 +1,704 @@
import type { WorkspaceFileReference } from "@tutti-os/workspace-file-reference/contracts";
import type {
AgentActivityActivateSessionResult,
AgentActivityComposerOptions,
AgentActivitySendInputResult,
AgentActivitySessionSettings,
AgentActivitySnapshot,
AgentActivityTurnCancelResponse,
AgentPromptContentBlock
} from "@tutti-os/agent-activity-core";
import type {
WorkspaceUserProject,
WorkspaceUserProjectDefaultSelection,
WorkspaceUserProjectMoveInput,
WorkspaceUserProjectPathCheck,
WorkspaceUserProjectSelectionPreparation,
WorkspaceUserProjectSelectionPreparationInput,
WorkspaceUserProjectServiceSnapshot
} from "@tutti-os/workspace-user-project/contracts";
export const TUTTI_EXTERNAL_AT_PROVIDER_IDS = {
agentGeneratedFile: "agent-generated-file",
agentSession: "agent-session",
agentTarget: "agent-target",
file: "file",
workspaceApp: "workspace-app",
workspaceIssue: "workspace-issue"
} as const;
export type TuttiExternalAtProviderId =
(typeof TUTTI_EXTERNAL_AT_PROVIDER_IDS)[keyof typeof TUTTI_EXTERNAL_AT_PROVIDER_IDS];
export const tuttiExternalAtProviderIds = [
TUTTI_EXTERNAL_AT_PROVIDER_IDS.file,
TUTTI_EXTERNAL_AT_PROVIDER_IDS.workspaceIssue,
TUTTI_EXTERNAL_AT_PROVIDER_IDS.workspaceApp,
TUTTI_EXTERNAL_AT_PROVIDER_IDS.agentTarget,
TUTTI_EXTERNAL_AT_PROVIDER_IDS.agentSession,
TUTTI_EXTERNAL_AT_PROVIDER_IDS.agentGeneratedFile
] as const satisfies readonly TuttiExternalAtProviderId[];
export interface TuttiExternalAtQueryInput {
keyword: string;
maxResults?: number;
providers?: readonly TuttiExternalAtProviderId[];
}
export interface TuttiExternalAtQueryDirectoryInput {
/** Empty string addresses the provider-owned root directory. */
directoryPath: string;
maxResults?: number;
providerId: TuttiExternalAtProviderId;
}
export interface TuttiExternalAtDirectoryDescriptor {
/** Canonical provider-owned directory path used for direct-child queries. */
path: string;
/** Number of direct children when the provider can determine it. */
childCount?: number | null;
}
export interface TuttiExternalAtQueryResult {
providerId: TuttiExternalAtProviderId;
itemId: string;
label: string;
subtitle?: string;
thumbnailUrl?: string | null;
insert: TuttiExternalAtInsertResult;
directory?: TuttiExternalAtDirectoryDescriptor;
}
export interface TuttiExternalAtResolveInput {
providerId: TuttiExternalAtProviderId;
entityId: string;
scope?: Readonly<Record<string, string>>;
}
export interface TuttiExternalAtResolveResult {
label?: string;
presentation?: TuttiExternalAtMentionPresentation;
}
export interface TuttiExternalAtInvalidation {
providerIds?: readonly TuttiExternalAtProviderId[];
entityIds?: readonly string[];
revision?: number;
}
export interface TuttiExternalAtMentionPresentation {
agentProviderId?: string;
agentIconUrl?: string;
iconUrl?: string;
thumbnailUrl?: string;
subtitle?: string;
description?: string;
participant?: string;
status?: string;
statusDataStatus?: string;
statusLabel?: string;
statusPulse?: string;
userAvatarPlaceholderUrl?: string;
}
export type TuttiExternalAtInsertResult =
| {
kind: "mention";
mention: {
entityId: string;
label: string;
scope?: Record<string, string>;
presentation?: TuttiExternalAtMentionPresentation;
};
}
| {
kind: "markdown-link";
label: string;
href: string;
}
| {
kind: "text";
text: string;
};
export interface TuttiExternalFileSelectInput {
multiple?: boolean;
}
export type TuttiExternalFileSelectResult = WorkspaceFileReference[];
export interface TuttiExternalFileOpenInput {
mode?: "auto" | "preview" | "reveal";
mtimeMs?: number | null;
name?: string;
path: string;
sizeBytes?: number | null;
}
export interface TuttiExternalFileUploadInput {
purpose?: "app-asset";
name?: string;
mimeType?: string;
onProgress?: (progress: TuttiExternalFileUploadProgress) => void;
signal?: AbortSignal;
}
export interface TuttiExternalUploadedFile {
path: string;
name: string;
mimeType: string;
sizeBytes: number;
sha256: string;
}
export interface TuttiExternalFileUploadProgress {
loadedBytes: number;
ratio: number;
totalBytes: number;
}
export const tuttiExternalManagedAiModelProviderIds = [
"agnes",
"openai",
"anthropic"
] as const;
export type TuttiExternalManagedAiModelProviderId =
(typeof tuttiExternalManagedAiModelProviderIds)[number];
export interface TuttiExternalManagedAiModel {
id: string;
name?: string;
provider: TuttiExternalManagedAiModelProviderId;
}
export interface TuttiExternalPermissionRequestInput {
permission: "managed-ai-models";
nonce: string;
providers?: readonly TuttiExternalManagedAiModelProviderId[];
scopes: readonly string[];
state: string;
}
export interface TuttiExternalPermissionRequestResult {
code: string;
contextToken?: string;
expiresAt?: string;
models?: readonly TuttiExternalManagedAiModel[];
providers?: readonly TuttiExternalManagedAiModelProviderId[];
}
export interface TuttiExternalSettingsOpenInput {
provider?: TuttiExternalManagedAiModelProviderId;
tab?: "models";
}
export interface TuttiExternalBrowserOpenUrlInput {
url: string;
}
export type TuttiExternalWorkspaceFeature =
| "app-center"
| "issue-manager"
| "message-center"
| "agent-connect"
| "agent-chat"
| "agent-manage";
export const tuttiExternalWorkspaceAgentProviders = [
"claude-code",
"codex",
"cursor",
"nexight",
"hermes",
"openclaw"
] as const;
export type TuttiExternalWorkspaceAgentProvider =
(typeof tuttiExternalWorkspaceAgentProviders)[number];
export interface TuttiExternalWorkspaceOpenFeatureInput {
autoSubmit?: boolean;
draftPrompt?: string;
feature: TuttiExternalWorkspaceFeature;
provider?: TuttiExternalWorkspaceAgentProvider;
}
export interface TuttiExternalWorkspaceOpenRouteIntent {
kind: "open-route";
params?: Record<string, string>;
/**
* Origin-root path for the app launch origin. It must start with "/".
*/
route: string;
state?: Record<string, unknown>;
}
export interface TuttiExternalReferenceOpenInput {
href: string;
}
export type TuttiExternalReferenceSelection =
| {
selectionKind: "path";
reference: WorkspaceFileReference;
}
| {
selectionKind: "workspace-reference";
displayName: string;
fileCount?: number;
groupId?: string;
id: string;
source: "app";
workspaceId: string;
};
export type TuttiExternalReferenceSelectResult =
TuttiExternalReferenceSelection[];
export type TuttiExternalAgentAvailabilityStatus =
| "ready"
| "checking"
| "coming_soon"
| "not_installed"
| "auth_required"
| "unavailable";
export interface TuttiExternalAgentTarget {
agentTargetId: string;
availability: {
pendingAction?: "install" | "login" | "refresh" | null;
reason?: string | null;
status: TuttiExternalAgentAvailabilityStatus;
};
description?: string | null;
/**
* Host-resolved presentation URL. This may be a data URL for Host-local
* assets. Consumers must retain a fallback when the URL cannot be rendered.
*/
iconUrl: string;
name: string;
provider: string;
}
export interface TuttiExternalAgentTargetCatalog {
agents: TuttiExternalAgentTarget[];
capturedAtUnixMs: number | null;
error: string | null;
status: "idle" | "loading" | "ready" | "error";
}
export interface TuttiExternalAgentActivityComposerOptionsInput {
agentTargetId: string;
cwd?: string | null;
provider: string;
settings?: AgentActivitySessionSettings | null;
}
export interface TuttiExternalAgentActivityActivateSessionInput {
agentSessionId: string;
agentTargetId: string;
clientSubmitId: string;
cwd?: string | null;
initialContent: AgentPromptContentBlock[];
initialDisplayPrompt?: string | null;
/**
* Host-owned navigation request. When true, the workspace owner opens its
* Agent GUI on the activated session after activation succeeds. Missing
* preserves the existing activate-without-navigation behavior.
*/
reveal?: boolean;
settings?: AgentActivitySessionSettings;
title?: string;
visible?: boolean;
}
export interface TuttiExternalAgentActivitySendInput {
agentSessionId: string;
clientSubmitId: string;
content: AgentPromptContentBlock[];
displayPrompt?: string | null;
guidance?: boolean;
}
export interface TuttiExternalAgentActivityCancelTurnInput {
agentSessionId: string;
turnId: string;
}
/**
* Explicit composer picks a launcher persists into the canonical per-target
* composer-defaults ledger. Absent fields stay untouched; null clears a field.
*/
export interface TuttiExternalAgentActivityRememberComposerDefaultsInput {
agentTargetId: string;
defaults: {
codexSaverMode?: boolean;
rtkSaverMode?: boolean;
model?: string | null;
permissionModeId?: string | null;
reasoningEffort?: string | null;
speed?: string | null;
};
}
export type TuttiExternalAgentActivityActivateSessionResult =
AgentActivityActivateSessionResult;
export type TuttiExternalAgentActivityComposerOptions =
AgentActivityComposerOptions;
export type TuttiExternalAgentActivitySendResult = AgentActivitySendInputResult;
export type TuttiExternalAgentActivityCancelTurnResult =
AgentActivityTurnCancelResponse;
export type TuttiExternalAgentActivitySnapshot = AgentActivitySnapshot;
export interface TuttiExternalUserProjectCreateInput {
name: string;
}
export interface TuttiExternalUserProjectPathInput {
path: string;
}
export interface TuttiExternalUserProjectRememberDefaultSelectionInput {
path: string | null;
}
export const tuttiExternalLogLevels = [
"debug",
"info",
"warn",
"error"
] as const;
export type TuttiExternalLogLevel = (typeof tuttiExternalLogLevels)[number];
export interface TuttiExternalLogInput {
details?: Record<string, unknown>;
event: string;
level?: TuttiExternalLogLevel;
}
export interface TuttiExternalPdfMargin {
bottom?: string;
left?: string;
right?: string;
top?: string;
}
export type TuttiExternalPdfPageSize =
| "A4"
| "Letter"
| {
height: number;
width: number;
};
export interface TuttiExternalPdfPrintHtmlInput {
baseUrl?: string;
html: string;
margin?: TuttiExternalPdfMargin;
pageSize?: TuttiExternalPdfPageSize;
preferCSSPageSize?: boolean;
printBackground?: boolean;
title?: string;
}
export interface TuttiExternalPdfPrintHtmlResult {
bytes: Uint8Array;
}
export interface TuttiExternalBridge {
app: {
getContext(): Promise<unknown>;
subscribe(listener: (context: unknown) => void): () => void;
};
activity: {
reportActive(): Promise<void>;
};
agentActivity: {
activateSession(
input: TuttiExternalAgentActivityActivateSessionInput
): Promise<TuttiExternalAgentActivityActivateSessionResult>;
cancelTurn(
input: TuttiExternalAgentActivityCancelTurnInput
): Promise<TuttiExternalAgentActivityCancelTurnResult>;
getComposerOptions(
input: TuttiExternalAgentActivityComposerOptionsInput
): Promise<TuttiExternalAgentActivityComposerOptions>;
getSnapshot(): Promise<TuttiExternalAgentActivitySnapshot>;
listTargets(): Promise<TuttiExternalAgentTargetCatalog>;
rememberComposerDefaults(
input: TuttiExternalAgentActivityRememberComposerDefaultsInput
): Promise<void>;
sendInput(
input: TuttiExternalAgentActivitySendInput
): Promise<TuttiExternalAgentActivitySendResult>;
};
browser: {
openUrl(input: TuttiExternalBrowserOpenUrlInput): Promise<void>;
};
at: {
query(
input: TuttiExternalAtQueryInput
): Promise<TuttiExternalAtQueryResult[]>;
queryDirectory?(
input: TuttiExternalAtQueryDirectoryInput
): Promise<TuttiExternalAtQueryResult[]>;
resolve?(
input: TuttiExternalAtResolveInput
): Promise<TuttiExternalAtResolveResult | null>;
subscribe?(
listener: (event: TuttiExternalAtInvalidation) => void
): () => void;
};
files: {
select(
input?: TuttiExternalFileSelectInput
): Promise<TuttiExternalFileSelectResult>;
open(input: TuttiExternalFileOpenInput): Promise<void>;
upload(
file: Blob | File,
input?: TuttiExternalFileUploadInput
): Promise<TuttiExternalUploadedFile>;
};
permissions: {
request(
input: TuttiExternalPermissionRequestInput
): Promise<TuttiExternalPermissionRequestResult>;
};
settings: {
open(input?: TuttiExternalSettingsOpenInput): Promise<void>;
};
workspace: {
onLaunchIntent(
listener: (intent: TuttiExternalWorkspaceOpenRouteIntent) => void
): () => void;
openFeature(input: TuttiExternalWorkspaceOpenFeatureInput): Promise<void>;
};
references: {
select?(): Promise<TuttiExternalReferenceSelectResult>;
open(input: TuttiExternalReferenceOpenInput): Promise<void>;
};
pdf: {
printHtmlToPdf(
input: TuttiExternalPdfPrintHtmlInput
): Promise<TuttiExternalPdfPrintHtmlResult>;
};
userProjects: {
checkPath(
input: TuttiExternalUserProjectPathInput
): Promise<WorkspaceUserProjectPathCheck>;
create(
input: TuttiExternalUserProjectCreateInput
): Promise<WorkspaceUserProject>;
getDefaultSelection(): Promise<WorkspaceUserProjectDefaultSelection | null>;
getSnapshot(): Promise<WorkspaceUserProjectServiceSnapshot>;
list(): Promise<{ projects: WorkspaceUserProject[] }>;
move(input: WorkspaceUserProjectMoveInput): Promise<void>;
remove(input: TuttiExternalUserProjectPathInput): Promise<void>;
prepareSelection(
input: WorkspaceUserProjectSelectionPreparationInput
): Promise<WorkspaceUserProjectSelectionPreparation>;
refresh(): Promise<WorkspaceUserProjectServiceSnapshot>;
rememberDefaultSelection(
input: TuttiExternalUserProjectRememberDefaultSelectionInput
): Promise<void>;
selectDirectory(): Promise<{ path: string } | null>;
/**
* Subscribes to user-project snapshots. Implementations replay the latest
* known snapshot after registration, then emit future snapshots.
*/
subscribe(
listener: (snapshot: WorkspaceUserProjectServiceSnapshot) => void
): () => void;
use(
input: TuttiExternalUserProjectPathInput
): Promise<WorkspaceUserProject>;
};
logs: {
write(input: TuttiExternalLogInput): void;
};
}
export type TuttiExternalRendererRequest =
| {
appId: string;
input: TuttiExternalAgentActivityActivateSessionInput;
operation: "agentActivity.activateSession";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalAgentActivityCancelTurnInput;
operation: "agentActivity.cancelTurn";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalAgentActivityComposerOptionsInput;
operation: "agentActivity.getComposerOptions";
requestId: string;
workspaceId: string;
}
| {
appId: string;
operation: "agentActivity.getSnapshot";
requestId: string;
workspaceId: string;
}
| {
appId: string;
operation: "agentActivity.listTargets";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalAgentActivityRememberComposerDefaultsInput;
operation: "agentActivity.rememberComposerDefaults";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalAgentActivitySendInput;
operation: "agentActivity.sendInput";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalAtResolveInput;
operation: "at.resolve";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalAtQueryInput;
operation: "at.query";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalAtQueryDirectoryInput;
operation: "at.queryDirectory";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalFileSelectInput;
operation: "files.select";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalFileOpenInput;
operation: "files.open";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalSettingsOpenInput;
operation: "settings.open";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalReferenceOpenInput;
operation: "references.open";
requestId: string;
workspaceId: string;
}
| {
appId: string;
operation: "references.select";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalUserProjectPathInput;
operation: "userProjects.checkPath";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalUserProjectCreateInput;
operation: "userProjects.create";
requestId: string;
workspaceId: string;
}
| {
appId: string;
operation: "userProjects.getDefaultSelection";
requestId: string;
workspaceId: string;
}
| {
appId: string;
operation: "userProjects.getSnapshot";
requestId: string;
workspaceId: string;
}
| {
appId: string;
operation: "userProjects.list";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: WorkspaceUserProjectMoveInput;
operation: "userProjects.move";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalUserProjectPathInput;
operation: "userProjects.remove";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: WorkspaceUserProjectSelectionPreparationInput;
operation: "userProjects.prepareSelection";
requestId: string;
workspaceId: string;
}
| {
appId: string;
operation: "userProjects.refresh";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalUserProjectRememberDefaultSelectionInput;
operation: "userProjects.rememberDefaultSelection";
requestId: string;
workspaceId: string;
}
| {
appId: string;
operation: "userProjects.selectDirectory";
requestId: string;
workspaceId: string;
}
| {
appId: string;
input: TuttiExternalUserProjectPathInput;
operation: "userProjects.use";
requestId: string;
workspaceId: string;
};
@@ -0,0 +1,779 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
normalizeTuttiExternalAtQueryInput,
normalizeTuttiExternalAtQueryDirectoryInput,
normalizeTuttiExternalAtResolveInput,
normalizeTuttiExternalAtInvalidation,
normalizeTuttiExternalAgentActivityActivateSessionInput,
normalizeTuttiExternalAgentActivityCancelTurnInput,
normalizeTuttiExternalAgentActivityRememberComposerDefaultsInput,
normalizeTuttiExternalAgentActivityComposerOptionsInput,
normalizeTuttiExternalAgentActivitySendInput,
normalizeTuttiExternalBrowserOpenUrlInput,
normalizeTuttiExternalFileOpenInput,
normalizeTuttiExternalFileSelectInput,
normalizeTuttiExternalFileUploadInput,
normalizeTuttiExternalLogInput,
normalizeTuttiExternalPdfPrintHtmlInput,
normalizeTuttiExternalPermissionRequestInput,
normalizeTuttiExternalReferenceOpenInput,
normalizeTuttiExternalSettingsOpenInput,
normalizeTuttiExternalUserProjectCreateInput,
normalizeTuttiExternalUserProjectMoveInput,
normalizeTuttiExternalUserProjectPathInput,
normalizeTuttiExternalUserProjectRememberDefaultSelectionInput,
normalizeTuttiExternalUserProjectSelectionPreparationInput,
normalizeTuttiExternalWorkspaceOpenFeatureInput,
tuttiExternalAtDefaultMaxResults,
tuttiExternalAtMaxResultsLimit
} from "./index.ts";
test("normalizes at query defaults", () => {
assert.deepEqual(normalizeTuttiExternalAtQueryInput({ keyword: "readme" }), {
keyword: "readme",
maxResults: tuttiExternalAtDefaultMaxResults,
providers: undefined
});
});
test("caps at query max results and deduplicates providers", () => {
assert.deepEqual(
normalizeTuttiExternalAtQueryInput({
keyword: "",
maxResults: tuttiExternalAtMaxResultsLimit + 10,
providers: ["file", "file", "agent-session"]
}),
{
keyword: "",
maxResults: tuttiExternalAtMaxResultsLimit,
providers: ["file", "agent-session"]
}
);
});
test("normalizes external at directory queries including the provider root", () => {
assert.deepEqual(
normalizeTuttiExternalAtQueryDirectoryInput({
directoryPath: " ",
maxResults: tuttiExternalAtMaxResultsLimit + 10,
providerId: "file"
}),
{
directoryPath: "",
maxResults: tuttiExternalAtMaxResultsLimit,
providerId: "file"
}
);
assert.throws(
() =>
normalizeTuttiExternalAtQueryDirectoryInput({
directoryPath: "",
providerId: "unknown"
}),
/providerId is unsupported/
);
});
test("rejects unsupported at providers", () => {
assert.throws(
() =>
normalizeTuttiExternalAtQueryInput({
keyword: "readme",
providers: ["file", "not-supported"]
}),
/unsupported provider/
);
});
test("normalizes exact at resolve identity and invalidation", () => {
assert.deepEqual(
normalizeTuttiExternalAtResolveInput({
providerId: "workspace-app",
entityId: " canvas ",
scope: { workspaceId: "workspace-1" }
}),
{
providerId: "workspace-app",
entityId: "canvas",
scope: { workspaceId: "workspace-1" }
}
);
assert.deepEqual(
normalizeTuttiExternalAtInvalidation({
providerIds: ["workspace-app", "workspace-app"],
entityIds: [" canvas ", "canvas"],
revision: 2
}),
{
providerIds: ["workspace-app"],
entityIds: ["canvas"],
revision: 2
}
);
});
test("rejects malformed at resolve identity and invalidation", () => {
assert.throws(
() =>
normalizeTuttiExternalAtResolveInput({
providerId: "unknown",
entityId: "canvas"
}),
/providerId is unsupported/
);
assert.throws(
() =>
normalizeTuttiExternalAtResolveInput({
providerId: "workspace-app",
entityId: "canvas",
scope: { workspaceId: 1 }
}),
/scope must contain string values/
);
assert.throws(
() => normalizeTuttiExternalAtInvalidation({ revision: Number.NaN }),
/revision must be finite/
);
});
test("normalizes agent activity session inputs without dropping prompt assets", () => {
assert.deepEqual(
normalizeTuttiExternalAgentActivityActivateSessionInput({
agentSessionId: " session-1 ",
agentTargetId: " codex ",
clientSubmitId: " batch-1 ",
cwd: " /workspace/project ",
initialContent: [
{ type: "text", text: "Run the provider smoke test." },
{
type: "file",
name: "fixture.txt",
path: "fixtures/fixture.txt",
sizeBytes: 42
}
],
initialDisplayPrompt: " provider smoke test ",
reveal: true,
settings: {
browserUse: false,
model: " test-model ",
planMode: null
},
title: " Provider Core Lab ",
visible: true
}),
{
agentSessionId: "session-1",
agentTargetId: "codex",
clientSubmitId: "batch-1",
cwd: "/workspace/project",
initialContent: [
{ type: "text", text: "Run the provider smoke test." },
{
type: "file",
name: "fixture.txt",
path: "fixtures/fixture.txt",
sizeBytes: 42
}
],
initialDisplayPrompt: "provider smoke test",
reveal: true,
settings: {
browserUse: false,
model: "test-model",
planMode: null
},
title: "Provider Core Lab",
visible: true
}
);
assert.equal(
"reveal" in
normalizeTuttiExternalAgentActivityActivateSessionInput({
agentSessionId: "session-1",
agentTargetId: "codex",
clientSubmitId: "batch-1",
initialContent: [{ type: "text", text: "test" }]
}),
false
);
assert.deepEqual(
normalizeTuttiExternalAgentActivitySendInput({
agentSessionId: " session-1 ",
clientSubmitId: " turn-2 ",
content: [{ type: "image", data: "base64", mimeType: "image/png" }],
displayPrompt: " image assertion ",
guidance: false
}),
{
agentSessionId: "session-1",
clientSubmitId: "turn-2",
content: [{ type: "image", data: "base64", mimeType: "image/png" }],
displayPrompt: "image assertion",
guidance: false
}
);
});
test("normalizes remember-composer-defaults input", () => {
assert.deepEqual(
normalizeTuttiExternalAgentActivityRememberComposerDefaultsInput({
agentTargetId: " local:codex ",
defaults: {
codexSaverMode: false,
model: " gpt-5.6-sol ",
permissionModeId: null,
reasoningEffort: " ",
speed: undefined
}
}),
{
agentTargetId: "local:codex",
defaults: {
codexSaverMode: false,
model: "gpt-5.6-sol",
permissionModeId: null,
reasoningEffort: null
}
}
);
assert.throws(
() =>
normalizeTuttiExternalAgentActivityRememberComposerDefaultsInput({
agentTargetId: "local:codex",
defaults: { model: 5 }
}),
/model must be a string or null/
);
assert.throws(
() =>
normalizeTuttiExternalAgentActivityRememberComposerDefaultsInput({
agentTargetId: "local:codex"
}),
/defaults must be an object/
);
});
test("normalizes agent activity target inputs", () => {
assert.deepEqual(
normalizeTuttiExternalAgentActivityComposerOptionsInput({
agentTargetId: " codex ",
cwd: null,
provider: " codex ",
settings: null
}),
{
agentTargetId: "codex",
cwd: null,
provider: "codex"
}
);
assert.deepEqual(
normalizeTuttiExternalAgentActivityCancelTurnInput({
agentSessionId: " session-1 ",
turnId: " turn-1 "
}),
{ agentSessionId: "session-1", turnId: "turn-1" }
);
});
test("rejects malformed agent activity inputs", () => {
assert.throws(
() =>
normalizeTuttiExternalAgentActivityActivateSessionInput({
agentSessionId: "session-1",
agentTargetId: "codex",
clientSubmitId: "batch-1",
initialContent: [],
visible: true
}),
/initialContent must be a non-empty array/
);
assert.throws(
() =>
normalizeTuttiExternalAgentActivitySendInput({
agentSessionId: "session-1",
clientSubmitId: "turn-2",
content: [{ type: "file", sizeBytes: -1 }]
}),
/sizeBytes must be a non-negative number/
);
assert.throws(
() =>
normalizeTuttiExternalAgentActivityActivateSessionInput({
agentSessionId: "session-1",
agentTargetId: "codex",
clientSubmitId: "batch-1",
initialContent: [{ type: "text", text: "test" }],
visible: "yes"
}),
/visible must be a boolean/
);
assert.throws(
() =>
normalizeTuttiExternalAgentActivityActivateSessionInput({
agentSessionId: "session-1",
agentTargetId: "codex",
clientSubmitId: "batch-1",
initialContent: [{ type: "text", text: "test" }],
reveal: "yes"
}),
/reveal must be a boolean/
);
});
test("normalizes browser open URL input", () => {
assert.deepEqual(
normalizeTuttiExternalBrowserOpenUrlInput({
url: " https://example.com/design "
}),
{
url: "https://example.com/design"
}
);
});
test("rejects invalid browser open URL input", () => {
assert.throws(
() => normalizeTuttiExternalBrowserOpenUrlInput({ url: "" }),
/browser\.openUrl url is required/
);
assert.throws(
() =>
normalizeTuttiExternalBrowserOpenUrlInput({ url: "file:///tmp/a.html" }),
/browser\.openUrl protocol is unsupported/
);
});
test("normalizes file select input", () => {
assert.deepEqual(normalizeTuttiExternalFileSelectInput(undefined), {});
assert.deepEqual(normalizeTuttiExternalFileSelectInput({ multiple: true }), {
multiple: true
});
assert.deepEqual(normalizeTuttiExternalFileSelectInput({ multiple: false }), {
multiple: false
});
});
test("normalizes file open input", () => {
assert.deepEqual(
normalizeTuttiExternalFileOpenInput({
mode: "auto",
mtimeMs: 123,
name: " Report.md ",
path: " docs/report.md ",
sizeBytes: null
}),
{
mode: "auto",
mtimeMs: 123,
name: "Report.md",
path: "docs/report.md",
sizeBytes: null
}
);
});
test("rejects invalid file open input", () => {
assert.throws(
() => normalizeTuttiExternalFileOpenInput({ path: "" }),
/path is required/
);
assert.throws(
() => normalizeTuttiExternalFileOpenInput({ path: "README.md", mode: "x" }),
/mode is unsupported/
);
});
test("normalizes file upload input defaults", () => {
assert.deepEqual(normalizeTuttiExternalFileUploadInput(undefined), {
purpose: "app-asset"
});
});
test("normalizes file upload input strings", () => {
const controller = new AbortController();
const onProgress = () => undefined;
assert.deepEqual(
normalizeTuttiExternalFileUploadInput({
purpose: "app-asset",
name: " Image.PNG ",
mimeType: " image/png ",
onProgress,
signal: controller.signal
}),
{
purpose: "app-asset",
name: "Image.PNG",
mimeType: "image/png",
onProgress,
signal: controller.signal
}
);
});
test("rejects invalid file upload input", () => {
assert.throws(
() => normalizeTuttiExternalFileUploadInput("bad"),
/input must be an object/
);
assert.throws(
() => normalizeTuttiExternalFileUploadInput({ purpose: "avatar" }),
/purpose is unsupported/
);
assert.throws(
() => normalizeTuttiExternalFileUploadInput({ name: 1 }),
/name must be a string/
);
assert.throws(
() => normalizeTuttiExternalFileUploadInput({ mimeType: 1 }),
/mimeType must be a string/
);
assert.throws(
() => normalizeTuttiExternalFileUploadInput({ onProgress: true }),
/onProgress must be a function/
);
assert.throws(
() => normalizeTuttiExternalFileUploadInput({ signal: {} }),
/signal must be an AbortSignal/
);
});
test("normalizes managed AI model permission requests", () => {
assert.deepEqual(
normalizeTuttiExternalPermissionRequestInput({
nonce: " nonce-1 ",
permission: "managed-ai-models",
providers: ["openai", "openai", "anthropic"],
scopes: [" model:invoke ", "model:invoke"],
state: " state-1 "
}),
{
nonce: "nonce-1",
permission: "managed-ai-models",
providers: ["openai", "anthropic"],
scopes: ["model:invoke"],
state: "state-1"
}
);
});
test("rejects invalid managed AI model permission requests", () => {
assert.throws(
() =>
normalizeTuttiExternalPermissionRequestInput({
nonce: "nonce-1",
permission: "managed-credentials",
scopes: ["model:invoke"],
state: "state-1"
}),
/permission is unsupported/
);
assert.throws(
() =>
normalizeTuttiExternalPermissionRequestInput({
nonce: "nonce-1",
permission: "managed-ai-models",
scopes: [],
state: "state-1"
}),
/scopes must not be empty/
);
assert.throws(
() =>
normalizeTuttiExternalPermissionRequestInput({
nonce: "nonce-1",
permission: "managed-ai-models",
providers: ["not-supported"],
scopes: ["model:invoke"],
state: "state-1"
}),
/provider is unsupported/
);
});
test("normalizes settings open input", () => {
assert.deepEqual(normalizeTuttiExternalSettingsOpenInput(undefined), {});
assert.deepEqual(
normalizeTuttiExternalSettingsOpenInput({
provider: "openai",
tab: "models"
}),
{
provider: "openai",
tab: "models"
}
);
});
test("rejects invalid settings open input", () => {
assert.throws(
() => normalizeTuttiExternalSettingsOpenInput({ tab: "credentials" }),
/tab is unsupported/
);
assert.throws(
() => normalizeTuttiExternalSettingsOpenInput({ provider: "codex" }),
/provider is unsupported/
);
});
test("normalizes PDF print HTML input", () => {
assert.deepEqual(
normalizeTuttiExternalPdfPrintHtmlInput({
baseUrl: " http://127.0.0.1:8790/project/ ",
html: " <h1>Doc</h1> ",
margin: {
bottom: "14mm",
left: " 10mm ",
right: "10mm",
top: "12mm"
},
pageSize: { width: 13.333333, height: 7.5 },
preferCSSPageSize: true,
printBackground: false,
title: " Report "
}),
{
baseUrl: "http://127.0.0.1:8790/project/",
html: "<h1>Doc</h1>",
margin: {
bottom: "14mm",
left: "10mm",
right: "10mm",
top: "12mm"
},
pageSize: { width: 13.333333, height: 7.5 },
preferCSSPageSize: true,
printBackground: false,
title: "Report"
}
);
});
test("rejects invalid PDF print HTML input", () => {
assert.throws(
() => normalizeTuttiExternalPdfPrintHtmlInput({ html: "" }),
/html is required/
);
assert.throws(
() =>
normalizeTuttiExternalPdfPrintHtmlInput({
baseUrl: "file:///tmp/doc.html",
html: "<h1>Doc</h1>"
}),
/baseUrl protocol is unsupported/
);
assert.throws(
() =>
normalizeTuttiExternalPdfPrintHtmlInput({
html: "<h1>Doc</h1>",
margin: { top: "12pt" }
}),
/margin top unit is unsupported/
);
assert.throws(
() =>
normalizeTuttiExternalPdfPrintHtmlInput({
html: "<h1>Doc</h1>",
pageSize: { width: 13.333333, height: 0 }
}),
/pageSize height must be a positive number/
);
});
test("normalizes workspace feature open input", () => {
assert.deepEqual(
normalizeTuttiExternalWorkspaceOpenFeatureInput({
feature: "agent-manage",
provider: " codex "
}),
{
feature: "agent-manage",
provider: "codex"
}
);
});
test("rejects invalid workspace feature open input", () => {
assert.throws(
() => normalizeTuttiExternalWorkspaceOpenFeatureInput(null),
/input must be an object/
);
assert.throws(
() =>
normalizeTuttiExternalWorkspaceOpenFeatureInput({
feature: "not-supported"
}),
/feature is unsupported/
);
assert.throws(
() =>
normalizeTuttiExternalWorkspaceOpenFeatureInput({
feature: "agent-chat",
provider: "unknown-agent"
}),
/provider is unsupported/
);
});
test("normalizes reference open input", () => {
assert.deepEqual(
normalizeTuttiExternalReferenceOpenInput({
href: "mention://workspace-app/app-1?workspaceId=workspace-1"
}),
{
href: "mention://workspace-app/app-1?workspaceId=workspace-1"
}
);
});
test("rejects invalid reference open input", () => {
assert.throws(
() =>
normalizeTuttiExternalReferenceOpenInput({ href: "https://example.com" }),
/mention URL/
);
});
test("normalizes user project inputs", () => {
assert.deepEqual(
normalizeTuttiExternalUserProjectCreateInput({ name: " Project " }),
{
name: "Project"
}
);
assert.deepEqual(
normalizeTuttiExternalUserProjectPathInput({ path: " /repo " }, "use"),
{
path: "/repo"
}
);
assert.deepEqual(
normalizeTuttiExternalUserProjectPathInput({ path: " /repo " }, "remove"),
{
path: "/repo"
}
);
assert.deepEqual(
normalizeTuttiExternalUserProjectMoveInput({
beforeProjectId: " before ",
projectId: " project "
}),
{ beforeProjectId: "before", projectId: "project" }
);
assert.deepEqual(
normalizeTuttiExternalUserProjectMoveInput({
beforeProjectId: null,
projectId: "project"
}),
{ beforeProjectId: null, projectId: "project" }
);
assert.deepEqual(
normalizeTuttiExternalUserProjectRememberDefaultSelectionInput({
path: " "
}),
{
path: null
}
);
assert.deepEqual(
normalizeTuttiExternalUserProjectSelectionPreparationInput({
projectLocked: true,
selectedPath: " /repo "
}),
{
projectLocked: true,
selectedPath: "/repo"
}
);
});
test("rejects invalid user project inputs", () => {
assert.throws(
() => normalizeTuttiExternalUserProjectCreateInput({ name: "" }),
/name is required/
);
assert.throws(
() => normalizeTuttiExternalUserProjectPathInput({ path: "" }, "checkPath"),
/path is required/
);
assert.throws(
() => normalizeTuttiExternalUserProjectMoveInput({ projectId: "project" }),
/beforeProjectId is required/
);
assert.throws(
() =>
normalizeTuttiExternalUserProjectMoveInput({
beforeProjectId: "",
projectId: "project"
}),
/beforeProjectId is required/
);
});
test("normalizes external log input defaults", () => {
assert.deepEqual(normalizeTuttiExternalLogInput({ event: "page.loaded" }), {
event: "page.loaded"
});
});
test("normalizes external log input with level and details", () => {
assert.deepEqual(
normalizeTuttiExternalLogInput({
event: " request.failed ",
level: "warn",
details: {
route: "/home",
retryCount: 2
}
}),
{
event: "request.failed",
level: "warn",
details: {
route: "/home",
retryCount: 2
}
}
);
});
test("truncates long external log detail strings", () => {
const longValue = "x".repeat(8_500);
const normalized = normalizeTuttiExternalLogInput({
event: "payload.large",
details: {
message: longValue
}
});
assert.equal(normalized.details?.message, `${"x".repeat(8_000)}...`);
});
test("rejects invalid external log input", () => {
assert.throws(
() => normalizeTuttiExternalLogInput(null),
/input must be an object/
);
assert.throws(
() => normalizeTuttiExternalLogInput({ event: "" }),
/event is required/
);
assert.throws(
() =>
normalizeTuttiExternalLogInput({
event: "page.loaded",
level: "trace"
}),
/level is unsupported/
);
assert.throws(
() =>
normalizeTuttiExternalLogInput({
event: "page.loaded",
details: "invalid"
}),
/details must be an object/
);
});
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,3 @@
export type * from "./contracts/index.ts";
export * from "./core/index.ts";
export * from "./rich-text/index.ts";
@@ -0,0 +1,494 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
appendTuttiExternalReferenceSelections,
createTuttiExternalAtRichTextTriggerProvider,
createTuttiExternalAtRichTextTriggerProviders,
createTuttiExternalRichTextMentionService,
queryTuttiExternalAtRichTextTriggerItems
} from "./index.ts";
import type {
TuttiExternalAtQueryInput,
TuttiExternalAtQueryResult
} from "../contracts/index.ts";
test("appends selected paths and application reference bundles", () => {
assert.equal(
appendTuttiExternalReferenceSelections("Create a summary", [
{
selectionKind: "path",
reference: {
displayName: "notes.md",
kind: "file",
path: "/workspace/notes.md"
}
},
{
selectionKind: "path",
reference: {
displayName: "Sources",
kind: "folder",
path: "/workspace/sources"
}
},
{
selectionKind: "workspace-reference",
displayName: "Canvas outputs",
fileCount: 3,
groupId: "outputs",
id: "ai-canvas",
source: "app",
workspaceId: "workspace-1"
}
]),
"Create a summary [notes.md](/workspace/notes.md) [Sources](/workspace/sources/) [@Canvas outputs](mention://workspace-reference/ai-canvas?count=3&groupId=outputs&source=app&workspaceId=workspace-1)"
);
});
test("deduplicates existing selected paths and application reference bundles", () => {
const content =
"Use [notes.md](/workspace/notes.md) [@Canvas outputs](mention://workspace-reference/ai-canvas?count=2&groupId=outputs&source=app&workspaceId=workspace-1)";
assert.equal(
appendTuttiExternalReferenceSelections(content, [
{
selectionKind: "path",
reference: {
displayName: "notes.md",
kind: "file",
path: "/workspace/notes.md"
}
},
{
selectionKind: "workspace-reference",
displayName: "Canvas outputs",
fileCount: 3,
groupId: "outputs",
id: "ai-canvas",
source: "app",
workspaceId: "workspace-1"
}
]),
content
);
});
test("creates one rich text provider per requested external at provider", () => {
const providers = createTuttiExternalAtRichTextTriggerProviders({
bridge: null,
providerIds: ["workspace-app", "agent-target", "agent-session"]
});
assert.deepEqual(
providers.map((provider) => provider.id),
["workspace-app", "agent-target", "agent-session"]
);
assert.deepEqual(
providers.map((provider) => provider.trigger),
["@", "@", "@"]
);
});
test("queries the external bridge with the provider filter", async () => {
const calls: TuttiExternalAtQueryInput[] = [];
const provider = createTuttiExternalAtRichTextTriggerProvider({
providerId: "workspace-app",
bridge: {
at: {
query(input) {
calls.push(input);
return [
createQueryResult("workspace-app", "apps", "Apps"),
createQueryResult("agent-session", "session", "Session")
];
}
}
}
});
const results = await provider.query({
keyword: "app",
maxResults: 5,
context: {},
trigger: "@"
});
assert.deepEqual(calls, [
{
keyword: "app",
maxResults: 5,
providers: ["workspace-app"]
}
]);
assert.deepEqual(
results.map((item) => item.providerId),
["workspace-app"]
);
});
test("file provider exposes external directory browsing when the host supports it", async () => {
const calls: unknown[] = [];
const directory = createQueryResult("file", "/workspace/docs", "docs", {
directory: { childCount: 2, path: "/workspace/docs" },
insert: {
href: "/workspace/docs/",
kind: "markdown-link",
label: "docs"
}
});
const provider = createTuttiExternalAtRichTextTriggerProvider({
providerId: "file",
bridge: {
at: {
query: () => [],
queryDirectory(input) {
calls.push(input);
return [directory];
}
}
}
});
assert.deepEqual(provider.getItemDirectory?.(directory), directory.directory);
assert.deepEqual(
await provider.queryDirectory?.({
context: {},
directoryPath: "/workspace",
keyword: "",
maxResults: 12,
trigger: "@"
}),
[directory]
);
assert.deepEqual(calls, [
{
directoryPath: "/workspace",
maxResults: 12,
providerId: "file"
}
]);
});
test("file provider keeps directory browsing absent on an older bridge", () => {
const provider = createTuttiExternalAtRichTextTriggerProvider({
providerId: "file",
bridge: { at: { query: () => [] } }
});
assert.equal(provider.queryDirectory, undefined);
assert.equal(provider.getItemDirectory, undefined);
});
test("defaults external at rich text providers to include agent targets", () => {
const providers = createTuttiExternalAtRichTextTriggerProviders({
bridge: null
});
assert.ok(providers.some((provider) => provider.id === "agent-target"));
});
test("queries multiple external at providers with one bridge call", async () => {
const calls: TuttiExternalAtQueryInput[] = [];
const results = await queryTuttiExternalAtRichTextTriggerItems({
keyword: "a",
maxResults: 10,
providerIds: ["workspace-app", "agent-session"],
bridge: {
at: {
query(input) {
calls.push(input);
return [
createQueryResult("workspace-app", "apps", "Apps"),
createQueryResult("agent-session", "session", "Session"),
createQueryResult("file", "README.md", "README.md")
];
}
}
}
});
assert.deepEqual(calls, [
{
keyword: "a",
maxResults: 10,
providers: ["workspace-app", "agent-session"]
}
]);
assert.deepEqual(
results.map((item) => item.providerId),
["workspace-app", "agent-session"]
);
});
test("preserves an explicit empty external at provider filter", async () => {
const calls: TuttiExternalAtQueryInput[] = [];
const results = await queryTuttiExternalAtRichTextTriggerItems({
keyword: "a",
providerIds: [],
bridge: {
at: {
query(input) {
calls.push(input);
return [createQueryResult("workspace-app", "apps", "Apps")];
}
}
}
});
assert.deepEqual(calls, [
{
keyword: "a",
providers: []
}
]);
assert.deepEqual(results, []);
assert.deepEqual(
createTuttiExternalAtRichTextTriggerProviders({
bridge: null,
providerIds: []
}),
[]
);
});
test("maps query results to the rich text trigger provider shape", () => {
const provider = createTuttiExternalAtRichTextTriggerProvider({
providerId: "agent-session",
bridge: null
});
const item = createQueryResult("agent-session", "run-1", "Run 1", {
subtitle: "created",
thumbnailUrl: "https://example.test/run.png"
});
assert.equal(provider.getItemKey(item), "run-1");
assert.equal(provider.getItemLabel(item), "Run 1");
assert.equal(provider.getItemSubtitle?.(item), "created");
assert.equal(provider.getItemIconUrl?.(item), "https://example.test/run.png");
assert.deepEqual(provider.toInsertResult(item), item.insert);
});
test("uses mention presentation icons when thumbnailUrl is absent", () => {
const provider = createTuttiExternalAtRichTextTriggerProvider({
providerId: "agent-session",
bridge: null
});
const item = createQueryResult("agent-session", "run-1", "Run 1", {
insert: {
kind: "mention",
mention: {
entityId: "run-1",
label: "Run 1",
presentation: {
iconUrl: "https://example.test/icon.png"
}
}
}
});
assert.equal(
provider.getItemIconUrl?.(item),
"https://example.test/icon.png"
);
});
test("uses exact host resolve when the optional bridge capability exists", async () => {
const provider = createTuttiExternalAtRichTextTriggerProvider({
providerId: "workspace-app",
getBridge: () => ({
at: {
query: () => [],
resolve(input) {
assert.deepEqual(input, {
providerId: "workspace-app",
entityId: "canvas",
scope: { workspaceId: "workspace-1" }
});
return {
label: "Canvas",
presentation: { iconUrl: "canvas.png" }
};
}
}
})
});
assert.deepEqual(
await provider.resolveMention?.({
providerId: "workspace-app",
entityId: "canvas",
label: "Old canvas",
scope: { workspaceId: "workspace-1" }
}),
{ label: "Canvas", presentation: { iconUrl: "canvas.png" } }
);
});
test("falls back to an exact identity and scope match on old hosts", async () => {
const calls: TuttiExternalAtQueryInput[] = [];
const provider = createTuttiExternalAtRichTextTriggerProvider({
providerId: "workspace-app",
bridge: {
at: {
query(input) {
calls.push(input);
return [
createQueryResult("workspace-app", "canvas", "Wrong scope", {
insert: {
kind: "mention",
mention: {
entityId: "canvas",
label: "Wrong scope",
scope: { workspaceId: "workspace-2" }
}
}
}),
createQueryResult("workspace-app", "canvas", "Canvas", {
insert: {
kind: "mention",
mention: {
entityId: "canvas",
label: "Canvas",
scope: { workspaceId: "workspace-1" },
presentation: { iconUrl: "canvas.png" }
}
}
})
];
}
}
}
});
const resolved = await provider.resolveMention?.({
providerId: "workspace-app",
entityId: "canvas",
label: "Old canvas",
scope: { workspaceId: "workspace-1" }
});
assert.deepEqual(calls, [
{ keyword: "Old canvas", maxResults: 50, providers: ["workspace-app"] }
]);
assert.deepEqual(resolved, {
label: "Canvas",
presentation: { iconUrl: "canvas.png" }
});
});
test("old host resolution retries with an empty keyword after a label miss", async () => {
const calls: TuttiExternalAtQueryInput[] = [];
const provider = createTuttiExternalAtRichTextTriggerProvider({
providerId: "workspace-app",
bridge: {
at: {
query(input) {
calls.push(input);
return input.keyword
? []
: [
createQueryResult("workspace-app", "canvas", "Renamed", {
insert: {
kind: "mention",
mention: {
entityId: "canvas",
label: "Renamed",
scope: { workspaceId: "workspace-1" }
}
}
})
];
}
}
}
});
assert.deepEqual(
await provider.resolveMention?.({
providerId: "workspace-app",
entityId: "canvas",
label: "Old canvas",
scope: { workspaceId: "workspace-1" }
}),
{ label: "Renamed", presentation: undefined }
);
assert.deepEqual(calls, [
{ keyword: "Old canvas", maxResults: 50, providers: ["workspace-app"] },
{ keyword: "", maxResults: 50, providers: ["workspace-app"] }
]);
});
test("external service invalidates from bridge events and unsubscribes", async () => {
let listener:
| ((event: { providerIds?: readonly ["workspace-app"] }) => void)
| undefined;
let unsubscribeCalls = 0;
let icon = "first.png";
const service = createTuttiExternalRichTextMentionService({
providerIds: ["workspace-app"],
getBridge: () => ({
at: {
query: () => [],
resolve: () => ({ presentation: { iconUrl: icon } }),
subscribe(nextListener) {
listener = nextListener;
return () => {
unsubscribeCalls += 1;
};
}
}
})
});
const mention = {
providerId: "workspace-app",
entityId: "canvas",
label: "Canvas"
};
await service.resolve(mention);
icon = "second.png";
listener?.({ providerIds: ["workspace-app"] });
await service.resolve(mention);
await new Promise((resolve) => setTimeout(resolve, 0));
assert.equal(
service.getSnapshot(mention).resolved?.presentation?.iconUrl,
"second.png"
);
service.dispose();
service.dispose();
assert.equal(unsubscribeCalls, 1);
});
test("external service getBridge remains SSR-safe when unavailable", async () => {
const service = createTuttiExternalRichTextMentionService({
getBridge: () => undefined,
providerIds: ["workspace-app"]
});
assert.equal(
(
await service.resolve({
providerId: "workspace-app",
entityId: "canvas",
label: "Canvas"
})
).state,
"missing"
);
});
function createQueryResult(
providerId: TuttiExternalAtQueryResult["providerId"],
itemId: string,
label: string,
overrides: Partial<TuttiExternalAtQueryResult> = {}
): TuttiExternalAtQueryResult {
return {
providerId,
itemId,
label,
insert: {
kind: "mention",
mention: {
entityId: itemId,
label
}
},
...overrides
};
}
@@ -0,0 +1,344 @@
import {
tuttiExternalAtProviderIds,
type TuttiExternalAtInvalidation,
type TuttiExternalAtQueryDirectoryInput,
type TuttiExternalAtProviderId,
type TuttiExternalAtQueryInput,
type TuttiExternalAtQueryResult,
type TuttiExternalReferenceSelection,
type TuttiExternalAtResolveInput,
type TuttiExternalAtResolveResult
} from "../contracts/index.ts";
import type {
RichTextMentionIdentity,
RichTextTriggerInsertResult,
RichTextTriggerProvider
} from "@tutti-os/ui-rich-text/types";
import {
appendRichTextLinksToContent,
createRichTextMentionMarkdown,
extractRichTextMentionsFromContent,
normalizeRichTextContent
} from "@tutti-os/ui-rich-text/core";
import {
createRichTextMentionService,
canonicalizeRichTextMentionScope,
type RichTextMentionService
} from "@tutti-os/ui-rich-text/service";
export interface TuttiExternalAtRichTextBridge {
at?: {
query(
input: TuttiExternalAtQueryInput
):
| Promise<readonly TuttiExternalAtQueryResult[]>
| readonly TuttiExternalAtQueryResult[];
queryDirectory?(
input: TuttiExternalAtQueryDirectoryInput
):
| Promise<readonly TuttiExternalAtQueryResult[]>
| readonly TuttiExternalAtQueryResult[];
resolve?(
input: TuttiExternalAtResolveInput
):
| Promise<TuttiExternalAtResolveResult | null>
| TuttiExternalAtResolveResult
| null;
subscribe?(
listener: (event: TuttiExternalAtInvalidation) => void
): () => void;
};
}
export interface CreateTuttiExternalAtRichTextTriggerProviderInput {
bridge?: TuttiExternalAtRichTextBridge | null;
getBridge?: () => TuttiExternalAtRichTextBridge | null | undefined;
providerId: TuttiExternalAtProviderId;
maxResults?: number;
}
export interface CreateTuttiExternalAtRichTextTriggerProvidersInput {
bridge?: TuttiExternalAtRichTextBridge | null;
getBridge?: () => TuttiExternalAtRichTextBridge | null | undefined;
providerIds?: readonly TuttiExternalAtProviderId[];
maxResults?: number;
}
export interface QueryTuttiExternalAtRichTextTriggerItemsInput {
bridge?: TuttiExternalAtRichTextBridge | null;
getBridge?: () => TuttiExternalAtRichTextBridge | null | undefined;
keyword: string;
providerIds?: readonly TuttiExternalAtProviderId[];
maxResults?: number;
}
export interface CreateTuttiExternalRichTextMentionServiceInput {
getBridge: () => TuttiExternalAtRichTextBridge | null | undefined;
providerIds?: readonly TuttiExternalAtProviderId[];
appLocalProviders?: readonly RichTextTriggerProvider[];
maxResults?: number;
}
function workspaceReferenceIdentityKey(input: {
entityId: string;
providerId: string;
scope?: Readonly<Record<string, string>>;
}): string | null {
if (input.providerId !== "workspace-reference") {
return null;
}
const entityId = input.entityId.trim();
const source = input.scope?.source?.trim() ?? "";
const workspaceId = input.scope?.workspaceId?.trim() ?? "";
if (!entityId || source !== "app" || !workspaceId) {
return null;
}
return JSON.stringify([
entityId,
source,
workspaceId,
input.scope?.groupId?.trim() ?? ""
]);
}
/**
* Appends Host-selected paths and lazy workspace-reference handles to the
* serialized rich-text prompt. Selection order is stable within each kind,
* duplicate paths or handles are omitted, and existing prompt text is kept.
*/
export function appendTuttiExternalReferenceSelections(
value: string | null | undefined,
selections: readonly TuttiExternalReferenceSelection[]
): string {
const pathSelections = selections.filter(
(
selection
): selection is Extract<
TuttiExternalReferenceSelection,
{ selectionKind: "path" }
> => selection.selectionKind === "path"
);
let content = appendRichTextLinksToContent(
value,
pathSelections.map(({ reference }) => ({
kind: reference.kind === "folder" ? "folder" : "file",
name: reference.displayName,
path: reference.path
}))
);
const existingWorkspaceReferenceKeys = new Set(
extractRichTextMentionsFromContent(content).flatMap((mention) => {
const key = workspaceReferenceIdentityKey(mention);
return key ? [key] : [];
})
);
const mentionMarkdown = selections.flatMap((selection) => {
if (selection.selectionKind !== "workspace-reference") {
return [];
}
const mention = {
providerId: "workspace-reference",
entityId: selection.id,
label: selection.displayName,
scope: {
workspaceId: selection.workspaceId,
source: selection.source,
...(selection.groupId ? { groupId: selection.groupId } : {}),
...(selection.fileCount && selection.fileCount > 0
? { count: String(selection.fileCount) }
: {})
}
};
const key = workspaceReferenceIdentityKey(mention);
if (!key || existingWorkspaceReferenceKeys.has(key)) {
return [];
}
existingWorkspaceReferenceKeys.add(key);
const markdown = createRichTextMentionMarkdown(mention);
return markdown ? [markdown] : [];
});
if (mentionMarkdown.length === 0) {
return content;
}
content = normalizeRichTextContent(content);
return content
? `${content} ${mentionMarkdown.join(" ")}`
: mentionMarkdown.join(" ");
}
export async function queryTuttiExternalAtRichTextTriggerItems(
input: QueryTuttiExternalAtRichTextTriggerItemsInput
): Promise<readonly TuttiExternalAtQueryResult[]> {
const bridge = (input.getBridge?.() ?? input.bridge)?.at;
if (!bridge) return [];
const providerIds =
input.providerIds === undefined
? tuttiExternalAtProviderIds
: input.providerIds;
const results = await bridge.query({
keyword: input.keyword,
...(input.maxResults !== undefined ? { maxResults: input.maxResults } : {}),
providers: providerIds
});
const providerSet = new Set<TuttiExternalAtProviderId>(providerIds);
return results.filter((item) => providerSet.has(item.providerId));
}
export function createTuttiExternalAtRichTextTriggerProvider(
input: CreateTuttiExternalAtRichTextTriggerProviderInput
): RichTextTriggerProvider<TuttiExternalAtQueryResult> {
return {
id: input.providerId,
trigger: "@",
async query(queryInput) {
return queryTuttiExternalAtRichTextTriggerItems({
bridge: input.bridge,
getBridge: input.getBridge,
keyword: queryInput.keyword,
maxResults: queryInput.maxResults ?? input.maxResults,
providerIds: [input.providerId]
});
},
...(input.providerId === "file" &&
(input.getBridge?.() ?? input.bridge)?.at?.queryDirectory
? {
getItemDirectory(item: TuttiExternalAtQueryResult) {
return item.directory;
},
async queryDirectory(queryInput) {
const bridge = (input.getBridge?.() ?? input.bridge)?.at;
if (!bridge?.queryDirectory) {
throw new Error(
"Tutti external @ bridge does not support directory browsing."
);
}
return bridge.queryDirectory({
directoryPath: queryInput.directoryPath,
maxResults: queryInput.maxResults ?? input.maxResults,
providerId: input.providerId
});
}
}
: {}),
async resolveMention(identity) {
const bridge = (input.getBridge?.() ?? input.bridge)?.at;
if (!bridge) return null;
if (bridge.resolve) {
return bridge.resolve({
providerId: input.providerId,
entityId: identity.entityId,
...(identity.scope ? { scope: identity.scope } : {})
});
}
const fallbackKeywords = [
identity.label.trim().replace(/^@+/, "").trim(),
""
].filter((keyword, index, values) => values.indexOf(keyword) === index);
for (const keyword of fallbackKeywords) {
const matches = await queryTuttiExternalAtRichTextTriggerItems({
bridge: input.bridge,
getBridge: input.getBridge,
keyword,
maxResults: 50,
providerIds: [input.providerId]
});
const match = matches.find((item) =>
matchesExternalMentionIdentity(item, identity)
);
if (match?.insert.kind === "mention") {
return {
label: match.insert.mention.label,
presentation: match.insert.mention.presentation
};
}
}
return null;
},
getItemKey: (item) => item.itemId,
getItemLabel: (item) => item.label,
getItemSubtitle: (item) => item.subtitle,
getItemIconUrl: (item) =>
item.thumbnailUrl ??
(item.insert.kind === "mention"
? (item.insert.mention.presentation?.iconUrl ??
item.insert.mention.presentation?.thumbnailUrl ??
item.insert.mention.presentation?.agentIconUrl)
: undefined),
toInsertResult: (item) => item.insert as RichTextTriggerInsertResult
};
}
export function createTuttiExternalAtRichTextTriggerProviders(
input: CreateTuttiExternalAtRichTextTriggerProvidersInput
): readonly RichTextTriggerProvider<TuttiExternalAtQueryResult>[] {
const providerIds =
input.providerIds === undefined
? tuttiExternalAtProviderIds
: input.providerIds;
return providerIds.map((providerId) =>
createTuttiExternalAtRichTextTriggerProvider({
bridge: input.bridge,
getBridge: input.getBridge,
providerId,
maxResults: input.maxResults
})
);
}
export function createTuttiExternalRichTextMentionService(
input: CreateTuttiExternalRichTextMentionServiceInput
): RichTextMentionService {
const hostProviders = createTuttiExternalAtRichTextTriggerProviders({
getBridge: input.getBridge,
providerIds: input.providerIds,
maxResults: input.maxResults
});
const service = createRichTextMentionService({
providers: [...hostProviders, ...(input.appLocalProviders ?? [])]
});
const unsubscribe = input.getBridge()?.at?.subscribe?.((event) => {
invalidateFromExternalEvent(service, event);
});
const disposeService = service.dispose.bind(service);
let disposed = false;
service.dispose = () => {
if (disposed) return;
disposed = true;
unsubscribe?.();
disposeService();
};
return service;
}
function matchesExternalMentionIdentity(
item: TuttiExternalAtQueryResult,
identity: RichTextMentionIdentity
): boolean {
if (
item.providerId !== identity.providerId ||
item.insert.kind !== "mention"
) {
return false;
}
return (
item.insert.mention.entityId.trim() === identity.entityId.trim() &&
canonicalizeRichTextMentionScope(item.insert.mention.scope) ===
canonicalizeRichTextMentionScope(identity.scope)
);
}
function invalidateFromExternalEvent(
service: RichTextMentionService,
event: TuttiExternalAtInvalidation
): void {
const providerIds = event.providerIds?.length
? event.providerIds
: [undefined];
const entityIds = event.entityIds?.length ? event.entityIds : [undefined];
for (const providerId of providerIds) {
for (const entityId of entityIds) {
service.invalidate({ providerId, entityId });
}
}
}