-
Notifications
You must be signed in to change notification settings - Fork 120
refactor: package code organization wave 9 #2274
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
gsxdsm
wants to merge
2
commits into
main
Choose a base branch
from
feature/code-organization-wave9
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| /** | ||
| * FNXC:CodeOrganization 2026-07-17-12:00: | ||
| * Messaging domain types peeled from types.ts. | ||
| */ | ||
|
|
||
| export type ParticipantType = "agent" | "user" | "system"; | ||
|
|
||
| /** Canonical recipient ID for dashboard user mailbox routing. */ | ||
| export const DASHBOARD_USER_ID = "dashboard"; | ||
|
|
||
| const DASHBOARD_USER_ALIASES = new Set([DASHBOARD_USER_ID, "user", "user:dashboard", "User: user:dashboard"]); | ||
|
|
||
| /** Normalize participant identity for durable mailbox routing. */ | ||
| export function normalizeMessageParticipant(id: string, type: ParticipantType): { id: string; type: ParticipantType } { | ||
| if (type !== "user") { | ||
| return { id, type }; | ||
| } | ||
|
|
||
| if (DASHBOARD_USER_ALIASES.has(id)) { | ||
| return { id: DASHBOARD_USER_ID, type }; | ||
| } | ||
|
|
||
| return { id, type }; | ||
| } | ||
|
|
||
| /** Message types/categories */ | ||
| export type MessageType = "agent-to-agent" | "agent-to-user" | "user-to-agent" | "system"; | ||
|
|
||
| /** Stable metadata contract for linking a reply to an earlier message. */ | ||
| export interface MessageReplyReference { | ||
| /** ID of the message this one is replying to. */ | ||
| messageId: string; | ||
| } | ||
|
|
||
| /** Optional metadata attached to mailbox messages. */ | ||
| export interface MessageMetadata extends Record<string, unknown> { | ||
| /** Optional link to the original message when this message is a reply. */ | ||
| replyTo?: MessageReplyReference; | ||
| /** | ||
| * If true, the recipient agent is woken immediately on receipt regardless | ||
| * of their own `messageResponseMode` setting. Sender-initiated override — | ||
| * use sparingly for urgent messages. Ignored when recipient is a user. | ||
| */ | ||
| wakeRecipient?: boolean; | ||
| } | ||
|
|
||
| /** Message record stored in the system */ | ||
| export interface Message { | ||
| /** Unique identifier */ | ||
| id: string; | ||
| /** Sender identifier */ | ||
| fromId: string; | ||
| /** Sender type */ | ||
| fromType: ParticipantType; | ||
| /** Recipient identifier */ | ||
| toId: string; | ||
| /** Recipient type */ | ||
| toType: ParticipantType; | ||
| /** Message body */ | ||
| content: string; | ||
| /** Message category */ | ||
| type: MessageType; | ||
| /** Whether the recipient has read this message */ | ||
| read: boolean; | ||
| /** Optional extra data */ | ||
| metadata?: MessageMetadata; | ||
| /** ISO-8601 timestamp of creation */ | ||
| createdAt: string; | ||
| /** ISO-8601 timestamp of last update */ | ||
| updatedAt: string; | ||
| } | ||
|
|
||
| /** Input for creating a new message */ | ||
| export interface MessageCreateInput { | ||
| /** Sender identifier (auto-filled by the transport layer if omitted) */ | ||
| fromId?: string; | ||
| /** Sender type (auto-filled by the transport layer if omitted) */ | ||
| fromType?: ParticipantType; | ||
| /** Recipient identifier */ | ||
| toId: string; | ||
| /** Recipient type */ | ||
| toType: ParticipantType; | ||
| /** Message body */ | ||
| content: string; | ||
| /** Message category */ | ||
| type: MessageType; | ||
| /** Optional extra data */ | ||
| metadata?: MessageMetadata; | ||
| } | ||
|
|
||
| /** Filter options for querying messages */ | ||
| export interface MessageFilter { | ||
| /** Filter by message type */ | ||
| type?: MessageType; | ||
| /** Filter by read status */ | ||
| read?: boolean; | ||
| /** Maximum number of messages to return */ | ||
| limit?: number; | ||
| /** Number of messages to skip (for pagination) */ | ||
| offset?: number; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| /** | ||
| * FNXC:CodeOrganization 2026-07-17-12:00: | ||
| * Global settings and pi-extension/package client API peeled from legacy.ts. | ||
| */ | ||
| import type { GlobalSettings, ProjectSettings, Settings } from "@fusion/core"; | ||
| import { api } from "./client.js"; | ||
| import type { FetchOptions } from "./client.js"; | ||
| import { withProjectId } from "./health.js"; | ||
| import { dedupe } from "./dedupe.js"; | ||
|
|
||
| export function fetchGlobalSettings(options?: FetchOptions): Promise<GlobalSettings> { | ||
| return dedupe("/settings/global", () => api<GlobalSettings>("/settings/global"), options); | ||
| } | ||
|
|
||
| /** Update global (user-level) settings. These persist across all fn projects. */ | ||
| export function updateGlobalSettings(settings: Partial<GlobalSettings>): Promise<Settings> { | ||
| return api<Settings>("/settings/global", { | ||
| method: "PUT", | ||
| body: JSON.stringify(settings), | ||
| }); | ||
| } | ||
|
|
||
| /** Fetch settings separated by scope: { global, project } */ | ||
| export function fetchSettingsByScope(projectId?: string): Promise<{ global: GlobalSettings; project: Partial<ProjectSettings> }> { | ||
| return api<{ global: GlobalSettings; project: Partial<ProjectSettings> }>(withProjectId("/settings/scopes", projectId)); | ||
| } | ||
|
|
||
| export interface PiExtensionEntry { | ||
| id: string; | ||
| name: string; | ||
| path: string; | ||
| source: "fusion-global" | "pi-global" | "fusion-project" | "pi-project" | "package"; | ||
| enabled: boolean; | ||
| } | ||
|
|
||
| export interface PiExtensionSettings { | ||
| extensions: PiExtensionEntry[]; | ||
| disabledIds: string[]; | ||
| settingsPath: string; | ||
| } | ||
|
|
||
| export function fetchPiExtensions(projectId?: string): Promise<PiExtensionSettings> { | ||
| return api<PiExtensionSettings>(withProjectId("/settings/pi-extensions", projectId)); | ||
| } | ||
|
|
||
| export function updatePiExtensions(disabledIds: string[], projectId?: string): Promise<PiExtensionSettings> { | ||
| return api<PiExtensionSettings>(withProjectId("/settings/pi-extensions", projectId), { | ||
| method: "PUT", | ||
| body: JSON.stringify({ disabledIds }), | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Test a notification provider by sending a test notification. | ||
| * Supports "ntfy" and "webhook" provider IDs. | ||
| */ | ||
| export function testNotification(providerId: string, config?: Record<string, unknown>, projectId?: string): Promise<{ success: boolean }> { | ||
| return api<{ success: boolean }>(withProjectId("/settings/test-notification", projectId), { | ||
| method: "POST", | ||
| // Pin providerId last so config.providerId cannot override the selected provider. | ||
| body: JSON.stringify({ ...(config ?? {}), providerId }), | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Backward-compatible ntfy test helper. | ||
| * Wraps testNotification() while preserving the legacy function signature. | ||
| */ | ||
| export function testNtfyNotification( | ||
| config?: { | ||
| ntfyEnabled?: boolean; | ||
| ntfyTopic?: string; | ||
| ntfyBaseUrl?: string; | ||
| ntfyAccessToken?: string; | ||
| }, | ||
| projectId?: string, | ||
| ): Promise<{ success: boolean }> { | ||
| return testNotification("ntfy", config as Record<string, unknown> | undefined, projectId); | ||
| } | ||
|
|
||
| /** Pi extension settings from ~/.pi/agent/settings.json (global scope) */ | ||
| export interface PiSettings { | ||
| packages: Array<string | { source: string; extensions?: string[]; skills?: string[]; prompts?: string[]; themes?: string[] }>; | ||
| extensions: string[]; | ||
| skills: string[]; | ||
| prompts: string[]; | ||
| themes: string[]; | ||
| } | ||
|
|
||
| /** Fetch pi extension settings (global scope from ~/.pi/agent/settings.json) */ | ||
| export function fetchPiSettings(): Promise<PiSettings> { | ||
| return api<PiSettings>("/pi-settings"); | ||
| } | ||
|
|
||
| /** Update pi extension settings (partial update, global scope) */ | ||
| export async function updatePiSettings(settings: Partial<PiSettings>): Promise<{ success: boolean }> { | ||
| return api<{ success: boolean }>("/pi-settings", { | ||
| method: "PUT", | ||
| body: JSON.stringify(settings), | ||
| }); | ||
| } | ||
|
|
||
| /** Install a new pi package source (adds to ~/.pi/agent/settings.json) */ | ||
| export async function installPiPackage(source: string): Promise<{ success: boolean }> { | ||
| return api<{ success: boolean }>("/pi-settings/packages", { | ||
| method: "POST", | ||
| body: JSON.stringify({ source }), | ||
| }); | ||
| } | ||
|
|
||
| /** Reinstall Fusion's bundled pi package and ensure it remains in global Pi settings. */ | ||
| export async function reinstallFusionPiPackage(projectId?: string): Promise<{ success: boolean; source: string }> { | ||
| return api<{ success: boolean; source: string }>(withProjectId("/pi-settings/reinstall-fusion", projectId), { | ||
| method: "POST", | ||
| }); | ||
| } | ||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.