@open-mercato/cli 0.6.8-develop.7100.1.fbf66fca35 → 0.7.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/.turbo/turbo-build.log +1 -7
- package/dist/agentic/guides/module-facts.json +598 -5508
- package/dist/agentic/guides/module-facts.v2.json +598 -5594
- package/dist/agentic/guides/modules/ai_assistant/index.md +1 -1
- package/dist/agentic/guides/modules/api_docs/index.md +1 -1
- package/dist/agentic/guides/modules/api_keys/exact-override-targets.md +0 -1
- package/dist/agentic/guides/modules/api_keys/index.md +2 -4
- package/dist/agentic/guides/modules/attachments/di-registrations-rich.md +5 -6
- package/dist/agentic/guides/modules/attachments/di-service-tokens.md +4 -5
- package/dist/agentic/guides/modules/attachments/exact-override-targets.md +5 -6
- package/dist/agentic/guides/modules/attachments/index.md +2 -2
- package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
- package/dist/agentic/guides/modules/auth/di-registrations-rich.md +2 -3
- package/dist/agentic/guides/modules/auth/di-service-tokens.md +2 -3
- package/dist/agentic/guides/modules/auth/exact-override-targets.md +2 -3
- package/dist/agentic/guides/modules/auth/index.md +1 -1
- package/dist/agentic/guides/modules/business_rules/index.md +1 -1
- package/dist/agentic/guides/modules/catalog/incoming-installed-contributions.md +0 -3
- package/dist/agentic/guides/modules/catalog/index.md +2 -2
- package/dist/agentic/guides/modules/channel_apns/index.md +1 -1
- package/dist/agentic/guides/modules/channel_expo/index.md +1 -1
- package/dist/agentic/guides/modules/channel_fcm/index.md +1 -1
- package/dist/agentic/guides/modules/channel_gmail/index.md +1 -1
- package/dist/agentic/guides/modules/channel_imap/index.md +1 -1
- package/dist/agentic/guides/modules/checkout/index.md +1 -1
- package/dist/agentic/guides/modules/communication_channels/di-registrations-rich.md +8 -9
- package/dist/agentic/guides/modules/communication_channels/exact-override-targets.md +8 -9
- package/dist/agentic/guides/modules/communication_channels/incoming-installed-contributions.md +0 -2
- package/dist/agentic/guides/modules/communication_channels/index.md +3 -3
- package/dist/agentic/guides/modules/configs/index.md +1 -1
- package/dist/agentic/guides/modules/content/index.md +1 -1
- package/dist/agentic/guides/modules/currencies/index.md +1 -1
- package/dist/agentic/guides/modules/customer_accounts/index.md +1 -1
- package/dist/agentic/guides/modules/customers/active-extension-bindings.md +3 -6
- package/dist/agentic/guides/modules/customers/contribution-resolutions.md +0 -1
- package/dist/agentic/guides/modules/customers/events.md +1 -2
- package/dist/agentic/guides/modules/customers/incoming-installed-contributions.md +0 -7
- package/dist/agentic/guides/modules/customers/index.md +4 -4
- package/dist/agentic/guides/modules/customers/umes-contributions.md +0 -1
- package/dist/agentic/guides/modules/customers/umes-hosts.md +0 -1
- package/dist/agentic/guides/modules/dashboards/index.md +1 -1
- package/dist/agentic/guides/modules/data_sync/exact-override-targets.md +2 -2
- package/dist/agentic/guides/modules/data_sync/index.md +1 -1
- package/dist/agentic/guides/modules/data_sync/workers.md +2 -2
- package/dist/agentic/guides/modules/design_system/index.md +1 -1
- package/dist/agentic/guides/modules/devices/index.md +1 -1
- package/dist/agentic/guides/modules/dictionaries/index.md +1 -1
- package/dist/agentic/guides/modules/directory/exact-override-targets.md +0 -2
- package/dist/agentic/guides/modules/directory/index.md +3 -5
- package/dist/agentic/guides/modules/entities/index.md +1 -1
- package/dist/agentic/guides/modules/eudr/index.md +1 -1
- package/dist/agentic/guides/modules/events/index.md +1 -1
- package/dist/agentic/guides/modules/feature_toggles/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe/exact-override-targets.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe/workers.md +1 -1
- package/dist/agentic/guides/modules/generators/index.md +1 -1
- package/dist/agentic/guides/modules/inbox_ops/index.md +1 -1
- package/dist/agentic/guides/modules/integrations/index.md +1 -1
- package/dist/agentic/guides/modules/messages/index.md +1 -1
- package/dist/agentic/guides/modules/notifications/index.md +1 -1
- package/dist/agentic/guides/modules/onboarding/index.md +1 -1
- package/dist/agentic/guides/modules/payment_gateways/index.md +1 -1
- package/dist/agentic/guides/modules/perspectives/index.md +1 -1
- package/dist/agentic/guides/modules/planner/index.md +1 -1
- package/dist/agentic/guides/modules/portal/index.md +1 -1
- package/dist/agentic/guides/modules/progress/index.md +1 -1
- package/dist/agentic/guides/modules/push_notifications/index.md +1 -1
- package/dist/agentic/guides/modules/query_index/index.md +1 -1
- package/dist/agentic/guides/modules/record_locks/index.md +1 -1
- package/dist/agentic/guides/modules/resources/index.md +1 -1
- package/dist/agentic/guides/modules/sales/active-extension-bindings.md +0 -1
- package/dist/agentic/guides/modules/sales/contribution-resolutions.md +0 -1
- package/dist/agentic/guides/modules/sales/exact-override-targets.md +4 -5
- package/dist/agentic/guides/modules/sales/host-extension-points.md +1 -1
- package/dist/agentic/guides/modules/sales/incoming-installed-contributions.md +0 -2
- package/dist/agentic/guides/modules/sales/index.md +3 -3
- package/dist/agentic/guides/modules/sales/setup.md +1 -1
- package/dist/agentic/guides/modules/sales/umes-contributions.md +0 -1
- package/dist/agentic/guides/modules/sales/umes-diagnostics.md +0 -1
- package/dist/agentic/guides/modules/sales/umes-hosts.md +0 -9
- package/dist/agentic/guides/modules/scheduler/cli-commands.md +0 -1
- package/dist/agentic/guides/modules/scheduler/exact-override-targets.md +1 -3
- package/dist/agentic/guides/modules/scheduler/index.md +2 -2
- package/dist/agentic/guides/modules/scheduler/workers.md +1 -2
- package/dist/agentic/guides/modules/search/index.md +1 -1
- package/dist/agentic/guides/modules/security/index.md +1 -1
- package/dist/agentic/guides/modules/security/owned-contract-module-metadata.md +1 -1
- package/dist/agentic/guides/modules/shipping_carriers/index.md +1 -1
- package/dist/agentic/guides/modules/sso/index.md +1 -1
- package/dist/agentic/guides/modules/staff/index.md +1 -1
- package/dist/agentic/guides/modules/storage_s3/index.md +1 -1
- package/dist/agentic/guides/modules/sync_akeneo/index.md +1 -1
- package/dist/agentic/guides/modules/sync_excel/index.md +1 -1
- package/dist/agentic/guides/modules/system_status_overlays/index.md +1 -1
- package/dist/agentic/guides/modules/translations/index.md +1 -1
- package/dist/agentic/guides/modules/warranty_claims/index.md +1 -1
- package/dist/agentic/guides/modules/webhooks/index.md +1 -1
- package/dist/agentic/guides/modules/wms/index.md +1 -1
- package/dist/agentic/guides/modules/workflows/index.md +1 -1
- package/dist/agentic/guides/reference-module-facts.json +2 -2
- package/dist/agentic/guides/reference-modules/example/index.md +1 -1
- package/dist/agentic/guides/upstream/manifest.json +1 -1
- package/dist/agentic/shared/AGENTS.md.template +3 -3
- package/dist/agentic/shared/ai/harness/README.md +2 -2
- package/dist/agentic/shared/ai/harness/RELEASE.md +6 -8
- package/dist/agentic/shared/ai/harness/cases.json +0 -83
- package/dist/agentic/shared/ai/harness/cases.schema.json +4 -4
- package/dist/agentic/shared/ai/harness/validators.json +1 -1
- package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.7-to-0.7.0/SKILL.md +12 -3
- package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +11 -37
- package/dist/lib/generators/ast/index.js +1 -4
- package/dist/lib/generators/ast/index.js.map +2 -2
- package/dist/lib/generators/ast/source-file.js +1 -8
- package/dist/lib/generators/ast/source-file.js.map +2 -2
- package/dist/lib/generators/ast/writers.js +1 -9
- package/dist/lib/generators/ast/writers.js.map +2 -2
- package/dist/lib/generators/module-registry.js +189 -424
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/generators/route-manifest-shards.js +1 -4
- package/dist/lib/generators/route-manifest-shards.js.map +2 -2
- package/dist/lib/spawn.js +2 -3
- package/dist/lib/spawn.js.map +2 -2
- package/dist/lib/testing/integration.js +24 -162
- package/dist/lib/testing/integration.js.map +2 -2
- package/dist/mercato.js +0 -14
- package/dist/mercato.js.map +2 -2
- package/package.json +7 -8
- package/src/lib/__tests__/spawn.test.ts +0 -23
- package/src/lib/generators/__tests__/metadata-extraction.test.ts +0 -44
- package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +8 -32
- package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +1 -4
- package/src/lib/generators/__tests__/module-facts.extension-hosts.test.ts +1 -1
- package/src/lib/generators/__tests__/module-subset.test.ts +72 -96
- package/src/lib/generators/__tests__/output-snapshots.test.ts +1 -1
- package/src/lib/generators/__tests__/route-manifest-shards.test.ts +0 -15
- package/src/lib/generators/__tests__/structural-contracts.test.ts +3 -7
- package/src/lib/generators/ast/index.ts +1 -2
- package/src/lib/generators/ast/source-file.ts +0 -13
- package/src/lib/generators/ast/writers.ts +1 -26
- package/src/lib/generators/module-registry.ts +227 -534
- package/src/lib/generators/route-manifest-shards.ts +1 -8
- package/src/lib/spawn.ts +4 -5
- package/src/lib/testing/__tests__/integration.test.ts +0 -435
- package/src/lib/testing/integration.ts +32 -254
- package/src/mercato.ts +0 -27
- package/dist/agentic/guides/modules/api_keys/di-registrations-rich.md +0 -11
- package/dist/agentic/guides/modules/api_keys/di-service-tokens.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/acl-features.md +0 -13
- package/dist/agentic/guides/modules/channel_discord/ai-agents.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/backend-pages.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/cli-commands.md +0 -13
- package/dist/agentic/guides/modules/channel_discord/contribution-resolutions.md +0 -14
- package/dist/agentic/guides/modules/channel_discord/di-registrations-rich.md +0 -12
- package/dist/agentic/guides/modules/channel_discord/exact-override-targets.md +0 -26
- package/dist/agentic/guides/modules/channel_discord/index.md +0 -22
- package/dist/agentic/guides/modules/channel_discord/owned-contract-module-metadata.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/setup.md +0 -11
- package/dist/agentic/guides/modules/channel_discord/umes-contributions.md +0 -14
- package/dist/agentic/guides/modules/channel_discord/workers.md +0 -12
- package/dist/agentic/guides/modules/directory/di-registrations-rich.md +0 -12
- package/dist/agentic/guides/modules/directory/di-service-tokens.md +0 -12
- package/dist/agentic/guides/modules/documents/acl-features.md +0 -17
- package/dist/agentic/guides/modules/documents/backend-pages.md +0 -13
- package/dist/agentic/guides/modules/documents/contribution-resolutions.md +0 -27
- package/dist/agentic/guides/modules/documents/di-registrations-rich.md +0 -21
- package/dist/agentic/guides/modules/documents/domain-commands.md +0 -37
- package/dist/agentic/guides/modules/documents/encryption.md +0 -11
- package/dist/agentic/guides/modules/documents/entities.md +0 -21
- package/dist/agentic/guides/modules/documents/events.md +0 -25
- package/dist/agentic/guides/modules/documents/exact-override-targets.md +0 -39
- package/dist/agentic/guides/modules/documents/index.md +0 -25
- package/dist/agentic/guides/modules/documents/notifications.md +0 -13
- package/dist/agentic/guides/modules/documents/owned-contract-module-metadata.md +0 -11
- package/dist/agentic/guides/modules/documents/setup.md +0 -11
- package/dist/agentic/guides/modules/documents/umes-contributions.md +0 -27
- package/dist/agentic/guides/modules/documents/umes-hosts.md +0 -36
- package/src/__tests__/resolve-queue-abandon-hook.test.ts +0 -39
- package/src/lib/generators/__tests__/__snapshots__/bootstrap-registrations.test.ts.snap +0 -14
- package/src/lib/generators/__tests__/__snapshots__/command-loaders.test.ts.snap +0 -23
- package/src/lib/generators/__tests__/ast-writers-escaping.test.ts +0 -64
- package/src/lib/generators/__tests__/bootstrap-registrations.test.ts +0 -176
- package/src/lib/generators/__tests__/command-loaders.test.ts +0 -239
- package/src/lib/generators/__tests__/generated-registry-imports.test.ts +0 -128
- package/src/lib/generators/__tests__/registry-variant-parity.test.ts +0 -258
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ChildProcess, StdioOptions } from 'node:child_process'
|
|
2
|
-
import { spawnSync } from 'node:child_process'
|
|
3
2
|
import { createServer } from 'node:net'
|
|
4
3
|
import { existsSync, readFileSync } from 'node:fs'
|
|
5
4
|
import { mkdir, readdir, readFile, rm, stat, writeFile } from 'node:fs/promises'
|
|
@@ -763,56 +762,23 @@ function runNpxCommand(args: string[], environment: NodeJS.ProcessEnv): Promise<
|
|
|
763
762
|
})
|
|
764
763
|
}
|
|
765
764
|
|
|
766
|
-
export type CapturedOutputProcess = ChildProcess & {
|
|
767
|
-
readCapturedOutput?: () => string
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
export const CAPTURED_OUTPUT_MAX_LENGTH = 64 * 1024
|
|
771
|
-
|
|
772
|
-
export function createBoundedOutputBuffer(): { append: (chunk: Buffer | string) => void; read: () => string } {
|
|
773
|
-
let buffered = ''
|
|
774
|
-
return {
|
|
775
|
-
append: (chunk: Buffer | string) => {
|
|
776
|
-
buffered += chunk.toString()
|
|
777
|
-
if (buffered.length > CAPTURED_OUTPUT_MAX_LENGTH) {
|
|
778
|
-
buffered = `…(truncated)…${buffered.slice(-CAPTURED_OUTPUT_MAX_LENGTH)}`
|
|
779
|
-
}
|
|
780
|
-
},
|
|
781
|
-
read: () => buffered,
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
// Both streams are returned when both carry output: a single stderr deprecation notice must not
|
|
786
|
-
// hide the stdout tail that usually holds the real startup failure. The 20-line tail in
|
|
787
|
-
// `exitError()` does the trimming.
|
|
788
|
-
export function formatCapturedOutput(stderrText: string, stdoutText: string): string {
|
|
789
|
-
if (stderrText && stdoutText) {
|
|
790
|
-
return `--- stderr ---\n${stderrText}\n--- stdout ---\n${stdoutText}`
|
|
791
|
-
}
|
|
792
|
-
return stderrText || stdoutText
|
|
793
|
-
}
|
|
794
|
-
|
|
795
765
|
function startYarnRawCommand(
|
|
796
766
|
commandArgs: string[],
|
|
797
767
|
environment: NodeJS.ProcessEnv,
|
|
798
|
-
opts: { silent?: boolean
|
|
768
|
+
opts: { silent?: boolean } = {},
|
|
799
769
|
cwd: string = projectRootDirectory,
|
|
800
|
-
):
|
|
770
|
+
): ChildProcess {
|
|
801
771
|
const outputMode: StdioOptions = opts.silent ? ['ignore', 'pipe', 'pipe'] : 'inherit'
|
|
802
|
-
const resolvedSpawn = resolveSpawnCommand(resolveYarnBinary(), commandArgs
|
|
803
|
-
const processHandle:
|
|
772
|
+
const resolvedSpawn = resolveSpawnCommand(resolveYarnBinary(), commandArgs)
|
|
773
|
+
const processHandle: ChildProcess = spawn(resolvedSpawn.command, resolvedSpawn.args, {
|
|
804
774
|
cwd,
|
|
805
775
|
env: environment,
|
|
806
776
|
stdio: outputMode,
|
|
807
777
|
...resolvedSpawn.spawnOptions,
|
|
808
778
|
})
|
|
809
779
|
if (opts.silent) {
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
processHandle.stdout?.on('data', (chunk: Buffer | string) => stdoutBuffer.append(chunk))
|
|
813
|
-
processHandle.stderr?.on('data', (chunk: Buffer | string) => stderrBuffer.append(chunk))
|
|
814
|
-
processHandle.readCapturedOutput = () =>
|
|
815
|
-
formatCapturedOutput(stderrBuffer.read().trim(), stdoutBuffer.read().trim())
|
|
780
|
+
processHandle.stdout?.on('data', () => {})
|
|
781
|
+
processHandle.stderr?.on('data', () => {})
|
|
816
782
|
}
|
|
817
783
|
return processHandle
|
|
818
784
|
}
|
|
@@ -820,9 +786,9 @@ function startYarnRawCommand(
|
|
|
820
786
|
function startYarnCommand(
|
|
821
787
|
args: string[],
|
|
822
788
|
environment: NodeJS.ProcessEnv,
|
|
823
|
-
opts: { silent?: boolean
|
|
789
|
+
opts: { silent?: boolean } = {},
|
|
824
790
|
cwd: string = projectRootDirectory,
|
|
825
|
-
):
|
|
791
|
+
): ChildProcess {
|
|
826
792
|
return startYarnRawCommand(['run', ...args], environment, opts, cwd)
|
|
827
793
|
}
|
|
828
794
|
|
|
@@ -1802,172 +1768,6 @@ function isProcessRunning(processId: number): boolean {
|
|
|
1802
1768
|
}
|
|
1803
1769
|
}
|
|
1804
1770
|
|
|
1805
|
-
export type ProcessTreeKillDependencies = {
|
|
1806
|
-
platform?: NodeJS.Platform
|
|
1807
|
-
killPosixProcessGroup?: (pid: number, signal: NodeJS.Signals) => void
|
|
1808
|
-
killWindowsProcessTree?: (pid: number, options: { forced: boolean }) => void
|
|
1809
|
-
gracePeriodMs?: number
|
|
1810
|
-
}
|
|
1811
|
-
|
|
1812
|
-
function defaultKillPosixProcessGroup(pid: number, signal: NodeJS.Signals): void {
|
|
1813
|
-
process.kill(-pid, signal)
|
|
1814
|
-
}
|
|
1815
|
-
|
|
1816
|
-
// `/f` is added only on escalation so the Windows path mirrors the POSIX SIGTERM → grace → SIGKILL
|
|
1817
|
-
// sequence: the first attempt lets the tree shut down cleanly, the second forces it.
|
|
1818
|
-
function defaultKillWindowsProcessTree(pid: number, options: { forced: boolean }): void {
|
|
1819
|
-
spawnSync('taskkill', ['/pid', String(pid), '/t', ...(options.forced ? ['/f'] : [])])
|
|
1820
|
-
}
|
|
1821
|
-
|
|
1822
|
-
export function killProcessTree(
|
|
1823
|
-
pid: number,
|
|
1824
|
-
signal: NodeJS.Signals,
|
|
1825
|
-
dependencies: ProcessTreeKillDependencies = {},
|
|
1826
|
-
): void {
|
|
1827
|
-
const platform = dependencies.platform ?? process.platform
|
|
1828
|
-
if (platform === 'win32') {
|
|
1829
|
-
const killWindowsProcessTree = dependencies.killWindowsProcessTree ?? defaultKillWindowsProcessTree
|
|
1830
|
-
killWindowsProcessTree(pid, { forced: signal === 'SIGKILL' })
|
|
1831
|
-
return
|
|
1832
|
-
}
|
|
1833
|
-
const killPosixProcessGroup = dependencies.killPosixProcessGroup ?? defaultKillPosixProcessGroup
|
|
1834
|
-
killPosixProcessGroup(pid, signal)
|
|
1835
|
-
}
|
|
1836
|
-
|
|
1837
|
-
const PROCESS_TREE_KILL_GRACE_PERIOD_MS = 3_000
|
|
1838
|
-
|
|
1839
|
-
function killProcessTreeIfRunning(
|
|
1840
|
-
pid: number,
|
|
1841
|
-
signal: NodeJS.Signals,
|
|
1842
|
-
dependencies: ProcessTreeKillDependencies,
|
|
1843
|
-
): void {
|
|
1844
|
-
try {
|
|
1845
|
-
killProcessTree(pid, signal, dependencies)
|
|
1846
|
-
} catch (error) {
|
|
1847
|
-
if ((error as NodeJS.ErrnoException).code !== 'ESRCH') {
|
|
1848
|
-
throw error
|
|
1849
|
-
}
|
|
1850
|
-
}
|
|
1851
|
-
}
|
|
1852
|
-
|
|
1853
|
-
// `getProcessExitPromise` only observes *future* events, so a process that already exited would
|
|
1854
|
-
// never settle it and the caller would stall for the whole grace period. This waiter detaches both
|
|
1855
|
-
// listeners and clears the timer whichever way it settles, so nothing is left pending and a late
|
|
1856
|
-
// `'error'` cannot surface as an unhandled rejection.
|
|
1857
|
-
function waitForProcessExitWithin(childProcess: ChildProcess, timeoutMs: number): Promise<boolean> {
|
|
1858
|
-
return new Promise((resolve) => {
|
|
1859
|
-
const settle = (exited: boolean) => {
|
|
1860
|
-
clearTimeout(gracePeriodTimer)
|
|
1861
|
-
childProcess.off('exit', onExit)
|
|
1862
|
-
childProcess.off('error', onError)
|
|
1863
|
-
resolve(exited)
|
|
1864
|
-
}
|
|
1865
|
-
const onExit = () => settle(true)
|
|
1866
|
-
const onError = () => settle(false)
|
|
1867
|
-
const gracePeriodTimer = setTimeout(() => settle(false), timeoutMs)
|
|
1868
|
-
childProcess.on('exit', onExit)
|
|
1869
|
-
childProcess.on('error', onError)
|
|
1870
|
-
})
|
|
1871
|
-
}
|
|
1872
|
-
|
|
1873
|
-
// A `ChildProcess` reports `null` on both fields while it is alive, so a non-null value means the
|
|
1874
|
-
// exit has already happened and its `'exit'` event will never fire again.
|
|
1875
|
-
function hasProcessAlreadyExited(childProcess: ChildProcess): boolean {
|
|
1876
|
-
return (childProcess.exitCode ?? null) !== null || (childProcess.signalCode ?? null) !== null
|
|
1877
|
-
}
|
|
1878
|
-
|
|
1879
|
-
export async function terminateProcessTree(
|
|
1880
|
-
childProcess: CapturedOutputProcess,
|
|
1881
|
-
dependencies: ProcessTreeKillDependencies = {},
|
|
1882
|
-
): Promise<void> {
|
|
1883
|
-
const pid = childProcess.pid
|
|
1884
|
-
if (!pid) return
|
|
1885
|
-
// A reaped leader answers only "waiting for its `'exit'` event can never settle" — without this the
|
|
1886
|
-
// crash path would stall the whole teardown for the grace period waiting for an event that already
|
|
1887
|
-
// fired. It does *not* mean the process group is empty: on the readiness-failure path the `yarn`
|
|
1888
|
-
// wrapper exits non-zero while the `mercato start`/Next/worker descendants it spawned stay in its
|
|
1889
|
-
// group, so the group still has to be signalled or #5333's orphan survives verbatim. POSIX keeps
|
|
1890
|
-
// the group id reserved while any member holds it, so signalling it after the leader is reaped is
|
|
1891
|
-
// both safe and effective. Skip the wait, never the signal — and go straight to SIGKILL, since
|
|
1892
|
-
// there is no leader left to coordinate a graceful shutdown or to report the exit we would await.
|
|
1893
|
-
if (hasProcessAlreadyExited(childProcess)) {
|
|
1894
|
-
killProcessTreeIfRunning(pid, 'SIGKILL', dependencies)
|
|
1895
|
-
return
|
|
1896
|
-
}
|
|
1897
|
-
|
|
1898
|
-
killProcessTreeIfRunning(pid, 'SIGTERM', dependencies)
|
|
1899
|
-
|
|
1900
|
-
const gracePeriodMs = dependencies.gracePeriodMs ?? PROCESS_TREE_KILL_GRACE_PERIOD_MS
|
|
1901
|
-
const exitedBeforeGracePeriod = await waitForProcessExitWithin(childProcess, gracePeriodMs)
|
|
1902
|
-
|
|
1903
|
-
if (!exitedBeforeGracePeriod && isProcessRunning(pid)) {
|
|
1904
|
-
killProcessTreeIfRunning(pid, 'SIGKILL', dependencies)
|
|
1905
|
-
}
|
|
1906
|
-
}
|
|
1907
|
-
|
|
1908
|
-
const EPHEMERAL_SHUTDOWN_SIGNALS: NodeJS.Signals[] = ['SIGINT', 'SIGTERM']
|
|
1909
|
-
|
|
1910
|
-
export type ShutdownProcessRef = Pick<NodeJS.Process, 'once' | 'off' | 'removeAllListeners' | 'kill' | 'pid'>
|
|
1911
|
-
|
|
1912
|
-
export type EphemeralShutdownHandlers = { dispose: () => void }
|
|
1913
|
-
|
|
1914
|
-
// The application is spawned `detached: true`, which puts its whole tree in a new session. A
|
|
1915
|
-
// terminal Ctrl+C only reaches the foreground process group of the controlling terminal, so the
|
|
1916
|
-
// tree never sees the signal and would outlive the run holding `server-start.lock` — exactly the
|
|
1917
|
-
// orphan this harness exists to prevent. Node also skips `'exit'` listeners when it dies from a
|
|
1918
|
-
// signal, so the crash sweep cannot cover this path either. The runner therefore forwards the
|
|
1919
|
-
// interrupt itself: stop the environment, then re-raise the signal so the process still exits with
|
|
1920
|
-
// the conventional 130/143 instead of a synthetic success.
|
|
1921
|
-
export function registerEphemeralShutdownHandlers(options: {
|
|
1922
|
-
stop: () => Promise<void>
|
|
1923
|
-
killApplicationTree: () => void
|
|
1924
|
-
onSignal?: (signal: NodeJS.Signals) => void
|
|
1925
|
-
processRef?: ShutdownProcessRef
|
|
1926
|
-
}): EphemeralShutdownHandlers {
|
|
1927
|
-
const processRef = options.processRef ?? process
|
|
1928
|
-
const onProcessExit = () => options.killApplicationTree()
|
|
1929
|
-
const signalHandlers = new Map<NodeJS.Signals, () => void>()
|
|
1930
|
-
|
|
1931
|
-
// Registered per `startEphemeralEnvironment()` call, and the environment is restarted on retry,
|
|
1932
|
-
// so the handlers must come back off in `stop()` or a retried run stacks dead closures until it
|
|
1933
|
-
// trips MaxListenersExceededWarning.
|
|
1934
|
-
const dispose = () => {
|
|
1935
|
-
processRef.off('exit', onProcessExit)
|
|
1936
|
-
for (const [signal, handler] of signalHandlers) {
|
|
1937
|
-
processRef.off(signal, handler)
|
|
1938
|
-
}
|
|
1939
|
-
signalHandlers.clear()
|
|
1940
|
-
}
|
|
1941
|
-
|
|
1942
|
-
for (const signal of EPHEMERAL_SHUTDOWN_SIGNALS) {
|
|
1943
|
-
const handler = () => {
|
|
1944
|
-
void (async () => {
|
|
1945
|
-
options.onSignal?.(signal)
|
|
1946
|
-
try {
|
|
1947
|
-
await options.stop()
|
|
1948
|
-
} catch (error) {
|
|
1949
|
-
// A teardown failure must not become an unhandled rejection, and must not swallow the
|
|
1950
|
-
// signal: report it and still re-raise so the runner exits the way the shell expects.
|
|
1951
|
-
console.error(`Failed to stop the ephemeral environment on ${signal}:`, error)
|
|
1952
|
-
} finally {
|
|
1953
|
-
dispose()
|
|
1954
|
-
// Load-bearing, not cleanup: `dispose()` already detached this module's `once` handler, so
|
|
1955
|
-
// the only listeners left belong to somebody else (testcontainers, Playwright, a host CLI).
|
|
1956
|
-
// Any survivor would swallow the re-raised signal and turn the interrupt back into the
|
|
1957
|
-
// synthetic success this whole path exists to avoid, so they come off before the re-raise.
|
|
1958
|
-
processRef.removeAllListeners(signal)
|
|
1959
|
-
processRef.kill(processRef.pid as number, signal)
|
|
1960
|
-
}
|
|
1961
|
-
})()
|
|
1962
|
-
}
|
|
1963
|
-
signalHandlers.set(signal, handler)
|
|
1964
|
-
processRef.once(signal, handler)
|
|
1965
|
-
}
|
|
1966
|
-
|
|
1967
|
-
processRef.once('exit', onProcessExit)
|
|
1968
|
-
return { dispose }
|
|
1969
|
-
}
|
|
1970
|
-
|
|
1971
1771
|
async function getPathAgeMilliseconds(targetPath: string): Promise<number | null> {
|
|
1972
1772
|
try {
|
|
1973
1773
|
const stats = await stat(targetPath)
|
|
@@ -2294,7 +2094,7 @@ export async function tryReuseExistingEnvironment(options: EphemeralRuntimeOptio
|
|
|
2294
2094
|
|
|
2295
2095
|
export async function waitForApplicationReadiness(
|
|
2296
2096
|
baseUrl: string,
|
|
2297
|
-
appProcess:
|
|
2097
|
+
appProcess: ChildProcess,
|
|
2298
2098
|
options: { timeoutMs: number; intervalMs?: number; stabilizationMs?: number },
|
|
2299
2099
|
): Promise<void> {
|
|
2300
2100
|
const startTimestamp = Date.now()
|
|
@@ -2315,15 +2115,8 @@ export async function waitForApplicationReadiness(
|
|
|
2315
2115
|
return { exited: true as const }
|
|
2316
2116
|
},
|
|
2317
2117
|
)
|
|
2318
|
-
const exitError = () =>
|
|
2319
|
-
|
|
2320
|
-
const capturedOutputTail = capturedOutput
|
|
2321
|
-
? `\nCaptured output:\n${capturedOutput.split('\n').slice(-20).join('\n')}`
|
|
2322
|
-
: ''
|
|
2323
|
-
return new Error(
|
|
2324
|
-
`Application process exited before readiness check (exit ${exitCode ?? 'unknown'})${capturedOutputTail}`,
|
|
2325
|
-
)
|
|
2326
|
-
}
|
|
2118
|
+
const exitError = () =>
|
|
2119
|
+
new Error(`Application process exited before readiness check (exit ${exitCode ?? 'unknown'})`)
|
|
2327
2120
|
|
|
2328
2121
|
while (Date.now() - startTimestamp < options.timeoutMs) {
|
|
2329
2122
|
// Run one probe cycle to completion before starting the next. Overlapping cycles (the previous
|
|
@@ -3627,45 +3420,21 @@ export async function startEphemeralEnvironment(options: EphemeralRuntimeOptions
|
|
|
3627
3420
|
})
|
|
3628
3421
|
|
|
3629
3422
|
const runtimeLock = await acquireEphemeralRuntimeLock(options.logPrefix)
|
|
3630
|
-
let applicationProcess:
|
|
3423
|
+
let applicationProcess: ChildProcess | null = null
|
|
3631
3424
|
let isStopped = false
|
|
3632
|
-
let shutdownHandlers: EphemeralShutdownHandlers | null = null
|
|
3633
3425
|
const stop = async (): Promise<void> => {
|
|
3634
3426
|
if (isStopped) return
|
|
3635
3427
|
isStopped = true
|
|
3636
3428
|
try {
|
|
3637
3429
|
if (applicationProcess && !applicationProcess.killed) {
|
|
3638
|
-
|
|
3639
|
-
await terminateProcessTree(applicationProcess)
|
|
3640
|
-
} catch (error) {
|
|
3641
|
-
// `killProcessTreeIfRunning` rethrows anything that is not `ESRCH`, and this call sits
|
|
3642
|
-
// ahead of the container and state cleanup. A kill that fails must not strand the
|
|
3643
|
-
// Postgres container and the state file too — report it and finish tearing down.
|
|
3644
|
-
console.error(`[${options.logPrefix}] Failed to terminate the application process tree:`, error)
|
|
3645
|
-
}
|
|
3430
|
+
applicationProcess.kill('SIGTERM')
|
|
3646
3431
|
}
|
|
3647
3432
|
await databaseContainer.stop()
|
|
3648
3433
|
await clearEphemeralEnvironmentState()
|
|
3649
3434
|
} finally {
|
|
3650
3435
|
await runtimeLock.release()
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
}
|
|
3654
|
-
shutdownHandlers = registerEphemeralShutdownHandlers({
|
|
3655
|
-
stop,
|
|
3656
|
-
onSignal: (signal) =>
|
|
3657
|
-
console.log(`[${options.logPrefix}] Received ${signal}, stopping ephemeral environment...`),
|
|
3658
|
-
// Deliberately not guarded on `isStopped`: `startEphemeralEnvironment`'s own catch already ran
|
|
3659
|
-
// `stop()` before rethrowing, so the guard made the sweep dead on exactly the paths that need
|
|
3660
|
-
// it. After a successful `stop()` the extra group kill is a harmless `ESRCH` this swallows.
|
|
3661
|
-
killApplicationTree: () => {
|
|
3662
|
-
const pid = applicationProcess?.pid
|
|
3663
|
-
if (!pid) return
|
|
3664
|
-
try {
|
|
3665
|
-
killProcessTree(pid, 'SIGKILL')
|
|
3666
|
-
} catch {}
|
|
3667
|
-
},
|
|
3668
|
-
})
|
|
3436
|
+
}
|
|
3437
|
+
}
|
|
3669
3438
|
|
|
3670
3439
|
try {
|
|
3671
3440
|
const appReadyTimeoutMs = resolveAppReadyTimeoutMs(options.logPrefix)
|
|
@@ -3752,7 +3521,6 @@ export async function startEphemeralEnvironment(options: EphemeralRuntimeOptions
|
|
|
3752
3521
|
console.log(`[${options.logPrefix}] Starting application on ${applicationBaseUrl}...`)
|
|
3753
3522
|
const startedAppProcess = startYarnCommand(['start'], commandEnvironment, {
|
|
3754
3523
|
silent: !options.verbose,
|
|
3755
|
-
detached: true,
|
|
3756
3524
|
}, appDirectory)
|
|
3757
3525
|
applicationProcess = startedAppProcess
|
|
3758
3526
|
|
|
@@ -3791,11 +3559,15 @@ export async function startEphemeralEnvironment(options: EphemeralRuntimeOptions
|
|
|
3791
3559
|
}
|
|
3792
3560
|
}
|
|
3793
3561
|
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3562
|
+
async function keepEnvironmentRunningForever(options: { logPrefix: string; stop: () => Promise<void> }): Promise<void> {
|
|
3563
|
+
const onSignal = async (signal: string): Promise<void> => {
|
|
3564
|
+
console.log(`[${options.logPrefix}] Received ${signal}, stopping ephemeral environment...`)
|
|
3565
|
+
await options.stop()
|
|
3566
|
+
process.exit(0)
|
|
3567
|
+
}
|
|
3568
|
+
|
|
3569
|
+
process.once('SIGINT', () => void onSignal('SIGINT'))
|
|
3570
|
+
process.once('SIGTERM', () => void onSignal('SIGTERM'))
|
|
3799
3571
|
await new Promise<void>(() => {})
|
|
3800
3572
|
}
|
|
3801
3573
|
|
|
@@ -3845,7 +3617,10 @@ export async function runIntegrationTestsInEphemeralEnvironment(rawArgs: string[
|
|
|
3845
3617
|
|
|
3846
3618
|
if (options.keep) {
|
|
3847
3619
|
console.log('[integration] --keep enabled: leaving app and database running. Press Ctrl+C to stop.')
|
|
3848
|
-
await keepEnvironmentRunningForever(
|
|
3620
|
+
await keepEnvironmentRunningForever({
|
|
3621
|
+
logPrefix: 'integration',
|
|
3622
|
+
stop: environment.stop,
|
|
3623
|
+
})
|
|
3849
3624
|
}
|
|
3850
3625
|
} finally {
|
|
3851
3626
|
if (!options.keep) {
|
|
@@ -3873,7 +3648,10 @@ export async function runEphemeralAppForQa(rawArgs: string[]): Promise<void> {
|
|
|
3873
3648
|
console.log('[ephemeral] Reused existing environment. Press Ctrl+C to exit without stopping the shared runtime.')
|
|
3874
3649
|
}
|
|
3875
3650
|
|
|
3876
|
-
await keepEnvironmentRunningForever(
|
|
3651
|
+
await keepEnvironmentRunningForever({
|
|
3652
|
+
logPrefix: 'ephemeral',
|
|
3653
|
+
stop: environment.stop,
|
|
3654
|
+
})
|
|
3877
3655
|
}
|
|
3878
3656
|
|
|
3879
3657
|
export async function runInteractiveIntegrationInEphemeralEnvironment(rawArgs: string[]): Promise<void> {
|
package/src/mercato.ts
CHANGED
|
@@ -78,29 +78,6 @@ function getRegisteredCliWorkers(modules: Module[] = getCliModules()): ModuleWor
|
|
|
78
78
|
return allWorkers
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
/**
|
|
82
|
-
* Picks the abandoned-job callback for a queue from its workers.
|
|
83
|
-
*
|
|
84
|
-
* The numeric queue options merge across a queue's workers with `Math.max`; two callbacks cannot
|
|
85
|
-
* merge, so the first declared one wins. Silence there would make a genuine wiring mistake — two
|
|
86
|
-
* handlers on one queue each expecting to report its abandoned jobs — look like it works while one of
|
|
87
|
-
* them never runs.
|
|
88
|
-
*/
|
|
89
|
-
export function resolveQueueAbandonHook(
|
|
90
|
-
queueName: string,
|
|
91
|
-
queueWorkers: Array<Pick<ModuleWorker, 'id' | 'onJobAbandoned'>>,
|
|
92
|
-
warn: (message: string) => void = console.warn,
|
|
93
|
-
): ModuleWorker['onJobAbandoned'] {
|
|
94
|
-
const declaring = queueWorkers.filter((worker) => worker.onJobAbandoned)
|
|
95
|
-
if (declaring.length > 1) {
|
|
96
|
-
warn(
|
|
97
|
-
`[worker] Queue "${queueName}" has ${declaring.length} workers declaring onJobAbandoned `
|
|
98
|
-
+ `(${declaring.map((worker) => worker.id).join(', ')}); using the first and ignoring the rest.`,
|
|
99
|
-
)
|
|
100
|
-
}
|
|
101
|
-
return declaring[0]?.onJobAbandoned
|
|
102
|
-
}
|
|
103
|
-
|
|
104
81
|
function shouldEmbedLocalSchedulerInSharedWorker(env: NodeJS.ProcessEnv = process.env): boolean {
|
|
105
82
|
return parseBooleanToken(env.OM_DEV_EMBED_SCHEDULER_IN_SHARED_WORKER) === true
|
|
106
83
|
}
|
|
@@ -1701,7 +1678,6 @@ export async function run(argv = process.argv) {
|
|
|
1701
1678
|
Math.max(...queueWorkers.map((w) => w.concurrency), 1)
|
|
1702
1679
|
const maxStalledCount = Math.max(...queueWorkers.map((w) => w.maxStalledCount ?? 1), 1)
|
|
1703
1680
|
const lockDuration = Math.max(...queueWorkers.map((w) => w.lockDuration ?? 0), 0) || undefined
|
|
1704
|
-
const onJobAbandoned = resolveQueueAbandonHook(queue, queueWorkers)
|
|
1705
1681
|
|
|
1706
1682
|
console.log(`[worker] Starting "${queue}" with ${queueWorkers.length} handler(s), concurrency: ${concurrency}`)
|
|
1707
1683
|
|
|
@@ -1712,7 +1688,6 @@ export async function run(argv = process.argv) {
|
|
|
1712
1688
|
concurrency,
|
|
1713
1689
|
lockDuration,
|
|
1714
1690
|
maxStalledCount,
|
|
1715
|
-
onJobAbandoned,
|
|
1716
1691
|
background: true,
|
|
1717
1692
|
handler: createPerJobWorkerHandler(queueWorkers, createRequestContainer),
|
|
1718
1693
|
})
|
|
@@ -1758,7 +1733,6 @@ export async function run(argv = process.argv) {
|
|
|
1758
1733
|
const concurrency = budgetPlan.entries[0]?.effective ?? requested
|
|
1759
1734
|
const maxStalledCount = Math.max(...queueWorkers.map((w) => w.maxStalledCount ?? 1), 1)
|
|
1760
1735
|
const lockDuration = Math.max(...queueWorkers.map((w) => w.lockDuration ?? 0), 0) || undefined
|
|
1761
|
-
const onJobAbandoned = resolveQueueAbandonHook(queueName!, queueWorkers)
|
|
1762
1736
|
|
|
1763
1737
|
console.log(`[worker] Found ${queueWorkers.length} worker(s) for queue "${queueName}"`)
|
|
1764
1738
|
|
|
@@ -1769,7 +1743,6 @@ export async function run(argv = process.argv) {
|
|
|
1769
1743
|
concurrency,
|
|
1770
1744
|
lockDuration,
|
|
1771
1745
|
maxStalledCount,
|
|
1772
|
-
onJobAbandoned,
|
|
1773
1746
|
handler: createPerJobWorkerHandler(queueWorkers, createRequestContainer),
|
|
1774
1747
|
})
|
|
1775
1748
|
} else {
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# api_keys — DI registrations (rich)
|
|
2
|
-
|
|
3
|
-
[Back to module index](index.md)
|
|
4
|
-
|
|
5
|
-
## DI registrations (rich)
|
|
6
|
-
|
|
7
|
-
| Token | Kind | Lifetime | Injection | Provider | Source |
|
|
8
|
-
|---|---|---|---|---|---|
|
|
9
|
-
| apiKeyPrincipalService | class | scoped | — | DefaultApiKeyPrincipalService | [di.ts:6](../../../../node_modules/@open-mercato/core/src/modules/api_keys/di.ts#L6) |
|
|
10
|
-
|
|
11
|
-
<!-- end module facts section: api_keys/di-registrations-rich -->
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# api_keys — DI service tokens
|
|
2
|
-
|
|
3
|
-
[Back to module index](index.md)
|
|
4
|
-
|
|
5
|
-
## DI service tokens
|
|
6
|
-
|
|
7
|
-
| Token | Source |
|
|
8
|
-
|---|---|
|
|
9
|
-
| apiKeyPrincipalService | [di.ts:6](../../../../node_modules/@open-mercato/core/src/modules/api_keys/di.ts#L6) |
|
|
10
|
-
|
|
11
|
-
<!-- end module facts section: api_keys/di-service-tokens -->
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# channel_discord — ACL features
|
|
2
|
-
|
|
3
|
-
[Back to module index](index.md)
|
|
4
|
-
|
|
5
|
-
## ACL features (3)
|
|
6
|
-
|
|
7
|
-
| Feature | Source |
|
|
8
|
-
|---|---|
|
|
9
|
-
| channel_discord.view | [acl.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/acl.ts) |
|
|
10
|
-
| channel_discord.configure | [acl.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/acl.ts) |
|
|
11
|
-
| channel_discord.ai_auto_reply.run | [acl.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/acl.ts) |
|
|
12
|
-
|
|
13
|
-
<!-- end module facts section: channel_discord/acl-features -->
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# channel_discord — AI agents
|
|
2
|
-
|
|
3
|
-
[Back to module index](index.md)
|
|
4
|
-
|
|
5
|
-
## AI agents
|
|
6
|
-
|
|
7
|
-
| ID / path | Source |
|
|
8
|
-
|---|---|
|
|
9
|
-
| channel_discord.auto_reply | [ai-agents.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/ai-agents.ts) |
|
|
10
|
-
|
|
11
|
-
<!-- end module facts section: channel_discord/ai-agents -->
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# channel_discord — Backend pages
|
|
2
|
-
|
|
3
|
-
[Back to module index](index.md)
|
|
4
|
-
|
|
5
|
-
## Backend pages
|
|
6
|
-
|
|
7
|
-
| ID / path | Source |
|
|
8
|
-
|---|---|
|
|
9
|
-
| /backend/channel_discord/channels/[id]/ai-auto-reply | [backend/channel_discord/channels/[id]/ai-auto-reply/page.tsx](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/backend/channel_discord/channels/[id]/ai-auto-reply/page.tsx) |
|
|
10
|
-
|
|
11
|
-
<!-- end module facts section: channel_discord/backend-pages -->
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# channel_discord — CLI commands
|
|
2
|
-
|
|
3
|
-
[Back to module index](index.md)
|
|
4
|
-
|
|
5
|
-
## CLI commands
|
|
6
|
-
|
|
7
|
-
| ID / path | Source |
|
|
8
|
-
|---|---|
|
|
9
|
-
| start-gateway | [cli.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/cli.ts) |
|
|
10
|
-
| configure-from-env | [cli.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/cli.ts) |
|
|
11
|
-
| register-slash-commands | [cli.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/cli.ts) |
|
|
12
|
-
|
|
13
|
-
<!-- end module facts section: channel_discord/cli-commands -->
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# channel_discord — Contribution resolutions
|
|
2
|
-
|
|
3
|
-
[Back to module index](index.md)
|
|
4
|
-
|
|
5
|
-
## Contribution resolutions
|
|
6
|
-
|
|
7
|
-
| Contribution | Target | Resolution | Activations | Source |
|
|
8
|
-
|---|---|---|---|---|
|
|
9
|
-
| ai:channel_discord.auto_reply | module:channel_discord.auto_reply | capability-only | — | [ai-agents.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/ai-agents.ts) |
|
|
10
|
-
| channel_discord:ai-auto-reply | event:communication_channels.message.received @communication_channels | capability-only | — | [subscribers/ai-auto-reply.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/subscribers/ai-auto-reply.ts) |
|
|
11
|
-
| channel_discord.injection.connect@profile:communication-channels:connect | widget-spot:profile:communication-channels:connect @communication_channels | bound | widget-spot:profile:communication-channels:connect:widget-injection-consumer | [widgets/injection-table.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/widgets/injection-table.ts) |
|
|
12
|
-
| integration:channel_discord | module:channel_discord | capability-only | — | [integration.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/integration.ts) |
|
|
13
|
-
|
|
14
|
-
<!-- end module facts section: channel_discord/contribution-resolutions -->
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# channel_discord — DI registrations (rich)
|
|
2
|
-
|
|
3
|
-
[Back to module index](index.md)
|
|
4
|
-
|
|
5
|
-
## DI registrations (rich)
|
|
6
|
-
|
|
7
|
-
| Token | Kind | Lifetime | Injection | Provider | Source |
|
|
8
|
-
|---|---|---|---|---|---|
|
|
9
|
-
| channelDiscordAdapter | value | — | — | — | [di.ts:20](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/di.ts#L20) |
|
|
10
|
-
| channelDiscordHealthCheck | value | — | — | — | [di.ts:24](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/di.ts#L24) |
|
|
11
|
-
|
|
12
|
-
<!-- end module facts section: channel_discord/di-registrations-rich -->
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# channel_discord — Exact override targets
|
|
2
|
-
|
|
3
|
-
[Back to module index](index.md)
|
|
4
|
-
|
|
5
|
-
## Exact override targets
|
|
6
|
-
|
|
7
|
-
| Domain | Path / key | Supported modes | Referenced fact | Source |
|
|
8
|
-
|---|---|---|---|---|
|
|
9
|
-
| acl | `overrides.acl.features["channel_discord.ai_auto_reply.run"]` | disable-replace | aclFeatures:channel_discord.ai_auto_reply.run | [acl.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/acl.ts) |
|
|
10
|
-
| acl | `overrides.acl.features["channel_discord.configure"]` | disable-replace | aclFeatures:channel_discord.configure | [acl.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/acl.ts) |
|
|
11
|
-
| acl | `overrides.acl.features["channel_discord.view"]` | disable-replace | aclFeatures:channel_discord.view | [acl.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/acl.ts) |
|
|
12
|
-
| ai | `overrides.ai.agents["channel_discord.auto_reply"]` | disable-replace | aiAgents:channel_discord.auto_reply | [ai-agents.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/ai-agents.ts) |
|
|
13
|
-
| cli | `overrides.cli["configure-from-env"]` | disable-replace | cliCommands:configure-from-env | [cli.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/cli.ts) |
|
|
14
|
-
| cli | `overrides.cli["register-slash-commands"]` | disable-replace | cliCommands:register-slash-commands | [cli.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/cli.ts) |
|
|
15
|
-
| cli | `overrides.cli["start-gateway"]` | disable-replace | cliCommands:start-gateway | [cli.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/cli.ts) |
|
|
16
|
-
| di | `overrides.di["channelDiscordAdapter"]` | disable-replace | ownedContracts.di-registration:channelDiscordAdapter | [di.ts:20](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/di.ts#L20) |
|
|
17
|
-
| di | `overrides.di["channelDiscordHealthCheck"]` | disable-replace | ownedContracts.di-registration:channelDiscordHealthCheck | [di.ts:24](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/di.ts#L24) |
|
|
18
|
-
| events | `overrides.events.subscribers["channel_discord:ai-auto-reply"]` | disable-replace | extensionSurfaces.contributions:channel_discord:ai-auto-reply | [subscribers/ai-auto-reply.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/subscribers/ai-auto-reply.ts) |
|
|
19
|
-
| routes | `overrides.routes.pages["backend:/backend/channel_discord/channels/[id]/ai-auto-reply"]` | disable-replace | backendPages:/backend/channel_discord/channels/[id]/ai-auto-reply | [backend/channel_discord/channels/[id]/ai-auto-reply/page.tsx](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/backend/channel_discord/channels/[id]/ai-auto-reply/page.tsx) |
|
|
20
|
-
| setup | `overrides.setup.defaultRoleFeatures` | replace | ownedContracts.setup:channel_discord:setup | [setup.ts:33](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/setup.ts#L33) |
|
|
21
|
-
| setup | `overrides.setup.onTenantCreated` | replace | ownedContracts.setup:channel_discord:setup | [setup.ts:33](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/setup.ts#L33) |
|
|
22
|
-
| widgets | `overrides.widgets.injection["channel_discord.injection.connect"]` | disable-replace | extensionSurfaces.contributions:channel_discord.injection.connect@profile:communication-channels:connect | [widgets/injection-table.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/widgets/injection-table.ts) |
|
|
23
|
-
| workers | `overrides.workers["channel_discord:gateway"]` | disable-replace | ownedContracts.worker:channel_discord:gateway | [workers/discord-gateway.ts:50](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/workers/discord-gateway.ts#L50) |
|
|
24
|
-
| workers | `overrides.workers["channel_discord:interactions"]` | disable-replace | ownedContracts.worker:channel_discord:interactions | [workers/discord-interactions.ts:39](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/workers/discord-interactions.ts#L39) |
|
|
25
|
-
|
|
26
|
-
<!-- end module facts section: channel_discord/exact-override-targets -->
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# channel_discord — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/channel-discord 0.6.8-develop.7100.1.fbf66fca35; core 0.6.8-develop.7100.1.fbf66fca35 — R1 staleness stamp -->
|
|
3
|
-
Source root: node_modules/@open-mercato/channel-discord/src/modules/channel_discord
|
|
4
|
-
|
|
5
|
-
## Sections
|
|
6
|
-
|
|
7
|
-
- [ACL features](acl-features.md) — ~1 KB — Generated acl features facts for channel_discord.
|
|
8
|
-
- [Backend pages](backend-pages.md) — ~1 KB — Generated backend pages facts for channel_discord.
|
|
9
|
-
- [UMES contributions](umes-contributions.md) — ~2 KB — Generated umes contributions facts for channel_discord.
|
|
10
|
-
- [Contribution resolutions](contribution-resolutions.md) — ~2 KB — Generated contribution resolutions facts for channel_discord.
|
|
11
|
-
- [CLI commands](cli-commands.md) — ~1 KB — Generated cli commands facts for channel_discord.
|
|
12
|
-
- [AI agents](ai-agents.md) — ~1 KB — Generated ai agents facts for channel_discord.
|
|
13
|
-
- [Exact override targets](exact-override-targets.md) — ~5 KB — Generated exact override targets facts for channel_discord.
|
|
14
|
-
- [Owned contract — module metadata](owned-contract-module-metadata.md) — ~1 KB — Generated owned contract — module metadata facts for channel_discord.
|
|
15
|
-
- [Workers](workers.md) — ~1 KB — Generated workers facts for channel_discord.
|
|
16
|
-
- [Setup](setup.md) — ~1 KB — Generated setup facts for channel_discord.
|
|
17
|
-
- [DI registrations (rich)](di-registrations-rich.md) — ~1 KB — Generated di registrations (rich) facts for channel_discord.
|
|
18
|
-
|
|
19
|
-
Read only the section files needed for the task; every section ends with a completion marker.
|
|
20
|
-
A section absent from this list has no facts for channel_discord; this index is complete only when the read reaches the marker below.
|
|
21
|
-
|
|
22
|
-
<!-- end module facts: channel_discord — 11 sections -->
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# channel_discord — Owned contract — module metadata
|
|
2
|
-
|
|
3
|
-
[Back to module index](index.md)
|
|
4
|
-
|
|
5
|
-
## Owned contract — module metadata
|
|
6
|
-
|
|
7
|
-
| ID | Metadata | Source |
|
|
8
|
-
|---|---|---|
|
|
9
|
-
| channel_discord | — | [index.ts:1](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/index.ts#L1) |
|
|
10
|
-
|
|
11
|
-
<!-- end module facts section: channel_discord/owned-contract-module-metadata -->
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# channel_discord — Setup
|
|
2
|
-
|
|
3
|
-
[Back to module index](index.md)
|
|
4
|
-
|
|
5
|
-
## Setup
|
|
6
|
-
|
|
7
|
-
| ID | Metadata | Source |
|
|
8
|
-
|---|---|---|
|
|
9
|
-
| channel_discord:setup | hooks=onTenantCreated; roles=admin, superadmin | [setup.ts:33](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/setup.ts#L33) |
|
|
10
|
-
|
|
11
|
-
<!-- end module facts section: channel_discord/setup -->
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# channel_discord — UMES contributions
|
|
2
|
-
|
|
3
|
-
[Back to module index](index.md)
|
|
4
|
-
|
|
5
|
-
## UMES contributions
|
|
6
|
-
|
|
7
|
-
| ID | Kind | Target | Phase / operations | Contract | Resolution | Source |
|
|
8
|
-
|---|---|---|---|---|---|---|
|
|
9
|
-
| ai:channel_discord.auto_reply | specialized-registry | channel_discord.auto_reply | — | registry=ai; registryId=channel_discord.auto_reply; specialistRoute=aiAgents | fact-ref | [ai-agents.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/ai-agents.ts) |
|
|
10
|
-
| integration:channel_discord | specialized-registry | channel_discord | — | registry=integration; registryId=channel_discord; specialistRoute=integrations | fact-ref | [integration.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/integration.ts) |
|
|
11
|
-
| channel_discord:ai-auto-reply | subscriber | communication_channels.message.received | async-delivery | event=communication_channels.message.received; persistent=true; subscriberId=channel_discord:ai-auto-reply; sync=false | fact-ref | [subscribers/ai-auto-reply.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/subscribers/ai-auto-reply.ts) |
|
|
12
|
-
| channel_discord.injection.connect@profile:communication-channels:connect | widget | profile:communication-channels:connect | — | executionGuard=host; payload=render; registryKey=channel_discord.injection.connect | exact | [widgets/injection-table.ts](../../../../node_modules/@open-mercato/channel-discord/src/modules/channel_discord/widgets/injection-table.ts) |
|
|
13
|
-
|
|
14
|
-
<!-- end module facts section: channel_discord/umes-contributions -->
|