@portel/photon 1.4.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +287 -1160
- package/dist/auto-ui/beam.d.ts +9 -0
- package/dist/auto-ui/beam.d.ts.map +1 -0
- package/dist/auto-ui/beam.js +2381 -0
- package/dist/auto-ui/beam.js.map +1 -0
- package/dist/auto-ui/components/card.d.ts +13 -0
- package/dist/auto-ui/components/card.d.ts.map +1 -0
- package/dist/auto-ui/components/card.js +64 -0
- package/dist/auto-ui/components/card.js.map +1 -0
- package/dist/auto-ui/components/form.d.ts +15 -0
- package/dist/auto-ui/components/form.d.ts.map +1 -0
- package/dist/auto-ui/components/form.js +72 -0
- package/dist/auto-ui/components/form.js.map +1 -0
- package/dist/auto-ui/components/list.d.ts +13 -0
- package/dist/auto-ui/components/list.d.ts.map +1 -0
- package/dist/auto-ui/components/list.js +58 -0
- package/dist/auto-ui/components/list.js.map +1 -0
- package/dist/auto-ui/components/progress.d.ts +18 -0
- package/dist/auto-ui/components/progress.d.ts.map +1 -0
- package/dist/auto-ui/components/progress.js +125 -0
- package/dist/auto-ui/components/progress.js.map +1 -0
- package/dist/auto-ui/components/table.d.ts +13 -0
- package/dist/auto-ui/components/table.d.ts.map +1 -0
- package/dist/auto-ui/components/table.js +82 -0
- package/dist/auto-ui/components/table.js.map +1 -0
- package/dist/auto-ui/components/tree.d.ts +13 -0
- package/dist/auto-ui/components/tree.d.ts.map +1 -0
- package/dist/auto-ui/components/tree.js +61 -0
- package/dist/auto-ui/components/tree.js.map +1 -0
- package/dist/auto-ui/daemon-tools.d.ts +45 -0
- package/dist/auto-ui/daemon-tools.d.ts.map +1 -0
- package/dist/auto-ui/daemon-tools.js +580 -0
- package/dist/auto-ui/daemon-tools.js.map +1 -0
- package/dist/auto-ui/design-system/index.d.ts +21 -0
- package/dist/auto-ui/design-system/index.d.ts.map +1 -0
- package/dist/auto-ui/design-system/index.js +27 -0
- package/dist/auto-ui/design-system/index.js.map +1 -0
- package/dist/auto-ui/design-system/tokens.d.ts +9 -0
- package/dist/auto-ui/design-system/tokens.d.ts.map +1 -0
- package/dist/auto-ui/design-system/tokens.js +27 -0
- package/dist/auto-ui/design-system/tokens.js.map +1 -0
- package/dist/auto-ui/design-system/transaction-ui.d.ts +70 -0
- package/dist/auto-ui/design-system/transaction-ui.d.ts.map +1 -0
- package/dist/auto-ui/design-system/transaction-ui.js +982 -0
- package/dist/auto-ui/design-system/transaction-ui.js.map +1 -0
- package/dist/auto-ui/frontend/index.html +84 -0
- package/dist/auto-ui/index.d.ts +21 -0
- package/dist/auto-ui/index.d.ts.map +1 -0
- package/dist/auto-ui/index.js +25 -0
- package/dist/auto-ui/index.js.map +1 -0
- package/dist/auto-ui/openapi-generator.d.ts +71 -0
- package/dist/auto-ui/openapi-generator.d.ts.map +1 -0
- package/dist/auto-ui/openapi-generator.js +223 -0
- package/dist/auto-ui/openapi-generator.js.map +1 -0
- package/dist/auto-ui/photon-bridge.d.ts +159 -0
- package/dist/auto-ui/photon-bridge.d.ts.map +1 -0
- package/dist/auto-ui/photon-bridge.js +262 -0
- package/dist/auto-ui/photon-bridge.js.map +1 -0
- package/dist/auto-ui/photon-host.d.ts +113 -0
- package/dist/auto-ui/photon-host.d.ts.map +1 -0
- package/dist/auto-ui/photon-host.js +284 -0
- package/dist/auto-ui/photon-host.js.map +1 -0
- package/dist/auto-ui/platform-compat.d.ts +71 -0
- package/dist/auto-ui/platform-compat.d.ts.map +1 -0
- package/dist/auto-ui/platform-compat.js +574 -0
- package/dist/auto-ui/platform-compat.js.map +1 -0
- package/dist/auto-ui/playground-html.d.ts +15 -0
- package/dist/auto-ui/playground-html.d.ts.map +1 -0
- package/dist/auto-ui/playground-html.js +1113 -0
- package/dist/auto-ui/playground-html.js.map +1 -0
- package/dist/auto-ui/playground-server.d.ts +7 -0
- package/dist/auto-ui/playground-server.d.ts.map +1 -0
- package/dist/auto-ui/playground-server.js +840 -0
- package/dist/auto-ui/playground-server.js.map +1 -0
- package/dist/auto-ui/registry.d.ts +13 -0
- package/dist/auto-ui/registry.d.ts.map +1 -0
- package/dist/auto-ui/registry.js +62 -0
- package/dist/auto-ui/registry.js.map +1 -0
- package/dist/auto-ui/renderer.d.ts +14 -0
- package/dist/auto-ui/renderer.d.ts.map +1 -0
- package/dist/auto-ui/renderer.js +88 -0
- package/dist/auto-ui/renderer.js.map +1 -0
- package/dist/auto-ui/rendering/components.d.ts +29 -0
- package/dist/auto-ui/rendering/components.d.ts.map +1 -0
- package/dist/auto-ui/rendering/components.js +773 -0
- package/dist/auto-ui/rendering/components.js.map +1 -0
- package/dist/auto-ui/rendering/field-analyzer.d.ts +48 -0
- package/dist/auto-ui/rendering/field-analyzer.d.ts.map +1 -0
- package/dist/auto-ui/rendering/field-analyzer.js +270 -0
- package/dist/auto-ui/rendering/field-analyzer.js.map +1 -0
- package/dist/auto-ui/rendering/field-renderers.d.ts +64 -0
- package/dist/auto-ui/rendering/field-renderers.d.ts.map +1 -0
- package/dist/auto-ui/rendering/field-renderers.js +317 -0
- package/dist/auto-ui/rendering/field-renderers.js.map +1 -0
- package/dist/auto-ui/rendering/index.d.ts +28 -0
- package/dist/auto-ui/rendering/index.d.ts.map +1 -0
- package/dist/auto-ui/rendering/index.js +60 -0
- package/dist/auto-ui/rendering/index.js.map +1 -0
- package/dist/auto-ui/rendering/layout-selector.d.ts +48 -0
- package/dist/auto-ui/rendering/layout-selector.d.ts.map +1 -0
- package/dist/auto-ui/rendering/layout-selector.js +352 -0
- package/dist/auto-ui/rendering/layout-selector.js.map +1 -0
- package/dist/auto-ui/rendering/template-engine.d.ts +41 -0
- package/dist/auto-ui/rendering/template-engine.d.ts.map +1 -0
- package/dist/auto-ui/rendering/template-engine.js +238 -0
- package/dist/auto-ui/rendering/template-engine.js.map +1 -0
- package/dist/auto-ui/streamable-http-transport.d.ts +79 -0
- package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -0
- package/dist/auto-ui/streamable-http-transport.js +1314 -0
- package/dist/auto-ui/streamable-http-transport.js.map +1 -0
- package/dist/auto-ui/types.d.ts +310 -0
- package/dist/auto-ui/types.d.ts.map +1 -0
- package/dist/auto-ui/types.js +71 -0
- package/dist/auto-ui/types.js.map +1 -0
- package/dist/beam.bundle.js +13506 -0
- package/dist/beam.bundle.js.map +7 -0
- package/dist/claude-code-plugin.d.ts.map +1 -1
- package/dist/claude-code-plugin.js +30 -30
- package/dist/claude-code-plugin.js.map +1 -1
- package/dist/cli/commands/info.d.ts +11 -0
- package/dist/cli/commands/info.d.ts.map +1 -0
- package/dist/cli/commands/info.js +313 -0
- package/dist/cli/commands/info.js.map +1 -0
- package/dist/cli/commands/marketplace.d.ts +11 -0
- package/dist/cli/commands/marketplace.d.ts.map +1 -0
- package/dist/cli/commands/marketplace.js +198 -0
- package/dist/cli/commands/marketplace.js.map +1 -0
- package/dist/cli/commands/package-app.d.ts +9 -0
- package/dist/cli/commands/package-app.d.ts.map +1 -0
- package/dist/cli/commands/package-app.js +191 -0
- package/dist/cli/commands/package-app.js.map +1 -0
- package/dist/cli/commands/package.d.ts +11 -0
- package/dist/cli/commands/package.d.ts.map +1 -0
- package/dist/cli/commands/package.js +573 -0
- package/dist/cli/commands/package.js.map +1 -0
- package/dist/cli-alias.d.ts.map +1 -1
- package/dist/cli-alias.js +30 -28
- package/dist/cli-alias.js.map +1 -1
- package/dist/cli-formatter.d.ts +8 -24
- package/dist/cli-formatter.d.ts.map +1 -1
- package/dist/cli-formatter.js +8 -325
- package/dist/cli-formatter.js.map +1 -1
- package/dist/cli.d.ts +15 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1157 -1132
- package/dist/cli.js.map +1 -1
- package/dist/daemon/client.d.ts +81 -0
- package/dist/daemon/client.d.ts.map +1 -1
- package/dist/daemon/client.js +583 -13
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/manager.d.ts +46 -12
- package/dist/daemon/manager.d.ts.map +1 -1
- package/dist/daemon/manager.js +102 -61
- package/dist/daemon/manager.js.map +1 -1
- package/dist/daemon/protocol.d.ts +74 -6
- package/dist/daemon/protocol.d.ts.map +1 -1
- package/dist/daemon/protocol.js +76 -1
- package/dist/daemon/protocol.js.map +1 -1
- package/dist/daemon/server.d.ts +6 -6
- package/dist/daemon/server.js +778 -117
- package/dist/daemon/server.js.map +1 -1
- package/dist/daemon/session-manager.d.ts +8 -1
- package/dist/daemon/session-manager.d.ts.map +1 -1
- package/dist/daemon/session-manager.js +32 -9
- package/dist/daemon/session-manager.js.map +1 -1
- package/dist/deploy/cloudflare.d.ts +12 -0
- package/dist/deploy/cloudflare.d.ts.map +1 -0
- package/dist/deploy/cloudflare.js +216 -0
- package/dist/deploy/cloudflare.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +172 -15
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +1132 -267
- package/dist/loader.js.map +1 -1
- package/dist/markdown-utils.d.ts +8 -0
- package/dist/markdown-utils.d.ts.map +1 -0
- package/dist/markdown-utils.js +63 -0
- package/dist/markdown-utils.js.map +1 -0
- package/dist/marketplace-manager.d.ts +10 -0
- package/dist/marketplace-manager.d.ts.map +1 -1
- package/dist/marketplace-manager.js +112 -28
- package/dist/marketplace-manager.js.map +1 -1
- package/dist/mcp-client.d.ts +9 -0
- package/dist/mcp-client.d.ts.map +1 -0
- package/dist/mcp-client.js +11 -0
- package/dist/mcp-client.js.map +1 -0
- package/dist/mcp-elicitation.d.ts +32 -0
- package/dist/mcp-elicitation.d.ts.map +1 -0
- package/dist/mcp-elicitation.js +26 -0
- package/dist/mcp-elicitation.js.map +1 -0
- package/dist/path-resolver.d.ts +9 -12
- package/dist/path-resolver.d.ts.map +1 -1
- package/dist/path-resolver.js +13 -43
- package/dist/path-resolver.js.map +1 -1
- package/dist/photon-cli-runner.d.ts.map +1 -1
- package/dist/photon-cli-runner.js +216 -73
- package/dist/photon-cli-runner.js.map +1 -1
- package/dist/photon-doc-extractor.d.ts +88 -0
- package/dist/photon-doc-extractor.d.ts.map +1 -1
- package/dist/photon-doc-extractor.js +536 -27
- package/dist/photon-doc-extractor.js.map +1 -1
- package/dist/photons/maker.photon.d.ts +182 -0
- package/dist/photons/maker.photon.d.ts.map +1 -0
- package/dist/photons/maker.photon.js +504 -0
- package/dist/photons/maker.photon.js.map +1 -0
- package/dist/photons/maker.photon.ts +626 -0
- package/dist/photons/marketplace.photon.d.ts +110 -0
- package/dist/photons/marketplace.photon.d.ts.map +1 -0
- package/dist/photons/marketplace.photon.js +260 -0
- package/dist/photons/marketplace.photon.js.map +1 -0
- package/dist/photons/marketplace.photon.ts +378 -0
- package/dist/photons/tunnel.photon.d.ts +80 -0
- package/dist/photons/tunnel.photon.d.ts.map +1 -0
- package/dist/photons/tunnel.photon.js +269 -0
- package/dist/photons/tunnel.photon.js.map +1 -0
- package/dist/photons/tunnel.photon.ts +345 -0
- package/dist/security-scanner.d.ts.map +1 -1
- package/dist/security-scanner.js +18 -15
- package/dist/security-scanner.js.map +1 -1
- package/dist/serv/auth/jwt.d.ts +89 -0
- package/dist/serv/auth/jwt.d.ts.map +1 -0
- package/dist/serv/auth/jwt.js +239 -0
- package/dist/serv/auth/jwt.js.map +1 -0
- package/dist/serv/auth/oauth.d.ts +117 -0
- package/dist/serv/auth/oauth.d.ts.map +1 -0
- package/dist/serv/auth/oauth.js +395 -0
- package/dist/serv/auth/oauth.js.map +1 -0
- package/dist/serv/auth/well-known.d.ts +60 -0
- package/dist/serv/auth/well-known.d.ts.map +1 -0
- package/dist/serv/auth/well-known.js +154 -0
- package/dist/serv/auth/well-known.js.map +1 -0
- package/dist/serv/db/d1-client.d.ts +65 -0
- package/dist/serv/db/d1-client.d.ts.map +1 -0
- package/dist/serv/db/d1-client.js +137 -0
- package/dist/serv/db/d1-client.js.map +1 -0
- package/dist/serv/db/d1-stores.d.ts +62 -0
- package/dist/serv/db/d1-stores.d.ts.map +1 -0
- package/dist/serv/db/d1-stores.js +307 -0
- package/dist/serv/db/d1-stores.js.map +1 -0
- package/dist/serv/index.d.ts +114 -0
- package/dist/serv/index.d.ts.map +1 -0
- package/dist/serv/index.js +172 -0
- package/dist/serv/index.js.map +1 -0
- package/dist/serv/local.d.ts +118 -0
- package/dist/serv/local.d.ts.map +1 -0
- package/dist/serv/local.js +392 -0
- package/dist/serv/local.js.map +1 -0
- package/dist/serv/middleware/auth.d.ts +66 -0
- package/dist/serv/middleware/auth.d.ts.map +1 -0
- package/dist/serv/middleware/auth.js +178 -0
- package/dist/serv/middleware/auth.js.map +1 -0
- package/dist/serv/middleware/tenant.d.ts +94 -0
- package/dist/serv/middleware/tenant.d.ts.map +1 -0
- package/dist/serv/middleware/tenant.js +152 -0
- package/dist/serv/middleware/tenant.js.map +1 -0
- package/dist/serv/runtime/executor.d.ts +76 -0
- package/dist/serv/runtime/executor.d.ts.map +1 -0
- package/dist/serv/runtime/executor.js +105 -0
- package/dist/serv/runtime/executor.js.map +1 -0
- package/dist/serv/runtime/index.d.ts +8 -0
- package/dist/serv/runtime/index.d.ts.map +1 -0
- package/dist/serv/runtime/index.js +10 -0
- package/dist/serv/runtime/index.js.map +1 -0
- package/dist/serv/runtime/oauth-context.d.ts +121 -0
- package/dist/serv/runtime/oauth-context.d.ts.map +1 -0
- package/dist/serv/runtime/oauth-context.js +153 -0
- package/dist/serv/runtime/oauth-context.js.map +1 -0
- package/dist/serv/session/kv-store.d.ts +54 -0
- package/dist/serv/session/kv-store.d.ts.map +1 -0
- package/dist/serv/session/kv-store.js +149 -0
- package/dist/serv/session/kv-store.js.map +1 -0
- package/dist/serv/session/store.d.ts +113 -0
- package/dist/serv/session/store.d.ts.map +1 -0
- package/dist/serv/session/store.js +284 -0
- package/dist/serv/session/store.js.map +1 -0
- package/dist/serv/types/index.d.ts +147 -0
- package/dist/serv/types/index.d.ts.map +1 -0
- package/dist/serv/types/index.js +8 -0
- package/dist/serv/types/index.js.map +1 -0
- package/dist/serv/vault/token-vault.d.ts +102 -0
- package/dist/serv/vault/token-vault.d.ts.map +1 -0
- package/dist/serv/vault/token-vault.js +177 -0
- package/dist/serv/vault/token-vault.js.map +1 -0
- package/dist/server.d.ts +173 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1622 -86
- package/dist/server.js.map +1 -1
- package/dist/shared/cli-sections.d.ts +6 -0
- package/dist/shared/cli-sections.d.ts.map +1 -0
- package/dist/shared/cli-sections.js +16 -0
- package/dist/shared/cli-sections.js.map +1 -0
- package/dist/shared/cli-utils.d.ts +81 -0
- package/dist/shared/cli-utils.d.ts.map +1 -0
- package/dist/shared/cli-utils.js +174 -0
- package/dist/shared/cli-utils.js.map +1 -0
- package/dist/shared/config-docs.d.ts +6 -0
- package/dist/shared/config-docs.d.ts.map +1 -0
- package/dist/shared/config-docs.js +6 -0
- package/dist/shared/config-docs.js.map +1 -0
- package/dist/shared/error-handler.d.ts +128 -0
- package/dist/shared/error-handler.d.ts.map +1 -0
- package/dist/shared/error-handler.js +342 -0
- package/dist/shared/error-handler.js.map +1 -0
- package/dist/shared/logger.d.ts +42 -0
- package/dist/shared/logger.d.ts.map +1 -0
- package/dist/shared/logger.js +123 -0
- package/dist/shared/logger.js.map +1 -0
- package/dist/shared/performance.d.ts +65 -0
- package/dist/shared/performance.d.ts.map +1 -0
- package/dist/shared/performance.js +136 -0
- package/dist/shared/performance.js.map +1 -0
- package/dist/shared/task-runner.d.ts +2 -0
- package/dist/shared/task-runner.d.ts.map +1 -0
- package/dist/shared/task-runner.js +16 -0
- package/dist/shared/task-runner.js.map +1 -0
- package/dist/shared/validation.d.ts +6 -0
- package/dist/shared/validation.d.ts.map +1 -0
- package/dist/shared/validation.js +6 -0
- package/dist/shared/validation.js.map +1 -0
- package/dist/shared-utils.d.ts +63 -0
- package/dist/shared-utils.d.ts.map +1 -0
- package/dist/shared-utils.js +123 -0
- package/dist/shared-utils.js.map +1 -0
- package/dist/template-manager.d.ts +23 -2
- package/dist/template-manager.d.ts.map +1 -1
- package/dist/template-manager.js +177 -88
- package/dist/template-manager.js.map +1 -1
- package/dist/test-client.d.ts.map +1 -1
- package/dist/test-client.js +10 -8
- package/dist/test-client.js.map +1 -1
- package/dist/test-runner.d.ts +52 -0
- package/dist/test-runner.d.ts.map +1 -0
- package/dist/test-runner.js +785 -0
- package/dist/test-runner.js.map +1 -0
- package/dist/testing.d.ts +103 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +163 -0
- package/dist/testing.js.map +1 -0
- package/dist/version-checker.d.ts.map +1 -1
- package/dist/version-checker.js +2 -2
- package/dist/version-checker.js.map +1 -1
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/dist/watcher.d.ts +6 -3
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +49 -10
- package/dist/watcher.js.map +1 -1
- package/package.json +47 -7
- package/templates/cloudflare/worker.ts.template +381 -0
- package/templates/cloudflare/wrangler.toml.template +9 -0
- package/dist/base.d.ts +0 -58
- package/dist/base.d.ts.map +0 -1
- package/dist/base.js +0 -92
- package/dist/base.js.map +0 -1
- package/dist/dependency-manager.d.ts +0 -49
- package/dist/dependency-manager.d.ts.map +0 -1
- package/dist/dependency-manager.js +0 -165
- package/dist/dependency-manager.js.map +0 -1
- package/dist/registry-manager.d.ts +0 -76
- package/dist/registry-manager.d.ts.map +0 -1
- package/dist/registry-manager.js +0 -220
- package/dist/registry-manager.js.map +0 -1
- package/dist/schema-extractor.d.ts +0 -110
- package/dist/schema-extractor.d.ts.map +0 -1
- package/dist/schema-extractor.js +0 -727
- package/dist/schema-extractor.js.map +0 -1
- package/dist/test-marketplace-sources.d.ts +0 -5
- package/dist/test-marketplace-sources.d.ts.map +0 -1
- package/dist/test-marketplace-sources.js +0 -53
- package/dist/test-marketplace-sources.js.map +0 -1
- package/dist/types.d.ts +0 -109
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -12
- package/dist/types.js.map +0 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
2
3
|
import { SchemaExtractor } from '@portel/photon-core';
|
|
4
|
+
import { PHOTON_VERSION } from './version.js';
|
|
3
5
|
/**
|
|
4
6
|
* Extracts comprehensive documentation from Photon files
|
|
5
7
|
*
|
|
@@ -22,20 +24,34 @@ export class PhotonDocExtractor {
|
|
|
22
24
|
this.content = await fs.readFile(this.filePath, 'utf-8');
|
|
23
25
|
const statefulTag = this.extractTag('stateful');
|
|
24
26
|
const idleTimeoutTag = this.extractTag('idleTimeout');
|
|
27
|
+
const internalTag = this.extractTag('internal');
|
|
28
|
+
const tools = await this.extractTools();
|
|
29
|
+
const photonType = this.detectPhotonType(tools);
|
|
30
|
+
const features = this.detectFeatures(tools, statefulTag !== undefined);
|
|
31
|
+
const externalDeps = this.extractDependencies();
|
|
32
|
+
const diagram = this.generateDiagramSync(tools, photonType, externalDeps);
|
|
25
33
|
return {
|
|
26
34
|
name: this.extractName(),
|
|
27
|
-
version: this.extractTag('version') ||
|
|
35
|
+
version: this.extractTag('version') || PHOTON_VERSION,
|
|
28
36
|
description: this.extractDescription(),
|
|
29
37
|
author: this.extractTag('author'),
|
|
30
38
|
license: this.extractTag('license'),
|
|
31
39
|
repository: this.extractTag('repository'),
|
|
32
40
|
homepage: this.extractTag('homepage'),
|
|
41
|
+
icon: this.extractTag('icon'),
|
|
42
|
+
internal: internalTag !== undefined,
|
|
33
43
|
configParams: this.extractConfigParams(),
|
|
34
44
|
setupInstructions: this.extractSetupInstructions(),
|
|
35
|
-
tools
|
|
45
|
+
tools,
|
|
36
46
|
dependencies: this.extractTag('dependencies'),
|
|
37
|
-
|
|
47
|
+
runtime: this.extractTag('runtime'),
|
|
48
|
+
stateful: statefulTag !== undefined,
|
|
38
49
|
idleTimeout: idleTimeoutTag ? parseInt(idleTimeoutTag, 10) : undefined,
|
|
50
|
+
assets: await this.extractAssets(),
|
|
51
|
+
photonType,
|
|
52
|
+
features,
|
|
53
|
+
externalDeps,
|
|
54
|
+
diagram,
|
|
39
55
|
};
|
|
40
56
|
}
|
|
41
57
|
/**
|
|
@@ -62,9 +78,18 @@ export class PhotonDocExtractor {
|
|
|
62
78
|
* Extract a specific JSDoc tag value
|
|
63
79
|
*/
|
|
64
80
|
extractTag(tagName) {
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
81
|
+
// First try to match tag with value: @tagName value
|
|
82
|
+
const regexWithValue = new RegExp(`@${tagName}\\s+(.+?)(?=\\n|$)`, 'm');
|
|
83
|
+
const matchWithValue = this.content.match(regexWithValue);
|
|
84
|
+
if (matchWithValue) {
|
|
85
|
+
return matchWithValue[1].trim();
|
|
86
|
+
}
|
|
87
|
+
// Then check for boolean tag without value: @tagName (followed by newline, *, or end)
|
|
88
|
+
const regexBoolean = new RegExp(`@${tagName}(?:\\s*\\n|\\s*\\*|$)`, 'm');
|
|
89
|
+
if (this.content.match(regexBoolean)) {
|
|
90
|
+
return 'true'; // Presence of tag means true
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
68
93
|
}
|
|
69
94
|
/**
|
|
70
95
|
* Extract configuration parameters from constructor
|
|
@@ -80,7 +105,10 @@ export class PhotonDocExtractor {
|
|
|
80
105
|
return params.map((param) => {
|
|
81
106
|
// Convert to environment variable format
|
|
82
107
|
// ClassName -> class-name -> CLASS_NAME_PARAM_NAME
|
|
83
|
-
const kebabCase = className
|
|
108
|
+
const kebabCase = className
|
|
109
|
+
.replace(/([A-Z])/g, '-$1')
|
|
110
|
+
.toLowerCase()
|
|
111
|
+
.replace(/^-/, '');
|
|
84
112
|
const envPrefix = kebabCase.toUpperCase().replace(/-/g, '_');
|
|
85
113
|
const envVar = `${envPrefix}_${param.name.toUpperCase()}`;
|
|
86
114
|
// Find description from Configuration section
|
|
@@ -138,21 +166,74 @@ export class PhotonDocExtractor {
|
|
|
138
166
|
// Clean up the configuration text
|
|
139
167
|
return configMatch[1]
|
|
140
168
|
.split('\n')
|
|
141
|
-
.map(line => line.replace(/^\s*\*\s?/, '').trim())
|
|
142
|
-
.filter(line => line.length > 0)
|
|
169
|
+
.map((line) => line.replace(/^\s*\*\s?/, '').trim())
|
|
170
|
+
.filter((line) => line.length > 0)
|
|
143
171
|
.join('\n')
|
|
144
172
|
.trim();
|
|
145
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Extract assets associated with the Photon
|
|
176
|
+
* Scans for ui/, prompts/, resources/ folders and @ui annotations
|
|
177
|
+
*/
|
|
178
|
+
async extractAssets() {
|
|
179
|
+
const assets = new Set();
|
|
180
|
+
const dir = path.dirname(this.filePath);
|
|
181
|
+
const basename = path.basename(this.filePath, '.photon.ts');
|
|
182
|
+
// Convention: asset folder has same name as photon (without .photon.ts)
|
|
183
|
+
// e.g. test-ui.photon.ts -> test-ui/
|
|
184
|
+
const assetFolder = path.join(dir, basename);
|
|
185
|
+
// Check if asset folder exists
|
|
186
|
+
try {
|
|
187
|
+
const stats = await fs.stat(assetFolder);
|
|
188
|
+
if (stats.isDirectory()) {
|
|
189
|
+
// Recursively find all files in the asset folder
|
|
190
|
+
const findFiles = async (currentDir, relativePath) => {
|
|
191
|
+
const entries = await fs.readdir(currentDir, { withFileTypes: true });
|
|
192
|
+
for (const entry of entries) {
|
|
193
|
+
const entryPath = path.join(currentDir, entry.name);
|
|
194
|
+
const entryRelative = path.join(relativePath, entry.name);
|
|
195
|
+
if (entry.isDirectory()) {
|
|
196
|
+
await findFiles(entryPath, entryRelative);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
// Add relative path from photon file's directory
|
|
200
|
+
// e.g. test-ui/ui/index.html
|
|
201
|
+
assets.add(path.join(basename, entryRelative));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
await findFiles(assetFolder, '');
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
// Asset folder doesn't exist, ignore
|
|
210
|
+
}
|
|
211
|
+
// Extract explicit @ui assets from JSDoc
|
|
212
|
+
// Format: @ui <id> <path>
|
|
213
|
+
const uiRegex = /@ui[ \t]+\S+[ \t]+(\S+)/g;
|
|
214
|
+
let match;
|
|
215
|
+
while ((match = uiRegex.exec(this.content)) !== null) {
|
|
216
|
+
const assetPath = match[1];
|
|
217
|
+
// Only include relative paths
|
|
218
|
+
if (assetPath.startsWith('./') || !path.isAbsolute(assetPath)) {
|
|
219
|
+
// Normalize path
|
|
220
|
+
const normalized = assetPath.startsWith('./') ? assetPath.slice(2) : assetPath;
|
|
221
|
+
assets.add(normalized);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return Array.from(assets);
|
|
225
|
+
}
|
|
146
226
|
/**
|
|
147
227
|
* Extract tool methods with their documentation
|
|
148
228
|
*/
|
|
149
229
|
async extractTools() {
|
|
150
230
|
const tools = [];
|
|
151
|
-
//
|
|
152
|
-
const methodRegex = /async\s+(\w+)\s*\([^)]*\)/g;
|
|
231
|
+
// Find all async methods (including generators with async *)
|
|
232
|
+
const methodRegex = /async\s+(\*?)\s*(\w+)\s*\([^)]*\)/g;
|
|
153
233
|
let match;
|
|
154
234
|
while ((match = methodRegex.exec(this.content)) !== null) {
|
|
155
|
-
const
|
|
235
|
+
const isGenerator = match[1] === '*';
|
|
236
|
+
const methodName = match[2];
|
|
156
237
|
const methodIndex = match.index;
|
|
157
238
|
// Skip private methods (starting with _) and lifecycle methods
|
|
158
239
|
if (methodName.startsWith('_') ||
|
|
@@ -177,6 +258,7 @@ export class PhotonDocExtractor {
|
|
|
177
258
|
const jsdoc = jsdocMatch[1];
|
|
178
259
|
const tool = this.parseToolMethodFromJSDoc(jsdoc, methodName);
|
|
179
260
|
if (tool) {
|
|
261
|
+
tool.isGenerator = isGenerator;
|
|
180
262
|
tools.push(tool);
|
|
181
263
|
}
|
|
182
264
|
}
|
|
@@ -215,24 +297,50 @@ export class PhotonDocExtractor {
|
|
|
215
297
|
constraints.push(`pattern: ${patternMatch[1]}`);
|
|
216
298
|
cleanDesc = cleanDesc.replace(/\{@pattern\s+[^}]+\}\s*/g, '');
|
|
217
299
|
}
|
|
218
|
-
// Extract {@
|
|
300
|
+
// Extract {@choice value1,value2,...}
|
|
301
|
+
const choiceMatch = cleanDesc.match(/\{@choice\s+([^}]+)\}/);
|
|
302
|
+
if (choiceMatch) {
|
|
303
|
+
constraints.push(`choice: ${choiceMatch[1]}`);
|
|
304
|
+
cleanDesc = cleanDesc.replace(/\{@choice\s+[^}]+\}\s*/g, '');
|
|
305
|
+
}
|
|
306
|
+
// Extract {@field type}
|
|
307
|
+
const fieldMatch = cleanDesc.match(/\{@field\s+([a-z]+)\}/);
|
|
308
|
+
if (fieldMatch) {
|
|
309
|
+
constraints.push(`field: ${fieldMatch[1]}`);
|
|
310
|
+
cleanDesc = cleanDesc.replace(/\{@field\s+[a-z]+\}\s*/g, '');
|
|
311
|
+
}
|
|
312
|
+
// Extract {@example value} - handle nested braces and brackets in JSON examples
|
|
219
313
|
const exampleStart = cleanDesc.indexOf('{@example ');
|
|
220
314
|
if (exampleStart !== -1) {
|
|
221
315
|
const contentStart = exampleStart + '{@example '.length;
|
|
222
|
-
let
|
|
316
|
+
let braceDepth = 0;
|
|
317
|
+
let bracketDepth = 0;
|
|
223
318
|
let i = contentStart;
|
|
224
|
-
|
|
319
|
+
let inString = false;
|
|
320
|
+
// Find the closing } by counting braces and brackets, respecting strings
|
|
225
321
|
while (i < cleanDesc.length) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
322
|
+
const ch = cleanDesc[i];
|
|
323
|
+
const prevCh = i > 0 ? cleanDesc[i - 1] : '';
|
|
324
|
+
// Handle string boundaries (skip escaped quotes)
|
|
325
|
+
if (ch === '"' && prevCh !== '\\') {
|
|
326
|
+
inString = !inString;
|
|
327
|
+
}
|
|
328
|
+
else if (!inString) {
|
|
329
|
+
if (ch === '{')
|
|
330
|
+
braceDepth++;
|
|
331
|
+
else if (ch === '[')
|
|
332
|
+
bracketDepth++;
|
|
333
|
+
else if (ch === ']')
|
|
334
|
+
bracketDepth--;
|
|
335
|
+
else if (ch === '}') {
|
|
336
|
+
if (braceDepth === 0 && bracketDepth === 0) {
|
|
337
|
+
// Found the closing brace of the {@example} tag
|
|
338
|
+
example = cleanDesc.substring(contentStart, i).trim();
|
|
339
|
+
cleanDesc = cleanDesc.substring(0, exampleStart) + cleanDesc.substring(i + 1);
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
braceDepth--;
|
|
234
343
|
}
|
|
235
|
-
depth--;
|
|
236
344
|
}
|
|
237
345
|
i++;
|
|
238
346
|
}
|
|
@@ -254,7 +362,7 @@ export class PhotonDocExtractor {
|
|
|
254
362
|
const description = descMatch
|
|
255
363
|
? descMatch[1]
|
|
256
364
|
.split('\n')
|
|
257
|
-
.map(line => line.replace(/^\s*\*\s?/, '').trim())
|
|
365
|
+
.map((line) => line.replace(/^\s*\*\s?/, '').trim())
|
|
258
366
|
.join(' ')
|
|
259
367
|
.trim()
|
|
260
368
|
: '';
|
|
@@ -271,7 +379,10 @@ export class PhotonDocExtractor {
|
|
|
271
379
|
// Format: "Param description (optional)" or "Param description (default: value)"
|
|
272
380
|
let cleanDesc = parsed.description;
|
|
273
381
|
const optional = /\(optional\)/i.test(cleanDesc) || /\(default:/i.test(cleanDesc);
|
|
274
|
-
cleanDesc = cleanDesc
|
|
382
|
+
cleanDesc = cleanDesc
|
|
383
|
+
.replace(/\(optional\)/gi, '')
|
|
384
|
+
.replace(/\(default:.*?\)/gi, '')
|
|
385
|
+
.trim();
|
|
275
386
|
params.push({
|
|
276
387
|
name: paramName,
|
|
277
388
|
type: 'any', // Type extraction from JSDoc would need more parsing
|
|
@@ -288,7 +399,7 @@ export class PhotonDocExtractor {
|
|
|
288
399
|
if (exampleMatch) {
|
|
289
400
|
const exampleText = exampleMatch[1]
|
|
290
401
|
.split('\n')
|
|
291
|
-
.map(line => line.replace(/^\s*\*\s?/, ''))
|
|
402
|
+
.map((line) => line.replace(/^\s*\*\s?/, ''))
|
|
292
403
|
.join('\n')
|
|
293
404
|
.trim();
|
|
294
405
|
// Only use it if it looks like actual code (not just a simple value from inline tag)
|
|
@@ -304,5 +415,403 @@ export class PhotonDocExtractor {
|
|
|
304
415
|
example,
|
|
305
416
|
};
|
|
306
417
|
}
|
|
418
|
+
// ============================================
|
|
419
|
+
// FEATURE DETECTION
|
|
420
|
+
// ============================================
|
|
421
|
+
/**
|
|
422
|
+
* Detect platform features used by this Photon
|
|
423
|
+
*/
|
|
424
|
+
detectFeatures(tools, isStateful) {
|
|
425
|
+
const features = [];
|
|
426
|
+
// generator — any async * method
|
|
427
|
+
if (tools.some((t) => t.isGenerator)) {
|
|
428
|
+
features.push('generator');
|
|
429
|
+
}
|
|
430
|
+
// custom-ui — @ui JSDoc tag
|
|
431
|
+
if (this.extractTag('ui') !== undefined || /@ui\s+\S+/.test(this.content)) {
|
|
432
|
+
features.push('custom-ui');
|
|
433
|
+
}
|
|
434
|
+
// elicitation — yield { ask: patterns
|
|
435
|
+
if (/yield\s*\{\s*ask\s*:/.test(this.content) || /yield\*\s/.test(this.content)) {
|
|
436
|
+
features.push('elicitation');
|
|
437
|
+
}
|
|
438
|
+
// streaming — yield { emit: or yield { step:
|
|
439
|
+
if (/yield\s*\{\s*(emit|step)\s*:/.test(this.content)) {
|
|
440
|
+
features.push('streaming');
|
|
441
|
+
}
|
|
442
|
+
// oauth — yield { ask: 'oauth'
|
|
443
|
+
if (/yield\s*\{\s*ask\s*:\s*['"]oauth['"]/.test(this.content)) {
|
|
444
|
+
features.push('oauth');
|
|
445
|
+
}
|
|
446
|
+
// stateful — @stateful tag
|
|
447
|
+
if (isStateful) {
|
|
448
|
+
features.push('stateful');
|
|
449
|
+
}
|
|
450
|
+
// webhooks — webhook endpoint patterns
|
|
451
|
+
if (/webhook/i.test(this.content) && /@webhook/.test(this.content)) {
|
|
452
|
+
features.push('webhooks');
|
|
453
|
+
}
|
|
454
|
+
// channels — channel in emit patterns
|
|
455
|
+
if (/channel/i.test(this.content) && /emit/.test(this.content)) {
|
|
456
|
+
features.push('channels');
|
|
457
|
+
}
|
|
458
|
+
// locks — acquireLock / releaseLock
|
|
459
|
+
if (/acquireLock|releaseLock/.test(this.content)) {
|
|
460
|
+
features.push('locks');
|
|
461
|
+
}
|
|
462
|
+
// mcp-bridge — this.mcp( calls
|
|
463
|
+
if (/this\.mcp\(/.test(this.content)) {
|
|
464
|
+
features.push('mcp-bridge');
|
|
465
|
+
}
|
|
466
|
+
// photon-bridge — this.photon( calls
|
|
467
|
+
if (/this\.photon\(/.test(this.content)) {
|
|
468
|
+
features.push('photon-bridge');
|
|
469
|
+
}
|
|
470
|
+
// wizard — @wizard tag
|
|
471
|
+
if (this.extractTag('wizard') !== undefined) {
|
|
472
|
+
features.push('wizard');
|
|
473
|
+
}
|
|
474
|
+
// dashboard — @ui + main method with linkedUi pattern
|
|
475
|
+
if (features.includes('custom-ui') &&
|
|
476
|
+
/async\s+\*?\s*main\b/.test(this.content) &&
|
|
477
|
+
/linkedUi|dashboard/i.test(this.content)) {
|
|
478
|
+
features.push('dashboard');
|
|
479
|
+
}
|
|
480
|
+
return features;
|
|
481
|
+
}
|
|
482
|
+
// ============================================
|
|
483
|
+
// DIAGRAM GENERATION
|
|
484
|
+
// ============================================
|
|
485
|
+
/**
|
|
486
|
+
* Generate a Mermaid diagram for this Photon
|
|
487
|
+
* Automatically detects the Photon type and generates appropriate diagram
|
|
488
|
+
*/
|
|
489
|
+
async generateDiagram() {
|
|
490
|
+
if (!this.content) {
|
|
491
|
+
this.content = await fs.readFile(this.filePath, 'utf-8');
|
|
492
|
+
}
|
|
493
|
+
const tools = await this.extractTools();
|
|
494
|
+
const photonType = this.detectPhotonType(tools);
|
|
495
|
+
const name = this.extractName();
|
|
496
|
+
const deps = this.extractDependencies();
|
|
497
|
+
switch (photonType) {
|
|
498
|
+
case 'workflow':
|
|
499
|
+
return this.generateWorkflowDiagram(name, tools, deps);
|
|
500
|
+
case 'streaming':
|
|
501
|
+
return this.generateStreamingDiagram(name, tools, deps);
|
|
502
|
+
default:
|
|
503
|
+
return this.generateApiSurfaceDiagram(name, tools, deps);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Generate diagram synchronously when content and tools are already loaded
|
|
508
|
+
*/
|
|
509
|
+
generateDiagramSync(tools, photonType, deps) {
|
|
510
|
+
const name = this.extractName();
|
|
511
|
+
switch (photonType) {
|
|
512
|
+
case 'workflow':
|
|
513
|
+
return this.generateWorkflowDiagram(name, tools, deps);
|
|
514
|
+
case 'streaming':
|
|
515
|
+
return this.generateStreamingDiagram(name, tools, deps);
|
|
516
|
+
default:
|
|
517
|
+
return this.generateApiSurfaceDiagram(name, tools, deps);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Detect the type of Photon based on its methods
|
|
522
|
+
*/
|
|
523
|
+
detectPhotonType(tools) {
|
|
524
|
+
const hasGenerator = tools.some((t) => t.isGenerator);
|
|
525
|
+
const hasAskEmit = this.hasAskEmitPatterns();
|
|
526
|
+
if (hasGenerator && hasAskEmit)
|
|
527
|
+
return 'workflow';
|
|
528
|
+
if (hasGenerator)
|
|
529
|
+
return 'streaming';
|
|
530
|
+
return 'api';
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Check if content has ask/emit yield patterns
|
|
534
|
+
*/
|
|
535
|
+
hasAskEmitPatterns() {
|
|
536
|
+
return /yield\s*\{\s*(ask|emit)\s*:/.test(this.content);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Extract dependencies from JSDoc tags
|
|
540
|
+
*/
|
|
541
|
+
extractDependencies() {
|
|
542
|
+
const mcpsTag = this.extractTag('mcps');
|
|
543
|
+
const photonsTag = this.extractTag('photons');
|
|
544
|
+
const depsTag = this.extractTag('dependencies');
|
|
545
|
+
return {
|
|
546
|
+
mcps: mcpsTag ? mcpsTag.split(/[,\s]+/).filter(Boolean) : [],
|
|
547
|
+
photons: photonsTag ? photonsTag.split(/[,\s]+/).filter(Boolean) : [],
|
|
548
|
+
npm: depsTag
|
|
549
|
+
? depsTag
|
|
550
|
+
.split(/[,\s]+/)
|
|
551
|
+
.map((d) => d.split('@')[0])
|
|
552
|
+
.filter(Boolean)
|
|
553
|
+
: [],
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Extract yield statements from content
|
|
558
|
+
*/
|
|
559
|
+
extractYieldStatements() {
|
|
560
|
+
const yields = [];
|
|
561
|
+
// Match: const varName = yield { ask: 'type', message: '...' }
|
|
562
|
+
// or: yield { emit: 'type', message: '...' }
|
|
563
|
+
const yieldRegex = /(?:const\s+(\w+)\s*(?::\s*\w+)?\s*=\s*)?yield\s*\{\s*(ask|emit)\s*:\s*['"](\w+)['"]\s*(?:,\s*message\s*:\s*[`'"]([^`'"]*)[`'"])?/g;
|
|
564
|
+
let match;
|
|
565
|
+
while ((match = yieldRegex.exec(this.content)) !== null) {
|
|
566
|
+
yields.push({
|
|
567
|
+
variable: match[1],
|
|
568
|
+
type: match[2],
|
|
569
|
+
subtype: match[3],
|
|
570
|
+
message: match[4],
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
return yields;
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Extract MCP and Photon calls from content
|
|
577
|
+
*/
|
|
578
|
+
extractExternalCalls() {
|
|
579
|
+
const calls = [];
|
|
580
|
+
// Match: this.mcp('name').method() or await this.mcp('name').method()
|
|
581
|
+
const mcpRegex = /this\.mcp\(['"](\w+)['"]\)\.(\w+)/g;
|
|
582
|
+
let match;
|
|
583
|
+
while ((match = mcpRegex.exec(this.content)) !== null) {
|
|
584
|
+
calls.push({ type: 'mcp', name: match[1], method: match[2] });
|
|
585
|
+
}
|
|
586
|
+
// Match: this.photon('name').method() or yield* this.photon('name').method()
|
|
587
|
+
const photonRegex = /this\.photon\(['"](\w+)['"]\)\.(\w+)/g;
|
|
588
|
+
while ((match = photonRegex.exec(this.content)) !== null) {
|
|
589
|
+
calls.push({ type: 'photon', name: match[1], method: match[2] });
|
|
590
|
+
}
|
|
591
|
+
return calls;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Infer emoji based on method/tool name
|
|
595
|
+
*/
|
|
596
|
+
inferEmoji(name) {
|
|
597
|
+
const lower = name.toLowerCase();
|
|
598
|
+
if (/^(read|get|fetch|load|find|query|search|list)/.test(lower))
|
|
599
|
+
return '📖';
|
|
600
|
+
if (/^(write|create|save|put|add|insert|set)/.test(lower))
|
|
601
|
+
return '✏️';
|
|
602
|
+
if (/^(delete|remove|drop|clear)/.test(lower))
|
|
603
|
+
return '🗑️';
|
|
604
|
+
if (/^(send|post|push|publish|notify)/.test(lower))
|
|
605
|
+
return '📤';
|
|
606
|
+
if (/^(update|modify|patch|edit)/.test(lower))
|
|
607
|
+
return '🔄';
|
|
608
|
+
if (/^(validate|check|verify|test)/.test(lower))
|
|
609
|
+
return '✅';
|
|
610
|
+
if (/^(config|setup|init)/.test(lower))
|
|
611
|
+
return '⚙️';
|
|
612
|
+
if (/^(run|execute|start|begin)/.test(lower))
|
|
613
|
+
return '▶️';
|
|
614
|
+
if (/^(stop|cancel|abort|end)/.test(lower))
|
|
615
|
+
return '⏹️';
|
|
616
|
+
if (/^(connect|login|auth)/.test(lower))
|
|
617
|
+
return '🔌';
|
|
618
|
+
if (/^(download|export)/.test(lower))
|
|
619
|
+
return '📥';
|
|
620
|
+
if (/^(upload|import)/.test(lower))
|
|
621
|
+
return '📤';
|
|
622
|
+
return '🔧';
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Get emoji for ask type
|
|
626
|
+
*/
|
|
627
|
+
getAskEmoji(subtype) {
|
|
628
|
+
switch (subtype) {
|
|
629
|
+
case 'confirm':
|
|
630
|
+
return '🙋';
|
|
631
|
+
case 'select':
|
|
632
|
+
return '📋';
|
|
633
|
+
case 'text':
|
|
634
|
+
return '✏️';
|
|
635
|
+
case 'number':
|
|
636
|
+
return '🔢';
|
|
637
|
+
case 'password':
|
|
638
|
+
return '🔒';
|
|
639
|
+
case 'date':
|
|
640
|
+
return '📅';
|
|
641
|
+
case 'file':
|
|
642
|
+
return '📁';
|
|
643
|
+
default:
|
|
644
|
+
return '❓';
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Get emoji for emit type
|
|
649
|
+
*/
|
|
650
|
+
getEmitEmoji(subtype) {
|
|
651
|
+
switch (subtype) {
|
|
652
|
+
case 'status':
|
|
653
|
+
return '📢';
|
|
654
|
+
case 'progress':
|
|
655
|
+
return '⏳';
|
|
656
|
+
case 'log':
|
|
657
|
+
return '📝';
|
|
658
|
+
case 'toast':
|
|
659
|
+
return '🎉';
|
|
660
|
+
case 'thinking':
|
|
661
|
+
return '🧠';
|
|
662
|
+
case 'artifact':
|
|
663
|
+
return '📊';
|
|
664
|
+
case 'stream':
|
|
665
|
+
return '💬';
|
|
666
|
+
default:
|
|
667
|
+
return '📣';
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Generate API surface diagram for tool collection Photons
|
|
672
|
+
*/
|
|
673
|
+
generateApiSurfaceDiagram(name, tools, deps) {
|
|
674
|
+
const lines = ['flowchart LR'];
|
|
675
|
+
// Main photon subgraph
|
|
676
|
+
lines.push(` subgraph ${this.sanitizeId(name)}["📦 ${this.titleCase(name)}"]`);
|
|
677
|
+
lines.push(' direction TB');
|
|
678
|
+
lines.push(' PHOTON((🎯))');
|
|
679
|
+
tools.forEach((tool, i) => {
|
|
680
|
+
const emoji = this.inferEmoji(tool.name);
|
|
681
|
+
const id = `T${i}`;
|
|
682
|
+
lines.push(` ${id}[${emoji} ${tool.name}]`);
|
|
683
|
+
lines.push(` PHOTON --> ${id}`);
|
|
684
|
+
});
|
|
685
|
+
lines.push(' end');
|
|
686
|
+
// Dependencies subgraph (if any)
|
|
687
|
+
const hasDeps = deps.mcps.length > 0 || deps.photons.length > 0 || deps.npm.length > 0;
|
|
688
|
+
if (hasDeps) {
|
|
689
|
+
lines.push('');
|
|
690
|
+
lines.push(' subgraph deps["Dependencies"]');
|
|
691
|
+
lines.push(' direction TB');
|
|
692
|
+
deps.mcps.forEach((mcp, i) => {
|
|
693
|
+
lines.push(` MCP${i}[🔌 ${mcp}]`);
|
|
694
|
+
});
|
|
695
|
+
deps.photons.forEach((photon, i) => {
|
|
696
|
+
lines.push(` PHO${i}[📦 ${photon}]`);
|
|
697
|
+
});
|
|
698
|
+
deps.npm.forEach((pkg, i) => {
|
|
699
|
+
lines.push(` NPM${i}[📚 ${pkg}]`);
|
|
700
|
+
});
|
|
701
|
+
lines.push(' end');
|
|
702
|
+
}
|
|
703
|
+
return lines.join('\n');
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Generate streaming diagram for generator Photons without ask/emit
|
|
707
|
+
*/
|
|
708
|
+
generateStreamingDiagram(name, tools, deps) {
|
|
709
|
+
// For streaming, show tools with streaming indicator
|
|
710
|
+
const lines = ['flowchart LR'];
|
|
711
|
+
lines.push(` subgraph ${this.sanitizeId(name)}["📦 ${this.titleCase(name)}"]`);
|
|
712
|
+
lines.push(' direction TB');
|
|
713
|
+
lines.push(' PHOTON((🎯))');
|
|
714
|
+
tools.forEach((tool, i) => {
|
|
715
|
+
const emoji = tool.isGenerator ? '🌊' : this.inferEmoji(tool.name);
|
|
716
|
+
const id = `T${i}`;
|
|
717
|
+
const suffix = tool.isGenerator ? ' (stream)' : '';
|
|
718
|
+
lines.push(` ${id}[${emoji} ${tool.name}${suffix}]`);
|
|
719
|
+
lines.push(` PHOTON --> ${id}`);
|
|
720
|
+
});
|
|
721
|
+
lines.push(' end');
|
|
722
|
+
return lines.join('\n');
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Generate workflow flowchart for Photons with ask/emit patterns
|
|
726
|
+
*/
|
|
727
|
+
generateWorkflowDiagram(name, tools, deps) {
|
|
728
|
+
const yields = this.extractYieldStatements();
|
|
729
|
+
const externalCalls = this.extractExternalCalls();
|
|
730
|
+
const lines = ['flowchart TD'];
|
|
731
|
+
lines.push(` subgraph ${this.sanitizeId(name)}["📦 ${this.titleCase(name)}"]`);
|
|
732
|
+
lines.push(' START([▶ Start])');
|
|
733
|
+
let prevNode = 'START';
|
|
734
|
+
let nodeCounter = 0;
|
|
735
|
+
// Process yields and calls in order they appear
|
|
736
|
+
for (const y of yields) {
|
|
737
|
+
const nodeId = `N${nodeCounter++}`;
|
|
738
|
+
if (y.type === 'emit') {
|
|
739
|
+
const emoji = this.getEmitEmoji(y.subtype);
|
|
740
|
+
const msg = y.message ? this.truncate(y.message, 30) : y.subtype;
|
|
741
|
+
lines.push(` ${nodeId}[${emoji} ${msg}]`);
|
|
742
|
+
lines.push(` ${prevNode} --> ${nodeId}`);
|
|
743
|
+
prevNode = nodeId;
|
|
744
|
+
}
|
|
745
|
+
else if (y.type === 'ask') {
|
|
746
|
+
const emoji = this.getAskEmoji(y.subtype);
|
|
747
|
+
const msg = y.message ? this.truncate(y.message, 25) : y.subtype;
|
|
748
|
+
lines.push(` ${nodeId}{${emoji} ${msg}}`);
|
|
749
|
+
lines.push(` ${prevNode} --> ${nodeId}`);
|
|
750
|
+
// For confirm, add Yes/No branches
|
|
751
|
+
if (y.subtype === 'confirm') {
|
|
752
|
+
const cancelId = `N${nodeCounter++}`;
|
|
753
|
+
const continueId = `N${nodeCounter++}`;
|
|
754
|
+
lines.push(` ${cancelId}([❌ Cancelled])`);
|
|
755
|
+
lines.push(` ${nodeId} -->|No| ${cancelId}`);
|
|
756
|
+
lines.push(` ${nodeId} -->|Yes| ${continueId}`);
|
|
757
|
+
// Create a dummy continue node for the flow
|
|
758
|
+
lines.push(` ${continueId}[Continue]`);
|
|
759
|
+
prevNode = continueId;
|
|
760
|
+
}
|
|
761
|
+
else {
|
|
762
|
+
prevNode = nodeId;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
// Add external calls
|
|
767
|
+
for (const call of externalCalls) {
|
|
768
|
+
const nodeId = `N${nodeCounter++}`;
|
|
769
|
+
const emoji = call.type === 'mcp' ? '🔌' : '📦';
|
|
770
|
+
lines.push(` ${nodeId}[${emoji} ${call.name}.${call.method}]`);
|
|
771
|
+
lines.push(` ${prevNode} --> ${nodeId}`);
|
|
772
|
+
prevNode = nodeId;
|
|
773
|
+
}
|
|
774
|
+
// End node
|
|
775
|
+
lines.push(` SUCCESS([✅ Success])`);
|
|
776
|
+
lines.push(` ${prevNode} --> SUCCESS`);
|
|
777
|
+
lines.push(' end');
|
|
778
|
+
// Dependencies
|
|
779
|
+
const hasDeps = deps.mcps.length > 0 || deps.photons.length > 0;
|
|
780
|
+
if (hasDeps) {
|
|
781
|
+
lines.push('');
|
|
782
|
+
lines.push(' subgraph deps["Dependencies"]');
|
|
783
|
+
deps.mcps.forEach((mcp, i) => {
|
|
784
|
+
lines.push(` DEP_MCP${i}[🔌 ${mcp}]`);
|
|
785
|
+
});
|
|
786
|
+
deps.photons.forEach((photon, i) => {
|
|
787
|
+
lines.push(` DEP_PHO${i}[📦 ${photon}]`);
|
|
788
|
+
});
|
|
789
|
+
lines.push(' end');
|
|
790
|
+
}
|
|
791
|
+
return lines.join('\n');
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Sanitize string for use as Mermaid node ID
|
|
795
|
+
*/
|
|
796
|
+
sanitizeId(str) {
|
|
797
|
+
return str.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* Convert kebab-case to Title Case
|
|
801
|
+
*/
|
|
802
|
+
titleCase(str) {
|
|
803
|
+
return str
|
|
804
|
+
.split('-')
|
|
805
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
806
|
+
.join(' ');
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
809
|
+
* Truncate string to max length
|
|
810
|
+
*/
|
|
811
|
+
truncate(str, maxLen) {
|
|
812
|
+
if (str.length <= maxLen)
|
|
813
|
+
return str;
|
|
814
|
+
return str.slice(0, maxLen - 3) + '...';
|
|
815
|
+
}
|
|
307
816
|
}
|
|
308
817
|
//# sourceMappingURL=photon-doc-extractor.js.map
|