{"_id":"@aimform/apps","_rev":"2-b427f95b6edc5fb74fd09d71f8f61ae6","name":"@aimform/apps","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@aimform/apps","version":"0.1.0","keywords":["aimform","apps","app-store","sdk","manifest","mcp","oauth2"],"author":{"name":"Aimform / Universal Reason LLC"},"license":"MIT","_id":"@aimform/apps@0.1.0","maintainers":[{"name":"adamhalasz","email":"mail@adamhalasz.com"}],"homepage":"https://github.com/adamhalasz/saas-stack#readme","bugs":{"url":"https://github.com/adamhalasz/saas-stack/issues"},"dist":{"shasum":"89430365ad937f58d0adcb45f5f6aad52c73d5e5","tarball":"https://registry.npmjs.org/@aimform/apps/-/apps-0.1.0.tgz","fileCount":28,"integrity":"sha512-0UxY84vu9izLx7K8B7hy/ZKk8igcPZAzmLv7cd44OD34Jr4pvzk07ZyX14Sgv1x6q/zvxikHdpTYOmPVrJF8GQ==","signatures":[{"sig":"MEUCIQCRxVIysHpQFqkuwnyg8hieHS/wxcT2XBr9Rmvsucl2awIgfJwqBhy4byj0ohcvnnM2JbQuMiCFmi8Q9IM/fPblWxo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":87206},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js"}},"gitHead":"80f5a0b559b0b76119250546fbb0909694f683a6","private":false,"scripts":{"build":"tsc","typecheck":"tsc --noEmit","prepublishOnly":"pnpm build"},"_npmUser":{"name":"adamhalasz","email":"mail@adamhalasz.com"},"repository":{"url":"git+https://github.com/adamhalasz/saas-stack.git","type":"git","directory":"packages/apps"},"_npmVersion":"11.8.0","description":"Aimform App Store SDK — define, validate, and publish apps for the Aimform platform","directories":{},"sideEffects":false,"_nodeVersion":"25.6.0","dependencies":{"zod":"^3.23.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.7.0","@cloudflare/workers-types":"^4.20250224.0"},"_npmOperationalInternal":{"tmp":"tmp/apps_0.1.0_1786105385863_0.937695265220813","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@aimform/apps","private":false,"version":"0.1.1","description":"Aimform App Store SDK — define, validate, and publish apps for the Aimform platform","type":"module","sideEffects":false,"license":"MIT","author":{"name":"Aimform / Universal Reason LLC"},"repository":{"type":"git","url":"git+https://github.com/adamhalasz/saas-stack.git","directory":"packages/apps"},"keywords":["aimform","apps","app-store","sdk","manifest","mcp","oauth2"],"main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js"}},"scripts":{"build":"tsc","typecheck":"tsc --noEmit","prepublishOnly":"pnpm build"},"dependencies":{"zod":"^3.23.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20250224.0","typescript":"^5.7.0"},"gitHead":"679b65b23d6a7fbbcbe8e6d5de9486688bdb8e0d","_id":"@aimform/apps@0.1.1","bugs":{"url":"https://github.com/adamhalasz/saas-stack/issues"},"homepage":"https://github.com/adamhalasz/saas-stack#readme","_nodeVersion":"25.6.0","_npmVersion":"11.8.0","dist":{"integrity":"sha512-t9s7hRbL6tHxDpdalXQZXy4BLfW3qQvJrispkMoCvfCQwgnvKP+94NVWRu9ze5e5oVRg4u/OTsqk6utLThaXTg==","shasum":"b9c8b144413b71ac16238945059dc10cd2c1090d","tarball":"https://registry.npmjs.org/@aimform/apps/-/apps-0.1.1.tgz","fileCount":28,"unpackedSize":87325,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDC4MWynuDIe9vvPD/6y+bbvhhxdDX63nmOElZTewGP/AiEA28WeOktcINd/cVAIWQbs317qtMt5SmUzPKlvDvIo/Bk="}]},"_npmUser":{"name":"adamhalasz","email":"mail@adamhalasz.com"},"directories":{},"maintainers":[{"name":"adamhalasz","email":"mail@adamhalasz.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/apps_0.1.1_1786105895877_0.986910939483526"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-07T12:23:05.728Z","modified":"2026-08-07T12:31:36.199Z","0.1.0":"2026-08-07T12:23:05.991Z","0.1.1":"2026-08-07T12:31:36.021Z"},"bugs":{"url":"https://github.com/adamhalasz/saas-stack/issues"},"author":{"name":"Aimform / Universal Reason LLC"},"license":"MIT","homepage":"https://github.com/adamhalasz/saas-stack#readme","keywords":["aimform","apps","app-store","sdk","manifest","mcp","oauth2"],"repository":{"type":"git","url":"git+https://github.com/adamhalasz/saas-stack.git","directory":"packages/apps"},"description":"Aimform App Store SDK — define, validate, and publish apps for the Aimform platform","maintainers":[{"name":"adamhalasz","email":"mail@adamhalasz.com"}],"readme":"# @aimform/apps\n\nThe official SDK for building, validating, and publishing apps on the **Aimform** platform.\n\n`@aimform/apps` gives third-party developers everything they need to define app manifests, entity types, tools, onboarding flows, and profile sections — all with full TypeScript support and runtime validation via Zod.\n\n## Installation\n\n```bash\nnpm install @aimform/apps\n# or\npnpm add @aimform/apps\n```\n\n## Quick Start\n\nUse `defineApp()` to create a complete app manifest:\n\n```typescript\nimport { defineApp } from \"@aimform/apps\";\n\nconst myApp = defineApp({\n  id: \"my-slack-bot\",\n  name: \"Slack Bot\",\n  version: \"1.0.0\",\n  avatar: \"https://example.com/slack-icon.png\",\n  description: \"Bring Slack messages into Aimform.\",\n  category: \"communication\",\n  entryPoint: {\n    type: \"mcp\",\n    url: \"https://slack-bot.example.com/mcp\",\n  },\n  auth: {\n    type: \"oauth2\",\n    provider: \"slack\",\n  },\n  declaresEntityTypes: [\n    {\n      name: \"slack_message\",\n      properties: [\n        { name: \"text\", type: \"text\", label: \"Message\", required: true },\n        { name: \"channel\", type: \"string\", label: \"Channel\" },\n        { name: \"sent_at\", type: \"date\", label: \"Sent\" },\n      ],\n    },\n  ],\n  scopes: {\n    read: [\"slack_message\"],\n    write: [\"slack_message\"],\n  },\n  tools: [\n    {\n      name: \"send_slack_message\",\n      description: \"Send a message to a Slack channel\",\n      riskTier: \"confirm\",\n      exposedToAi: true,\n      inputSchema: {\n        type: \"object\",\n        properties: {\n          channel: { type: \"string\" },\n          text: { type: \"string\" },\n        },\n        required: [\"channel\", \"text\"],\n      },\n    },\n  ],\n  onboarding: {\n    steps: [\n      {\n        id: \"connect-slack\",\n        type: \"oauth_connect\",\n        title: \"Connect your Slack workspace\",\n        provider: \"slack\",\n      },\n    ],\n  },\n  profile: {\n    sections: [\n      {\n        id: \"recent-messages\",\n        type: \"view\",\n        title: \"Recent Messages\",\n        entityType: \"slack_message\",\n        fields: [\"text\", \"channel\", \"sent_at\"],\n        defaultSort: \"sent_at\",\n      },\n    ],\n  },\n});\n```\n\n## Entity Types\n\nEntity types define the data model your app brings into Aimform. Use the fluent builder or inline array syntax:\n\n```typescript\nimport { defineEntityType } from \"@aimform/apps\";\n\n// Fluent builder\nconst taskEntity = defineEntityType(\"task\")\n  .addProperty(\"title\", \"string\", { label: \"Title\", required: true, searchable: true })\n  .addProperty(\"status\", \"string\", { label: \"Status\" })\n  .addProperty(\"due_date\", \"date\", { label: \"Due Date\" })\n  .build();\n\n// Inline array\nconst noteEntity = defineEntityType(\"note\", [\n  { name: \"title\", type: \"string\", label: \"Title\", required: true },\n  { name: \"content\", type: \"text\", label: \"Content\", searchable: true },\n  { name: \"created_at\", type: \"date\", label: \"Created\" },\n]);\n```\n\n## Tools\n\nTools are actions exposed by your app that users and the AI assistant can invoke:\n\n```typescript\nimport { defineTool } from \"@aimform/apps\";\n\n// Safe read-only tool (auto-executable)\nconst searchTasks = defineTool({\n  name: \"search_tasks\",\n  description: \"Search tasks by title or status\",\n  riskTier: \"auto\",\n  exposedToAi: true,\n  inputSchema: {\n    type: \"object\",\n    properties: {\n      query: { type: \"string\", description: \"Search query\" },\n    },\n    required: [\"query\"],\n  },\n});\n\n// Write operation (requires user confirmation)\nconst createTask = defineTool({\n  name: \"create_task\",\n  description: \"Create a new task\",\n  riskTier: \"confirm\",\n  exposedToAi: true,\n  inputSchema: {\n    type: \"object\",\n    properties: {\n      title: { type: \"string\", description: \"Task title\" },\n      dueDate: { type: \"string\", description: \"Due date (ISO 8601)\" },\n    },\n    required: [\"title\"],\n  },\n});\n\n// Blocked tool (requires explicit user action)\nconst deleteTask = defineTool({\n  name: \"delete_task\",\n  description: \"Permanently delete a task\",\n  riskTier: \"blocked\",\n  exposedToAi: false,\n  inputSchema: {\n    type: \"object\",\n    properties: {\n      taskId: { type: \"string\", description: \"Task ID\" },\n    },\n    required: [\"taskId\"],\n  },\n});\n```\n\n### Risk Tiers\n\n| Tier | Behavior |\n|------|----------|\n| `auto` | Executes automatically without user confirmation. Use for safe read-only operations. |\n| `confirm` | Requires user confirmation before execution. Use for write/delete operations. |\n| `blocked` | Never auto-executes. Requires explicit user trigger. Use for dangerous or irreversible actions. |\n\n## Onboarding Steps\n\nOnboarding steps guide users through connecting your app:\n\n```typescript\nimport { defineOnboardingStep } from \"@aimform/apps\";\n\n// OAuth2 connection\nconst connectStep = defineOnboardingStep({\n  id: \"connect\",\n  type: \"oauth_connect\",\n  title: \"Connect your account\",\n  description: \"Authorize access to your data.\",\n  provider: \"google\",\n});\n\n// API key entry\nconst apiKeyStep = defineOnboardingStep({\n  id: \"api-key\",\n  type: \"api_key_form\",\n  title: \"Enter your API key\",\n  description: \"Find your API key in your account settings.\",\n  apiKeyLabel: \"API Key\",\n  apiKeyHelpText: \"Paste the API key from your provider dashboard.\",\n});\n\n// Permission review\nconst reviewStep = defineOnboardingStep({\n  id: \"review\",\n  type: \"permission_review\",\n  title: \"Review permissions\",\n  description: \"This app will be able to read your emails.\",\n});\n\n// Custom setup\nconst customStep = defineOnboardingStep({\n  id: \"setup\",\n  type: \"custom\",\n  title: \"Configure your workspace\",\n  customUrl: \"https://my-app.example.com/setup\",\n});\n```\n\n## Profile Sections\n\nProfile sections display your app's data in Aimform entity detail views:\n\n```typescript\nimport { defineProfileSection } from \"@aimform/apps\";\n\n// Table/list view\nconst listView = defineProfileSection({\n  id: \"recent-items\",\n  type: \"view\",\n  title: \"Recent Items\",\n  entityType: \"task\",\n  fields: [\"title\", \"status\", \"due_date\"],\n  defaultSort: \"due_date\",\n});\n\n// Document view (rich content)\nconst docView = defineProfileSection({\n  id: \"note-content\",\n  type: \"document\",\n  title: \"Note\",\n  entityType: \"note\",\n  documentType: \"text/markdown\",\n});\n\n// Freeform board\nconst board = defineProfileSection({\n  id: \"kanban\",\n  type: \"space\",\n  title: \"Project Board\",\n  entityType: \"task\",\n});\n```\n\n## Full Gmail App Example\n\nA complete Gmail app manifest using all the SDK features:\n\n```typescript\nimport {\n  defineApp,\n  defineEntityType,\n  defineTool,\n  defineOnboardingStep,\n  defineProfileSection,\n  defineScopes,\n} from \"@aimform/apps\";\n\nconst gmail = defineApp({\n  id: \"gmail\",\n  name: \"Gmail\",\n  version: \"1.0.0\",\n  avatar: \"https://example.com/gmail-icon.png\",\n  description: \"Read, search, and send emails from Gmail.\",\n  category: \"communication\",\n  entryPoint: {\n    type: \"mcp\",\n    url: \"https://gmail-app.example.com/mcp\",\n  },\n  auth: {\n    type: \"oauth2\",\n    provider: \"google\",\n  },\n  declaresEntityTypes: [\n    defineEntityType(\"email_thread\", [\n      { name: \"subject\", type: \"string\", label: \"Subject\", required: true, searchable: true },\n      { name: \"snippet\", type: \"text\", label: \"Snippet\", searchable: true },\n      { name: \"sender\", type: \"email\", label: \"Sender\" },\n      { name: \"recipients\", type: \"json\", label: \"Recipients\" },\n      { name: \"received_at\", type: \"date\", label: \"Received\" },\n      { name: \"is_read\", type: \"boolean\", label: \"Read\" },\n      { name: \"labels\", type: \"json\", label: \"Labels\" },\n    ]) as ReturnType<typeof defineEntityType>,\n  ],\n  scopes: defineScopes([\"email_thread\"], [\"email_thread\"]),\n  tools: [\n    defineTool({\n      name: \"search_emails\",\n      description: \"Search Gmail messages by query\",\n      riskTier: \"auto\",\n      exposedToAi: true,\n      inputSchema: {\n        type: \"object\",\n        properties: {\n          query: { type: \"string\", description: \"Gmail search query (supports Gmail search operators)\" },\n          maxResults: { type: \"number\", description: \"Maximum results to return\", default: 10 },\n        },\n        required: [\"query\"],\n      },\n    }),\n    defineTool({\n      name: \"get_email\",\n      description: \"Get full content of a specific email\",\n      riskTier: \"auto\",\n      exposedToAi: true,\n      inputSchema: {\n        type: \"object\",\n        properties: {\n          emailId: { type: \"string\", description: \"Email message ID\" },\n        },\n        required: [\"emailId\"],\n      },\n    }),\n    defineTool({\n      name: \"send_email\",\n      description: \"Send an email via Gmail\",\n      riskTier: \"confirm\",\n      exposedToAi: true,\n      inputSchema: {\n        type: \"object\",\n        properties: {\n          to: { type: \"string\", description: \"Recipient email address(es)\" },\n          cc: { type: \"string\", description: \"CC recipients\" },\n          subject: { type: \"string\", description: \"Email subject\" },\n          body: { type: \"string\", description: \"Email body (plain text or HTML)\" },\n        },\n        required: [\"to\", \"subject\", \"body\"],\n      },\n    }),\n    defineTool({\n      name: \"delete_email\",\n      description: \"Delete an email (moves to trash)\",\n      riskTier: \"confirm\",\n      exposedToAi: true,\n      inputSchema: {\n        type: \"object\",\n        properties: {\n          emailId: { type: \"string\", description: \"Email message ID\" },\n        },\n        required: [\"emailId\"],\n      },\n    }),\n  ],\n  onboarding: {\n    steps: [\n      defineOnboardingStep({\n        id: \"connect-gmail\",\n        type: \"oauth_connect\",\n        title: \"Connect your Gmail account\",\n        description: \"We'll redirect you to Google to authorize access to your Gmail.\",\n        provider: \"google\",\n      }),\n      defineOnboardingStep({\n        id: \"review-permissions\",\n        type: \"permission_review\",\n        title: \"Review permissions\",\n        description: \"This app needs access to read, search, and send emails from your Gmail account.\",\n      }),\n    ],\n  },\n  profile: {\n    sections: [\n      defineProfileSection({\n        id: \"recent-emails\",\n        type: \"view\",\n        title: \"Recent Emails\",\n        entityType: \"email_thread\",\n        fields: [\"subject\", \"snippet\", \"sender\", \"received_at\", \"is_read\"],\n        defaultSort: \"received_at\",\n      }),\n      defineProfileSection({\n        id: \"email-content\",\n        type: \"document\",\n        title: \"Email Body\",\n        entityType: \"email_thread\",\n        documentType: \"text/html\",\n      }),\n    ],\n  },\n});\n```\n\n## Validation\n\nThe SDK includes runtime validation via Zod schemas, accessible from the server entry point:\n\n```typescript\nimport { validateManifest, scanApp } from \"@aimform/apps/server\";\n\n// Validate a manifest loaded from JSON\nconst rawManifest = JSON.parse(\n  await Deno.readTextFile(\"aimform.manifest.json\"),\n);\nconst result = validateManifest(rawManifest);\n\nif (!result.success) {\n  console.error(\"Manifest is invalid:\");\n  for (const error of result.errors) {\n    console.error(`  - ${error}`);\n  }\n  process.exit(1);\n}\n\n// Deep scan for warnings and blocking issues\nconst report = scanApp(result.data);\n\nif (!report.passed) {\n  console.error(\"Scan found blocking issues:\");\n  for (const error of report.errors) {\n    console.error(`  - ${error}`);\n  }\n}\n\nif (report.warnings.length > 0) {\n  console.warn(\"Warnings (non-blocking):\");\n  for (const warning of report.warnings) {\n    console.warn(`  - ${warning}`);\n  }\n}\n```\n\n## API Reference\n\n### Main Entry (`@aimform/apps`)\n\n| Export | Description |\n|--------|-------------|\n| `defineApp(manifest)` | Create a complete app manifest |\n| `defineEntityType(name, properties?)` | Define an entity type (returns builder or declaration) |\n| `defineTool(config)` | Define a tool/action |\n| `defineOnboardingStep(step)` | Define an onboarding step |\n| `defineProfileSection(section)` | Define a profile section |\n| `defineScopes(read, write?)` | Define scoped permissions |\n| `OAUTH2_PROVIDERS` | Constants for known OAuth2 providers |\n| `InferAppManifest<T>` | Infer the type of a specific manifest |\n\n### Server Entry (`@aimform/apps/server`)\n\n| Export | Description |\n|--------|-------------|\n| `validateManifest(input)` | Validate unknown input against the manifest schema |\n| `scanApp(manifest)` | Deep scan a manifest for warnings and errors |\n| `aimformAppManifestSchema` | Raw Zod schema for custom validation logic |\n\n### Client Entry (`@aimform/apps/client`)\n\nType-only exports for browser-safe imports. All manifest types are re-exported:\n`AimformAppManifest`, `ToolDeclaration`, `EntityTypeDeclaration`, `AppScopes`, etc.\n\n## Types\n\n### `AimformAppManifest`\n\nThe top-level manifest type. See the [Quick Start](#quick-start) example for full shape.\n\n### `EntityTypeDeclaration`\n\n```typescript\ninterface EntityTypeDeclaration {\n  name: string;\n  properties: PropertyDefinition[];\n}\n```\n\n### `ToolDeclaration`\n\n```typescript\ninterface ToolDeclaration {\n  name: string;\n  description?: string;\n  riskTier: \"auto\" | \"confirm\" | \"blocked\";\n  exposedToAi: boolean;\n  inputSchema?: Record<string, unknown>;\n}\n```\n\n### `OnboardingStep`\n\n```typescript\ninterface OnboardingStep {\n  id: string;\n  type: \"oauth_connect\" | \"api_key_form\" | \"permission_review\" | \"custom\";\n  title: string;\n  description?: string;\n  provider?: string;\n  apiKeyLabel?: string;\n  apiKeyHelpText?: string;\n  customUrl?: string;\n}\n```\n\n### `ProfileSection`\n\n```typescript\ninterface ProfileSection {\n  id: string;\n  type: \"view\" | \"document\" | \"space\";\n  title: string;\n  entityType?: string;\n  fields?: string[];\n  defaultSort?: string;\n  documentType?: string;\n}\n```\n\n### `AuthConfig`\n\n```typescript\ninterface AuthConfig {\n  type: \"oauth2\" | \"api_key\" | \"none\";\n  provider?: string;\n}\n```\n\n### `EntryPointConfig`\n\n```typescript\ninterface EntryPointConfig {\n  type: \"mcp\" | \"sandboxed_code\" | \"external_call\";\n  url?: string;\n}\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}