@portel/photon-core 2.9.3 → 2.10.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/dist/compiler.d.ts.map +1 -1
- package/dist/compiler.js +26 -2
- package/dist/compiler.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/mixins.d.ts +42 -0
- package/dist/mixins.d.ts.map +1 -0
- package/dist/mixins.js +156 -0
- package/dist/mixins.js.map +1 -0
- package/dist/schema-extractor.d.ts +13 -1
- package/dist/schema-extractor.d.ts.map +1 -1
- package/dist/schema-extractor.js +302 -18
- package/dist/schema-extractor.js.map +1 -1
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +6 -4
- package/src/compiler.ts +29 -2
- package/src/index.ts +3 -0
- package/src/mixins.ts +187 -0
- package/src/schema-extractor.ts +382 -19
- package/src/types.ts +48 -0
package/src/mixins.ts
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Photon Capabilities Mixin
|
|
3
|
+
*
|
|
4
|
+
* Injects all Photon framework capabilities into any class without requiring inheritance.
|
|
5
|
+
* Works with classes that already extend other bases.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // Plain class (no inheritance)
|
|
10
|
+
* export default class Calculator {
|
|
11
|
+
* async add(a: number, b: number) { return a + b; }
|
|
12
|
+
* }
|
|
13
|
+
* // Gets wrapped: withPhotonCapabilities(Calculator)
|
|
14
|
+
* // Now has: this.emit(), this.memory, this.mcp(), this.call()
|
|
15
|
+
*
|
|
16
|
+
* // Class with own parent
|
|
17
|
+
* export default class Todo extends TodoBase {
|
|
18
|
+
* async add(text: string) { ... }
|
|
19
|
+
* }
|
|
20
|
+
* // Gets wrapped: withPhotonCapabilities(Todo)
|
|
21
|
+
* // Still works: this.someBaseMethod() + this.emit() + this.memory
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { MCPClient, MCPClientFactory, createMCPProxy } from '@portel/mcp';
|
|
26
|
+
import { executionContext } from '@portel/cli';
|
|
27
|
+
import { getBroker } from './channels/index.js';
|
|
28
|
+
import { MemoryProvider } from './memory.js';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Type for a constructor that may or may not extend Photon base class
|
|
32
|
+
*/
|
|
33
|
+
type Constructor<T = any> = new (...args: any[]) => T;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Injects Photon framework capabilities into any class via mixin composition.
|
|
37
|
+
*
|
|
38
|
+
* Works with:
|
|
39
|
+
* - Plain classes (no parent)
|
|
40
|
+
* - Classes extending user-defined bases
|
|
41
|
+
* - Classes extending imported library classes
|
|
42
|
+
* - Classes already extending Photon (no-op, already has capabilities)
|
|
43
|
+
*
|
|
44
|
+
* @param Base The class to enhance with Photon capabilities
|
|
45
|
+
* @returns Enhanced class with all Photon methods and properties
|
|
46
|
+
*/
|
|
47
|
+
export function withPhotonCapabilities<T extends Constructor>(Base: T): T {
|
|
48
|
+
// If already has Photon capabilities, return as-is
|
|
49
|
+
if ((Base.prototype as any)._photonName !== undefined || (Base.prototype as any).emit) {
|
|
50
|
+
return Base;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return class PhotonEnhanced extends Base {
|
|
54
|
+
/**
|
|
55
|
+
* Photon name (MCP name) - set by runtime loader
|
|
56
|
+
* @internal
|
|
57
|
+
*/
|
|
58
|
+
_photonName?: string;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Session ID for session-scoped memory - set by runtime
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
64
|
+
_sessionId?: string;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Scoped memory provider - lazy-initialized on first access
|
|
68
|
+
* @internal
|
|
69
|
+
*/
|
|
70
|
+
private _memory?: MemoryProvider;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Cross-photon call handler - injected by runtime
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
76
|
+
_callHandler?: (photon: string, method: string, params: Record<string, any>, targetInstance?: string) => Promise<any>;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* MCP client factory - injected by runtime
|
|
80
|
+
* @internal
|
|
81
|
+
*/
|
|
82
|
+
protected _mcpFactory?: MCPClientFactory;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Cache of MCP client instances
|
|
86
|
+
* @internal
|
|
87
|
+
*/
|
|
88
|
+
private _mcpClients: Map<string, MCPClient & Record<string, (params?: any) => Promise<any>>> = new Map();
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Scoped key-value storage for photon data
|
|
92
|
+
*/
|
|
93
|
+
get memory(): MemoryProvider {
|
|
94
|
+
if (!this._memory) {
|
|
95
|
+
const name = this._photonName || this.constructor.name
|
|
96
|
+
.replace(/MCP$/, '')
|
|
97
|
+
.replace(/([A-Z])/g, '-$1')
|
|
98
|
+
.toLowerCase()
|
|
99
|
+
.replace(/^-/, '');
|
|
100
|
+
this._memory = new MemoryProvider(name, this._sessionId);
|
|
101
|
+
}
|
|
102
|
+
return this._memory;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Emit an event/progress update
|
|
107
|
+
*/
|
|
108
|
+
protected emit(data: any): void {
|
|
109
|
+
const store = executionContext.getStore();
|
|
110
|
+
|
|
111
|
+
const emitData = this._photonName && typeof data === 'object' && data !== null
|
|
112
|
+
? { ...data, _source: this._photonName }
|
|
113
|
+
: data;
|
|
114
|
+
|
|
115
|
+
if (store?.outputHandler) {
|
|
116
|
+
store.outputHandler(emitData);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (data && typeof data.channel === 'string') {
|
|
120
|
+
const broker = getBroker();
|
|
121
|
+
broker.publish({
|
|
122
|
+
channel: data.channel,
|
|
123
|
+
event: data.event || 'message',
|
|
124
|
+
data: data.data !== undefined ? data.data : data,
|
|
125
|
+
timestamp: Date.now(),
|
|
126
|
+
source: this.constructor.name,
|
|
127
|
+
}).catch((err) => {
|
|
128
|
+
if (process.env.PHOTON_DEBUG) {
|
|
129
|
+
console.error('Channel publish error:', err);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Call another photon's method through the daemon
|
|
137
|
+
*/
|
|
138
|
+
protected async call(target: string, params: Record<string, any> = {}, options?: { instance?: string }): Promise<any> {
|
|
139
|
+
const dotIndex = target.indexOf('.');
|
|
140
|
+
if (dotIndex === -1) {
|
|
141
|
+
throw new Error(
|
|
142
|
+
`Invalid call target: '${target}'. Expected format: 'photonName.methodName'`
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const photonName = target.slice(0, dotIndex);
|
|
147
|
+
const methodName = target.slice(dotIndex + 1);
|
|
148
|
+
|
|
149
|
+
if (!this._callHandler) {
|
|
150
|
+
throw new Error(
|
|
151
|
+
`Cross-photon calls not available. To use this.call('${target}'), the Photon must be run in a runtime with a daemon.`
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return this._callHandler(photonName, methodName, params, options?.instance);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get an MCP client for calling external MCP servers
|
|
160
|
+
*/
|
|
161
|
+
mcp(mcpName: string): MCPClient & Record<string, (params?: any) => Promise<any>> {
|
|
162
|
+
if (!this._mcpFactory) {
|
|
163
|
+
throw new Error(
|
|
164
|
+
`MCP access not available. To use this.mcp('${mcpName}'), the Photon must be run in a runtime that supports MCP access.`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let client = this._mcpClients.get(mcpName);
|
|
169
|
+
if (client) {
|
|
170
|
+
return client;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const rawClient = this._mcpFactory.create(mcpName);
|
|
174
|
+
client = createMCPProxy(rawClient);
|
|
175
|
+
this._mcpClients.set(mcpName, client);
|
|
176
|
+
return client;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Set the MCP client factory
|
|
181
|
+
* @internal
|
|
182
|
+
*/
|
|
183
|
+
setMCPFactory(factory: MCPClientFactory): void {
|
|
184
|
+
this._mcpFactory = factory;
|
|
185
|
+
}
|
|
186
|
+
} as T;
|
|
187
|
+
}
|