@unisonlabs/sixminute-admin 0.1.1186-next → 0.1.1188-next
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/sixminute-admin.mjs +282 -10
- package/package.json +1 -1
package/dist/sixminute-admin.mjs
CHANGED
|
@@ -21,7 +21,7 @@ import { homedir } from "node:os";
|
|
|
21
21
|
import { fileURLToPath } from "node:url";
|
|
22
22
|
|
|
23
23
|
// tools/admin/src/build-info.ts
|
|
24
|
-
var BUILT = { version: "0.1.
|
|
24
|
+
var BUILT = { version: "0.1.1188-next", commit: "20f4bf99e8e3ce3d14dc7e52172b8cd5e9568924", surface: "9cd8ad25f1495c42" };
|
|
25
25
|
|
|
26
26
|
// tools/admin/src/run.ts
|
|
27
27
|
import { rmSync as rmSync3 } from "node:fs";
|
|
@@ -4895,7 +4895,8 @@ var TenantPolicySchema = exports_external.object({
|
|
|
4895
4895
|
excluded_bundles: exports_external.array(exports_external.string().min(1)).default([]),
|
|
4896
4896
|
security_tier: exports_external.enum(["standard", "confidential"]).default("standard"),
|
|
4897
4897
|
raw_archive: exports_external.boolean().default(false),
|
|
4898
|
-
research_export: exports_external.boolean().default(false)
|
|
4898
|
+
research_export: exports_external.boolean().default(false),
|
|
4899
|
+
context_retention_days: exports_external.number().int().min(0).max(365).default(30)
|
|
4899
4900
|
}).default({});
|
|
4900
4901
|
var NARRATIVE_GUIDANCE_MAX_CHARS = 1500;
|
|
4901
4902
|
var GUIDANCE_CONTROL = /[\u0000-\u0009\u000B-\u001F\u007F-\u009F]/;
|
|
@@ -5682,6 +5683,33 @@ var ResearchExportResultSchema = exports_external.discriminatedUnion("tier", [
|
|
|
5682
5683
|
ResearchExportConfidentialSchema,
|
|
5683
5684
|
ResearchExportSealedSchema
|
|
5684
5685
|
]);
|
|
5686
|
+
var ResearchContextExportSchema = exports_external.object({
|
|
5687
|
+
export_id: exports_external.string(),
|
|
5688
|
+
tenant_id: exports_external.string(),
|
|
5689
|
+
tenant_name: exports_external.string(),
|
|
5690
|
+
from: exports_external.string(),
|
|
5691
|
+
to: exports_external.string(),
|
|
5692
|
+
operator: exports_external.string(),
|
|
5693
|
+
contexts: exports_external.array(exports_external.object({
|
|
5694
|
+
member_id: exports_external.string(),
|
|
5695
|
+
recording_id: exports_external.string(),
|
|
5696
|
+
seq: exports_external.number().int(),
|
|
5697
|
+
t_start: exports_external.string(),
|
|
5698
|
+
t_end: exports_external.string(),
|
|
5699
|
+
context: exports_external.unknown()
|
|
5700
|
+
})),
|
|
5701
|
+
steps: exports_external.array(exports_external.object({
|
|
5702
|
+
run_id: exports_external.string(),
|
|
5703
|
+
kind: exports_external.string(),
|
|
5704
|
+
member_id: exports_external.string(),
|
|
5705
|
+
subject_from: exports_external.string(),
|
|
5706
|
+
name: exports_external.string(),
|
|
5707
|
+
prompt_fingerprint: exports_external.string().nullable(),
|
|
5708
|
+
usage: exports_external.unknown(),
|
|
5709
|
+
output: exports_external.unknown(),
|
|
5710
|
+
created_at: exports_external.string()
|
|
5711
|
+
}))
|
|
5712
|
+
});
|
|
5685
5713
|
// packages/contracts/src/admin-tenants.ts
|
|
5686
5714
|
var AdminTenantParamsSchema = exports_external.object({ tenant: TenantIdSchema });
|
|
5687
5715
|
var AdminSecurityTierSchema = exports_external.enum(["standard", "confidential"]);
|
|
@@ -5762,6 +5790,26 @@ var AdminEntriesPurgeResultSchema = exports_external.object({
|
|
|
5762
5790
|
rows: exports_external.object({ demo: exports_external.array(AdminPurgeRowSchema), unmatched: exports_external.array(AdminPurgeRowSchema) }),
|
|
5763
5791
|
deleted: exports_external.object({ demo: exports_external.number().int(), unmatched: exports_external.number().int(), total: exports_external.number().int() }).nullable()
|
|
5764
5792
|
});
|
|
5793
|
+
var AdminContextRetentionSetSchema = exports_external.object({ days: exports_external.number().int().min(1).max(365) });
|
|
5794
|
+
var AdminContextRetentionResultSchema = exports_external.object({
|
|
5795
|
+
tenant: exports_external.object({ id: TenantIdSchema, name: exports_external.string() }),
|
|
5796
|
+
days: exports_external.number().int(),
|
|
5797
|
+
previous: exports_external.number().int(),
|
|
5798
|
+
shifted: exports_external.object({
|
|
5799
|
+
interval_contexts: exports_external.number().int(),
|
|
5800
|
+
pipeline_runs: exports_external.number().int(),
|
|
5801
|
+
pipeline_steps: exports_external.number().int(),
|
|
5802
|
+
derivation_cache: exports_external.number().int(),
|
|
5803
|
+
intervals: exports_external.number().int()
|
|
5804
|
+
})
|
|
5805
|
+
});
|
|
5806
|
+
var AdminSealedBackfillResultSchema = exports_external.object({
|
|
5807
|
+
tenant: TenantIdSchema,
|
|
5808
|
+
decisions_sealed: exports_external.number().int(),
|
|
5809
|
+
intervals_aged: exports_external.number().int(),
|
|
5810
|
+
judged_sealed: exports_external.number().int(),
|
|
5811
|
+
done: exports_external.boolean()
|
|
5812
|
+
});
|
|
5765
5813
|
// packages/contracts/src/admin-firm-acting.ts
|
|
5766
5814
|
var ACTING_AS_HEADER = "X-Six-Minute-Acting-As";
|
|
5767
5815
|
var TeamApplyRequestSchema = exports_external.object({
|
|
@@ -5998,6 +6046,49 @@ var ServedConfigBundleSchema = ConfigBundleSchema.extend({
|
|
|
5998
6046
|
prompts: ServedConfigPromptsSchema,
|
|
5999
6047
|
vocabularies: ServedConfigVocabulariesSchema
|
|
6000
6048
|
});
|
|
6049
|
+
// packages/contracts/src/device.ts
|
|
6050
|
+
var DEVICE_CREDENTIAL_PREFIX = "smd_";
|
|
6051
|
+
var ENROLLMENT_CODE_PREFIX = "sme_";
|
|
6052
|
+
var EnrollmentCodeSchema = exports_external.object({
|
|
6053
|
+
code: exports_external.string().startsWith(ENROLLMENT_CODE_PREFIX),
|
|
6054
|
+
expires_at: TimestampSchema
|
|
6055
|
+
});
|
|
6056
|
+
var DeviceEnrollSchema = exports_external.object({
|
|
6057
|
+
code: exports_external.string().startsWith(ENROLLMENT_CODE_PREFIX).max(200),
|
|
6058
|
+
device_id: DeviceIdSchema,
|
|
6059
|
+
name: DeviceRegistrationSchema.shape.name,
|
|
6060
|
+
platform: DeviceSchema.shape.platform
|
|
6061
|
+
});
|
|
6062
|
+
var DeviceEnrolledSchema = exports_external.object({
|
|
6063
|
+
credential: exports_external.string().startsWith(DEVICE_CREDENTIAL_PREFIX),
|
|
6064
|
+
device: DeviceSchema
|
|
6065
|
+
});
|
|
6066
|
+
var DevicePolicySchema = exports_external.object({
|
|
6067
|
+
excluded_bundles: exports_external.array(exports_external.string()),
|
|
6068
|
+
raw_archive: exports_external.boolean(),
|
|
6069
|
+
swallow_short_pauses: exports_external.boolean().nullable(),
|
|
6070
|
+
unit_minutes: UnitMinutesSchema,
|
|
6071
|
+
context_retention_days: exports_external.number().int().nonnegative(),
|
|
6072
|
+
minimum_version: exports_external.string().nullable()
|
|
6073
|
+
});
|
|
6074
|
+
var RecordingStopSchema = exports_external.object({
|
|
6075
|
+
after_seq: exports_external.number().int().nonnegative(),
|
|
6076
|
+
at: TimestampSchema,
|
|
6077
|
+
reason: exports_external.enum(["person", "quit", "update", "sign-out", "roll"])
|
|
6078
|
+
});
|
|
6079
|
+
var RecordingSkipSchema = exports_external.object({ seq: exports_external.number().int().positive() });
|
|
6080
|
+
var RecordingClockSchema = exports_external.object({
|
|
6081
|
+
device_clock: TimestampSchema,
|
|
6082
|
+
last_witness_at: TimestampSchema.nullable(),
|
|
6083
|
+
silence_end_after: TimestampSchema.nullable()
|
|
6084
|
+
});
|
|
6085
|
+
var RecordingParamsSchema = exports_external.object({ id: RecordingIdSchema });
|
|
6086
|
+
var ContextAcceptedSchema = exports_external.object({
|
|
6087
|
+
accepted: exports_external.number().int().positive(),
|
|
6088
|
+
run_id: RunIdSchema.optional(),
|
|
6089
|
+
recording_id: RecordingIdSchema.optional()
|
|
6090
|
+
});
|
|
6091
|
+
var DeviceCredentialParamsSchema = exports_external.object({ id: DeviceIdSchema });
|
|
6001
6092
|
// packages/contracts/src/recording.ts
|
|
6002
6093
|
var RecordingSchema = exports_external.object({
|
|
6003
6094
|
id: RecordingIdSchema,
|
|
@@ -6392,6 +6483,100 @@ var LocalHostEventSchema = exports_external.discriminatedUnion("name", [
|
|
|
6392
6483
|
}).strict()
|
|
6393
6484
|
]);
|
|
6394
6485
|
var LocalMethodSchema = exports_external.enum(["GET", "POST", "PATCH", "DELETE"]);
|
|
6486
|
+
// packages/contracts/src/pipeline-status.ts
|
|
6487
|
+
var PipelineStatusQuerySchema = exports_external.object({
|
|
6488
|
+
since: exports_external.string().regex(/^\d{1,18}$/, "expected a version number").optional()
|
|
6489
|
+
});
|
|
6490
|
+
var PipelineRecordingStatusSchema = exports_external.object({
|
|
6491
|
+
recording_id: RecordingIdSchema,
|
|
6492
|
+
device_id: DeviceIdSchema,
|
|
6493
|
+
decided_through: TimestampSchema.nullable(),
|
|
6494
|
+
behind_seconds: exports_external.number().int().nonnegative(),
|
|
6495
|
+
stopped_at: TimestampSchema.nullable()
|
|
6496
|
+
});
|
|
6497
|
+
var PipelineStatusSchema = exports_external.object({
|
|
6498
|
+
version: exports_external.number().int().nonnegative(),
|
|
6499
|
+
recordings: exports_external.array(PipelineRecordingStatusSchema),
|
|
6500
|
+
deciding: exports_external.object({ recording_id: RecordingIdSchema, from: TimestampSchema, to: TimestampSchema }).nullable(),
|
|
6501
|
+
generate: exports_external.object({
|
|
6502
|
+
running: exports_external.object({
|
|
6503
|
+
run_id: RunIdSchema,
|
|
6504
|
+
kind: exports_external.enum(["generate", "regenerate", "propose"]),
|
|
6505
|
+
day: LocalDaySchema,
|
|
6506
|
+
step: exports_external.object({ name: exports_external.string(), at: TimestampSchema, entry_from: TimestampSchema.optional() })
|
|
6507
|
+
}).nullable(),
|
|
6508
|
+
pending: exports_external.array(exports_external.object({ day: LocalDaySchema, from: TimestampSchema, to: TimestampSchema })),
|
|
6509
|
+
failed: exports_external.object({ run_id: RunIdSchema, day: LocalDaySchema, error_class: exports_external.string() }).nullable()
|
|
6510
|
+
})
|
|
6511
|
+
});
|
|
6512
|
+
// packages/contracts/src/pipeline.ts
|
|
6513
|
+
var ContextStopReasonSchema = exports_external.enum(["person", "quit", "update", "sign-out", "roll"]);
|
|
6514
|
+
var IntervalContextHeaderSchema = exports_external.object({
|
|
6515
|
+
recording_id: RecordingIdSchema,
|
|
6516
|
+
seq: exports_external.number().int().min(1),
|
|
6517
|
+
from: TimestampSchema,
|
|
6518
|
+
to: TimestampSchema,
|
|
6519
|
+
unit_minutes: exports_external.number().int().min(1),
|
|
6520
|
+
time_zone: exports_external.string().min(1),
|
|
6521
|
+
swallow_short_pauses: exports_external.boolean(),
|
|
6522
|
+
sent_at: TimestampSchema,
|
|
6523
|
+
clock_steps: exports_external.array(CaptureClockStepSchema),
|
|
6524
|
+
complete: exports_external.literal(true),
|
|
6525
|
+
recording: exports_external.object({
|
|
6526
|
+
started_at: TimestampSchema,
|
|
6527
|
+
capture_enabled: exports_external.boolean(),
|
|
6528
|
+
excluded_bundles: exports_external.array(exports_external.string()),
|
|
6529
|
+
stop: exports_external.object({ at: TimestampSchema, reason: ContextStopReasonSchema }).optional()
|
|
6530
|
+
})
|
|
6531
|
+
});
|
|
6532
|
+
var ContextSnapshotSchema = exports_external.object({
|
|
6533
|
+
id: SnapshotIdSchema,
|
|
6534
|
+
t: TimestampSchema,
|
|
6535
|
+
kind: exports_external.enum(["anchor", "diff"]),
|
|
6536
|
+
text: exports_external.string()
|
|
6537
|
+
});
|
|
6538
|
+
var ContextObservationSchema = exports_external.object({
|
|
6539
|
+
id: ObservationIdSchema,
|
|
6540
|
+
app: exports_external.string(),
|
|
6541
|
+
bundle: exports_external.string(),
|
|
6542
|
+
title: exports_external.string(),
|
|
6543
|
+
url: exports_external.string().nullable(),
|
|
6544
|
+
t_start: TimestampSchema,
|
|
6545
|
+
t_end: TimestampSchema,
|
|
6546
|
+
open: exports_external.boolean(),
|
|
6547
|
+
screen_at_start: exports_external.string().optional(),
|
|
6548
|
+
snapshots: exports_external.array(ContextSnapshotSchema),
|
|
6549
|
+
typed: exports_external.string(),
|
|
6550
|
+
clicks: exports_external.array(CaptureClickSchema)
|
|
6551
|
+
});
|
|
6552
|
+
var IntervalContextSchema = exports_external.object({
|
|
6553
|
+
schema_version: exports_external.literal(1),
|
|
6554
|
+
header: IntervalContextHeaderSchema,
|
|
6555
|
+
observations: exports_external.array(ContextObservationSchema),
|
|
6556
|
+
marks: exports_external.object({
|
|
6557
|
+
state_at_start: exports_external.object({
|
|
6558
|
+
lock: exports_external.boolean(),
|
|
6559
|
+
sleep: exports_external.boolean(),
|
|
6560
|
+
mic: exports_external.boolean(),
|
|
6561
|
+
camera: exports_external.boolean(),
|
|
6562
|
+
display: exports_external.boolean(),
|
|
6563
|
+
audio: exports_external.boolean()
|
|
6564
|
+
}),
|
|
6565
|
+
inside: exports_external.array(CaptureMarkSchema)
|
|
6566
|
+
}),
|
|
6567
|
+
files: exports_external.array(CaptureFileEventSchema),
|
|
6568
|
+
silence: exports_external.object({
|
|
6569
|
+
last_end_before: TimestampSchema.nullable(),
|
|
6570
|
+
first_end_inside: TimestampSchema.nullable()
|
|
6571
|
+
}),
|
|
6572
|
+
lost: exports_external.array(exports_external.string()).optional(),
|
|
6573
|
+
imported_decision: exports_external.object({
|
|
6574
|
+
summary: exports_external.string().nullable(),
|
|
6575
|
+
matter_id: exports_external.string().nullable(),
|
|
6576
|
+
block_start: TimestampSchema.nullable(),
|
|
6577
|
+
activity_label: exports_external.string().nullable()
|
|
6578
|
+
}).optional()
|
|
6579
|
+
});
|
|
6395
6580
|
// packages/contracts/src/run.ts
|
|
6396
6581
|
var VerdictSchema = exports_external.enum(["matter", "unmatched", "absent"]);
|
|
6397
6582
|
var WORK_VERDICTS = ["matter", "unmatched"];
|
|
@@ -6695,23 +6880,23 @@ async function deviceLogin(io, environment) {
|
|
|
6695
6880
|
if (!started.ok) {
|
|
6696
6881
|
throw new AdminUsageError(`WorkOS answered ${started.status} to the sign-in request for ${environment.name}. CLI Auth must be enabled ` + "for this environment in the WorkOS dashboard.");
|
|
6697
6882
|
}
|
|
6698
|
-
const
|
|
6699
|
-
if (typeof
|
|
6883
|
+
const device2 = await started.json();
|
|
6884
|
+
if (typeof device2.device_code !== "string" || typeof device2.user_code !== "string") {
|
|
6700
6885
|
throw new Error("WorkOS answered the sign-in request without a device code");
|
|
6701
6886
|
}
|
|
6702
|
-
const url = typeof
|
|
6887
|
+
const url = typeof device2.verification_uri_complete === "string" ? device2.verification_uri_complete : typeof device2.verification_uri === "string" ? device2.verification_uri : null;
|
|
6703
6888
|
if (url === null)
|
|
6704
6889
|
throw new Error("WorkOS answered the sign-in request without a url to confirm it at");
|
|
6705
6890
|
io.say(`Sign in to ${environment.name} in your browser: ${url}`);
|
|
6706
|
-
io.say(`Confirm that it shows the code ${
|
|
6891
|
+
io.say(`Confirm that it shows the code ${device2.user_code}.`);
|
|
6707
6892
|
io.openBrowser(url);
|
|
6708
|
-
let interval = (typeof
|
|
6709
|
-
const deadline = io.now() + (typeof
|
|
6893
|
+
let interval = (typeof device2.interval === "number" && device2.interval > 0 ? device2.interval : 5) * 1000;
|
|
6894
|
+
const deadline = io.now() + (typeof device2.expires_in === "number" ? device2.expires_in : 300) * 1000;
|
|
6710
6895
|
for (;; ) {
|
|
6711
6896
|
await io.sleep(interval);
|
|
6712
6897
|
const answer = await authenticate(io, {
|
|
6713
6898
|
grant_type: DEVICE_GRANT,
|
|
6714
|
-
device_code:
|
|
6899
|
+
device_code: device2.device_code,
|
|
6715
6900
|
client_id: environment.clientId
|
|
6716
6901
|
});
|
|
6717
6902
|
if (answer.status === 200) {
|
|
@@ -7151,6 +7336,24 @@ is required; without one every command answers 403.
|
|
|
7151
7336
|
The unseal runs as you, with your own Google sign-in (gcloud auth
|
|
7152
7337
|
login); only the people granted the research key can open a card.
|
|
7153
7338
|
|
|
7339
|
+
sixminute-admin retention set --env <env> --tenant tenant_... --days <1-365> [--json]
|
|
7340
|
+
Sets how many days the cloud keeps the firm's interval contexts after
|
|
7341
|
+
each interval's day (30 unless its agreement says otherwise), and moves
|
|
7342
|
+
every stored expiry of the firm by the difference at once: a shorter
|
|
7343
|
+
setting deletes at the next hourly purge. Summaries, labels and entries
|
|
7344
|
+
are not affected.
|
|
7345
|
+
|
|
7346
|
+
sixminute-admin backfill sealed --env <env> --tenant tenant_... [--json]
|
|
7347
|
+
Seals the firm's interval summaries and labels and its entries' judged
|
|
7348
|
+
drafts under its own key, and gives intervals stored before the context
|
|
7349
|
+
store an age, a bounded pass at a time until nothing is left.
|
|
7350
|
+
|
|
7351
|
+
sixminute-admin research contexts --env <env> --tenant tenant_... --from YYYY-MM-DD --to YYYY-MM-DD --out <dir> [--json]
|
|
7352
|
+
A firm's research data (R10): its interval contexts and the step ledger
|
|
7353
|
+
over a day range, written as two jsonl files in --out (a new folder
|
|
7354
|
+
0700, as research export). Refused unless the firm instructed it in
|
|
7355
|
+
writing (research-export allow); the audit row is written first.
|
|
7356
|
+
|
|
7154
7357
|
sixminute-admin entries purge --env <env> --tenant tenant_... --author member_... (--demo | --unmatched | both) [--dry-run] [--yes] [--json]
|
|
7155
7358
|
Removes entry rows from one firm. A person may only soft-delete
|
|
7156
7359
|
their own draft (2026-09-25) and nothing but a merge removes a row
|
|
@@ -7527,6 +7730,12 @@ async function runAdmin(argv, deps) {
|
|
|
7527
7730
|
return runResearchExportFlag(run2, subcommand);
|
|
7528
7731
|
if (group === "research" && subcommand === "export")
|
|
7529
7732
|
return runResearchExport(run2);
|
|
7733
|
+
if (group === "research" && subcommand === "contexts")
|
|
7734
|
+
return runResearchContexts(run2);
|
|
7735
|
+
if (group === "retention" && subcommand === "set")
|
|
7736
|
+
return runRetentionSet(run2);
|
|
7737
|
+
if (group === "backfill" && subcommand === "sealed")
|
|
7738
|
+
return runBackfillSealed(run2);
|
|
7530
7739
|
if (group === "entries" && subcommand === "purge")
|
|
7531
7740
|
return runEntriesPurge(run2);
|
|
7532
7741
|
if (group === "connector")
|
|
@@ -7716,6 +7925,65 @@ async function runResearchExportFlag(run2, subcommand) {
|
|
|
7716
7925
|
allow ? "Research cards are stored for this firm from its next completion, for 30 days, sealed under the research key." : "No research card is stored for this firm from its next completion. Cards already stored stay until the 30-day purge."
|
|
7717
7926
|
]);
|
|
7718
7927
|
}
|
|
7928
|
+
async function runRetentionSet(run2) {
|
|
7929
|
+
const tenantId = required(run2.flags, "tenant", "whose retention");
|
|
7930
|
+
const days = Number(required(run2.flags, "days", "how many days after each interval's day its context is kept"));
|
|
7931
|
+
if (!Number.isInteger(days) || days < 1 || days > 365)
|
|
7932
|
+
throw new AdminUsageError("--days is a whole number from 1 to 365.");
|
|
7933
|
+
const done = AdminContextRetentionResultSchema.parse(expectOk(await call(run2.api, "PUT", tenantPath(tenantId, "/context-retention"), { days })));
|
|
7934
|
+
const moved = Object.entries(done.shifted).map(([table2, rows]) => `${table2} ${rows}`).join(", ");
|
|
7935
|
+
return render(run2, done, [
|
|
7936
|
+
`tenant ${done.tenant.id} ${done.tenant.name}`,
|
|
7937
|
+
`retention ${done.previous} -> ${done.days} days`,
|
|
7938
|
+
`moved ${moved}`
|
|
7939
|
+
]);
|
|
7940
|
+
}
|
|
7941
|
+
async function runBackfillSealed(run2) {
|
|
7942
|
+
const tenantId = required(run2.flags, "tenant", "whose rows to seal");
|
|
7943
|
+
const total = { decisions_sealed: 0, intervals_aged: 0, judged_sealed: 0 };
|
|
7944
|
+
for (;; ) {
|
|
7945
|
+
const pass = AdminSealedBackfillResultSchema.parse(expectOk(await call(run2.api, "POST", tenantPath(tenantId, "/backfill/sealed"))));
|
|
7946
|
+
total.decisions_sealed += pass.decisions_sealed;
|
|
7947
|
+
total.intervals_aged += pass.intervals_aged;
|
|
7948
|
+
total.judged_sealed += pass.judged_sealed;
|
|
7949
|
+
if (pass.done)
|
|
7950
|
+
break;
|
|
7951
|
+
}
|
|
7952
|
+
return render(run2, { tenant: tenantId, ...total }, [
|
|
7953
|
+
`tenant ${tenantId}`,
|
|
7954
|
+
`sealed ${total.decisions_sealed} interval decision(s), ${total.judged_sealed} judged draft(s)`,
|
|
7955
|
+
`aged ${total.intervals_aged} interval(s)`
|
|
7956
|
+
]);
|
|
7957
|
+
}
|
|
7958
|
+
async function runResearchContexts(run2) {
|
|
7959
|
+
const { flags } = run2;
|
|
7960
|
+
const tenantId = required(flags, "tenant", "an export is one firm's contexts and steps");
|
|
7961
|
+
const from = dayOf2(flags, "from", "the first day of the range");
|
|
7962
|
+
const to = dayOf2(flags, "to", "the day the range stops before; --to is not included");
|
|
7963
|
+
if (from >= to)
|
|
7964
|
+
throw new AdminUsageError("--from must be before --to; the range is half-open and an empty one exports nothing.");
|
|
7965
|
+
const out = resolve(required(flags, "out", "where to write the files; an export lives on this machine and nowhere else"));
|
|
7966
|
+
const claimed = claimExportDirectory(out);
|
|
7967
|
+
let done;
|
|
7968
|
+
try {
|
|
7969
|
+
done = ResearchContextExportSchema.parse(expectOk(await call(run2.api, "POST", tenantPath(tenantId, "/research-exports/contexts"), { from, to })));
|
|
7970
|
+
} catch (err) {
|
|
7971
|
+
releaseExportDirectory(out, claimed);
|
|
7972
|
+
throw err;
|
|
7973
|
+
}
|
|
7974
|
+
const contextsPath = join2(out, `contexts-${tenantId}-${from}-${to}.jsonl`);
|
|
7975
|
+
const stepsPath = join2(out, `steps-${tenantId}-${from}-${to}.jsonl`);
|
|
7976
|
+
writePrivateFile(contextsPath, jsonLines(done.contexts));
|
|
7977
|
+
writePrivateFile(stepsPath, jsonLines(done.steps));
|
|
7978
|
+
return render(run2, { tenant_id: tenantId, from: done.from, to: done.to, contexts: done.contexts.length, steps: done.steps.length, files: [contextsPath, stepsPath], operator: done.operator }, [
|
|
7979
|
+
`tenant ${tenantId} ${done.tenant_name}`,
|
|
7980
|
+
`range ${from} to ${to} (--to not included)`,
|
|
7981
|
+
`contexts ${done.contexts.length}`,
|
|
7982
|
+
`steps ${done.steps.length}`,
|
|
7983
|
+
`files ${contextsPath}`,
|
|
7984
|
+
` ${stepsPath}`
|
|
7985
|
+
]);
|
|
7986
|
+
}
|
|
7719
7987
|
async function runVersions(run2) {
|
|
7720
7988
|
const tenantId = required(run2.flags, "tenant", "whose devices");
|
|
7721
7989
|
const found = AdminDeviceVersionListSchema.parse(expectOk(await call(run2.api, "GET", tenantPath(tenantId, "/devices"))));
|
|
@@ -8371,7 +8639,11 @@ ${ADMIN_USAGE}`);
|
|
|
8371
8639
|
|
|
8372
8640
|
// tools/admin/src/surface.ts
|
|
8373
8641
|
import { createHash } from "node:crypto";
|
|
8374
|
-
var MACHINE_ADMIN_PATHS = [
|
|
8642
|
+
var MACHINE_ADMIN_PATHS = [
|
|
8643
|
+
"/v1/admin/research/purge",
|
|
8644
|
+
"/v1/admin/connectors/sync",
|
|
8645
|
+
"/v1/admin/context/purge"
|
|
8646
|
+
];
|
|
8375
8647
|
function canonicalJson(value) {
|
|
8376
8648
|
if (Array.isArray(value))
|
|
8377
8649
|
return `[${value.map((item) => item === undefined ? "null" : canonicalJson(item)).join(",")}]`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unisonlabs/sixminute-admin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1188-next",
|
|
4
4
|
"description": "Sixminute operator tool: the admin commands of the Sixminute API, run with your own operator sign-in.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|