@pellux/goodvibes-tui 1.22.0 → 1.24.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/CHANGELOG.md +24 -0
- package/README.md +1 -1
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- package/package.json +7 -7
- package/src/cli/bundle-command.ts +4 -0
- package/src/cli/help.ts +5 -0
- package/src/cli/management-utils.ts +4 -0
- package/src/cluster/commands.ts +382 -0
- package/src/cluster/remote-daemon-target.ts +225 -0
- package/src/cluster/render.ts +268 -0
- package/src/core/conversation-line-cache.ts +11 -6
- package/src/core/conversation-render-context.ts +122 -0
- package/src/core/conversation-rendering.ts +86 -89
- package/src/daemon/cli.ts +71 -2
- package/src/daemon/handlers/inbox/index.ts +63 -3
- package/src/daemon/handlers/inbox/poller.ts +54 -8
- package/src/input/command-args-hint.ts +2 -0
- package/src/input/commands/cluster-runtime.ts +53 -0
- package/src/input/commands.ts +2 -0
- package/src/input/settings-modal-data.ts +6 -0
- package/src/main.ts +3 -0
- package/src/renderer/conversation-surface.ts +23 -6
- package/src/renderer/conversation-tree.ts +142 -93
- package/src/renderer/tool-call.ts +13 -12
- package/src/runtime/bootstrap.ts +6 -1
- package/src/runtime/cluster-composition.ts +124 -0
- package/src/runtime/cluster-group-composition.ts +284 -0
- package/src/runtime/daemon-handler-composition.ts +80 -0
- package/src/runtime/disposal-wiring.ts +66 -0
- package/src/runtime/durability-services.ts +7 -3
- package/src/runtime/embedded-service-factories.ts +19 -1
- package/src/runtime/process-lifecycle.ts +9 -1
- package/src/runtime/remote-execution-composition.ts +62 -0
- package/src/runtime/services.ts +50 -50
- package/src/verification/verification-ledger.ts +38 -0
- package/src/version.ts +1 -1
package/src/runtime/services.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { StepUpService } from '@pellux/goodvibes-sdk/daemon';
|
|
|
11
11
|
import { PairingTokenManager } from '@pellux/goodvibes-sdk/platform/pairing';
|
|
12
12
|
import { resolvePairingWebOrigin } from '../core/pairing-origin.ts';
|
|
13
13
|
import { attachWsOnlyGatewayVerbHandlers } from '@pellux/goodvibes-terminal-shell';
|
|
14
|
+
import { createDisposalScope, registerSurfaceRuntimePollers } from './disposal-wiring.ts';
|
|
14
15
|
import { WatcherRegistry } from '@pellux/goodvibes-sdk/platform/watchers';
|
|
15
16
|
import { ArtifactStore } from '@pellux/goodvibes-sdk/platform/artifacts';
|
|
16
17
|
import { createWebKnowledgeGapRepairer } from '@pellux/goodvibes-sdk/platform/knowledge';
|
|
@@ -36,8 +37,7 @@ import type { DomainDispatch, RuntimeStore } from './store/index.ts';
|
|
|
36
37
|
import {
|
|
37
38
|
type RuntimeEventBus, DistributedRuntimeManager, RemoteRunnerRegistry, RemoteSupervisor, IntegrationHelperService,
|
|
38
39
|
IdempotencyStore, ComponentHealthMonitor, WorktreeRegistry, SandboxSessionRegistry, createShellPathService,
|
|
39
|
-
type ShellPathService, type FeatureFlagManager, createFeatureFlagManager, PolicyRuntimeState,
|
|
40
|
-
type SessionSurface,
|
|
40
|
+
type ShellPathService, type FeatureFlagManager, createFeatureFlagManager, PolicyRuntimeState, type SessionSurface,
|
|
41
41
|
} from '@/runtime/index.ts';
|
|
42
42
|
import { createSessionStorageServices } from './session-storage-services.ts';
|
|
43
43
|
import { VoiceProviderRegistry, VoiceService, ensureBuiltinVoiceProviders } from '@pellux/goodvibes-sdk/platform/voice';
|
|
@@ -55,6 +55,7 @@ import { SessionManager, CrossSessionTaskRegistry, SessionChangeTracker } from '
|
|
|
55
55
|
import { ApiTokenAuditor, UserAuthManager } from '@pellux/goodvibes-sdk/platform/security';
|
|
56
56
|
import { WebhookNotifier } from '@pellux/goodvibes-sdk/platform/integrations';
|
|
57
57
|
import { McpRegistry } from '@pellux/goodvibes-sdk/platform/mcp';
|
|
58
|
+
import { createRemoteExecutionServices } from './remote-execution-composition.ts';
|
|
58
59
|
import { BenchmarkStore, CacheHitTracker, FavoritesStore, ModelLimitsService, ProviderCapabilityRegistry, ProviderOptimizer, ProviderRegistry } from '@pellux/goodvibes-sdk/platform/providers';
|
|
59
60
|
import { KeybindingsManager } from '../input/keybindings.ts';
|
|
60
61
|
import { AdaptivePlanner, DeterministicReplayEngine, ExecutionPlanManager, SessionLineageTracker, SessionMemoryStore } from '@pellux/goodvibes-sdk/platform/core';
|
|
@@ -67,16 +68,10 @@ import { createWorkstreamServices, type OrchestrationEngine, type WorkstreamComm
|
|
|
67
68
|
import { wireFleetNeedsInputPush } from './fleet-needs-input-push.ts';
|
|
68
69
|
import { codeIndexDbPath, createCodeIndexServices, createStoreRerooter, isCodeInjectionSettingEnabled } from './code-index-services.ts';
|
|
69
70
|
import type { WorkPlanStore } from '../work-plans/work-plan-store.ts';
|
|
70
|
-
import {
|
|
71
|
-
import
|
|
72
|
-
import {
|
|
73
|
-
import {
|
|
74
|
-
import { registerInboxMethods } from '../daemon/handlers/inbox/index.ts';
|
|
75
|
-
import { registerTriagedInbox } from '../daemon/handlers/triage/index.ts';
|
|
76
|
-
import { registerDraftMethods } from '../daemon/handlers/drafts/index.ts';
|
|
77
|
-
import { registerCalendar } from '../daemon/handlers/calendar/index.ts';
|
|
78
|
-
import { registerEmailMethods } from '../daemon/handlers/email/index.ts';
|
|
79
|
-
import { registerRemoteSurface } from '../daemon/handlers/remote/index.ts';
|
|
71
|
+
import type { DaemonHandlerSurfaces } from '../daemon/handlers/index.ts';
|
|
72
|
+
import { createDaemonHandlerComposition } from './daemon-handler-composition.ts';
|
|
73
|
+
import { createClusterServices, startClusterServices, type ClusterGroupComposition } from './cluster-group-composition.ts';
|
|
74
|
+
import type { ClusterCoordinator } from '@pellux/goodvibes-sdk/platform/cluster';
|
|
80
75
|
import { WorkspaceTrustManager } from './trust/workspace-trust.ts';
|
|
81
76
|
import { ensureConfiguredModelIsRoutable } from './provider-fallback.ts';
|
|
82
77
|
|
|
@@ -184,6 +179,12 @@ export interface RuntimeServices {
|
|
|
184
179
|
readonly toolLLM: ToolLLM;
|
|
185
180
|
readonly distributedRuntime: DistributedRuntimeManager;
|
|
186
181
|
readonly daemonHandlers: DaemonHandlerSurfaces;
|
|
182
|
+
/** Elects the one node on this network that consumes inbound messages; hand it to the DaemonServer so its consumers share this leadership instead of holding a second election. */
|
|
183
|
+
readonly clusterCoordinator: ClusterCoordinator;
|
|
184
|
+
/** LAN group membership: identity, keys, roster, and the `cluster` verbs. */
|
|
185
|
+
readonly clusterGroup: ClusterGroupComposition;
|
|
186
|
+
/** Start the group layer and then the election, in that order. Idempotent. */
|
|
187
|
+
readonly startCluster: () => Promise<void>;
|
|
187
188
|
readonly remoteRunnerRegistry: RemoteRunnerRegistry;
|
|
188
189
|
readonly remoteSupervisor: RemoteSupervisor;
|
|
189
190
|
readonly sessionMemoryStore: SessionMemoryStore;
|
|
@@ -231,10 +232,11 @@ export interface RuntimeServices {
|
|
|
231
232
|
readonly integrationHelpers: IntegrationHelperService;
|
|
232
233
|
/** Re-root path-bound stores (MemoryStore, ProjectIndex) to a new working directory, called by WorkspaceSwapManager after verification; stores needing a process restart just warn-log and keep serving the old path until the daemon restarts with the new --working-dir. */
|
|
233
234
|
rerootStores(newWorkingDir: string): Promise<void>;
|
|
235
|
+
dispose(): void; // Stop every poller this graph started; best-effort, total, idempotent. This surface owns its graph — see disposal-wiring.ts.
|
|
234
236
|
}
|
|
235
237
|
|
|
236
238
|
export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeServices {
|
|
237
|
-
const workingDirectory = options.workingDir;
|
|
239
|
+
const disposalScope = createDisposalScope('RuntimeServices'); const workingDirectory = options.workingDir; // disposal seam: see ./disposal-wiring.ts
|
|
238
240
|
const homeDirectory = options.homeDirectory;
|
|
239
241
|
const shellPaths = createShellPathService({
|
|
240
242
|
workingDirectory,
|
|
@@ -382,6 +384,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
382
384
|
routeBindings,
|
|
383
385
|
agentStatusProvider: agentManager,
|
|
384
386
|
messageSender: agentMessageBus,
|
|
387
|
+
conversationGateConfig: configManager, // without this the gate runs on DEFAULTS: an inbound message landing in a live session takes the handover and starts work whatever conversationGate.mode/gatedSurfaces say
|
|
385
388
|
});
|
|
386
389
|
sessionBroker.setContinuationRunner(async ({ task, input }) => {
|
|
387
390
|
const record = agentManager.spawn({
|
|
@@ -418,6 +421,12 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
418
421
|
const memorySpine = new MemorySpineClient({ local: createLocalMemoryAccess(memoryRegistry) });
|
|
419
422
|
const deliveryManager = new AutomationDeliveryManager({
|
|
420
423
|
configManager,
|
|
424
|
+
// This manager builds the delivery router the daemon actually replies
|
|
425
|
+
// through (bootstrap.ts hands it to the daemon facade). Without the
|
|
426
|
+
// secrets manager it cannot resolve a goodvibes://secrets/... credential,
|
|
427
|
+
// so Telegram accepted every inbound message and dropped every reply with
|
|
428
|
+
// "Missing Telegram bot token" while ntfy — which needs no secret — worked.
|
|
429
|
+
secretsManager,
|
|
421
430
|
serviceRegistry,
|
|
422
431
|
runtimeBus: options.runtimeBus,
|
|
423
432
|
runtimeStore: options.runtimeStore,
|
|
@@ -497,43 +506,30 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
497
506
|
automationBridge: automationManager,
|
|
498
507
|
});
|
|
499
508
|
|
|
500
|
-
//
|
|
501
|
-
//
|
|
502
|
-
//
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
credentials: createDaemonCredentialStore(secretsManager),
|
|
509
|
+
// Which machines on this network are "us", and which of them reads the
|
|
510
|
+
// shared inbox. Both inert until startCluster() — no socket, no key material
|
|
511
|
+
// read; see cluster-group-composition.ts for why they are built together.
|
|
512
|
+
const { clusterGroup, clusterCoordinator } = createClusterServices({
|
|
513
|
+
configManager, shellPaths, secretsManager,
|
|
514
|
+
});
|
|
515
|
+
// Daemon handler surfaces (see daemon-handler-composition.ts); the inbox
|
|
516
|
+
// poller registers itself with the coordinator rather than starting eagerly.
|
|
517
|
+
const daemonHandlers = createDaemonHandlerComposition({
|
|
518
|
+
gatewayMethods,
|
|
519
|
+
secretsManager,
|
|
512
520
|
configManager,
|
|
513
521
|
workingDirectory,
|
|
514
522
|
homeDirectory,
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
const daemonHandlers = registerDaemonHandlers(handlerContext, {
|
|
518
|
-
registerRouting,
|
|
519
|
-
registerInbox: (ctx, routing) =>
|
|
520
|
-
registerTriagedInbox(ctx, (inboxCtx) => registerInboxMethods(inboxCtx, routing))
|
|
521
|
-
.unregister,
|
|
522
|
-
registerDrafts: (ctx) => registerDraftMethods(ctx),
|
|
523
|
-
registerCalendar,
|
|
524
|
-
registerEmail: (ctx) => registerEmailMethods(ctx),
|
|
525
|
-
registerRemote: (ctx) => registerRemoteSurface(ctx, { manager: distributedRuntime }),
|
|
523
|
+
distributedRuntime,
|
|
524
|
+
clusterCoordinator,
|
|
526
525
|
});
|
|
527
526
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
const sandboxSessionRegistry
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
});
|
|
535
|
-
mcpRegistry.setRuntimeBus(options.runtimeBus);
|
|
536
|
-
mcpRegistry.setSandboxRuntime(configManager, sandboxSessionRegistry);
|
|
527
|
+
// Remote runners and the sandboxes tool calls are confined to; see
|
|
528
|
+
// remote-execution-composition.ts for why the four are built as one.
|
|
529
|
+
const { remoteRunnerRegistry, remoteSupervisor, sandboxSessionRegistry, mcpRegistry }
|
|
530
|
+
= createRemoteExecutionServices({
|
|
531
|
+
agentManager, workingDirectory, hookDispatcher, configManager, runtimeBus: options.runtimeBus,
|
|
532
|
+
});
|
|
537
533
|
const tokenAuditor = new ApiTokenAuditor({ managed: false });
|
|
538
534
|
const componentHealthMonitor = new ComponentHealthMonitor();
|
|
539
535
|
const worktreeRegistry = new WorktreeRegistry(workingDirectory);
|
|
@@ -544,8 +540,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
544
540
|
bindProviderOptimizerFeatureFlag(featureFlags, providerOptimizer);
|
|
545
541
|
applyProviderOptimizerConfigMode(configManager, providerOptimizer);
|
|
546
542
|
const sessionMemoryStore = new SessionMemoryStore();
|
|
547
|
-
const sessionLineageTracker = new SessionLineageTracker();
|
|
548
|
-
const sessionChangeTracker = new SessionChangeTracker();
|
|
543
|
+
const sessionLineageTracker = new SessionLineageTracker(); const sessionChangeTracker = new SessionChangeTracker();
|
|
549
544
|
const planManager = new ExecutionPlanManager(workingDirectory);
|
|
550
545
|
const adaptivePlanner = new AdaptivePlanner();
|
|
551
546
|
const idempotencyStore = new IdempotencyStore();
|
|
@@ -572,7 +567,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
572
567
|
// code-index-services.ts's header doc.
|
|
573
568
|
const { codeIndexStore, codeIndexReindexScheduler } = createCodeIndexServices({ workingDirectory, configManager, memoryEmbeddingRegistry, isReindexPaused: () => pauseController.isPaused('code-index-reindex'), admitExpensiveWork });
|
|
574
569
|
// Store snapshots, the periodic append-only sweep, durable remembered-approval rules + the live credential chain — see durability-services.ts.
|
|
575
|
-
const { storeSnapshotScheduler, appendOnlyRetentionScheduler, userPermissionRuleStore, stopDurabilityHousekeeping } = createDurabilityServices({
|
|
570
|
+
const { storeSnapshotScheduler, appendOnlyRetentionScheduler, userPermissionRuleStore, stopDurabilityHousekeeping, stopConfigWatch } = createDurabilityServices({
|
|
576
571
|
configManager, secretsManager, providerRegistry, memoryDbPath, codeIndexDbPath: codeIndexDbPath(workingDirectory), surface, shellPaths, // + retention-sweep roots & live config watch (mirrors the SDK)
|
|
577
572
|
...(options.currentSessionId ? { currentSessionId: options.currentSessionId } : {}), // exempts the running session from crash-residue reaping
|
|
578
573
|
});
|
|
@@ -618,7 +613,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
618
613
|
const { voiceSetup } = wireVoiceSetup({ configManager, shellPaths, voiceProviders, admitExpensiveWork });
|
|
619
614
|
|
|
620
615
|
// Terminal-shell wrapper over the SDK registerGatewayVerbGroups (gateway-verbs.ts); checkin.*/fleet-needs-input/pairing.* register only when their deps are present. memoryGovernor lights up ops.memory.get; voiceSetup lights up voice.local.status/install.
|
|
621
|
-
attachWsOnlyGatewayVerbHandlers(gatewayMethods, { processRegistry, workspaceCheckpointManager, conversationRewindPort: createSessionConversationRewindPort(), sessionBroker, secretsManager, stepUpService, approvalBroker, requestApproval: (input) => approvalBroker.requestApproval(input), watcherRegistry, userPermissionRuleStore, shellPaths, configManager, runtimeStore: options.runtimeStore, channelDeliveryRouter, providerRegistry, automationManager, sessionLister: sessionBroker, sessionIntake: sessionBroker, workingDirectory, memoryRegistry, pairingTokens, sessionLiveTurnControls, powerManager, memoryGovernor, voiceSetup, relayAvailable: () => configManager.get('relay.enabled') === true, pairingWebOrigin: () => resolvePairingWebOrigin(configManager).origin, ...wireFleetNeedsInputPush({ registry: processRegistry, runtimeBus: options.runtimeBus, sessionBroker }) });
|
|
616
|
+
attachWsOnlyGatewayVerbHandlers(gatewayMethods, { processRegistry, workspaceCheckpointManager, conversationRewindPort: createSessionConversationRewindPort(), sessionBroker, secretsManager, stepUpService, approvalBroker, requestApproval: (input) => approvalBroker.requestApproval(input), watcherRegistry, userPermissionRuleStore, shellPaths, configManager, runtimeStore: options.runtimeStore, channelDeliveryRouter, providerRegistry, automationManager, sessionLister: sessionBroker, sessionIntake: sessionBroker, workingDirectory, memoryRegistry, pairingTokens, sessionLiveTurnControls, powerManager, memoryGovernor, voiceSetup, relayAvailable: () => configManager.get('relay.enabled') === true, pairingWebOrigin: () => resolvePairingWebOrigin(configManager).origin, disposal: disposalScope.registry, ...wireFleetNeedsInputPush({ registry: processRegistry, runtimeBus: options.runtimeBus, sessionBroker }) });
|
|
622
617
|
const integrationHelpers = new IntegrationHelperService({
|
|
623
618
|
surface, // surface-scoped: continuity's recovery-file check must read the SAME paths the app writes with, not the unscoped legacy pair.
|
|
624
619
|
runtimeStore: options.runtimeStore,
|
|
@@ -684,7 +679,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
684
679
|
// bridge (the high-churn 'ops' domain stays out of the wholesale allowlist).
|
|
685
680
|
wireMemoryPressureNotice(options.runtimeBus, notificationDispatcher);
|
|
686
681
|
|
|
687
|
-
|
|
682
|
+
const services: RuntimeServices = {
|
|
688
683
|
workingDirectory,
|
|
689
684
|
homeDirectory,
|
|
690
685
|
surface,
|
|
@@ -762,6 +757,9 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
762
757
|
toolLLM,
|
|
763
758
|
distributedRuntime,
|
|
764
759
|
daemonHandlers,
|
|
760
|
+
clusterCoordinator,
|
|
761
|
+
clusterGroup,
|
|
762
|
+
startCluster: () => startClusterServices({ clusterGroup, clusterCoordinator }),
|
|
765
763
|
remoteRunnerRegistry,
|
|
766
764
|
remoteSupervisor,
|
|
767
765
|
sessionMemoryStore,
|
|
@@ -796,5 +794,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
796
794
|
workspaceCheckpointManager,
|
|
797
795
|
integrationHelpers,
|
|
798
796
|
rerootStores: createStoreRerooter({ codeIndexStore, projectIndex }),
|
|
797
|
+
dispose: (): void => disposalScope.dispose(),
|
|
799
798
|
};
|
|
799
|
+
registerSurfaceRuntimePollers(disposalScope.registry, services, { stopConfigWatch }); return services;
|
|
800
800
|
}
|
|
@@ -206,9 +206,47 @@ const ENABLEMENT_KEYS_BEHAVIOR_VERIFIED = new Set(
|
|
|
206
206
|
).size;
|
|
207
207
|
|
|
208
208
|
/** Settings with real local behavior verification: the authored baseline plus the persistence-tested feature-knob, device/trigger, and enablement keys. */
|
|
209
|
+
/**
|
|
210
|
+
* Config keys added by the LAN group-key layer: the automatic group-key
|
|
211
|
+
* rotation interval, the dual-generation acceptance window around a rotation,
|
|
212
|
+
* the discovery beacon interval, and the roster gossip interval.
|
|
213
|
+
*
|
|
214
|
+
* THIS CONSTANT IS NOT A DIAL, for the same reason as the two above. Each key
|
|
215
|
+
* is counted because a test that exercises it was actually written:
|
|
216
|
+
* `src/test/verification/cluster-group-settings-persistence.test.ts` runs the
|
|
217
|
+
* same four-part persistence contract — schema default exposure, `set()`
|
|
218
|
+
* through the key's own validator to disk, reload into a fresh ConfigManager
|
|
219
|
+
* with read-back equality, and reset-to-default that survives reload.
|
|
220
|
+
*
|
|
221
|
+
* PER-KEY EVIDENCE. All four have a LIVE consumer in this build, which is more
|
|
222
|
+
* than several of the keys counted above can claim:
|
|
223
|
+
* cluster.keyRotationHours — read by resolveClusterGroupSettings and
|
|
224
|
+
* compared against the current key's age in
|
|
225
|
+
* the group runtime's rotation check.
|
|
226
|
+
* cluster.keyRotationGraceMinutes — sets how long the previous generation
|
|
227
|
+
* stays accepted after a scheduled
|
|
228
|
+
* rotation; drives the keyring's accepted
|
|
229
|
+
* generation set.
|
|
230
|
+
* cluster.beaconSeconds — the discovery beacon timer interval, and
|
|
231
|
+
* the basis of the "recently heard from"
|
|
232
|
+
* window that decides which member mints a
|
|
233
|
+
* rotation.
|
|
234
|
+
* cluster.rosterGossipSeconds — how often the member list is shared.
|
|
235
|
+
*
|
|
236
|
+
* `cluster.enabled` is NOT here: it is a feature enablement key and the ledger
|
|
237
|
+
* counts those in its own set.
|
|
238
|
+
*/
|
|
239
|
+
export const CLUSTER_GROUP_LOCAL_SETTINGS = [
|
|
240
|
+
'cluster.keyRotationHours',
|
|
241
|
+
'cluster.keyRotationGraceMinutes',
|
|
242
|
+
'cluster.beaconSeconds',
|
|
243
|
+
'cluster.rosterGossipSeconds',
|
|
244
|
+
] as const;
|
|
245
|
+
|
|
209
246
|
const SETTINGS_BEHAVIOR_VERIFIED = SETTINGS_BEHAVIOR_BASELINE
|
|
210
247
|
+ FEATURE_KNOB_LOCAL_SETTINGS.length
|
|
211
248
|
+ DEVICE_AND_TRIGGER_LOCAL_SETTINGS.length
|
|
249
|
+
+ CLUSTER_GROUP_LOCAL_SETTINGS.length
|
|
212
250
|
+ ENABLEMENT_KEYS_BEHAVIOR_VERIFIED;
|
|
213
251
|
|
|
214
252
|
const EXTERNAL_SLASH_COMMANDS = new Set([
|
package/src/version.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { join } from 'node:path';
|
|
|
6
6
|
// The prebuild script updates the fallback value before compilation.
|
|
7
7
|
// Uses import.meta.dir (Bun) to locate package.json relative to this file,
|
|
8
8
|
// which is correct regardless of the process working directory.
|
|
9
|
-
let _version = '1.
|
|
9
|
+
let _version = '1.24.0';
|
|
10
10
|
try {
|
|
11
11
|
const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8'));
|
|
12
12
|
// Only trust a version read from OUR OWN package.json. A Bun single-file
|