@portel/photon 1.28.2 → 1.31.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/README.md +42 -11
- package/dist/asset-resolver.d.ts +44 -0
- package/dist/asset-resolver.d.ts.map +1 -0
- package/dist/asset-resolver.js +105 -0
- package/dist/asset-resolver.js.map +1 -0
- package/dist/auto-ui/beam/external-mcp-manager.d.ts +73 -0
- package/dist/auto-ui/beam/external-mcp-manager.d.ts.map +1 -0
- package/dist/auto-ui/beam/external-mcp-manager.js +65 -0
- package/dist/auto-ui/beam/external-mcp-manager.js.map +1 -0
- package/dist/auto-ui/beam/external-mcp.d.ts.map +1 -1
- package/dist/auto-ui/beam/external-mcp.js +25 -1
- package/dist/auto-ui/beam/external-mcp.js.map +1 -1
- package/dist/auto-ui/beam/photon-management.d.ts.map +1 -1
- package/dist/auto-ui/beam/photon-management.js +11 -8
- package/dist/auto-ui/beam/photon-management.js.map +1 -1
- package/dist/auto-ui/beam/routes/api-browse.d.ts.map +1 -1
- package/dist/auto-ui/beam/routes/api-browse.js +7 -4
- package/dist/auto-ui/beam/routes/api-browse.js.map +1 -1
- package/dist/auto-ui/beam/routes/api-config.d.ts.map +1 -1
- package/dist/auto-ui/beam/routes/api-config.js +3 -2
- package/dist/auto-ui/beam/routes/api-config.js.map +1 -1
- package/dist/auto-ui/beam/routes/api-marketplace.d.ts.map +1 -1
- package/dist/auto-ui/beam/routes/api-marketplace.js +6 -2
- package/dist/auto-ui/beam/routes/api-marketplace.js.map +1 -1
- package/dist/auto-ui/beam/startup.js.map +1 -1
- package/dist/auto-ui/beam/types.d.ts +5 -2
- package/dist/auto-ui/beam/types.d.ts.map +1 -1
- package/dist/auto-ui/beam.d.ts.map +1 -1
- package/dist/auto-ui/beam.js +239 -88
- package/dist/auto-ui/beam.js.map +1 -1
- package/dist/auto-ui/bridge/index.d.ts.map +1 -1
- package/dist/auto-ui/bridge/index.js +11 -0
- package/dist/auto-ui/bridge/index.js.map +1 -1
- package/dist/auto-ui/bridge/types.d.ts +2 -0
- package/dist/auto-ui/bridge/types.d.ts.map +1 -1
- package/dist/auto-ui/openapi-generator.js +1 -4
- package/dist/auto-ui/openapi-generator.js.map +1 -1
- package/dist/auto-ui/photon-bridge.d.ts +4 -0
- package/dist/auto-ui/photon-bridge.d.ts.map +1 -1
- package/dist/auto-ui/photon-bridge.js.map +1 -1
- package/dist/auto-ui/photon-host.js.map +1 -1
- package/dist/auto-ui/streamable-http-transport.d.ts +7 -0
- package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -1
- package/dist/auto-ui/streamable-http-transport.js +252 -43
- package/dist/auto-ui/streamable-http-transport.js.map +1 -1
- package/dist/auto-ui/types.d.ts +24 -2
- package/dist/auto-ui/types.d.ts.map +1 -1
- package/dist/auto-ui/types.js.map +1 -1
- package/dist/beam.bundle.js +202 -24
- package/dist/beam.bundle.js.map +3 -3
- package/dist/capability-negotiator.d.ts +39 -1
- package/dist/capability-negotiator.d.ts.map +1 -1
- package/dist/capability-negotiator.js +5 -0
- package/dist/capability-negotiator.js.map +1 -1
- package/dist/cf-bindings-parser.d.ts +15 -0
- package/dist/cf-bindings-parser.d.ts.map +1 -0
- package/dist/cf-bindings-parser.js +98 -0
- package/dist/cf-bindings-parser.js.map +1 -0
- package/dist/cf-usage-scanner.d.ts +76 -0
- package/dist/cf-usage-scanner.d.ts.map +1 -0
- package/dist/cf-usage-scanner.js +179 -0
- package/dist/cf-usage-scanner.js.map +1 -0
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +124 -16
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/cf.d.ts +18 -0
- package/dist/cli/commands/cf.d.ts.map +1 -0
- package/dist/cli/commands/cf.js +207 -0
- package/dist/cli/commands/cf.js.map +1 -0
- package/dist/cli/commands/info.js +1 -1
- package/dist/cli/commands/info.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +59 -46
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +3 -0
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +43 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/daemon/client.d.ts.map +1 -1
- package/dist/daemon/client.js +40 -33
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/manager.d.ts +6 -2
- package/dist/daemon/manager.d.ts.map +1 -1
- package/dist/daemon/manager.js +75 -20
- package/dist/daemon/manager.js.map +1 -1
- package/dist/daemon/server.js +69 -11
- package/dist/daemon/server.js.map +1 -1
- package/dist/daemon/worker-host.js.map +1 -1
- package/dist/deploy/cloudflare.d.ts +27 -0
- package/dist/deploy/cloudflare.d.ts.map +1 -1
- package/dist/deploy/cloudflare.js +210 -3
- package/dist/deploy/cloudflare.js.map +1 -1
- package/dist/editor-support/docblock-tag-catalog.d.ts.map +1 -1
- package/dist/editor-support/docblock-tag-catalog.js +32 -2
- package/dist/editor-support/docblock-tag-catalog.js.map +1 -1
- package/dist/embedded-runtime.js.map +1 -1
- package/dist/format/registry.d.ts +83 -0
- package/dist/format/registry.d.ts.map +1 -0
- package/dist/format/registry.js +139 -0
- package/dist/format/registry.js.map +1 -0
- package/dist/format/seed.d.ts +18 -0
- package/dist/format/seed.d.ts.map +1 -0
- package/dist/format/seed.js +246 -0
- package/dist/format/seed.js.map +1 -0
- package/dist/loader.d.ts +61 -66
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +315 -327
- package/dist/loader.js.map +1 -1
- package/dist/photon-cli-runner.d.ts.map +1 -1
- package/dist/photon-cli-runner.js +20 -11
- package/dist/photon-cli-runner.js.map +1 -1
- package/dist/photons/maker.photon.d.ts +2 -2
- package/dist/photons/maker.photon.d.ts.map +1 -1
- package/dist/photons/maker.photon.js +5 -6
- package/dist/photons/maker.photon.js.map +1 -1
- package/dist/photons/maker.photon.ts +5 -6
- package/dist/resource-server.d.ts +55 -15
- package/dist/resource-server.d.ts.map +1 -1
- package/dist/resource-server.js +205 -50
- package/dist/resource-server.js.map +1 -1
- package/dist/runtime/cf-local.d.ts +157 -0
- package/dist/runtime/cf-local.d.ts.map +1 -0
- package/dist/runtime/cf-local.js +406 -0
- package/dist/runtime/cf-local.js.map +1 -0
- package/dist/server.d.ts +117 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +681 -67
- package/dist/server.js.map +1 -1
- package/dist/settings-persistence.d.ts +50 -0
- package/dist/settings-persistence.d.ts.map +1 -0
- package/dist/settings-persistence.js +188 -0
- package/dist/settings-persistence.js.map +1 -0
- package/dist/shared/asset-encoding.d.ts +30 -0
- package/dist/shared/asset-encoding.d.ts.map +1 -0
- package/dist/shared/asset-encoding.js +0 -0
- package/dist/shared/asset-encoding.js.map +1 -0
- package/dist/shared/audit-sqlite.d.ts.map +1 -1
- package/dist/shared/audit-sqlite.js +0 -1
- package/dist/shared/audit-sqlite.js.map +1 -1
- package/dist/shared/cross-origin-headers.d.ts +47 -0
- package/dist/shared/cross-origin-headers.d.ts.map +1 -0
- package/dist/shared/cross-origin-headers.js +61 -0
- package/dist/shared/cross-origin-headers.js.map +1 -0
- package/dist/shared/error-handler.d.ts.map +1 -1
- package/dist/shared/error-handler.js +3 -1
- package/dist/shared/error-handler.js.map +1 -1
- package/dist/shared/expose-route-extractor.d.ts +36 -0
- package/dist/shared/expose-route-extractor.d.ts.map +1 -0
- package/dist/shared/expose-route-extractor.js +64 -0
- package/dist/shared/expose-route-extractor.js.map +1 -0
- package/dist/shared/extract-claims.d.ts +33 -0
- package/dist/shared/extract-claims.d.ts.map +1 -0
- package/dist/shared/extract-claims.js +60 -0
- package/dist/shared/extract-claims.js.map +1 -0
- package/dist/shared/http-route-extractor.d.ts +6 -0
- package/dist/shared/http-route-extractor.d.ts.map +1 -1
- package/dist/shared/http-route-extractor.js +29 -5
- package/dist/shared/http-route-extractor.js.map +1 -1
- package/dist/shared/instance-binding.d.ts +53 -0
- package/dist/shared/instance-binding.d.ts.map +1 -0
- package/dist/shared/instance-binding.js +85 -0
- package/dist/shared/instance-binding.js.map +1 -0
- package/dist/shared/io.d.ts.map +1 -1
- package/dist/shared/io.js +5 -2
- package/dist/shared/io.js.map +1 -1
- package/dist/shared/logger.js.map +1 -1
- package/dist/shared/sqlite-runtime.d.ts.map +1 -1
- package/dist/shared/sqlite-runtime.js +0 -1
- package/dist/shared/sqlite-runtime.js.map +1 -1
- package/dist/task-executor.js.map +1 -1
- package/dist/telemetry/sdk.d.ts.map +1 -1
- package/dist/telemetry/sdk.js +0 -1
- package/dist/telemetry/sdk.js.map +1 -1
- package/dist/test-runner.d.ts.map +1 -1
- package/dist/test-runner.js.map +1 -1
- package/dist/types/server-types.d.ts +16 -7
- package/dist/types/server-types.d.ts.map +1 -1
- package/package.json +14 -4
- package/templates/cloudflare/worker.ts.template +428 -14
- package/templates/cloudflare/wrangler.toml.template +2 -7
- package/templates/photon.template.ts +13 -0
package/dist/daemon/server.js
CHANGED
|
@@ -144,8 +144,10 @@ setBroker(inProcessBroker);
|
|
|
144
144
|
const workerManager = new WorkerManager(logger);
|
|
145
145
|
// Wire worker manager pub/sub bridge to main broker
|
|
146
146
|
workerManager.onPublish = (channel, message) => {
|
|
147
|
+
// Worker pub/sub bridge: the worker emits a ChannelMessage-shaped envelope;
|
|
148
|
+
// unknown → ChannelMessage cast is the trust boundary between the worker
|
|
149
|
+
// protocol and the in-process broker.
|
|
147
150
|
void inProcessBroker.publish(message);
|
|
148
|
-
// Also forward to other workers
|
|
149
151
|
workerManager.dispatchToWorkers(channel, message);
|
|
150
152
|
};
|
|
151
153
|
// Track connected sockets for graceful shutdown broadcast
|
|
@@ -311,6 +313,8 @@ const pendingPrompts = new Map();
|
|
|
311
313
|
const channelSubscriptions = new Map();
|
|
312
314
|
/** Buffer retention window — events older than this are purged */
|
|
313
315
|
const EVENT_BUFFER_DURATION_MS = 5 * 60 * 1000; // 5 minutes
|
|
316
|
+
/** Hard cap per channel — prevents unbounded growth on high-frequency channels */
|
|
317
|
+
const MAX_BUFFER_EVENTS_PER_CHANNEL = 500;
|
|
314
318
|
const channelEventBuffers = new Map();
|
|
315
319
|
function bufferEvent(channel, message) {
|
|
316
320
|
let buffer = channelEventBuffers.get(channel);
|
|
@@ -338,6 +342,13 @@ function bufferEvent(channel, message) {
|
|
|
338
342
|
buffer.events.splice(0, firstValid);
|
|
339
343
|
}
|
|
340
344
|
}
|
|
345
|
+
// Hard cap: trim oldest when a high-frequency channel exceeds the count limit.
|
|
346
|
+
// A reconnecting subscriber whose lastEventId predates the oldest buffered event
|
|
347
|
+
// will receive refreshNeeded:true via getEventsSince — same handling as the
|
|
348
|
+
// time-based purge above.
|
|
349
|
+
if (buffer.events.length > MAX_BUFFER_EVENTS_PER_CHANNEL) {
|
|
350
|
+
buffer.events.splice(0, buffer.events.length - MAX_BUFFER_EVENTS_PER_CHANNEL);
|
|
351
|
+
}
|
|
341
352
|
return now;
|
|
342
353
|
}
|
|
343
354
|
function getEventsSince(channel, lastTimestamp) {
|
|
@@ -1346,6 +1357,8 @@ async function scanOneForProactiveMetadata(photonName, filePath, workingDir) {
|
|
|
1346
1357
|
return dropProactiveMetadataFor(photonName, workingDir);
|
|
1347
1358
|
}
|
|
1348
1359
|
let changed = false;
|
|
1360
|
+
// ExtractedMetadata isn't part of photon-core's public surface; type the
|
|
1361
|
+
// bits we read structurally so we get checking without re-exporting.
|
|
1349
1362
|
let meta;
|
|
1350
1363
|
try {
|
|
1351
1364
|
const extractor = new SchemaExtractor();
|
|
@@ -1366,8 +1379,7 @@ async function scanOneForProactiveMetadata(photonName, filePath, workingDir) {
|
|
|
1366
1379
|
// See src/daemon/registry-keys.ts for the branded-key rationale.
|
|
1367
1380
|
const nextSchedules = new Map();
|
|
1368
1381
|
const nextRoutes = new Map(); // routePath → methodName
|
|
1369
|
-
for (const
|
|
1370
|
-
const tool = rawTool;
|
|
1382
|
+
for (const tool of meta.tools) {
|
|
1371
1383
|
if (tool.scheduled) {
|
|
1372
1384
|
nextSchedules.set(declaredKey(photonName, tool.name, workingDir), {
|
|
1373
1385
|
photon: photonName,
|
|
@@ -3703,7 +3715,8 @@ async function handleRequest(request, socket) {
|
|
|
3703
3715
|
// Worker photons don't have a session manager — handle runtime tools directly
|
|
3704
3716
|
if (workerManager.has(cmdKey) && runtimeTools.includes(request.method)) {
|
|
3705
3717
|
if (request.method === '_use') {
|
|
3706
|
-
const
|
|
3718
|
+
const rawName = request.args?.name;
|
|
3719
|
+
const instanceName = typeof rawName === 'string' ? rawName : '';
|
|
3707
3720
|
const label = instanceName || 'default';
|
|
3708
3721
|
return {
|
|
3709
3722
|
type: 'result',
|
|
@@ -3760,7 +3773,8 @@ async function handleRequest(request, socket) {
|
|
|
3760
3773
|
}
|
|
3761
3774
|
// ── Runtime-injected instance tools ──────────────────────────
|
|
3762
3775
|
if (request.method === '_use') {
|
|
3763
|
-
const
|
|
3776
|
+
const rawName = request.args?.name;
|
|
3777
|
+
const instanceName = typeof rawName === 'string' ? rawName : '';
|
|
3764
3778
|
await sessionManager.switchInstance(session.id, instanceName);
|
|
3765
3779
|
const label = instanceName || 'default';
|
|
3766
3780
|
// Ensure a state file exists so _instances can discover this instance
|
|
@@ -4252,7 +4266,10 @@ async function appendEventLog(photonName, instanceName, entry, workingDir) {
|
|
|
4252
4266
|
const stat = await fsPromises.stat(logPath);
|
|
4253
4267
|
if (stat.size >= EVENT_LOG_MAX_SIZE) {
|
|
4254
4268
|
const rotatedPath = logPath + '.1';
|
|
4255
|
-
await fsPromises.rename(logPath, rotatedPath).catch(() => {
|
|
4269
|
+
await fsPromises.rename(logPath, rotatedPath).catch((err) => logger.debug('Event log rotation rename failed', {
|
|
4270
|
+
photon: photonName,
|
|
4271
|
+
error: String(err),
|
|
4272
|
+
}));
|
|
4256
4273
|
logger.debug('Rotated event log', { photon: photonName, instance: instanceName });
|
|
4257
4274
|
}
|
|
4258
4275
|
}
|
|
@@ -4559,7 +4576,7 @@ function watchPhotonFile(photonName, photonPath) {
|
|
|
4559
4576
|
}, 100);
|
|
4560
4577
|
watchDebounce.set(watchPath, timer);
|
|
4561
4578
|
});
|
|
4562
|
-
if (
|
|
4579
|
+
if (typeof watcher.on === 'function') {
|
|
4563
4580
|
watcher.on('error', (err) => {
|
|
4564
4581
|
logger.warn('File watcher error', { photonName, error: getErrorMessage(err) });
|
|
4565
4582
|
unwatchPhotonFile(watchPath);
|
|
@@ -4723,7 +4740,7 @@ function watchWorkingDir(workingDir) {
|
|
|
4723
4740
|
}, 150);
|
|
4724
4741
|
watchDebounce.set(debounceKey, timer);
|
|
4725
4742
|
});
|
|
4726
|
-
if (
|
|
4743
|
+
if (typeof watcher.on === 'function') {
|
|
4727
4744
|
watcher.on('error', (err) => {
|
|
4728
4745
|
logger.warn('workingDir parent watcher error', { parentDir, error: getErrorMessage(err) });
|
|
4729
4746
|
parentDirWatchers.delete(parentDir);
|
|
@@ -4785,7 +4802,7 @@ function watchStateDir(workingDir) {
|
|
|
4785
4802
|
}, 150);
|
|
4786
4803
|
watchDebounce.set(debounceKey, timer);
|
|
4787
4804
|
});
|
|
4788
|
-
if (
|
|
4805
|
+
if (typeof watcher.on === 'function') {
|
|
4789
4806
|
watcher.on('error', (err) => {
|
|
4790
4807
|
logger.warn('State dir watcher error', { stateDir, error: getErrorMessage(err) });
|
|
4791
4808
|
stateDirWatchers.delete(workingDir);
|
|
@@ -5188,7 +5205,7 @@ function startupWatchPhotons() {
|
|
|
5188
5205
|
});
|
|
5189
5206
|
return;
|
|
5190
5207
|
}
|
|
5191
|
-
eagerLoad().catch(() => { });
|
|
5208
|
+
eagerLoad().catch((err) => logger.debug('Eager load failed', { error: String(err) }));
|
|
5192
5209
|
}, 1000);
|
|
5193
5210
|
}
|
|
5194
5211
|
// Watch the directory itself for new photon files added after startup
|
|
@@ -5220,7 +5237,7 @@ function startupWatchPhotons() {
|
|
|
5220
5237
|
logger.info('Photon file removed', { photonName, path: filePath });
|
|
5221
5238
|
}
|
|
5222
5239
|
});
|
|
5223
|
-
if (
|
|
5240
|
+
if (typeof dirWatcher.on === 'function') {
|
|
5224
5241
|
dirWatcher.on('error', () => { }); // Non-fatal
|
|
5225
5242
|
}
|
|
5226
5243
|
}
|
|
@@ -5345,6 +5362,47 @@ function startServer() {
|
|
|
5345
5362
|
stack: reason instanceof Error ? reason.stack : undefined,
|
|
5346
5363
|
});
|
|
5347
5364
|
});
|
|
5365
|
+
// Periodic self-check: log once when the daemon binary on disk is newer
|
|
5366
|
+
// than this running daemon. The DaemonManager.isBinaryStale path already
|
|
5367
|
+
// restarts the daemon when a CLI command runs after `npm install`, so
|
|
5368
|
+
// the staleness window for interactive users is short. This nudge
|
|
5369
|
+
// covers the *non-interactive* case: a developer who upgrades photon
|
|
5370
|
+
// and then walks away leaving only scheduled jobs running. The daemon
|
|
5371
|
+
// does NOT auto-exit — schedules need continuity, and the next CLI
|
|
5372
|
+
// invocation triggers the same restart anyway. The warning is logged
|
|
5373
|
+
// at most once per detected upgrade so it doesn't spam the log when
|
|
5374
|
+
// running for hours after an upgrade.
|
|
5375
|
+
// Default 60s interval; tests can override via env var to assert the
|
|
5376
|
+
// log warning fires without waiting a full minute.
|
|
5377
|
+
const STALE_CHECK_INTERVAL_MS = Math.max(100, Number.parseInt(process.env.PHOTON_STALE_CHECK_INTERVAL_MS || '', 10) || 60_000);
|
|
5378
|
+
const daemonStartedAtMs = Date.now();
|
|
5379
|
+
let lastWarnedBinaryMtimeMs = 0;
|
|
5380
|
+
const myScript = process.argv[1];
|
|
5381
|
+
if (myScript) {
|
|
5382
|
+
const staleCheckTimer = setInterval(() => {
|
|
5383
|
+
try {
|
|
5384
|
+
const mtime = fs.statSync(myScript).mtimeMs;
|
|
5385
|
+
if (mtime > daemonStartedAtMs && mtime !== lastWarnedBinaryMtimeMs) {
|
|
5386
|
+
lastWarnedBinaryMtimeMs = mtime;
|
|
5387
|
+
logger.warn('Daemon binary on disk is newer than this running daemon. ' +
|
|
5388
|
+
'Run any photon CLI command (e.g. `photon ps`) to bounce the daemon to the new build, ' +
|
|
5389
|
+
'or restart it manually with `pkill -9 -f daemon/server.js`.', {
|
|
5390
|
+
pid: process.pid,
|
|
5391
|
+
scriptPath: myScript,
|
|
5392
|
+
binaryMtimeMs: mtime,
|
|
5393
|
+
daemonStartedAtMs,
|
|
5394
|
+
ageSec: Math.round((mtime - daemonStartedAtMs) / 1000),
|
|
5395
|
+
});
|
|
5396
|
+
}
|
|
5397
|
+
}
|
|
5398
|
+
catch {
|
|
5399
|
+
// stat raced with a write — try again next tick.
|
|
5400
|
+
}
|
|
5401
|
+
}, STALE_CHECK_INTERVAL_MS);
|
|
5402
|
+
// Don't keep the event loop alive on this watchdog alone — the
|
|
5403
|
+
// listening socket is the canonical liveness anchor.
|
|
5404
|
+
staleCheckTimer.unref?.();
|
|
5405
|
+
}
|
|
5348
5406
|
}
|
|
5349
5407
|
/**
|
|
5350
5408
|
* Scan the OS process table for any other process whose argv looks like
|