@kodycodes/cli 1.26.2 → 1.27.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 +175 -167
- package/dist/add-mcp-install.d.ts +1 -1
- package/dist/api-token.d.ts +1 -1
- package/dist/auth-6ZE6QQXA.js +31 -0
- package/dist/auth-6ZE6QQXA.js.map +6 -0
- package/dist/auth-bootstrap.d.ts +1 -1
- package/dist/auth.d.ts +27 -3
- package/dist/bin.js +27 -3
- package/dist/bin.js.map +6 -1
- package/dist/capability-proxy.d.ts +1 -1
- package/dist/chunk-2IHISXHN.js +1413 -0
- package/dist/chunk-2IHISXHN.js.map +6 -0
- package/dist/chunk-2XPH7L2P.js +23 -0
- package/dist/chunk-2XPH7L2P.js.map +6 -0
- package/dist/chunk-3H72XY5R.js +535 -0
- package/dist/chunk-3H72XY5R.js.map +6 -0
- package/dist/chunk-46IJPEID.js +30 -0
- package/dist/chunk-46IJPEID.js.map +6 -0
- package/dist/chunk-4GIFJVGT.js +14 -0
- package/dist/chunk-4GIFJVGT.js.map +6 -0
- package/dist/chunk-5JIRHJQP.js +1016 -0
- package/dist/chunk-5JIRHJQP.js.map +6 -0
- package/dist/chunk-5ZBJAP6G.js +2005 -0
- package/dist/chunk-5ZBJAP6G.js.map +6 -0
- package/dist/chunk-6ZYUGXVW.js +26 -0
- package/dist/chunk-6ZYUGXVW.js.map +6 -0
- package/dist/chunk-7PRJ36I5.js +23 -0
- package/dist/chunk-7PRJ36I5.js.map +6 -0
- package/dist/chunk-BTL3PJ2H.js +38 -0
- package/dist/chunk-BTL3PJ2H.js.map +6 -0
- package/dist/chunk-CASGRYOF.js +21 -0
- package/dist/chunk-CASGRYOF.js.map +6 -0
- package/dist/chunk-CPS7HW4T.js +56 -0
- package/dist/chunk-CPS7HW4T.js.map +6 -0
- package/dist/chunk-CWWHR4FH.js +19 -0
- package/dist/chunk-CWWHR4FH.js.map +6 -0
- package/dist/chunk-D366STO5.js +2051 -0
- package/dist/chunk-D366STO5.js.map +6 -0
- package/dist/chunk-DW5UTJ6T.js +115 -0
- package/dist/chunk-DW5UTJ6T.js.map +6 -0
- package/dist/chunk-EJXEVGWF.js +47 -0
- package/dist/chunk-EJXEVGWF.js.map +6 -0
- package/dist/chunk-FBEZ6PZ7.js +746 -0
- package/dist/chunk-FBEZ6PZ7.js.map +6 -0
- package/dist/chunk-JOMBXQOS.js +435 -0
- package/dist/chunk-JOMBXQOS.js.map +6 -0
- package/dist/{package-local-runtime-source.js → chunk-LU7I7CQ4.js} +395 -52
- package/dist/chunk-LU7I7CQ4.js.map +6 -0
- package/dist/chunk-OZDWOZLV.js +964 -0
- package/dist/chunk-OZDWOZLV.js.map +6 -0
- package/dist/chunk-SLNAWWQK.js +64 -0
- package/dist/chunk-SLNAWWQK.js.map +6 -0
- package/dist/chunk-TUUFQYWP.js +348 -0
- package/dist/chunk-TUUFQYWP.js.map +6 -0
- package/dist/chunk-UW6AWLXX.js +43 -0
- package/dist/chunk-UW6AWLXX.js.map +6 -0
- package/dist/chunk-W2SAFAT4.js +1563 -0
- package/dist/chunk-W2SAFAT4.js.map +6 -0
- package/dist/chunk-XV6D6HSG.js +57 -0
- package/dist/chunk-XV6D6HSG.js.map +6 -0
- package/dist/chunk-Y4FOJETX.js +616 -0
- package/dist/chunk-Y4FOJETX.js.map +6 -0
- package/dist/chunk-YDWTXEKQ.js +469 -0
- package/dist/chunk-YDWTXEKQ.js.map +6 -0
- package/dist/chunk-ZILB2HWE.js +24 -0
- package/dist/chunk-ZILB2HWE.js.map +6 -0
- package/dist/cli.js +74 -1500
- package/dist/cli.js.map +6 -1
- package/dist/defaults.d.ts +1 -1
- package/dist/detect-running-hosts.d.ts +1 -1
- package/dist/dev/dev-assets.d.ts +1 -1
- package/dist/dev/dev-registry.d.ts +1 -1
- package/dist/dev/error-page.d.ts +1 -1
- package/dist/dev/live-reload.d.ts +2 -2
- package/dist/dev-command-5PDEIWOC.js +5025 -0
- package/dist/dev-command-5PDEIWOC.js.map +6 -0
- package/dist/dev-command.d.ts +1 -1
- package/dist/discover-login-identity.d.ts +6 -7
- package/dist/discover-org.d.ts +2 -3
- package/dist/generated/openapi-routes.d.ts +6 -0
- package/dist/git-credential-INB2UV4C.js +170 -0
- package/dist/git-credential-INB2UV4C.js.map +6 -0
- package/dist/install-ONEJRYZ3.js +10728 -0
- package/dist/install-ONEJRYZ3.js.map +6 -0
- package/dist/install.d.ts +1 -1
- package/dist/local-execute-I3BP5NEQ.js +395 -0
- package/dist/local-execute-I3BP5NEQ.js.map +6 -0
- package/dist/local-execute-auth.d.ts +2 -2
- package/dist/local-execute.d.ts +1 -1
- package/dist/local-gateway-fetch-forward.d.ts +2 -2
- package/dist/local-package-run-JFKNSNWM.js +23 -0
- package/dist/local-package-run-JFKNSNWM.js.map +6 -0
- package/dist/local-package-run.d.ts +2 -2
- package/dist/mock/mock-fetch-gateway.d.ts +2 -2
- package/dist/mock/mock-supported.d.ts +1 -1
- package/dist/mock-dep-resolve-B5ZH4U3H.js +60 -0
- package/dist/mock-dep-resolve-B5ZH4U3H.js.map +6 -0
- package/dist/mock-fetch-gateway-S2ULVFAI.js +35 -0
- package/dist/mock-fetch-gateway-S2ULVFAI.js.map +6 -0
- package/dist/mock-local-deps-2VVNJLFF.js +200 -0
- package/dist/mock-local-deps-2VVNJLFF.js.map +6 -0
- package/dist/mock-local-deps.d.ts +1 -1
- package/dist/mock-server-TFO7Q26H.js +22 -0
- package/dist/mock-server-TFO7Q26H.js.map +6 -0
- package/dist/oauth-browser.d.ts +42 -0
- package/dist/oauth-provider.d.ts +14 -19
- package/dist/open-api-client-SR4B7265.js +43 -0
- package/dist/open-api-client-SR4B7265.js.map +6 -0
- package/dist/open-api-client.d.ts +2 -1
- package/dist/org-535LB4PD.js +134 -0
- package/dist/org-535LB4PD.js.map +6 -0
- package/dist/org-resolve.d.ts +2 -0
- package/dist/package-app-dev.d.ts +2 -2
- package/dist/package-manifest-DFF6XCPV.js +15 -0
- package/dist/package-manifest-DFF6XCPV.js.map +6 -0
- package/dist/remote-execute-JN6DRFEU.js +129 -0
- package/dist/remote-execute-JN6DRFEU.js.map +6 -0
- package/dist/remote-execute.d.ts +3 -3
- package/dist/setup-git-MHK563LB.js +87 -0
- package/dist/setup-git-MHK563LB.js.map +6 -0
- package/dist/setup-git.d.ts +1 -1
- package/dist/skill-D74XVI6T.js +61 -0
- package/dist/skill-D74XVI6T.js.map +6 -0
- package/dist/store-27J4CQZ2.js +48 -0
- package/dist/store-27J4CQZ2.js.map +6 -0
- package/dist/structured-error-5MLWXYR3.js +14 -0
- package/dist/structured-error-5MLWXYR3.js.map +6 -0
- package/dist/structured-error.d.ts +1 -1
- package/dist/target-33ATHDUF.js +17 -0
- package/dist/target-33ATHDUF.js.map +6 -0
- package/package.json +12 -11
- package/skills/kody/SKILL.md +53 -50
- package/dist/add-mcp-install.js +0 -59
- package/dist/add-mcp-install.js.map +0 -1
- package/dist/api-token-store.js +0 -120
- package/dist/api-token-store.js.map +0 -1
- package/dist/api-token.js +0 -238
- package/dist/api-token.js.map +0 -1
- package/dist/auth-bootstrap.js +0 -373
- package/dist/auth-bootstrap.js.map +0 -1
- package/dist/auth.js +0 -386
- package/dist/auth.js.map +0 -1
- package/dist/capability-proxy.js +0 -527
- package/dist/capability-proxy.js.map +0 -1
- package/dist/credential-call-map.js +0 -155
- package/dist/credential-call-map.js.map +0 -1
- package/dist/credential-client-runtime-source.js +0 -9
- package/dist/credential-client-runtime-source.js.map +0 -1
- package/dist/credentialed-fetch-scan.js +0 -98
- package/dist/credentialed-fetch-scan.js.map +0 -1
- package/dist/defaults.js +0 -34
- package/dist/defaults.js.map +0 -1
- package/dist/detect-running-hosts.js +0 -13
- package/dist/detect-running-hosts.js.map +0 -1
- package/dist/dev/dev-assets.js +0 -202
- package/dist/dev/dev-assets.js.map +0 -1
- package/dist/dev/dev-bundler.js +0 -65
- package/dist/dev/dev-bundler.js.map +0 -1
- package/dist/dev/dev-events.js +0 -94
- package/dist/dev/dev-events.js.map +0 -1
- package/dist/dev/dev-port.js +0 -80
- package/dist/dev/dev-port.js.map +0 -1
- package/dist/dev/dev-protocol.js +0 -14
- package/dist/dev/dev-protocol.js.map +0 -1
- package/dist/dev/dev-registry.js +0 -95
- package/dist/dev/dev-registry.js.map +0 -1
- package/dist/dev/dev-watcher.js +0 -162
- package/dist/dev/dev-watcher.js.map +0 -1
- package/dist/dev/error-page.js +0 -64
- package/dist/dev/error-page.js.map +0 -1
- package/dist/dev/live-reload.js +0 -151
- package/dist/dev/live-reload.js.map +0 -1
- package/dist/dev/prebuild.js +0 -102
- package/dist/dev/prebuild.js.map +0 -1
- package/dist/dev/process-reaper.js +0 -151
- package/dist/dev/process-reaper.js.map +0 -1
- package/dist/dev/stack-trace.js +0 -56
- package/dist/dev/stack-trace.js.map +0 -1
- package/dist/dev/workerd-process.js +0 -118
- package/dist/dev/workerd-process.js.map +0 -1
- package/dist/dev-command.js +0 -676
- package/dist/dev-command.js.map +0 -1
- package/dist/discover-login-identity.js +0 -77
- package/dist/discover-login-identity.js.map +0 -1
- package/dist/discover-org.js +0 -62
- package/dist/discover-org.js.map +0 -1
- package/dist/git-credential.js +0 -147
- package/dist/git-credential.js.map +0 -1
- package/dist/help.js +0 -333
- package/dist/help.js.map +0 -1
- package/dist/host-catalog.js +0 -427
- package/dist/host-catalog.js.map +0 -1
- package/dist/host-config.js +0 -80
- package/dist/host-config.js.map +0 -1
- package/dist/http-error-body.js +0 -35
- package/dist/http-error-body.js.map +0 -1
- package/dist/install-hosts.js +0 -328
- package/dist/install-hosts.js.map +0 -1
- package/dist/install.js +0 -120
- package/dist/install.js.map +0 -1
- package/dist/invoke-passthrough.js +0 -60
- package/dist/invoke-passthrough.js.map +0 -1
- package/dist/local-bundle.js +0 -200
- package/dist/local-bundle.js.map +0 -1
- package/dist/local-execute-auth.js +0 -53
- package/dist/local-execute-auth.js.map +0 -1
- package/dist/local-execute.js +0 -338
- package/dist/local-execute.js.map +0 -1
- package/dist/local-gateway-fetch-forward.js +0 -135
- package/dist/local-gateway-fetch-forward.js.map +0 -1
- package/dist/local-host-runtime-surface.js +0 -75
- package/dist/local-host-runtime-surface.js.map +0 -1
- package/dist/local-package-graph.js +0 -405
- package/dist/local-package-graph.js.map +0 -1
- package/dist/local-package-run.js +0 -307
- package/dist/local-package-run.js.map +0 -1
- package/dist/local-runtime-bridge.js +0 -132
- package/dist/local-runtime-bridge.js.map +0 -1
- package/dist/local-runtime-source.js +0 -541
- package/dist/local-runtime-source.js.map +0 -1
- package/dist/login-callback-assets.js +0 -10
- package/dist/login-callback-assets.js.map +0 -1
- package/dist/login-callback-page.js +0 -362
- package/dist/login-callback-page.js.map +0 -1
- package/dist/mcp.d.ts +0 -34
- package/dist/mcp.js +0 -134
- package/dist/mcp.js.map +0 -1
- package/dist/mock/ensure-msw.js +0 -215
- package/dist/mock/ensure-msw.js.map +0 -1
- package/dist/mock/install-mock-fetch-shim.js +0 -36
- package/dist/mock/install-mock-fetch-shim.js.map +0 -1
- package/dist/mock/load-package-mocks.js +0 -136
- package/dist/mock/load-package-mocks.js.map +0 -1
- package/dist/mock/mock-fetch-gateway.js +0 -343
- package/dist/mock/mock-fetch-gateway.js.map +0 -1
- package/dist/mock/mock-gateway-fetch-shim.js +0 -104
- package/dist/mock/mock-gateway-fetch-shim.js.map +0 -1
- package/dist/mock/mock-server.js +0 -499
- package/dist/mock/mock-server.js.map +0 -1
- package/dist/mock/mock-storage.js +0 -186
- package/dist/mock/mock-storage.js.map +0 -1
- package/dist/mock/mock-supported.js +0 -63
- package/dist/mock/mock-supported.js.map +0 -1
- package/dist/mock-dep-resolve.js +0 -47
- package/dist/mock-dep-resolve.js.map +0 -1
- package/dist/mock-local-deps.js +0 -207
- package/dist/mock-local-deps.js.map +0 -1
- package/dist/network-error.js +0 -11
- package/dist/network-error.js.map +0 -1
- package/dist/node-engine.js +0 -21
- package/dist/node-engine.js.map +0 -1
- package/dist/oauth-provider.js +0 -107
- package/dist/oauth-provider.js.map +0 -1
- package/dist/onboarding-prompt.js +0 -15
- package/dist/onboarding-prompt.js.map +0 -1
- package/dist/open-api-client.js +0 -432
- package/dist/open-api-client.js.map +0 -1
- package/dist/open-url.js +0 -21
- package/dist/open-url.js.map +0 -1
- package/dist/org-resolve.js +0 -16
- package/dist/org-resolve.js.map +0 -1
- package/dist/org-slug.js +0 -11
- package/dist/org-slug.js.map +0 -1
- package/dist/org.js +0 -100
- package/dist/org.js.map +0 -1
- package/dist/package-app-dev.js +0 -922
- package/dist/package-app-dev.js.map +0 -1
- package/dist/package-collaborators.js +0 -179
- package/dist/package-collaborators.js.map +0 -1
- package/dist/package-info.js +0 -19
- package/dist/package-info.js.map +0 -1
- package/dist/package-local-runtime-source.js.map +0 -1
- package/dist/package-manifest.js +0 -364
- package/dist/package-manifest.js.map +0 -1
- package/dist/process-info.js +0 -14
- package/dist/process-info.js.map +0 -1
- package/dist/redact.js +0 -16
- package/dist/redact.js.map +0 -1
- package/dist/remote-execute.js +0 -108
- package/dist/remote-execute.js.map +0 -1
- package/dist/setup-git.js +0 -676
- package/dist/setup-git.js.map +0 -1
- package/dist/skill.js +0 -35
- package/dist/skill.js.map +0 -1
- package/dist/store.js +0 -597
- package/dist/store.js.map +0 -1
- package/dist/structured-error.js +0 -57
- package/dist/structured-error.js.map +0 -1
- package/dist/target.js +0 -52
- package/dist/target.js.map +0 -1
- package/dist/tool-result.js +0 -19
- package/dist/tool-result.js.map +0 -1
- package/dist/which.js +0 -22
- package/dist/which.js.map +0 -1
- package/dist/workerd-binary.js +0 -98
- package/dist/workerd-binary.js.map +0 -1
|
@@ -0,0 +1,746 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
unmockedRequestError
|
|
4
|
+
} from "./chunk-Y4FOJETX.js";
|
|
5
|
+
import {
|
|
6
|
+
StructuredCliError,
|
|
7
|
+
notImplementedInMock
|
|
8
|
+
} from "./chunk-XV6D6HSG.js";
|
|
9
|
+
import {
|
|
10
|
+
userCacheDir
|
|
11
|
+
} from "./chunk-DW5UTJ6T.js";
|
|
12
|
+
|
|
13
|
+
// src/mock/mock-server.ts
|
|
14
|
+
import {
|
|
15
|
+
createServer
|
|
16
|
+
} from "node:http";
|
|
17
|
+
|
|
18
|
+
// src/mock/mock-supported.ts
|
|
19
|
+
var mockOpenApiOperationIds = [
|
|
20
|
+
"search",
|
|
21
|
+
"searchTool",
|
|
22
|
+
"metaGetCurrentUser",
|
|
23
|
+
"usageGet"
|
|
24
|
+
];
|
|
25
|
+
var mockCapabilityPaths = [
|
|
26
|
+
"kody.metaGetCurrentUser",
|
|
27
|
+
"kody.search",
|
|
28
|
+
"kody.execute",
|
|
29
|
+
"kody.usageGet",
|
|
30
|
+
// Local package scratch storage via capability hops used by packageStorage()
|
|
31
|
+
// bridging in the mock runtime (see mock-server call dispatch).
|
|
32
|
+
"kody.__mockPackageStorageGet",
|
|
33
|
+
"kody.__mockPackageStorageSet",
|
|
34
|
+
"kody.__mockPackageStorageDelete",
|
|
35
|
+
"kody.__mockPackageStorageList",
|
|
36
|
+
"kody.__mockPackageStorageSql",
|
|
37
|
+
// Published package-app-kit / packageStorage helpers may hop these names
|
|
38
|
+
// directly (same scratch store as the __mock* bridges above).
|
|
39
|
+
"kody.packageStorageGet",
|
|
40
|
+
"kody.packageStorageSet",
|
|
41
|
+
"kody.packageStorageDelete",
|
|
42
|
+
"kody.packageStorageList",
|
|
43
|
+
"kody.packageStorageSql",
|
|
44
|
+
// Credential client: fake metadata + handles only (never prod secrets).
|
|
45
|
+
"kody.credentialClientOpen",
|
|
46
|
+
"kody.credentialClientOpenAll",
|
|
47
|
+
"kody.credentialClientCheck",
|
|
48
|
+
"kody.credentialClientRefresh",
|
|
49
|
+
// OAuth / ambient outbound hops — intercepted by the Node MSW gateway on
|
|
50
|
+
// --target mock (see mock-fetch-gateway.ts). Listed here so CapabilityProxy
|
|
51
|
+
// session probes treat them as known; the mock HTTP server refuses with
|
|
52
|
+
// unmocked_request if a call somehow bypasses the bridge.
|
|
53
|
+
"kody.authenticatedFetch",
|
|
54
|
+
"kody.gatewayFetch",
|
|
55
|
+
"kody.gatewayFetchStream",
|
|
56
|
+
// Read-only admin fixture so gift-cliff-ops-style packages can smoke locally.
|
|
57
|
+
"kody.adminUserList"
|
|
58
|
+
];
|
|
59
|
+
function isMockCapabilityPath(pathKey) {
|
|
60
|
+
return mockCapabilityPaths.includes(pathKey);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/mock/mock-storage.ts
|
|
64
|
+
import { mkdirSync } from "node:fs";
|
|
65
|
+
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
66
|
+
import { join } from "node:path";
|
|
67
|
+
import { DatabaseSync } from "node:sqlite";
|
|
68
|
+
var mockStateFile = "state.json";
|
|
69
|
+
function mockSessionRoot(sessionId, env = process.env) {
|
|
70
|
+
return join(userCacheDir(env), "mock-sessions", sessionId);
|
|
71
|
+
}
|
|
72
|
+
function defaultMockSessionId(env = process.env) {
|
|
73
|
+
return env.KODY_MOCK_SESSION_ID?.trim() || "default";
|
|
74
|
+
}
|
|
75
|
+
async function loadMockSession(input) {
|
|
76
|
+
const env = input.env ?? process.env;
|
|
77
|
+
const sessionId = input.sessionId ?? defaultMockSessionId(env);
|
|
78
|
+
const root = mockSessionRoot(sessionId, env);
|
|
79
|
+
if (input.reset) {
|
|
80
|
+
await rm(root, { recursive: true, force: true });
|
|
81
|
+
}
|
|
82
|
+
await mkdir(root, { recursive: true });
|
|
83
|
+
const path = join(root, mockStateFile);
|
|
84
|
+
try {
|
|
85
|
+
const raw = JSON.parse(await readFile(path, "utf8"));
|
|
86
|
+
if (raw?.version === 1 && raw.sessionId === sessionId) {
|
|
87
|
+
return normalizeMockSessionCredentials(raw);
|
|
88
|
+
}
|
|
89
|
+
} catch {
|
|
90
|
+
}
|
|
91
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
92
|
+
const fresh = {
|
|
93
|
+
version: 1,
|
|
94
|
+
sessionId,
|
|
95
|
+
createdAt: now,
|
|
96
|
+
updatedAt: now,
|
|
97
|
+
packageStorage: {},
|
|
98
|
+
credentials: {
|
|
99
|
+
MOCK_SECRET: {
|
|
100
|
+
id: "cred_mock_secret",
|
|
101
|
+
name: "MOCK_SECRET",
|
|
102
|
+
kind: "secret",
|
|
103
|
+
hosts: ["example.com"],
|
|
104
|
+
scope: "personal",
|
|
105
|
+
mockValue: "mock-secret-value"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
searchCatalog: [
|
|
109
|
+
{
|
|
110
|
+
type: "guide",
|
|
111
|
+
id: "local_execute",
|
|
112
|
+
title: "Local CLI execute",
|
|
113
|
+
description: "Prefer @kodycodes/cli execute --local when Node \u226522."
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
type: "capability",
|
|
117
|
+
id: "metaGetCurrentUser",
|
|
118
|
+
title: "metaGetCurrentUser",
|
|
119
|
+
description: "Return the current authenticated user and org binding."
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
type: "guide",
|
|
123
|
+
id: "package_apps",
|
|
124
|
+
title: "Package apps",
|
|
125
|
+
description: "Hosted Worker apps on *.kody.run; use kody dev for local."
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
};
|
|
129
|
+
await persistMockSession(fresh, env);
|
|
130
|
+
return fresh;
|
|
131
|
+
}
|
|
132
|
+
async function persistMockSession(state, env = process.env) {
|
|
133
|
+
state.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
134
|
+
const root = mockSessionRoot(state.sessionId, env);
|
|
135
|
+
await mkdir(root, { recursive: true });
|
|
136
|
+
await writeFile(
|
|
137
|
+
join(root, mockStateFile),
|
|
138
|
+
`${JSON.stringify(state, null, 2)}
|
|
139
|
+
`
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
function normalizeMockSessionCredentials(state) {
|
|
143
|
+
const credentials = {};
|
|
144
|
+
for (const [key, cred] of Object.entries(state.credentials ?? {})) {
|
|
145
|
+
credentials[key] = {
|
|
146
|
+
...cred,
|
|
147
|
+
hosts: Array.isArray(cred.hosts) && cred.hosts.length > 0 ? cred.hosts : ["example.com"],
|
|
148
|
+
scope: cred.scope === "org" ? "org" : "personal"
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
if (!credentials.MOCK_SECRET) {
|
|
152
|
+
credentials.MOCK_SECRET = {
|
|
153
|
+
id: "cred_mock_secret",
|
|
154
|
+
name: "MOCK_SECRET",
|
|
155
|
+
kind: "secret",
|
|
156
|
+
hosts: ["example.com"],
|
|
157
|
+
scope: "personal",
|
|
158
|
+
mockValue: "mock-secret-value"
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
state.credentials = credentials;
|
|
162
|
+
return state;
|
|
163
|
+
}
|
|
164
|
+
function packageStorageGet(state, packageId, key) {
|
|
165
|
+
return state.packageStorage[packageId]?.rows[key];
|
|
166
|
+
}
|
|
167
|
+
function packageStorageSet(state, packageId, key, value) {
|
|
168
|
+
const bucket = state.packageStorage[packageId] ??= { rows: {} };
|
|
169
|
+
bucket.rows[key] = value;
|
|
170
|
+
}
|
|
171
|
+
function packageStorageDelete(state, packageId, key) {
|
|
172
|
+
const bucket = state.packageStorage[packageId];
|
|
173
|
+
if (!bucket || !(key in bucket.rows)) return false;
|
|
174
|
+
delete bucket.rows[key];
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
function packageStorageList(state, packageId) {
|
|
178
|
+
const rows = state.packageStorage[packageId]?.rows ?? {};
|
|
179
|
+
return Object.entries(rows).map(([key, value]) => ({ key, value }));
|
|
180
|
+
}
|
|
181
|
+
var openSqlDbs = /* @__PURE__ */ new Map();
|
|
182
|
+
function packageSqlDbPath(state, packageId, env = process.env) {
|
|
183
|
+
const safe = packageId.replace(/[^a-zA-Z0-9._-]+/g, "_");
|
|
184
|
+
const dir = join(mockSessionRoot(state.sessionId, env), "sqlite");
|
|
185
|
+
mkdirSync(dir, { recursive: true });
|
|
186
|
+
return join(dir, `${safe || "package"}.sqlite`);
|
|
187
|
+
}
|
|
188
|
+
function openPackageSqlDb(state, packageId, env = process.env) {
|
|
189
|
+
const path = packageSqlDbPath(state, packageId, env);
|
|
190
|
+
const cacheKey = `${state.sessionId}:${path}`;
|
|
191
|
+
const existing = openSqlDbs.get(cacheKey);
|
|
192
|
+
if (existing) return existing;
|
|
193
|
+
const db = new DatabaseSync(path);
|
|
194
|
+
openSqlDbs.set(cacheKey, db);
|
|
195
|
+
return db;
|
|
196
|
+
}
|
|
197
|
+
function closePackageSqlDbsForSession(sessionId) {
|
|
198
|
+
for (const [key, db] of openSqlDbs) {
|
|
199
|
+
if (!key.startsWith(`${sessionId}:`)) continue;
|
|
200
|
+
try {
|
|
201
|
+
db.close();
|
|
202
|
+
} catch {
|
|
203
|
+
}
|
|
204
|
+
openSqlDbs.delete(key);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function packageStorageSql(state, packageId, query, bindings = [], env = process.env) {
|
|
208
|
+
const db = openPackageSqlDb(state, packageId, env);
|
|
209
|
+
const stmt = db.prepare(query);
|
|
210
|
+
const params = bindings.map((value) => {
|
|
211
|
+
if (value === null) return null;
|
|
212
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint") {
|
|
213
|
+
return value;
|
|
214
|
+
}
|
|
215
|
+
if (typeof value === "boolean") return value ? 1 : 0;
|
|
216
|
+
if (value instanceof Uint8Array) return value;
|
|
217
|
+
return String(value);
|
|
218
|
+
});
|
|
219
|
+
const trimmed = query.trimStart().toLowerCase();
|
|
220
|
+
const isQuery = trimmed.startsWith("select") || trimmed.startsWith("with") || trimmed.startsWith("pragma") || trimmed.startsWith("explain");
|
|
221
|
+
if (isQuery) {
|
|
222
|
+
const rows = stmt.all(...params);
|
|
223
|
+
return { rows };
|
|
224
|
+
}
|
|
225
|
+
const info = stmt.run(...params);
|
|
226
|
+
return {
|
|
227
|
+
rows: [],
|
|
228
|
+
changes: typeof info.changes === "number" ? info.changes : 0
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// src/mock/mock-server.ts
|
|
233
|
+
var mockTokenPrefix = "kody_mock_";
|
|
234
|
+
function isMockApiToken(token) {
|
|
235
|
+
return token.startsWith(mockTokenPrefix) || token === "mock";
|
|
236
|
+
}
|
|
237
|
+
function mintMockApiToken(sessionId) {
|
|
238
|
+
return `${mockTokenPrefix}${sessionId}`;
|
|
239
|
+
}
|
|
240
|
+
async function startMockServer(options = {}) {
|
|
241
|
+
const sessionIdForClose = options.sessionId?.trim() || defaultMockSessionId(options.env ?? process.env);
|
|
242
|
+
if (options.resetStorage) {
|
|
243
|
+
closePackageSqlDbsForSession(sessionIdForClose);
|
|
244
|
+
}
|
|
245
|
+
let state = await loadMockSession({
|
|
246
|
+
sessionId: options.sessionId,
|
|
247
|
+
env: options.env,
|
|
248
|
+
reset: options.resetStorage
|
|
249
|
+
});
|
|
250
|
+
const packageId = options.packageId ?? `local-${state.sessionId}`;
|
|
251
|
+
const orgSlug = options.orgSlug?.trim() || "mock-org";
|
|
252
|
+
const env = options.env;
|
|
253
|
+
const server = createServer((req, res) => {
|
|
254
|
+
void handleRequest(req, res, {
|
|
255
|
+
getState: () => state,
|
|
256
|
+
setState: async (next) => {
|
|
257
|
+
state = next;
|
|
258
|
+
await persistMockSession(state, env);
|
|
259
|
+
},
|
|
260
|
+
packageId,
|
|
261
|
+
orgSlug,
|
|
262
|
+
env
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
const host = options.host ?? "127.0.0.1";
|
|
266
|
+
const port = options.port ?? 0;
|
|
267
|
+
await new Promise((resolve, reject) => {
|
|
268
|
+
server.once("error", reject);
|
|
269
|
+
server.listen(port, host, () => resolve());
|
|
270
|
+
});
|
|
271
|
+
const address = server.address();
|
|
272
|
+
const url = `http://${host}:${address.port}`;
|
|
273
|
+
return {
|
|
274
|
+
url,
|
|
275
|
+
port: address.port,
|
|
276
|
+
sessionId: state.sessionId,
|
|
277
|
+
state: () => state,
|
|
278
|
+
close: () => new Promise((resolve, reject) => {
|
|
279
|
+
server.close((error) => error ? reject(error) : resolve());
|
|
280
|
+
})
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
async function ensureMockTarget(input) {
|
|
284
|
+
if (input.existing) {
|
|
285
|
+
return {
|
|
286
|
+
apiUrl: input.existing.url,
|
|
287
|
+
token: mintMockApiToken(input.existing.sessionId),
|
|
288
|
+
server: input.existing,
|
|
289
|
+
started: false
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
const server = await startMockServer({
|
|
293
|
+
sessionId: input.sessionId,
|
|
294
|
+
resetStorage: input.resetStorage,
|
|
295
|
+
packageId: input.packageId,
|
|
296
|
+
orgSlug: input.orgSlug,
|
|
297
|
+
env: input.env
|
|
298
|
+
});
|
|
299
|
+
return {
|
|
300
|
+
apiUrl: server.url,
|
|
301
|
+
token: mintMockApiToken(server.sessionId),
|
|
302
|
+
server,
|
|
303
|
+
started: true
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
async function handleRequest(req, res, ctx) {
|
|
307
|
+
try {
|
|
308
|
+
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
309
|
+
const method = (req.method ?? "GET").toUpperCase();
|
|
310
|
+
const body = await readJsonBody(req);
|
|
311
|
+
const requestOrg = url.searchParams.get("org")?.trim() || void 0;
|
|
312
|
+
const effectiveOrg = requestOrg || ctx.orgSlug;
|
|
313
|
+
const callCtx = { ...ctx, orgSlug: effectiveOrg };
|
|
314
|
+
if (method === "GET" && url.pathname === "/openapi.json") {
|
|
315
|
+
return sendJson(res, 200, mockOpenApiDocument());
|
|
316
|
+
}
|
|
317
|
+
if (method === "GET" && url.pathname === "/v1/capability-proxy/session") {
|
|
318
|
+
assertMockAuth(req);
|
|
319
|
+
return sendJson(res, 200, {
|
|
320
|
+
scopes: [
|
|
321
|
+
"org:execute",
|
|
322
|
+
"org:read",
|
|
323
|
+
"package:execute",
|
|
324
|
+
"package:read",
|
|
325
|
+
"search:read"
|
|
326
|
+
],
|
|
327
|
+
features: ["local-execute", "credential-call-map"],
|
|
328
|
+
expiresAt: new Date(Date.now() + 864e5).toISOString()
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
if (method === "POST" && url.pathname === "/v1/capability-proxy/call") {
|
|
332
|
+
assertMockAuth(req);
|
|
333
|
+
const path = Array.isArray(body?.path) ? body.path : null;
|
|
334
|
+
const args = Array.isArray(body?.args) ? body.args : [];
|
|
335
|
+
if (!path || path.length === 0) {
|
|
336
|
+
return sendJson(res, 400, {
|
|
337
|
+
error: { code: "invalid_request", message: "path is required" }
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
const pathKey = path.join(".");
|
|
341
|
+
if (!isMockCapabilityPath(pathKey)) {
|
|
342
|
+
const err2 = notImplementedInMock({
|
|
343
|
+
operation: `CapabilityProxy ${pathKey}`
|
|
344
|
+
});
|
|
345
|
+
return sendJson(res, 501, { error: err2.toJSON() });
|
|
346
|
+
}
|
|
347
|
+
try {
|
|
348
|
+
const result = await dispatchCapabilityCall(pathKey, args, callCtx);
|
|
349
|
+
return sendJson(res, 200, { result });
|
|
350
|
+
} catch (error) {
|
|
351
|
+
if (error instanceof StructuredCliError) {
|
|
352
|
+
const status = error.code === "unmocked_request" ? 400 : 501;
|
|
353
|
+
return sendJson(res, status, { error: error.toJSON() });
|
|
354
|
+
}
|
|
355
|
+
throw error;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
if (method === "POST" && url.pathname === "/v1/local-execute/package-graph") {
|
|
359
|
+
assertMockAuth(req);
|
|
360
|
+
return sendJson(res, 200, {
|
|
361
|
+
modules: [],
|
|
362
|
+
compatibilityDate: "2026-04-16",
|
|
363
|
+
compatibilityFlags: ["nodejs_compat"]
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
if (method === "GET" && url.pathname === "/v1/search") {
|
|
367
|
+
assertMockAuth(req);
|
|
368
|
+
const query = url.searchParams.get("query") ?? "";
|
|
369
|
+
const entity = url.searchParams.get("entity") ?? void 0;
|
|
370
|
+
return sendJson(
|
|
371
|
+
res,
|
|
372
|
+
200,
|
|
373
|
+
mockSearch(callCtx.getState(), { query, entity })
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
if (method === "POST" && url.pathname === "/v1/search/tool") {
|
|
377
|
+
assertMockAuth(req);
|
|
378
|
+
const query = typeof body?.query === "string" ? body.query : "";
|
|
379
|
+
const entity = typeof body?.entity === "string" ? body.entity : void 0;
|
|
380
|
+
const limit = typeof body?.limit === "number" ? body.limit : void 0;
|
|
381
|
+
return sendJson(
|
|
382
|
+
res,
|
|
383
|
+
200,
|
|
384
|
+
mockSearch(callCtx.getState(), { query, entity, limit })
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
if (method === "GET" && url.pathname === "/v1/me") {
|
|
388
|
+
assertMockAuth(req);
|
|
389
|
+
return sendJson(
|
|
390
|
+
res,
|
|
391
|
+
200,
|
|
392
|
+
mockCurrentUser(callCtx.getState(), callCtx.orgSlug)
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
if (url.pathname.startsWith("/v1/")) {
|
|
396
|
+
const err2 = notImplementedInMock({
|
|
397
|
+
operation: `${method} ${url.pathname}`
|
|
398
|
+
});
|
|
399
|
+
return sendJson(res, 501, { error: err2.toJSON() });
|
|
400
|
+
}
|
|
401
|
+
const err = notImplementedInMock({ operation: `${method} ${url.pathname}` });
|
|
402
|
+
return sendJson(res, 501, { error: err.toJSON() });
|
|
403
|
+
} catch (error) {
|
|
404
|
+
if (error instanceof AuthError) {
|
|
405
|
+
return sendJson(res, 401, {
|
|
406
|
+
error: { code: "unauthorized", message: error.message }
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
410
|
+
return sendJson(res, 500, {
|
|
411
|
+
error: { code: "mock_internal_error", message }
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
var AuthError = class extends Error {
|
|
416
|
+
constructor(message) {
|
|
417
|
+
super(message);
|
|
418
|
+
this.name = "AuthError";
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
function assertMockAuth(req) {
|
|
422
|
+
const header = req.headers.authorization;
|
|
423
|
+
if (typeof header !== "string" || !header.toLowerCase().startsWith("bearer ")) {
|
|
424
|
+
throw new AuthError("Mock API requires Authorization: Bearer <token>.");
|
|
425
|
+
}
|
|
426
|
+
const token = header.slice("bearer ".length).trim();
|
|
427
|
+
if (!isMockApiToken(token) && !token.startsWith("kody_at_") && token.length > 0) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
if (!token) throw new AuthError("Mock API bearer token is empty.");
|
|
431
|
+
}
|
|
432
|
+
async function dispatchCapabilityCall(pathKey, args, ctx) {
|
|
433
|
+
const state = ctx.getState();
|
|
434
|
+
switch (pathKey) {
|
|
435
|
+
case "kody.metaGetCurrentUser":
|
|
436
|
+
return mockCurrentUser(state, ctx.orgSlug);
|
|
437
|
+
case "kody.search": {
|
|
438
|
+
const params = args[0] ?? {};
|
|
439
|
+
return mockSearch(state, params);
|
|
440
|
+
}
|
|
441
|
+
case "kody.usageGet":
|
|
442
|
+
return {
|
|
443
|
+
period: "mock",
|
|
444
|
+
credits: { used: 0, limit: null },
|
|
445
|
+
note: "Mock usage \u2014 not real entitlement data."
|
|
446
|
+
};
|
|
447
|
+
case "kody.execute": {
|
|
448
|
+
const params = args[0] ?? {};
|
|
449
|
+
throw notImplementedInMock({
|
|
450
|
+
operation: "kody.execute (cloud sandbox)",
|
|
451
|
+
fix: "Use `kody execute --local --target mock` so the module runs in local workerd against this mock."
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
case "kody.__mockPackageStorageGet":
|
|
455
|
+
case "kody.packageStorageGet": {
|
|
456
|
+
const key = String(args[0]?.key ?? "");
|
|
457
|
+
return { value: packageStorageGet(state, ctx.packageId, key) ?? null };
|
|
458
|
+
}
|
|
459
|
+
case "kody.__mockPackageStorageSet":
|
|
460
|
+
case "kody.packageStorageSet": {
|
|
461
|
+
const input = args[0];
|
|
462
|
+
packageStorageSet(
|
|
463
|
+
state,
|
|
464
|
+
ctx.packageId,
|
|
465
|
+
String(input?.key ?? ""),
|
|
466
|
+
input?.value
|
|
467
|
+
);
|
|
468
|
+
await ctx.setState(state);
|
|
469
|
+
return { ok: true };
|
|
470
|
+
}
|
|
471
|
+
case "kody.__mockPackageStorageDelete":
|
|
472
|
+
case "kody.packageStorageDelete": {
|
|
473
|
+
const key = String(args[0]?.key ?? "");
|
|
474
|
+
const deleted = packageStorageDelete(state, ctx.packageId, key);
|
|
475
|
+
await ctx.setState(state);
|
|
476
|
+
return { deleted };
|
|
477
|
+
}
|
|
478
|
+
case "kody.__mockPackageStorageList":
|
|
479
|
+
case "kody.packageStorageList": {
|
|
480
|
+
return { entries: packageStorageList(state, ctx.packageId) };
|
|
481
|
+
}
|
|
482
|
+
case "kody.__mockPackageStorageSql":
|
|
483
|
+
case "kody.packageStorageSql": {
|
|
484
|
+
const input = args[0] ?? {};
|
|
485
|
+
const query = String(input.query ?? "");
|
|
486
|
+
if (!query.trim()) {
|
|
487
|
+
throw new Error(
|
|
488
|
+
"packageStorage().sql requires a non-empty query string."
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
return packageStorageSql(
|
|
492
|
+
state,
|
|
493
|
+
ctx.packageId,
|
|
494
|
+
query,
|
|
495
|
+
Array.isArray(input.bindings) ? input.bindings : [],
|
|
496
|
+
ctx.env
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
case "kody.credentialClientOpen": {
|
|
500
|
+
const input = args[0] ?? {};
|
|
501
|
+
const key = String(input.key ?? input.name ?? args[0] ?? "").trim();
|
|
502
|
+
const opened = openMockCredential(state, key);
|
|
503
|
+
return { ok: true, value: opened };
|
|
504
|
+
}
|
|
505
|
+
case "kody.credentialClientOpenAll": {
|
|
506
|
+
const key = String(args[0]?.key ?? "").trim();
|
|
507
|
+
const matches = Object.values(state.credentials).filter(
|
|
508
|
+
(cred) => !key || cred.name === key || cred.name.toUpperCase() === key.toUpperCase() || cred.id === key
|
|
509
|
+
);
|
|
510
|
+
if (key && matches.length === 0) {
|
|
511
|
+
return { ok: true, value: [] };
|
|
512
|
+
}
|
|
513
|
+
const opened = (key ? matches : Object.values(state.credentials)).map(
|
|
514
|
+
(cred) => mockOpenedCredential(cred)
|
|
515
|
+
);
|
|
516
|
+
return { ok: true, value: opened };
|
|
517
|
+
}
|
|
518
|
+
case "kody.credentialClientCheck":
|
|
519
|
+
return {
|
|
520
|
+
ok: true,
|
|
521
|
+
value: { warnings: [], checked: args[0] ?? null, strict: false }
|
|
522
|
+
};
|
|
523
|
+
case "kody.credentialClientRefresh":
|
|
524
|
+
return { ok: true, value: { refreshed: false, mock: true } };
|
|
525
|
+
case "kody.authenticatedFetch":
|
|
526
|
+
case "kody.gatewayFetch":
|
|
527
|
+
case "kody.gatewayFetchStream": {
|
|
528
|
+
const request = args[0] ?? {};
|
|
529
|
+
const nested = request.request ?? request;
|
|
530
|
+
const method = String(nested.method ?? "GET").toUpperCase();
|
|
531
|
+
const url = String(nested.url ?? "");
|
|
532
|
+
if (url) throw unmockedRequestError(method, url);
|
|
533
|
+
throw new StructuredCliError({
|
|
534
|
+
code: "unmocked_request",
|
|
535
|
+
message: `Unmocked ${pathKey} under --target mock (missing request.url).`,
|
|
536
|
+
target: "mock",
|
|
537
|
+
where: pathKey,
|
|
538
|
+
fix: "Pass request.url, or add handlers in .kody/mocks.ts. createAuthenticatedFetch, credential().fetch, gatewayFetch, and gatewayFetchStream go through the same MSW gateway.",
|
|
539
|
+
details: { mocksPath: ".kody/mocks.ts" }
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
case "kody.adminUserList": {
|
|
543
|
+
const params = args[0] ?? {};
|
|
544
|
+
const page = typeof params.page === "number" ? params.page : 1;
|
|
545
|
+
const pageSize = typeof params.pageSize === "number" ? params.pageSize : typeof params.limit === "number" ? params.limit : 20;
|
|
546
|
+
return {
|
|
547
|
+
total: 1,
|
|
548
|
+
page,
|
|
549
|
+
pageSize,
|
|
550
|
+
users: [
|
|
551
|
+
{
|
|
552
|
+
stableUserId: "user_mock",
|
|
553
|
+
username: "mock-user",
|
|
554
|
+
email: "mock@example.com",
|
|
555
|
+
email_verified: true,
|
|
556
|
+
email_verified_at: "2026-01-01T00:00:00.000Z",
|
|
557
|
+
plan: "free",
|
|
558
|
+
manualPlan: "free",
|
|
559
|
+
stripePlan: null,
|
|
560
|
+
effectivePlan: "free",
|
|
561
|
+
secondAgentGiftExpiresAt: null,
|
|
562
|
+
referralCreditExpiresAt: null,
|
|
563
|
+
overlayExpiresAt: null,
|
|
564
|
+
isProOverlay: false,
|
|
565
|
+
overlayType: null,
|
|
566
|
+
entitlementLadder: "public",
|
|
567
|
+
stripeCustomerLinked: false,
|
|
568
|
+
suspended_at: null,
|
|
569
|
+
email_outbound_paused_at: null,
|
|
570
|
+
email_verification_delivery: null,
|
|
571
|
+
email_verification_delivery_detail: null,
|
|
572
|
+
utm_source: null,
|
|
573
|
+
utm_medium: null,
|
|
574
|
+
utm_campaign: null,
|
|
575
|
+
utm_content: null,
|
|
576
|
+
utm_term: null,
|
|
577
|
+
first_touch_landing_path: null,
|
|
578
|
+
first_touch_referrer: null,
|
|
579
|
+
first_mcp_connected_at: null,
|
|
580
|
+
first_execute_at: null,
|
|
581
|
+
first_search_at: null,
|
|
582
|
+
first_saved_package_at: null,
|
|
583
|
+
mcp_client_name: null,
|
|
584
|
+
last_active_at: null,
|
|
585
|
+
created_at: "2026-01-01T00:00:00.000Z",
|
|
586
|
+
updated_at: "2026-01-01T00:00:00.000Z",
|
|
587
|
+
roles: ["user"]
|
|
588
|
+
}
|
|
589
|
+
]
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
default: {
|
|
593
|
+
const exhaustive = pathKey;
|
|
594
|
+
throw notImplementedInMock({ operation: String(exhaustive) });
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
function openMockCredential(state, key) {
|
|
599
|
+
const cred = state.credentials[key] ?? state.credentials[key.toUpperCase()] ?? Object.values(state.credentials).find(
|
|
600
|
+
(entry) => entry.name === key || entry.name.toUpperCase() === key.toUpperCase()
|
|
601
|
+
);
|
|
602
|
+
if (!cred) {
|
|
603
|
+
throw new StructuredCliError({
|
|
604
|
+
code: "missing_secret",
|
|
605
|
+
message: `Mock credential ${JSON.stringify(key)} is not defined for this session.`,
|
|
606
|
+
target: "mock",
|
|
607
|
+
fix: "Add a fake credential to the mock session state or use --target prod with a real allow-listed secret.",
|
|
608
|
+
details: { key }
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
return mockOpenedCredential(cred);
|
|
612
|
+
}
|
|
613
|
+
function mockOpenedCredential(cred) {
|
|
614
|
+
return {
|
|
615
|
+
handle: `mock-handle:${cred.id}`,
|
|
616
|
+
key: cred.name,
|
|
617
|
+
name: cred.name,
|
|
618
|
+
scope: cred.scope ?? "personal",
|
|
619
|
+
kind: cred.kind,
|
|
620
|
+
hosts: [...cred.hosts?.length ? cred.hosts : ["example.com"]],
|
|
621
|
+
hint: "mock",
|
|
622
|
+
// Never expose a real secret; mockValue stays session-local scratch only.
|
|
623
|
+
metadata: { mock: true }
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
function mockCurrentUser(state, orgSlug) {
|
|
627
|
+
return {
|
|
628
|
+
user_id: "user_mock",
|
|
629
|
+
username: "mock-user",
|
|
630
|
+
email: "mock@example.com",
|
|
631
|
+
display_name: "Mock User",
|
|
632
|
+
org: {
|
|
633
|
+
slug: orgSlug || "mock-org"
|
|
634
|
+
},
|
|
635
|
+
mockSessionId: state.sessionId
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
function mockSearch(state, params) {
|
|
639
|
+
if (params.entity) {
|
|
640
|
+
const hit = state.searchCatalog.find(
|
|
641
|
+
(item) => `${item.type}:${item.id}` === params.entity || item.id === params.entity
|
|
642
|
+
);
|
|
643
|
+
return {
|
|
644
|
+
conversationId: `mock-${state.sessionId}`,
|
|
645
|
+
matches: hit ? [
|
|
646
|
+
{
|
|
647
|
+
type: hit.type,
|
|
648
|
+
id: hit.id,
|
|
649
|
+
entityRef: `${hit.type}:${hit.id}`,
|
|
650
|
+
title: hit.title,
|
|
651
|
+
description: hit.description
|
|
652
|
+
}
|
|
653
|
+
] : [],
|
|
654
|
+
offline: false,
|
|
655
|
+
warnings: [],
|
|
656
|
+
guidance: "Mock catalog \u2014 not the live Kody search index."
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
const q = (params.query ?? "").toLowerCase().trim();
|
|
660
|
+
const matches = state.searchCatalog.filter(
|
|
661
|
+
(item) => !q || item.title.toLowerCase().includes(q) || item.description.toLowerCase().includes(q) || item.id.toLowerCase().includes(q)
|
|
662
|
+
).slice(0, params.limit ?? 20).map((item) => ({
|
|
663
|
+
type: item.type,
|
|
664
|
+
id: item.id,
|
|
665
|
+
entityRef: `${item.type}:${item.id}`,
|
|
666
|
+
title: item.title,
|
|
667
|
+
description: item.description
|
|
668
|
+
}));
|
|
669
|
+
return {
|
|
670
|
+
conversationId: `mock-${state.sessionId}`,
|
|
671
|
+
matches,
|
|
672
|
+
offline: false,
|
|
673
|
+
warnings: [],
|
|
674
|
+
guidance: "Mock catalog \u2014 not the live Kody search index."
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
function mockOpenApiDocument() {
|
|
678
|
+
return {
|
|
679
|
+
openapi: "3.1.0",
|
|
680
|
+
info: {
|
|
681
|
+
title: "Kody API (CLI mock)",
|
|
682
|
+
version: "mock",
|
|
683
|
+
description: "Subset document for the CLI mock. Unsupported operations refuse with not_implemented_in_mock."
|
|
684
|
+
},
|
|
685
|
+
paths: {
|
|
686
|
+
"/v1/search": {
|
|
687
|
+
get: {
|
|
688
|
+
operationId: "search",
|
|
689
|
+
summary: "Search the mock catalog"
|
|
690
|
+
}
|
|
691
|
+
},
|
|
692
|
+
"/v1/search/tool": {
|
|
693
|
+
post: {
|
|
694
|
+
operationId: "searchTool",
|
|
695
|
+
summary: "Search the mock catalog (MCP search tool shape)"
|
|
696
|
+
}
|
|
697
|
+
},
|
|
698
|
+
"/v1/me": {
|
|
699
|
+
get: {
|
|
700
|
+
operationId: "metaGetCurrentUser",
|
|
701
|
+
summary: "Mock current user"
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
},
|
|
705
|
+
"x-kody-mock-operations": [...mockOpenApiOperationIds]
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
async function readJsonBody(req) {
|
|
709
|
+
const chunks = [];
|
|
710
|
+
for await (const chunk of req) {
|
|
711
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
712
|
+
}
|
|
713
|
+
if (chunks.length === 0) return null;
|
|
714
|
+
const text = Buffer.concat(chunks).toString("utf8").trim();
|
|
715
|
+
if (!text) return null;
|
|
716
|
+
try {
|
|
717
|
+
return JSON.parse(text);
|
|
718
|
+
} catch {
|
|
719
|
+
return null;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
function sendJson(res, status, body) {
|
|
723
|
+
const payload = JSON.stringify(body);
|
|
724
|
+
res.writeHead(status, {
|
|
725
|
+
"content-type": "application/json; charset=utf-8",
|
|
726
|
+
"content-length": Buffer.byteLength(payload)
|
|
727
|
+
});
|
|
728
|
+
res.end(payload);
|
|
729
|
+
}
|
|
730
|
+
async function withMockServer(options, fn) {
|
|
731
|
+
const server = await startMockServer(options);
|
|
732
|
+
try {
|
|
733
|
+
return await fn(server);
|
|
734
|
+
} finally {
|
|
735
|
+
await server.close();
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
export {
|
|
740
|
+
isMockApiToken,
|
|
741
|
+
mintMockApiToken,
|
|
742
|
+
startMockServer,
|
|
743
|
+
ensureMockTarget,
|
|
744
|
+
withMockServer
|
|
745
|
+
};
|
|
746
|
+
//# sourceMappingURL=chunk-FBEZ6PZ7.js.map
|