toolhome 0.5.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/LICENSE +21 -0
- package/README.md +295 -0
- package/README.zh.md +281 -0
- package/dist/server/app.d.ts +16 -0
- package/dist/server/app.d.ts.map +1 -0
- package/dist/server/app.js +166 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/cli/main.d.ts +3 -0
- package/dist/server/cli/main.d.ts.map +1 -0
- package/dist/server/cli/main.js +587 -0
- package/dist/server/cli/main.js.map +1 -0
- package/dist/server/cli-plane/allow-list.d.ts +18 -0
- package/dist/server/cli-plane/allow-list.d.ts.map +1 -0
- package/dist/server/cli-plane/allow-list.js +28 -0
- package/dist/server/cli-plane/allow-list.js.map +1 -0
- package/dist/server/cli-plane/cli-service.d.ts +41 -0
- package/dist/server/cli-plane/cli-service.d.ts.map +1 -0
- package/dist/server/cli-plane/cli-service.js +282 -0
- package/dist/server/cli-plane/cli-service.js.map +1 -0
- package/dist/server/cli-plane/frames.d.ts +26 -0
- package/dist/server/cli-plane/frames.d.ts.map +1 -0
- package/dist/server/cli-plane/frames.js +12 -0
- package/dist/server/cli-plane/frames.js.map +1 -0
- package/dist/server/cli-plane/models.d.ts +174 -0
- package/dist/server/cli-plane/models.d.ts.map +1 -0
- package/dist/server/cli-plane/models.js +169 -0
- package/dist/server/cli-plane/models.js.map +1 -0
- package/dist/server/cli-plane/routes.d.ts +32 -0
- package/dist/server/cli-plane/routes.d.ts.map +1 -0
- package/dist/server/cli-plane/routes.js +94 -0
- package/dist/server/cli-plane/routes.js.map +1 -0
- package/dist/server/cli-plane/runner.d.ts +41 -0
- package/dist/server/cli-plane/runner.d.ts.map +1 -0
- package/dist/server/cli-plane/runner.js +163 -0
- package/dist/server/cli-plane/runner.js.map +1 -0
- package/dist/server/cli-plane/status.d.ts +12 -0
- package/dist/server/cli-plane/status.d.ts.map +1 -0
- package/dist/server/cli-plane/status.js +24 -0
- package/dist/server/cli-plane/status.js.map +1 -0
- package/dist/server/config/harness-import.d.ts +44 -0
- package/dist/server/config/harness-import.d.ts.map +1 -0
- package/dist/server/config/harness-import.js +166 -0
- package/dist/server/config/harness-import.js.map +1 -0
- package/dist/server/config.d.ts +20 -0
- package/dist/server/config.d.ts.map +1 -0
- package/dist/server/config.js +80 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/control/client.d.ts +24 -0
- package/dist/server/control/client.d.ts.map +1 -0
- package/dist/server/control/client.js +115 -0
- package/dist/server/control/client.js.map +1 -0
- package/dist/server/control/control-api.d.ts +39 -0
- package/dist/server/control/control-api.d.ts.map +1 -0
- package/dist/server/control/control-api.js +291 -0
- package/dist/server/control/control-api.js.map +1 -0
- package/dist/server/control/control-service.d.ts +713 -0
- package/dist/server/control/control-service.d.ts.map +1 -0
- package/dist/server/control/control-service.js +693 -0
- package/dist/server/control/control-service.js.map +1 -0
- package/dist/server/control/openapi.d.ts +2 -0
- package/dist/server/control/openapi.d.ts.map +1 -0
- package/dist/server/control/openapi.js +370 -0
- package/dist/server/control/openapi.js.map +1 -0
- package/dist/server/data-plane/data-plane.d.ts +20 -0
- package/dist/server/data-plane/data-plane.d.ts.map +1 -0
- package/dist/server/data-plane/data-plane.js +335 -0
- package/dist/server/data-plane/data-plane.js.map +1 -0
- package/dist/server/data-plane/gateway-server.d.ts +13 -0
- package/dist/server/data-plane/gateway-server.d.ts.map +1 -0
- package/dist/server/data-plane/gateway-server.js +796 -0
- package/dist/server/data-plane/gateway-server.js.map +1 -0
- package/dist/server/data-plane/legacy-session.d.ts +18 -0
- package/dist/server/data-plane/legacy-session.d.ts.map +1 -0
- package/dist/server/data-plane/legacy-session.js +137 -0
- package/dist/server/data-plane/legacy-session.js.map +1 -0
- package/dist/server/data-plane/projection.d.ts +18 -0
- package/dist/server/data-plane/projection.d.ts.map +1 -0
- package/dist/server/data-plane/projection.js +44 -0
- package/dist/server/data-plane/projection.js.map +1 -0
- package/dist/server/data-plane/registry.d.ts +31 -0
- package/dist/server/data-plane/registry.d.ts.map +1 -0
- package/dist/server/data-plane/registry.js +129 -0
- package/dist/server/data-plane/registry.js.map +1 -0
- package/dist/server/data-plane/task-extension.d.ts +7 -0
- package/dist/server/data-plane/task-extension.d.ts.map +1 -0
- package/dist/server/data-plane/task-extension.js +33 -0
- package/dist/server/data-plane/task-extension.js.map +1 -0
- package/dist/server/data-plane/virtualization.d.ts +35 -0
- package/dist/server/data-plane/virtualization.d.ts.map +1 -0
- package/dist/server/data-plane/virtualization.js +228 -0
- package/dist/server/data-plane/virtualization.js.map +1 -0
- package/dist/server/domain/errors.d.ts +9 -0
- package/dist/server/domain/errors.d.ts.map +1 -0
- package/dist/server/domain/errors.js +19 -0
- package/dist/server/domain/errors.js.map +1 -0
- package/dist/server/domain/models.d.ts +720 -0
- package/dist/server/domain/models.d.ts.map +1 -0
- package/dist/server/domain/models.js +327 -0
- package/dist/server/domain/models.js.map +1 -0
- package/dist/server/main.d.ts +2 -0
- package/dist/server/main.d.ts.map +1 -0
- package/dist/server/main.js +37 -0
- package/dist/server/main.js.map +1 -0
- package/dist/server/manage/management-mcp.d.ts +27 -0
- package/dist/server/manage/management-mcp.d.ts.map +1 -0
- package/dist/server/manage/management-mcp.js +431 -0
- package/dist/server/manage/management-mcp.js.map +1 -0
- package/dist/server/market/catalog.d.ts +111 -0
- package/dist/server/market/catalog.d.ts.map +1 -0
- package/dist/server/market/catalog.js +784 -0
- package/dist/server/market/catalog.js.map +1 -0
- package/dist/server/market/installers.d.ts +64 -0
- package/dist/server/market/installers.d.ts.map +1 -0
- package/dist/server/market/installers.js +181 -0
- package/dist/server/market/installers.js.map +1 -0
- package/dist/server/market/market-service.d.ts +146 -0
- package/dist/server/market/market-service.d.ts.map +1 -0
- package/dist/server/market/market-service.js +930 -0
- package/dist/server/market/market-service.js.map +1 -0
- package/dist/server/observability/call-recorder.d.ts +22 -0
- package/dist/server/observability/call-recorder.d.ts.map +1 -0
- package/dist/server/observability/call-recorder.js +99 -0
- package/dist/server/observability/call-recorder.js.map +1 -0
- package/dist/server/observability/logger.d.ts +16 -0
- package/dist/server/observability/logger.d.ts.map +1 -0
- package/dist/server/observability/logger.js +25 -0
- package/dist/server/observability/logger.js.map +1 -0
- package/dist/server/security/api-keys.d.ts +15 -0
- package/dist/server/security/api-keys.d.ts.map +1 -0
- package/dist/server/security/api-keys.js +35 -0
- package/dist/server/security/api-keys.js.map +1 -0
- package/dist/server/security/auth-service.d.ts +26 -0
- package/dist/server/security/auth-service.d.ts.map +1 -0
- package/dist/server/security/auth-service.js +76 -0
- package/dist/server/security/auth-service.js.map +1 -0
- package/dist/server/security/control-session.d.ts +9 -0
- package/dist/server/security/control-session.d.ts.map +1 -0
- package/dist/server/security/control-session.js +51 -0
- package/dist/server/security/control-session.js.map +1 -0
- package/dist/server/security/credential-materializer.d.ts +20 -0
- package/dist/server/security/credential-materializer.d.ts.map +1 -0
- package/dist/server/security/credential-materializer.js +82 -0
- package/dist/server/security/credential-materializer.js.map +1 -0
- package/dist/server/security/cursor-codec.d.ts +13 -0
- package/dist/server/security/cursor-codec.d.ts.map +1 -0
- package/dist/server/security/cursor-codec.js +43 -0
- package/dist/server/security/cursor-codec.js.map +1 -0
- package/dist/server/security/oauth-routes.d.ts +21 -0
- package/dist/server/security/oauth-routes.d.ts.map +1 -0
- package/dist/server/security/oauth-routes.js +100 -0
- package/dist/server/security/oauth-routes.js.map +1 -0
- package/dist/server/security/oauth-server.d.ts +16 -0
- package/dist/server/security/oauth-server.d.ts.map +1 -0
- package/dist/server/security/oauth-server.js +544 -0
- package/dist/server/security/oauth-server.js.map +1 -0
- package/dist/server/security/secret-box.d.ts +7 -0
- package/dist/server/security/secret-box.d.ts.map +1 -0
- package/dist/server/security/secret-box.js +27 -0
- package/dist/server/security/secret-box.js.map +1 -0
- package/dist/server/security/secure-action.d.ts +21 -0
- package/dist/server/security/secure-action.d.ts.map +1 -0
- package/dist/server/security/secure-action.js +69 -0
- package/dist/server/security/secure-action.js.map +1 -0
- package/dist/server/storage/sqlite-store.d.ts +70 -0
- package/dist/server/storage/sqlite-store.d.ts.map +1 -0
- package/dist/server/storage/sqlite-store.js +1522 -0
- package/dist/server/storage/sqlite-store.js.map +1 -0
- package/dist/server/storage/store.d.ts +82 -0
- package/dist/server/storage/store.d.ts.map +1 -0
- package/dist/server/storage/store.js +2 -0
- package/dist/server/storage/store.js.map +1 -0
- package/dist/server/upstream/adapter.d.ts +52 -0
- package/dist/server/upstream/adapter.d.ts.map +1 -0
- package/dist/server/upstream/adapter.js +807 -0
- package/dist/server/upstream/adapter.js.map +1 -0
- package/dist/server/upstream/credential-resolver.d.ts +14 -0
- package/dist/server/upstream/credential-resolver.d.ts.map +1 -0
- package/dist/server/upstream/credential-resolver.js +56 -0
- package/dist/server/upstream/credential-resolver.js.map +1 -0
- package/dist/server/upstream/extension-transport.d.ts +17 -0
- package/dist/server/upstream/extension-transport.d.ts.map +1 -0
- package/dist/server/upstream/extension-transport.js +207 -0
- package/dist/server/upstream/extension-transport.js.map +1 -0
- package/dist/server/upstream/manager.d.ts +23 -0
- package/dist/server/upstream/manager.d.ts.map +1 -0
- package/dist/server/upstream/manager.js +324 -0
- package/dist/server/upstream/manager.js.map +1 -0
- package/dist/server/upstream/oauth-provider.d.ts +38 -0
- package/dist/server/upstream/oauth-provider.d.ts.map +1 -0
- package/dist/server/upstream/oauth-provider.js +225 -0
- package/dist/server/upstream/oauth-provider.js.map +1 -0
- package/dist/server/upstream/oauth-refresh.d.ts +65 -0
- package/dist/server/upstream/oauth-refresh.d.ts.map +1 -0
- package/dist/server/upstream/oauth-refresh.js +240 -0
- package/dist/server/upstream/oauth-refresh.js.map +1 -0
- package/dist/server/upstream/oauth-routes.d.ts +17 -0
- package/dist/server/upstream/oauth-routes.d.ts.map +1 -0
- package/dist/server/upstream/oauth-routes.js +87 -0
- package/dist/server/upstream/oauth-routes.js.map +1 -0
- package/dist/server/upstream/oauth-service.d.ts +143 -0
- package/dist/server/upstream/oauth-service.d.ts.map +1 -0
- package/dist/server/upstream/oauth-service.js +217 -0
- package/dist/server/upstream/oauth-service.js.map +1 -0
- package/dist/server/upstream/stable-json.d.ts +3 -0
- package/dist/server/upstream/stable-json.d.ts.map +1 -0
- package/dist/server/upstream/stable-json.js +17 -0
- package/dist/server/upstream/stable-json.js.map +1 -0
- package/package.json +69 -0
- package/skills/toolhome/SKILL.md +238 -0
- package/skills/toolhome/references/cli-reference.md +242 -0
- package/skills/toolhome/references/deployment.md +113 -0
- package/skills/toolhome/references/market-guide.md +128 -0
- package/skills/toolhome/references/oauth-guide.md +96 -0
- package/skills/toolhome/references/troubleshooting.md +133 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { slugSchema } from '../domain/models.js';
|
|
3
|
+
/**
|
|
4
|
+
* CLI plane record schemas (Form A of docs/cli-hosting-research.md).
|
|
5
|
+
*
|
|
6
|
+
* A CLI is a first-class entity: a command or container image plus a declarative
|
|
7
|
+
* allow-list, optional probe for status checks, and an optional Env Credential
|
|
8
|
+
* whose variables are injected into every execution.
|
|
9
|
+
*/
|
|
10
|
+
/** One argv rule: token patterns, where `*` matches a single argv token. */
|
|
11
|
+
export const cliAllowRuleSchema = z.array(z.string().min(1)).min(1);
|
|
12
|
+
export const cliAllowListSchema = z.object({
|
|
13
|
+
allow: z.array(cliAllowRuleSchema).default([]),
|
|
14
|
+
deny: z.array(cliAllowRuleSchema).default([]),
|
|
15
|
+
});
|
|
16
|
+
export const cliProbeSchema = z.object({
|
|
17
|
+
command: z.string().min(1).max(1024),
|
|
18
|
+
args: z.array(z.string()).default([]),
|
|
19
|
+
});
|
|
20
|
+
const cliCredentialBindingsValueSchema = z.record(z.string().min(1), z.string().min(1));
|
|
21
|
+
export const cliCredentialBindingsSchema = cliCredentialBindingsValueSchema.default({});
|
|
22
|
+
const cliAuthStrategyValueSchema = z.enum([
|
|
23
|
+
'none',
|
|
24
|
+
'azure-service-principal',
|
|
25
|
+
'tailscale-auth-key',
|
|
26
|
+
]);
|
|
27
|
+
export const cliAuthStrategySchema = cliAuthStrategyValueSchema.default('none');
|
|
28
|
+
const namedVolumeSourceSchema = z
|
|
29
|
+
.string()
|
|
30
|
+
.min(1)
|
|
31
|
+
.max(128)
|
|
32
|
+
.regex(/^[A-Za-z0-9][A-Za-z0-9_.-]*$/, 'Only Docker named volumes are supported');
|
|
33
|
+
const containerVolumeSchema = z.object({
|
|
34
|
+
source: namedVolumeSourceSchema,
|
|
35
|
+
target: z
|
|
36
|
+
.string()
|
|
37
|
+
.min(1)
|
|
38
|
+
.max(512)
|
|
39
|
+
.refine((value) => value.startsWith('/') && !/[\0\r\n:]/.test(value), 'Container volume targets must be absolute paths without control characters or colons'),
|
|
40
|
+
readOnly: z.boolean().default(false),
|
|
41
|
+
});
|
|
42
|
+
export const cliRuntimeConfigSchema = z
|
|
43
|
+
.object({
|
|
44
|
+
executionMode: z.enum(['host', 'docker']),
|
|
45
|
+
authStrategy: cliAuthStrategySchema,
|
|
46
|
+
containerVolumes: z.array(containerVolumeSchema).max(16),
|
|
47
|
+
})
|
|
48
|
+
.superRefine((value, context) => {
|
|
49
|
+
if (value.executionMode === 'host' && value.authStrategy !== 'none') {
|
|
50
|
+
context.addIssue({
|
|
51
|
+
code: 'custom',
|
|
52
|
+
path: ['authStrategy'],
|
|
53
|
+
message: 'Authentication bootstrap requires Docker execution mode',
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (value.executionMode === 'host' && value.containerVolumes.length > 0) {
|
|
57
|
+
context.addIssue({
|
|
58
|
+
code: 'custom',
|
|
59
|
+
path: ['containerVolumes'],
|
|
60
|
+
message: 'Container volumes require Docker execution mode',
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const targets = new Set();
|
|
64
|
+
for (const [index, volume] of value.containerVolumes.entries()) {
|
|
65
|
+
if (targets.has(volume.target)) {
|
|
66
|
+
context.addIssue({
|
|
67
|
+
code: 'custom',
|
|
68
|
+
path: ['containerVolumes', index, 'target'],
|
|
69
|
+
message: 'Container volume targets must be unique',
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
targets.add(volume.target);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
export const createCliInputSchema = z
|
|
76
|
+
.object({
|
|
77
|
+
slug: slugSchema,
|
|
78
|
+
name: z.string().min(1).max(120),
|
|
79
|
+
command: z.string().min(1).max(1024),
|
|
80
|
+
executionMode: z.enum(['host', 'docker']).default('host'),
|
|
81
|
+
entrypoint: z.string().min(1).max(256).nullable().default(null),
|
|
82
|
+
authStrategy: cliAuthStrategySchema,
|
|
83
|
+
containerVolumes: z.array(containerVolumeSchema).default([]),
|
|
84
|
+
platform: z.string().min(1).max(120).nullable().default(null),
|
|
85
|
+
allowList: cliAllowListSchema.default({ allow: [], deny: [] }),
|
|
86
|
+
interactive: z.boolean().default(false),
|
|
87
|
+
credentialId: z.string().nullable().default(null),
|
|
88
|
+
credentialBindings: cliCredentialBindingsSchema,
|
|
89
|
+
probe: cliProbeSchema.nullable().default(null),
|
|
90
|
+
enabled: z.boolean().default(true),
|
|
91
|
+
timeoutMs: z.number().int().min(100).max(3_600_000).default(60_000),
|
|
92
|
+
maxOutputBytes: z
|
|
93
|
+
.number()
|
|
94
|
+
.int()
|
|
95
|
+
.min(1024)
|
|
96
|
+
.max(64 * 1024 * 1024)
|
|
97
|
+
.default(64 * 1024),
|
|
98
|
+
})
|
|
99
|
+
.superRefine((value, context) => {
|
|
100
|
+
const result = cliRuntimeConfigSchema.safeParse(value);
|
|
101
|
+
if (!result.success) {
|
|
102
|
+
for (const issue of result.error.issues) {
|
|
103
|
+
context.addIssue({
|
|
104
|
+
code: issue.code === 'custom' ? 'custom' : 'custom',
|
|
105
|
+
path: issue.path,
|
|
106
|
+
message: issue.message,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
export const updateCliInputSchema = z.object({
|
|
112
|
+
name: z.string().min(1).max(120).optional(),
|
|
113
|
+
command: z.string().min(1).max(1024).optional(),
|
|
114
|
+
executionMode: z.enum(['host', 'docker']).optional(),
|
|
115
|
+
entrypoint: z.string().min(1).max(256).nullable().optional(),
|
|
116
|
+
authStrategy: cliAuthStrategyValueSchema.optional(),
|
|
117
|
+
containerVolumes: z.array(containerVolumeSchema).optional(),
|
|
118
|
+
platform: z.string().min(1).max(120).nullable().optional(),
|
|
119
|
+
allowList: cliAllowListSchema.optional(),
|
|
120
|
+
interactive: z.boolean().optional(),
|
|
121
|
+
credentialId: z.string().nullable().optional(),
|
|
122
|
+
credentialBindings: cliCredentialBindingsValueSchema.optional(),
|
|
123
|
+
probe: cliProbeSchema.nullable().optional(),
|
|
124
|
+
enabled: z.boolean().optional(),
|
|
125
|
+
timeoutMs: z.number().int().min(100).max(3_600_000).optional(),
|
|
126
|
+
maxOutputBytes: z
|
|
127
|
+
.number()
|
|
128
|
+
.int()
|
|
129
|
+
.min(1024)
|
|
130
|
+
.max(64 * 1024 * 1024)
|
|
131
|
+
.optional(),
|
|
132
|
+
});
|
|
133
|
+
export function assertCliRuntimeConfig(value) {
|
|
134
|
+
cliRuntimeConfigSchema.parse(value);
|
|
135
|
+
}
|
|
136
|
+
export const cliRecordSchema = z.object({
|
|
137
|
+
id: z.uuid(),
|
|
138
|
+
slug: slugSchema,
|
|
139
|
+
name: z.string(),
|
|
140
|
+
command: z.string(),
|
|
141
|
+
executionMode: z.enum(['host', 'docker']),
|
|
142
|
+
entrypoint: z.string().min(1).max(256).nullable(),
|
|
143
|
+
authStrategy: cliAuthStrategySchema,
|
|
144
|
+
containerVolumes: z.array(containerVolumeSchema),
|
|
145
|
+
platform: z.string().min(1).max(120).nullable(),
|
|
146
|
+
allowList: cliAllowListSchema,
|
|
147
|
+
interactive: z.boolean(),
|
|
148
|
+
credentialId: z.string().nullable(),
|
|
149
|
+
credentialBindings: cliCredentialBindingsSchema,
|
|
150
|
+
probe: cliProbeSchema.nullable(),
|
|
151
|
+
enabled: z.boolean(),
|
|
152
|
+
timeoutMs: z.number(),
|
|
153
|
+
maxOutputBytes: z.number(),
|
|
154
|
+
createdAt: z.iso.datetime(),
|
|
155
|
+
updatedAt: z.iso.datetime(),
|
|
156
|
+
});
|
|
157
|
+
/** Per-exec request body. `argv` is an array only — never a shell string. */
|
|
158
|
+
export const cliExecInputSchema = z.object({
|
|
159
|
+
argv: z.array(z.string()).min(1),
|
|
160
|
+
stdin: z.string().nullable().optional(),
|
|
161
|
+
timeoutMs: z.number().int().min(100).max(3_600_000).optional(),
|
|
162
|
+
maxOutputBytes: z
|
|
163
|
+
.number()
|
|
164
|
+
.int()
|
|
165
|
+
.min(1024)
|
|
166
|
+
.max(64 * 1024 * 1024)
|
|
167
|
+
.optional(),
|
|
168
|
+
});
|
|
169
|
+
//# sourceMappingURL=models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../../../src/cli-plane/models.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Logger } from '../observability/logger.js';
|
|
2
|
+
import type { AuthService } from '../security/auth-service.js';
|
|
3
|
+
import type { CliService } from './cli-service.js';
|
|
4
|
+
interface HonoLike {
|
|
5
|
+
get(path: string, handler: (context: HonoContext) => Response | Promise<Response>): void;
|
|
6
|
+
post(path: string, handler: (context: HonoContext) => Response | Promise<Response>): void;
|
|
7
|
+
}
|
|
8
|
+
interface HonoContext {
|
|
9
|
+
req: {
|
|
10
|
+
raw: Request;
|
|
11
|
+
path: string;
|
|
12
|
+
param(name: string): string;
|
|
13
|
+
json(): Promise<unknown>;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Mount the CLI data-plane routes (docs/cli-hosting-research.md §2.2/§2.6):
|
|
18
|
+
*
|
|
19
|
+
* POST /cli/{slug}/exec NDJSON stream of stdout/stderr/exit frames
|
|
20
|
+
* GET /cli/{slug}/status { installed, version, loggedIn, lastCheckedAt }
|
|
21
|
+
*
|
|
22
|
+
* Both require an admin Control Key. All validation and the allow-list verdict
|
|
23
|
+
* happen before the response stream starts, so 400/403/404 errors are returned
|
|
24
|
+
* as JSON without spawning anything.
|
|
25
|
+
*/
|
|
26
|
+
export declare function mountCliExecRoutes(app: HonoLike, options: {
|
|
27
|
+
service: CliService;
|
|
28
|
+
auth: AuthService;
|
|
29
|
+
logger: Logger;
|
|
30
|
+
}): void;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/cli-plane/routes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,UAAU,QAAQ;IAChB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;IACzF,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;CAC3F;AAED,UAAU,WAAW;IACnB,GAAG,EAAE;QACH,GAAG,EAAE,OAAO,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;QAC5B,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;KAC1B,CAAC;CACH;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,QAAQ,EACb,OAAO,EAAE;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClE,IAAI,CA0EN"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { AppError } from '../domain/errors.js';
|
|
2
|
+
import { errorResponse } from '../control/control-api.js';
|
|
3
|
+
import { cliNdjsonContentType, encodeFrame } from './frames.js';
|
|
4
|
+
/**
|
|
5
|
+
* Mount the CLI data-plane routes (docs/cli-hosting-research.md §2.2/§2.6):
|
|
6
|
+
*
|
|
7
|
+
* POST /cli/{slug}/exec NDJSON stream of stdout/stderr/exit frames
|
|
8
|
+
* GET /cli/{slug}/status { installed, version, loggedIn, lastCheckedAt }
|
|
9
|
+
*
|
|
10
|
+
* Both require an admin Control Key. All validation and the allow-list verdict
|
|
11
|
+
* happen before the response stream starts, so 400/403/404 errors are returned
|
|
12
|
+
* as JSON without spawning anything.
|
|
13
|
+
*/
|
|
14
|
+
export function mountCliExecRoutes(app, options) {
|
|
15
|
+
const requireAdmin = (context) => {
|
|
16
|
+
const principal = options.auth.authenticateBearer('control', context.req.raw);
|
|
17
|
+
if (principal.scope !== 'admin') {
|
|
18
|
+
throw new AppError('forbidden', 'This operation requires an admin control key', 403);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
app.post('/cli/:slug/exec', async (context) => {
|
|
22
|
+
try {
|
|
23
|
+
requireAdmin(context);
|
|
24
|
+
let body;
|
|
25
|
+
try {
|
|
26
|
+
body = await context.req.json();
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
throw new AppError('validation_error', 'Request body must be JSON', 400);
|
|
30
|
+
}
|
|
31
|
+
const prepared = options.service.prepareExec(context.req.param('slug'), body);
|
|
32
|
+
const abort = new AbortController();
|
|
33
|
+
const stream = new ReadableStream({
|
|
34
|
+
start(controller) {
|
|
35
|
+
void (async () => {
|
|
36
|
+
const emit = (frame) => {
|
|
37
|
+
try {
|
|
38
|
+
controller.enqueue(new TextEncoder().encode(encodeFrame(frame)));
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// stream already closed by the client
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
try {
|
|
45
|
+
await options.service.runExec(prepared.record, prepared.input, emit, abort.signal);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
emit({
|
|
49
|
+
type: 'stderr',
|
|
50
|
+
data: error instanceof Error ? error.message : String(error),
|
|
51
|
+
});
|
|
52
|
+
emit({ type: 'exit', code: null, durationMs: 0, result: 'error' });
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
try {
|
|
56
|
+
controller.close();
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// already closed
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
})();
|
|
63
|
+
},
|
|
64
|
+
cancel() {
|
|
65
|
+
abort.abort();
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
return new Response(stream, {
|
|
69
|
+
status: 200,
|
|
70
|
+
headers: {
|
|
71
|
+
'content-type': cliNdjsonContentType,
|
|
72
|
+
'cache-control': 'no-store',
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
return errorResponse(error, options.logger);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
app.get('/cli/:slug/status', async (context) => {
|
|
81
|
+
try {
|
|
82
|
+
requireAdmin(context);
|
|
83
|
+
const status = await options.service.status(context.req.param('slug'));
|
|
84
|
+
return new Response(JSON.stringify(status), {
|
|
85
|
+
status: 200,
|
|
86
|
+
headers: { 'content-type': 'application/json', 'cache-control': 'no-store' },
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
return errorResponse(error, options.logger);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../src/cli-plane/routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { CliExecFrame } from './frames.js';
|
|
2
|
+
export interface ExecRequest {
|
|
3
|
+
/** Host: binary path/name. Docker: container image reference. */
|
|
4
|
+
command: string;
|
|
5
|
+
/** argv passed verbatim to the binary — never through a shell. */
|
|
6
|
+
argv: string[];
|
|
7
|
+
/** Full environment for the child (base env + enforcement vars + credential vars). */
|
|
8
|
+
env: Record<string, string>;
|
|
9
|
+
stdin?: string | null;
|
|
10
|
+
timeoutMs: number;
|
|
11
|
+
maxOutputBytes: number;
|
|
12
|
+
executionMode: 'host' | 'docker';
|
|
13
|
+
/** Environment variable names explicitly forwarded into the container. */
|
|
14
|
+
containerEnvKeys?: string[];
|
|
15
|
+
/** Persistent or bind-mounted state directories explicitly forwarded into the container. */
|
|
16
|
+
containerVolumes?: {
|
|
17
|
+
source: string;
|
|
18
|
+
target: string;
|
|
19
|
+
readOnly?: boolean;
|
|
20
|
+
}[];
|
|
21
|
+
/** Fixed authentication bootstrap performed inside a hosted container. */
|
|
22
|
+
authStrategy?: 'none' | 'azure-service-principal' | 'tailscale-auth-key';
|
|
23
|
+
entrypoint?: string | null;
|
|
24
|
+
}
|
|
25
|
+
export interface ExecOutcome {
|
|
26
|
+
code: number | null;
|
|
27
|
+
durationMs: number;
|
|
28
|
+
result: 'ok' | 'error' | 'timeout';
|
|
29
|
+
truncated: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Run a CLI process and stream its output as NDJSON frames.
|
|
33
|
+
*
|
|
34
|
+
* The process is spawned directly (no shell); stdout and stderr are forwarded
|
|
35
|
+
* as separate frames. A still-running child is SIGTERM'd at `timeoutMs` and
|
|
36
|
+
* SIGKILL'd after a grace period. Output is memory-bounded: once
|
|
37
|
+
* `maxOutputBytes` have been forwarded, further chunks are dropped and the
|
|
38
|
+
* final exit frame carries `truncated: true`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function execCli(request: ExecRequest, emit: (frame: CliExecFrame) => void, signal?: AbortSignal): Promise<ExecOutcome>;
|
|
41
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/cli-plane/runner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,WAAW;IAC1B,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,sFAAsF;IACtF,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,QAAQ,CAAC;IACjC,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,4FAA4F;IAC5F,gBAAgB,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC5E,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,GAAG,yBAAyB,GAAG,oBAAoB,CAAC;IACzE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,IAAI,GAAG,OAAO,GAAG,SAAS,CAAC;IACnC,SAAS,EAAE,OAAO,CAAC;CACpB;AAID;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CACrB,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,EACnC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,WAAW,CAAC,CAsJtB"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
const killGraceMs = 1_000;
|
|
3
|
+
/**
|
|
4
|
+
* Run a CLI process and stream its output as NDJSON frames.
|
|
5
|
+
*
|
|
6
|
+
* The process is spawned directly (no shell); stdout and stderr are forwarded
|
|
7
|
+
* as separate frames. A still-running child is SIGTERM'd at `timeoutMs` and
|
|
8
|
+
* SIGKILL'd after a grace period. Output is memory-bounded: once
|
|
9
|
+
* `maxOutputBytes` have been forwarded, further chunks are dropped and the
|
|
10
|
+
* final exit frame carries `truncated: true`.
|
|
11
|
+
*/
|
|
12
|
+
export function execCli(request, emit, signal) {
|
|
13
|
+
return new Promise((resolve) => {
|
|
14
|
+
const isDocker = request.executionMode === 'docker';
|
|
15
|
+
const spawnCommand = isDocker ? 'docker' : request.command;
|
|
16
|
+
const containerArgv = request.authStrategy === 'azure-service-principal'
|
|
17
|
+
? [
|
|
18
|
+
'-c',
|
|
19
|
+
'az login --service-principal --username "$AZURE_CLIENT_ID" --password "$AZURE_CLIENT_SECRET" --tenant "$AZURE_TENANT_ID" --output none && exec az "$@"',
|
|
20
|
+
'--',
|
|
21
|
+
...request.argv,
|
|
22
|
+
]
|
|
23
|
+
: request.authStrategy === 'tailscale-auth-key'
|
|
24
|
+
? [
|
|
25
|
+
'-c',
|
|
26
|
+
'mkdir -p /var/run/tailscale && tailscaled --tun=userspace-networking --statedir=/var/lib/tailscale --socket=/var/run/tailscale/tailscaled.sock >/tmp/tailscaled.log 2>&1 & daemon=$!; attempt=0; while [ "$attempt" -lt 50 ] && [ ! -S /var/run/tailscale/tailscaled.sock ]; do attempt=$((attempt + 1)); sleep 0.1; done; tailscale --socket=/var/run/tailscale/tailscaled.sock up --auth-key="$TS_AUTHKEY" --reset >/dev/null 2>&1 && exec tailscale --socket=/var/run/tailscale/tailscaled.sock "$@"; status=$?; kill "$daemon" >/dev/null 2>&1 || true; wait "$daemon" >/dev/null 2>&1 || true; exit "$status"',
|
|
27
|
+
'--',
|
|
28
|
+
...request.argv,
|
|
29
|
+
]
|
|
30
|
+
: request.argv;
|
|
31
|
+
const spawnArgs = isDocker
|
|
32
|
+
? [
|
|
33
|
+
'run',
|
|
34
|
+
'--rm',
|
|
35
|
+
'-i',
|
|
36
|
+
...(request.authStrategy === 'azure-service-principal' ||
|
|
37
|
+
request.authStrategy === 'tailscale-auth-key'
|
|
38
|
+
? ['--entrypoint', '/bin/sh']
|
|
39
|
+
: request.entrypoint
|
|
40
|
+
? ['--entrypoint', request.entrypoint]
|
|
41
|
+
: []),
|
|
42
|
+
...(request.containerVolumes ?? []).flatMap((volume) => [
|
|
43
|
+
'--volume',
|
|
44
|
+
`${volume.source}:${volume.target}${volume.readOnly ? ':ro' : ''}`,
|
|
45
|
+
]),
|
|
46
|
+
...(request.authStrategy === 'tailscale-auth-key'
|
|
47
|
+
? ['--env', 'TS_STATE_DIR=/var/lib/tailscale']
|
|
48
|
+
: []),
|
|
49
|
+
...(request.containerEnvKeys ?? []).flatMap((name) => ['--env', name]),
|
|
50
|
+
request.command,
|
|
51
|
+
...containerArgv,
|
|
52
|
+
]
|
|
53
|
+
: request.argv;
|
|
54
|
+
let child;
|
|
55
|
+
try {
|
|
56
|
+
child = spawn(spawnCommand, spawnArgs, {
|
|
57
|
+
env: request.env,
|
|
58
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
59
|
+
shell: false,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
emit({ type: 'stderr', data: error instanceof Error ? error.message : String(error) });
|
|
64
|
+
emit({ type: 'exit', code: null, durationMs: 0, result: 'error' });
|
|
65
|
+
resolve({ code: null, durationMs: 0, result: 'error', truncated: false });
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const started = Date.now();
|
|
69
|
+
let timedOut = false;
|
|
70
|
+
let aborted = false;
|
|
71
|
+
let truncated = false;
|
|
72
|
+
let forwardedBytes = 0;
|
|
73
|
+
let settled = false;
|
|
74
|
+
let killTimer;
|
|
75
|
+
let escalateTimer;
|
|
76
|
+
const forward = (stream, chunk) => {
|
|
77
|
+
if (settled || timedOut || aborted)
|
|
78
|
+
return;
|
|
79
|
+
const remaining = request.maxOutputBytes - forwardedBytes;
|
|
80
|
+
if (remaining <= 0) {
|
|
81
|
+
truncated = true;
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (chunk.length > remaining) {
|
|
85
|
+
truncated = true;
|
|
86
|
+
forwardedBytes += remaining;
|
|
87
|
+
emit({ type: stream, data: chunk.subarray(0, remaining).toString('utf8') });
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
forwardedBytes += chunk.length;
|
|
91
|
+
emit({ type: stream, data: chunk.toString('utf8') });
|
|
92
|
+
};
|
|
93
|
+
child.stdout.on('data', (chunk) => forward('stdout', chunk));
|
|
94
|
+
child.stderr.on('data', (chunk) => forward('stderr', chunk));
|
|
95
|
+
if (request.stdin !== null && request.stdin !== undefined) {
|
|
96
|
+
child.stdin.end(request.stdin);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
child.stdin.end();
|
|
100
|
+
}
|
|
101
|
+
const terminate = () => {
|
|
102
|
+
try {
|
|
103
|
+
child.kill('SIGTERM');
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// child already gone
|
|
107
|
+
}
|
|
108
|
+
if (escalateTimer === undefined) {
|
|
109
|
+
escalateTimer = setTimeout(() => {
|
|
110
|
+
try {
|
|
111
|
+
child.kill('SIGKILL');
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// child already gone
|
|
115
|
+
}
|
|
116
|
+
}, killGraceMs);
|
|
117
|
+
escalateTimer.unref();
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
killTimer = setTimeout(() => {
|
|
121
|
+
timedOut = true;
|
|
122
|
+
terminate();
|
|
123
|
+
}, request.timeoutMs);
|
|
124
|
+
killTimer.unref();
|
|
125
|
+
const onAbort = () => {
|
|
126
|
+
aborted = true;
|
|
127
|
+
terminate();
|
|
128
|
+
};
|
|
129
|
+
if (signal !== undefined) {
|
|
130
|
+
if (signal.aborted)
|
|
131
|
+
onAbort();
|
|
132
|
+
else
|
|
133
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
134
|
+
}
|
|
135
|
+
const finish = (code) => {
|
|
136
|
+
if (settled)
|
|
137
|
+
return;
|
|
138
|
+
settled = true;
|
|
139
|
+
if (killTimer !== undefined)
|
|
140
|
+
clearTimeout(killTimer);
|
|
141
|
+
if (escalateTimer !== undefined)
|
|
142
|
+
clearTimeout(escalateTimer);
|
|
143
|
+
signal?.removeEventListener('abort', onAbort);
|
|
144
|
+
const durationMs = Date.now() - started;
|
|
145
|
+
const result = aborted ? 'error' : timedOut ? 'timeout' : code === 0 ? 'ok' : 'error';
|
|
146
|
+
emit({
|
|
147
|
+
type: 'exit',
|
|
148
|
+
code: timedOut || aborted ? null : code,
|
|
149
|
+
durationMs,
|
|
150
|
+
result,
|
|
151
|
+
...(truncated ? { truncated: true } : {}),
|
|
152
|
+
});
|
|
153
|
+
resolve({ code: timedOut || aborted ? null : code, durationMs, result, truncated });
|
|
154
|
+
};
|
|
155
|
+
child.on('error', (error) => {
|
|
156
|
+
if (!settled) {
|
|
157
|
+
emit({ type: 'stderr', data: error instanceof Error ? error.message : String(error) });
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
child.on('close', (code) => finish(code));
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/cli-plane/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI status probe parsing (docs/cli-hosting-research.md §2.6).
|
|
3
|
+
*
|
|
4
|
+
* The probe command's stdout is key=value on each line; `version` surfaces as
|
|
5
|
+
* the version string and `loggedIn`/`logged_in` as the boolean login state.
|
|
6
|
+
* Absent keys keep their defaults.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseProbeOutput(stdout: string): {
|
|
9
|
+
version: string | null;
|
|
10
|
+
loggedIn: boolean;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli-plane/status.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAgB9F"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI status probe parsing (docs/cli-hosting-research.md §2.6).
|
|
3
|
+
*
|
|
4
|
+
* The probe command's stdout is key=value on each line; `version` surfaces as
|
|
5
|
+
* the version string and `loggedIn`/`logged_in` as the boolean login state.
|
|
6
|
+
* Absent keys keep their defaults.
|
|
7
|
+
*/
|
|
8
|
+
export function parseProbeOutput(stdout) {
|
|
9
|
+
let version = null;
|
|
10
|
+
let loggedIn = false;
|
|
11
|
+
for (const line of stdout.split('\n')) {
|
|
12
|
+
const trimmed = line.trim();
|
|
13
|
+
const versionMatch = /^version=(.*)$/.exec(trimmed);
|
|
14
|
+
if (versionMatch?.[1] !== undefined && versionMatch[1] !== '') {
|
|
15
|
+
version = versionMatch[1];
|
|
16
|
+
}
|
|
17
|
+
const loginMatch = /^loggedIn=(true|false)$/i.exec(trimmed) ?? /^logged_in=(true|false)$/i.exec(trimmed);
|
|
18
|
+
if (loginMatch?.[1] !== undefined) {
|
|
19
|
+
loggedIn = loginMatch[1].toLowerCase() === 'true';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return { version, loggedIn };
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli-plane/status.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,IAAI,OAAO,GAAkB,IAAI,CAAC;IAClC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,MAAM,YAAY,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpD,IAAI,YAAY,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;YAC9D,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC;QACD,MAAM,UAAU,GACd,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,2BAA2B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxF,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;YAClC,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC;QACpD,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { CredentialPayload, TransportConfig } from '../domain/models.js';
|
|
3
|
+
export declare const harnessConfigSchema: z.ZodObject<{
|
|
4
|
+
mcpServers: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
5
|
+
command: z.ZodOptional<z.ZodString>;
|
|
6
|
+
args: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
7
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
8
|
+
url: z.ZodOptional<z.ZodString>;
|
|
9
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
10
|
+
}, z.core.$strip>>;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
export type HarnessConfig = z.infer<typeof harnessConfigSchema>;
|
|
13
|
+
export interface HarnessImportedCredential {
|
|
14
|
+
name: string;
|
|
15
|
+
payload: CredentialPayload;
|
|
16
|
+
}
|
|
17
|
+
export interface HarnessImportedEntry {
|
|
18
|
+
name: string;
|
|
19
|
+
slug: string;
|
|
20
|
+
kind: 'remote' | 'home';
|
|
21
|
+
transport: TransportConfig;
|
|
22
|
+
credential: HarnessImportedCredential | null;
|
|
23
|
+
warnings: string[];
|
|
24
|
+
}
|
|
25
|
+
export interface HarnessImportPreview {
|
|
26
|
+
name: string;
|
|
27
|
+
slug: string;
|
|
28
|
+
kind: 'remote' | 'home';
|
|
29
|
+
transportSummary: string;
|
|
30
|
+
credential: {
|
|
31
|
+
name: string;
|
|
32
|
+
type: string;
|
|
33
|
+
fields: {
|
|
34
|
+
name: string;
|
|
35
|
+
masked: boolean;
|
|
36
|
+
}[];
|
|
37
|
+
} | null;
|
|
38
|
+
warnings: string[];
|
|
39
|
+
}
|
|
40
|
+
export declare function toSlug(name: string): string;
|
|
41
|
+
export declare function parseHarnessConfig(value: unknown): HarnessImportedEntry[];
|
|
42
|
+
/** Masked view for previews — never contains secret values. */
|
|
43
|
+
export declare function toPreview(entry: HarnessImportedEntry): HarnessImportPreview;
|
|
44
|
+
//# sourceMappingURL=harness-import.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-import.d.ts","sourceRoot":"","sources":["../../../src/config/harness-import.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAyB9E,eAAO,MAAM,mBAAmB;;;;;;;;iBAE9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAKhE,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,iBAAiB,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,SAAS,EAAE,eAAe,CAAC;IAC3B,UAAU,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC7C,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,OAAO,CAAA;SAAE,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/F,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO3C;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,EAAE,CAkBzE;AAkGD,+DAA+D;AAC/D,wBAAgB,SAAS,CAAC,KAAK,EAAE,oBAAoB,GAAG,oBAAoB,CA2B3E"}
|