@dam-agents/cli 0.2.7-rc1 → 0.2.8-rc1
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/dist/bin.js +588 -170
- package/package.json +3 -3
package/dist/bin.js
CHANGED
|
@@ -26799,6 +26799,18 @@ var skillListInputSchema = external_exports.object({
|
|
|
26799
26799
|
sourceId: external_exports.string().min(1),
|
|
26800
26800
|
agentId: external_exports.string().min(1).optional()
|
|
26801
26801
|
});
|
|
26802
|
+
var skillGetContentInputSchema = external_exports.object({
|
|
26803
|
+
sourceId: external_exports.string().min(1),
|
|
26804
|
+
name: external_exports.string().min(1),
|
|
26805
|
+
agentId: external_exports.string().min(1).optional()
|
|
26806
|
+
});
|
|
26807
|
+
var skillContentSchema = external_exports.object({
|
|
26808
|
+
content: external_exports.string(),
|
|
26809
|
+
/** Source-relative directory the SKILL.md was found in, when resolvable —
|
|
26810
|
+
* lets the UI build an accurate blob link instead of guessing the dir from
|
|
26811
|
+
* the (frontmatter) skill name. */
|
|
26812
|
+
dir: external_exports.string().optional()
|
|
26813
|
+
});
|
|
26802
26814
|
var skillInstallInputSchema = external_exports.object({
|
|
26803
26815
|
agentId: external_exports.string().min(1),
|
|
26804
26816
|
source: external_exports.string().url(),
|
|
@@ -26892,6 +26904,38 @@ var repoSchema = external_exports.object({
|
|
|
26892
26904
|
compatibleTemplates: external_exports.array(external_exports.string()).default([])
|
|
26893
26905
|
});
|
|
26894
26906
|
|
|
26907
|
+
// ../api-server-api/src/modules/invocations/schemas.ts
|
|
26908
|
+
var DEFAULT_INVOCATION_TTL_MS = 60 * 60 * 1e3;
|
|
26909
|
+
var MIN_INVOCATION_TTL_MS = 60 * 1e3;
|
|
26910
|
+
var MAX_INVOCATION_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
26911
|
+
var spawnInvocationRequestSchema = external_exports.object({
|
|
26912
|
+
image: external_exports.string().min(1).optional(),
|
|
26913
|
+
templateId: external_exports.string().min(1).optional(),
|
|
26914
|
+
connections: external_exports.array(external_exports.string().min(1)).optional(),
|
|
26915
|
+
prompt: external_exports.string().min(1),
|
|
26916
|
+
// The result JSON Schema — arbitrary JSON, validated structurally by ajv
|
|
26917
|
+
// when the target reports (a malformed schema is rejected at spawn).
|
|
26918
|
+
schema: external_exports.unknown(),
|
|
26919
|
+
// Optional liveness deadline for this target, in ms. Bounded server-side; a
|
|
26920
|
+
// shorter value fails a wedged/misconfigured target fast, a longer one lets
|
|
26921
|
+
// a heavy target run past the default hour.
|
|
26922
|
+
ttlMs: external_exports.number().int().min(MIN_INVOCATION_TTL_MS).max(MAX_INVOCATION_TTL_MS).optional(),
|
|
26923
|
+
// Optional resource limits. A heavy Make (clone + install + build)
|
|
26924
|
+
// OOM-kills at the template's small default memory, so let the driver raise
|
|
26925
|
+
// it. Same grammar and floors as the agent size knob.
|
|
26926
|
+
memory: external_exports.string().regex(/^\d+(Mi|Gi)$/, "memory must look like '512Mi' or '4Gi'").optional(),
|
|
26927
|
+
cpu: external_exports.string().regex(/^\d+(\.\d+)?m?$/, "cpu must look like '2', '0.5' or '500m'").optional()
|
|
26928
|
+
}).refine((d2) => d2.image !== void 0 || d2.templateId !== void 0, {
|
|
26929
|
+
message: "either image or templateId is required"
|
|
26930
|
+
});
|
|
26931
|
+
var spawnInvocationResponseSchema = external_exports.object({
|
|
26932
|
+
id: external_exports.string().min(1)
|
|
26933
|
+
});
|
|
26934
|
+
var invocationViewSchema = external_exports.object({
|
|
26935
|
+
status: external_exports.enum(["running", "done", "failed"]),
|
|
26936
|
+
result: external_exports.unknown()
|
|
26937
|
+
});
|
|
26938
|
+
|
|
26895
26939
|
// ../agent-runtime-api/src/modules/files/schemas.ts
|
|
26896
26940
|
var pathSchema = external_exports.string().min(1);
|
|
26897
26941
|
var fileListDirsInputSchema = external_exports.object({
|
|
@@ -27209,6 +27253,10 @@ var harnessConfigSettledSchema = external_exports.object({
|
|
|
27209
27253
|
|
|
27210
27254
|
// ../api-server-api/src/modules/egress-rules/schemas.ts
|
|
27211
27255
|
var ruleVerdictSchema = external_exports.enum(["allow", "deny"]);
|
|
27256
|
+
var HOSTNAME = /^(\*\.)?[a-zA-Z0-9]([-a-zA-Z0-9]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([-a-zA-Z0-9]{0,61}[a-zA-Z0-9])?)*$/;
|
|
27257
|
+
var egressHostSchema = external_exports.string().min(1).max(253).refine((h2) => h2 === "*" || HOSTNAME.test(h2), {
|
|
27258
|
+
message: "host must be a DNS hostname, a *.wildcard, or bare *"
|
|
27259
|
+
});
|
|
27212
27260
|
var egressPresetSchema = external_exports.enum(["none", "trusted", "all"]);
|
|
27213
27261
|
var egressRuleListForAgentInputSchema = external_exports.object({
|
|
27214
27262
|
agentId: external_exports.string().min(1)
|
|
@@ -27218,7 +27266,7 @@ var egressRuleCurrentPresetInputSchema = external_exports.object({
|
|
|
27218
27266
|
});
|
|
27219
27267
|
var egressRuleCreateInputSchema = external_exports.object({
|
|
27220
27268
|
agentId: external_exports.string().min(1),
|
|
27221
|
-
host:
|
|
27269
|
+
host: egressHostSchema,
|
|
27222
27270
|
// Upstream port; omit for 443. Promotes the host onto the L7 chain.
|
|
27223
27271
|
port: external_exports.number().int().min(1).max(65535).optional(),
|
|
27224
27272
|
method: external_exports.string().min(1).default("*"),
|
|
@@ -27257,6 +27305,9 @@ var agentSizeSchema = external_exports.object({
|
|
|
27257
27305
|
cpu: cpuQuantitySchema.optional(),
|
|
27258
27306
|
memory: memoryQuantitySchema.optional()
|
|
27259
27307
|
});
|
|
27308
|
+
var agentUpgradeInputSchema = idSchema.extend({
|
|
27309
|
+
expectedToImage: external_exports.string().min(1).optional()
|
|
27310
|
+
});
|
|
27260
27311
|
var agentCreateInputSchema = external_exports.object({
|
|
27261
27312
|
name: external_exports.string().min(1).refine((n) => !n.startsWith("agent-"), {
|
|
27262
27313
|
message: "agent name cannot start with 'agent-' (reserved for IDs)"
|
|
@@ -27290,7 +27341,15 @@ var agentCreateInputSchema = external_exports.object({
|
|
|
27290
27341
|
// dimensions inherit the template's limits, else the chart default.
|
|
27291
27342
|
// Requests are derived server-side — never a user concept. Floors match
|
|
27292
27343
|
// the chart's derivation floors; the budget gate is the only ceiling.
|
|
27293
|
-
size: agentSizeSchema.optional()
|
|
27344
|
+
size: agentSizeSchema.optional(),
|
|
27345
|
+
// Sweepable (#2816): mark this agent for automatic deletion by the Agent
|
|
27346
|
+
// Sweep once it hibernates. Set on ephemeral agents (Invocation targets);
|
|
27347
|
+
// durable owned agents omit it. Stamped as an annotation at create.
|
|
27348
|
+
sweepable: external_exports.boolean().optional(),
|
|
27349
|
+
// Agent Lifetime (#2816): optional grace in ms a Sweepable agent may stay
|
|
27350
|
+
// hibernated before the Sweep deletes it. Default zero — deleted as soon
|
|
27351
|
+
// as it hibernates. Ignored unless `sweepable`.
|
|
27352
|
+
lifetimeMs: external_exports.number().int().min(0).optional()
|
|
27294
27353
|
}).refine((d2) => d2.templateId !== void 0 || d2.image !== void 0, {
|
|
27295
27354
|
message: "Either templateId or image is required"
|
|
27296
27355
|
});
|
|
@@ -27310,11 +27369,32 @@ var agentUpdateInputSchema = external_exports.object({
|
|
|
27310
27369
|
});
|
|
27311
27370
|
var agentConnectSlackInputSchema = external_exports.object({
|
|
27312
27371
|
id: external_exports.string().min(1),
|
|
27313
|
-
slackChannelId: external_exports.string().min(1)
|
|
27372
|
+
slackChannelId: external_exports.string().min(1),
|
|
27373
|
+
// Access mode; absent = person-scoped.
|
|
27374
|
+
mode: external_exports.enum(["shared", "person-scoped"]).optional(),
|
|
27375
|
+
// Ambient mode; absent = off. Unlike mode it is mutable: re-connecting
|
|
27376
|
+
// with the same mode updates it in place.
|
|
27377
|
+
ambient: external_exports.boolean().optional()
|
|
27378
|
+
}).refine((v2) => !v2.ambient || v2.mode === "shared", {
|
|
27379
|
+
message: "Ambient mode requires a shared binding",
|
|
27380
|
+
path: ["ambient"]
|
|
27381
|
+
});
|
|
27382
|
+
var agentListTelegramChatsInputSchema = external_exports.object({
|
|
27383
|
+
agentId: external_exports.string().min(1)
|
|
27314
27384
|
});
|
|
27315
|
-
var
|
|
27316
|
-
|
|
27317
|
-
|
|
27385
|
+
var agentUnbindTelegramChatInputSchema = external_exports.object({
|
|
27386
|
+
agentId: external_exports.string().min(1),
|
|
27387
|
+
conversationId: external_exports.string().min(1)
|
|
27388
|
+
});
|
|
27389
|
+
var agentBindTelegramChatInputSchema = external_exports.object({
|
|
27390
|
+
agentId: external_exports.string().min(1),
|
|
27391
|
+
// Opaque bind-flow id minted by the Telegram OAuth callback.
|
|
27392
|
+
flowId: external_exports.string().min(1)
|
|
27393
|
+
});
|
|
27394
|
+
var agentBindSlackChannelInputSchema = external_exports.object({
|
|
27395
|
+
agentId: external_exports.string().min(1),
|
|
27396
|
+
// Opaque bind-flow id minted by the Slack in-chat bind OAuth callback.
|
|
27397
|
+
flowId: external_exports.string().min(1)
|
|
27318
27398
|
});
|
|
27319
27399
|
|
|
27320
27400
|
// ../api-server-api/src/modules/schedules/schemas.ts
|
|
@@ -27417,6 +27497,83 @@ var experimentAddArmInputSchema = external_exports.object({
|
|
|
27417
27497
|
armVariation: armVariationSchema.default("")
|
|
27418
27498
|
});
|
|
27419
27499
|
|
|
27500
|
+
// ../api-server-api/src/modules/artifact-library/schemas.ts
|
|
27501
|
+
var artifactKindSchema = external_exports.enum([
|
|
27502
|
+
"html",
|
|
27503
|
+
"jsx",
|
|
27504
|
+
"markdown",
|
|
27505
|
+
"code",
|
|
27506
|
+
"text",
|
|
27507
|
+
"binary"
|
|
27508
|
+
]);
|
|
27509
|
+
var artifactVisibilitySchema = external_exports.enum(["private", "public"]);
|
|
27510
|
+
var titleSchema = external_exports.string().trim().min(1, "title is required").max(300);
|
|
27511
|
+
var fileNameSchema = external_exports.string().trim().min(1).max(255);
|
|
27512
|
+
var expiresInHoursSchema = external_exports.number().int().positive().max(24 * 365 * 10);
|
|
27513
|
+
var artifactIdInputSchema = external_exports.object({ id: external_exports.string().min(1) });
|
|
27514
|
+
var artifactListInputSchema = external_exports.object({
|
|
27515
|
+
folderId: external_exports.string().min(1).nullish(),
|
|
27516
|
+
agentId: external_exports.string().min(1).optional(),
|
|
27517
|
+
search: external_exports.string().trim().max(200).optional()
|
|
27518
|
+
});
|
|
27519
|
+
var artifactContentInputSchema = external_exports.object({
|
|
27520
|
+
id: external_exports.string().min(1),
|
|
27521
|
+
version: external_exports.number().int().positive().optional()
|
|
27522
|
+
});
|
|
27523
|
+
var INLINE_CONTENT_MAX_BYTES = 2 * 1024 * 1024;
|
|
27524
|
+
var contentOrUploadRef = {
|
|
27525
|
+
content: external_exports.string().max(INLINE_CONTENT_MAX_BYTES).optional(),
|
|
27526
|
+
uploadRef: external_exports.string().min(1).max(1024).optional()
|
|
27527
|
+
};
|
|
27528
|
+
var artifactCreateInputSchema = external_exports.object({
|
|
27529
|
+
title: titleSchema,
|
|
27530
|
+
...contentOrUploadRef,
|
|
27531
|
+
fileName: fileNameSchema.optional(),
|
|
27532
|
+
kind: artifactKindSchema.optional(),
|
|
27533
|
+
contentType: external_exports.string().trim().min(1).max(200).optional(),
|
|
27534
|
+
folderId: external_exports.string().min(1).optional(),
|
|
27535
|
+
visibility: artifactVisibilitySchema.optional(),
|
|
27536
|
+
expiresInHours: expiresInHoursSchema.nullish()
|
|
27537
|
+
}).refine((v2) => v2.content == null !== (v2.uploadRef == null), {
|
|
27538
|
+
message: "provide exactly one of content or uploadRef",
|
|
27539
|
+
path: ["content"]
|
|
27540
|
+
});
|
|
27541
|
+
var artifactUpdateInputSchema = external_exports.object({
|
|
27542
|
+
id: external_exports.string().min(1),
|
|
27543
|
+
title: titleSchema.optional(),
|
|
27544
|
+
folderId: external_exports.string().min(1).nullish(),
|
|
27545
|
+
...contentOrUploadRef,
|
|
27546
|
+
fileName: fileNameSchema.optional(),
|
|
27547
|
+
kind: artifactKindSchema.optional(),
|
|
27548
|
+
contentType: external_exports.string().trim().min(1).max(200).optional()
|
|
27549
|
+
}).refine((v2) => !(v2.content != null && v2.uploadRef != null), {
|
|
27550
|
+
message: "provide at most one of content or uploadRef",
|
|
27551
|
+
path: ["content"]
|
|
27552
|
+
});
|
|
27553
|
+
var artifactSharingInputSchema = external_exports.object({
|
|
27554
|
+
id: external_exports.string().min(1),
|
|
27555
|
+
visibility: artifactVisibilitySchema.optional(),
|
|
27556
|
+
expiresInHours: expiresInHoursSchema.nullish()
|
|
27557
|
+
});
|
|
27558
|
+
var artifactUploadUrlInputSchema = external_exports.object({
|
|
27559
|
+
fileName: fileNameSchema
|
|
27560
|
+
});
|
|
27561
|
+
var folderCreateInputSchema = external_exports.object({
|
|
27562
|
+
name: external_exports.string().trim().min(1, "name is required").max(200)
|
|
27563
|
+
});
|
|
27564
|
+
var folderUpdateInputSchema = external_exports.object({
|
|
27565
|
+
id: external_exports.string().min(1),
|
|
27566
|
+
name: external_exports.string().trim().min(1).max(200).optional()
|
|
27567
|
+
});
|
|
27568
|
+
var folderIdInputSchema = external_exports.object({ id: external_exports.string().min(1) });
|
|
27569
|
+
|
|
27570
|
+
// ../api-server-api/src/modules/features/schemas.ts
|
|
27571
|
+
var featureIdSchema = external_exports.enum(["advanced-connections", "experiments"]);
|
|
27572
|
+
var featureSetFlagInputSchema = external_exports.object({
|
|
27573
|
+
feature: featureIdSchema,
|
|
27574
|
+
enabled: external_exports.boolean()
|
|
27575
|
+
});
|
|
27576
|
+
|
|
27420
27577
|
// ../../node_modules/.pnpm/rrule@2.8.1/node_modules/rrule/dist/esm/index.js
|
|
27421
27578
|
var esm_exports = {};
|
|
27422
27579
|
__export(esm_exports, {
|
|
@@ -30648,6 +30805,17 @@ var clientCredentialsAuth = external_exports.object({
|
|
|
30648
30805
|
tokenEndpointAcceptJson: external_exports.boolean().optional(),
|
|
30649
30806
|
host: external_exports.string().min(1).optional()
|
|
30650
30807
|
});
|
|
30808
|
+
var githubAppAuth = external_exports.object({
|
|
30809
|
+
kind: external_exports.literal("github-app"),
|
|
30810
|
+
appId: external_exports.string().min(1),
|
|
30811
|
+
installationId: external_exports.string().min(1),
|
|
30812
|
+
privateKeyRef: secretRef,
|
|
30813
|
+
accessTokenRef: secretRef,
|
|
30814
|
+
apiBaseUrl: external_exports.string().url(),
|
|
30815
|
+
expiresAt: external_exports.number().int().optional(),
|
|
30816
|
+
connectedAt: external_exports.number().int().optional(),
|
|
30817
|
+
host: external_exports.string().min(1).optional()
|
|
30818
|
+
});
|
|
30651
30819
|
var headerAuth = external_exports.object({
|
|
30652
30820
|
kind: external_exports.literal("header"),
|
|
30653
30821
|
valueRef: secretRef,
|
|
@@ -30660,6 +30828,7 @@ var noneAuth = external_exports.object({
|
|
|
30660
30828
|
var authConfig = external_exports.discriminatedUnion("kind", [
|
|
30661
30829
|
oauthAuth,
|
|
30662
30830
|
clientCredentialsAuth,
|
|
30831
|
+
githubAppAuth,
|
|
30663
30832
|
headerAuth,
|
|
30664
30833
|
noneAuth
|
|
30665
30834
|
]);
|
|
@@ -30681,6 +30850,7 @@ var connectionStatus = external_exports.enum([
|
|
|
30681
30850
|
var authKind = external_exports.enum([
|
|
30682
30851
|
"oauth",
|
|
30683
30852
|
"client-credentials",
|
|
30853
|
+
"github-app",
|
|
30684
30854
|
"header",
|
|
30685
30855
|
"none"
|
|
30686
30856
|
]);
|
|
@@ -30708,6 +30878,8 @@ var templateInput = external_exports.object({
|
|
|
30708
30878
|
state: templateInputState,
|
|
30709
30879
|
presetValue: external_exports.string().optional(),
|
|
30710
30880
|
secret: external_exports.boolean().optional(),
|
|
30881
|
+
// Renders as a multi-line textarea rather than a single-line input (e.g. a PEM private key).
|
|
30882
|
+
multiline: external_exports.boolean().optional(),
|
|
30711
30883
|
// Marks a config input the form packs into `configInputs` rather than the typed auth fields.
|
|
30712
30884
|
configInput: external_exports.boolean().optional(),
|
|
30713
30885
|
label: external_exports.string().optional(),
|
|
@@ -30823,14 +30995,26 @@ var clientCredentialsCreateInput = external_exports.object({
|
|
|
30823
30995
|
"env var name must be letters, digits, and underscores (not starting with a digit)"
|
|
30824
30996
|
).optional()
|
|
30825
30997
|
});
|
|
30998
|
+
var githubAppCreateInput = external_exports.object({
|
|
30999
|
+
...commonFields,
|
|
31000
|
+
authKind: external_exports.literal("github-app"),
|
|
31001
|
+
appId: external_exports.string().min(1),
|
|
31002
|
+
installationId: external_exports.string().min(1),
|
|
31003
|
+
privateKey: external_exports.string().min(1)
|
|
31004
|
+
});
|
|
30826
31005
|
var noneCreateInput = external_exports.object({
|
|
30827
31006
|
...commonFields,
|
|
30828
31007
|
authKind: external_exports.literal("none"),
|
|
30829
|
-
url: external_exports.string().url().optional()
|
|
31008
|
+
url: external_exports.string().url().optional(),
|
|
31009
|
+
// Optional header credential (API key) for MCP servers guarded by a
|
|
31010
|
+
// static header — injected at the gateway, never written to harness config.
|
|
31011
|
+
headerName: external_exports.string().min(1).optional(),
|
|
31012
|
+
value: external_exports.string().min(1).optional()
|
|
30830
31013
|
});
|
|
30831
31014
|
var connectionCreateInputSchema = external_exports.discriminatedUnion("authKind", [
|
|
30832
31015
|
oauthCreateInput,
|
|
30833
31016
|
clientCredentialsCreateInput,
|
|
31017
|
+
githubAppCreateInput,
|
|
30834
31018
|
headerCreateInput,
|
|
30835
31019
|
noneCreateInput
|
|
30836
31020
|
]);
|
|
@@ -31078,7 +31262,9 @@ var slackFireMentionInputSchema = external_exports.object({
|
|
|
31078
31262
|
channel: external_exports.string().min(1),
|
|
31079
31263
|
ts: external_exports.string().min(1),
|
|
31080
31264
|
threadTs: external_exports.string().optional(),
|
|
31081
|
-
text: external_exports.string()
|
|
31265
|
+
text: external_exports.string(),
|
|
31266
|
+
/** Workspace id; present so the fake exercises the live-streaming path. */
|
|
31267
|
+
teamId: external_exports.string().optional()
|
|
31082
31268
|
}).strict();
|
|
31083
31269
|
var slackFireCommandInputSchema = external_exports.object({
|
|
31084
31270
|
text: external_exports.string(),
|
|
@@ -31110,6 +31296,33 @@ var slackOutboundRecordSchema = external_exports.discriminatedUnion("kind", [
|
|
|
31110
31296
|
kind: external_exports.literal("upload"),
|
|
31111
31297
|
channelId: external_exports.string(),
|
|
31112
31298
|
filename: external_exports.string()
|
|
31299
|
+
}).strict(),
|
|
31300
|
+
external_exports.object({
|
|
31301
|
+
kind: external_exports.literal("stream_start"),
|
|
31302
|
+
channel: external_exports.string(),
|
|
31303
|
+
threadTs: external_exports.string(),
|
|
31304
|
+
ts: external_exports.string(),
|
|
31305
|
+
text: external_exports.string(),
|
|
31306
|
+
recipientTeamId: external_exports.string().optional(),
|
|
31307
|
+
recipientUserId: external_exports.string().optional()
|
|
31308
|
+
}).strict(),
|
|
31309
|
+
external_exports.object({
|
|
31310
|
+
kind: external_exports.literal("stream_append"),
|
|
31311
|
+
channel: external_exports.string(),
|
|
31312
|
+
ts: external_exports.string(),
|
|
31313
|
+
text: external_exports.string()
|
|
31314
|
+
}).strict(),
|
|
31315
|
+
external_exports.object({
|
|
31316
|
+
kind: external_exports.literal("stream_stop"),
|
|
31317
|
+
channel: external_exports.string(),
|
|
31318
|
+
ts: external_exports.string(),
|
|
31319
|
+
text: external_exports.string().optional()
|
|
31320
|
+
}).strict(),
|
|
31321
|
+
external_exports.object({
|
|
31322
|
+
kind: external_exports.literal("status"),
|
|
31323
|
+
channel: external_exports.string(),
|
|
31324
|
+
threadTs: external_exports.string(),
|
|
31325
|
+
status: external_exports.string()
|
|
31113
31326
|
}).strict()
|
|
31114
31327
|
]);
|
|
31115
31328
|
var slackReadOutboundResultSchema = external_exports.object({ records: external_exports.array(slackOutboundRecordSchema) }).strict();
|
|
@@ -31436,6 +31649,7 @@ var EXIT_RULE_NOT_FOUND = 6;
|
|
|
31436
31649
|
var EXIT_AGENT_NOT_REACHABLE = 7;
|
|
31437
31650
|
var EXIT_APPROVAL_NOT_ACTIONABLE = 8;
|
|
31438
31651
|
var EXIT_SCHEDULE_NOT_FOUND = 9;
|
|
31652
|
+
var EXIT_TERMS_NOT_ACCEPTED = 10;
|
|
31439
31653
|
var EXIT_SIGINT = 130;
|
|
31440
31654
|
|
|
31441
31655
|
// src/modules/agent/commands/create.ts
|
|
@@ -37247,11 +37461,16 @@ function buildDisallowCommand(deps) {
|
|
|
37247
37461
|
// src/modules/channel/commands/list.ts
|
|
37248
37462
|
function renderHuman(channels, allowedUserEmails) {
|
|
37249
37463
|
const channelsBlock = channels.length === 0 ? "No channels connected.\n" : renderTable([
|
|
37250
|
-
["TYPE", "IDENTIFIER"],
|
|
37464
|
+
["TYPE", "IDENTIFIER", "MODE"],
|
|
37251
37465
|
...channels.map(
|
|
37252
37466
|
(c2) => (
|
|
37253
37467
|
// Telegram has no readable identifier — the bot token is write-only.
|
|
37254
|
-
|
|
37468
|
+
// Telegram is structurally shared-only.
|
|
37469
|
+
c2.type === "slack" /* Slack */ ? [
|
|
37470
|
+
"slack",
|
|
37471
|
+
c2.slackChannelId,
|
|
37472
|
+
c2.ambient ? "shared (ambient)" : c2.mode ?? "person-scoped"
|
|
37473
|
+
] : ["telegram", "\u2014", "shared"]
|
|
37255
37474
|
)
|
|
37256
37475
|
)
|
|
37257
37476
|
]);
|
|
@@ -37305,7 +37524,7 @@ function buildListCommand3(deps) {
|
|
|
37305
37524
|
// src/modules/channel/commands/precheck.ts
|
|
37306
37525
|
var UNAVAILABLE_MESSAGE = {
|
|
37307
37526
|
["slack" /* Slack */]: "Slack app token not configured",
|
|
37308
|
-
["telegram" /* Telegram */]: "Telegram
|
|
37527
|
+
["telegram" /* Telegram */]: "Telegram bot not configured"
|
|
37309
37528
|
};
|
|
37310
37529
|
async function ensureProviderAvailable(svc, provider, host) {
|
|
37311
37530
|
const res = await svc.available();
|
|
@@ -37323,11 +37542,17 @@ async function ensureProviderAvailable(svc, provider, host) {
|
|
|
37323
37542
|
// src/modules/channel/commands/slack-connect.ts
|
|
37324
37543
|
function buildSlackConnectCommand(deps) {
|
|
37325
37544
|
return new Command("connect").description("Bind a Slack channel to an Agent").argument("<agent>", "Agent Ref \u2014 name or 'agent-\u2026' ID").requiredOption("--channel-id <id>", "Slack channel id (e.g. C0123ABCD)").option(
|
|
37545
|
+
"--mode <mode>",
|
|
37546
|
+
"access mode: 'person-scoped' (default) or 'shared'"
|
|
37547
|
+
).option(
|
|
37548
|
+
"--ambient",
|
|
37549
|
+
"ambient mode (shared only): the agent reads along and may chime in without being mentioned"
|
|
37550
|
+
).option(
|
|
37326
37551
|
"--server <url>",
|
|
37327
37552
|
"override the configured server URL for this call"
|
|
37328
37553
|
).option("--json", "emit the updated ChannelConfig[] as JSON").addHelpText(
|
|
37329
37554
|
"after",
|
|
37330
|
-
"\nExamples:\n dam channel slack connect my-agent --channel-id C0123ABCD\n"
|
|
37555
|
+
"\nExamples:\n dam channel slack connect my-agent --channel-id C0123ABCD\n dam channel slack connect my-agent --channel-id C0123ABCD --mode shared\n dam channel slack connect my-agent --channel-id C0123ABCD --mode shared --ambient\n"
|
|
37331
37556
|
).action(
|
|
37332
37557
|
async (ref, opts) => {
|
|
37333
37558
|
const channelId = opts.channelId.trim();
|
|
@@ -37335,6 +37560,17 @@ function buildSlackConnectCommand(deps) {
|
|
|
37335
37560
|
process.stderr.write("error: --channel-id must not be empty\n");
|
|
37336
37561
|
process.exit(EXIT_INVALID_INPUT);
|
|
37337
37562
|
}
|
|
37563
|
+
if (opts.mode !== void 0 && opts.mode !== "shared" && opts.mode !== "person-scoped") {
|
|
37564
|
+
process.stderr.write(
|
|
37565
|
+
"error: --mode must be 'shared' or 'person-scoped'\n"
|
|
37566
|
+
);
|
|
37567
|
+
process.exit(EXIT_INVALID_INPUT);
|
|
37568
|
+
}
|
|
37569
|
+
const mode = opts.mode;
|
|
37570
|
+
if (opts.ambient && mode !== "shared") {
|
|
37571
|
+
process.stderr.write("error: --ambient requires --mode shared\n");
|
|
37572
|
+
process.exit(EXIT_INVALID_INPUT);
|
|
37573
|
+
}
|
|
37338
37574
|
const host = await resolveActiveHost(deps, {
|
|
37339
37575
|
flag: opts.server ? { server: opts.server } : void 0,
|
|
37340
37576
|
exitCodes: {
|
|
@@ -37352,7 +37588,12 @@ function buildSlackConnectCommand(deps) {
|
|
|
37352
37588
|
}
|
|
37353
37589
|
const svc = deps.createChannelService(host);
|
|
37354
37590
|
await ensureProviderAvailable(svc, "slack" /* Slack */, host);
|
|
37355
|
-
const res = await svc.connectSlack(
|
|
37591
|
+
const res = await svc.connectSlack(
|
|
37592
|
+
resolved.value.id,
|
|
37593
|
+
channelId,
|
|
37594
|
+
mode,
|
|
37595
|
+
opts.ambient
|
|
37596
|
+
);
|
|
37356
37597
|
if (!res.ok) {
|
|
37357
37598
|
if (res.error.kind === "channel-conflict") {
|
|
37358
37599
|
process.stderr.write(
|
|
@@ -37368,17 +37609,54 @@ function buildSlackConnectCommand(deps) {
|
|
|
37368
37609
|
printServiceError(res.error, host);
|
|
37369
37610
|
process.exit(EXIT_RUNTIME_FAILURE);
|
|
37370
37611
|
}
|
|
37612
|
+
if (mode === "shared") {
|
|
37613
|
+
const slackCh = res.value.find((c2) => c2.type === "slack" /* Slack */);
|
|
37614
|
+
if (!slackCh || slackCh.mode !== "shared") {
|
|
37615
|
+
const rolledBack = await svc.disconnectSlack(resolved.value.id);
|
|
37616
|
+
if (rolledBack.ok) {
|
|
37617
|
+
process.stderr.write(
|
|
37618
|
+
"error: this server does not support shared access mode \u2014 binding rolled back\n"
|
|
37619
|
+
);
|
|
37620
|
+
} else {
|
|
37621
|
+
process.stderr.write(
|
|
37622
|
+
"error: this server does not support shared access mode, and rolling the binding back failed \u2014 the channel is still bound in person-scoped mode; disconnect it manually\n"
|
|
37623
|
+
);
|
|
37624
|
+
printServiceError(rolledBack.error, host);
|
|
37625
|
+
}
|
|
37626
|
+
process.exit(EXIT_RUNTIME_FAILURE);
|
|
37627
|
+
}
|
|
37628
|
+
}
|
|
37629
|
+
if (opts.ambient) {
|
|
37630
|
+
const slackCh = res.value.find((c2) => c2.type === "slack" /* Slack */);
|
|
37631
|
+
if (slackCh?.type === "slack" /* Slack */ && !slackCh.ambient) {
|
|
37632
|
+
process.stderr.write(
|
|
37633
|
+
"error: this server does not support ambient mode \u2014 the channel is connected in shared mode without it\n"
|
|
37634
|
+
);
|
|
37635
|
+
process.exit(EXIT_RUNTIME_FAILURE);
|
|
37636
|
+
}
|
|
37637
|
+
}
|
|
37371
37638
|
if (opts.json) {
|
|
37372
37639
|
process.stdout.write(`${JSON.stringify(res.value)}
|
|
37373
37640
|
`);
|
|
37374
37641
|
} else {
|
|
37375
37642
|
process.stdout.write(
|
|
37376
|
-
`\u2713 Slack channel ${channelId} connected to ${resolved.value.name}.
|
|
37643
|
+
`\u2713 Slack channel ${channelId} connected to ${resolved.value.name}${mode === "shared" ? opts.ambient ? " in shared mode with ambient on" : " in shared mode" : ""}.
|
|
37377
37644
|
`
|
|
37378
37645
|
);
|
|
37379
|
-
|
|
37380
|
-
|
|
37381
|
-
|
|
37646
|
+
if (opts.ambient) {
|
|
37647
|
+
process.stderr.write(
|
|
37648
|
+
"note: the agent reads along in this channel and may chime in without being mentioned; the channel gets a visible notice\n"
|
|
37649
|
+
);
|
|
37650
|
+
}
|
|
37651
|
+
if (mode === "shared") {
|
|
37652
|
+
process.stderr.write(
|
|
37653
|
+
"note: everyone in the channel drives this agent under its credentials; your Terms-of-Use acceptance covers every turn\n"
|
|
37654
|
+
);
|
|
37655
|
+
} else {
|
|
37656
|
+
process.stderr.write(
|
|
37657
|
+
"hint: users must run `/platform login` inside Slack before they can drive this agent\n"
|
|
37658
|
+
);
|
|
37659
|
+
}
|
|
37382
37660
|
}
|
|
37383
37661
|
process.exit(EXIT_SUCCESS);
|
|
37384
37662
|
}
|
|
@@ -37430,131 +37708,19 @@ function buildSlackDisconnectCommand(deps) {
|
|
|
37430
37708
|
});
|
|
37431
37709
|
}
|
|
37432
37710
|
|
|
37433
|
-
// src/modules/channel/commands/telegram-connect.ts
|
|
37434
|
-
function buildTelegramConnectCommand(deps) {
|
|
37435
|
-
return new Command("connect").description("Bind a Telegram bot to an Agent").argument("<agent>", "Agent Ref \u2014 name or 'agent-\u2026' ID").option(
|
|
37436
|
-
"--bot-token <token>",
|
|
37437
|
-
"bot token from @BotFather (prompted, masked, if omitted on a TTY)"
|
|
37438
|
-
).option(
|
|
37439
|
-
"--server <url>",
|
|
37440
|
-
"override the configured server URL for this call"
|
|
37441
|
-
).option("--json", "emit the updated ChannelConfig[] as JSON").addHelpText(
|
|
37442
|
-
"after",
|
|
37443
|
-
"\nExamples:\n dam channel telegram connect my-agent\n dam channel telegram connect my-agent --bot-token 123:ABC\n"
|
|
37444
|
-
).action(
|
|
37445
|
-
async (ref, opts) => {
|
|
37446
|
-
const host = await resolveActiveHost(deps, {
|
|
37447
|
-
flag: opts.server ? { server: opts.server } : void 0,
|
|
37448
|
-
exitCodes: {
|
|
37449
|
-
runtimeFailure: EXIT_RUNTIME_FAILURE,
|
|
37450
|
-
belowFloor: EXIT_BELOW_FLOOR
|
|
37451
|
-
}
|
|
37452
|
-
});
|
|
37453
|
-
const resolver = createAgentResolver({
|
|
37454
|
-
agentService: deps.createAgentService(host)
|
|
37455
|
-
});
|
|
37456
|
-
const resolved = await resolver.resolve(ref);
|
|
37457
|
-
if (!resolved.ok) {
|
|
37458
|
-
printResolveError(resolved.error, host);
|
|
37459
|
-
process.exit(exitCodeForResolveError(resolved.error));
|
|
37460
|
-
}
|
|
37461
|
-
const token = await resolveToken(opts);
|
|
37462
|
-
const svc = deps.createChannelService(host);
|
|
37463
|
-
await ensureProviderAvailable(svc, "telegram" /* Telegram */, host);
|
|
37464
|
-
const res = await svc.connectTelegram(resolved.value.id, token);
|
|
37465
|
-
if (!res.ok) {
|
|
37466
|
-
if (res.error.kind === "channel-precondition" || res.error.kind === "invalid-input") {
|
|
37467
|
-
process.stderr.write(`error: ${res.error.message}
|
|
37468
|
-
`);
|
|
37469
|
-
process.exit(EXIT_INVALID_INPUT);
|
|
37470
|
-
}
|
|
37471
|
-
printServiceError(res.error, host);
|
|
37472
|
-
process.exit(EXIT_RUNTIME_FAILURE);
|
|
37473
|
-
}
|
|
37474
|
-
if (opts.json) {
|
|
37475
|
-
process.stdout.write(`${JSON.stringify(res.value)}
|
|
37476
|
-
`);
|
|
37477
|
-
} else {
|
|
37478
|
-
process.stdout.write(
|
|
37479
|
-
`\u2713 Telegram bot connected to ${resolved.value.name}.
|
|
37480
|
-
`
|
|
37481
|
-
);
|
|
37482
|
-
}
|
|
37483
|
-
process.exit(EXIT_SUCCESS);
|
|
37484
|
-
}
|
|
37485
|
-
);
|
|
37486
|
-
}
|
|
37487
|
-
async function resolveToken(opts) {
|
|
37488
|
-
const flag = opts.botToken?.trim();
|
|
37489
|
-
if (flag) return flag;
|
|
37490
|
-
if (!process.stdin.isTTY) {
|
|
37491
|
-
process.stderr.write("error: --bot-token is required on a non-TTY\n");
|
|
37492
|
-
process.exit(EXIT_INVALID_INPUT);
|
|
37493
|
-
}
|
|
37494
|
-
const answer = await Ce({
|
|
37495
|
-
message: "Telegram bot token (from @BotFather)",
|
|
37496
|
-
validate: (v2) => v2 && v2.trim().length > 0 ? void 0 : "Required"
|
|
37497
|
-
});
|
|
37498
|
-
if (q(answer)) exitCancelled({ json: opts.json });
|
|
37499
|
-
return String(answer).trim();
|
|
37500
|
-
}
|
|
37501
|
-
|
|
37502
|
-
// src/modules/channel/commands/telegram-disconnect.ts
|
|
37503
|
-
function buildTelegramDisconnectCommand(deps) {
|
|
37504
|
-
return new Command("disconnect").description(
|
|
37505
|
-
"Unbind an Agent's Telegram bot (deletes its k8s Secret). Idempotent \u2014 a not-connected agent exits 0."
|
|
37506
|
-
).argument("<agent>", "Agent Ref \u2014 name or 'agent-\u2026' ID").option(
|
|
37507
|
-
"--server <url>",
|
|
37508
|
-
"override the configured server URL for this call"
|
|
37509
|
-
).option("--json", "emit the updated ChannelConfig[] as JSON").addHelpText(
|
|
37510
|
-
"after",
|
|
37511
|
-
"\nExamples:\n dam channel telegram disconnect my-agent\n"
|
|
37512
|
-
).action(async (ref, opts) => {
|
|
37513
|
-
const host = await resolveActiveHost(deps, {
|
|
37514
|
-
flag: opts.server ? { server: opts.server } : void 0,
|
|
37515
|
-
exitCodes: {
|
|
37516
|
-
runtimeFailure: EXIT_RUNTIME_FAILURE,
|
|
37517
|
-
belowFloor: EXIT_BELOW_FLOOR
|
|
37518
|
-
}
|
|
37519
|
-
});
|
|
37520
|
-
const resolver = createAgentResolver({
|
|
37521
|
-
agentService: deps.createAgentService(host)
|
|
37522
|
-
});
|
|
37523
|
-
const resolved = await resolver.resolve(ref);
|
|
37524
|
-
if (!resolved.ok) {
|
|
37525
|
-
printResolveError(resolved.error, host);
|
|
37526
|
-
process.exit(exitCodeForResolveError(resolved.error));
|
|
37527
|
-
}
|
|
37528
|
-
const svc = deps.createChannelService(host);
|
|
37529
|
-
const res = await svc.disconnectTelegram(resolved.value.id);
|
|
37530
|
-
if (!res.ok) {
|
|
37531
|
-
printServiceError(res.error, host);
|
|
37532
|
-
process.exit(EXIT_RUNTIME_FAILURE);
|
|
37533
|
-
}
|
|
37534
|
-
if (opts.json) {
|
|
37535
|
-
process.stdout.write(`${JSON.stringify(res.value)}
|
|
37536
|
-
`);
|
|
37537
|
-
} else {
|
|
37538
|
-
process.stdout.write(
|
|
37539
|
-
`\u2713 Telegram disconnected from ${resolved.value.name}.
|
|
37540
|
-
`
|
|
37541
|
-
);
|
|
37542
|
-
}
|
|
37543
|
-
process.exit(EXIT_SUCCESS);
|
|
37544
|
-
});
|
|
37545
|
-
}
|
|
37546
|
-
|
|
37547
37711
|
// src/modules/channel/services/channel-service.ts
|
|
37548
37712
|
function createChannelService(deps) {
|
|
37549
37713
|
return {
|
|
37550
37714
|
async available() {
|
|
37551
37715
|
return trpcCall(() => deps.trpc.channels.available.query());
|
|
37552
37716
|
},
|
|
37553
|
-
async connectSlack(id, slackChannelId) {
|
|
37717
|
+
async connectSlack(id, slackChannelId, mode, ambient) {
|
|
37554
37718
|
try {
|
|
37555
37719
|
const agent = await deps.trpc.agents.connectSlack.mutate({
|
|
37556
37720
|
id,
|
|
37557
|
-
slackChannelId
|
|
37721
|
+
slackChannelId,
|
|
37722
|
+
...mode ? { mode } : {},
|
|
37723
|
+
...ambient ? { ambient: true } : {}
|
|
37558
37724
|
});
|
|
37559
37725
|
return ok2(agent.channels);
|
|
37560
37726
|
} catch (e2) {
|
|
@@ -37574,29 +37740,6 @@ function createChannelService(deps) {
|
|
|
37574
37740
|
const agent = await deps.trpc.agents.disconnectSlack.mutate({ id });
|
|
37575
37741
|
return agent.channels;
|
|
37576
37742
|
});
|
|
37577
|
-
},
|
|
37578
|
-
async connectTelegram(id, botToken) {
|
|
37579
|
-
try {
|
|
37580
|
-
const agent = await deps.trpc.agents.connectTelegram.mutate({
|
|
37581
|
-
id,
|
|
37582
|
-
botToken
|
|
37583
|
-
});
|
|
37584
|
-
return ok2(agent.channels);
|
|
37585
|
-
} catch (e2) {
|
|
37586
|
-
const code = e2?.data?.code;
|
|
37587
|
-
const message = e2 instanceof Error ? e2.message : String(e2);
|
|
37588
|
-
if (code === "PRECONDITION_FAILED")
|
|
37589
|
-
return err2({ kind: "channel-precondition", message });
|
|
37590
|
-
if (code === "BAD_REQUEST")
|
|
37591
|
-
return err2({ kind: "invalid-input", message });
|
|
37592
|
-
return classifyTrpcError(e2);
|
|
37593
|
-
}
|
|
37594
|
-
},
|
|
37595
|
-
async disconnectTelegram(id) {
|
|
37596
|
-
return trpcCall(async () => {
|
|
37597
|
-
const agent = await deps.trpc.agents.disconnectTelegram.mutate({ id });
|
|
37598
|
-
return agent.channels;
|
|
37599
|
-
});
|
|
37600
37743
|
}
|
|
37601
37744
|
};
|
|
37602
37745
|
}
|
|
@@ -37612,7 +37755,7 @@ function composeChannelModule(opts) {
|
|
|
37612
37755
|
createChannelService: createService
|
|
37613
37756
|
};
|
|
37614
37757
|
const parent = new Command("channel").description(
|
|
37615
|
-
"Manage messenger channel bindings (
|
|
37758
|
+
"Manage messenger channel bindings (Telegram chats bind in-chat via /login)"
|
|
37616
37759
|
);
|
|
37617
37760
|
parent.addCommand(
|
|
37618
37761
|
buildAvailableCommand({
|
|
@@ -37634,12 +37777,6 @@ function composeChannelModule(opts) {
|
|
|
37634
37777
|
slack.addCommand(buildSlackConnectCommand(agentScoped));
|
|
37635
37778
|
slack.addCommand(buildSlackDisconnectCommand(agentScoped));
|
|
37636
37779
|
parent.addCommand(slack);
|
|
37637
|
-
const telegram = new Command("telegram").description(
|
|
37638
|
-
"Bind or unbind an Agent's Telegram bot"
|
|
37639
|
-
);
|
|
37640
|
-
telegram.addCommand(buildTelegramConnectCommand(agentScoped));
|
|
37641
|
-
telegram.addCommand(buildTelegramDisconnectCommand(agentScoped));
|
|
37642
|
-
parent.addCommand(telegram);
|
|
37643
37780
|
const allowScoped = {
|
|
37644
37781
|
compatService: opts.compatService,
|
|
37645
37782
|
configService: opts.configService,
|
|
@@ -40174,7 +40311,7 @@ function createProcessEnvReader() {
|
|
|
40174
40311
|
|
|
40175
40312
|
// src/modules/cli/infrastructure/package-version.ts
|
|
40176
40313
|
function readPackageVersion() {
|
|
40177
|
-
return true ? "0.2.
|
|
40314
|
+
return true ? "0.2.8-rc1" : DEV_VERSION;
|
|
40178
40315
|
}
|
|
40179
40316
|
|
|
40180
40317
|
// src/modules/cli/infrastructure/version-probe.ts
|
|
@@ -40410,7 +40547,13 @@ function buildConnectCommand(deps) {
|
|
|
40410
40547
|
).option(
|
|
40411
40548
|
"--audience <audience>",
|
|
40412
40549
|
"input: OAuth audience (client credentials)"
|
|
40413
|
-
).option("--app-slug <slug>", "input: GitHub App slug").option("--
|
|
40550
|
+
).option("--app-slug <slug>", "input: GitHub App slug").option("--app-id <id>", "input: GitHub App ID (GitHub App installation)").option(
|
|
40551
|
+
"--installation-id <id>",
|
|
40552
|
+
"input: GitHub App installation ID (GitHub App installation)"
|
|
40553
|
+
).option(
|
|
40554
|
+
"--private-key <pem>",
|
|
40555
|
+
'input: GitHub App private key \u2014 PEM or base64; use --private-key "$(cat app.pem)" (GitHub App installation)'
|
|
40556
|
+
).option("--header-name <name>", "input: header name").option("--value-format <format>", "input: header value format").option(
|
|
40414
40557
|
"--env-name <name>",
|
|
40415
40558
|
"input: expose the credential to the agent as this env var (custom header credentials)"
|
|
40416
40559
|
).option("--value <value>", "input: header secret value").option(
|
|
@@ -40433,7 +40576,7 @@ function buildConnectCommand(deps) {
|
|
|
40433
40576
|
String(DEFAULT_TIMEOUT_SECONDS3)
|
|
40434
40577
|
).addHelpText(
|
|
40435
40578
|
"after",
|
|
40436
|
-
|
|
40579
|
+
'\nExamples:\n dam connection connect github\n dam connection connect github --client-id Iv1.\u2026 --client-secret \u2026 # use your own OAuth app\n dam connection connect github --no-browser\n dam connection connect my-api --header-name X-API-Key --value sk-\u2026\n dam connection connect custom-client-credentials --host api.example.com \\\n --issuer-url https://auth.example.com/realms/main --client-id \u2026 --client-secret \u2026\n dam connection connect github-app --app-id 123456 --installation-id 987654 \\\n --private-key "$(cat app.pem)"\n dam connection connect bob --value sk-\u2026 --config model=premium-shell --config chatMode=code\n dam connection connect https://mcp.example.com\n dam connection connect https://mcp.example.com --auth none\n'
|
|
40437
40580
|
).action(async (providerOrUrl, opts) => {
|
|
40438
40581
|
const json2 = opts.json ?? false;
|
|
40439
40582
|
const timeoutSeconds = parseTimeout2(opts.timeout);
|
|
@@ -40655,8 +40798,9 @@ async function collectInputs(template, opts, json2) {
|
|
|
40655
40798
|
}
|
|
40656
40799
|
for (const input of missing) {
|
|
40657
40800
|
const prompt = input.secret ? Ce : Re;
|
|
40801
|
+
const label = input.label ?? labelFor(input.name);
|
|
40658
40802
|
const answer = await prompt({
|
|
40659
|
-
message:
|
|
40803
|
+
message: input.hint ? `${label} \u2014 ${input.hint}` : label,
|
|
40660
40804
|
validate: (v2) => v2 && v2.trim().length > 0 ? void 0 : "Required"
|
|
40661
40805
|
});
|
|
40662
40806
|
if (q(answer)) exitCancelled({ json: json2 });
|
|
@@ -40695,6 +40839,25 @@ function buildPayload(template, name, values) {
|
|
|
40695
40839
|
...v2("valueFormat") ? { valueFormat: v2("valueFormat") } : {},
|
|
40696
40840
|
...v2("envName") ? { envName: v2("envName") } : {}
|
|
40697
40841
|
};
|
|
40842
|
+
case "github-app": {
|
|
40843
|
+
const appId = v2("appId");
|
|
40844
|
+
const installationId = v2("installationId");
|
|
40845
|
+
const privateKey = v2("privateKey");
|
|
40846
|
+
if (!appId) return { error: "the App ID is required (--app-id)" };
|
|
40847
|
+
if (!installationId) {
|
|
40848
|
+
return { error: "the installation ID is required (--installation-id)" };
|
|
40849
|
+
}
|
|
40850
|
+
if (!privateKey) {
|
|
40851
|
+
return { error: "the private key is required (--private-key)" };
|
|
40852
|
+
}
|
|
40853
|
+
return {
|
|
40854
|
+
...common2,
|
|
40855
|
+
authKind: "github-app",
|
|
40856
|
+
appId,
|
|
40857
|
+
installationId,
|
|
40858
|
+
privateKey
|
|
40859
|
+
};
|
|
40860
|
+
}
|
|
40698
40861
|
case "header": {
|
|
40699
40862
|
const value = v2("value");
|
|
40700
40863
|
if (!value) return { error: "the secret value is required (--value)" };
|
|
@@ -40817,6 +40980,9 @@ var FIELD_LABELS = {
|
|
|
40817
40980
|
scopes: "Scopes (space-separated)",
|
|
40818
40981
|
audience: "Audience",
|
|
40819
40982
|
appSlug: "GitHub App slug",
|
|
40983
|
+
appId: "GitHub App ID",
|
|
40984
|
+
installationId: "GitHub App installation ID",
|
|
40985
|
+
privateKey: "GitHub App private key (PEM)",
|
|
40820
40986
|
envName: "Env var name",
|
|
40821
40987
|
caData: "Cluster CA certificate"
|
|
40822
40988
|
};
|
|
@@ -44230,6 +44396,12 @@ function createSkillsService(deps) {
|
|
|
44230
44396
|
const message = e2.message.replace(/\nplatform-cta:\S+/, "").trim();
|
|
44231
44397
|
return err2({ kind: "source-needs-connection", message, cta });
|
|
44232
44398
|
}
|
|
44399
|
+
if (e2?.data?.code === "FORBIDDEN") {
|
|
44400
|
+
return err2({
|
|
44401
|
+
kind: "source-needs-connection",
|
|
44402
|
+
message: e2 instanceof Error ? e2.message : String(e2)
|
|
44403
|
+
});
|
|
44404
|
+
}
|
|
44233
44405
|
return classifyWakeError(e2);
|
|
44234
44406
|
}
|
|
44235
44407
|
},
|
|
@@ -45159,6 +45331,248 @@ function composeTemplateModule(opts) {
|
|
|
45159
45331
|
};
|
|
45160
45332
|
}
|
|
45161
45333
|
|
|
45334
|
+
// src/modules/terms/commands/accept.ts
|
|
45335
|
+
function buildAcceptCommand(deps) {
|
|
45336
|
+
return new Command("accept").description(
|
|
45337
|
+
"Accept the current Terms of Use \u2014 interactive on a TTY, use --yes for CI/headless"
|
|
45338
|
+
).option(
|
|
45339
|
+
"--yes",
|
|
45340
|
+
"accept without the interactive confirmation (required on a non-TTY)"
|
|
45341
|
+
).option(
|
|
45342
|
+
"--expect-version <version>",
|
|
45343
|
+
"assert the version you reviewed; fails if it differs from the server's current version (not named --version, which is reserved for the CLI's own version)"
|
|
45344
|
+
).option(
|
|
45345
|
+
"--server <url>",
|
|
45346
|
+
"override the configured server URL for this call"
|
|
45347
|
+
).option("--json", "emit the acceptance result as JSON").action(
|
|
45348
|
+
async (opts) => {
|
|
45349
|
+
const host = await resolveActiveHost(deps, {
|
|
45350
|
+
flag: opts.server ? { server: opts.server } : void 0,
|
|
45351
|
+
exitCodes: {
|
|
45352
|
+
runtimeFailure: EXIT_RUNTIME_FAILURE,
|
|
45353
|
+
belowFloor: EXIT_BELOW_FLOOR
|
|
45354
|
+
}
|
|
45355
|
+
});
|
|
45356
|
+
if (!opts.yes && !process.stdin.isTTY) {
|
|
45357
|
+
process.stderr.write(
|
|
45358
|
+
"error: refusing to accept the Terms of Use non-interactively without --yes\nhint: re-run with --yes to accept in a script or CI\n"
|
|
45359
|
+
);
|
|
45360
|
+
process.exit(EXIT_RUNTIME_FAILURE);
|
|
45361
|
+
}
|
|
45362
|
+
const service = deps.createTermsService(host);
|
|
45363
|
+
const doc = await service.document();
|
|
45364
|
+
if (!doc.ok) {
|
|
45365
|
+
printServiceError(doc.error, host);
|
|
45366
|
+
process.exit(EXIT_RUNTIME_FAILURE);
|
|
45367
|
+
}
|
|
45368
|
+
const currentVersion = doc.value.version;
|
|
45369
|
+
if (opts.expectVersion && opts.expectVersion !== currentVersion) {
|
|
45370
|
+
process.stderr.write(
|
|
45371
|
+
`error: reviewed version ${opts.expectVersion} does not match the server's current version ${currentVersion}; re-review before accepting
|
|
45372
|
+
`
|
|
45373
|
+
);
|
|
45374
|
+
process.exit(EXIT_RUNTIME_FAILURE);
|
|
45375
|
+
}
|
|
45376
|
+
if (!opts.yes) {
|
|
45377
|
+
process.stderr.write(
|
|
45378
|
+
`Terms of Use \u2014 version ${currentVersion}
|
|
45379
|
+
|
|
45380
|
+
${doc.value.text}
|
|
45381
|
+
|
|
45382
|
+
`
|
|
45383
|
+
);
|
|
45384
|
+
if (!await confirm("Accept the Terms of Use?", {
|
|
45385
|
+
timeoutMs: 15 * 6e4
|
|
45386
|
+
}))
|
|
45387
|
+
exitCancelled({ json: opts.json });
|
|
45388
|
+
}
|
|
45389
|
+
const accepted = await service.accept(currentVersion);
|
|
45390
|
+
if (!accepted.ok) {
|
|
45391
|
+
if (accepted.error.kind === "transport" && accepted.error.serverCode === "PRECONDITION_FAILED") {
|
|
45392
|
+
process.stderr.write(
|
|
45393
|
+
"error: the Terms of Use changed while you were reviewing; re-run `dam terms accept` to review the current version\n"
|
|
45394
|
+
);
|
|
45395
|
+
} else {
|
|
45396
|
+
printServiceError(accepted.error, host);
|
|
45397
|
+
}
|
|
45398
|
+
process.exit(EXIT_RUNTIME_FAILURE);
|
|
45399
|
+
}
|
|
45400
|
+
if (opts.json) {
|
|
45401
|
+
return writeStdoutAndExit(
|
|
45402
|
+
`${JSON.stringify({ accepted: true, version: currentVersion })}
|
|
45403
|
+
`,
|
|
45404
|
+
EXIT_SUCCESS
|
|
45405
|
+
);
|
|
45406
|
+
}
|
|
45407
|
+
return writeStdoutAndExit(
|
|
45408
|
+
`Accepted Terms of Use ${currentVersion}.
|
|
45409
|
+
`,
|
|
45410
|
+
EXIT_SUCCESS
|
|
45411
|
+
);
|
|
45412
|
+
}
|
|
45413
|
+
);
|
|
45414
|
+
}
|
|
45415
|
+
|
|
45416
|
+
// src/modules/terms/commands/show.ts
|
|
45417
|
+
function buildShowCommand(deps) {
|
|
45418
|
+
return new Command("show").description(
|
|
45419
|
+
"Print the current Terms of Use text, version, and your acceptance state"
|
|
45420
|
+
).option(
|
|
45421
|
+
"--server <url>",
|
|
45422
|
+
"override the configured server URL for this call"
|
|
45423
|
+
).option("--json", "emit the raw Terms of Use document as JSON").action(async (opts) => {
|
|
45424
|
+
const host = await resolveActiveHost(deps, {
|
|
45425
|
+
flag: opts.server ? { server: opts.server } : void 0,
|
|
45426
|
+
exitCodes: {
|
|
45427
|
+
runtimeFailure: EXIT_RUNTIME_FAILURE,
|
|
45428
|
+
belowFloor: EXIT_BELOW_FLOOR
|
|
45429
|
+
}
|
|
45430
|
+
});
|
|
45431
|
+
const service = deps.createTermsService(host);
|
|
45432
|
+
const [doc, latest] = await Promise.all([
|
|
45433
|
+
service.document(),
|
|
45434
|
+
service.latestAcceptance()
|
|
45435
|
+
]);
|
|
45436
|
+
if (!doc.ok) {
|
|
45437
|
+
printServiceError(doc.error, host);
|
|
45438
|
+
process.exit(EXIT_RUNTIME_FAILURE);
|
|
45439
|
+
}
|
|
45440
|
+
if (!latest.ok) {
|
|
45441
|
+
printServiceError(latest.error, host);
|
|
45442
|
+
process.exit(EXIT_RUNTIME_FAILURE);
|
|
45443
|
+
}
|
|
45444
|
+
if (opts.json) {
|
|
45445
|
+
return writeStdoutAndExit(
|
|
45446
|
+
`${JSON.stringify(doc.value)}
|
|
45447
|
+
`,
|
|
45448
|
+
EXIT_SUCCESS
|
|
45449
|
+
);
|
|
45450
|
+
}
|
|
45451
|
+
const acceptState = !latest.value ? "Not accepted." : latest.value.version === doc.value.version ? `Accepted on ${new Date(latest.value.acceptedAt).toISOString()}.` : `You accepted version ${latest.value.version}; version ${doc.value.version} is current and not yet accepted.`;
|
|
45452
|
+
return writeStdoutAndExit(
|
|
45453
|
+
`Terms of Use \u2014 version ${doc.value.version}
|
|
45454
|
+
${acceptState}
|
|
45455
|
+
|
|
45456
|
+
${doc.value.text}
|
|
45457
|
+
`,
|
|
45458
|
+
EXIT_SUCCESS
|
|
45459
|
+
);
|
|
45460
|
+
});
|
|
45461
|
+
}
|
|
45462
|
+
|
|
45463
|
+
// src/modules/terms/commands/status.ts
|
|
45464
|
+
function buildStatusCommand2(deps) {
|
|
45465
|
+
return new Command("status").description(
|
|
45466
|
+
"Check whether you've accepted the current Terms of Use \u2014 no text dump; exits non-zero when not accepted, so it works as a CI gate"
|
|
45467
|
+
).option(
|
|
45468
|
+
"--server <url>",
|
|
45469
|
+
"override the configured server URL for this call"
|
|
45470
|
+
).option("--json", "emit the acceptance state as JSON").action(async (opts) => {
|
|
45471
|
+
const host = await resolveActiveHost(deps, {
|
|
45472
|
+
flag: opts.server ? { server: opts.server } : void 0,
|
|
45473
|
+
exitCodes: {
|
|
45474
|
+
runtimeFailure: EXIT_RUNTIME_FAILURE,
|
|
45475
|
+
belowFloor: EXIT_BELOW_FLOOR
|
|
45476
|
+
}
|
|
45477
|
+
});
|
|
45478
|
+
const service = deps.createTermsService(host);
|
|
45479
|
+
const [current, latest] = await Promise.all([
|
|
45480
|
+
service.current(),
|
|
45481
|
+
service.latestAcceptance()
|
|
45482
|
+
]);
|
|
45483
|
+
if (!current.ok) {
|
|
45484
|
+
printServiceError(current.error, host);
|
|
45485
|
+
process.exit(EXIT_RUNTIME_FAILURE);
|
|
45486
|
+
}
|
|
45487
|
+
if (!latest.ok) {
|
|
45488
|
+
printServiceError(latest.error, host);
|
|
45489
|
+
process.exit(EXIT_RUNTIME_FAILURE);
|
|
45490
|
+
}
|
|
45491
|
+
const acceptedVersion = latest.value?.version ?? null;
|
|
45492
|
+
const accepted = acceptedVersion === current.value.version;
|
|
45493
|
+
const exitCode = accepted ? EXIT_SUCCESS : EXIT_TERMS_NOT_ACCEPTED;
|
|
45494
|
+
if (opts.json) {
|
|
45495
|
+
return writeStdoutAndExit(
|
|
45496
|
+
`${JSON.stringify({ currentVersion: current.value.version, acceptedVersion, accepted })}
|
|
45497
|
+
`,
|
|
45498
|
+
exitCode
|
|
45499
|
+
);
|
|
45500
|
+
}
|
|
45501
|
+
const line = accepted ? `Terms of Use ${current.value.version}: accepted.` : acceptedVersion ? `Terms of Use ${current.value.version}: NOT accepted (you accepted ${acceptedVersion}).` : `Terms of Use ${current.value.version}: NOT accepted (no acceptance on record).`;
|
|
45502
|
+
return writeStdoutAndExit(`${line}
|
|
45503
|
+
`, exitCode);
|
|
45504
|
+
});
|
|
45505
|
+
}
|
|
45506
|
+
|
|
45507
|
+
// src/modules/terms/services/terms-service.ts
|
|
45508
|
+
function createTermsService(deps) {
|
|
45509
|
+
const doFetch = deps.fetch ?? fetch;
|
|
45510
|
+
const base = deps.host.replace(/\/+$/, "");
|
|
45511
|
+
return {
|
|
45512
|
+
async document() {
|
|
45513
|
+
let res;
|
|
45514
|
+
try {
|
|
45515
|
+
res = await doFetch(`${base}/api/terms`);
|
|
45516
|
+
} catch (e2) {
|
|
45517
|
+
return err2({
|
|
45518
|
+
kind: "transport",
|
|
45519
|
+
reason: e2 instanceof Error ? e2.message : "cannot reach server"
|
|
45520
|
+
});
|
|
45521
|
+
}
|
|
45522
|
+
if (!res.ok)
|
|
45523
|
+
return err2({
|
|
45524
|
+
kind: "transport",
|
|
45525
|
+
reason: `GET /api/terms returned ${res.status}`
|
|
45526
|
+
});
|
|
45527
|
+
let body;
|
|
45528
|
+
try {
|
|
45529
|
+
body = await res.json();
|
|
45530
|
+
} catch {
|
|
45531
|
+
return err2({
|
|
45532
|
+
kind: "transport",
|
|
45533
|
+
reason: "malformed Terms of Use document from server"
|
|
45534
|
+
});
|
|
45535
|
+
}
|
|
45536
|
+
const parsed = termsDocumentSchema.safeParse(body);
|
|
45537
|
+
if (!parsed.success)
|
|
45538
|
+
return err2({
|
|
45539
|
+
kind: "transport",
|
|
45540
|
+
reason: "malformed Terms of Use document from server"
|
|
45541
|
+
});
|
|
45542
|
+
return ok2(parsed.data);
|
|
45543
|
+
},
|
|
45544
|
+
async current() {
|
|
45545
|
+
return trpcCall(() => deps.trpc.terms.current.query());
|
|
45546
|
+
},
|
|
45547
|
+
async latestAcceptance() {
|
|
45548
|
+
return trpcCall(() => deps.trpc.terms.latestAcceptance.query());
|
|
45549
|
+
},
|
|
45550
|
+
async accept(version2) {
|
|
45551
|
+
return trpcCall(() => deps.trpc.terms.accept.mutate({ version: version2 }));
|
|
45552
|
+
}
|
|
45553
|
+
};
|
|
45554
|
+
}
|
|
45555
|
+
|
|
45556
|
+
// src/modules/terms/compose.ts
|
|
45557
|
+
function composeTermsModule(opts) {
|
|
45558
|
+
const createService = (host) => createTermsService({
|
|
45559
|
+
trpc: createTrpcClient({ host, tokenProvider: opts.tokenProvider }),
|
|
45560
|
+
host
|
|
45561
|
+
});
|
|
45562
|
+
const scoped = {
|
|
45563
|
+
compatService: opts.compatService,
|
|
45564
|
+
configService: opts.configService,
|
|
45565
|
+
createTermsService: createService
|
|
45566
|
+
};
|
|
45567
|
+
const parent = new Command("terms").description(
|
|
45568
|
+
"View and accept the deployment's Terms of Use"
|
|
45569
|
+
);
|
|
45570
|
+
parent.addCommand(buildShowCommand(scoped));
|
|
45571
|
+
parent.addCommand(buildStatusCommand2(scoped));
|
|
45572
|
+
parent.addCommand(buildAcceptCommand(scoped));
|
|
45573
|
+
return { commands: [parent] };
|
|
45574
|
+
}
|
|
45575
|
+
|
|
45162
45576
|
// src/compose.ts
|
|
45163
45577
|
function compose(opts = {}) {
|
|
45164
45578
|
const cli = composeCliModule({ configPath: opts.configPath });
|
|
@@ -45251,6 +45665,11 @@ function compose(opts = {}) {
|
|
|
45251
45665
|
compatService: cli.services.compatService,
|
|
45252
45666
|
createAgentService: agent.exports.createService
|
|
45253
45667
|
});
|
|
45668
|
+
const terms = composeTermsModule({
|
|
45669
|
+
tokenProvider: auth.exports.tokenProvider,
|
|
45670
|
+
configService: cli.services.configService,
|
|
45671
|
+
compatService: cli.services.compatService
|
|
45672
|
+
});
|
|
45254
45673
|
const program3 = new Command();
|
|
45255
45674
|
program3.name("dam").description("Command-line client for a Platform deployment").version(cli.cliVersion);
|
|
45256
45675
|
for (const command of cli.commands) program3.addCommand(command);
|
|
@@ -45268,6 +45687,7 @@ function compose(opts = {}) {
|
|
|
45268
45687
|
for (const command of ssh.commands) program3.addCommand(command);
|
|
45269
45688
|
for (const command of channel.commands) program3.addCommand(command);
|
|
45270
45689
|
for (const command of metrics.commands) program3.addCommand(command);
|
|
45690
|
+
for (const command of terms.commands) program3.addCommand(command);
|
|
45271
45691
|
return program3;
|
|
45272
45692
|
}
|
|
45273
45693
|
|
|
@@ -45278,9 +45698,7 @@ try {
|
|
|
45278
45698
|
} catch (err3) {
|
|
45279
45699
|
if (err3 instanceof TermsStaleAtTransportError) {
|
|
45280
45700
|
process.stderr.write(
|
|
45281
|
-
|
|
45282
|
-
hint: open ${err3.host} to accept
|
|
45283
|
-
`
|
|
45701
|
+
"error: Terms of Use acceptance required\nhint: run `dam terms accept` to review and accept\n"
|
|
45284
45702
|
);
|
|
45285
45703
|
process.exit(1);
|
|
45286
45704
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dam-agents/cli",
|
|
3
3
|
"author": "IBM Corp.",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.8-rc1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"homepage": "https://github.com/dam-agents/dam/tree/main/packages/cli#readme",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"vitest": "^4.1.3",
|
|
44
44
|
"ws": "^8.20.0",
|
|
45
45
|
"zod": "^4.4.3",
|
|
46
|
-
"
|
|
46
|
+
"api-server-api": "0.0.1",
|
|
47
47
|
"dev-config": "0.0.1",
|
|
48
|
-
"
|
|
48
|
+
"agent-runtime-api": "0.0.1"
|
|
49
49
|
}
|
|
50
50
|
}
|