@keystrokehq/cli 0.0.66 → 0.0.69
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/{cat-TSFMZVYS-RwFYGRgl.mjs → cat-TSFMZVYS-Bp6ZgHzP.mjs} +2 -2
- package/dist/{cat-TSFMZVYS-RwFYGRgl.mjs.map → cat-TSFMZVYS-Bp6ZgHzP.mjs.map} +1 -1
- package/dist/{cut-OKARJCCV-7cebiTlb.mjs → cut-OKARJCCV-DLzvnQ0X.mjs} +2 -2
- package/dist/{cut-OKARJCCV-7cebiTlb.mjs.map → cut-OKARJCCV-DLzvnQ0X.mjs.map} +1 -1
- package/dist/{dist-DRPUD4yJ-3gMinGsn.mjs → dist-BNJUEQuz-C9tkfUCE.mjs} +124 -3
- package/dist/dist-BNJUEQuz-C9tkfUCE.mjs.map +1 -0
- package/dist/{dist-CrZVpQSd.mjs → dist-nRx_8hnk.mjs} +6 -8
- package/dist/dist-nRx_8hnk.mjs.map +1 -0
- package/dist/{du-572XNP42-RgaK1Rqq.mjs → du-572XNP42-DCcv0kSr.mjs} +2 -2
- package/dist/{du-572XNP42-RgaK1Rqq.mjs.map → du-572XNP42-DCcv0kSr.mjs.map} +1 -1
- package/dist/{emit-route-manifest-DRcNXHCP-DN1BpGOi.mjs → emit-route-manifest-DRcNXHCP-BkSmGkhV.mjs} +14 -13
- package/dist/{emit-route-manifest-DRcNXHCP-DN1BpGOi.mjs.map → emit-route-manifest-DRcNXHCP-BkSmGkhV.mjs.map} +1 -1
- package/dist/index.mjs +903 -94
- package/dist/index.mjs.map +1 -1
- package/dist/{jq-4XLYLOS5-DNvJFpkY.mjs → jq-4XLYLOS5-CgTVHGto.mjs} +2 -2
- package/dist/{jq-4XLYLOS5-DNvJFpkY.mjs.map → jq-4XLYLOS5-CgTVHGto.mjs.map} +1 -1
- package/dist/{ls-ZJGQER7M-DHpAibRp.mjs → ls-ZJGQER7M-DbHjJAJ5.mjs} +2 -2
- package/dist/{ls-ZJGQER7M-DHpAibRp.mjs.map → ls-ZJGQER7M-DbHjJAJ5.mjs.map} +1 -1
- package/dist/{mistral-R2FX6jgL-C3TQNHh7.mjs → mistral-D7a1LQ-6-CFFRHspK.mjs} +3 -3
- package/dist/{mistral-R2FX6jgL-C3TQNHh7.mjs.map → mistral-D7a1LQ-6-CFFRHspK.mjs.map} +1 -1
- package/dist/{sort-SW2YEO5B-BD_P9Q6n.mjs → sort-SW2YEO5B-DM3UAdjd.mjs} +2 -2
- package/dist/{sort-SW2YEO5B-BD_P9Q6n.mjs.map → sort-SW2YEO5B-DM3UAdjd.mjs.map} +1 -1
- package/dist/{tree-YLD52CNT-C9IR00tM.mjs → tree-YLD52CNT-Bv1j-DWN.mjs} +2 -2
- package/dist/{tree-YLD52CNT-C9IR00tM.mjs.map → tree-YLD52CNT-Bv1j-DWN.mjs.map} +1 -1
- package/dist/{uniq-XSIZR6PB-gU1BpRGX.mjs → uniq-XSIZR6PB-d6Kx_H64.mjs} +2 -2
- package/dist/{uniq-XSIZR6PB-gU1BpRGX.mjs.map → uniq-XSIZR6PB-d6Kx_H64.mjs.map} +1 -1
- package/dist/{wc-LF7NU4LA-DwSj8_V4.mjs → wc-LF7NU4LA-B6PXzeyp.mjs} +2 -2
- package/dist/{wc-LF7NU4LA-DwSj8_V4.mjs.map → wc-LF7NU4LA-B6PXzeyp.mjs.map} +1 -1
- package/dist/{xan-Y6WF3IRG-CAgH4sE_.mjs → xan-Y6WF3IRG-CnmH45qB.mjs} +2 -2
- package/dist/{xan-Y6WF3IRG-CAgH4sE_.mjs.map → xan-Y6WF3IRG-CnmH45qB.mjs.map} +1 -1
- package/package.json +3 -21
- package/dist/dist-CrZVpQSd.mjs.map +0 -1
- package/dist/dist-DRPUD4yJ-3gMinGsn.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1460,7 +1460,7 @@ const propertyKeyTypes = /* @__PURE__ */ new Set([
|
|
|
1460
1460
|
function escapeRegex(str) {
|
|
1461
1461
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1462
1462
|
}
|
|
1463
|
-
function clone(inst, def, params) {
|
|
1463
|
+
function clone$1(inst, def, params) {
|
|
1464
1464
|
const cl = new inst._zod.constr(def ?? inst._zod.def);
|
|
1465
1465
|
if (!def || params?.parent) cl._zod.parent = inst;
|
|
1466
1466
|
return cl;
|
|
@@ -1496,7 +1496,7 @@ function pick(schema, mask) {
|
|
|
1496
1496
|
const currDef = schema._zod.def;
|
|
1497
1497
|
const checks = currDef.checks;
|
|
1498
1498
|
if (checks && checks.length > 0) throw new Error(".pick() cannot be used on object schemas containing refinements");
|
|
1499
|
-
return clone(schema, mergeDefs(schema._zod.def, {
|
|
1499
|
+
return clone$1(schema, mergeDefs(schema._zod.def, {
|
|
1500
1500
|
get shape() {
|
|
1501
1501
|
const newShape = {};
|
|
1502
1502
|
for (const key in mask) {
|
|
@@ -1514,7 +1514,7 @@ function omit(schema, mask) {
|
|
|
1514
1514
|
const currDef = schema._zod.def;
|
|
1515
1515
|
const checks = currDef.checks;
|
|
1516
1516
|
if (checks && checks.length > 0) throw new Error(".omit() cannot be used on object schemas containing refinements");
|
|
1517
|
-
return clone(schema, mergeDefs(schema._zod.def, {
|
|
1517
|
+
return clone$1(schema, mergeDefs(schema._zod.def, {
|
|
1518
1518
|
get shape() {
|
|
1519
1519
|
const newShape = { ...schema._zod.def.shape };
|
|
1520
1520
|
for (const key in mask) {
|
|
@@ -1535,7 +1535,7 @@ function extend(schema, shape) {
|
|
|
1535
1535
|
const existingShape = schema._zod.def.shape;
|
|
1536
1536
|
for (const key in shape) if (Object.getOwnPropertyDescriptor(existingShape, key) !== void 0) throw new Error("Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.");
|
|
1537
1537
|
}
|
|
1538
|
-
return clone(schema, mergeDefs(schema._zod.def, { get shape() {
|
|
1538
|
+
return clone$1(schema, mergeDefs(schema._zod.def, { get shape() {
|
|
1539
1539
|
const _shape = {
|
|
1540
1540
|
...schema._zod.def.shape,
|
|
1541
1541
|
...shape
|
|
@@ -1546,7 +1546,7 @@ function extend(schema, shape) {
|
|
|
1546
1546
|
}
|
|
1547
1547
|
function safeExtend(schema, shape) {
|
|
1548
1548
|
if (!isPlainObject$1(shape)) throw new Error("Invalid input to safeExtend: expected a plain object");
|
|
1549
|
-
return clone(schema, mergeDefs(schema._zod.def, { get shape() {
|
|
1549
|
+
return clone$1(schema, mergeDefs(schema._zod.def, { get shape() {
|
|
1550
1550
|
const _shape = {
|
|
1551
1551
|
...schema._zod.def.shape,
|
|
1552
1552
|
...shape
|
|
@@ -1557,7 +1557,7 @@ function safeExtend(schema, shape) {
|
|
|
1557
1557
|
}
|
|
1558
1558
|
function merge(a, b) {
|
|
1559
1559
|
if (a._zod.def.checks?.length) throw new Error(".merge() cannot be used on object schemas containing refinements. Use .safeExtend() instead.");
|
|
1560
|
-
return clone(a, mergeDefs(a._zod.def, {
|
|
1560
|
+
return clone$1(a, mergeDefs(a._zod.def, {
|
|
1561
1561
|
get shape() {
|
|
1562
1562
|
const _shape = {
|
|
1563
1563
|
...a._zod.def.shape,
|
|
@@ -1575,7 +1575,7 @@ function merge(a, b) {
|
|
|
1575
1575
|
function partial(Class, schema, mask) {
|
|
1576
1576
|
const checks = schema._zod.def.checks;
|
|
1577
1577
|
if (checks && checks.length > 0) throw new Error(".partial() cannot be used on object schemas containing refinements");
|
|
1578
|
-
return clone(schema, mergeDefs(schema._zod.def, {
|
|
1578
|
+
return clone$1(schema, mergeDefs(schema._zod.def, {
|
|
1579
1579
|
get shape() {
|
|
1580
1580
|
const oldShape = schema._zod.def.shape;
|
|
1581
1581
|
const shape = { ...oldShape };
|
|
@@ -1598,7 +1598,7 @@ function partial(Class, schema, mask) {
|
|
|
1598
1598
|
}));
|
|
1599
1599
|
}
|
|
1600
1600
|
function required(Class, schema, mask) {
|
|
1601
|
-
return clone(schema, mergeDefs(schema._zod.def, { get shape() {
|
|
1601
|
+
return clone$1(schema, mergeDefs(schema._zod.def, { get shape() {
|
|
1602
1602
|
const oldShape = schema._zod.def.shape;
|
|
1603
1603
|
const shape = { ...oldShape };
|
|
1604
1604
|
if (mask) for (const key in mask) {
|
|
@@ -5354,7 +5354,7 @@ const ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
|
5354
5354
|
return this.check(...chks);
|
|
5355
5355
|
},
|
|
5356
5356
|
clone(def, params) {
|
|
5357
|
-
return clone(this, def, params);
|
|
5357
|
+
return clone$1(this, def, params);
|
|
5358
5358
|
},
|
|
5359
5359
|
brand() {
|
|
5360
5360
|
return this;
|
|
@@ -6795,6 +6795,126 @@ function listenPortFromPublicUrl(value, fallback) {
|
|
|
6795
6795
|
return fallback;
|
|
6796
6796
|
}
|
|
6797
6797
|
}
|
|
6798
|
+
const serializedRouteManifestEntrySchema = discriminatedUnion("kind", [
|
|
6799
|
+
object({
|
|
6800
|
+
kind: literal("health"),
|
|
6801
|
+
method: literal("GET"),
|
|
6802
|
+
path: literal("/health")
|
|
6803
|
+
}),
|
|
6804
|
+
object({
|
|
6805
|
+
kind: literal("agent"),
|
|
6806
|
+
method: literal("POST"),
|
|
6807
|
+
path: string(),
|
|
6808
|
+
moduleFile: string(),
|
|
6809
|
+
requestSchema: record(string(), unknown()),
|
|
6810
|
+
responseSchema: record(string(), unknown())
|
|
6811
|
+
}),
|
|
6812
|
+
object({
|
|
6813
|
+
kind: literal("agent-sessions-list"),
|
|
6814
|
+
method: literal("GET"),
|
|
6815
|
+
path: string(),
|
|
6816
|
+
agentId: string(),
|
|
6817
|
+
moduleFile: string()
|
|
6818
|
+
}),
|
|
6819
|
+
object({
|
|
6820
|
+
kind: literal("agent-session-detail"),
|
|
6821
|
+
method: literal("GET"),
|
|
6822
|
+
path: string(),
|
|
6823
|
+
agentId: string(),
|
|
6824
|
+
moduleFile: string()
|
|
6825
|
+
}),
|
|
6826
|
+
object({
|
|
6827
|
+
kind: literal("workflow"),
|
|
6828
|
+
method: literal("POST"),
|
|
6829
|
+
path: string(),
|
|
6830
|
+
workflowId: string(),
|
|
6831
|
+
workflowName: string().optional(),
|
|
6832
|
+
moduleFile: string(),
|
|
6833
|
+
requestSchema: record(string(), unknown()),
|
|
6834
|
+
responseSchema: record(string(), unknown())
|
|
6835
|
+
}),
|
|
6836
|
+
object({
|
|
6837
|
+
kind: literal("workflow-runs-list"),
|
|
6838
|
+
method: literal("GET"),
|
|
6839
|
+
path: string(),
|
|
6840
|
+
workflowId: string(),
|
|
6841
|
+
workflowName: string().optional(),
|
|
6842
|
+
moduleFile: string()
|
|
6843
|
+
}),
|
|
6844
|
+
object({
|
|
6845
|
+
kind: literal("workflow-run-detail"),
|
|
6846
|
+
method: literal("GET"),
|
|
6847
|
+
path: string(),
|
|
6848
|
+
workflowId: string(),
|
|
6849
|
+
workflowName: string().optional(),
|
|
6850
|
+
moduleFile: string()
|
|
6851
|
+
}),
|
|
6852
|
+
object({
|
|
6853
|
+
kind: literal("trigger-webhook"),
|
|
6854
|
+
method: literal("POST"),
|
|
6855
|
+
path: string(),
|
|
6856
|
+
attachmentIds: array(string()),
|
|
6857
|
+
moduleFile: string(),
|
|
6858
|
+
requestSchema: record(string(), unknown()),
|
|
6859
|
+
responseSchema: record(string(), unknown())
|
|
6860
|
+
}),
|
|
6861
|
+
object({
|
|
6862
|
+
kind: literal("trigger-poll"),
|
|
6863
|
+
method: literal("POST"),
|
|
6864
|
+
path: string(),
|
|
6865
|
+
attachmentId: string(),
|
|
6866
|
+
moduleFile: string(),
|
|
6867
|
+
schedule: string(),
|
|
6868
|
+
responseSchema: record(string(), unknown())
|
|
6869
|
+
}),
|
|
6870
|
+
object({
|
|
6871
|
+
kind: literal("trigger-poll-group"),
|
|
6872
|
+
method: literal("POST"),
|
|
6873
|
+
path: string(),
|
|
6874
|
+
pollId: string(),
|
|
6875
|
+
attachmentIds: array(string()),
|
|
6876
|
+
moduleFile: string(),
|
|
6877
|
+
schedule: string(),
|
|
6878
|
+
responseSchema: record(string(), unknown())
|
|
6879
|
+
}),
|
|
6880
|
+
object({
|
|
6881
|
+
kind: literal("trigger-runs-list"),
|
|
6882
|
+
method: literal("GET"),
|
|
6883
|
+
path: string(),
|
|
6884
|
+
attachmentId: string(),
|
|
6885
|
+
moduleFile: string()
|
|
6886
|
+
}),
|
|
6887
|
+
object({
|
|
6888
|
+
kind: literal("trigger-run-detail"),
|
|
6889
|
+
method: literal("GET"),
|
|
6890
|
+
path: string(),
|
|
6891
|
+
attachmentId: string(),
|
|
6892
|
+
moduleFile: string()
|
|
6893
|
+
}),
|
|
6894
|
+
object({
|
|
6895
|
+
kind: literal("cron-schedule"),
|
|
6896
|
+
attachmentId: string(),
|
|
6897
|
+
moduleFile: string(),
|
|
6898
|
+
schedule: string()
|
|
6899
|
+
}),
|
|
6900
|
+
object({
|
|
6901
|
+
kind: literal("plugin"),
|
|
6902
|
+
method: _enum([
|
|
6903
|
+
"GET",
|
|
6904
|
+
"POST",
|
|
6905
|
+
"PUT",
|
|
6906
|
+
"PATCH",
|
|
6907
|
+
"DELETE"
|
|
6908
|
+
]),
|
|
6909
|
+
path: string(),
|
|
6910
|
+
plugin: string()
|
|
6911
|
+
})
|
|
6912
|
+
]);
|
|
6913
|
+
object({
|
|
6914
|
+
version: literal(1),
|
|
6915
|
+
entries: array(serializedRouteManifestEntrySchema),
|
|
6916
|
+
integrations: array(string()).optional()
|
|
6917
|
+
});
|
|
6798
6918
|
/** How a credential instance is stored (`credential_instances.auth_kind`). */
|
|
6799
6919
|
const CredentialAuthKindSchema = _enum(["api_key", "oauth_managed"]);
|
|
6800
6920
|
/** Where a credential instance is stored (`credential_instances.scope_type`). */
|
|
@@ -8063,8 +8183,8 @@ const DEFAULT_PROJECT_SETTINGS = {
|
|
|
8063
8183
|
defaultRole: "editor",
|
|
8064
8184
|
invitePermission: "admin"
|
|
8065
8185
|
};
|
|
8066
|
-
const MOCK_STORAGE_KEY$
|
|
8067
|
-
function getBrowserLocalStorage$
|
|
8186
|
+
const MOCK_STORAGE_KEY$4 = "keystroke:mock-project-settings:v1";
|
|
8187
|
+
function getBrowserLocalStorage$4() {
|
|
8068
8188
|
if (typeof globalThis !== "object") return null;
|
|
8069
8189
|
return globalThis.localStorage ?? null;
|
|
8070
8190
|
}
|
|
@@ -8090,10 +8210,10 @@ function mergeProjectSettings(current, patch) {
|
|
|
8090
8210
|
});
|
|
8091
8211
|
}
|
|
8092
8212
|
function readSettingsStore() {
|
|
8093
|
-
const localStorage = getBrowserLocalStorage$
|
|
8213
|
+
const localStorage = getBrowserLocalStorage$4();
|
|
8094
8214
|
if (!localStorage) return {};
|
|
8095
8215
|
try {
|
|
8096
|
-
const raw = localStorage.getItem(MOCK_STORAGE_KEY$
|
|
8216
|
+
const raw = localStorage.getItem(MOCK_STORAGE_KEY$4);
|
|
8097
8217
|
if (!raw) return {};
|
|
8098
8218
|
const parsed = JSON.parse(raw);
|
|
8099
8219
|
if (!parsed || typeof parsed !== "object") return {};
|
|
@@ -8103,10 +8223,10 @@ function readSettingsStore() {
|
|
|
8103
8223
|
}
|
|
8104
8224
|
}
|
|
8105
8225
|
function writeSettingsStore(store) {
|
|
8106
|
-
const localStorage = getBrowserLocalStorage$
|
|
8226
|
+
const localStorage = getBrowserLocalStorage$4();
|
|
8107
8227
|
if (!localStorage) return;
|
|
8108
8228
|
try {
|
|
8109
|
-
localStorage.setItem(MOCK_STORAGE_KEY$
|
|
8229
|
+
localStorage.setItem(MOCK_STORAGE_KEY$4, JSON.stringify(store));
|
|
8110
8230
|
} catch {}
|
|
8111
8231
|
}
|
|
8112
8232
|
function requireProjectId(projectId) {
|
|
@@ -9210,7 +9330,6 @@ const agentSeed = [{
|
|
|
9210
9330
|
updatedAt: "2026-06-02T14:20:00Z",
|
|
9211
9331
|
description: "Triage support requests and draft helpful replies.",
|
|
9212
9332
|
sourcePath: "src/agents/support-agent.ts",
|
|
9213
|
-
mode: "sandbox",
|
|
9214
9333
|
model: "claude-4-sonnet",
|
|
9215
9334
|
toolCount: 4,
|
|
9216
9335
|
credentialCount: 2,
|
|
@@ -9222,7 +9341,6 @@ const agentSeed = [{
|
|
|
9222
9341
|
updatedAt: "2026-06-01T09:15:00Z",
|
|
9223
9342
|
description: "Summarize docs and pull answers from connected sources.",
|
|
9224
9343
|
sourcePath: "src/agents/research-agent.ts",
|
|
9225
|
-
mode: "worker",
|
|
9226
9344
|
model: "claude-4-sonnet",
|
|
9227
9345
|
toolCount: 6,
|
|
9228
9346
|
credentialCount: 3,
|
|
@@ -9235,11 +9353,8 @@ const workflowSeed = [{
|
|
|
9235
9353
|
updatedAt: "2026-06-02T11:05:00Z",
|
|
9236
9354
|
description: "Collect project updates and send a daily summary.",
|
|
9237
9355
|
sourcePath: "src/workflows/daily-digest.ts",
|
|
9238
|
-
trigger: "schedule.daily",
|
|
9239
9356
|
stepCount: 2,
|
|
9240
|
-
|
|
9241
|
-
lastRunAt: "2026-06-02T11:05:00Z",
|
|
9242
|
-
runState: "Succeeded"
|
|
9357
|
+
lastRunAt: "2026-06-02T11:05:00Z"
|
|
9243
9358
|
}, {
|
|
9244
9359
|
id: "workflow-email-triage",
|
|
9245
9360
|
name: "Email Triage",
|
|
@@ -9247,11 +9362,8 @@ const workflowSeed = [{
|
|
|
9247
9362
|
updatedAt: "2026-05-31T16:40:00Z",
|
|
9248
9363
|
description: "Label, prioritize, and draft replies for inbound email.",
|
|
9249
9364
|
sourcePath: "src/workflows/email-triage.ts",
|
|
9250
|
-
trigger: "gmail.new_message",
|
|
9251
9365
|
stepCount: 4,
|
|
9252
|
-
|
|
9253
|
-
lastRunAt: "2026-05-31T16:40:00Z",
|
|
9254
|
-
runState: "Running"
|
|
9366
|
+
lastRunAt: "2026-05-31T16:40:00Z"
|
|
9255
9367
|
}];
|
|
9256
9368
|
const skillSeed = [{
|
|
9257
9369
|
id: "skill-attio-sync",
|
|
@@ -9259,20 +9371,14 @@ const skillSeed = [{
|
|
|
9259
9371
|
projectId: "project_personal_repo",
|
|
9260
9372
|
updatedAt: "2026-06-01T18:05:00Z",
|
|
9261
9373
|
description: "Enrich company and contact records from Attio.",
|
|
9262
|
-
sourcePath: ".agents/skills/attio-sync/SKILL.md"
|
|
9263
|
-
category: "CRM",
|
|
9264
|
-
availability: "Private",
|
|
9265
|
-
lastUsedAt: "2026-06-02T08:30:00Z"
|
|
9374
|
+
sourcePath: ".agents/skills/attio-sync/SKILL.md"
|
|
9266
9375
|
}, {
|
|
9267
9376
|
id: "skill-doc-coauthor",
|
|
9268
9377
|
name: "Doc Co-author",
|
|
9269
9378
|
projectId: "project_personal_repo",
|
|
9270
9379
|
updatedAt: "2026-05-30T10:24:00Z",
|
|
9271
9380
|
description: "Collaborative writing, editing, and version tracking for docs.",
|
|
9272
|
-
sourcePath: ".agents/skills/doc-coauthor/SKILL.md"
|
|
9273
|
-
category: "Writing",
|
|
9274
|
-
availability: "Private",
|
|
9275
|
-
lastUsedAt: "2026-05-29T14:12:00Z"
|
|
9381
|
+
sourcePath: ".agents/skills/doc-coauthor/SKILL.md"
|
|
9276
9382
|
}];
|
|
9277
9383
|
const deploymentSeed = [{
|
|
9278
9384
|
id: "deployment-v002",
|
|
@@ -9283,11 +9389,7 @@ const deploymentSeed = [{
|
|
|
9283
9389
|
deployedBy: "Dallin Bentley",
|
|
9284
9390
|
deployedByEmail: "dallin@keystroke.ai",
|
|
9285
9391
|
createdAt: "2026-04-20T15:44:00Z",
|
|
9286
|
-
active: true
|
|
9287
|
-
summary: "Added support-agent and daily digest workflow.",
|
|
9288
|
-
changedFiles: 4,
|
|
9289
|
-
lineAdditions: 182,
|
|
9290
|
-
lineDeletions: 24
|
|
9392
|
+
active: true
|
|
9291
9393
|
}, {
|
|
9292
9394
|
id: "deployment-v001",
|
|
9293
9395
|
projectId: "project_personal_repo",
|
|
@@ -9297,11 +9399,7 @@ const deploymentSeed = [{
|
|
|
9297
9399
|
deployedBy: "Dallin Bentley",
|
|
9298
9400
|
deployedByEmail: "dallin@keystroke.ai",
|
|
9299
9401
|
createdAt: "2026-04-18T15:44:00Z",
|
|
9300
|
-
active: false
|
|
9301
|
-
summary: "Initial deployed project snapshot.",
|
|
9302
|
-
changedFiles: 2,
|
|
9303
|
-
lineAdditions: 96,
|
|
9304
|
-
lineDeletions: 0
|
|
9402
|
+
active: false
|
|
9305
9403
|
}];
|
|
9306
9404
|
const projectFileSeed = [
|
|
9307
9405
|
{
|
|
@@ -9495,7 +9593,7 @@ function buildRecentResourceSeed() {
|
|
|
9495
9593
|
});
|
|
9496
9594
|
const skillRecents = skillSeed.map((skill, index) => {
|
|
9497
9595
|
const lastModifiedAt = skill.updatedAt;
|
|
9498
|
-
const lastOpenedAt =
|
|
9596
|
+
const lastOpenedAt = hoursBefore(lastModifiedAt, index * 3 + 1);
|
|
9499
9597
|
return {
|
|
9500
9598
|
id: `recent-skill-${skill.id}`,
|
|
9501
9599
|
resourceKind: "skill",
|
|
@@ -9733,6 +9831,57 @@ function createRecentsResource() {
|
|
|
9733
9831
|
}, async () => buildRecentResourceSeed()) };
|
|
9734
9832
|
}
|
|
9735
9833
|
const historyProjectNameById = { project_personal_repo: "Blake's Project" };
|
|
9834
|
+
const MOCK_ACTOR = {
|
|
9835
|
+
userId: "user_blake",
|
|
9836
|
+
name: "Blake Rouse",
|
|
9837
|
+
avatarUrl: null
|
|
9838
|
+
};
|
|
9839
|
+
function buildCompletedUsage(durationMs) {
|
|
9840
|
+
return {
|
|
9841
|
+
runDurationMs: durationMs,
|
|
9842
|
+
lineItems: [
|
|
9843
|
+
{
|
|
9844
|
+
id: "claude-opus",
|
|
9845
|
+
label: "Claude Opus 4.8",
|
|
9846
|
+
amountUsd: .413
|
|
9847
|
+
},
|
|
9848
|
+
{
|
|
9849
|
+
id: "gemini-flash",
|
|
9850
|
+
label: "Gemini Flash 3.5",
|
|
9851
|
+
amountUsd: .001
|
|
9852
|
+
},
|
|
9853
|
+
{
|
|
9854
|
+
id: "daytona",
|
|
9855
|
+
label: "Daytona Sandbox",
|
|
9856
|
+
amountUsd: .188
|
|
9857
|
+
}
|
|
9858
|
+
],
|
|
9859
|
+
totalExcludingDurationUsd: .603
|
|
9860
|
+
};
|
|
9861
|
+
}
|
|
9862
|
+
function buildRunningUsage() {
|
|
9863
|
+
return {
|
|
9864
|
+
runDurationMs: null,
|
|
9865
|
+
lineItems: [],
|
|
9866
|
+
totalExcludingDurationUsd: null
|
|
9867
|
+
};
|
|
9868
|
+
}
|
|
9869
|
+
function buildFailedUsage(durationMs) {
|
|
9870
|
+
if (durationMs == null) return {
|
|
9871
|
+
runDurationMs: null,
|
|
9872
|
+
lineItems: [],
|
|
9873
|
+
totalExcludingDurationUsd: null
|
|
9874
|
+
};
|
|
9875
|
+
return {
|
|
9876
|
+
runDurationMs: durationMs,
|
|
9877
|
+
lineItems: [{
|
|
9878
|
+
id: "claude-opus",
|
|
9879
|
+
label: "Claude Opus 4.8",
|
|
9880
|
+
amountUsd: .021
|
|
9881
|
+
}],
|
|
9882
|
+
totalExcludingDurationUsd: .021
|
|
9883
|
+
};
|
|
9884
|
+
}
|
|
9736
9885
|
function workflowKeyFromId(workflowId) {
|
|
9737
9886
|
const row = workflowSeed.find((workflow) => workflow.id === workflowId);
|
|
9738
9887
|
if (!row?.sourcePath) return workflowId;
|
|
@@ -9754,11 +9903,17 @@ const historyRunSeed = [
|
|
|
9754
9903
|
resourceId: "agent-support",
|
|
9755
9904
|
resourceName: "Support Agent",
|
|
9756
9905
|
status: "completed",
|
|
9906
|
+
triggeredAt: "2026-04-20T15:44:00Z",
|
|
9907
|
+
timeInQueueMs: 85,
|
|
9757
9908
|
startedAt: "2026-04-20T15:44:00Z",
|
|
9758
9909
|
finishedAt: "2026-04-20T15:44:42Z",
|
|
9759
9910
|
durationMs: 42e3,
|
|
9760
9911
|
triggerLabel: "Gateway",
|
|
9761
9912
|
triggerRaw: "gateway",
|
|
9913
|
+
ranAs: MOCK_ACTOR,
|
|
9914
|
+
modelsUsed: ["Claude Opus 4.8", "Gemini Flash 3.5"],
|
|
9915
|
+
otherServicesUsed: ["Slack", "Daytona Sandbox"],
|
|
9916
|
+
totalCostUsd: .603,
|
|
9762
9917
|
messageCount: 8
|
|
9763
9918
|
},
|
|
9764
9919
|
{
|
|
@@ -9771,11 +9926,17 @@ const historyRunSeed = [
|
|
|
9771
9926
|
resourceId: "workflow-daily-digest",
|
|
9772
9927
|
resourceName: "Daily Digest",
|
|
9773
9928
|
status: "running",
|
|
9929
|
+
triggeredAt: "2026-04-20T15:12:00Z",
|
|
9930
|
+
timeInQueueMs: null,
|
|
9774
9931
|
startedAt: "2026-04-20T15:12:00Z",
|
|
9775
9932
|
finishedAt: null,
|
|
9776
9933
|
durationMs: null,
|
|
9777
9934
|
triggerLabel: "Cron",
|
|
9778
9935
|
triggerRaw: "cron",
|
|
9936
|
+
ranAs: MOCK_ACTOR,
|
|
9937
|
+
modelsUsed: [],
|
|
9938
|
+
otherServicesUsed: [],
|
|
9939
|
+
totalCostUsd: null,
|
|
9779
9940
|
stepCount: 1
|
|
9780
9941
|
},
|
|
9781
9942
|
{
|
|
@@ -9788,11 +9949,17 @@ const historyRunSeed = [
|
|
|
9788
9949
|
resourceId: "agent-support",
|
|
9789
9950
|
resourceName: "Support Agent",
|
|
9790
9951
|
status: "failed",
|
|
9952
|
+
triggeredAt: "2026-04-19T18:22:00Z",
|
|
9953
|
+
timeInQueueMs: 45,
|
|
9791
9954
|
startedAt: "2026-04-19T18:22:00Z",
|
|
9792
9955
|
finishedAt: "2026-04-19T18:22:12Z",
|
|
9793
9956
|
durationMs: 12e3,
|
|
9794
9957
|
triggerLabel: "Gateway",
|
|
9795
9958
|
triggerRaw: "gateway",
|
|
9959
|
+
ranAs: MOCK_ACTOR,
|
|
9960
|
+
modelsUsed: ["Claude Opus 4.8"],
|
|
9961
|
+
otherServicesUsed: ["Slack"],
|
|
9962
|
+
totalCostUsd: .021,
|
|
9796
9963
|
messageCount: 2
|
|
9797
9964
|
},
|
|
9798
9965
|
{
|
|
@@ -9805,11 +9972,17 @@ const historyRunSeed = [
|
|
|
9805
9972
|
resourceId: "workflow-email-triage",
|
|
9806
9973
|
resourceName: "Email Triage",
|
|
9807
9974
|
status: "failed",
|
|
9975
|
+
triggeredAt: "2026-05-31T16:40:05Z",
|
|
9976
|
+
timeInQueueMs: 120,
|
|
9808
9977
|
startedAt: "2026-05-31T16:40:05Z",
|
|
9809
9978
|
finishedAt: "2026-05-31T16:40:18Z",
|
|
9810
9979
|
durationMs: 13e3,
|
|
9811
9980
|
triggerLabel: "Webhook",
|
|
9812
9981
|
triggerRaw: "webhook",
|
|
9982
|
+
ranAs: MOCK_ACTOR,
|
|
9983
|
+
modelsUsed: ["Claude Opus 4.8"],
|
|
9984
|
+
otherServicesUsed: ["Gmail"],
|
|
9985
|
+
totalCostUsd: .021,
|
|
9813
9986
|
stepCount: 2
|
|
9814
9987
|
},
|
|
9815
9988
|
{
|
|
@@ -9822,15 +9995,59 @@ const historyRunSeed = [
|
|
|
9822
9995
|
resourceId: "agent-research",
|
|
9823
9996
|
resourceName: "Research Agent",
|
|
9824
9997
|
status: "completed",
|
|
9998
|
+
triggeredAt: "2026-06-01T09:15:00Z",
|
|
9999
|
+
timeInQueueMs: 210,
|
|
9825
10000
|
startedAt: "2026-06-01T09:15:00Z",
|
|
9826
10001
|
finishedAt: "2026-06-01T09:16:24Z",
|
|
9827
10002
|
durationMs: 84e3,
|
|
9828
10003
|
triggerLabel: "API",
|
|
9829
10004
|
triggerRaw: "api",
|
|
10005
|
+
ranAs: MOCK_ACTOR,
|
|
10006
|
+
modelsUsed: ["Claude Opus 4.8"],
|
|
10007
|
+
otherServicesUsed: ["Exa"],
|
|
10008
|
+
totalCostUsd: .603,
|
|
9830
10009
|
messageCount: 12
|
|
9831
10010
|
}
|
|
9832
10011
|
];
|
|
10012
|
+
const historyRunById = Object.fromEntries(historyRunSeed.map((run) => [run.id, run]));
|
|
10013
|
+
/** Resolve a seed run by id so fixtures stay consistent if the seed is reordered. */
|
|
10014
|
+
function runById(id) {
|
|
10015
|
+
const run = historyRunById[id];
|
|
10016
|
+
if (!run) throw new Error(`Unknown history run: ${id}`);
|
|
10017
|
+
return run;
|
|
10018
|
+
}
|
|
10019
|
+
let historyRuns = historyRunSeed.map((run) => ({ ...run }));
|
|
10020
|
+
const historyRunStatusOverrides = /* @__PURE__ */ new Map();
|
|
10021
|
+
function listHistoryRuns() {
|
|
10022
|
+
return historyRuns;
|
|
10023
|
+
}
|
|
10024
|
+
/**
|
|
10025
|
+
* Cancel a running/queued run. Terminal runs are returned unchanged. Updates the
|
|
10026
|
+
* list row and records an override so {@link getHistoryRunDetail} stays in sync.
|
|
10027
|
+
*/
|
|
10028
|
+
function cancelHistoryRun(runId) {
|
|
10029
|
+
const run = historyRuns.find((entry) => entry.id === runId);
|
|
10030
|
+
if (!run) return null;
|
|
10031
|
+
if (run.status !== "running" && run.status !== "pending") return run;
|
|
10032
|
+
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
10033
|
+
const durationMs = run.startedAt ? Math.max(0, new Date(finishedAt).getTime() - new Date(run.startedAt).getTime()) : run.durationMs;
|
|
10034
|
+
const canceled = {
|
|
10035
|
+
...run,
|
|
10036
|
+
status: "canceled",
|
|
10037
|
+
finishedAt,
|
|
10038
|
+
durationMs
|
|
10039
|
+
};
|
|
10040
|
+
historyRuns = historyRuns.map((entry) => entry.id === runId ? canceled : entry);
|
|
10041
|
+
historyRunStatusOverrides.set(runId, {
|
|
10042
|
+
status: "canceled",
|
|
10043
|
+
finishedAt
|
|
10044
|
+
});
|
|
10045
|
+
return canceled;
|
|
10046
|
+
}
|
|
9833
10047
|
function buildSupportAgentTrace(runId, failed) {
|
|
10048
|
+
const run = runById(runId);
|
|
10049
|
+
const startedAt = run.startedAt;
|
|
10050
|
+
const finishedAt = run.finishedAt ?? run.startedAt;
|
|
9834
10051
|
const sessionSpanId = `span-session-${runId}`;
|
|
9835
10052
|
return {
|
|
9836
10053
|
traceId: runId,
|
|
@@ -9838,13 +10055,17 @@ function buildSupportAgentTrace(runId, failed) {
|
|
|
9838
10055
|
triggerType: "gateway",
|
|
9839
10056
|
triggerRunId: `trigger-${runId}`,
|
|
9840
10057
|
agentKey: "support-agent",
|
|
10058
|
+
attachmentId: "attach-slack-incoming",
|
|
9841
10059
|
attachmentKey: "slack-incoming",
|
|
10060
|
+
route: "/agents/support-agent",
|
|
9842
10061
|
sourcePath: "src/triggers/slack-message.ts"
|
|
9843
10062
|
},
|
|
9844
10063
|
gateway: {
|
|
10064
|
+
gatewayAttachmentId: "attach-slack-incoming",
|
|
9845
10065
|
gatewayAttachmentKey: "slack-incoming",
|
|
9846
10066
|
threadId: "C01234567",
|
|
9847
|
-
channelId: "support-escalations"
|
|
10067
|
+
channelId: "support-escalations",
|
|
10068
|
+
mode: "thread"
|
|
9848
10069
|
},
|
|
9849
10070
|
spans: [{
|
|
9850
10071
|
id: sessionSpanId,
|
|
@@ -9854,8 +10075,8 @@ function buildSupportAgentTrace(runId, failed) {
|
|
|
9854
10075
|
refId: runId,
|
|
9855
10076
|
name: "Support Agent",
|
|
9856
10077
|
status: failed ? "error" : "ok",
|
|
9857
|
-
startedAt
|
|
9858
|
-
finishedAt
|
|
10078
|
+
startedAt,
|
|
10079
|
+
finishedAt,
|
|
9859
10080
|
metadata: { messageCount: failed ? 2 : 8 },
|
|
9860
10081
|
error: failed ? { message: "Credential expired" } : null
|
|
9861
10082
|
}, {
|
|
@@ -9866,8 +10087,8 @@ function buildSupportAgentTrace(runId, failed) {
|
|
|
9866
10087
|
refId: `tool-${runId}`,
|
|
9867
10088
|
name: "post_slack_reply",
|
|
9868
10089
|
status: failed ? "error" : "ok",
|
|
9869
|
-
startedAt
|
|
9870
|
-
finishedAt
|
|
10090
|
+
startedAt,
|
|
10091
|
+
finishedAt,
|
|
9871
10092
|
metadata: null,
|
|
9872
10093
|
error: failed ? { message: "oauth_token_expired" } : null
|
|
9873
10094
|
}],
|
|
@@ -9880,7 +10101,7 @@ function buildSupportAgentTrace(runId, failed) {
|
|
|
9880
10101
|
message: failed ? "Received Slack message" : "Session started from gateway thread",
|
|
9881
10102
|
data: null,
|
|
9882
10103
|
source: "system",
|
|
9883
|
-
createdAt:
|
|
10104
|
+
createdAt: startedAt
|
|
9884
10105
|
}, {
|
|
9885
10106
|
id: `log-${runId}-2`,
|
|
9886
10107
|
traceId: runId,
|
|
@@ -9890,7 +10111,7 @@ function buildSupportAgentTrace(runId, failed) {
|
|
|
9890
10111
|
message: failed ? "Credential expired before response could be posted." : "Drafted three support replies.",
|
|
9891
10112
|
data: null,
|
|
9892
10113
|
source: "system",
|
|
9893
|
-
createdAt:
|
|
10114
|
+
createdAt: finishedAt
|
|
9894
10115
|
}]
|
|
9895
10116
|
};
|
|
9896
10117
|
}
|
|
@@ -9901,7 +10122,9 @@ function buildDailyDigestTrace() {
|
|
|
9901
10122
|
triggerType: "cron",
|
|
9902
10123
|
triggerRunId: "trigger-daily-digest-001",
|
|
9903
10124
|
workflowKey: "daily-digest",
|
|
10125
|
+
attachmentId: "attach-schedule-daily",
|
|
9904
10126
|
attachmentKey: "schedule-daily",
|
|
10127
|
+
route: "/workflows/daily-digest",
|
|
9905
10128
|
sourcePath: "src/triggers/daily-digest.ts"
|
|
9906
10129
|
},
|
|
9907
10130
|
gateway: null,
|
|
@@ -9996,7 +10219,9 @@ function buildEmailTriageDetail() {
|
|
|
9996
10219
|
triggerType: "webhook",
|
|
9997
10220
|
triggerRunId: "trigger-email-002",
|
|
9998
10221
|
workflowKey: "email-triage",
|
|
9999
|
-
|
|
10222
|
+
attachmentId: "attach-gmail-new-message",
|
|
10223
|
+
attachmentKey: "gmail-new-message",
|
|
10224
|
+
route: "/workflows/email-triage"
|
|
10000
10225
|
},
|
|
10001
10226
|
gateway: null,
|
|
10002
10227
|
spans: [{
|
|
@@ -10023,7 +10248,9 @@ function buildEmailTriageDetail() {
|
|
|
10023
10248
|
source: "system",
|
|
10024
10249
|
createdAt: "2026-05-31T16:40:18Z"
|
|
10025
10250
|
}]
|
|
10026
|
-
}
|
|
10251
|
+
},
|
|
10252
|
+
ranAs: MOCK_ACTOR,
|
|
10253
|
+
usage: buildFailedUsage(13e3)
|
|
10027
10254
|
};
|
|
10028
10255
|
}
|
|
10029
10256
|
const historyDetailById = {
|
|
@@ -10050,7 +10277,9 @@ const historyDetailById = {
|
|
|
10050
10277
|
role: "assistant",
|
|
10051
10278
|
content: "Drafted reply with prorated credit explanation."
|
|
10052
10279
|
}],
|
|
10053
|
-
trace: buildSupportAgentTrace("run-support-agent-001", false)
|
|
10280
|
+
trace: buildSupportAgentTrace("run-support-agent-001", false),
|
|
10281
|
+
ranAs: MOCK_ACTOR,
|
|
10282
|
+
usage: buildCompletedUsage(42e3)
|
|
10054
10283
|
},
|
|
10055
10284
|
"run-support-agent-000": {
|
|
10056
10285
|
kind: "agent",
|
|
@@ -10072,7 +10301,9 @@ const historyDetailById = {
|
|
|
10072
10301
|
role: "user",
|
|
10073
10302
|
content: "Urgent refund request in #support."
|
|
10074
10303
|
}],
|
|
10075
|
-
trace: buildSupportAgentTrace("run-support-agent-000", true)
|
|
10304
|
+
trace: buildSupportAgentTrace("run-support-agent-000", true),
|
|
10305
|
+
ranAs: MOCK_ACTOR,
|
|
10306
|
+
usage: buildFailedUsage(12e3)
|
|
10076
10307
|
},
|
|
10077
10308
|
"run-daily-digest-001": {
|
|
10078
10309
|
kind: "workflow",
|
|
@@ -10102,7 +10333,9 @@ const historyDetailById = {
|
|
|
10102
10333
|
output: { projects: 3 },
|
|
10103
10334
|
completedAt: "2026-04-20T15:12:45Z"
|
|
10104
10335
|
}],
|
|
10105
|
-
trace: buildDailyDigestTrace()
|
|
10336
|
+
trace: buildDailyDigestTrace(),
|
|
10337
|
+
ranAs: MOCK_ACTOR,
|
|
10338
|
+
usage: buildRunningUsage()
|
|
10106
10339
|
},
|
|
10107
10340
|
"run-email-triage-002": buildEmailTriageDetail(),
|
|
10108
10341
|
"run-research-agent-003": {
|
|
@@ -10130,7 +10363,8 @@ const historyDetailById = {
|
|
|
10130
10363
|
trigger: {
|
|
10131
10364
|
triggerType: "api",
|
|
10132
10365
|
triggerRunId: "trigger-research-003",
|
|
10133
|
-
agentKey: "research-agent"
|
|
10366
|
+
agentKey: "research-agent",
|
|
10367
|
+
route: "/agents/research-agent"
|
|
10134
10368
|
},
|
|
10135
10369
|
gateway: null,
|
|
10136
10370
|
spans: [{
|
|
@@ -10157,11 +10391,34 @@ const historyDetailById = {
|
|
|
10157
10391
|
source: "system",
|
|
10158
10392
|
createdAt: "2026-06-01T09:16:24Z"
|
|
10159
10393
|
}]
|
|
10160
|
-
}
|
|
10394
|
+
},
|
|
10395
|
+
ranAs: MOCK_ACTOR,
|
|
10396
|
+
usage: buildCompletedUsage(84e3)
|
|
10161
10397
|
}
|
|
10162
10398
|
};
|
|
10399
|
+
function applyRunStatusOverride(detail, override) {
|
|
10400
|
+
if (detail.kind === "workflow") return {
|
|
10401
|
+
...detail,
|
|
10402
|
+
run: {
|
|
10403
|
+
...detail.run,
|
|
10404
|
+
status: override.status,
|
|
10405
|
+
finishedAt: override.finishedAt
|
|
10406
|
+
}
|
|
10407
|
+
};
|
|
10408
|
+
return {
|
|
10409
|
+
...detail,
|
|
10410
|
+
session: {
|
|
10411
|
+
...detail.session,
|
|
10412
|
+
status: override.status,
|
|
10413
|
+
updatedAt: override.finishedAt ?? detail.session.updatedAt
|
|
10414
|
+
}
|
|
10415
|
+
};
|
|
10416
|
+
}
|
|
10163
10417
|
function getHistoryRunDetail(runId) {
|
|
10164
|
-
|
|
10418
|
+
const detail = historyDetailById[runId];
|
|
10419
|
+
if (!detail) return null;
|
|
10420
|
+
const override = historyRunStatusOverrides.get(runId);
|
|
10421
|
+
return override ? applyRunStatusOverride(detail, override) : detail;
|
|
10165
10422
|
}
|
|
10166
10423
|
function createHistoryResource() {
|
|
10167
10424
|
return {
|
|
@@ -10170,16 +10427,22 @@ function createHistoryResource() {
|
|
|
10170
10427
|
domain: "history",
|
|
10171
10428
|
method: "list",
|
|
10172
10429
|
plannedEndpoint: "GET /api/orgs/:orgSlug/history"
|
|
10173
|
-
}, async () => [...
|
|
10430
|
+
}, async () => [...listHistoryRuns()].sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime())),
|
|
10174
10431
|
get: mock({
|
|
10175
10432
|
domain: "history",
|
|
10176
10433
|
method: "get",
|
|
10177
10434
|
plannedEndpoint: "GET /api/orgs/:orgSlug/history/:runId"
|
|
10178
|
-
}, async (runId) => getHistoryRunDetail(runId))
|
|
10435
|
+
}, async (runId) => getHistoryRunDetail(runId)),
|
|
10436
|
+
/** Cancel a running/queued run. Returns the updated run (or null if unknown). */
|
|
10437
|
+
cancel: mock({
|
|
10438
|
+
domain: "history",
|
|
10439
|
+
method: "cancel",
|
|
10440
|
+
plannedEndpoint: "POST /api/orgs/:orgSlug/history/:runId/cancel"
|
|
10441
|
+
}, async (runId) => cancelHistoryRun(runId))
|
|
10179
10442
|
};
|
|
10180
10443
|
}
|
|
10181
|
-
const MOCK_STORAGE_KEY$
|
|
10182
|
-
function getBrowserLocalStorage$
|
|
10444
|
+
const MOCK_STORAGE_KEY$3 = "keystroke:mock-organization-sidebar-branding:v1";
|
|
10445
|
+
function getBrowserLocalStorage$3() {
|
|
10183
10446
|
if (typeof globalThis !== "object") return null;
|
|
10184
10447
|
return globalThis.localStorage ?? null;
|
|
10185
10448
|
}
|
|
@@ -10222,10 +10485,10 @@ function mergeOrganizationSidebarBranding(current, patch) {
|
|
|
10222
10485
|
});
|
|
10223
10486
|
}
|
|
10224
10487
|
function readBrandingStore() {
|
|
10225
|
-
const localStorage = getBrowserLocalStorage$
|
|
10488
|
+
const localStorage = getBrowserLocalStorage$3();
|
|
10226
10489
|
if (!localStorage) return {};
|
|
10227
10490
|
try {
|
|
10228
|
-
const raw = localStorage.getItem(MOCK_STORAGE_KEY$
|
|
10491
|
+
const raw = localStorage.getItem(MOCK_STORAGE_KEY$3);
|
|
10229
10492
|
if (!raw) return {};
|
|
10230
10493
|
const parsed = JSON.parse(raw);
|
|
10231
10494
|
if (!parsed || typeof parsed !== "object") return {};
|
|
@@ -10235,10 +10498,10 @@ function readBrandingStore() {
|
|
|
10235
10498
|
}
|
|
10236
10499
|
}
|
|
10237
10500
|
function writeBrandingStore(store) {
|
|
10238
|
-
const localStorage = getBrowserLocalStorage$
|
|
10501
|
+
const localStorage = getBrowserLocalStorage$3();
|
|
10239
10502
|
if (!localStorage) return;
|
|
10240
10503
|
try {
|
|
10241
|
-
localStorage.setItem(MOCK_STORAGE_KEY$
|
|
10504
|
+
localStorage.setItem(MOCK_STORAGE_KEY$3, JSON.stringify(store));
|
|
10242
10505
|
} catch {}
|
|
10243
10506
|
}
|
|
10244
10507
|
function resolveOrganizationId(getActiveOrganizationId) {
|
|
@@ -10272,8 +10535,8 @@ function createOrganizationSidebarBrandingResource(options) {
|
|
|
10272
10535
|
})
|
|
10273
10536
|
};
|
|
10274
10537
|
}
|
|
10275
|
-
const MOCK_STORAGE_KEY$
|
|
10276
|
-
function getBrowserLocalStorage$
|
|
10538
|
+
const MOCK_STORAGE_KEY$2 = "keystroke:mock-user-preferences:v1";
|
|
10539
|
+
function getBrowserLocalStorage$2() {
|
|
10277
10540
|
if (typeof globalThis !== "object") return null;
|
|
10278
10541
|
return globalThis.localStorage ?? null;
|
|
10279
10542
|
}
|
|
@@ -10381,10 +10644,10 @@ function mergeUserPreferences(current, patch) {
|
|
|
10381
10644
|
});
|
|
10382
10645
|
}
|
|
10383
10646
|
function readPreferencesStore() {
|
|
10384
|
-
const localStorage = getBrowserLocalStorage$
|
|
10647
|
+
const localStorage = getBrowserLocalStorage$2();
|
|
10385
10648
|
if (!localStorage) return {};
|
|
10386
10649
|
try {
|
|
10387
|
-
const raw = localStorage.getItem(MOCK_STORAGE_KEY$
|
|
10650
|
+
const raw = localStorage.getItem(MOCK_STORAGE_KEY$2);
|
|
10388
10651
|
if (!raw) return {};
|
|
10389
10652
|
const parsed = JSON.parse(raw);
|
|
10390
10653
|
if (!parsed || typeof parsed !== "object") return {};
|
|
@@ -10395,10 +10658,10 @@ function readPreferencesStore() {
|
|
|
10395
10658
|
}
|
|
10396
10659
|
}
|
|
10397
10660
|
function writePreferencesStore(store) {
|
|
10398
|
-
const localStorage = getBrowserLocalStorage$
|
|
10661
|
+
const localStorage = getBrowserLocalStorage$2();
|
|
10399
10662
|
if (!localStorage) return;
|
|
10400
10663
|
try {
|
|
10401
|
-
localStorage.setItem(MOCK_STORAGE_KEY$
|
|
10664
|
+
localStorage.setItem(MOCK_STORAGE_KEY$2, JSON.stringify(store));
|
|
10402
10665
|
} catch {}
|
|
10403
10666
|
}
|
|
10404
10667
|
function resolveUserId$1(getCurrentUserId) {
|
|
@@ -10433,8 +10696,8 @@ function createUserPreferencesResource(options) {
|
|
|
10433
10696
|
};
|
|
10434
10697
|
}
|
|
10435
10698
|
const DEFAULT_USER_AVATAR = { dataUrl: null };
|
|
10436
|
-
const MOCK_STORAGE_KEY = "keystroke:mock-user-avatar:v1";
|
|
10437
|
-
function getBrowserLocalStorage() {
|
|
10699
|
+
const MOCK_STORAGE_KEY$1 = "keystroke:mock-user-avatar:v1";
|
|
10700
|
+
function getBrowserLocalStorage$1() {
|
|
10438
10701
|
if (typeof globalThis !== "object") return null;
|
|
10439
10702
|
return globalThis.localStorage ?? null;
|
|
10440
10703
|
}
|
|
@@ -10444,10 +10707,10 @@ function normalizeUserAvatar(value) {
|
|
|
10444
10707
|
return { dataUrl: typeof dataUrl === "string" && dataUrl.length > 0 ? dataUrl : null };
|
|
10445
10708
|
}
|
|
10446
10709
|
function readAvatarStore() {
|
|
10447
|
-
const localStorage = getBrowserLocalStorage();
|
|
10710
|
+
const localStorage = getBrowserLocalStorage$1();
|
|
10448
10711
|
if (!localStorage) return {};
|
|
10449
10712
|
try {
|
|
10450
|
-
const raw = localStorage.getItem(MOCK_STORAGE_KEY);
|
|
10713
|
+
const raw = localStorage.getItem(MOCK_STORAGE_KEY$1);
|
|
10451
10714
|
if (!raw) return {};
|
|
10452
10715
|
const parsed = JSON.parse(raw);
|
|
10453
10716
|
if (!parsed || typeof parsed !== "object") return {};
|
|
@@ -10457,10 +10720,10 @@ function readAvatarStore() {
|
|
|
10457
10720
|
}
|
|
10458
10721
|
}
|
|
10459
10722
|
function writeAvatarStore(store) {
|
|
10460
|
-
const localStorage = getBrowserLocalStorage();
|
|
10723
|
+
const localStorage = getBrowserLocalStorage$1();
|
|
10461
10724
|
if (!localStorage) return;
|
|
10462
10725
|
try {
|
|
10463
|
-
localStorage.setItem(MOCK_STORAGE_KEY, JSON.stringify(store));
|
|
10726
|
+
localStorage.setItem(MOCK_STORAGE_KEY$1, JSON.stringify(store));
|
|
10464
10727
|
} catch {}
|
|
10465
10728
|
}
|
|
10466
10729
|
function resolveUserId(getCurrentUserId) {
|
|
@@ -10494,6 +10757,558 @@ function createUserAvatarResource(options) {
|
|
|
10494
10757
|
})
|
|
10495
10758
|
};
|
|
10496
10759
|
}
|
|
10760
|
+
const CHANNEL_PLATFORMS = [
|
|
10761
|
+
{
|
|
10762
|
+
key: "slack",
|
|
10763
|
+
name: "Slack",
|
|
10764
|
+
appLogoId: "slack",
|
|
10765
|
+
fallbackDomain: "slack.com",
|
|
10766
|
+
description: "Connect a Slack workspace so this agent can respond in channels, threads, and DMs.",
|
|
10767
|
+
tagline: "Respond in channels, threads, and DMs.",
|
|
10768
|
+
authKind: "oauth",
|
|
10769
|
+
credentialFields: [],
|
|
10770
|
+
capabilities: {
|
|
10771
|
+
mentions: true,
|
|
10772
|
+
reactions: "full",
|
|
10773
|
+
cards: "full",
|
|
10774
|
+
modals: true,
|
|
10775
|
+
streaming: "native",
|
|
10776
|
+
dms: true
|
|
10777
|
+
},
|
|
10778
|
+
supportedModes: [
|
|
10779
|
+
"mention",
|
|
10780
|
+
"all",
|
|
10781
|
+
"dm"
|
|
10782
|
+
],
|
|
10783
|
+
resourceNoun: {
|
|
10784
|
+
singular: "channel",
|
|
10785
|
+
plural: "channels"
|
|
10786
|
+
},
|
|
10787
|
+
webhookPathHint: "/gateways/slack",
|
|
10788
|
+
supportsChannelDirectory: true,
|
|
10789
|
+
docsUrl: "https://chat-sdk.dev/adapters/official/slack"
|
|
10790
|
+
},
|
|
10791
|
+
{
|
|
10792
|
+
key: "discord",
|
|
10793
|
+
name: "Discord",
|
|
10794
|
+
appLogoId: "discord",
|
|
10795
|
+
fallbackDomain: "discord.com",
|
|
10796
|
+
description: "Connect a Discord application so this agent can respond in servers and channels.",
|
|
10797
|
+
tagline: "Respond in servers and channels.",
|
|
10798
|
+
authKind: "credentials",
|
|
10799
|
+
credentialFields: [
|
|
10800
|
+
{
|
|
10801
|
+
key: "botToken",
|
|
10802
|
+
label: "Bot token",
|
|
10803
|
+
placeholder: "Bot token from the Discord developer portal",
|
|
10804
|
+
helpText: "Bot → Reset Token. Shown only once.",
|
|
10805
|
+
type: "password",
|
|
10806
|
+
required: true
|
|
10807
|
+
},
|
|
10808
|
+
{
|
|
10809
|
+
key: "applicationId",
|
|
10810
|
+
label: "Application ID",
|
|
10811
|
+
placeholder: "Application ID",
|
|
10812
|
+
type: "text",
|
|
10813
|
+
required: true
|
|
10814
|
+
},
|
|
10815
|
+
{
|
|
10816
|
+
key: "publicKey",
|
|
10817
|
+
label: "Public key",
|
|
10818
|
+
placeholder: "Public key",
|
|
10819
|
+
helpText: "General Information → Public Key, used to verify interactions.",
|
|
10820
|
+
type: "text",
|
|
10821
|
+
required: true
|
|
10822
|
+
}
|
|
10823
|
+
],
|
|
10824
|
+
capabilities: {
|
|
10825
|
+
mentions: true,
|
|
10826
|
+
reactions: "full",
|
|
10827
|
+
cards: "full",
|
|
10828
|
+
modals: false,
|
|
10829
|
+
streaming: "post-edit",
|
|
10830
|
+
dms: true
|
|
10831
|
+
},
|
|
10832
|
+
supportedModes: [
|
|
10833
|
+
"mention",
|
|
10834
|
+
"all",
|
|
10835
|
+
"dm"
|
|
10836
|
+
],
|
|
10837
|
+
resourceNoun: {
|
|
10838
|
+
singular: "channel",
|
|
10839
|
+
plural: "channels"
|
|
10840
|
+
},
|
|
10841
|
+
webhookPathHint: "/gateways/discord",
|
|
10842
|
+
supportsChannelDirectory: true,
|
|
10843
|
+
docsUrl: "https://chat-sdk.dev/adapters/official/discord"
|
|
10844
|
+
},
|
|
10845
|
+
{
|
|
10846
|
+
key: "telegram",
|
|
10847
|
+
name: "Telegram",
|
|
10848
|
+
appLogoId: "telegram",
|
|
10849
|
+
fallbackDomain: "telegram.org",
|
|
10850
|
+
description: "Connect a Telegram bot so this agent can respond in chats and groups.",
|
|
10851
|
+
tagline: "Respond in chats and groups.",
|
|
10852
|
+
authKind: "bot-token",
|
|
10853
|
+
credentialFields: [{
|
|
10854
|
+
key: "botToken",
|
|
10855
|
+
label: "Bot token",
|
|
10856
|
+
placeholder: "123456:ABC-DEF…",
|
|
10857
|
+
helpText: "Create a bot with @BotFather and paste its token.",
|
|
10858
|
+
type: "password",
|
|
10859
|
+
required: true
|
|
10860
|
+
}, {
|
|
10861
|
+
key: "botUsername",
|
|
10862
|
+
label: "Bot username",
|
|
10863
|
+
placeholder: "my_agent_bot",
|
|
10864
|
+
type: "text",
|
|
10865
|
+
required: false,
|
|
10866
|
+
prefix: "@"
|
|
10867
|
+
}],
|
|
10868
|
+
capabilities: {
|
|
10869
|
+
mentions: true,
|
|
10870
|
+
reactions: "full",
|
|
10871
|
+
cards: "partial",
|
|
10872
|
+
modals: false,
|
|
10873
|
+
streaming: "drafts",
|
|
10874
|
+
dms: true
|
|
10875
|
+
},
|
|
10876
|
+
supportedModes: [
|
|
10877
|
+
"mention",
|
|
10878
|
+
"all",
|
|
10879
|
+
"dm"
|
|
10880
|
+
],
|
|
10881
|
+
resourceNoun: {
|
|
10882
|
+
singular: "chat",
|
|
10883
|
+
plural: "chats"
|
|
10884
|
+
},
|
|
10885
|
+
webhookPathHint: "/gateways/telegram",
|
|
10886
|
+
supportsChannelDirectory: false,
|
|
10887
|
+
docsUrl: "https://chat-sdk.dev/adapters/official/telegram"
|
|
10888
|
+
},
|
|
10889
|
+
{
|
|
10890
|
+
key: "microsoft-teams",
|
|
10891
|
+
name: "Microsoft Teams",
|
|
10892
|
+
appLogoId: "microsoft-teams",
|
|
10893
|
+
fallbackDomain: "teams.microsoft.com",
|
|
10894
|
+
description: "Connect a Microsoft Teams app so this agent can respond in channels and chats.",
|
|
10895
|
+
tagline: "Respond in channels and chats.",
|
|
10896
|
+
authKind: "credentials",
|
|
10897
|
+
credentialFields: [
|
|
10898
|
+
{
|
|
10899
|
+
key: "appId",
|
|
10900
|
+
label: "App ID",
|
|
10901
|
+
placeholder: "Azure AD application (client) ID",
|
|
10902
|
+
type: "text",
|
|
10903
|
+
required: true
|
|
10904
|
+
},
|
|
10905
|
+
{
|
|
10906
|
+
key: "appPassword",
|
|
10907
|
+
label: "App password",
|
|
10908
|
+
placeholder: "Client secret",
|
|
10909
|
+
type: "password",
|
|
10910
|
+
required: true
|
|
10911
|
+
},
|
|
10912
|
+
{
|
|
10913
|
+
key: "tenantId",
|
|
10914
|
+
label: "Tenant ID",
|
|
10915
|
+
placeholder: "Azure AD tenant ID",
|
|
10916
|
+
type: "text",
|
|
10917
|
+
required: true
|
|
10918
|
+
}
|
|
10919
|
+
],
|
|
10920
|
+
capabilities: {
|
|
10921
|
+
mentions: true,
|
|
10922
|
+
reactions: "read-only",
|
|
10923
|
+
cards: "full",
|
|
10924
|
+
modals: true,
|
|
10925
|
+
streaming: "buffered",
|
|
10926
|
+
dms: true
|
|
10927
|
+
},
|
|
10928
|
+
supportedModes: [
|
|
10929
|
+
"mention",
|
|
10930
|
+
"all",
|
|
10931
|
+
"dm"
|
|
10932
|
+
],
|
|
10933
|
+
resourceNoun: {
|
|
10934
|
+
singular: "channel",
|
|
10935
|
+
plural: "channels"
|
|
10936
|
+
},
|
|
10937
|
+
webhookPathHint: "/gateways/teams",
|
|
10938
|
+
supportsChannelDirectory: true,
|
|
10939
|
+
docsUrl: "https://chat-sdk.dev/adapters/official/teams"
|
|
10940
|
+
},
|
|
10941
|
+
{
|
|
10942
|
+
key: "google-chat",
|
|
10943
|
+
name: "Google Chat",
|
|
10944
|
+
appLogoId: "google-chat",
|
|
10945
|
+
fallbackDomain: "chat.google.com",
|
|
10946
|
+
description: "Connect a Google Chat app so this agent can respond in spaces and direct messages.",
|
|
10947
|
+
tagline: "Respond in spaces and DMs.",
|
|
10948
|
+
authKind: "credentials",
|
|
10949
|
+
credentialFields: [{
|
|
10950
|
+
key: "serviceAccountJson",
|
|
10951
|
+
label: "Service account JSON",
|
|
10952
|
+
placeholder: "Paste the service account key JSON",
|
|
10953
|
+
helpText: "IAM → Service Accounts → Keys → Add key → JSON.",
|
|
10954
|
+
type: "textarea",
|
|
10955
|
+
required: true
|
|
10956
|
+
}, {
|
|
10957
|
+
key: "projectNumber",
|
|
10958
|
+
label: "GCP project number",
|
|
10959
|
+
placeholder: "Project number used to verify webhooks",
|
|
10960
|
+
type: "text",
|
|
10961
|
+
required: true
|
|
10962
|
+
}],
|
|
10963
|
+
capabilities: {
|
|
10964
|
+
mentions: true,
|
|
10965
|
+
reactions: "full",
|
|
10966
|
+
cards: "full",
|
|
10967
|
+
modals: false,
|
|
10968
|
+
streaming: "post-edit",
|
|
10969
|
+
dms: true
|
|
10970
|
+
},
|
|
10971
|
+
supportedModes: [
|
|
10972
|
+
"mention",
|
|
10973
|
+
"all",
|
|
10974
|
+
"dm"
|
|
10975
|
+
],
|
|
10976
|
+
resourceNoun: {
|
|
10977
|
+
singular: "space",
|
|
10978
|
+
plural: "spaces"
|
|
10979
|
+
},
|
|
10980
|
+
webhookPathHint: "/gateways/gchat",
|
|
10981
|
+
supportsChannelDirectory: true,
|
|
10982
|
+
docsUrl: "https://chat-sdk.dev/adapters/official/google-chat"
|
|
10983
|
+
}
|
|
10984
|
+
];
|
|
10985
|
+
function getChannelPlatform(key) {
|
|
10986
|
+
return CHANNEL_PLATFORMS.find((platform) => platform.key === key);
|
|
10987
|
+
}
|
|
10988
|
+
const CHANNEL_DIRECTORY = {
|
|
10989
|
+
slack: [
|
|
10990
|
+
{
|
|
10991
|
+
id: "C0SUPPORT",
|
|
10992
|
+
name: "support",
|
|
10993
|
+
kind: "public",
|
|
10994
|
+
memberCount: 48
|
|
10995
|
+
},
|
|
10996
|
+
{
|
|
10997
|
+
id: "C0GENERAL",
|
|
10998
|
+
name: "general",
|
|
10999
|
+
kind: "public",
|
|
11000
|
+
memberCount: 132
|
|
11001
|
+
},
|
|
11002
|
+
{
|
|
11003
|
+
id: "C0ENG",
|
|
11004
|
+
name: "engineering",
|
|
11005
|
+
kind: "public",
|
|
11006
|
+
memberCount: 27
|
|
11007
|
+
},
|
|
11008
|
+
{
|
|
11009
|
+
id: "C0INCIDENTS",
|
|
11010
|
+
name: "incidents",
|
|
11011
|
+
kind: "private",
|
|
11012
|
+
memberCount: 12
|
|
11013
|
+
},
|
|
11014
|
+
{
|
|
11015
|
+
id: "C0RANDOM",
|
|
11016
|
+
name: "random",
|
|
11017
|
+
kind: "public",
|
|
11018
|
+
memberCount: 118
|
|
11019
|
+
},
|
|
11020
|
+
{
|
|
11021
|
+
id: "C0ARCHIVE",
|
|
11022
|
+
name: "launch-2025",
|
|
11023
|
+
kind: "public",
|
|
11024
|
+
memberCount: 9,
|
|
11025
|
+
isArchived: true
|
|
11026
|
+
}
|
|
11027
|
+
],
|
|
11028
|
+
discord: [
|
|
11029
|
+
{
|
|
11030
|
+
id: "d-general",
|
|
11031
|
+
name: "general",
|
|
11032
|
+
kind: "public",
|
|
11033
|
+
memberCount: 540
|
|
11034
|
+
},
|
|
11035
|
+
{
|
|
11036
|
+
id: "d-help",
|
|
11037
|
+
name: "help",
|
|
11038
|
+
kind: "public",
|
|
11039
|
+
memberCount: 312
|
|
11040
|
+
},
|
|
11041
|
+
{
|
|
11042
|
+
id: "d-dev",
|
|
11043
|
+
name: "dev",
|
|
11044
|
+
kind: "public",
|
|
11045
|
+
memberCount: 76
|
|
11046
|
+
},
|
|
11047
|
+
{
|
|
11048
|
+
id: "d-staff",
|
|
11049
|
+
name: "staff",
|
|
11050
|
+
kind: "private",
|
|
11051
|
+
memberCount: 8
|
|
11052
|
+
}
|
|
11053
|
+
],
|
|
11054
|
+
telegram: [],
|
|
11055
|
+
"microsoft-teams": [
|
|
11056
|
+
{
|
|
11057
|
+
id: "t-general",
|
|
11058
|
+
name: "General",
|
|
11059
|
+
kind: "public",
|
|
11060
|
+
memberCount: 64
|
|
11061
|
+
},
|
|
11062
|
+
{
|
|
11063
|
+
id: "t-support",
|
|
11064
|
+
name: "Customer Support",
|
|
11065
|
+
kind: "public",
|
|
11066
|
+
memberCount: 22
|
|
11067
|
+
},
|
|
11068
|
+
{
|
|
11069
|
+
id: "t-leads",
|
|
11070
|
+
name: "Leadership",
|
|
11071
|
+
kind: "private",
|
|
11072
|
+
memberCount: 6
|
|
11073
|
+
}
|
|
11074
|
+
],
|
|
11075
|
+
"google-chat": [
|
|
11076
|
+
{
|
|
11077
|
+
id: "spaces/AAA-support",
|
|
11078
|
+
name: "Support",
|
|
11079
|
+
kind: "space",
|
|
11080
|
+
memberCount: 31
|
|
11081
|
+
},
|
|
11082
|
+
{
|
|
11083
|
+
id: "spaces/AAA-eng",
|
|
11084
|
+
name: "Engineering",
|
|
11085
|
+
kind: "space",
|
|
11086
|
+
memberCount: 44
|
|
11087
|
+
},
|
|
11088
|
+
{
|
|
11089
|
+
id: "spaces/AAA-ops",
|
|
11090
|
+
name: "Ops On-call",
|
|
11091
|
+
kind: "space",
|
|
11092
|
+
memberCount: 10
|
|
11093
|
+
}
|
|
11094
|
+
]
|
|
11095
|
+
};
|
|
11096
|
+
const MOCK_STORAGE_KEY = "keystroke:mock-channels:v1";
|
|
11097
|
+
function getBrowserLocalStorage() {
|
|
11098
|
+
if (typeof globalThis !== "object") return null;
|
|
11099
|
+
return globalThis.localStorage ?? null;
|
|
11100
|
+
}
|
|
11101
|
+
/** A connected Slack workspace with two bindings, so the panel is reviewable. */
|
|
11102
|
+
function seedStore() {
|
|
11103
|
+
return { "agent-support": [{
|
|
11104
|
+
id: "chan-conn-slack-support",
|
|
11105
|
+
platform: "slack",
|
|
11106
|
+
agentId: "agent-support",
|
|
11107
|
+
accountLabel: "Keystroke HQ",
|
|
11108
|
+
accountId: "T0KEYSTROKE",
|
|
11109
|
+
connectedAt: "2026-05-28T15:30:00Z",
|
|
11110
|
+
bindings: [{
|
|
11111
|
+
id: "chan-bind-support",
|
|
11112
|
+
channelId: "C0SUPPORT",
|
|
11113
|
+
channelName: "support",
|
|
11114
|
+
channelKind: "public",
|
|
11115
|
+
mode: "all",
|
|
11116
|
+
subscribeOnMention: true,
|
|
11117
|
+
createdAt: "2026-05-28T15:31:00Z",
|
|
11118
|
+
updatedAt: "2026-05-28T15:31:00Z"
|
|
11119
|
+
}, {
|
|
11120
|
+
id: "chan-bind-incidents",
|
|
11121
|
+
channelId: "C0INCIDENTS",
|
|
11122
|
+
channelName: "incidents",
|
|
11123
|
+
channelKind: "private",
|
|
11124
|
+
mode: "mention",
|
|
11125
|
+
subscribeOnMention: true,
|
|
11126
|
+
createdAt: "2026-05-29T09:05:00Z",
|
|
11127
|
+
updatedAt: "2026-05-29T09:05:00Z"
|
|
11128
|
+
}]
|
|
11129
|
+
}] };
|
|
11130
|
+
}
|
|
11131
|
+
function readStore() {
|
|
11132
|
+
const localStorage = getBrowserLocalStorage();
|
|
11133
|
+
if (!localStorage) return seedStore();
|
|
11134
|
+
try {
|
|
11135
|
+
const raw = localStorage.getItem(MOCK_STORAGE_KEY);
|
|
11136
|
+
if (!raw) {
|
|
11137
|
+
const seeded = seedStore();
|
|
11138
|
+
localStorage.setItem(MOCK_STORAGE_KEY, JSON.stringify(seeded));
|
|
11139
|
+
return seeded;
|
|
11140
|
+
}
|
|
11141
|
+
const parsed = JSON.parse(raw);
|
|
11142
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
11143
|
+
return parsed;
|
|
11144
|
+
} catch {
|
|
11145
|
+
return {};
|
|
11146
|
+
}
|
|
11147
|
+
}
|
|
11148
|
+
function writeStore(store) {
|
|
11149
|
+
const localStorage = getBrowserLocalStorage();
|
|
11150
|
+
if (!localStorage) return;
|
|
11151
|
+
try {
|
|
11152
|
+
localStorage.setItem(MOCK_STORAGE_KEY, JSON.stringify(store));
|
|
11153
|
+
} catch {}
|
|
11154
|
+
}
|
|
11155
|
+
function newId(prefix) {
|
|
11156
|
+
const cryptoRef = globalThis.crypto;
|
|
11157
|
+
if (cryptoRef?.randomUUID) return `${prefix}-${cryptoRef.randomUUID()}`;
|
|
11158
|
+
return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
11159
|
+
}
|
|
11160
|
+
function requireAgentId(agentId) {
|
|
11161
|
+
const trimmed = agentId.trim();
|
|
11162
|
+
if (!trimmed) throw new Error("Channels require an agent id");
|
|
11163
|
+
return trimmed;
|
|
11164
|
+
}
|
|
11165
|
+
function clone(value) {
|
|
11166
|
+
return JSON.parse(JSON.stringify(value));
|
|
11167
|
+
}
|
|
11168
|
+
function defaultAccountLabel(platform) {
|
|
11169
|
+
const meta = getChannelPlatform(platform);
|
|
11170
|
+
return meta ? `${meta.name} workspace` : platform;
|
|
11171
|
+
}
|
|
11172
|
+
function findConnection(connections, connectionId) {
|
|
11173
|
+
const connection = connections.find((entry) => entry.id === connectionId);
|
|
11174
|
+
if (!connection) throw new Error(`Channel connection not found: ${connectionId}`);
|
|
11175
|
+
return connection;
|
|
11176
|
+
}
|
|
11177
|
+
function toBinding(input, now) {
|
|
11178
|
+
return {
|
|
11179
|
+
id: newId("chan-bind"),
|
|
11180
|
+
channelId: input.channelId,
|
|
11181
|
+
channelName: input.channelName,
|
|
11182
|
+
channelKind: input.channelKind ?? "public",
|
|
11183
|
+
mode: input.mode ?? "mention",
|
|
11184
|
+
subscribeOnMention: input.subscribeOnMention ?? true,
|
|
11185
|
+
createdAt: now,
|
|
11186
|
+
updatedAt: now
|
|
11187
|
+
};
|
|
11188
|
+
}
|
|
11189
|
+
function createChannelsResource() {
|
|
11190
|
+
return {
|
|
11191
|
+
/** The supported-platform catalog (static; backend may derive from the adapter registry). */
|
|
11192
|
+
listPlatforms: mock({
|
|
11193
|
+
domain: "channels",
|
|
11194
|
+
method: "listPlatforms",
|
|
11195
|
+
plannedEndpoint: "GET /api/channels/platforms"
|
|
11196
|
+
}, async () => clone(CHANNEL_PLATFORMS)),
|
|
11197
|
+
/** Connections (with their channel bindings) for one agent. */
|
|
11198
|
+
listForAgent: mock({
|
|
11199
|
+
domain: "channels",
|
|
11200
|
+
method: "listForAgent",
|
|
11201
|
+
plannedEndpoint: "GET /api/agents/:agentId/channels"
|
|
11202
|
+
}, async (agentId) => {
|
|
11203
|
+
const id = requireAgentId(agentId);
|
|
11204
|
+
return clone(readStore()[id] ?? []);
|
|
11205
|
+
}),
|
|
11206
|
+
/**
|
|
11207
|
+
* Channel directory for a platform — the picker source. NET-NEW vs. the
|
|
11208
|
+
* current backend (no channel-list endpoint exists). The runtime team needs
|
|
11209
|
+
* to expose this (e.g. Slack `conversations.list`) for a real picker.
|
|
11210
|
+
*/
|
|
11211
|
+
listChannels: mock({
|
|
11212
|
+
domain: "channels",
|
|
11213
|
+
method: "listChannels",
|
|
11214
|
+
plannedEndpoint: "GET /api/channels/:platform/directory"
|
|
11215
|
+
}, async (platform) => clone(CHANNEL_DIRECTORY[platform] ?? [])),
|
|
11216
|
+
/** Connect a platform for an agent (OAuth install or credential entry), optionally with a first binding. */
|
|
11217
|
+
connect: mock({
|
|
11218
|
+
domain: "channels",
|
|
11219
|
+
method: "connect",
|
|
11220
|
+
plannedEndpoint: "POST /api/agents/:agentId/channels"
|
|
11221
|
+
}, async (input) => {
|
|
11222
|
+
const agentId = requireAgentId(input.agentId);
|
|
11223
|
+
const store = readStore();
|
|
11224
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11225
|
+
const connection = {
|
|
11226
|
+
id: newId("chan-conn"),
|
|
11227
|
+
platform: input.platform,
|
|
11228
|
+
agentId,
|
|
11229
|
+
accountLabel: input.accountLabel ?? defaultAccountLabel(input.platform),
|
|
11230
|
+
accountId: newId("acct").toUpperCase(),
|
|
11231
|
+
connectedAt: now,
|
|
11232
|
+
bindings: input.initialBinding ? [toBinding(input.initialBinding, now)] : []
|
|
11233
|
+
};
|
|
11234
|
+
writeStore({
|
|
11235
|
+
...store,
|
|
11236
|
+
[agentId]: [...store[agentId] ?? [], connection]
|
|
11237
|
+
});
|
|
11238
|
+
return clone(connection);
|
|
11239
|
+
}),
|
|
11240
|
+
/** Add a channel binding to an existing connection. */
|
|
11241
|
+
addBinding: mock({
|
|
11242
|
+
domain: "channels",
|
|
11243
|
+
method: "addBinding",
|
|
11244
|
+
plannedEndpoint: "PUT /gateways/:platform/attachments/:channelId"
|
|
11245
|
+
}, async (input) => {
|
|
11246
|
+
const agentId = requireAgentId(input.agentId);
|
|
11247
|
+
const store = readStore();
|
|
11248
|
+
const connections = store[agentId] ?? [];
|
|
11249
|
+
const connection = findConnection(connections, input.connectionId);
|
|
11250
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11251
|
+
connection.bindings = [...connection.bindings, toBinding(input.binding, now)];
|
|
11252
|
+
writeStore({
|
|
11253
|
+
...store,
|
|
11254
|
+
[agentId]: connections
|
|
11255
|
+
});
|
|
11256
|
+
return clone(connection);
|
|
11257
|
+
}),
|
|
11258
|
+
/** Update a binding's listen mode / subscribe flag. */
|
|
11259
|
+
updateBinding: mock({
|
|
11260
|
+
domain: "channels",
|
|
11261
|
+
method: "updateBinding",
|
|
11262
|
+
plannedEndpoint: "PUT /gateways/:platform/attachments/:channelId"
|
|
11263
|
+
}, async (input) => {
|
|
11264
|
+
const agentId = requireAgentId(input.agentId);
|
|
11265
|
+
const store = readStore();
|
|
11266
|
+
const connections = store[agentId] ?? [];
|
|
11267
|
+
const connection = findConnection(connections, input.connectionId);
|
|
11268
|
+
const binding = connection.bindings.find((entry) => entry.id === input.bindingId);
|
|
11269
|
+
if (!binding) throw new Error(`Channel binding not found: ${input.bindingId}`);
|
|
11270
|
+
if (input.patch.mode !== void 0) binding.mode = input.patch.mode;
|
|
11271
|
+
if (input.patch.subscribeOnMention !== void 0) binding.subscribeOnMention = input.patch.subscribeOnMention;
|
|
11272
|
+
binding.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
11273
|
+
writeStore({
|
|
11274
|
+
...store,
|
|
11275
|
+
[agentId]: connections
|
|
11276
|
+
});
|
|
11277
|
+
return clone(connection);
|
|
11278
|
+
}),
|
|
11279
|
+
/** Remove a channel binding. */
|
|
11280
|
+
removeBinding: mock({
|
|
11281
|
+
domain: "channels",
|
|
11282
|
+
method: "removeBinding",
|
|
11283
|
+
plannedEndpoint: "DELETE /gateways/:platform/attachments/:channelId"
|
|
11284
|
+
}, async (input) => {
|
|
11285
|
+
const agentId = requireAgentId(input.agentId);
|
|
11286
|
+
const store = readStore();
|
|
11287
|
+
const connections = store[agentId] ?? [];
|
|
11288
|
+
const connection = findConnection(connections, input.connectionId);
|
|
11289
|
+
connection.bindings = connection.bindings.filter((entry) => entry.id !== input.bindingId);
|
|
11290
|
+
writeStore({
|
|
11291
|
+
...store,
|
|
11292
|
+
[agentId]: connections
|
|
11293
|
+
});
|
|
11294
|
+
return clone(connection);
|
|
11295
|
+
}),
|
|
11296
|
+
/** Disconnect the agent from a platform (removes the connection + its bindings). */
|
|
11297
|
+
disconnect: mock({
|
|
11298
|
+
domain: "channels",
|
|
11299
|
+
method: "disconnect",
|
|
11300
|
+
plannedEndpoint: "DELETE /api/agents/:agentId/channels/:connectionId"
|
|
11301
|
+
}, async (input) => {
|
|
11302
|
+
const agentId = requireAgentId(input.agentId);
|
|
11303
|
+
const store = readStore();
|
|
11304
|
+
const next = (store[agentId] ?? []).filter((entry) => entry.id !== input.connectionId);
|
|
11305
|
+
writeStore({
|
|
11306
|
+
...store,
|
|
11307
|
+
[agentId]: next
|
|
11308
|
+
});
|
|
11309
|
+
})
|
|
11310
|
+
};
|
|
11311
|
+
}
|
|
10497
11312
|
function createPlatformClient(options) {
|
|
10498
11313
|
const auth = options.auth ?? { type: "none" };
|
|
10499
11314
|
const base = normalizeBaseUrl(options.baseUrl);
|
|
@@ -10530,6 +11345,7 @@ function createPlatformClient(options) {
|
|
|
10530
11345
|
deployments: createDeploymentsResource(),
|
|
10531
11346
|
projectMetrics: createProjectMetricsResource(),
|
|
10532
11347
|
projectFiles: createProjectFilesResource(),
|
|
11348
|
+
channels: createChannelsResource(),
|
|
10533
11349
|
members: createMembersResource(http),
|
|
10534
11350
|
invitations: createInvitationsResource(http),
|
|
10535
11351
|
apiKeys: createApiKeysResource(),
|
|
@@ -12857,11 +13673,8 @@ function registerBuildCommand(program) {
|
|
|
12857
13673
|
program.command("build").description("Build the keystroke project for production").option("--dir <path>", "Project directory", process.cwd()).action(async (options) => {
|
|
12858
13674
|
try {
|
|
12859
13675
|
const root = resolveProjectRoot(options.dir);
|
|
12860
|
-
const { buildApp } = await import("./dist-
|
|
12861
|
-
await buildApp({
|
|
12862
|
-
root,
|
|
12863
|
-
emitRouteManifest: false
|
|
12864
|
-
});
|
|
13676
|
+
const { buildApp } = await import("./dist-nRx_8hnk.mjs");
|
|
13677
|
+
await buildApp({ root });
|
|
12865
13678
|
process.stdout.write(`Built ${root}\n`);
|
|
12866
13679
|
} catch (error) {
|
|
12867
13680
|
const message = error instanceof Error ? error.message : "Build failed";
|
|
@@ -12916,11 +13729,8 @@ async function runDeploy(options) {
|
|
|
12916
13729
|
const config = createCliConfig();
|
|
12917
13730
|
const client = createCliPlatformClient(config);
|
|
12918
13731
|
if (!options.skipBuild) {
|
|
12919
|
-
const { buildApp } = await import("./dist-
|
|
12920
|
-
await buildApp({
|
|
12921
|
-
root,
|
|
12922
|
-
emitRouteManifest: false
|
|
12923
|
-
});
|
|
13732
|
+
const { buildApp } = await import("./dist-nRx_8hnk.mjs");
|
|
13733
|
+
await buildApp({ root });
|
|
12924
13734
|
}
|
|
12925
13735
|
const archive = packProjectArtifact(root);
|
|
12926
13736
|
let active = await client.organizations.getActive();
|
|
@@ -13010,7 +13820,7 @@ function runtimeChildEnv(parentEnv, overrides) {
|
|
|
13010
13820
|
//#region src/project/bootstrap-run.ts
|
|
13011
13821
|
/** Node args + env for `@keystrokehq/build` bootstrap (shared by start + dev). */
|
|
13012
13822
|
async function resolveBootstrapRun(options) {
|
|
13013
|
-
const { resolveRuntimeBuildArtifact } = await import("./dist-
|
|
13823
|
+
const { resolveRuntimeBuildArtifact } = await import("./dist-nRx_8hnk.mjs");
|
|
13014
13824
|
const loader = pathToFileURL(resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/runtime-loader.mjs")).href;
|
|
13015
13825
|
const bootstrap = resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/bootstrap.mjs");
|
|
13016
13826
|
const args = [`--import=${loader}`];
|
|
@@ -13175,7 +13985,7 @@ async function runDev(options) {
|
|
|
13175
13985
|
process.on("SIGINT", shutdown);
|
|
13176
13986
|
process.on("SIGTERM", shutdown);
|
|
13177
13987
|
try {
|
|
13178
|
-
const { watchApp } = await import("./dist-
|
|
13988
|
+
const { watchApp } = await import("./dist-nRx_8hnk.mjs");
|
|
13179
13989
|
await watchApp({
|
|
13180
13990
|
root,
|
|
13181
13991
|
clean: false,
|
|
@@ -13562,11 +14372,10 @@ async function runStart(options) {
|
|
|
13562
14372
|
const apiPort = Number(new URL(serverUrl).port || 80);
|
|
13563
14373
|
const runtimeNodeModules = resolveCliRuntimeNodeModules(resolveCliRoot(import.meta.url));
|
|
13564
14374
|
ensureNativeDeps(runtimeNodeModules);
|
|
13565
|
-
const { buildApp } = await import("./dist-
|
|
14375
|
+
const { buildApp } = await import("./dist-nRx_8hnk.mjs");
|
|
13566
14376
|
await buildApp({
|
|
13567
14377
|
root,
|
|
13568
|
-
clean: false
|
|
13569
|
-
emitRouteManifest: false
|
|
14378
|
+
clean: false
|
|
13570
14379
|
});
|
|
13571
14380
|
const processes = [{
|
|
13572
14381
|
name: "api",
|