@visa/cli 5.0.0-rc.409 → 5.0.0-rc.412
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 +166 -761
- package/bin/visa-tool.js +6 -0
- package/dist/cli.js +128 -177
- package/dist/enrollment-finisher.js +67 -13
- package/dist/managed-runtime/runtime-readiness.mjs +0 -44
- package/dist/managed-runtime/update-and-restart.mjs +36 -120
- package/dist/mcp-server/index.js +339 -627
- package/dist/tool-call.js +64 -0
- package/package.json +5 -7
- package/server.json +2 -2
- package/dist/skills/pair-visa-agent/RUNTIMES.md +0 -117
- package/dist/skills/pair-visa-agent/SKILL.md +0 -517
- package/dist/skills/pair-visa-agent/scripts/__tests__/setup.test.mjs +0 -422
- package/dist/skills/pair-visa-agent/scripts/setup.mjs +0 -328
|
@@ -1,22 +1,4 @@
|
|
|
1
1
|
export const DEFAULT_RUNTIME_READINESS_TIMEOUT_MS = 60_000
|
|
2
|
-
const COMMERCE_RUNTIMES = new Set(['openclaw', 'hermes'])
|
|
3
|
-
|
|
4
|
-
/** Fixed argv only: callers cannot substitute a package, command, or script path. */
|
|
5
|
-
export function commerceSkillArgs(env = process.env, check = false) {
|
|
6
|
-
const runtime = env.VISA_COMMERCE_RUNTIME || ''
|
|
7
|
-
if (runtime && !COMMERCE_RUNTIMES.has(runtime)) {
|
|
8
|
-
throw new Error('VISA_COMMERCE_RUNTIME must be openclaw or hermes')
|
|
9
|
-
}
|
|
10
|
-
return [
|
|
11
|
-
'agent',
|
|
12
|
-
'skill',
|
|
13
|
-
'--commerce',
|
|
14
|
-
...(runtime ? ['--runtime', runtime] : []),
|
|
15
|
-
...(check ? ['--check'] : []),
|
|
16
|
-
'--format',
|
|
17
|
-
'json',
|
|
18
|
-
]
|
|
19
|
-
}
|
|
20
2
|
|
|
21
3
|
function isPlainRecord(value) {
|
|
22
4
|
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
@@ -57,32 +39,6 @@ export function parseRuntimeReadiness(raw) {
|
|
|
57
39
|
}
|
|
58
40
|
}
|
|
59
41
|
|
|
60
|
-
export function assertSameShopifyRuntime(actual, expected) {
|
|
61
|
-
if (!isPlainRecord(actual)) {
|
|
62
|
-
throw new Error('loaded runtime readiness must attest the named shopify-ucp MCP')
|
|
63
|
-
}
|
|
64
|
-
if (actual.serverName !== 'shopify-ucp') {
|
|
65
|
-
throw new Error('loaded runtime readiness did not attest the canonical shopify-ucp mount')
|
|
66
|
-
}
|
|
67
|
-
for (const field of ['installedVersion', 'toolSchemaFingerprint', 'command']) {
|
|
68
|
-
if (actual[field] !== expected[field]) {
|
|
69
|
-
throw new Error(`loaded Shopify UCP ${field} does not match the certified local runtime`)
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
if (
|
|
73
|
-
!Array.isArray(actual.args) ||
|
|
74
|
-
actual.args.length !== expected.args.length ||
|
|
75
|
-
!actual.args.every((value, index) => value === expected.args[index])
|
|
76
|
-
) {
|
|
77
|
-
throw new Error('loaded Shopify UCP command arguments do not match the certified local runtime')
|
|
78
|
-
}
|
|
79
|
-
if (!Array.isArray(actual.blockedTools) || !actual.blockedTools.includes('checkout_complete')) {
|
|
80
|
-
throw new Error(
|
|
81
|
-
'loaded Shopify UCP runtime does not attest the checkout completion deny boundary'
|
|
82
|
-
)
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
42
|
export function resolveRuntimeUpdateConfig(env = process.env) {
|
|
87
43
|
const restartCommand = env.RUNTIME_RESTART_COMMAND || env.OPENCLAW_RESTART_COMMAND || ''
|
|
88
44
|
const readinessCommand = env.RUNTIME_READINESS_COMMAND || ''
|
|
@@ -25,8 +25,6 @@ import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:pat
|
|
|
25
25
|
import { fileURLToPath } from 'node:url'
|
|
26
26
|
import {
|
|
27
27
|
assertSameRuntimeBuild,
|
|
28
|
-
assertSameShopifyRuntime,
|
|
29
|
-
commerceSkillArgs,
|
|
30
28
|
parseRuntimeReadiness,
|
|
31
29
|
resolveRuntimeUpdateConfig,
|
|
32
30
|
runtimeReadinessExecOptions,
|
|
@@ -656,105 +654,34 @@ export function recoverInterruptedActivation(managedDir, logger = console) {
|
|
|
656
654
|
return true
|
|
657
655
|
}
|
|
658
656
|
|
|
659
|
-
function
|
|
657
|
+
export function certifyLocalBinary(
|
|
658
|
+
releaseDir,
|
|
659
|
+
env = process.env,
|
|
660
|
+
execFile = execFileSync,
|
|
661
|
+
timeout = DEFAULT_COMMAND_TIMEOUT_MS
|
|
662
|
+
) {
|
|
660
663
|
try {
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
timeout,
|
|
664
|
-
})
|
|
665
|
-
} catch (error) {
|
|
666
|
-
throw new ManagedRuntimeUpdateError(
|
|
667
|
-
'rebuild_or_remount_required',
|
|
668
|
-
'the managed runtime could not refresh its installer-owned commerce mount; rebuild or remount it',
|
|
669
|
-
{ cause: error }
|
|
670
|
-
)
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
function certifyLocalBinary(releaseDir, execFile, timeout) {
|
|
675
|
-
const rawCapabilities = execFile(visaBinary(releaseDir), ['capabilities', '--format', 'json'], {
|
|
676
|
-
encoding: 'utf8',
|
|
677
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
678
|
-
timeout,
|
|
679
|
-
})
|
|
680
|
-
const capabilities = parseJson(rawCapabilities, 'visa capabilities')
|
|
681
|
-
const build = capabilities?.data?.build ?? capabilities?.build
|
|
682
|
-
if (typeof build?.version !== 'string' || typeof build?.targetEnvironment !== 'string') {
|
|
683
|
-
throw new ManagedRuntimeUpdateError(
|
|
684
|
-
'local_readiness_failed',
|
|
685
|
-
'local capabilities omitted build identity'
|
|
686
|
-
)
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
return {
|
|
690
|
-
version: build.version,
|
|
691
|
-
targetEnvironment: build.targetEnvironment,
|
|
692
|
-
minCompatibleVersion: build.minCompatibleVersion || null,
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
function certifyLocalCommerce(releaseDir, env, execFile, timeout) {
|
|
697
|
-
let rawCommerce
|
|
698
|
-
try {
|
|
699
|
-
rawCommerce = execFile(visaBinary(releaseDir), commerceSkillArgs(env, true), {
|
|
664
|
+
const entry = join(releaseDir, 'node_modules', '@visa', 'cli', 'dist', 'mcp-server', 'index.js')
|
|
665
|
+
const raw = execFile(process.execPath, [entry, '--self-check'], {
|
|
700
666
|
encoding: 'utf8',
|
|
701
667
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
702
668
|
timeout,
|
|
669
|
+
env,
|
|
703
670
|
})
|
|
671
|
+
if (JSON.parse(raw)?.ok !== true) throw new Error('self-check did not succeed')
|
|
672
|
+
const build = parseRuntimeReadiness(raw)
|
|
673
|
+
return {
|
|
674
|
+
version: build.version,
|
|
675
|
+
targetEnvironment: build.targetEnvironment,
|
|
676
|
+
minCompatibleVersion: null,
|
|
677
|
+
}
|
|
704
678
|
} catch (error) {
|
|
705
679
|
throw new ManagedRuntimeUpdateError(
|
|
706
|
-
'
|
|
707
|
-
'
|
|
680
|
+
'local_readiness_failed',
|
|
681
|
+
'staged MCP server failed its self-check',
|
|
708
682
|
{ cause: error }
|
|
709
683
|
)
|
|
710
684
|
}
|
|
711
|
-
const commerce = parseJson(rawCommerce, 'commerce readiness')
|
|
712
|
-
if (
|
|
713
|
-
commerce?.localBundleReady !== true ||
|
|
714
|
-
commerce?.shopifyRuntime?.status !== 'ready' ||
|
|
715
|
-
typeof commerce?.shopifyRuntime?.toolSchemaFingerprint !== 'string'
|
|
716
|
-
) {
|
|
717
|
-
throw new ManagedRuntimeUpdateError(
|
|
718
|
-
'commerce_runtime_not_ready',
|
|
719
|
-
'local Shopify UCP runtime did not certify its required tools'
|
|
720
|
-
)
|
|
721
|
-
}
|
|
722
|
-
return commerce.shopifyRuntime
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
function assessLocalCommerce(releaseDir, env, execFile, timeout) {
|
|
726
|
-
try {
|
|
727
|
-
runCommerceInstall(releaseDir, env, execFile, timeout)
|
|
728
|
-
return {
|
|
729
|
-
commerceReady: true,
|
|
730
|
-
commerceActionRequired: null,
|
|
731
|
-
shopifyRuntime: certifyLocalCommerce(releaseDir, env, execFile, timeout),
|
|
732
|
-
}
|
|
733
|
-
} catch (error) {
|
|
734
|
-
const code =
|
|
735
|
-
error instanceof ManagedRuntimeUpdateError && error.code === 'rebuild_or_remount_required'
|
|
736
|
-
? 'rebuild_or_remount_required'
|
|
737
|
-
: 'commerce_runtime_not_ready'
|
|
738
|
-
return {
|
|
739
|
-
commerceReady: false,
|
|
740
|
-
commerceActionRequired: code,
|
|
741
|
-
shopifyRuntime: null,
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
function assessLoadedCommerce(loaded, localCommerce) {
|
|
747
|
-
if (!localCommerce.commerceReady) return localCommerce
|
|
748
|
-
try {
|
|
749
|
-
assertSameShopifyRuntime(loaded.shopifyRuntime, localCommerce.shopifyRuntime)
|
|
750
|
-
return localCommerce
|
|
751
|
-
} catch {
|
|
752
|
-
return {
|
|
753
|
-
commerceReady: false,
|
|
754
|
-
commerceActionRequired: 'commerce_runtime_not_ready',
|
|
755
|
-
shopifyRuntime: null,
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
685
|
}
|
|
759
686
|
|
|
760
687
|
function restartSupervisor(config, dependencies, operation = 'restart') {
|
|
@@ -917,7 +844,7 @@ export async function runManagedRuntimeUpdate(env = process.env, dependencies =
|
|
|
917
844
|
)
|
|
918
845
|
targetRelease = stageExactRelease(config, dependencies)
|
|
919
846
|
const execFile = dependencies.execFileSync ?? execFileSync
|
|
920
|
-
const local = certifyLocalBinary(targetRelease, execFile, config.commandTimeoutMs)
|
|
847
|
+
const local = certifyLocalBinary(targetRelease, env, execFile, config.commandTimeoutMs)
|
|
921
848
|
if (local.version !== config.exactVersion) {
|
|
922
849
|
throw new ManagedRuntimeUpdateError(
|
|
923
850
|
'installed_version_mismatch',
|
|
@@ -930,27 +857,25 @@ export async function runManagedRuntimeUpdate(env = process.env, dependencies =
|
|
|
930
857
|
`staged CLI targets ${local.targetEnvironment}, expected ${config.expectedEnvironment}`
|
|
931
858
|
)
|
|
932
859
|
}
|
|
933
|
-
const localCommerce = assessLocalCommerce(targetRelease, env, execFile, config.commandTimeoutMs)
|
|
934
|
-
|
|
935
860
|
const releaseIntegrity = releaseTreeIntegrity(targetRelease)
|
|
936
861
|
writePendingTransaction(config, targetRelease, previous, correlationId)
|
|
937
862
|
activateRelease(config.managedDir, targetRelease)
|
|
938
863
|
activated = true
|
|
939
864
|
const loaded = restartAndReadLoaded(config, dependencies)
|
|
940
865
|
assertSameRuntimeBuild(loaded, local)
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
866
|
+
// Preserve the receipt contract without invoking the retired Shopify installer.
|
|
867
|
+
// Binary readiness never establishes payment readiness.
|
|
868
|
+
const commerceActionRequired = 'commerce_runtime_removed'
|
|
869
|
+
structuredLog(
|
|
870
|
+
'commerce_action_required',
|
|
871
|
+
{
|
|
872
|
+
correlationId,
|
|
873
|
+
version: local.version,
|
|
874
|
+
code: commerceActionRequired,
|
|
875
|
+
checkoutBlocked: true,
|
|
876
|
+
},
|
|
877
|
+
dependencies.logger
|
|
878
|
+
)
|
|
954
879
|
|
|
955
880
|
const receipt = {
|
|
956
881
|
ok: true,
|
|
@@ -962,19 +887,10 @@ export async function runManagedRuntimeUpdate(env = process.env, dependencies =
|
|
|
962
887
|
releaseDir: targetRelease,
|
|
963
888
|
previousVersion: previous?.receipt.version ?? null,
|
|
964
889
|
releaseIntegrity,
|
|
965
|
-
commerceReady:
|
|
966
|
-
checkoutBlocked:
|
|
967
|
-
commerceActionRequired
|
|
968
|
-
shopifyRuntime:
|
|
969
|
-
? {
|
|
970
|
-
serverName: 'shopify-ucp',
|
|
971
|
-
installedVersion: commerce.shopifyRuntime.installedVersion,
|
|
972
|
-
toolSchemaFingerprint: commerce.shopifyRuntime.toolSchemaFingerprint,
|
|
973
|
-
command: commerce.shopifyRuntime.command,
|
|
974
|
-
args: commerce.shopifyRuntime.args,
|
|
975
|
-
blockedTools: commerce.shopifyRuntime.blockedTools,
|
|
976
|
-
}
|
|
977
|
-
: null,
|
|
890
|
+
commerceReady: false,
|
|
891
|
+
checkoutBlocked: true,
|
|
892
|
+
commerceActionRequired,
|
|
893
|
+
shopifyRuntime: null,
|
|
978
894
|
durationMs: Date.now() - startedAt,
|
|
979
895
|
}
|
|
980
896
|
try {
|