@portel/photon-core 1.0.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -76,3 +76,94 @@ export {
76
76
 
77
77
  // Types
78
78
  export * from './types.js';
79
+
80
+ // Generator-based tools with ask/emit pattern
81
+ // See generator.ts for comprehensive documentation
82
+ export {
83
+ // Type guards - check yield direction
84
+ isAskYield,
85
+ isEmitYield,
86
+ getAskType,
87
+ getEmitType,
88
+
89
+ // Generator detection
90
+ isAsyncGeneratorFunction,
91
+ isAsyncGenerator,
92
+
93
+ // Executor - runs generators to completion
94
+ executeGenerator,
95
+
96
+ // Ask extraction (for REST API schema generation)
97
+ extractAsks,
98
+
99
+ // Built-in providers
100
+ createPrefilledProvider,
101
+ NeedsInputError,
102
+
103
+ // Utility
104
+ wrapAsGenerator,
105
+
106
+ // Ask yield types (input from user)
107
+ type AskYield,
108
+ type AskText,
109
+ type AskPassword,
110
+ type AskConfirm,
111
+ type AskSelect,
112
+ type AskNumber,
113
+ type AskFile,
114
+ type AskDate,
115
+
116
+ // Emit yield types (output to user)
117
+ type EmitYield,
118
+ type EmitStatus,
119
+ type EmitProgress,
120
+ type EmitStream,
121
+ type EmitLog,
122
+ type EmitToast,
123
+ type EmitThinking,
124
+ type EmitArtifact,
125
+
126
+ // Combined type
127
+ type PhotonYield,
128
+
129
+ // Execution config
130
+ type InputProvider,
131
+ type OutputHandler,
132
+ type GeneratorExecutorConfig,
133
+ type ExtractedAsk,
134
+
135
+ // Legacy compatibility (deprecated)
136
+ isInputYield,
137
+ isProgressYield,
138
+ isStreamYield,
139
+ isLogYield,
140
+ extractYields,
141
+ type PromptYield,
142
+ type ConfirmYield,
143
+ type SelectYield,
144
+ type ProgressYield,
145
+ type StreamYield,
146
+ type LogYield,
147
+ type ExtractedYield,
148
+ } from './generator.js';
149
+
150
+ // Elicit - Cross-platform user input (legacy, prefer generators)
151
+ export {
152
+ // Simple functions (no imports needed in photon files)
153
+ prompt,
154
+ confirm,
155
+ // Full elicit with options
156
+ elicit,
157
+ elicitReadline,
158
+ elicitNativeDialog,
159
+ // Handler management (for runtimes)
160
+ setPromptHandler,
161
+ getPromptHandler,
162
+ setElicitHandler,
163
+ getElicitHandler,
164
+ // Types
165
+ type ElicitOptions,
166
+ type ElicitResult,
167
+ type ElicitHandler,
168
+ type PromptHandler,
169
+ } from './elicit.js';
@@ -10,7 +10,7 @@
10
10
 
11
11
  import * as fs from 'fs/promises';
12
12
  import * as ts from 'typescript';
13
- import { ExtractedSchema, ConstructorParam, TemplateInfo, StaticInfo, OutputFormat } from './types.js';
13
+ import { ExtractedSchema, ConstructorParam, TemplateInfo, StaticInfo, OutputFormat, YieldInfo } from './types.js';
14
14
 
15
15
  export interface ExtractedMetadata {
16
16
  tools: ExtractedSchema[];
@@ -63,6 +63,9 @@ export class SchemaExtractor {
63
63
  const methodName = member.name.getText(sourceFile);
64
64
  const jsdoc = this.getJSDocComment(member, sourceFile);
65
65
 
66
+ // Check if this is an async generator method (has asterisk token)
67
+ const isGenerator = member.asteriskToken !== undefined;
68
+
66
69
  // Extract parameter type information
67
70
  const paramsType = this.getFirstParameterType(member, sourceFile);
68
71
  if (!paramsType) {
@@ -126,11 +129,15 @@ export class SchemaExtractor {
126
129
  // Otherwise, it's a regular tool
127
130
  else {
128
131
  const outputFormat = this.extractFormat(jsdoc);
132
+ const yields = isGenerator ? this.extractYieldsFromJSDoc(jsdoc) : undefined;
133
+
129
134
  tools.push({
130
135
  name: methodName,
131
136
  description,
132
137
  inputSchema,
133
138
  ...(outputFormat ? { outputFormat } : {}),
139
+ ...(isGenerator ? { isGenerator: true } : {}),
140
+ ...(yields && yields.length > 0 ? { yields } : {}),
134
141
  });
135
142
  }
136
143
  };
@@ -140,7 +147,7 @@ export class SchemaExtractor {
140
147
  // Look for class declarations
141
148
  if (ts.isClassDeclaration(node)) {
142
149
  node.members.forEach((member) => {
143
- // Look for async methods
150
+ // Look for async methods (including async generators with *)
144
151
  if (ts.isMethodDeclaration(member) &&
145
152
  member.modifiers?.some(m => m.kind === ts.SyntaxKind.AsyncKeyword)) {
146
153
  processMethod(member);
@@ -846,4 +853,27 @@ export class SchemaExtractor {
846
853
  const match = jsdocContent.match(/@mimeType\s+([\w\/\-+.]+)/i);
847
854
  return match ? match[1].trim() : undefined;
848
855
  }
856
+
857
+ /**
858
+ * Extract yield information from JSDoc for generator methods
859
+ * Supports @yields tags with id, type, and description
860
+ * Example: @yields {pairing_code} text Enter the 6-digit code shown on TV
861
+ */
862
+ private extractYieldsFromJSDoc(jsdocContent: string): YieldInfo[] {
863
+ const yields: YieldInfo[] = [];
864
+ // Match @yields {id} type description
865
+ const yieldRegex = /@yields?\s+\{(\w+)\}\s+(prompt|confirm|select)\s+(.+)/gi;
866
+
867
+ let match;
868
+ while ((match = yieldRegex.exec(jsdocContent)) !== null) {
869
+ const [, id, type, description] = match;
870
+ yields.push({
871
+ id,
872
+ type: type.toLowerCase() as 'prompt' | 'confirm' | 'select',
873
+ prompt: description.trim(),
874
+ });
875
+ }
876
+
877
+ return yields;
878
+ }
849
879
  }
package/src/types.ts CHANGED
@@ -23,6 +23,22 @@ export interface PhotonTool {
23
23
  outputFormat?: OutputFormat;
24
24
  }
25
25
 
26
+ /**
27
+ * Yield information extracted from generator methods
28
+ * Used for REST API schema generation (yields become optional parameters)
29
+ */
30
+ export interface YieldInfo {
31
+ id: string;
32
+ type: 'prompt' | 'confirm' | 'select';
33
+ prompt?: string;
34
+ options?: Array<string | { value: string; label: string }>;
35
+ default?: string;
36
+ required?: boolean;
37
+ pattern?: string;
38
+ dangerous?: boolean;
39
+ multi?: boolean;
40
+ }
41
+
26
42
  export interface ExtractedSchema {
27
43
  name: string;
28
44
  description: string;
@@ -32,6 +48,10 @@ export interface ExtractedSchema {
32
48
  required?: string[];
33
49
  };
34
50
  outputFormat?: OutputFormat;
51
+ /** True if this method is an async generator (uses yield for prompts) */
52
+ isGenerator?: boolean;
53
+ /** Yield information for generator methods (used by REST APIs) */
54
+ yields?: YieldInfo[];
35
55
  }
36
56
 
37
57
  export interface PhotonMCPClass {