camstack 1.2.190 → 1.2.192
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/cli.js +393 -291
- package/dist/{launcher-ILGFB3AQ.js → launcher-PJJ7PTWL.js} +3873 -3518
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -37,7 +37,7 @@ async function runServe(args) {
|
|
|
37
37
|
...typeof values.data === "string" ? { data: values.data } : {}
|
|
38
38
|
};
|
|
39
39
|
Object.assign(process.env, buildServeEnv(opts));
|
|
40
|
-
await import("./launcher-
|
|
40
|
+
await import("./launcher-PJJ7PTWL.js");
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// src/commands/agent.ts
|
|
@@ -82,7 +82,7 @@ async function runAgent(args) {
|
|
|
82
82
|
...typeof values.port === "string" ? { port: values.port } : {}
|
|
83
83
|
};
|
|
84
84
|
Object.assign(process.env, buildAgentEnv(opts));
|
|
85
|
-
await import("./launcher-
|
|
85
|
+
await import("./launcher-PJJ7PTWL.js");
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
// src/commands/setup.ts
|
|
@@ -14773,7 +14773,7 @@ function date4(params) {
|
|
|
14773
14773
|
// ../../node_modules/zod/v4/classic/external.js
|
|
14774
14774
|
config(en_default());
|
|
14775
14775
|
|
|
14776
|
-
// ../types/dist/sleep-
|
|
14776
|
+
// ../types/dist/sleep-yKL5gfrH.mjs
|
|
14777
14777
|
var AUDIO_CHUNK_FORMATS = [
|
|
14778
14778
|
"f32le",
|
|
14779
14779
|
"pcmu",
|
|
@@ -14968,6 +14968,7 @@ var WELL_KNOWN_TABS = [
|
|
|
14968
14968
|
];
|
|
14969
14969
|
var WELL_KNOWN_TAB_MAP = Object.fromEntries(WELL_KNOWN_TABS.map((t) => [t.id, t]));
|
|
14970
14970
|
var SECRET_RETRY_MAX_MS = 5 * 6e4;
|
|
14971
|
+
var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
|
|
14971
14972
|
var PEER_BYTES_CHUNK_BYTES = 256 * 1024;
|
|
14972
14973
|
var PeerBytesTicketSchema = external_exports.object({
|
|
14973
14974
|
/** `http://127.0.0.1:<port>/<token>`. One `GET` takes it. */
|
|
@@ -18452,6 +18453,204 @@ var ConvertResultSchema = external_exports.object({
|
|
|
18452
18453
|
entry: ModelCatalogEntrySchema,
|
|
18453
18454
|
artifacts: external_exports.array(ConvertArtifactSchema).readonly()
|
|
18454
18455
|
});
|
|
18456
|
+
var MethodAccessSchema = external_exports.enum([
|
|
18457
|
+
"view",
|
|
18458
|
+
"create",
|
|
18459
|
+
"delete"
|
|
18460
|
+
]);
|
|
18461
|
+
var AllowedProviderSchema = external_exports.union([external_exports.literal("*"), external_exports.array(external_exports.string())]);
|
|
18462
|
+
var AllowedDevicesSchema = external_exports.record(external_exports.string(), external_exports.union([external_exports.literal("*"), external_exports.array(external_exports.string())]));
|
|
18463
|
+
var CapScopeSchema = external_exports.enum(["device", "system"]);
|
|
18464
|
+
var DeviceSelectorSchema = external_exports.discriminatedUnion("kind", [
|
|
18465
|
+
external_exports.object({ kind: external_exports.literal("all") }),
|
|
18466
|
+
external_exports.object({
|
|
18467
|
+
kind: external_exports.literal("ids"),
|
|
18468
|
+
ids: external_exports.array(external_exports.number().int()).min(1)
|
|
18469
|
+
}),
|
|
18470
|
+
external_exports.object({
|
|
18471
|
+
kind: external_exports.literal("types"),
|
|
18472
|
+
types: external_exports.array(external_exports.enum(DeviceType)).min(1)
|
|
18473
|
+
}),
|
|
18474
|
+
external_exports.object({
|
|
18475
|
+
kind: external_exports.literal("locations"),
|
|
18476
|
+
locations: external_exports.array(external_exports.string().min(1)).min(1)
|
|
18477
|
+
})
|
|
18478
|
+
]);
|
|
18479
|
+
var DeviceTokenScopeSchema = external_exports.object({
|
|
18480
|
+
type: external_exports.literal("device"),
|
|
18481
|
+
/** The device SET this grant covers — resolved against the live fleet. */
|
|
18482
|
+
selector: DeviceSelectorSchema,
|
|
18483
|
+
access: external_exports.array(MethodAccessSchema).min(1),
|
|
18484
|
+
/**
|
|
18485
|
+
* Whether a grant on a PARENT device transparently covers its accessory
|
|
18486
|
+
* CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
|
|
18487
|
+
* Direction is parent → children ONLY.
|
|
18488
|
+
*
|
|
18489
|
+
* Absent → the matcher DERIVES it from the access flavour: `view`
|
|
18490
|
+
* inherits (a camera viewer sees the camera's accessories), `create` /
|
|
18491
|
+
* `delete` do NOT (actuating/removing a child is an explicit act the
|
|
18492
|
+
* operator must grant on the child, not inherit from the parent). Set it
|
|
18493
|
+
* explicitly to override that default per grant.
|
|
18494
|
+
*/
|
|
18495
|
+
includeLinked: external_exports.boolean().optional()
|
|
18496
|
+
});
|
|
18497
|
+
function migrateLegacyTokenScope(raw) {
|
|
18498
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
|
|
18499
|
+
if (Reflect.get(raw, "type") !== "device") return raw;
|
|
18500
|
+
if (Reflect.get(raw, "selector") !== void 0) return raw;
|
|
18501
|
+
const targets = Reflect.get(raw, "targets");
|
|
18502
|
+
if (!Array.isArray(targets)) return raw;
|
|
18503
|
+
return {
|
|
18504
|
+
type: "device",
|
|
18505
|
+
selector: {
|
|
18506
|
+
kind: "ids",
|
|
18507
|
+
ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
|
|
18508
|
+
},
|
|
18509
|
+
access: Reflect.get(raw, "access")
|
|
18510
|
+
};
|
|
18511
|
+
}
|
|
18512
|
+
var TokenScopeSchema = external_exports.preprocess(migrateLegacyTokenScope, external_exports.discriminatedUnion("type", [
|
|
18513
|
+
external_exports.object({
|
|
18514
|
+
type: external_exports.literal("category"),
|
|
18515
|
+
target: CapScopeSchema,
|
|
18516
|
+
access: external_exports.array(MethodAccessSchema).min(1)
|
|
18517
|
+
}),
|
|
18518
|
+
external_exports.object({
|
|
18519
|
+
type: external_exports.literal("capability"),
|
|
18520
|
+
target: external_exports.string(),
|
|
18521
|
+
access: external_exports.array(MethodAccessSchema).min(1)
|
|
18522
|
+
}),
|
|
18523
|
+
external_exports.object({
|
|
18524
|
+
type: external_exports.literal("addon"),
|
|
18525
|
+
target: external_exports.string(),
|
|
18526
|
+
access: external_exports.array(MethodAccessSchema).min(1)
|
|
18527
|
+
}),
|
|
18528
|
+
DeviceTokenScopeSchema
|
|
18529
|
+
]));
|
|
18530
|
+
var UserRecordSchema = external_exports.object({
|
|
18531
|
+
id: external_exports.string(),
|
|
18532
|
+
username: external_exports.string(),
|
|
18533
|
+
passwordHash: external_exports.string(),
|
|
18534
|
+
/**
|
|
18535
|
+
* Admin bypass. When true, the middleware skips the scope-access
|
|
18536
|
+
* check entirely. There is no other axis of privilege; the legacy
|
|
18537
|
+
* role enum collapsed onto this boolean in v2.
|
|
18538
|
+
*/
|
|
18539
|
+
isAdmin: external_exports.boolean().default(false),
|
|
18540
|
+
allowedProviders: AllowedProviderSchema,
|
|
18541
|
+
allowedDevices: AllowedDevicesSchema,
|
|
18542
|
+
/**
|
|
18543
|
+
* Scopes granted to this user. Admins bypass; their `scopes` is
|
|
18544
|
+
* ignored. Non-admins without scopes are locked out of every
|
|
18545
|
+
* protected call.
|
|
18546
|
+
*/
|
|
18547
|
+
scopes: external_exports.array(TokenScopeSchema).default([]),
|
|
18548
|
+
createdAt: external_exports.number(),
|
|
18549
|
+
updatedAt: external_exports.number()
|
|
18550
|
+
});
|
|
18551
|
+
var ApiKeyRecordSchema = external_exports.object({
|
|
18552
|
+
id: external_exports.string(),
|
|
18553
|
+
label: external_exports.string(),
|
|
18554
|
+
isAdmin: external_exports.boolean().default(false),
|
|
18555
|
+
allowedProviders: AllowedProviderSchema,
|
|
18556
|
+
allowedDevices: AllowedDevicesSchema,
|
|
18557
|
+
tokenHash: external_exports.string(),
|
|
18558
|
+
tokenPrefix: external_exports.string(),
|
|
18559
|
+
createdAt: external_exports.number(),
|
|
18560
|
+
lastUsedAt: external_exports.number().optional()
|
|
18561
|
+
});
|
|
18562
|
+
var ScopedTokenSchema = external_exports.object({
|
|
18563
|
+
id: external_exports.string(),
|
|
18564
|
+
userId: external_exports.string(),
|
|
18565
|
+
name: external_exports.string(),
|
|
18566
|
+
tokenHash: external_exports.string(),
|
|
18567
|
+
tokenPrefix: external_exports.string(),
|
|
18568
|
+
scopes: external_exports.array(TokenScopeSchema),
|
|
18569
|
+
expiresAt: external_exports.number().nullish(),
|
|
18570
|
+
lastUsedAt: external_exports.number().nullish(),
|
|
18571
|
+
createdAt: external_exports.number()
|
|
18572
|
+
});
|
|
18573
|
+
var ShareViewGrantSchema = external_exports.object({
|
|
18574
|
+
kind: external_exports.enum(SHARE_VIEW_KINDS),
|
|
18575
|
+
deviceIds: external_exports.array(external_exports.number().int().nonnegative()).min(1).max(64),
|
|
18576
|
+
/** Talk-back, opt-in at mint time; absent means off. */
|
|
18577
|
+
talk: external_exports.boolean().optional()
|
|
18578
|
+
});
|
|
18579
|
+
var ShareViewScopeSchema = external_exports.object({
|
|
18580
|
+
type: external_exports.literal("share-view"),
|
|
18581
|
+
grant: ShareViewGrantSchema
|
|
18582
|
+
});
|
|
18583
|
+
var AddonRoutesScopeSchema = external_exports.object({
|
|
18584
|
+
type: external_exports.literal("addon-routes"),
|
|
18585
|
+
access: external_exports.array(MethodAccessSchema).min(1)
|
|
18586
|
+
});
|
|
18587
|
+
var PreferencesSelfScopeSchema = external_exports.object({ type: external_exports.literal("preferences-self") });
|
|
18588
|
+
var CredentialScopeSchema = external_exports.union([
|
|
18589
|
+
external_exports.literal("*"),
|
|
18590
|
+
ShareViewScopeSchema,
|
|
18591
|
+
AddonRoutesScopeSchema,
|
|
18592
|
+
PreferencesSelfScopeSchema,
|
|
18593
|
+
TokenScopeSchema
|
|
18594
|
+
]);
|
|
18595
|
+
var CREDENTIAL_TOKEN_KIND = "credential";
|
|
18596
|
+
var CredentialTokenClaimsSchema = external_exports.object({
|
|
18597
|
+
kind: external_exports.literal(CREDENTIAL_TOKEN_KIND),
|
|
18598
|
+
sub: external_exports.string().min(1),
|
|
18599
|
+
jti: external_exports.string().min(16),
|
|
18600
|
+
scopes: external_exports.array(CredentialScopeSchema).min(1)
|
|
18601
|
+
});
|
|
18602
|
+
var PREFERENCES_NAMESPACE_PATTERN = /^[a-z][a-z0-9.-]{0,63}$/;
|
|
18603
|
+
var PREFERENCES_MAX_VALUE_BYTES = 256 * 1024;
|
|
18604
|
+
var PreferenceNamespaceSchema = external_exports.string().regex(PREFERENCES_NAMESPACE_PATTERN);
|
|
18605
|
+
var PreferenceValueSchema = external_exports.record(external_exports.string(), external_exports.unknown());
|
|
18606
|
+
var PreferenceDeviceIdSchema = external_exports.string().min(1).max(64);
|
|
18607
|
+
var PreferenceRowSchema = external_exports.object({
|
|
18608
|
+
namespace: PreferenceNamespaceSchema,
|
|
18609
|
+
value: PreferenceValueSchema,
|
|
18610
|
+
/** Starts at 1, +1 on every write of this namespace. A delete ends the row and its count. */
|
|
18611
|
+
revision: external_exports.number().int().positive(),
|
|
18612
|
+
updatedAt: external_exports.number().int(),
|
|
18613
|
+
/** The client id the last writer sent; `null` when it sent none. */
|
|
18614
|
+
updatedByDevice: PreferenceDeviceIdSchema.nullable()
|
|
18615
|
+
});
|
|
18616
|
+
var PreferencesGetInputSchema = external_exports.object({
|
|
18617
|
+
/** Absent: every namespace the caller holds. */
|
|
18618
|
+
namespaces: external_exports.array(PreferenceNamespaceSchema).max(32).optional()
|
|
18619
|
+
});
|
|
18620
|
+
var PreferencesGetOutputSchema = external_exports.object({ rows: external_exports.array(PreferenceRowSchema) });
|
|
18621
|
+
var PreferencesPutInputSchema = external_exports.object({
|
|
18622
|
+
namespace: PreferenceNamespaceSchema,
|
|
18623
|
+
value: PreferenceValueSchema,
|
|
18624
|
+
/**
|
|
18625
|
+
* The revision the edit was based on. Absent: last write wins. `0`: the
|
|
18626
|
+
* namespace must not exist yet. Any other value that is not the current
|
|
18627
|
+
* revision answers `conflict` and writes nothing.
|
|
18628
|
+
*/
|
|
18629
|
+
baseRevision: external_exports.number().int().nonnegative().optional(),
|
|
18630
|
+
deviceId: PreferenceDeviceIdSchema.optional()
|
|
18631
|
+
});
|
|
18632
|
+
var PreferencesPutOutputSchema = external_exports.discriminatedUnion("status", [external_exports.object({
|
|
18633
|
+
status: external_exports.literal("saved"),
|
|
18634
|
+
row: PreferenceRowSchema
|
|
18635
|
+
}), external_exports.object({
|
|
18636
|
+
status: external_exports.literal("conflict"),
|
|
18637
|
+
current: PreferenceRowSchema.nullable()
|
|
18638
|
+
})]);
|
|
18639
|
+
var PreferencesDeleteInputSchema = external_exports.object({ namespace: PreferenceNamespaceSchema });
|
|
18640
|
+
var PreferencesDeleteOutputSchema = external_exports.object({
|
|
18641
|
+
/** `false` when the namespace did not exist. */
|
|
18642
|
+
deleted: external_exports.boolean()
|
|
18643
|
+
});
|
|
18644
|
+
var PreferencesChangedSinceInputSchema = external_exports.object({
|
|
18645
|
+
/** The revision the client holds per namespace; a namespace it does not list is new to it. */
|
|
18646
|
+
revisionByNamespace: external_exports.record(PreferenceNamespaceSchema, external_exports.number().int().nonnegative()).refine((map2) => Object.keys(map2).length <= 32, { message: `at most 32 namespaces` })
|
|
18647
|
+
});
|
|
18648
|
+
var PreferencesChangedSinceOutputSchema = external_exports.object({
|
|
18649
|
+
/** Every row whose revision differs from the client's, and every row it did not list. */
|
|
18650
|
+
rows: external_exports.array(PreferenceRowSchema),
|
|
18651
|
+
/** Namespaces the client listed that no longer exist. */
|
|
18652
|
+
deleted: external_exports.array(PreferenceNamespaceSchema)
|
|
18653
|
+
});
|
|
18455
18654
|
var AppFlowPurposeSchema = external_exports.enum(["new-session", "step-up"]);
|
|
18456
18655
|
var AppPageLangSchema = external_exports.enum(["en", "it"]);
|
|
18457
18656
|
var APP_FLOW_REFUSAL_MESSAGES = {
|
|
@@ -46431,27 +46630,30 @@ var llmRuntimeCapability = {
|
|
|
46431
46630
|
})
|
|
46432
46631
|
}
|
|
46433
46632
|
};
|
|
46434
|
-
var
|
|
46435
|
-
|
|
46436
|
-
|
|
46437
|
-
|
|
46438
|
-
|
|
46439
|
-
|
|
46440
|
-
|
|
46441
|
-
|
|
46633
|
+
var LLM_PROFILE_KIND_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
46634
|
+
var LlmProfileKindSchema = external_exports.string().regex(LLM_PROFILE_KIND_PATTERN, "a kind id is lower-case letters, digits and dashes");
|
|
46635
|
+
var LlmModelFeaturesSchema = external_exports.object({
|
|
46636
|
+
vision: external_exports.boolean(),
|
|
46637
|
+
tools: external_exports.boolean(),
|
|
46638
|
+
streaming: external_exports.boolean()
|
|
46639
|
+
});
|
|
46640
|
+
var LlmModelInfoSchema = external_exports.object({
|
|
46641
|
+
id: external_exports.string(),
|
|
46642
|
+
label: external_exports.string().optional(),
|
|
46643
|
+
contextLength: external_exports.number().int().positive().optional(),
|
|
46644
|
+
features: LlmModelFeaturesSchema.partial().optional()
|
|
46645
|
+
});
|
|
46646
|
+
var LlmProviderConfigSchema = external_exports.record(external_exports.string(), external_exports.unknown());
|
|
46442
46647
|
var LlmProfileSchema = external_exports.object({
|
|
46443
46648
|
id: external_exports.string(),
|
|
46444
46649
|
name: external_exports.string(),
|
|
46650
|
+
/** The provider-declared kind (`LlmProfileKindDescriptor.kind`). */
|
|
46445
46651
|
kind: LlmProfileKindSchema,
|
|
46446
46652
|
/** Stamped by the provider — keeps the fanned catalog routable. */
|
|
46447
46653
|
addonId: external_exports.string(),
|
|
46448
46654
|
enabled: external_exports.boolean(),
|
|
46449
46655
|
/** Vendor model id, or the managed runtime's loaded model. */
|
|
46450
46656
|
model: external_exports.string(),
|
|
46451
|
-
/** Required for openai-compatible; override for cloud kinds. */
|
|
46452
|
-
baseUrl: external_exports.string().optional(),
|
|
46453
|
-
/** ConfigUISchema type:'password' — never round-trips (spec §5). */
|
|
46454
|
-
apiKey: external_exports.string().optional(),
|
|
46455
46657
|
/** Vision on/off. A vision call against a `false` profile is REFUSED, never
|
|
46456
46658
|
* degraded to text — that shipped once and produced a confident answer to a
|
|
46457
46659
|
* question about a picture nobody sent. */
|
|
@@ -46459,15 +46661,11 @@ var LlmProfileSchema = external_exports.object({
|
|
|
46459
46661
|
temperature: external_exports.number().min(0).max(2).optional(),
|
|
46460
46662
|
/** Nucleus sampling. Every wire we speak has it. */
|
|
46461
46663
|
topP: external_exports.number().min(0).max(1).optional(),
|
|
46462
|
-
/** Top-k sampling. Carried only by the wires that have it —
|
|
46463
|
-
*
|
|
46464
|
-
* `top_p` and no `top_k`). The profile editor hides the field wherever it
|
|
46465
|
-
* would change nothing; `KINDS_WITH_TOP_K` is the single owner of that list. */
|
|
46664
|
+
/** Top-k sampling. Carried only by the wires that have it — a kind offers the
|
|
46665
|
+
* field in its editor only when its descriptor lists it in `profileFields`. */
|
|
46466
46666
|
topK: external_exports.number().int().positive().optional(),
|
|
46467
46667
|
maxTokens: external_exports.number().int().positive().optional(),
|
|
46468
|
-
/** Prompt context window. Advisory for cloud kinds (they enforce their own)
|
|
46469
|
-
* for `managed-local` it is the llama.cpp `--ctx-size` the runtime starts
|
|
46470
|
-
* the model with, so it is the one field that changes a PROCESS. */
|
|
46668
|
+
/** Prompt context window. Advisory for cloud kinds (they enforce their own). */
|
|
46471
46669
|
contextLength: external_exports.number().int().positive().optional(),
|
|
46472
46670
|
/** Default system prompt. A caller's `system` REPLACES it (never appends —
|
|
46473
46671
|
* two system prompts fighting is worse than either alone). */
|
|
@@ -46493,26 +46691,76 @@ var LlmProfileSchema = external_exports.object({
|
|
|
46493
46691
|
* library; the REGISTRY of callable tools is ours and is empty in v1, so a
|
|
46494
46692
|
* `true` here buys the wiring, not behaviour, until tools are registered. */
|
|
46495
46693
|
toolsEnabled: external_exports.boolean().default(false),
|
|
46496
|
-
|
|
46497
|
-
|
|
46498
|
-
|
|
46499
|
-
|
|
46500
|
-
|
|
46501
|
-
|
|
46502
|
-
|
|
46503
|
-
|
|
46504
|
-
|
|
46505
|
-
|
|
46694
|
+
/** Everything the kind's provider owns (endpoint, key, node, runtime…). */
|
|
46695
|
+
providerConfig: LlmProviderConfigSchema.default({})
|
|
46696
|
+
});
|
|
46697
|
+
var LlmProfileFieldSchema = external_exports.enum([
|
|
46698
|
+
"temperature",
|
|
46699
|
+
"topP",
|
|
46700
|
+
"topK",
|
|
46701
|
+
"maxTokens",
|
|
46702
|
+
"contextLength",
|
|
46703
|
+
"systemPrompt",
|
|
46704
|
+
"timeoutMs",
|
|
46705
|
+
"connectTimeoutMs",
|
|
46706
|
+
"firstTokenTimeoutMs",
|
|
46707
|
+
"idleTimeoutMs",
|
|
46708
|
+
"retry",
|
|
46709
|
+
"toolsEnabled"
|
|
46710
|
+
]);
|
|
46711
|
+
var LlmProviderWidgetSchema = external_exports.object({
|
|
46712
|
+
id: external_exports.string(),
|
|
46713
|
+
placement: external_exports.enum(["connection", "model"]),
|
|
46714
|
+
/** `providerConfig` keys this widget must fill before the profile can be saved. */
|
|
46715
|
+
requires: external_exports.array(external_exports.string()).optional()
|
|
46506
46716
|
});
|
|
46507
46717
|
var ConfigSchemaPassthrough$3 = external_exports.unknown();
|
|
46508
46718
|
var LlmProfileKindDescriptorSchema = external_exports.object({
|
|
46509
46719
|
kind: LlmProfileKindSchema,
|
|
46510
46720
|
label: external_exports.string(),
|
|
46721
|
+
/** A generic icon name (`cloud`, `plug`, `cpu`) — never a glyph or a logo. */
|
|
46511
46722
|
icon: external_exports.string(),
|
|
46512
46723
|
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
46513
46724
|
addonId: external_exports.string(),
|
|
46514
|
-
|
|
46725
|
+
/** The provider's own fields (`providerConfig`); `password` fields are keychain-held. */
|
|
46726
|
+
connectionSchema: ConfigSchemaPassthrough$3,
|
|
46727
|
+
/** Provider fields that belong under "Advanced" (extra headers, runtime tuning). */
|
|
46728
|
+
advancedSchema: ConfigSchemaPassthrough$3.optional(),
|
|
46729
|
+
/** The kind's defaults; a model from `listModels` may override any of them. */
|
|
46730
|
+
features: LlmModelFeaturesSchema,
|
|
46731
|
+
/** `false` = the provider stamps `supportsVision` itself (from what a node reports). */
|
|
46732
|
+
visionEditable: external_exports.boolean(),
|
|
46733
|
+
/** Where the model list comes from: `listModels`, `staticModels`, or nowhere. */
|
|
46734
|
+
modelCatalog: external_exports.enum([
|
|
46735
|
+
"fetch",
|
|
46736
|
+
"static",
|
|
46737
|
+
"none"
|
|
46738
|
+
]),
|
|
46739
|
+
staticModels: external_exports.array(LlmModelInfoSchema).optional(),
|
|
46740
|
+
/** The common fields that mean something on this kind's wire. */
|
|
46741
|
+
profileFields: external_exports.array(LlmProfileFieldSchema),
|
|
46742
|
+
providerWidgets: external_exports.array(LlmProviderWidgetSchema).optional()
|
|
46743
|
+
});
|
|
46744
|
+
var LlmListModelsInputSchema = external_exports.object({
|
|
46745
|
+
addonId: external_exports.string(),
|
|
46746
|
+
kind: LlmProfileKindSchema,
|
|
46747
|
+
profileId: external_exports.string().optional(),
|
|
46748
|
+
connection: LlmProviderConfigSchema.optional()
|
|
46515
46749
|
});
|
|
46750
|
+
var LlmListModelsErrorCodeSchema = external_exports.enum([
|
|
46751
|
+
"auth",
|
|
46752
|
+
"network",
|
|
46753
|
+
"unsupported",
|
|
46754
|
+
"invalid"
|
|
46755
|
+
]);
|
|
46756
|
+
var LlmListModelsResultSchema = external_exports.discriminatedUnion("ok", [external_exports.object({
|
|
46757
|
+
ok: external_exports.literal(true),
|
|
46758
|
+
models: external_exports.array(LlmModelInfoSchema)
|
|
46759
|
+
}), external_exports.object({
|
|
46760
|
+
ok: external_exports.literal(false),
|
|
46761
|
+
code: LlmListModelsErrorCodeSchema,
|
|
46762
|
+
message: external_exports.string()
|
|
46763
|
+
})]);
|
|
46516
46764
|
var LlmDefaultSelectorSchema = external_exports.union([external_exports.object({ consumer: external_exports.string() }), external_exports.object({ purpose: external_exports.enum(["text", "vision"]) })]);
|
|
46517
46765
|
var LlmDefaultSchema = external_exports.object({
|
|
46518
46766
|
selector: LlmDefaultSelectorSchema,
|
|
@@ -46632,8 +46880,17 @@ var llmCapability = {
|
|
|
46632
46880
|
auth: "admin",
|
|
46633
46881
|
timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
|
|
46634
46882
|
}),
|
|
46635
|
-
/**
|
|
46636
|
-
|
|
46883
|
+
/**
|
|
46884
|
+
* The models a kind offers, for a SAVED profile or an unsaved draft
|
|
46885
|
+
* (`connection`). A mutation, not a query: a draft may carry a key, and a
|
|
46886
|
+
* query's input travels in the URL. Admin: it dials whatever endpoint the
|
|
46887
|
+
* draft names and may resolve a stored key to do it. The answer never
|
|
46888
|
+
* carries a secret — failures are a typed result, never a throw.
|
|
46889
|
+
*/
|
|
46890
|
+
listModels: method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
|
|
46891
|
+
kind: "mutation",
|
|
46892
|
+
auth: "admin"
|
|
46893
|
+
}),
|
|
46637
46894
|
getDefaults: method(external_exports.object({}), external_exports.array(LlmDefaultSchema)),
|
|
46638
46895
|
setDefault: method(external_exports.object({
|
|
46639
46896
|
selector: LlmDefaultSelectorSchema,
|
|
@@ -50264,123 +50521,6 @@ var notificationRulesCapability = {
|
|
|
50264
50521
|
getAlarmSensors: method(NcAlarmSensorsInputSchema, NcAlarmSensorsSchema, { auth: "admin" })
|
|
50265
50522
|
}
|
|
50266
50523
|
};
|
|
50267
|
-
var MethodAccessSchema = external_exports.enum([
|
|
50268
|
-
"view",
|
|
50269
|
-
"create",
|
|
50270
|
-
"delete"
|
|
50271
|
-
]);
|
|
50272
|
-
var AllowedProviderSchema = external_exports.union([external_exports.literal("*"), external_exports.array(external_exports.string())]);
|
|
50273
|
-
var AllowedDevicesSchema = external_exports.record(external_exports.string(), external_exports.union([external_exports.literal("*"), external_exports.array(external_exports.string())]));
|
|
50274
|
-
var CapScopeSchema = external_exports.enum(["device", "system"]);
|
|
50275
|
-
var DeviceSelectorSchema = external_exports.discriminatedUnion("kind", [
|
|
50276
|
-
external_exports.object({ kind: external_exports.literal("all") }),
|
|
50277
|
-
external_exports.object({
|
|
50278
|
-
kind: external_exports.literal("ids"),
|
|
50279
|
-
ids: external_exports.array(external_exports.number().int()).min(1)
|
|
50280
|
-
}),
|
|
50281
|
-
external_exports.object({
|
|
50282
|
-
kind: external_exports.literal("types"),
|
|
50283
|
-
types: external_exports.array(external_exports.enum(DeviceType)).min(1)
|
|
50284
|
-
}),
|
|
50285
|
-
external_exports.object({
|
|
50286
|
-
kind: external_exports.literal("locations"),
|
|
50287
|
-
locations: external_exports.array(external_exports.string().min(1)).min(1)
|
|
50288
|
-
})
|
|
50289
|
-
]);
|
|
50290
|
-
var DeviceTokenScopeSchema = external_exports.object({
|
|
50291
|
-
type: external_exports.literal("device"),
|
|
50292
|
-
/** The device SET this grant covers — resolved against the live fleet. */
|
|
50293
|
-
selector: DeviceSelectorSchema,
|
|
50294
|
-
access: external_exports.array(MethodAccessSchema).min(1),
|
|
50295
|
-
/**
|
|
50296
|
-
* Whether a grant on a PARENT device transparently covers its accessory
|
|
50297
|
-
* CHILDREN (siren / floodlight / PIR) via the persisted-parentage walk.
|
|
50298
|
-
* Direction is parent → children ONLY.
|
|
50299
|
-
*
|
|
50300
|
-
* Absent → the matcher DERIVES it from the access flavour: `view`
|
|
50301
|
-
* inherits (a camera viewer sees the camera's accessories), `create` /
|
|
50302
|
-
* `delete` do NOT (actuating/removing a child is an explicit act the
|
|
50303
|
-
* operator must grant on the child, not inherit from the parent). Set it
|
|
50304
|
-
* explicitly to override that default per grant.
|
|
50305
|
-
*/
|
|
50306
|
-
includeLinked: external_exports.boolean().optional()
|
|
50307
|
-
});
|
|
50308
|
-
function migrateLegacyTokenScope(raw) {
|
|
50309
|
-
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
|
|
50310
|
-
if (Reflect.get(raw, "type") !== "device") return raw;
|
|
50311
|
-
if (Reflect.get(raw, "selector") !== void 0) return raw;
|
|
50312
|
-
const targets = Reflect.get(raw, "targets");
|
|
50313
|
-
if (!Array.isArray(targets)) return raw;
|
|
50314
|
-
return {
|
|
50315
|
-
type: "device",
|
|
50316
|
-
selector: {
|
|
50317
|
-
kind: "ids",
|
|
50318
|
-
ids: targets.map((t) => typeof t === "string" ? Number(t) : t).filter((n) => typeof n === "number" && Number.isInteger(n))
|
|
50319
|
-
},
|
|
50320
|
-
access: Reflect.get(raw, "access")
|
|
50321
|
-
};
|
|
50322
|
-
}
|
|
50323
|
-
var TokenScopeSchema = external_exports.preprocess(migrateLegacyTokenScope, external_exports.discriminatedUnion("type", [
|
|
50324
|
-
external_exports.object({
|
|
50325
|
-
type: external_exports.literal("category"),
|
|
50326
|
-
target: CapScopeSchema,
|
|
50327
|
-
access: external_exports.array(MethodAccessSchema).min(1)
|
|
50328
|
-
}),
|
|
50329
|
-
external_exports.object({
|
|
50330
|
-
type: external_exports.literal("capability"),
|
|
50331
|
-
target: external_exports.string(),
|
|
50332
|
-
access: external_exports.array(MethodAccessSchema).min(1)
|
|
50333
|
-
}),
|
|
50334
|
-
external_exports.object({
|
|
50335
|
-
type: external_exports.literal("addon"),
|
|
50336
|
-
target: external_exports.string(),
|
|
50337
|
-
access: external_exports.array(MethodAccessSchema).min(1)
|
|
50338
|
-
}),
|
|
50339
|
-
DeviceTokenScopeSchema
|
|
50340
|
-
]));
|
|
50341
|
-
var UserRecordSchema = external_exports.object({
|
|
50342
|
-
id: external_exports.string(),
|
|
50343
|
-
username: external_exports.string(),
|
|
50344
|
-
passwordHash: external_exports.string(),
|
|
50345
|
-
/**
|
|
50346
|
-
* Admin bypass. When true, the middleware skips the scope-access
|
|
50347
|
-
* check entirely. There is no other axis of privilege; the legacy
|
|
50348
|
-
* role enum collapsed onto this boolean in v2.
|
|
50349
|
-
*/
|
|
50350
|
-
isAdmin: external_exports.boolean().default(false),
|
|
50351
|
-
allowedProviders: AllowedProviderSchema,
|
|
50352
|
-
allowedDevices: AllowedDevicesSchema,
|
|
50353
|
-
/**
|
|
50354
|
-
* Scopes granted to this user. Admins bypass; their `scopes` is
|
|
50355
|
-
* ignored. Non-admins without scopes are locked out of every
|
|
50356
|
-
* protected call.
|
|
50357
|
-
*/
|
|
50358
|
-
scopes: external_exports.array(TokenScopeSchema).default([]),
|
|
50359
|
-
createdAt: external_exports.number(),
|
|
50360
|
-
updatedAt: external_exports.number()
|
|
50361
|
-
});
|
|
50362
|
-
var ApiKeyRecordSchema = external_exports.object({
|
|
50363
|
-
id: external_exports.string(),
|
|
50364
|
-
label: external_exports.string(),
|
|
50365
|
-
isAdmin: external_exports.boolean().default(false),
|
|
50366
|
-
allowedProviders: AllowedProviderSchema,
|
|
50367
|
-
allowedDevices: AllowedDevicesSchema,
|
|
50368
|
-
tokenHash: external_exports.string(),
|
|
50369
|
-
tokenPrefix: external_exports.string(),
|
|
50370
|
-
createdAt: external_exports.number(),
|
|
50371
|
-
lastUsedAt: external_exports.number().optional()
|
|
50372
|
-
});
|
|
50373
|
-
var ScopedTokenSchema = external_exports.object({
|
|
50374
|
-
id: external_exports.string(),
|
|
50375
|
-
userId: external_exports.string(),
|
|
50376
|
-
name: external_exports.string(),
|
|
50377
|
-
tokenHash: external_exports.string(),
|
|
50378
|
-
tokenPrefix: external_exports.string(),
|
|
50379
|
-
scopes: external_exports.array(TokenScopeSchema),
|
|
50380
|
-
expiresAt: external_exports.number().nullish(),
|
|
50381
|
-
lastUsedAt: external_exports.number().nullish(),
|
|
50382
|
-
createdAt: external_exports.number()
|
|
50383
|
-
});
|
|
50384
50524
|
var OauthIntegrationDescriptorSchema = external_exports.object({
|
|
50385
50525
|
/** Stable id used as the `integration=` query param, e.g. 'export-alexa'. */
|
|
50386
50526
|
integrationId: external_exports.string(),
|
|
@@ -70016,26 +70156,6 @@ var ApiKeySummarySchema = external_exports.object({
|
|
|
70016
70156
|
createdAt: external_exports.number(),
|
|
70017
70157
|
lastUsedAt: external_exports.number().optional()
|
|
70018
70158
|
});
|
|
70019
|
-
var ScopedTokenSummarySchema = external_exports.object({
|
|
70020
|
-
id: external_exports.string(),
|
|
70021
|
-
userId: external_exports.string(),
|
|
70022
|
-
name: external_exports.string(),
|
|
70023
|
-
tokenPrefix: external_exports.string(),
|
|
70024
|
-
scopes: external_exports.array(TokenScopeSchema),
|
|
70025
|
-
expiresAt: external_exports.number().nullish(),
|
|
70026
|
-
lastUsedAt: external_exports.number().nullish(),
|
|
70027
|
-
createdAt: external_exports.number()
|
|
70028
|
-
});
|
|
70029
|
-
var CreateScopedTokenInputSchema = external_exports.object({
|
|
70030
|
-
userId: external_exports.string(),
|
|
70031
|
-
name: external_exports.string(),
|
|
70032
|
-
scopes: external_exports.array(TokenScopeSchema),
|
|
70033
|
-
expiresAt: external_exports.number().optional()
|
|
70034
|
-
});
|
|
70035
|
-
var CreateScopedTokenResultSchema = external_exports.object({
|
|
70036
|
-
token: external_exports.string(),
|
|
70037
|
-
record: ScopedTokenSummarySchema
|
|
70038
|
-
});
|
|
70039
70159
|
var OauthSessionSummarySchema = external_exports.object({
|
|
70040
70160
|
id: external_exports.string(),
|
|
70041
70161
|
userId: external_exports.string(),
|
|
@@ -70122,18 +70242,6 @@ var userManagementCapability = {
|
|
|
70122
70242
|
auth: "admin",
|
|
70123
70243
|
access: "delete"
|
|
70124
70244
|
}),
|
|
70125
|
-
createScopedToken: method(CreateScopedTokenInputSchema, CreateScopedTokenResultSchema, {
|
|
70126
|
-
kind: "mutation",
|
|
70127
|
-
auth: "admin",
|
|
70128
|
-
access: "create"
|
|
70129
|
-
}),
|
|
70130
|
-
revokeScopedToken: method(external_exports.object({ id: external_exports.string() }), external_exports.object({ success: external_exports.literal(true) }), {
|
|
70131
|
-
kind: "mutation",
|
|
70132
|
-
auth: "admin",
|
|
70133
|
-
access: "delete"
|
|
70134
|
-
}),
|
|
70135
|
-
validateScopedToken: method(external_exports.object({ token: external_exports.string() }), ScopedTokenSummarySchema.nullable(), { access: "view" }),
|
|
70136
|
-
listScopedTokens: method(external_exports.object({ userId: external_exports.string() }), external_exports.array(ScopedTokenSummarySchema), { auth: "admin" }),
|
|
70137
70245
|
setupTotp: method(external_exports.object({ userId: external_exports.string() }), TotpSetupResultSchema, {
|
|
70138
70246
|
kind: "mutation",
|
|
70139
70247
|
auth: "admin",
|
|
@@ -74811,7 +74919,7 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
74811
74919
|
capName: "llm",
|
|
74812
74920
|
capScope: "system",
|
|
74813
74921
|
addonId: null,
|
|
74814
|
-
access: "
|
|
74922
|
+
access: "create"
|
|
74815
74923
|
},
|
|
74816
74924
|
"llm.listNodeModels": {
|
|
74817
74925
|
capName: "llm",
|
|
@@ -79475,12 +79583,6 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
79475
79583
|
addonId: null,
|
|
79476
79584
|
access: "create"
|
|
79477
79585
|
},
|
|
79478
|
-
"userManagement.createScopedToken": {
|
|
79479
|
-
capName: "user-management",
|
|
79480
|
-
capScope: "system",
|
|
79481
|
-
addonId: null,
|
|
79482
|
-
access: "create"
|
|
79483
|
-
},
|
|
79484
79586
|
"userManagement.createUser": {
|
|
79485
79587
|
capName: "user-management",
|
|
79486
79588
|
capScope: "system",
|
|
@@ -79529,12 +79631,6 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
79529
79631
|
addonId: null,
|
|
79530
79632
|
access: "view"
|
|
79531
79633
|
},
|
|
79532
|
-
"userManagement.listScopedTokens": {
|
|
79533
|
-
capName: "user-management",
|
|
79534
|
-
capScope: "system",
|
|
79535
|
-
addonId: null,
|
|
79536
|
-
access: "view"
|
|
79537
|
-
},
|
|
79538
79634
|
"userManagement.listUsers": {
|
|
79539
79635
|
capName: "user-management",
|
|
79540
79636
|
capScope: "system",
|
|
@@ -79589,12 +79685,6 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
79589
79685
|
addonId: null,
|
|
79590
79686
|
access: "delete"
|
|
79591
79687
|
},
|
|
79592
|
-
"userManagement.revokeScopedToken": {
|
|
79593
|
-
capName: "user-management",
|
|
79594
|
-
capScope: "system",
|
|
79595
|
-
addonId: null,
|
|
79596
|
-
access: "delete"
|
|
79597
|
-
},
|
|
79598
79688
|
"userManagement.setupTotp": {
|
|
79599
79689
|
capName: "user-management",
|
|
79600
79690
|
capScope: "system",
|
|
@@ -79625,12 +79715,6 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
79625
79715
|
addonId: null,
|
|
79626
79716
|
access: "view"
|
|
79627
79717
|
},
|
|
79628
|
-
"userManagement.validateScopedToken": {
|
|
79629
|
-
capName: "user-management",
|
|
79630
|
-
capScope: "system",
|
|
79631
|
-
addonId: null,
|
|
79632
|
-
access: "view"
|
|
79633
|
-
},
|
|
79634
79718
|
"userManagement.verifyTotp": {
|
|
79635
79719
|
capName: "user-management",
|
|
79636
79720
|
capScope: "system",
|
|
@@ -85953,6 +86037,7 @@ import * as clack from "@clack/prompts";
|
|
|
85953
86037
|
import {
|
|
85954
86038
|
clearSession,
|
|
85955
86039
|
defaultSession,
|
|
86040
|
+
jwtClaims,
|
|
85956
86041
|
listSessions,
|
|
85957
86042
|
loadSession,
|
|
85958
86043
|
saveSession
|
|
@@ -85968,20 +86053,11 @@ import {
|
|
|
85968
86053
|
validateHubAddress
|
|
85969
86054
|
} from "@camstack/develop";
|
|
85970
86055
|
import {
|
|
85971
|
-
discoverHubs
|
|
85972
|
-
normalizeHubUrl
|
|
86056
|
+
discoverHubs
|
|
85973
86057
|
} from "@camstack/develop/hub-discovery";
|
|
85974
|
-
var ADMIN_TOKEN_SUFFIX = ".admin-token";
|
|
85975
86058
|
function validateManualHubUrl(value) {
|
|
85976
86059
|
return validateHubAddress(value);
|
|
85977
86060
|
}
|
|
85978
|
-
function hubUrlFromAdminTokenFile(fileName) {
|
|
85979
|
-
if (!fileName.endsWith(ADMIN_TOKEN_SUFFIX)) return null;
|
|
85980
|
-
const slug = fileName.slice(0, -ADMIN_TOKEN_SUFFIX.length);
|
|
85981
|
-
const match = /^(.+?)_(\d{1,5})$/.exec(slug);
|
|
85982
|
-
const candidate = match ? `https://${match[1]}:${match[2]}` : `https://${slug}`;
|
|
85983
|
-
return normalizeHubUrl(candidate)?.url ?? null;
|
|
85984
|
-
}
|
|
85985
86061
|
function knownHubCandidates(deps) {
|
|
85986
86062
|
const dir = deps.sessionDir ?? defaultSessionDir();
|
|
85987
86063
|
const env = deps.env ?? process.env;
|
|
@@ -86004,9 +86080,6 @@ function knownHubCandidates(deps) {
|
|
|
86004
86080
|
}
|
|
86005
86081
|
} catch {
|
|
86006
86082
|
}
|
|
86007
|
-
} else {
|
|
86008
|
-
const url2 = hubUrlFromAdminTokenFile(file2);
|
|
86009
|
-
if (url2 !== null) out.push({ url: url2, source: "saved admin token" });
|
|
86010
86083
|
}
|
|
86011
86084
|
}
|
|
86012
86085
|
const fromEnv = resolveHubUrl({ env, session: null });
|
|
@@ -86134,30 +86207,32 @@ function isLoginPayload(value) {
|
|
|
86134
86207
|
const u = v.user;
|
|
86135
86208
|
return typeof u.id === "string" && typeof u.username === "string";
|
|
86136
86209
|
}
|
|
86137
|
-
function
|
|
86138
|
-
if (
|
|
86139
|
-
|
|
86140
|
-
|
|
86141
|
-
|
|
86142
|
-
|
|
86143
|
-
|
|
86144
|
-
if (prior.token.startsWith(SCOPED_TOKEN_PREFIX) && prior.tokenId) {
|
|
86145
|
-
await callTrpcMutation(
|
|
86146
|
-
`${server}/trpc/userManagement.revokeScopedToken?batch=1`,
|
|
86147
|
-
`Bearer ${authJwt}`,
|
|
86148
|
-
{ id: prior.tokenId },
|
|
86149
|
-
isUnknown
|
|
86150
|
-
);
|
|
86151
|
-
return;
|
|
86210
|
+
function revocationFor(session) {
|
|
86211
|
+
if (session.tokenId) {
|
|
86212
|
+
return {
|
|
86213
|
+
procedure: "auth.revokeToken",
|
|
86214
|
+
input: { id: session.tokenId },
|
|
86215
|
+
bearer: "fresh"
|
|
86216
|
+
};
|
|
86152
86217
|
}
|
|
86153
|
-
if (
|
|
86154
|
-
|
|
86155
|
-
`${server}/trpc/auth.logout?batch=1`,
|
|
86156
|
-
`Bearer ${prior.token}`,
|
|
86157
|
-
{},
|
|
86158
|
-
isLogoutPayload
|
|
86159
|
-
);
|
|
86218
|
+
if (jwtClaims(session.token) !== null) {
|
|
86219
|
+
return { procedure: "auth.logout", input: {}, bearer: "self" };
|
|
86160
86220
|
}
|
|
86221
|
+
return null;
|
|
86222
|
+
}
|
|
86223
|
+
async function performRevocation(server, session, freshJwt) {
|
|
86224
|
+
const r = revocationFor(session);
|
|
86225
|
+
if (!r) return;
|
|
86226
|
+
const bearer = r.bearer === "fresh" && freshJwt ? freshJwt : session.token;
|
|
86227
|
+
await callTrpcMutation(
|
|
86228
|
+
`${server}/trpc/${r.procedure}?batch=1`,
|
|
86229
|
+
`Bearer ${bearer}`,
|
|
86230
|
+
r.input,
|
|
86231
|
+
isUnknown
|
|
86232
|
+
);
|
|
86233
|
+
}
|
|
86234
|
+
async function revokePriorSession(server, prior, authJwt) {
|
|
86235
|
+
await performRevocation(server, prior, authJwt);
|
|
86161
86236
|
}
|
|
86162
86237
|
async function completeSecondFactor(server, login) {
|
|
86163
86238
|
const factors = login.secondFactors ?? [];
|
|
@@ -86174,7 +86249,7 @@ async function completeSecondFactor(server, login) {
|
|
|
86174
86249
|
return await callTrpcMutation(
|
|
86175
86250
|
`${server}/trpc/auth.loginVerifyTotp?batch=1`,
|
|
86176
86251
|
void 0,
|
|
86177
|
-
{ challengeToken: login.token, code },
|
|
86252
|
+
{ challengeToken: login.token, code, refreshable: true },
|
|
86178
86253
|
isLoginPayload
|
|
86179
86254
|
);
|
|
86180
86255
|
} catch (err) {
|
|
@@ -86267,6 +86342,8 @@ async function loginCommand(opts) {
|
|
|
86267
86342
|
let displayName;
|
|
86268
86343
|
let userId;
|
|
86269
86344
|
let isAdmin = false;
|
|
86345
|
+
let refreshToken;
|
|
86346
|
+
let expiresAt;
|
|
86270
86347
|
while (true) {
|
|
86271
86348
|
const authSpinner = clack.spinner();
|
|
86272
86349
|
authSpinner.start(
|
|
@@ -86276,7 +86353,7 @@ async function loginCommand(opts) {
|
|
|
86276
86353
|
const first = await callTrpcMutation(
|
|
86277
86354
|
`${server}/trpc/auth.login?batch=1`,
|
|
86278
86355
|
void 0,
|
|
86279
|
-
{ username, password: password2 },
|
|
86356
|
+
{ username, password: password2, refreshable: true },
|
|
86280
86357
|
isLoginPayload
|
|
86281
86358
|
);
|
|
86282
86359
|
const owesSecondFactor = (first.secondFactors ?? []).length > 0;
|
|
@@ -86286,6 +86363,8 @@ async function loginCommand(opts) {
|
|
|
86286
86363
|
displayName = login.user.username;
|
|
86287
86364
|
userId = login.user.id;
|
|
86288
86365
|
isAdmin = login.user.isAdmin === true;
|
|
86366
|
+
refreshToken = login.refreshToken;
|
|
86367
|
+
expiresAt = login.expiresAt;
|
|
86289
86368
|
if (!owesSecondFactor) authSpinner.stop(`Authenticated as ${displayName}`);
|
|
86290
86369
|
break;
|
|
86291
86370
|
} catch (err) {
|
|
@@ -86317,14 +86396,14 @@ async function loginCommand(opts) {
|
|
|
86317
86396
|
token: jwt2,
|
|
86318
86397
|
scopes: [],
|
|
86319
86398
|
createdAt: Date.now(),
|
|
86320
|
-
...isAdmin ? { isAdmin: true } : {}
|
|
86399
|
+
...isAdmin ? { isAdmin: true } : {},
|
|
86400
|
+
...refreshToken ? { refreshToken } : {},
|
|
86401
|
+
...expiresAt !== void 0 ? { expiresAt } : {}
|
|
86321
86402
|
};
|
|
86322
86403
|
const file2 = saveSession(session);
|
|
86323
86404
|
const role = isAdmin ? "administrator" : "user";
|
|
86324
|
-
clack.outro(
|
|
86325
|
-
|
|
86326
|
-
Cached at ${file2}`
|
|
86327
|
-
);
|
|
86405
|
+
clack.outro(`\u2713 Logged in as ${displayName} (${role}) \u2192 ${server}
|
|
86406
|
+
Cached at ${file2}`);
|
|
86328
86407
|
}
|
|
86329
86408
|
async function logoutCommand(opts) {
|
|
86330
86409
|
const session = loadSession(opts.server);
|
|
@@ -86336,21 +86415,7 @@ async function logoutCommand(opts) {
|
|
|
86336
86415
|
const spinner3 = clack.spinner();
|
|
86337
86416
|
spinner3.start(`Revoking token on ${session.server}`);
|
|
86338
86417
|
try {
|
|
86339
|
-
|
|
86340
|
-
await callTrpcMutation(
|
|
86341
|
-
`${session.server}/trpc/userManagement.revokeScopedToken?batch=1`,
|
|
86342
|
-
`Bearer ${session.token}`,
|
|
86343
|
-
{ id: session.tokenId },
|
|
86344
|
-
isUnknown
|
|
86345
|
-
);
|
|
86346
|
-
} else if (!session.token.startsWith(SCOPED_TOKEN_PREFIX) && !session.token.startsWith(ADMIN_TOKEN_PREFIX)) {
|
|
86347
|
-
await callTrpcMutation(
|
|
86348
|
-
`${session.server}/trpc/auth.logout?batch=1`,
|
|
86349
|
-
`Bearer ${session.token}`,
|
|
86350
|
-
{},
|
|
86351
|
-
isLogoutPayload
|
|
86352
|
-
);
|
|
86353
|
-
}
|
|
86418
|
+
await performRevocation(session.server, session, void 0);
|
|
86354
86419
|
spinner3.stop("Session revoked server-side.");
|
|
86355
86420
|
} catch (err) {
|
|
86356
86421
|
spinner3.stop(
|
|
@@ -86396,7 +86461,15 @@ async function whoamiCommand(opts) {
|
|
|
86396
86461
|
if (session.tokenId) console.log(` tokenId: ${session.tokenId}`);
|
|
86397
86462
|
const scopeLine = session.scopes.length > 0 ? session.scopes.map((s) => `${s.type}:${s.target}`).join(", ") : "(login JWT)";
|
|
86398
86463
|
console.log(` scopes: ${scopeLine}`);
|
|
86399
|
-
|
|
86464
|
+
const claims = jwtClaims(session.token);
|
|
86465
|
+
const admin = session.isAdmin === true || claims?.["isAdmin"] === true;
|
|
86466
|
+
console.log(` admin: ${admin ? "yes" : "no"}`);
|
|
86467
|
+
const expiresAt = session.expiresAt ?? (typeof claims?.["exp"] === "number" ? claims["exp"] * 1e3 : void 0);
|
|
86468
|
+
if (expiresAt !== void 0) {
|
|
86469
|
+
console.log(
|
|
86470
|
+
` expires: ${new Date(expiresAt).toISOString()}${session.refreshToken ? " (renewed automatically)" : ""}`
|
|
86471
|
+
);
|
|
86472
|
+
}
|
|
86400
86473
|
console.log(` createdAt: ${new Date(session.createdAt).toISOString()}`);
|
|
86401
86474
|
console.log("");
|
|
86402
86475
|
console.log(`[camstack] Pinging ${session.server}/api/auth/whoami\u2026`);
|
|
@@ -86441,7 +86514,7 @@ import {
|
|
|
86441
86514
|
MissingCredentialsError,
|
|
86442
86515
|
normalizeHubAddress as normalizeHubAddress3,
|
|
86443
86516
|
touchSession as touchSession3,
|
|
86444
|
-
|
|
86517
|
+
resolveFreshCredentials as resolveFreshCredentials3
|
|
86445
86518
|
} from "@camstack/develop";
|
|
86446
86519
|
|
|
86447
86520
|
// src/commands/discover.ts
|
|
@@ -86688,7 +86761,20 @@ import * as fs7 from "fs";
|
|
|
86688
86761
|
import * as path7 from "path";
|
|
86689
86762
|
import { parseArgs as parseArgs6 } from "util";
|
|
86690
86763
|
import * as clack3 from "@clack/prompts";
|
|
86691
|
-
import { loadSession as loadSession2,
|
|
86764
|
+
import { loadSession as loadSession2, resolveFreshCredentials, touchSession } from "@camstack/develop";
|
|
86765
|
+
|
|
86766
|
+
// src/http/hub-transport.ts
|
|
86767
|
+
var cliHubTransport = async (req) => {
|
|
86768
|
+
const res = await hubRequest(req.url, {
|
|
86769
|
+
method: req.method,
|
|
86770
|
+
headers: req.headers,
|
|
86771
|
+
...req.body !== void 0 ? { body: req.body } : {},
|
|
86772
|
+
timeoutMs: req.timeoutMs
|
|
86773
|
+
});
|
|
86774
|
+
return { status: res.status, text: await res.text() };
|
|
86775
|
+
};
|
|
86776
|
+
|
|
86777
|
+
// src/commands/dev.ts
|
|
86692
86778
|
var DEFAULT_DEBOUNCE_MS = 500;
|
|
86693
86779
|
var DEFAULT_WATCH_SUBDIR = "src";
|
|
86694
86780
|
function resolveAddonDir(arg) {
|
|
@@ -86720,12 +86806,12 @@ function watchRecursive(target, onEvent) {
|
|
|
86720
86806
|
return { close: () => w.close(), recursive: false };
|
|
86721
86807
|
}
|
|
86722
86808
|
}
|
|
86723
|
-
async function pushOnce(addonPath,
|
|
86809
|
+
async function pushOnce(addonPath, getOpts, label) {
|
|
86724
86810
|
const start = Date.now();
|
|
86725
86811
|
console.log(`
|
|
86726
86812
|
[camstack dev] \u2192 ${label}\u2026`);
|
|
86727
86813
|
try {
|
|
86728
|
-
await deployAddon(addonPath,
|
|
86814
|
+
await deployAddon(addonPath, await getOpts());
|
|
86729
86815
|
const took = ((Date.now() - start) / 1e3).toFixed(1);
|
|
86730
86816
|
console.log(`[camstack dev] \u2713 Synced in ${took}s`);
|
|
86731
86817
|
} catch (err) {
|
|
@@ -86754,12 +86840,14 @@ async function runDev(args) {
|
|
|
86754
86840
|
});
|
|
86755
86841
|
const addonArg = positionals[0] ?? ".";
|
|
86756
86842
|
const addonDir = resolveAddonDir(addonArg);
|
|
86757
|
-
const
|
|
86843
|
+
const credentialInputs = {
|
|
86758
86844
|
...typeof values.server === "string" ? { server: values.server } : {},
|
|
86759
86845
|
...typeof values.token === "string" ? { token: values.token } : {},
|
|
86760
86846
|
...typeof values["token-file"] === "string" ? { tokenFile: values["token-file"] } : {},
|
|
86761
|
-
loadSession: loadSession2
|
|
86762
|
-
|
|
86847
|
+
loadSession: loadSession2,
|
|
86848
|
+
transport: cliHubTransport
|
|
86849
|
+
};
|
|
86850
|
+
const creds = await resolveFreshCredentials(credentialInputs);
|
|
86763
86851
|
if (creds.warning) console.error(`[camstack dev] Warning: ${creds.warning}`);
|
|
86764
86852
|
if (creds.source === "session" && creds.server) touchSession(creds.server);
|
|
86765
86853
|
const serverUrl = creds.server;
|
|
@@ -86778,6 +86866,10 @@ async function runDev(args) {
|
|
|
86778
86866
|
buildMode: values["no-build"] === true ? "skip" : "auto",
|
|
86779
86867
|
...typeof values["build-script"] === "string" ? { buildScript: values["build-script"] } : {}
|
|
86780
86868
|
};
|
|
86869
|
+
const freshOpts = async () => ({
|
|
86870
|
+
...deployOpts,
|
|
86871
|
+
token: (await resolveFreshCredentials(credentialInputs)).token
|
|
86872
|
+
});
|
|
86781
86873
|
const watchOverride = typeof values["watch-path"] === "string" ? values["watch-path"] : void 0;
|
|
86782
86874
|
const watchTarget = watchOverride ? path7.resolve(addonDir, watchOverride) : fs7.existsSync(path7.join(addonDir, DEFAULT_WATCH_SUBDIR)) ? path7.join(addonDir, DEFAULT_WATCH_SUBDIR) : addonDir;
|
|
86783
86875
|
if (!fs7.existsSync(watchTarget)) {
|
|
@@ -86791,7 +86883,7 @@ async function runDev(args) {
|
|
|
86791
86883
|
);
|
|
86792
86884
|
clack3.log.info(`Debounce: ${debounceMs}ms`);
|
|
86793
86885
|
if (values["no-initial-push"] !== true) {
|
|
86794
|
-
await pushOnce(addonDir,
|
|
86886
|
+
await pushOnce(addonDir, freshOpts, "Initial sync");
|
|
86795
86887
|
} else {
|
|
86796
86888
|
console.log("[camstack dev] Skipping initial push (--no-initial-push). Waiting for changes\u2026");
|
|
86797
86889
|
}
|
|
@@ -86807,7 +86899,7 @@ async function runDev(args) {
|
|
|
86807
86899
|
}
|
|
86808
86900
|
pushing = true;
|
|
86809
86901
|
try {
|
|
86810
|
-
await pushOnce(addonDir,
|
|
86902
|
+
await pushOnce(addonDir, freshOpts, "File change detected \u2014 rebuilding");
|
|
86811
86903
|
} finally {
|
|
86812
86904
|
pushing = false;
|
|
86813
86905
|
if (pending) {
|
|
@@ -86843,7 +86935,7 @@ import * as clack4 from "@clack/prompts";
|
|
|
86843
86935
|
import {
|
|
86844
86936
|
loadSession as loadSession3,
|
|
86845
86937
|
touchSession as touchSession2,
|
|
86846
|
-
|
|
86938
|
+
resolveFreshCredentials as resolveFreshCredentials2,
|
|
86847
86939
|
withAuthHint as withAuthHint3
|
|
86848
86940
|
} from "@camstack/develop";
|
|
86849
86941
|
var POLL_INTERVAL_MS2 = 2e3;
|
|
@@ -86907,12 +86999,14 @@ async function runWatch(args) {
|
|
|
86907
86999
|
allowPositionals: true
|
|
86908
87000
|
});
|
|
86909
87001
|
const addonArg = positionals[0] ?? ".";
|
|
86910
|
-
const
|
|
87002
|
+
const credentialInputs = {
|
|
86911
87003
|
...typeof values.server === "string" ? { server: values.server } : {},
|
|
86912
87004
|
...typeof values.token === "string" ? { token: values.token } : {},
|
|
86913
87005
|
...typeof values["token-file"] === "string" ? { tokenFile: values["token-file"] } : {},
|
|
86914
|
-
loadSession: loadSession3
|
|
86915
|
-
|
|
87006
|
+
loadSession: loadSession3,
|
|
87007
|
+
transport: cliHubTransport
|
|
87008
|
+
};
|
|
87009
|
+
const creds = await resolveFreshCredentials2(credentialInputs);
|
|
86916
87010
|
if (creds.warning) console.error(`[camstack watch] Warning: ${creds.warning}`);
|
|
86917
87011
|
if (creds.source === "session" && creds.server) touchSession2(creds.server);
|
|
86918
87012
|
const serverUrl = creds.server;
|
|
@@ -86951,7 +87045,14 @@ async function runWatch(args) {
|
|
|
86951
87045
|
process.on("SIGTERM", shutdown);
|
|
86952
87046
|
while (!stop) {
|
|
86953
87047
|
try {
|
|
86954
|
-
const
|
|
87048
|
+
const fresh = await resolveFreshCredentials2(credentialInputs);
|
|
87049
|
+
const entries2 = await fetchLogs(
|
|
87050
|
+
serverUrl,
|
|
87051
|
+
fresh.token,
|
|
87052
|
+
addonId,
|
|
87053
|
+
LOG_BATCH_LIMIT,
|
|
87054
|
+
creds.source
|
|
87055
|
+
);
|
|
86955
87056
|
const sorted = [...entries2].toSorted((a, b) => {
|
|
86956
87057
|
const ta = typeof a.timestamp === "number" ? a.timestamp : new Date(a.timestamp).getTime();
|
|
86957
87058
|
const tb = typeof b.timestamp === "number" ? b.timestamp : new Date(b.timestamp).getTime();
|
|
@@ -87423,7 +87524,7 @@ function buildCommands() {
|
|
|
87423
87524
|
" -p, --password <pwd> Password (skips prompt \u2014 prefer letting the CLI prompt)",
|
|
87424
87525
|
` --token-name <name> Ignored (kept for scripts); login uses your hub session JWT`,
|
|
87425
87526
|
" --admin Ignored (kept for muscle memory); admin follows your account role",
|
|
87426
|
-
" --admin-days <n> Ignored (kept for muscle memory);
|
|
87527
|
+
" --admin-days <n> Ignored (kept for muscle memory); one login, one token format"
|
|
87427
87528
|
].join("\n")
|
|
87428
87529
|
},
|
|
87429
87530
|
{
|
|
@@ -87434,7 +87535,7 @@ function buildCommands() {
|
|
|
87434
87535
|
"Usage: camstack discover [options]",
|
|
87435
87536
|
"",
|
|
87436
87537
|
"Lists the hubs `camstack login` would offer: those announcing _camstack._tcp over",
|
|
87437
|
-
" mDNS plus saved sessions,
|
|
87538
|
+
" mDNS plus saved sessions, $CAMSTACK_HUB_URL and scratchpad/.hub-url,",
|
|
87438
87539
|
" reachable ones only, each with its source. Agents never announce this service.",
|
|
87439
87540
|
"",
|
|
87440
87541
|
"Options:",
|
|
@@ -87711,7 +87812,7 @@ async function runWhoami(args) {
|
|
|
87711
87812
|
const server = stringOpt(parsed.values, "server");
|
|
87712
87813
|
await whoamiCommand(server ? { server: normalizeHubAddress3(server) } : {});
|
|
87713
87814
|
}
|
|
87714
|
-
function resolveClosureDeployOpts(values) {
|
|
87815
|
+
async function resolveClosureDeployOpts(values) {
|
|
87715
87816
|
const nodeId = stringOpt(values, "node");
|
|
87716
87817
|
const cluster = boolOpt(values, "cluster") || boolOpt(values, "all");
|
|
87717
87818
|
if (cluster && nodeId) {
|
|
@@ -87719,7 +87820,7 @@ function resolveClosureDeployOpts(values) {
|
|
|
87719
87820
|
process.exit(1);
|
|
87720
87821
|
}
|
|
87721
87822
|
const version2 = stringOpt(values, "version");
|
|
87722
|
-
const creds = resolveCommandCredentials(values);
|
|
87823
|
+
const creds = await resolveCommandCredentials(values);
|
|
87723
87824
|
return {
|
|
87724
87825
|
serverUrl: creds.server ?? DEFAULT_SERVER_URL,
|
|
87725
87826
|
token: creds.token,
|
|
@@ -87757,7 +87858,7 @@ async function runDeploy(args) {
|
|
|
87757
87858
|
console.error("[camstack] Error: --closure does not take addon --build / --no-build flags.");
|
|
87758
87859
|
process.exit(1);
|
|
87759
87860
|
}
|
|
87760
|
-
await deployServer(resolveClosureDeployOpts(parsed.values));
|
|
87861
|
+
await deployServer(await resolveClosureDeployOpts(parsed.values));
|
|
87761
87862
|
return;
|
|
87762
87863
|
}
|
|
87763
87864
|
if (stringOpt(parsed.values, "version")) {
|
|
@@ -87765,7 +87866,7 @@ async function runDeploy(args) {
|
|
|
87765
87866
|
process.exit(1);
|
|
87766
87867
|
}
|
|
87767
87868
|
const addonPath = parsed.positionals[0] ?? ".";
|
|
87768
|
-
const creds = resolveCommandCredentials(parsed.values);
|
|
87869
|
+
const creds = await resolveCommandCredentials(parsed.values);
|
|
87769
87870
|
const server = creds.server ?? DEFAULT_SERVER_URL;
|
|
87770
87871
|
const token = creds.token;
|
|
87771
87872
|
const nodeId = stringOpt(parsed.values, "node");
|
|
@@ -87817,19 +87918,20 @@ async function runDeployServer(args) {
|
|
|
87817
87918
|
return;
|
|
87818
87919
|
}
|
|
87819
87920
|
console.log("[camstack] note: `deploy-server` is an alias of `deploy --closure`");
|
|
87820
|
-
await deployServer(resolveClosureDeployOpts(parsed.values));
|
|
87921
|
+
await deployServer(await resolveClosureDeployOpts(parsed.values));
|
|
87821
87922
|
}
|
|
87822
87923
|
var DEFAULT_SERVER_URL = "https://localhost:4443";
|
|
87823
|
-
function resolveCommandCredentials(values) {
|
|
87924
|
+
async function resolveCommandCredentials(values) {
|
|
87824
87925
|
const server = stringOpt(values, "server");
|
|
87825
87926
|
const token = stringOpt(values, "token");
|
|
87826
87927
|
const tokenFile = stringOpt(values, "token-file");
|
|
87827
87928
|
try {
|
|
87828
|
-
const creds =
|
|
87929
|
+
const creds = await resolveFreshCredentials3({
|
|
87829
87930
|
...server ? { server } : {},
|
|
87830
87931
|
...token ? { token } : {},
|
|
87831
87932
|
...tokenFile ? { tokenFile } : {},
|
|
87832
|
-
loadSession: loadSession4
|
|
87933
|
+
loadSession: loadSession4,
|
|
87934
|
+
transport: cliHubTransport
|
|
87833
87935
|
});
|
|
87834
87936
|
if (creds.warning) console.error(`[camstack] Warning: ${creds.warning}`);
|
|
87835
87937
|
if (creds.source === "session" && creds.server) touchSession3(creds.server);
|