openmates 0.15.0-alpha.28 → 0.15.0-alpha.29
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/{chunk-LJQTUMTN.js → chunk-LPJME5IC.js} +724 -119
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +155 -12
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-AXNRPVLE.js";
|
|
5
5
|
|
|
6
6
|
// src/client.ts
|
|
7
|
-
import { createHash as
|
|
7
|
+
import { createHash as createHash7, randomBytes as randomBytes3, randomUUID as randomUUID5 } from "crypto";
|
|
8
8
|
import { arch, platform as platform2, release } from "os";
|
|
9
9
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
10
10
|
import { stdin as stdin2, stdout } from "process";
|
|
@@ -198,9 +198,9 @@ function generateSecureRecoveryKey(length = 24) {
|
|
|
198
198
|
const chars = requiredSets[index];
|
|
199
199
|
result[index] = chars.charAt(randomByte % chars.length);
|
|
200
200
|
}
|
|
201
|
-
const
|
|
201
|
+
const randomBytes6 = cryptoApi.getRandomValues(new Uint8Array(length));
|
|
202
202
|
for (let index = requiredSets.length; index < length; index += 1) {
|
|
203
|
-
result[index] = allChars.charAt(
|
|
203
|
+
result[index] = allChars.charAt(randomBytes6[index] % allChars.length);
|
|
204
204
|
}
|
|
205
205
|
for (let index = result.length - 1; index > 0; index -= 1) {
|
|
206
206
|
const randomByte = cryptoApi.getRandomValues(new Uint8Array(1))[0];
|
|
@@ -699,6 +699,7 @@ import {
|
|
|
699
699
|
rmSync,
|
|
700
700
|
writeFileSync
|
|
701
701
|
} from "fs";
|
|
702
|
+
import { createHash as createHash3 } from "crypto";
|
|
702
703
|
import { homedir as homedir2 } from "os";
|
|
703
704
|
import { join } from "path";
|
|
704
705
|
|
|
@@ -975,6 +976,7 @@ function saveSession(session) {
|
|
|
975
976
|
createdAt: session.createdAt,
|
|
976
977
|
authorizerDeviceName: session.authorizerDeviceName,
|
|
977
978
|
autoLogoutMinutes: session.autoLogoutMinutes,
|
|
979
|
+
activeTeamId: session.activeTeamId ?? null,
|
|
978
980
|
masterKeyStorage: result.type
|
|
979
981
|
};
|
|
980
982
|
if (result.type === "encrypted") {
|
|
@@ -1082,26 +1084,32 @@ function buildSession(onDisk, masterKey, emailEncryptionKey) {
|
|
|
1082
1084
|
userEmailSalt: onDisk.userEmailSalt,
|
|
1083
1085
|
createdAt: onDisk.createdAt,
|
|
1084
1086
|
authorizerDeviceName: onDisk.authorizerDeviceName,
|
|
1085
|
-
autoLogoutMinutes: onDisk.autoLogoutMinutes
|
|
1087
|
+
autoLogoutMinutes: onDisk.autoLogoutMinutes,
|
|
1088
|
+
activeTeamId: onDisk.activeTeamId ?? null
|
|
1086
1089
|
};
|
|
1087
1090
|
}
|
|
1088
1091
|
var SYNC_CACHE_FILE = "sync_cache.json";
|
|
1089
|
-
function
|
|
1090
|
-
|
|
1092
|
+
function syncCacheFile(teamId) {
|
|
1093
|
+
if (!teamId) return SYNC_CACHE_FILE;
|
|
1094
|
+
const digest = createHash3("sha256").update(teamId).digest("hex").slice(0, 32);
|
|
1095
|
+
return `sync_cache.team.${digest}.json`;
|
|
1096
|
+
}
|
|
1097
|
+
function saveSyncCache(cache, teamId) {
|
|
1098
|
+
const filePath = join(ensureStateDir(), syncCacheFile(teamId));
|
|
1091
1099
|
writeJsonFile(filePath, cache);
|
|
1092
1100
|
}
|
|
1093
|
-
function loadSyncCache() {
|
|
1094
|
-
const filePath = join(ensureStateDir(),
|
|
1101
|
+
function loadSyncCache(teamId) {
|
|
1102
|
+
const filePath = join(ensureStateDir(), syncCacheFile(teamId));
|
|
1095
1103
|
return readJsonFile(filePath);
|
|
1096
1104
|
}
|
|
1097
|
-
function clearSyncCache() {
|
|
1098
|
-
const filePath = join(ensureStateDir(),
|
|
1105
|
+
function clearSyncCache(teamId) {
|
|
1106
|
+
const filePath = join(ensureStateDir(), syncCacheFile(teamId));
|
|
1099
1107
|
if (existsSync2(filePath)) {
|
|
1100
1108
|
rmSync(filePath);
|
|
1101
1109
|
}
|
|
1102
1110
|
}
|
|
1103
|
-
function isSyncCacheFresh(maxAgeMs = 3e5) {
|
|
1104
|
-
const cache = loadSyncCache();
|
|
1111
|
+
function isSyncCacheFresh(maxAgeMs = 3e5, teamId) {
|
|
1112
|
+
const cache = loadSyncCache(teamId);
|
|
1105
1113
|
if (!cache) return false;
|
|
1106
1114
|
return Date.now() - cache.syncedAt < maxAgeMs;
|
|
1107
1115
|
}
|
|
@@ -2297,7 +2305,7 @@ function escapeRegExp(s) {
|
|
|
2297
2305
|
}
|
|
2298
2306
|
|
|
2299
2307
|
// src/embedCreator.ts
|
|
2300
|
-
import { randomUUID, createHash as
|
|
2308
|
+
import { randomUUID, createHash as createHash4, randomBytes, webcrypto as webcrypto3 } from "crypto";
|
|
2301
2309
|
import { encode as toonEncode } from "@toon-format/toon";
|
|
2302
2310
|
var cryptoApi3 = webcrypto3;
|
|
2303
2311
|
var AES_GCM_IV_LENGTH3 = 12;
|
|
@@ -2351,7 +2359,7 @@ function generateEmbedKey() {
|
|
|
2351
2359
|
return new Uint8Array(randomBytes(32));
|
|
2352
2360
|
}
|
|
2353
2361
|
function computeSHA256(content) {
|
|
2354
|
-
return
|
|
2362
|
+
return createHash4("sha256").update(content).digest("hex");
|
|
2355
2363
|
}
|
|
2356
2364
|
function toonEncodeContent(data) {
|
|
2357
2365
|
try {
|
|
@@ -2546,7 +2554,7 @@ function buildEmbedShareUrl(origin, embedId, blob) {
|
|
|
2546
2554
|
}
|
|
2547
2555
|
|
|
2548
2556
|
// src/connectedAccountImport.ts
|
|
2549
|
-
import { createHash as
|
|
2557
|
+
import { createHash as createHash5, randomUUID as randomUUID2, webcrypto as webcrypto5 } from "crypto";
|
|
2550
2558
|
var TRANSFER_PREFIX = "OMCA1.";
|
|
2551
2559
|
var SUPPORTED_KDF_ITERATIONS = 1e5;
|
|
2552
2560
|
async function decryptConnectedAccountCliTransferPayload(encryptedPayload, passcode) {
|
|
@@ -2691,7 +2699,7 @@ function defaultProviderLabel(providerId) {
|
|
|
2691
2699
|
return providerId === "google_calendar" ? "Google Calendar" : "Connected account";
|
|
2692
2700
|
}
|
|
2693
2701
|
function sha256Hex2(value) {
|
|
2694
|
-
return
|
|
2702
|
+
return createHash5("sha256").update(value).digest("hex");
|
|
2695
2703
|
}
|
|
2696
2704
|
function base64UrlToBytes2(value) {
|
|
2697
2705
|
return base64ToBytes(value.replace(/-/g, "+").replace(/_/g, "/"));
|
|
@@ -3540,7 +3548,7 @@ function stripTimer(job) {
|
|
|
3540
3548
|
}
|
|
3541
3549
|
|
|
3542
3550
|
// src/tasksCli.ts
|
|
3543
|
-
import { createHash as
|
|
3551
|
+
import { createHash as createHash6, createHmac, hkdfSync, randomBytes as randomBytes2, randomUUID as randomUUID4 } from "crypto";
|
|
3544
3552
|
var TASK_STATUSES2 = ["backlog", "todo", "in_progress", "blocked", "done"];
|
|
3545
3553
|
var DEFAULT_STANDALONE_PREFIX = "TASK";
|
|
3546
3554
|
var PRIORITY_LEVELS = ["none", "low", "medium", "high", "urgent"];
|
|
@@ -3722,7 +3730,7 @@ function workflowProjectionToTask(record) {
|
|
|
3722
3730
|
}
|
|
3723
3731
|
function workflowProjectionShortId(record) {
|
|
3724
3732
|
const stableId = record.workflow_run_id || record.task_id;
|
|
3725
|
-
return `WF-${
|
|
3733
|
+
return `WF-${createHash6("sha256").update(stableId).digest("hex").slice(0, 6).toUpperCase()}`;
|
|
3726
3734
|
}
|
|
3727
3735
|
async function decryptUserTasks(records, masterKey) {
|
|
3728
3736
|
const output = [];
|
|
@@ -3828,7 +3836,7 @@ function parseStringArray(value) {
|
|
|
3828
3836
|
function deriveShortId(record) {
|
|
3829
3837
|
const prefix = record.short_id_prefix || DEFAULT_STANDALONE_PREFIX;
|
|
3830
3838
|
const source = record.task_id || `${record.created_at ?? ""}-${record.position ?? ""}`;
|
|
3831
|
-
const digest =
|
|
3839
|
+
const digest = createHash6("sha256").update(source).digest("hex").slice(0, 4).toUpperCase();
|
|
3832
3840
|
return `${prefix}-${parseInt(digest, 16) % 1e4}`;
|
|
3833
3841
|
}
|
|
3834
3842
|
function nowSeconds() {
|
|
@@ -3968,7 +3976,8 @@ function buildTurnTokenRefsRequestPayload(params) {
|
|
|
3968
3976
|
return {
|
|
3969
3977
|
chat_id: params.chatId,
|
|
3970
3978
|
message_id: params.messageId,
|
|
3971
|
-
refs: params.refs.map((ref) => ({ ...ref }))
|
|
3979
|
+
refs: params.refs.map((ref) => ({ ...ref })),
|
|
3980
|
+
...params.teamId ? { team_id: params.teamId } : {}
|
|
3972
3981
|
};
|
|
3973
3982
|
}
|
|
3974
3983
|
function categoryFromMemoryKey(key) {
|
|
@@ -4752,6 +4761,189 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
4752
4761
|
hasSession() {
|
|
4753
4762
|
return this.session !== null;
|
|
4754
4763
|
}
|
|
4764
|
+
getActiveTeamId() {
|
|
4765
|
+
return this.session?.activeTeamId ?? null;
|
|
4766
|
+
}
|
|
4767
|
+
setActiveTeamId(teamId) {
|
|
4768
|
+
const session = this.requireSession();
|
|
4769
|
+
this.session = { ...session, activeTeamId: teamId };
|
|
4770
|
+
saveSession(this.session);
|
|
4771
|
+
}
|
|
4772
|
+
resolveTeamContext(options = {}) {
|
|
4773
|
+
if (options.personal) return null;
|
|
4774
|
+
if (options.teamId !== void 0) return options.teamId;
|
|
4775
|
+
return this.getActiveTeamId();
|
|
4776
|
+
}
|
|
4777
|
+
appendTeamQuery(path, options = {}) {
|
|
4778
|
+
const teamId = this.resolveTeamContext(options);
|
|
4779
|
+
if (!teamId) return path;
|
|
4780
|
+
const separator2 = path.includes("?") ? "&" : "?";
|
|
4781
|
+
return `${path}${separator2}team_id=${encodeURIComponent(teamId)}`;
|
|
4782
|
+
}
|
|
4783
|
+
async listTeams() {
|
|
4784
|
+
this.requireSession();
|
|
4785
|
+
const response = await this.http.get("/v1/teams", this.getCliRequestHeaders());
|
|
4786
|
+
if (!response.ok) throw new Error(`Team list failed with HTTP ${response.status}`);
|
|
4787
|
+
return response.data.teams ?? [];
|
|
4788
|
+
}
|
|
4789
|
+
async createTeam(input) {
|
|
4790
|
+
this.requireSession();
|
|
4791
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
4792
|
+
const teamKeyBytes = randomBytes3(32);
|
|
4793
|
+
const payload = {
|
|
4794
|
+
team_id: input.teamId ?? randomUUID5(),
|
|
4795
|
+
slug: input.slug ?? void 0,
|
|
4796
|
+
encrypted_name: input.encryptedName ?? await encryptWithAesGcmCombined(input.name ?? "Untitled team", teamKeyBytes),
|
|
4797
|
+
encrypted_description: input.encryptedDescription ?? (input.description ? await encryptWithAesGcmCombined(input.description, teamKeyBytes) : void 0),
|
|
4798
|
+
encrypted_team_key: input.encryptedTeamKey ?? await encryptBytesWithAesGcm(teamKeyBytes, this.getMasterKeyBytes()),
|
|
4799
|
+
encrypted_zero_balance: input.encryptedZeroBalance ?? await encryptWithAesGcmCombined("0", teamKeyBytes),
|
|
4800
|
+
created_at: input.createdAt ?? now,
|
|
4801
|
+
updated_at: input.createdAt ?? now
|
|
4802
|
+
};
|
|
4803
|
+
const response = await this.http.post("/v1/teams", payload, this.getCliRequestHeaders());
|
|
4804
|
+
if (!response.ok || !response.data.team) throw new Error(`Team create failed with HTTP ${response.status}`);
|
|
4805
|
+
return response.data.team;
|
|
4806
|
+
}
|
|
4807
|
+
async getTeam(teamId) {
|
|
4808
|
+
this.requireSession();
|
|
4809
|
+
const response = await this.http.get(`/v1/teams/${encodeURIComponent(teamId)}`, this.getCliRequestHeaders());
|
|
4810
|
+
if (!response.ok || !response.data.team) throw new Error(`Team get failed with HTTP ${response.status}`);
|
|
4811
|
+
return response.data.team;
|
|
4812
|
+
}
|
|
4813
|
+
async updateTeam(teamId, input) {
|
|
4814
|
+
this.requireSession();
|
|
4815
|
+
const response = await this.http.patch(`/v1/teams/${encodeURIComponent(teamId)}`, {
|
|
4816
|
+
updated_at: input.updated_at ?? Math.floor(Date.now() / 1e3),
|
|
4817
|
+
...input
|
|
4818
|
+
}, this.getCliRequestHeaders());
|
|
4819
|
+
if (!response.ok || !response.data.team) throw new Error(`Team update failed with HTTP ${response.status}`);
|
|
4820
|
+
return response.data.team;
|
|
4821
|
+
}
|
|
4822
|
+
async deleteTeam(teamId) {
|
|
4823
|
+
this.requireSession();
|
|
4824
|
+
const response = await this.http.delete(`/v1/teams/${encodeURIComponent(teamId)}`, void 0, this.getCliRequestHeaders());
|
|
4825
|
+
if (!response.ok) throw new Error(`Team delete failed with HTTP ${response.status}`);
|
|
4826
|
+
return { success: response.data.success === true };
|
|
4827
|
+
}
|
|
4828
|
+
async createTeamInvite(teamId, input) {
|
|
4829
|
+
this.requireSession();
|
|
4830
|
+
const response = await this.http.post(`/v1/teams/${encodeURIComponent(teamId)}/invites`, {
|
|
4831
|
+
invite_id: input.invite_id ?? randomUUID5(),
|
|
4832
|
+
created_at: input.created_at ?? Math.floor(Date.now() / 1e3),
|
|
4833
|
+
...input
|
|
4834
|
+
}, this.getCliRequestHeaders());
|
|
4835
|
+
if (!response.ok || !response.data.invite) throw new Error(`Team invite create failed with HTTP ${response.status}`);
|
|
4836
|
+
return response.data.invite;
|
|
4837
|
+
}
|
|
4838
|
+
async acceptTeamInvite(inviteId) {
|
|
4839
|
+
this.requireSession();
|
|
4840
|
+
const response = await this.http.post(`/v1/teams/invites/${encodeURIComponent(inviteId)}/accept`, { accepted_at: Math.floor(Date.now() / 1e3) }, this.getCliRequestHeaders());
|
|
4841
|
+
if (!response.ok || !response.data.access_request) throw new Error(`Team invite accept failed with HTTP ${response.status}`);
|
|
4842
|
+
return { access_request: response.data.access_request, status_label: response.data.status_label };
|
|
4843
|
+
}
|
|
4844
|
+
async declineTeamInvite(inviteId) {
|
|
4845
|
+
this.requireSession();
|
|
4846
|
+
const response = await this.http.post(`/v1/teams/invites/${encodeURIComponent(inviteId)}/decline`, { declined_at: Math.floor(Date.now() / 1e3) }, this.getCliRequestHeaders());
|
|
4847
|
+
if (!response.ok) throw new Error(`Team invite decline failed with HTTP ${response.status}`);
|
|
4848
|
+
return { success: response.data.success === true };
|
|
4849
|
+
}
|
|
4850
|
+
async listTeamAccessRequests(teamId, status) {
|
|
4851
|
+
this.requireSession();
|
|
4852
|
+
const query = status && status !== "all" ? `?status=${encodeURIComponent(status)}` : status === "all" ? "?status=" : "";
|
|
4853
|
+
const response = await this.http.get(`/v1/teams/${encodeURIComponent(teamId)}/access-requests${query}`, this.getCliRequestHeaders());
|
|
4854
|
+
if (!response.ok) throw new Error(`Team access requests failed with HTTP ${response.status}`);
|
|
4855
|
+
return response.data.access_requests ?? [];
|
|
4856
|
+
}
|
|
4857
|
+
async approveTeamAccessRequest(teamId, accessRequestId, encryptedTeamKey) {
|
|
4858
|
+
this.requireSession();
|
|
4859
|
+
const response = await this.http.post(`/v1/teams/${encodeURIComponent(teamId)}/access-requests/${encodeURIComponent(accessRequestId)}/approve`, { encrypted_team_key: encryptedTeamKey, approved_at: Math.floor(Date.now() / 1e3) }, this.getCliRequestHeaders());
|
|
4860
|
+
if (!response.ok || !response.data.membership) throw new Error(`Team access approval failed with HTTP ${response.status}`);
|
|
4861
|
+
return response.data.membership;
|
|
4862
|
+
}
|
|
4863
|
+
async rejectTeamAccessRequest(teamId, accessRequestId) {
|
|
4864
|
+
this.requireSession();
|
|
4865
|
+
const response = await this.http.post(`/v1/teams/${encodeURIComponent(teamId)}/access-requests/${encodeURIComponent(accessRequestId)}/reject`, { rejected_at: Math.floor(Date.now() / 1e3) }, this.getCliRequestHeaders());
|
|
4866
|
+
if (!response.ok) throw new Error(`Team access rejection failed with HTTP ${response.status}`);
|
|
4867
|
+
return { success: response.data.success === true };
|
|
4868
|
+
}
|
|
4869
|
+
async exportTeamData(teamId, input = {}) {
|
|
4870
|
+
this.requireSession();
|
|
4871
|
+
const response = await this.http.post(`/v1/teams/${encodeURIComponent(teamId)}/export`, {
|
|
4872
|
+
export_id: input.export_id,
|
|
4873
|
+
created_at: input.created_at ?? Math.floor(Date.now() / 1e3)
|
|
4874
|
+
}, this.getCliRequestHeaders());
|
|
4875
|
+
if (!response.ok) throw new Error(`Team export failed with HTTP ${response.status}`);
|
|
4876
|
+
return response.data;
|
|
4877
|
+
}
|
|
4878
|
+
async getTeamExport(teamId, exportId) {
|
|
4879
|
+
this.requireSession();
|
|
4880
|
+
const response = await this.http.get(`/v1/teams/${encodeURIComponent(teamId)}/export/${encodeURIComponent(exportId)}`, this.getCliRequestHeaders());
|
|
4881
|
+
if (!response.ok) throw new Error(`Team export download failed with HTTP ${response.status}`);
|
|
4882
|
+
return response.data;
|
|
4883
|
+
}
|
|
4884
|
+
async importTeamData(destinationTeamId, artifact) {
|
|
4885
|
+
this.requireSession();
|
|
4886
|
+
const response = await this.http.post("/v1/teams/import", {
|
|
4887
|
+
destination_team_id: destinationTeamId,
|
|
4888
|
+
artifact,
|
|
4889
|
+
imported_at: Math.floor(Date.now() / 1e3)
|
|
4890
|
+
}, this.getCliRequestHeaders());
|
|
4891
|
+
if (!response.ok) throw new Error(`Team import failed with HTTP ${response.status}`);
|
|
4892
|
+
return response.data;
|
|
4893
|
+
}
|
|
4894
|
+
async updateTeamMemberRole(teamId, memberUserId, role) {
|
|
4895
|
+
this.requireSession();
|
|
4896
|
+
const response = await this.http.patch(`/v1/teams/${encodeURIComponent(teamId)}/members/${encodeURIComponent(memberUserId)}`, { role, updated_at: Math.floor(Date.now() / 1e3) }, this.getCliRequestHeaders());
|
|
4897
|
+
if (!response.ok || !response.data.membership) throw new Error(`Team member update failed with HTTP ${response.status}`);
|
|
4898
|
+
return response.data.membership;
|
|
4899
|
+
}
|
|
4900
|
+
async removeTeamMember(teamId, memberUserId) {
|
|
4901
|
+
this.requireSession();
|
|
4902
|
+
const response = await this.http.post(`/v1/teams/${encodeURIComponent(teamId)}/members/${encodeURIComponent(memberUserId)}/remove`, { removed_at: Math.floor(Date.now() / 1e3) }, this.getCliRequestHeaders());
|
|
4903
|
+
if (!response.ok) throw new Error(`Team member remove failed with HTTP ${response.status}`);
|
|
4904
|
+
return { success: response.data.success === true };
|
|
4905
|
+
}
|
|
4906
|
+
async getTeamBilling(teamId) {
|
|
4907
|
+
this.requireSession();
|
|
4908
|
+
const response = await this.http.get(`/v1/teams/${encodeURIComponent(teamId)}/billing`, this.getCliRequestHeaders());
|
|
4909
|
+
if (!response.ok || !response.data.billing) throw new Error(`Team billing failed with HTTP ${response.status}`);
|
|
4910
|
+
return response.data.billing;
|
|
4911
|
+
}
|
|
4912
|
+
async addTeamCredits(teamId, input) {
|
|
4913
|
+
this.requireSession();
|
|
4914
|
+
const response = await this.http.post(`/v1/teams/${encodeURIComponent(teamId)}/billing/credits`, {
|
|
4915
|
+
event_id: input.event_id ?? randomUUID5(),
|
|
4916
|
+
encrypted_balance: input.encrypted_balance ?? String(input.encryptedBalance ?? "0"),
|
|
4917
|
+
occurred_at: input.occurred_at ?? Math.floor(Date.now() / 1e3),
|
|
4918
|
+
...input
|
|
4919
|
+
}, this.getCliRequestHeaders());
|
|
4920
|
+
if (!response.ok || !response.data.billing) throw new Error(`Team credit add failed with HTTP ${response.status}`);
|
|
4921
|
+
return response.data.billing;
|
|
4922
|
+
}
|
|
4923
|
+
async listTeamUsage(teamId, memberUserId) {
|
|
4924
|
+
this.requireSession();
|
|
4925
|
+
const query = memberUserId ? `?member_user_id=${encodeURIComponent(memberUserId)}` : "";
|
|
4926
|
+
const response = await this.http.get(`/v1/teams/${encodeURIComponent(teamId)}/billing/usage${query}`, this.getCliRequestHeaders());
|
|
4927
|
+
if (!response.ok) throw new Error(`Team usage failed with HTTP ${response.status}`);
|
|
4928
|
+
return response.data.usage ?? [];
|
|
4929
|
+
}
|
|
4930
|
+
async moveWorkspaceToTeam(workspaceType, objectId, teamId) {
|
|
4931
|
+
this.requireSession();
|
|
4932
|
+
const routeByType = {
|
|
4933
|
+
chat: `/v1/chats/${encodeURIComponent(objectId)}/move`,
|
|
4934
|
+
project: `/v1/projects/${encodeURIComponent(objectId)}/move`,
|
|
4935
|
+
task: `/v1/user-tasks/${encodeURIComponent(objectId)}/move`,
|
|
4936
|
+
plan: `/v1/user-plans/${encodeURIComponent(objectId)}/move`,
|
|
4937
|
+
workflow: `/v1/workflows/${encodeURIComponent(objectId)}/move`
|
|
4938
|
+
};
|
|
4939
|
+
const response = await this.http.post(
|
|
4940
|
+
routeByType[workspaceType],
|
|
4941
|
+
{ team_id: teamId, confirmed: true, moved_at: Math.floor(Date.now() / 1e3) },
|
|
4942
|
+
this.getCliRequestHeaders()
|
|
4943
|
+
);
|
|
4944
|
+
if (!response.ok) throw new Error(`${workspaceType} move failed with HTTP ${response.status}`);
|
|
4945
|
+
return response.data;
|
|
4946
|
+
}
|
|
4755
4947
|
async getAnonymousFreeUsageStatus() {
|
|
4756
4948
|
const response = await this.http.get("/v1/anonymous/free-usage/status");
|
|
4757
4949
|
if (response.status === 404) {
|
|
@@ -4910,7 +5102,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
4910
5102
|
if (!userId) {
|
|
4911
5103
|
throw new Error("Could not resolve current user id for local connected-account connector.");
|
|
4912
5104
|
}
|
|
4913
|
-
const { createHash:
|
|
5105
|
+
const { createHash: createHash11 } = await import("crypto");
|
|
4914
5106
|
const accountId = randomUUID5();
|
|
4915
5107
|
const masterKey = this.getMasterKeyBytes();
|
|
4916
5108
|
const encryptLocalConnectorValue = async (value) => {
|
|
@@ -4919,9 +5111,9 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
4919
5111
|
};
|
|
4920
5112
|
const payload = {
|
|
4921
5113
|
id: accountId,
|
|
4922
|
-
hashed_user_id:
|
|
5114
|
+
hashed_user_id: createHash11("sha256").update(userId).digest("hex"),
|
|
4923
5115
|
encrypted_provider_type: await encryptLocalConnectorValue(input.provider_id),
|
|
4924
|
-
provider_type_hash:
|
|
5116
|
+
provider_type_hash: createHash11("sha256").update(input.provider_id).digest("hex"),
|
|
4925
5117
|
encrypted_account_label: await encryptLocalConnectorValue(input.label),
|
|
4926
5118
|
encrypted_capabilities: await encryptLocalConnectorValue(input.capabilities),
|
|
4927
5119
|
encrypted_app_permissions: await encryptLocalConnectorValue({
|
|
@@ -5363,7 +5555,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5363
5555
|
return decryptBytesWithAesGcm(encryptedChatKey, masterKey);
|
|
5364
5556
|
}
|
|
5365
5557
|
getMasterWrapperEncryptedChatKey(cache, chatId) {
|
|
5366
|
-
const hashedChatId =
|
|
5558
|
+
const hashedChatId = createHash7("sha256").update(chatId).digest("hex");
|
|
5367
5559
|
const wrapper = (cache?.chatKeyWrappers ?? []).find(
|
|
5368
5560
|
(entry) => entry.key_type === "master" && entry.hashed_chat_id === hashedChatId && typeof entry.encrypted_chat_key === "string"
|
|
5369
5561
|
);
|
|
@@ -5398,8 +5590,8 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5398
5590
|
mateName: category ? MATE_NAMES[category] ?? null : null
|
|
5399
5591
|
};
|
|
5400
5592
|
}
|
|
5401
|
-
async listChats(limit = 10, page = 1) {
|
|
5402
|
-
const cache = await this.ensureSynced();
|
|
5593
|
+
async listChats(limit = 10, page = 1, options = {}) {
|
|
5594
|
+
const cache = await this.ensureSynced(false, [], options);
|
|
5403
5595
|
const masterKey = this.getMasterKeyBytes();
|
|
5404
5596
|
const total = cache.chats.length;
|
|
5405
5597
|
const offset = (page - 1) * limit;
|
|
@@ -5567,8 +5759,8 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5567
5759
|
preview
|
|
5568
5760
|
};
|
|
5569
5761
|
}
|
|
5570
|
-
async searchChats(query) {
|
|
5571
|
-
const cache = await this.ensureSynced();
|
|
5762
|
+
async searchChats(query, options = {}) {
|
|
5763
|
+
const cache = await this.ensureSynced(false, [], options);
|
|
5572
5764
|
const masterKey = this.getMasterKeyBytes();
|
|
5573
5765
|
const normalized = query.trim().toLowerCase();
|
|
5574
5766
|
const results = [];
|
|
@@ -5595,8 +5787,8 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5595
5787
|
*
|
|
5596
5788
|
* @param query Full UUID, 8-char short ID, or chat title.
|
|
5597
5789
|
*/
|
|
5598
|
-
async getChatMessages(query) {
|
|
5599
|
-
const cache = await this.ensureSynced(true);
|
|
5790
|
+
async getChatMessages(query, options = {}) {
|
|
5791
|
+
const cache = await this.ensureSynced(true, [], options);
|
|
5600
5792
|
const masterKey = this.getMasterKeyBytes();
|
|
5601
5793
|
const normalized = query.trim().toLowerCase();
|
|
5602
5794
|
let found;
|
|
@@ -5658,8 +5850,8 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5658
5850
|
);
|
|
5659
5851
|
let msgEmbedIds = [];
|
|
5660
5852
|
if (clientMsgId && cache.embeds.length > 0) {
|
|
5661
|
-
const { createHash:
|
|
5662
|
-
const hashed =
|
|
5853
|
+
const { createHash: createHash11 } = await import("crypto");
|
|
5854
|
+
const hashed = createHash11("sha256").update(clientMsgId).digest("hex");
|
|
5663
5855
|
msgEmbedIds = cache.embeds.filter(
|
|
5664
5856
|
(e) => e.hashed_message_id === hashed && // Only include parent embeds (no parent_embed_id).
|
|
5665
5857
|
// Child embeds inherit the parent's key and are loaded
|
|
@@ -5706,8 +5898,8 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5706
5898
|
);
|
|
5707
5899
|
}
|
|
5708
5900
|
const embedId = String(embed.embed_id ?? embed.id ?? "");
|
|
5709
|
-
const { createHash:
|
|
5710
|
-
const hashedEmbedId =
|
|
5901
|
+
const { createHash: createHash11 } = await import("crypto");
|
|
5902
|
+
const hashedEmbedId = createHash11("sha256").update(embedId).digest("hex");
|
|
5711
5903
|
const embedKeyBytes = await this.resolveEmbedKey(
|
|
5712
5904
|
cache,
|
|
5713
5905
|
masterKey,
|
|
@@ -5815,7 +6007,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5815
6007
|
async resolveEmbedKey(cache, masterKey, embed, embedId, hashedEmbedId, visited = /* @__PURE__ */ new Set()) {
|
|
5816
6008
|
if (visited.has(embedId)) return null;
|
|
5817
6009
|
visited.add(embedId);
|
|
5818
|
-
const { createHash:
|
|
6010
|
+
const { createHash: createHash11 } = await import("crypto");
|
|
5819
6011
|
const masterKeyEntry = cache.embedKeys.find(
|
|
5820
6012
|
(ek) => ek.hashed_embed_id === hashedEmbedId && String(ek.key_type) === "master"
|
|
5821
6013
|
);
|
|
@@ -5832,7 +6024,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5832
6024
|
if (chatKeyEntry && typeof chatKeyEntry.encrypted_embed_key === "string") {
|
|
5833
6025
|
const hashedChatId = String(chatKeyEntry.hashed_chat_id ?? "");
|
|
5834
6026
|
const owningChat = cache.chats.find((c) => {
|
|
5835
|
-
const chatHash =
|
|
6027
|
+
const chatHash = createHash11("sha256").update(String(c.details.id ?? "")).digest("hex");
|
|
5836
6028
|
return chatHash === hashedChatId;
|
|
5837
6029
|
});
|
|
5838
6030
|
if (owningChat) {
|
|
@@ -5861,7 +6053,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5861
6053
|
const parentFullId = String(
|
|
5862
6054
|
parentEmbed2.embed_id ?? parentEmbed2.id ?? ""
|
|
5863
6055
|
);
|
|
5864
|
-
const parentHashedId =
|
|
6056
|
+
const parentHashedId = createHash11("sha256").update(parentFullId).digest("hex");
|
|
5865
6057
|
const parentKey = await this.resolveEmbedKey(
|
|
5866
6058
|
cache,
|
|
5867
6059
|
masterKey,
|
|
@@ -5879,8 +6071,9 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5879
6071
|
* Resolve a short chat ID (first 8 chars) or partial title to a full UUID.
|
|
5880
6072
|
* Accepts full UUIDs unchanged. Returns undefined if no match found.
|
|
5881
6073
|
*/
|
|
5882
|
-
async resolveFullChatId(idOrShort) {
|
|
5883
|
-
const
|
|
6074
|
+
async resolveFullChatId(idOrShort, options = {}) {
|
|
6075
|
+
const teamId = this.resolveTeamContext(options);
|
|
6076
|
+
const staleCache = loadSyncCache(teamId);
|
|
5884
6077
|
const lower = idOrShort.toLowerCase();
|
|
5885
6078
|
if (staleCache) {
|
|
5886
6079
|
for (const chat of staleCache.chats) {
|
|
@@ -5891,7 +6084,9 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5891
6084
|
}
|
|
5892
6085
|
const freshCache = await this.ensureSynced(
|
|
5893
6086
|
/* forceRefresh */
|
|
5894
|
-
true
|
|
6087
|
+
true,
|
|
6088
|
+
[],
|
|
6089
|
+
{ teamId }
|
|
5895
6090
|
);
|
|
5896
6091
|
for (const chat of freshCache.chats) {
|
|
5897
6092
|
const fullId = String(chat.details.id ?? "");
|
|
@@ -5911,8 +6106,8 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5911
6106
|
*
|
|
5912
6107
|
* @param limit Maximum number of suggestions to return (default: 10)
|
|
5913
6108
|
*/
|
|
5914
|
-
async listNewChatSuggestions(limit = 10) {
|
|
5915
|
-
const cache = await this.ensureSynced();
|
|
6109
|
+
async listNewChatSuggestions(limit = 10, options = {}) {
|
|
6110
|
+
const cache = await this.ensureSynced(false, [], options);
|
|
5916
6111
|
const masterKey = this.getMasterKeyBytes();
|
|
5917
6112
|
const rawSuggestions = cache.newChatSuggestions ?? [];
|
|
5918
6113
|
const results = [];
|
|
@@ -5942,12 +6137,13 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5942
6137
|
*
|
|
5943
6138
|
* Mirrors: chat_actions_store.ts / FollowUpSuggestions.svelte (web app)
|
|
5944
6139
|
*/
|
|
5945
|
-
async getChatFollowUpSuggestions(chatId) {
|
|
5946
|
-
const
|
|
6140
|
+
async getChatFollowUpSuggestions(chatId, options = {}) {
|
|
6141
|
+
const teamId = this.resolveTeamContext(options);
|
|
6142
|
+
const cachedMatch = loadSyncCache(teamId)?.chats.find(
|
|
5947
6143
|
(c) => String(c.details.id ?? "") === chatId || String(c.details.id ?? "").startsWith(chatId)
|
|
5948
6144
|
);
|
|
5949
6145
|
const refreshChatId = String(cachedMatch?.details.id ?? chatId);
|
|
5950
|
-
const cache = await this.ensureSynced(true, [refreshChatId]);
|
|
6146
|
+
const cache = await this.ensureSynced(true, [refreshChatId], { teamId });
|
|
5951
6147
|
const masterKey = this.getMasterKeyBytes();
|
|
5952
6148
|
const found = cache.chats.find(
|
|
5953
6149
|
(c) => String(c.details.id ?? "") === chatId || String(c.details.id ?? "").startsWith(chatId)
|
|
@@ -5972,11 +6168,12 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5972
6168
|
return [];
|
|
5973
6169
|
}
|
|
5974
6170
|
async sendMessage(params) {
|
|
6171
|
+
const teamId = this.resolveTeamContext({ teamId: params.teamId, personal: params.personal });
|
|
5975
6172
|
let chatId;
|
|
5976
6173
|
if (!params.chatId) {
|
|
5977
6174
|
chatId = randomUUID5();
|
|
5978
6175
|
} else if (params.chatId.length < 36) {
|
|
5979
|
-
const resolved = await this.resolveFullChatId(params.chatId);
|
|
6176
|
+
const resolved = await this.resolveFullChatId(params.chatId, { teamId });
|
|
5980
6177
|
if (!resolved) {
|
|
5981
6178
|
throw new Error(
|
|
5982
6179
|
`Chat not found for '${params.chatId}'. Use a full UUID or the first 8 characters of an existing chat ID.`
|
|
@@ -5990,7 +6187,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
5990
6187
|
let memoryMetadataKeys = [];
|
|
5991
6188
|
if (!params.incognito) {
|
|
5992
6189
|
try {
|
|
5993
|
-
availableMemories = await this.listMemories();
|
|
6190
|
+
availableMemories = await this.listMemories({ teamId });
|
|
5994
6191
|
memoryMetadataKeys = [
|
|
5995
6192
|
...new Set(
|
|
5996
6193
|
availableMemories.filter((memory) => memory.app_id && memory.item_type).map((memory) => `${memory.app_id}-${memory.item_type}`)
|
|
@@ -6014,14 +6211,15 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
6014
6211
|
const messageId = randomUUID5();
|
|
6015
6212
|
const createdAt = Math.floor(Date.now() / 1e3);
|
|
6016
6213
|
const isNewChat = !params.chatId;
|
|
6017
|
-
ws.send("set_active_chat", { chat_id: chatId });
|
|
6214
|
+
ws.send("set_active_chat", { chat_id: chatId, ...teamId ? { team_id: teamId } : {} });
|
|
6018
6215
|
const connectedAccountDirectory = buildConnectedAccountDirectoryPayload(
|
|
6019
6216
|
params.connectedAccountDirectory
|
|
6020
6217
|
);
|
|
6021
6218
|
const connectedAccountTokenRefs = params.connectedAccountTokenRefInputs?.length ? await this.createTurnTokenRefs({
|
|
6022
6219
|
chatId,
|
|
6023
6220
|
messageId,
|
|
6024
|
-
refs: params.connectedAccountTokenRefInputs
|
|
6221
|
+
refs: params.connectedAccountTokenRefInputs,
|
|
6222
|
+
teamId
|
|
6025
6223
|
}) : [];
|
|
6026
6224
|
assertNoConnectedAccountSecretLeak(connectedAccountTokenRefs);
|
|
6027
6225
|
const piiMappings = params.piiMappings ?? [];
|
|
@@ -6043,7 +6241,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
6043
6241
|
masterKey
|
|
6044
6242
|
);
|
|
6045
6243
|
} else {
|
|
6046
|
-
const cache = loadSyncCache() ?? await this.ensureSynced();
|
|
6244
|
+
const cache = loadSyncCache(teamId) ?? await this.ensureSynced(false, [], { teamId });
|
|
6047
6245
|
const chat = cache.chats.find(
|
|
6048
6246
|
(c) => String(c.details.id ?? "") === chatId || String(c.details.id ?? "").startsWith(chatId)
|
|
6049
6247
|
);
|
|
@@ -6063,6 +6261,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
6063
6261
|
const clientCapabilities = explicitTasksAppSkill ? [] : ["task_update_jobs"];
|
|
6064
6262
|
const messagePayload = {
|
|
6065
6263
|
chat_id: chatId,
|
|
6264
|
+
...teamId ? { team_id: teamId } : {},
|
|
6066
6265
|
client_capabilities: clientCapabilities,
|
|
6067
6266
|
is_incognito: Boolean(params.incognito),
|
|
6068
6267
|
message: {
|
|
@@ -6188,6 +6387,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
6188
6387
|
const preflightPayload = {
|
|
6189
6388
|
protocol_version: protocolVersion,
|
|
6190
6389
|
chat_id: chatId,
|
|
6390
|
+
...teamId ? { team_id: teamId } : {},
|
|
6191
6391
|
turn_id: turnId,
|
|
6192
6392
|
message_id: messageId,
|
|
6193
6393
|
chat_key_version: chatKeyVersion,
|
|
@@ -6624,7 +6824,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
6624
6824
|
} catch (error) {
|
|
6625
6825
|
if (error instanceof WebSocketProtocolError) {
|
|
6626
6826
|
if (error.code === "version_conflict") {
|
|
6627
|
-
const latestCache = await this.ensureSynced(true, [chatId]);
|
|
6827
|
+
const latestCache = await this.ensureSynced(true, [chatId], { teamId });
|
|
6628
6828
|
const latestChat = latestCache.chats.find(
|
|
6629
6829
|
(chat) => String(chat.details.id ?? "") === chatId
|
|
6630
6830
|
);
|
|
@@ -6657,6 +6857,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
6657
6857
|
await this.persistPostProcessingMetadata({
|
|
6658
6858
|
ws,
|
|
6659
6859
|
chatId,
|
|
6860
|
+
teamId,
|
|
6660
6861
|
chatKeyBytes,
|
|
6661
6862
|
followUpSuggestions: resp.followUpSuggestions,
|
|
6662
6863
|
newChatSuggestions: resp.newChatSuggestions,
|
|
@@ -6673,7 +6874,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
6673
6874
|
});
|
|
6674
6875
|
pendingTaskUpdateJobs = pendingTaskUpdateJobs.filter((job) => !persistedTaskJobIds.has(job.job_id));
|
|
6675
6876
|
await persistTaskEventSystemMessages(taskEvents);
|
|
6676
|
-
clearSyncCache();
|
|
6877
|
+
clearSyncCache(teamId);
|
|
6677
6878
|
}
|
|
6678
6879
|
} finally {
|
|
6679
6880
|
ws.close();
|
|
@@ -7099,6 +7300,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
7099
7300
|
if (!encryptedFollowUps && encryptedNewChatSuggestions.length === 0) return;
|
|
7100
7301
|
await params.ws.sendAsync("update_post_processing_metadata", {
|
|
7101
7302
|
chat_id: params.chatId,
|
|
7303
|
+
...params.teamId ? { team_id: params.teamId } : {},
|
|
7102
7304
|
encrypted_follow_up_suggestions: encryptedFollowUps,
|
|
7103
7305
|
encrypted_new_chat_suggestions: encryptedNewChatSuggestions,
|
|
7104
7306
|
encrypted_chat_key: params.encryptedChatKey ?? ""
|
|
@@ -7118,10 +7320,11 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
7118
7320
|
* Mirrors the web app's sendDeleteChatImpl in chatSyncServiceSenders.ts.
|
|
7119
7321
|
* Sends a delete_chat WebSocket message and waits for the server ack.
|
|
7120
7322
|
*/
|
|
7121
|
-
async deleteChat(chatIdInput) {
|
|
7323
|
+
async deleteChat(chatIdInput, options = {}) {
|
|
7324
|
+
const teamId = this.resolveTeamContext(options);
|
|
7122
7325
|
let chatId;
|
|
7123
7326
|
if (chatIdInput.length < 36) {
|
|
7124
|
-
const resolved = await this.resolveFullChatId(chatIdInput);
|
|
7327
|
+
const resolved = await this.resolveFullChatId(chatIdInput, { teamId });
|
|
7125
7328
|
if (!resolved) {
|
|
7126
7329
|
throw new Error(
|
|
7127
7330
|
`Chat not found for '${chatIdInput}'. Use a full UUID or the first 8 characters of an existing chat ID.`
|
|
@@ -7133,7 +7336,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
7133
7336
|
}
|
|
7134
7337
|
const { ws } = await this.openWsClient();
|
|
7135
7338
|
try {
|
|
7136
|
-
ws.send("delete_chat", { chatId });
|
|
7339
|
+
ws.send("delete_chat", { chatId, chat_id: chatId, ...teamId ? { team_id: teamId } : {} });
|
|
7137
7340
|
await ws.waitForMessage(
|
|
7138
7341
|
"chat_deleted",
|
|
7139
7342
|
(payload) => {
|
|
@@ -7145,6 +7348,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
7145
7348
|
} finally {
|
|
7146
7349
|
ws.close();
|
|
7147
7350
|
}
|
|
7351
|
+
clearSyncCache(teamId);
|
|
7148
7352
|
}
|
|
7149
7353
|
// -------------------------------------------------------------------------
|
|
7150
7354
|
// Apps
|
|
@@ -7429,10 +7633,10 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
7429
7633
|
// -------------------------------------------------------------------------
|
|
7430
7634
|
// Workflows
|
|
7431
7635
|
// -------------------------------------------------------------------------
|
|
7432
|
-
async listWorkflows() {
|
|
7636
|
+
async listWorkflows(options = {}) {
|
|
7433
7637
|
this.requireSession();
|
|
7434
7638
|
const response = await this.http.get(
|
|
7435
|
-
"/v1/workflows",
|
|
7639
|
+
this.appendTeamQuery("/v1/workflows", options),
|
|
7436
7640
|
this.getCliRequestHeaders()
|
|
7437
7641
|
);
|
|
7438
7642
|
if (!response.ok) {
|
|
@@ -7497,10 +7701,10 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
7497
7701
|
}
|
|
7498
7702
|
return { workflow: createLike.data.workflow, validation: createLike.data.validation };
|
|
7499
7703
|
}
|
|
7500
|
-
async getWorkflow(workflowId) {
|
|
7704
|
+
async getWorkflow(workflowId, options = {}) {
|
|
7501
7705
|
this.requireSession();
|
|
7502
7706
|
const response = await this.http.get(
|
|
7503
|
-
`/v1/workflows/${encodeURIComponent(workflowId)}`,
|
|
7707
|
+
this.appendTeamQuery(`/v1/workflows/${encodeURIComponent(workflowId)}`, options),
|
|
7504
7708
|
this.getCliRequestHeaders()
|
|
7505
7709
|
);
|
|
7506
7710
|
if (!response.ok || !response.data.workflow) {
|
|
@@ -7875,6 +8079,8 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
7875
8079
|
if (filters.priority !== void 0) params.set("priority", String(filters.priority));
|
|
7876
8080
|
const limit = filters.limit;
|
|
7877
8081
|
if (Number.isSafeInteger(limit) && limit !== void 0 && limit > 0) params.set("limit", String(limit));
|
|
8082
|
+
const teamId = this.resolveTeamContext({ teamId: filters.teamId, personal: filters.personal });
|
|
8083
|
+
if (teamId) params.set("team_id", teamId);
|
|
7878
8084
|
const query = params.toString();
|
|
7879
8085
|
const response = await this.http.get(
|
|
7880
8086
|
`/v1/user-tasks${query ? `?${query}` : ""}`,
|
|
@@ -7995,6 +8201,8 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
7995
8201
|
if (filters.chatId) params.set("chat_id", filters.chatId);
|
|
7996
8202
|
if (filters.projectId) params.set("project_id", filters.projectId);
|
|
7997
8203
|
if (filters.activeOnly !== void 0) params.set("active_only", String(filters.activeOnly));
|
|
8204
|
+
const teamId = this.resolveTeamContext({ teamId: filters.teamId, personal: filters.personal });
|
|
8205
|
+
if (teamId) params.set("team_id", teamId);
|
|
7998
8206
|
const query = params.toString();
|
|
7999
8207
|
const response = await this.http.get(
|
|
8000
8208
|
`/v1/user-plans${query ? `?${query}` : ""}`,
|
|
@@ -8643,9 +8851,18 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
8643
8851
|
* List all memories for the current user, decrypted.
|
|
8644
8852
|
* Fetches from the GDPR export endpoint and decrypts each entry with the master key.
|
|
8645
8853
|
*/
|
|
8646
|
-
async
|
|
8854
|
+
async sdkGetMemories(teamId) {
|
|
8855
|
+
const response = await this.http.get(
|
|
8856
|
+
`/v1/sdk/memories?team_id=${encodeURIComponent(teamId)}`,
|
|
8857
|
+
this.getCliRequestHeaders()
|
|
8858
|
+
);
|
|
8859
|
+
if (!response.ok) throw new Error(`Team memory list failed with HTTP ${response.status}`);
|
|
8860
|
+
return response.data.memories ?? [];
|
|
8861
|
+
}
|
|
8862
|
+
async listMemories(options = {}) {
|
|
8647
8863
|
const masterKey = this.getMasterKeyBytes();
|
|
8648
|
-
const
|
|
8864
|
+
const teamId = this.resolveTeamContext(options);
|
|
8865
|
+
const data = teamId ? { data: { app_settings_memories: await this.sdkGetMemories(teamId) } } : await this.settingsGet(
|
|
8649
8866
|
"/v1/settings/export-account-data?include_usage=false&include_invoices=false"
|
|
8650
8867
|
);
|
|
8651
8868
|
const rawEntries = data.data?.app_settings_memories ?? [];
|
|
@@ -8711,17 +8928,20 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
8711
8928
|
itemType: params.itemType,
|
|
8712
8929
|
itemValue: params.itemValue,
|
|
8713
8930
|
entryId: params.entryId,
|
|
8714
|
-
itemVersion: params.currentVersion + 1
|
|
8931
|
+
itemVersion: params.currentVersion + 1,
|
|
8932
|
+
teamId: params.teamId,
|
|
8933
|
+
personal: params.personal
|
|
8715
8934
|
});
|
|
8716
8935
|
}
|
|
8717
8936
|
/**
|
|
8718
8937
|
* Delete a memory entry. Sends `delete_app_settings_memories_entry` over
|
|
8719
8938
|
* WebSocket. The server deletes from Directus and broadcasts to all devices.
|
|
8720
8939
|
*/
|
|
8721
|
-
async deleteMemory(entryId) {
|
|
8940
|
+
async deleteMemory(entryId, options = {}) {
|
|
8722
8941
|
const { ws } = await this.openWsClient();
|
|
8723
8942
|
try {
|
|
8724
|
-
|
|
8943
|
+
const teamId = this.resolveTeamContext(options);
|
|
8944
|
+
ws.send("delete_app_settings_memories_entry", { entry_id: entryId, ...teamId ? { team_id: teamId } : {} });
|
|
8725
8945
|
await ws.waitForMessage(
|
|
8726
8946
|
"app_settings_memories_entry_deleted",
|
|
8727
8947
|
(payload) => {
|
|
@@ -8774,6 +8994,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
8774
8994
|
}
|
|
8775
8995
|
const entryId = params.entryId ?? randomUUID5();
|
|
8776
8996
|
const now = Math.floor(Date.now() / 1e3);
|
|
8997
|
+
const teamId = this.resolveTeamContext({ teamId: params.teamId, personal: params.personal });
|
|
8777
8998
|
const hashedKey = hashItemKey(params.appId, params.itemType);
|
|
8778
8999
|
const plaintextPayload = {
|
|
8779
9000
|
...params.itemValue,
|
|
@@ -8788,6 +9009,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
8788
9009
|
const { ws } = await this.openWsClient();
|
|
8789
9010
|
try {
|
|
8790
9011
|
ws.send("store_app_settings_memories_entry", {
|
|
9012
|
+
...teamId ? { team_id: teamId } : {},
|
|
8791
9013
|
entry: {
|
|
8792
9014
|
id: entryId,
|
|
8793
9015
|
app_id: params.appId,
|
|
@@ -8797,7 +9019,8 @@ Required: ${schema.required.join(", ")}`
|
|
|
8797
9019
|
encrypted_app_key: "",
|
|
8798
9020
|
created_at: now,
|
|
8799
9021
|
updated_at: now,
|
|
8800
|
-
item_version: params.itemVersion
|
|
9022
|
+
item_version: params.itemVersion,
|
|
9023
|
+
...teamId ? { team_id: teamId } : {}
|
|
8801
9024
|
}
|
|
8802
9025
|
});
|
|
8803
9026
|
await ws.waitForMessage(
|
|
@@ -8927,7 +9150,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
8927
9150
|
const session = this.requireSession();
|
|
8928
9151
|
const masterKey = base64ToBytes(session.masterKeyExportedB64);
|
|
8929
9152
|
const cache = await this.ensureSynced();
|
|
8930
|
-
const { createHash:
|
|
9153
|
+
const { createHash: createHash11 } = await import("crypto");
|
|
8931
9154
|
const embed = cache.embeds.find(
|
|
8932
9155
|
(e) => String(e.embed_id ?? "").startsWith(embedIdOrShort) || String(e.id ?? "").startsWith(embedIdOrShort)
|
|
8933
9156
|
);
|
|
@@ -8935,7 +9158,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
8935
9158
|
throw new Error(`Embed '${embedIdOrShort}' not found in local cache.`);
|
|
8936
9159
|
}
|
|
8937
9160
|
const embedId = String(embed.embed_id ?? embed.id ?? "");
|
|
8938
|
-
const hashedEmbedId =
|
|
9161
|
+
const hashedEmbedId = createHash11("sha256").update(embedId).digest("hex");
|
|
8939
9162
|
const embedKeyBytes = await this.resolveEmbedKey(
|
|
8940
9163
|
cache,
|
|
8941
9164
|
masterKey,
|
|
@@ -9043,8 +9266,8 @@ Required: ${schema.required.join(", ")}`
|
|
|
9043
9266
|
if (!embed) {
|
|
9044
9267
|
throw new Error(`Embed '${embedId}' not found in local cache. Run 'openmates chats list' to sync first.`);
|
|
9045
9268
|
}
|
|
9046
|
-
const { createHash:
|
|
9047
|
-
const hashedEmbedId =
|
|
9269
|
+
const { createHash: createHash11 } = await import("crypto");
|
|
9270
|
+
const hashedEmbedId = createHash11("sha256").update(embedId).digest("hex");
|
|
9048
9271
|
const embedKey = await this.resolveEmbedKey(
|
|
9049
9272
|
cache,
|
|
9050
9273
|
masterKey,
|
|
@@ -9138,8 +9361,8 @@ Required: ${schema.required.join(", ")}`
|
|
|
9138
9361
|
if (!embed) {
|
|
9139
9362
|
throw new Error(`Embed '${embedId}' not found in local cache. Run 'openmates chats list' to sync first.`);
|
|
9140
9363
|
}
|
|
9141
|
-
const { createHash:
|
|
9142
|
-
const hashedEmbedId =
|
|
9364
|
+
const { createHash: createHash11 } = await import("crypto");
|
|
9365
|
+
const hashedEmbedId = createHash11("sha256").update(embedId).digest("hex");
|
|
9143
9366
|
const embedKey = await this.resolveEmbedKey(
|
|
9144
9367
|
cache,
|
|
9145
9368
|
masterKey,
|
|
@@ -9378,13 +9601,14 @@ Required: ${schema.required.join(", ")}`
|
|
|
9378
9601
|
* The sync cache stores encrypted data — decryption is always on-demand.
|
|
9379
9602
|
* SECURITY: decrypted user content is NEVER written to disk.
|
|
9380
9603
|
*/
|
|
9381
|
-
async ensureSynced(forceRefresh = false, refreshChatIds = []) {
|
|
9604
|
+
async ensureSynced(forceRefresh = false, refreshChatIds = [], options = {}) {
|
|
9605
|
+
const teamId = this.resolveTeamContext(options);
|
|
9382
9606
|
const refreshChatIdSet = new Set(refreshChatIds.filter(Boolean));
|
|
9383
|
-
if (!forceRefresh && refreshChatIdSet.size === 0 && isSyncCacheFresh()) {
|
|
9384
|
-
const cache2 = loadSyncCache();
|
|
9607
|
+
if (!forceRefresh && refreshChatIdSet.size === 0 && isSyncCacheFresh(3e5, teamId)) {
|
|
9608
|
+
const cache2 = loadSyncCache(teamId);
|
|
9385
9609
|
if (cache2) return cache2;
|
|
9386
9610
|
}
|
|
9387
|
-
const existingCache = loadSyncCache();
|
|
9611
|
+
const existingCache = loadSyncCache(teamId);
|
|
9388
9612
|
const clientChatVersions = {};
|
|
9389
9613
|
const clientChatIds = [];
|
|
9390
9614
|
const clientEmbedIds = [];
|
|
@@ -9420,6 +9644,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
9420
9644
|
try {
|
|
9421
9645
|
ws.send("phased_sync_request", {
|
|
9422
9646
|
phase: "all",
|
|
9647
|
+
...teamId ? { team_id: teamId } : {},
|
|
9423
9648
|
client_chat_versions: clientChatVersions,
|
|
9424
9649
|
client_chat_ids: clientChatIds,
|
|
9425
9650
|
client_embed_ids: clientEmbedIds
|
|
@@ -9542,9 +9767,9 @@ Required: ${schema.required.join(", ")}`
|
|
|
9542
9767
|
const reconciledChats = reconcileAuthoritativeChats(chats, reconciliation);
|
|
9543
9768
|
chats.splice(0, chats.length, ...reconciledChats);
|
|
9544
9769
|
if (reconciliation.deleted_chat_ids?.length) {
|
|
9545
|
-
const { createHash:
|
|
9770
|
+
const { createHash: createHash11 } = await import("crypto");
|
|
9546
9771
|
const deletedHashes = new Set(
|
|
9547
|
-
reconciliation.deleted_chat_ids.map((id) =>
|
|
9772
|
+
reconciliation.deleted_chat_ids.map((id) => createHash11("sha256").update(id).digest("hex"))
|
|
9548
9773
|
);
|
|
9549
9774
|
const keptEmbeds = embeds.filter((embed) => !deletedHashes.has(String(embed.hashed_chat_id ?? "")));
|
|
9550
9775
|
const keptKeys = embedKeys.filter((key) => !deletedHashes.has(String(key.hashed_chat_id ?? "")));
|
|
@@ -9558,7 +9783,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
9558
9783
|
);
|
|
9559
9784
|
let persistedTaskJobIds = /* @__PURE__ */ new Set();
|
|
9560
9785
|
try {
|
|
9561
|
-
await this.persistPendingAIResponsesFromSync(ws, chats, pendingAIResponses);
|
|
9786
|
+
await this.persistPendingAIResponsesFromSync(ws, chats, pendingAIResponses, teamId);
|
|
9562
9787
|
persistedTaskJobIds = await this.persistPendingTaskUpdateJobs({
|
|
9563
9788
|
ws,
|
|
9564
9789
|
jobs: pendingTaskUpdateJobs,
|
|
@@ -9573,8 +9798,8 @@ Required: ${schema.required.join(", ")}`
|
|
|
9573
9798
|
ws.close();
|
|
9574
9799
|
}
|
|
9575
9800
|
if (persistedTaskJobIds.size > 0) {
|
|
9576
|
-
clearSyncCache();
|
|
9577
|
-
return this.ensureSynced(true, refreshChatIds);
|
|
9801
|
+
clearSyncCache(teamId);
|
|
9802
|
+
return this.ensureSynced(true, refreshChatIds, { teamId });
|
|
9578
9803
|
}
|
|
9579
9804
|
const cache = {
|
|
9580
9805
|
syncedAt: Date.now(),
|
|
@@ -9586,10 +9811,10 @@ Required: ${schema.required.join(", ")}`
|
|
|
9586
9811
|
chatKeyWrappers,
|
|
9587
9812
|
newChatSuggestions
|
|
9588
9813
|
};
|
|
9589
|
-
saveSyncCache(cache);
|
|
9814
|
+
saveSyncCache(cache, teamId);
|
|
9590
9815
|
return cache;
|
|
9591
9816
|
}
|
|
9592
|
-
async persistPendingAIResponsesFromSync(ws, chats, pendingResponses) {
|
|
9817
|
+
async persistPendingAIResponsesFromSync(ws, chats, pendingResponses, teamId) {
|
|
9593
9818
|
if (pendingResponses.length === 0) return;
|
|
9594
9819
|
const masterKey = this.getMasterKeyBytes();
|
|
9595
9820
|
for (const pending of pendingResponses) {
|
|
@@ -9615,7 +9840,7 @@ Required: ${schema.required.join(", ")}`
|
|
|
9615
9840
|
} catch {
|
|
9616
9841
|
}
|
|
9617
9842
|
}
|
|
9618
|
-
const chatKeyBytes = await this.resolveChatKey(loadSyncCache(), chat, masterKey);
|
|
9843
|
+
const chatKeyBytes = await this.resolveChatKey(loadSyncCache(teamId), chat, masterKey);
|
|
9619
9844
|
if (!chatKeyBytes) continue;
|
|
9620
9845
|
const completedAt = normalizeUnixSeconds(
|
|
9621
9846
|
pending.fired_at,
|
|
@@ -10000,6 +10225,70 @@ var APP_SKILL_METADATA = [
|
|
|
10000
10225
|
"properties": {}
|
|
10001
10226
|
}
|
|
10002
10227
|
},
|
|
10228
|
+
{
|
|
10229
|
+
"app_id": "design",
|
|
10230
|
+
"skill_id": "search_icons",
|
|
10231
|
+
"app_namespace_ts": "design",
|
|
10232
|
+
"skill_method_ts": "searchIcons",
|
|
10233
|
+
"app_namespace_py": "design",
|
|
10234
|
+
"skill_method_py": "search_icons",
|
|
10235
|
+
"description_key": "app_skills.design.search_icons.description",
|
|
10236
|
+
"description": "Search for free SVG icons for UI, product, interface, or graphic design. Use this when the user asks to find icons by name, concept, object, or action. Do not use it for brand-logo search or generated icon creation.",
|
|
10237
|
+
"schema": {
|
|
10238
|
+
"type": "object",
|
|
10239
|
+
"properties": {
|
|
10240
|
+
"requests": {
|
|
10241
|
+
"type": "array",
|
|
10242
|
+
"description": "Array of icon search requests backed by Iconify.",
|
|
10243
|
+
"items": {
|
|
10244
|
+
"type": "object",
|
|
10245
|
+
"properties": {
|
|
10246
|
+
"query": {
|
|
10247
|
+
"type": "string",
|
|
10248
|
+
"description": 'Search query, e.g. "home", "calendar", or "settings".'
|
|
10249
|
+
},
|
|
10250
|
+
"count": {
|
|
10251
|
+
"type": "integer",
|
|
10252
|
+
"minimum": 1,
|
|
10253
|
+
"maximum": 50,
|
|
10254
|
+
"default": 24,
|
|
10255
|
+
"description": "Maximum number of icon results to return."
|
|
10256
|
+
},
|
|
10257
|
+
"license_policy": {
|
|
10258
|
+
"type": "string",
|
|
10259
|
+
"enum": [
|
|
10260
|
+
"permissive",
|
|
10261
|
+
"all"
|
|
10262
|
+
],
|
|
10263
|
+
"default": "permissive",
|
|
10264
|
+
"description": "Filter to permissive/no-attribution licenses by default."
|
|
10265
|
+
},
|
|
10266
|
+
"include_prefixes": {
|
|
10267
|
+
"type": "array",
|
|
10268
|
+
"items": {
|
|
10269
|
+
"type": "string"
|
|
10270
|
+
},
|
|
10271
|
+
"description": "Optional Iconify collection prefixes to include."
|
|
10272
|
+
},
|
|
10273
|
+
"exclude_prefixes": {
|
|
10274
|
+
"type": "array",
|
|
10275
|
+
"items": {
|
|
10276
|
+
"type": "string"
|
|
10277
|
+
},
|
|
10278
|
+
"description": "Optional Iconify collection prefixes to exclude."
|
|
10279
|
+
}
|
|
10280
|
+
},
|
|
10281
|
+
"required": [
|
|
10282
|
+
"query"
|
|
10283
|
+
]
|
|
10284
|
+
}
|
|
10285
|
+
}
|
|
10286
|
+
},
|
|
10287
|
+
"required": [
|
|
10288
|
+
"requests"
|
|
10289
|
+
]
|
|
10290
|
+
}
|
|
10291
|
+
},
|
|
10003
10292
|
{
|
|
10004
10293
|
"app_id": "electronics",
|
|
10005
10294
|
"skill_id": "search_components",
|
|
@@ -13180,6 +13469,20 @@ var CodeAppSkills = class {
|
|
|
13180
13469
|
return this.runSkill("code", "search_repos", input);
|
|
13181
13470
|
}
|
|
13182
13471
|
};
|
|
13472
|
+
var DesignAppSkills = class {
|
|
13473
|
+
runSkill;
|
|
13474
|
+
constructor(runSkill) {
|
|
13475
|
+
this.runSkill = runSkill;
|
|
13476
|
+
}
|
|
13477
|
+
/**
|
|
13478
|
+
* Search for free SVG icons for UI, product, interface, or graphic design. Use this when the user asks to find icons by name, concept, object, or action. Do not use it for brand-logo search or generated icon creation.
|
|
13479
|
+
* Description key: app_skills.design.search_icons.description
|
|
13480
|
+
* Skill: design/search_icons
|
|
13481
|
+
*/
|
|
13482
|
+
async searchIcons(input) {
|
|
13483
|
+
return this.runSkill("design", "search_icons", input);
|
|
13484
|
+
}
|
|
13485
|
+
};
|
|
13183
13486
|
var ElectronicsAppSkills = class {
|
|
13184
13487
|
runSkill;
|
|
13185
13488
|
constructor(runSkill) {
|
|
@@ -13673,6 +13976,7 @@ var GeneratedAppSkills = class {
|
|
|
13673
13976
|
this.ai = new AiAppSkills(runSkill);
|
|
13674
13977
|
this.books = new BooksAppSkills(runSkill);
|
|
13675
13978
|
this.code = new CodeAppSkills(runSkill);
|
|
13979
|
+
this.design = new DesignAppSkills(runSkill);
|
|
13676
13980
|
this.electronics = new ElectronicsAppSkills(runSkill);
|
|
13677
13981
|
this.events = new EventsAppSkills(runSkill);
|
|
13678
13982
|
this.fitness = new FitnessAppSkills(runSkill);
|
|
@@ -13701,6 +14005,7 @@ var GeneratedAppSkills = class {
|
|
|
13701
14005
|
ai;
|
|
13702
14006
|
books;
|
|
13703
14007
|
code;
|
|
14008
|
+
design;
|
|
13704
14009
|
electronics;
|
|
13705
14010
|
events;
|
|
13706
14011
|
fitness;
|
|
@@ -13729,7 +14034,7 @@ var GeneratedAppSkills = class {
|
|
|
13729
14034
|
|
|
13730
14035
|
// src/sdk.ts
|
|
13731
14036
|
import { decode as toonDecode } from "@toon-format/toon";
|
|
13732
|
-
import { createHash as
|
|
14037
|
+
import { createHash as createHash8, randomBytes as randomBytes4, randomUUID as randomUUID6 } from "crypto";
|
|
13733
14038
|
import { chmodSync as chmodSync2, existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
13734
14039
|
import { homedir as homedir4 } from "os";
|
|
13735
14040
|
import { dirname, join as join3 } from "path";
|
|
@@ -13867,7 +14172,7 @@ var OpenMates = class {
|
|
|
13867
14172
|
}
|
|
13868
14173
|
async resolveEmbedKeyForShare(embedKeys, embedId) {
|
|
13869
14174
|
const masterKey = await this.getMasterKey();
|
|
13870
|
-
const hashedEmbedId =
|
|
14175
|
+
const hashedEmbedId = createHash8("sha256").update(embedId).digest("hex");
|
|
13871
14176
|
return this.resolveLoadedEmbedKey(embedKeys, hashedEmbedId, masterKey, masterKey);
|
|
13872
14177
|
}
|
|
13873
14178
|
async decryptChatMetadata(chat, chatKeyWrappers) {
|
|
@@ -13924,7 +14229,7 @@ var OpenMates = class {
|
|
|
13924
14229
|
}
|
|
13925
14230
|
async resolveLoadedChatKey(chat, chatKeyWrappers) {
|
|
13926
14231
|
const masterKey = await this.getMasterKey();
|
|
13927
|
-
const hashedChatId =
|
|
14232
|
+
const hashedChatId = createHash8("sha256").update(chat.id).digest("hex");
|
|
13928
14233
|
const wrapper = (chatKeyWrappers ?? []).find(
|
|
13929
14234
|
(entry) => entry.key_type === "master" && entry.hashed_chat_id === hashedChatId && typeof entry.encrypted_chat_key === "string"
|
|
13930
14235
|
);
|
|
@@ -13938,7 +14243,7 @@ var OpenMates = class {
|
|
|
13938
14243
|
if (!embedId) {
|
|
13939
14244
|
return { ...embed };
|
|
13940
14245
|
}
|
|
13941
|
-
const hashedEmbedId =
|
|
14246
|
+
const hashedEmbedId = createHash8("sha256").update(embedId).digest("hex");
|
|
13942
14247
|
const embedKey = await this.resolveLoadedEmbedKey(embedKeys, hashedEmbedId, masterKey, chatKey);
|
|
13943
14248
|
if (!embedKey) {
|
|
13944
14249
|
return { ...embed };
|
|
@@ -14171,7 +14476,7 @@ var OpenMatesChats = class {
|
|
|
14171
14476
|
encryptedChatKey = chat.encrypted_chat_key;
|
|
14172
14477
|
expectedMessagesV = Number(chat.messages_v ?? 0);
|
|
14173
14478
|
} else {
|
|
14174
|
-
chatKey = new Uint8Array(
|
|
14479
|
+
chatKey = new Uint8Array(randomBytes4(32));
|
|
14175
14480
|
encryptedChatKey = await encryptBytesWithAesGcm(chatKey, masterKey);
|
|
14176
14481
|
encryptedChatMetadata = {
|
|
14177
14482
|
encrypted_title: await encryptWithAesGcmCombined(options.title ?? message.slice(0, 80), chatKey),
|
|
@@ -16024,7 +16329,7 @@ var OutputRedactor = class {
|
|
|
16024
16329
|
import { readFileSync as readFileSync5, statSync, existsSync as existsSync6 } from "fs";
|
|
16025
16330
|
import { basename, extname, resolve as resolve2 } from "path";
|
|
16026
16331
|
import { homedir as homedir5 } from "os";
|
|
16027
|
-
import { createHash as
|
|
16332
|
+
import { createHash as createHash9 } from "crypto";
|
|
16028
16333
|
var MAX_PER_FILE_SIZE = 100 * 1024 * 1024;
|
|
16029
16334
|
var BLOCKED_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
16030
16335
|
".pem",
|
|
@@ -16334,7 +16639,7 @@ function processCodeFile(filePath, filename, redactor) {
|
|
|
16334
16639
|
line_count: lineCount
|
|
16335
16640
|
});
|
|
16336
16641
|
const textPreview = `${filename} (${language}, ${lineCount} lines)`;
|
|
16337
|
-
const contentHash =
|
|
16642
|
+
const contentHash = createHash9("sha256").update(content).digest("hex");
|
|
16338
16643
|
const embed = {
|
|
16339
16644
|
embedId,
|
|
16340
16645
|
embedRef,
|
|
@@ -17889,7 +18194,7 @@ function formatTs(ts) {
|
|
|
17889
18194
|
|
|
17890
18195
|
// src/server.ts
|
|
17891
18196
|
import { execFileSync as execFileSync2, execSync, spawn as nodeSpawn, spawnSync } from "child_process";
|
|
17892
|
-
import { createHash as
|
|
18197
|
+
import { createHash as createHash10, randomBytes as randomBytes5 } from "crypto";
|
|
17893
18198
|
import { chmodSync as chmodSync3, closeSync, copyFileSync, cpSync, existsSync as existsSync7, mkdirSync as mkdirSync4, mkdtempSync, openSync, readFileSync as readFileSync6, readSync, readdirSync, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
17894
18199
|
import { createInterface as createInterface3 } from "readline";
|
|
17895
18200
|
import { createInterface as createPromptInterface } from "readline/promises";
|
|
@@ -18507,10 +18812,10 @@ function resolveTargetImageTag(flags, currentTag, packageVersion) {
|
|
|
18507
18812
|
return { tag: getDefaultImageTagForVersion(packageVersion) };
|
|
18508
18813
|
}
|
|
18509
18814
|
function randomHex(bytes) {
|
|
18510
|
-
return
|
|
18815
|
+
return randomBytes5(bytes).toString("hex");
|
|
18511
18816
|
}
|
|
18512
18817
|
function generateInviteCode() {
|
|
18513
|
-
const digits = Array.from(
|
|
18818
|
+
const digits = Array.from(randomBytes5(12), (byte) => String(byte % 10)).join("");
|
|
18514
18819
|
return `${digits.slice(0, 4)}-${digits.slice(4, 8)}-${digits.slice(8, 12)}`;
|
|
18515
18820
|
}
|
|
18516
18821
|
function getEnvVar(content, name) {
|
|
@@ -18554,7 +18859,7 @@ function packagedCaddyTemplatePath(role) {
|
|
|
18554
18859
|
}
|
|
18555
18860
|
function fileHash(path) {
|
|
18556
18861
|
if (!existsSync7(path)) return null;
|
|
18557
|
-
return
|
|
18862
|
+
return createHash10("sha256").update(readFileSync6(path)).digest("hex");
|
|
18558
18863
|
}
|
|
18559
18864
|
async function loadSelfHostComposeTemplate(templateRef, role) {
|
|
18560
18865
|
const templateDir = process.env.OPENMATES_SELFHOST_TEMPLATE_DIR;
|
|
@@ -18940,7 +19245,7 @@ function formatSecretPreflight(preflight) {
|
|
|
18940
19245
|
return parts.join("; ");
|
|
18941
19246
|
}
|
|
18942
19247
|
function hashFile(path) {
|
|
18943
|
-
const hash =
|
|
19248
|
+
const hash = createHash10("sha256");
|
|
18944
19249
|
const fd = openSync(path, "r");
|
|
18945
19250
|
const buffer = Buffer.allocUnsafe(CHECKSUM_BUFFER_BYTES);
|
|
18946
19251
|
try {
|
|
@@ -45934,7 +46239,7 @@ As of mid-2026, the severe supply shocks from the 2024\u20132025 avian flu have
|
|
|
45934
46239
|
text: "Web, search, and content retrieval (only when you use a web or search skill)"
|
|
45935
46240
|
},
|
|
45936
46241
|
description: {
|
|
45937
|
-
text: "These providers are only used when you invoke a web, videos, news,
|
|
46242
|
+
text: "These providers are only used when you invoke a web, videos, news, web-read, or design icon search skill. They see the content of what you search for, the URLs you ask to read, or the public icon identifiers you ask to preview, but no user identifier \u2014 they do not know which OpenMates user made each request."
|
|
45938
46243
|
},
|
|
45939
46244
|
brave: {
|
|
45940
46245
|
heading: {
|
|
@@ -45952,6 +46257,14 @@ As of mid-2026, the severe supply shocks from the 2024\u20132025 avian flu have
|
|
|
45952
46257
|
text: "Firecrawl powers the web read skill, scraping and extracting content from web pages you ask about. Firecrawl sees the URL you requested and the full content of the scraped page."
|
|
45953
46258
|
}
|
|
45954
46259
|
},
|
|
46260
|
+
iconify: {
|
|
46261
|
+
heading: {
|
|
46262
|
+
text: "Iconify (public SVG icon search)"
|
|
46263
|
+
},
|
|
46264
|
+
description: {
|
|
46265
|
+
text: "Iconify powers the design.search_icons skill. Iconify sees icon search queries and the icon collection/name needed to fetch SVG previews, but no OpenMates user identifier. OpenMates fetches Iconify data server-side and clients do not call Iconify directly."
|
|
46266
|
+
}
|
|
46267
|
+
},
|
|
45955
46268
|
webshare: {
|
|
45956
46269
|
heading: {
|
|
45957
46270
|
text: "Webshare (rotating proxy)"
|
|
@@ -58078,6 +58391,10 @@ async function main() {
|
|
|
58078
58391
|
printTasksHelp();
|
|
58079
58392
|
return;
|
|
58080
58393
|
}
|
|
58394
|
+
if (command === "teams") {
|
|
58395
|
+
printTeamsHelp();
|
|
58396
|
+
return;
|
|
58397
|
+
}
|
|
58081
58398
|
if (command === "connected-accounts") {
|
|
58082
58399
|
printConnectedAccountsHelp();
|
|
58083
58400
|
return;
|
|
@@ -58200,6 +58517,10 @@ async function main() {
|
|
|
58200
58517
|
await handleTasks(client, subcommand, rest, parsed.flags);
|
|
58201
58518
|
return;
|
|
58202
58519
|
}
|
|
58520
|
+
if (command === "teams") {
|
|
58521
|
+
await handleTeams(client, subcommand, rest, parsed.flags);
|
|
58522
|
+
return;
|
|
58523
|
+
}
|
|
58203
58524
|
if (command === "drafts") {
|
|
58204
58525
|
await handleDrafts(client, subcommand, rest, parsed.flags);
|
|
58205
58526
|
return;
|
|
@@ -58469,11 +58790,12 @@ function taskScopeFromFlags(flags, masterKey) {
|
|
|
58469
58790
|
projectId: typeof flags.project === "string" ? flags.project : void 0,
|
|
58470
58791
|
planId: typeof flags.plan === "string" ? flags.plan : void 0,
|
|
58471
58792
|
labelHashes: labelHashes(masterKey, labelFlags(flags)),
|
|
58472
|
-
priority: typeof flags.priority === "string" ? normalizeTaskPriority(flags.priority) : void 0
|
|
58793
|
+
priority: typeof flags.priority === "string" ? normalizeTaskPriority(flags.priority) : void 0,
|
|
58794
|
+
...teamContextFromFlags(flags)
|
|
58473
58795
|
};
|
|
58474
58796
|
}
|
|
58475
58797
|
async function loadTasks(client, masterKey, scope) {
|
|
58476
|
-
const records = await client.listUserTasks({ status: scope.status, chatId: scope.chatId, projectId: scope.projectId, labelHashes: scope.labelHashes, priority: scope.priority });
|
|
58798
|
+
const records = await client.listUserTasks({ status: scope.status, chatId: scope.chatId, projectId: scope.projectId, labelHashes: scope.labelHashes, priority: scope.priority, teamId: scope.teamId, personal: scope.personal });
|
|
58477
58799
|
const tasks = await decryptUserTasks(records, masterKey);
|
|
58478
58800
|
return scope.planId ? tasks.filter((task) => task.planId === scope.planId) : tasks;
|
|
58479
58801
|
}
|
|
@@ -58488,6 +58810,252 @@ function printTaskOutput(task, flags) {
|
|
|
58488
58810
|
if (flags.json === true) printJson2({ task: taskToJson(task) });
|
|
58489
58811
|
else console.log(renderTaskDetail(task));
|
|
58490
58812
|
}
|
|
58813
|
+
async function handleTeams(client, subcommand, rest, flags) {
|
|
58814
|
+
if (!subcommand || subcommand === "help" || flags.help === true) {
|
|
58815
|
+
printTeamsHelp();
|
|
58816
|
+
return;
|
|
58817
|
+
}
|
|
58818
|
+
if (subcommand === "list") {
|
|
58819
|
+
const teams = await client.listTeams();
|
|
58820
|
+
printTeamsOutput(teams, client.getActiveTeamId(), flags);
|
|
58821
|
+
return;
|
|
58822
|
+
}
|
|
58823
|
+
if (subcommand === "switch") {
|
|
58824
|
+
const teamId = requireTeamId(rest, flags);
|
|
58825
|
+
client.setActiveTeamId(teamId);
|
|
58826
|
+
if (flags.json === true) printJson2({ active_team_id: teamId, context: "team" });
|
|
58827
|
+
else console.log(`Active team: ${teamId}`);
|
|
58828
|
+
return;
|
|
58829
|
+
}
|
|
58830
|
+
if (subcommand === "personal") {
|
|
58831
|
+
client.setActiveTeamId(null);
|
|
58832
|
+
if (flags.json === true) printJson2({ active_team_id: null, context: "personal" });
|
|
58833
|
+
else console.log("Active context: personal");
|
|
58834
|
+
return;
|
|
58835
|
+
}
|
|
58836
|
+
if (subcommand === "show") {
|
|
58837
|
+
const teamId = requireTeamId(rest, flags);
|
|
58838
|
+
const team = await client.getTeam(teamId);
|
|
58839
|
+
if (flags.json === true) printJson2({ team, active_team_id: client.getActiveTeamId() });
|
|
58840
|
+
else printTeamRecord(team, client.getActiveTeamId());
|
|
58841
|
+
return;
|
|
58842
|
+
}
|
|
58843
|
+
if (subcommand === "create") {
|
|
58844
|
+
const name = requiredStringFlag(flags.name, "--name <name>");
|
|
58845
|
+
const team = await client.createTeam({
|
|
58846
|
+
name,
|
|
58847
|
+
description: typeof flags.description === "string" ? flags.description : void 0,
|
|
58848
|
+
slug: typeof flags.slug === "string" ? flags.slug : void 0
|
|
58849
|
+
});
|
|
58850
|
+
if (flags.switch === true || flags.activate === true) {
|
|
58851
|
+
const teamId = team.team_id ?? team.id;
|
|
58852
|
+
if (typeof teamId === "string") client.setActiveTeamId(teamId);
|
|
58853
|
+
}
|
|
58854
|
+
if (flags.json === true) printJson2({ team, active_team_id: client.getActiveTeamId() });
|
|
58855
|
+
else printTeamRecord(team, client.getActiveTeamId());
|
|
58856
|
+
return;
|
|
58857
|
+
}
|
|
58858
|
+
if (subcommand === "update") {
|
|
58859
|
+
const teamId = requireTeamId(rest, flags);
|
|
58860
|
+
const patch = {};
|
|
58861
|
+
if (typeof flags.name === "string") patch.encrypted_name = flags.name;
|
|
58862
|
+
if (typeof flags.description === "string") patch.encrypted_description = flags.description;
|
|
58863
|
+
if (typeof flags.slug === "string") patch.slug = flags.slug;
|
|
58864
|
+
if (Object.keys(patch).length === 0) throw new Error("Nothing to update. Provide --name, --description, or --slug.");
|
|
58865
|
+
const team = await client.updateTeam(teamId, patch);
|
|
58866
|
+
if (flags.json === true) printJson2({ team });
|
|
58867
|
+
else printTeamRecord(team, client.getActiveTeamId());
|
|
58868
|
+
return;
|
|
58869
|
+
}
|
|
58870
|
+
if (subcommand === "delete") {
|
|
58871
|
+
const teamId = requireTeamId(rest, flags);
|
|
58872
|
+
if (flags.yes !== true && flags.confirm !== true) throw new Error("Deleting a team requires --yes.");
|
|
58873
|
+
const result = await client.deleteTeam(teamId);
|
|
58874
|
+
if (client.getActiveTeamId() === teamId) client.setActiveTeamId(null);
|
|
58875
|
+
if (flags.json === true) printJson2(result);
|
|
58876
|
+
else console.log(`Team deleted: ${teamId}`);
|
|
58877
|
+
return;
|
|
58878
|
+
}
|
|
58879
|
+
if (subcommand === "invite") {
|
|
58880
|
+
const teamId = requireTeamId(rest, flags);
|
|
58881
|
+
const input = {};
|
|
58882
|
+
if (typeof flags.email === "string") input.recipient_email = flags.email;
|
|
58883
|
+
if (typeof flags.user === "string") input.invitee_user_id = flags.user;
|
|
58884
|
+
if (typeof flags["encrypted-recipient-hint"] === "string") input.encrypted_recipient_hint = flags["encrypted-recipient-hint"];
|
|
58885
|
+
if (typeof flags["expires-at"] === "string") input.expires_at = Number.parseInt(flags["expires-at"], 10);
|
|
58886
|
+
input.role = parseTeamInviteRole(flags.role);
|
|
58887
|
+
const invite = await client.createTeamInvite(teamId, input);
|
|
58888
|
+
if (flags.json === true) printJson2({ invite });
|
|
58889
|
+
else printJson2(invite);
|
|
58890
|
+
return;
|
|
58891
|
+
}
|
|
58892
|
+
if (subcommand === "accept-invite") {
|
|
58893
|
+
const inviteId = requiredStringFlag(flags.invite ?? rest[0], "<invite-id>");
|
|
58894
|
+
const result = await client.acceptTeamInvite(inviteId);
|
|
58895
|
+
if (flags.json === true) printJson2(result);
|
|
58896
|
+
else printJson2(result);
|
|
58897
|
+
return;
|
|
58898
|
+
}
|
|
58899
|
+
if (subcommand === "decline-invite") {
|
|
58900
|
+
const inviteId = requiredStringFlag(flags.invite ?? rest[0], "<invite-id>");
|
|
58901
|
+
const result = await client.declineTeamInvite(inviteId);
|
|
58902
|
+
if (flags.json === true) printJson2(result);
|
|
58903
|
+
else console.log("Team invite declined.");
|
|
58904
|
+
return;
|
|
58905
|
+
}
|
|
58906
|
+
if (subcommand === "access-requests") {
|
|
58907
|
+
const teamId = requireTeamId(rest, flags);
|
|
58908
|
+
const status = typeof flags.status === "string" ? flags.status : void 0;
|
|
58909
|
+
const accessRequests = await client.listTeamAccessRequests(teamId, status);
|
|
58910
|
+
if (flags.json === true) printJson2({ access_requests: accessRequests });
|
|
58911
|
+
else printJson2(accessRequests);
|
|
58912
|
+
return;
|
|
58913
|
+
}
|
|
58914
|
+
if (subcommand === "approve-access") {
|
|
58915
|
+
const teamId = requireTeamId(rest, flags);
|
|
58916
|
+
const accessRequestId = requiredStringFlag(flags.request ?? flags["access-request"] ?? rest[1], "<access-request-id>");
|
|
58917
|
+
const encryptedTeamKey = requiredStringFlag(flags["encrypted-team-key"], "--encrypted-team-key <value>");
|
|
58918
|
+
const membership = await client.approveTeamAccessRequest(teamId, accessRequestId, encryptedTeamKey);
|
|
58919
|
+
if (flags.json === true) printJson2({ membership });
|
|
58920
|
+
else printJson2(membership);
|
|
58921
|
+
return;
|
|
58922
|
+
}
|
|
58923
|
+
if (subcommand === "reject-access") {
|
|
58924
|
+
const teamId = requireTeamId(rest, flags);
|
|
58925
|
+
const accessRequestId = requiredStringFlag(flags.request ?? flags["access-request"] ?? rest[1], "<access-request-id>");
|
|
58926
|
+
const result = await client.rejectTeamAccessRequest(teamId, accessRequestId);
|
|
58927
|
+
if (flags.json === true) printJson2(result);
|
|
58928
|
+
else console.log(`Team access request rejected: ${accessRequestId}`);
|
|
58929
|
+
return;
|
|
58930
|
+
}
|
|
58931
|
+
if (subcommand === "role") {
|
|
58932
|
+
const teamId = requireTeamId(rest, flags);
|
|
58933
|
+
const memberUserId = requiredStringFlag(flags.user ?? rest[1], "--user <user-id>");
|
|
58934
|
+
const role = parseTeamAssignableRole(flags.role);
|
|
58935
|
+
const membership = await client.updateTeamMemberRole(teamId, memberUserId, role);
|
|
58936
|
+
if (flags.json === true) printJson2({ membership });
|
|
58937
|
+
else printJson2(membership);
|
|
58938
|
+
return;
|
|
58939
|
+
}
|
|
58940
|
+
if (subcommand === "remove-member") {
|
|
58941
|
+
const teamId = requireTeamId(rest, flags);
|
|
58942
|
+
const memberUserId = requiredStringFlag(flags.user ?? rest[1], "--user <user-id>");
|
|
58943
|
+
const result = await client.removeTeamMember(teamId, memberUserId);
|
|
58944
|
+
if (flags.json === true) printJson2(result);
|
|
58945
|
+
else console.log(`Team member removed: ${memberUserId}`);
|
|
58946
|
+
return;
|
|
58947
|
+
}
|
|
58948
|
+
if (subcommand === "billing") {
|
|
58949
|
+
const teamId = requireTeamId(rest, flags);
|
|
58950
|
+
const billing = await client.getTeamBilling(teamId);
|
|
58951
|
+
if (flags.json === true) printJson2({ billing });
|
|
58952
|
+
else printJson2(billing);
|
|
58953
|
+
return;
|
|
58954
|
+
}
|
|
58955
|
+
if (subcommand === "add-credits") {
|
|
58956
|
+
const teamId = requireTeamId(rest, flags);
|
|
58957
|
+
const credits = requiredNumberFlag(flags.credits, "--credits <amount>");
|
|
58958
|
+
const billing = await client.addTeamCredits(teamId, { credits });
|
|
58959
|
+
if (flags.json === true) printJson2({ billing });
|
|
58960
|
+
else printJson2(billing);
|
|
58961
|
+
return;
|
|
58962
|
+
}
|
|
58963
|
+
if (subcommand === "usage") {
|
|
58964
|
+
const teamId = requireTeamId(rest, flags);
|
|
58965
|
+
const usage = await client.listTeamUsage(teamId, typeof flags.user === "string" ? flags.user : void 0);
|
|
58966
|
+
if (flags.json === true) printJson2({ usage });
|
|
58967
|
+
else printJson2(usage);
|
|
58968
|
+
return;
|
|
58969
|
+
}
|
|
58970
|
+
if (subcommand === "move") {
|
|
58971
|
+
const teamId = requireTeamId(rest, flags);
|
|
58972
|
+
const workspaceType = parseWorkspaceMoveType(flags.type ?? rest[1]);
|
|
58973
|
+
const objectId = requiredStringFlag(flags.id ?? rest[2], "--id <resource-id>");
|
|
58974
|
+
if (flags.yes !== true && flags.confirm !== true) throw new Error("Moving a workspace resource requires --yes.");
|
|
58975
|
+
const result = await client.moveWorkspaceToTeam(workspaceType, objectId, teamId);
|
|
58976
|
+
if (flags.json === true) printJson2(result);
|
|
58977
|
+
else console.log(`${workspaceType} moved to team ${teamId}: ${objectId}`);
|
|
58978
|
+
return;
|
|
58979
|
+
}
|
|
58980
|
+
if (subcommand === "export") {
|
|
58981
|
+
const teamId = requireTeamId(rest, flags);
|
|
58982
|
+
const output = requiredStringFlag(flags.output, "--output <path>");
|
|
58983
|
+
const result = await client.exportTeamData(teamId);
|
|
58984
|
+
const artifact = result.artifact && typeof result.artifact === "object" ? result.artifact : result;
|
|
58985
|
+
writeFileSync7(output, `${JSON.stringify(artifact, null, 2)}
|
|
58986
|
+
`, { encoding: "utf-8", mode: 384 });
|
|
58987
|
+
if (flags.json === true) printJson2({ ...result, output });
|
|
58988
|
+
else console.log(`Team export written: ${output}`);
|
|
58989
|
+
return;
|
|
58990
|
+
}
|
|
58991
|
+
if (subcommand === "import") {
|
|
58992
|
+
const file = requiredStringFlag(flags.file ?? rest[0], "--file <path>");
|
|
58993
|
+
const artifact = JSON.parse(readFileSync10(file, "utf-8"));
|
|
58994
|
+
let teamId = typeof flags.team === "string" ? flags.team : typeof flags["destination-team"] === "string" ? flags["destination-team"] : void 0;
|
|
58995
|
+
if (!teamId && typeof flags["new-team-name"] === "string") {
|
|
58996
|
+
const team = await client.createTeam({ name: flags["new-team-name"] });
|
|
58997
|
+
teamId = typeof team.team_id === "string" ? team.team_id : typeof team.id === "string" ? team.id : void 0;
|
|
58998
|
+
}
|
|
58999
|
+
if (!teamId) throw new Error("Team import requires --team <team-id> or --new-team-name <name>.");
|
|
59000
|
+
const result = await client.importTeamData(teamId, artifact);
|
|
59001
|
+
if (flags.json === true) printJson2(result);
|
|
59002
|
+
else printJson2(result);
|
|
59003
|
+
return;
|
|
59004
|
+
}
|
|
59005
|
+
throw new Error(`Unknown teams command '${subcommand}'. Run 'openmates teams --help'.`);
|
|
59006
|
+
}
|
|
59007
|
+
function requireTeamId(rest, flags) {
|
|
59008
|
+
return requiredStringFlag(flags.team ?? flags["team-id"] ?? rest[0], "--team <team-id>");
|
|
59009
|
+
}
|
|
59010
|
+
function requiredStringFlag(value, label) {
|
|
59011
|
+
if (typeof value !== "string" || value.trim().length === 0) throw new Error(`Missing ${label}.`);
|
|
59012
|
+
return value.trim();
|
|
59013
|
+
}
|
|
59014
|
+
function requiredNumberFlag(value, label) {
|
|
59015
|
+
const raw = requiredStringFlag(value, label);
|
|
59016
|
+
const parsed = Number(raw);
|
|
59017
|
+
if (!Number.isFinite(parsed) || parsed <= 0) throw new Error(`Invalid ${label}: ${raw}`);
|
|
59018
|
+
return parsed;
|
|
59019
|
+
}
|
|
59020
|
+
function parseTeamInviteRole(value) {
|
|
59021
|
+
if (value === void 0 || value === false) return "member";
|
|
59022
|
+
return parseTeamAssignableRole(value);
|
|
59023
|
+
}
|
|
59024
|
+
function parseTeamAssignableRole(value) {
|
|
59025
|
+
const role = requiredStringFlag(value, "--role <admin|member|viewer>");
|
|
59026
|
+
if (role === "admin" || role === "member" || role === "viewer") return role;
|
|
59027
|
+
throw new Error("Team role must be admin, member, or viewer.");
|
|
59028
|
+
}
|
|
59029
|
+
function parseWorkspaceMoveType(value) {
|
|
59030
|
+
const type = requiredStringFlag(value, "--type <chat|project|task|plan|workflow>");
|
|
59031
|
+
if (type === "chat" || type === "project" || type === "task" || type === "plan" || type === "workflow") return type;
|
|
59032
|
+
throw new Error("Workspace type must be chat, project, task, plan, or workflow.");
|
|
59033
|
+
}
|
|
59034
|
+
function teamContextFromFlags(flags) {
|
|
59035
|
+
if (flags.personal === true) return { personal: true };
|
|
59036
|
+
if (typeof flags.team === "string") return { teamId: flags.team };
|
|
59037
|
+
if (typeof flags["team-id"] === "string") return { teamId: flags["team-id"] };
|
|
59038
|
+
return {};
|
|
59039
|
+
}
|
|
59040
|
+
function printTeamsOutput(teams, activeTeamId, flags) {
|
|
59041
|
+
if (flags.json === true) {
|
|
59042
|
+
printJson2({ teams, active_team_id: activeTeamId });
|
|
59043
|
+
return;
|
|
59044
|
+
}
|
|
59045
|
+
if (teams.length === 0) {
|
|
59046
|
+
console.log("No teams.");
|
|
59047
|
+
return;
|
|
59048
|
+
}
|
|
59049
|
+
for (const team of teams) printTeamRecord(team, activeTeamId);
|
|
59050
|
+
}
|
|
59051
|
+
function printTeamRecord(team, activeTeamId) {
|
|
59052
|
+
const teamId = typeof team.team_id === "string" ? team.team_id : typeof team.id === "string" ? team.id : "unknown";
|
|
59053
|
+
const activeMarker = activeTeamId === teamId ? " *" : "";
|
|
59054
|
+
console.log(`${teamId}${activeMarker}`);
|
|
59055
|
+
if (typeof team.slug === "string") kv("slug", team.slug);
|
|
59056
|
+
if (typeof team.role === "string") kv("role", team.role);
|
|
59057
|
+
if (typeof team.status === "string") kv("status", team.status);
|
|
59058
|
+
}
|
|
58491
59059
|
function taskToJson(task) {
|
|
58492
59060
|
return {
|
|
58493
59061
|
task_id: task.taskId,
|
|
@@ -58693,6 +59261,7 @@ async function handleChats(client, subcommand, rest, flags, redactor) {
|
|
|
58693
59261
|
return;
|
|
58694
59262
|
}
|
|
58695
59263
|
const apiKey = resolveApiKey(flags) ?? void 0;
|
|
59264
|
+
const teamContext = teamContextFromFlags(flags);
|
|
58696
59265
|
if (rest[0] === "tasks") {
|
|
58697
59266
|
await handleTasks(client, rest[1], rest.slice(2), { ...flags, chat: subcommand });
|
|
58698
59267
|
return;
|
|
@@ -58700,7 +59269,7 @@ async function handleChats(client, subcommand, rest, flags, redactor) {
|
|
|
58700
59269
|
if (subcommand === "list") {
|
|
58701
59270
|
const limit = typeof flags.limit === "string" ? parseInt(flags.limit, 10) : 10;
|
|
58702
59271
|
const page = typeof flags.page === "string" ? parseInt(flags.page, 10) : 1;
|
|
58703
|
-
const result = apiKey ? await listApiKeyChats(client, apiKey, limit, page) : client.hasSession() ? await client.listChats(limit, page) : listExampleChats(limit, page);
|
|
59272
|
+
const result = apiKey ? await listApiKeyChats(client, apiKey, limit, page) : client.hasSession() ? await client.listChats(limit, page, teamContext) : listExampleChats(limit, page);
|
|
58704
59273
|
if (flags.json === true) {
|
|
58705
59274
|
printJson2(result);
|
|
58706
59275
|
} else {
|
|
@@ -58714,7 +59283,7 @@ async function handleChats(client, subcommand, rest, flags, redactor) {
|
|
|
58714
59283
|
throw new Error(
|
|
58715
59284
|
"Missing search query. Usage: openmates chats search <query>"
|
|
58716
59285
|
);
|
|
58717
|
-
const result = apiKey ? await searchApiKeyChats(client, apiKey, query) : client.hasSession() ? await client.searchChats(query) : searchExampleChats(query);
|
|
59286
|
+
const result = apiKey ? await searchApiKeyChats(client, apiKey, query) : client.hasSession() ? await client.searchChats(query, teamContext) : searchExampleChats(query);
|
|
58718
59287
|
if (flags.json === true) {
|
|
58719
59288
|
printJson2(result);
|
|
58720
59289
|
} else {
|
|
@@ -58746,6 +59315,7 @@ async function handleChats(client, subcommand, rest, flags, redactor) {
|
|
|
58746
59315
|
acceptTaskProposals: flags["accept-task-proposals"] === true,
|
|
58747
59316
|
piiDetection: flags["no-pii-detection"] !== true,
|
|
58748
59317
|
responseTimeoutMs: parseResponseTimeoutMs(flags),
|
|
59318
|
+
...teamContext,
|
|
58749
59319
|
anonymousLearningMode: client.hasSession() ? void 0 : parseAnonymousLearningModeFlags(flags)
|
|
58750
59320
|
},
|
|
58751
59321
|
redactor
|
|
@@ -58771,14 +59341,14 @@ async function handleChats(client, subcommand, rest, flags, redactor) {
|
|
|
58771
59341
|
);
|
|
58772
59342
|
process.exit(1);
|
|
58773
59343
|
}
|
|
58774
|
-
const fullId = await client.resolveFullChatId(chatId).catch(() => void 0);
|
|
59344
|
+
const fullId = await client.resolveFullChatId(chatId, teamContext).catch(() => void 0);
|
|
58775
59345
|
if (!fullId) {
|
|
58776
59346
|
console.error(
|
|
58777
59347
|
`Chat '${chatId}' not found. Run 'openmates chats list' to see available chats.`
|
|
58778
59348
|
);
|
|
58779
59349
|
process.exit(1);
|
|
58780
59350
|
}
|
|
58781
|
-
const suggestions = await client.getChatFollowUpSuggestions(fullId);
|
|
59351
|
+
const suggestions = await client.getChatFollowUpSuggestions(fullId, teamContext);
|
|
58782
59352
|
if (suggestions.length === 0) {
|
|
58783
59353
|
console.error(
|
|
58784
59354
|
`No follow-up suggestions stored for chat '${chatId}'.
|
|
@@ -58822,7 +59392,8 @@ Run 'openmates chats show ` + chatId + "' to check if suggestions have been save
|
|
|
58822
59392
|
autoApproveMemories: flags["auto-approve-memories"] === true,
|
|
58823
59393
|
acceptTaskProposals: flags["accept-task-proposals"] === true,
|
|
58824
59394
|
piiDetection: flags["no-pii-detection"] !== true,
|
|
58825
|
-
responseTimeoutMs: parseResponseTimeoutMs(flags)
|
|
59395
|
+
responseTimeoutMs: parseResponseTimeoutMs(flags),
|
|
59396
|
+
...teamContext
|
|
58826
59397
|
},
|
|
58827
59398
|
redactor
|
|
58828
59399
|
);
|
|
@@ -58852,7 +59423,8 @@ Run 'openmates chats show ` + chatId + "' to check if suggestions have been save
|
|
|
58852
59423
|
autoApproveMemories: flags["auto-approve-memories"] === true,
|
|
58853
59424
|
acceptTaskProposals: flags["accept-task-proposals"] === true,
|
|
58854
59425
|
piiDetection: flags["no-pii-detection"] !== true,
|
|
58855
|
-
responseTimeoutMs: parseResponseTimeoutMs(flags)
|
|
59426
|
+
responseTimeoutMs: parseResponseTimeoutMs(flags),
|
|
59427
|
+
...teamContext
|
|
58856
59428
|
},
|
|
58857
59429
|
redactor
|
|
58858
59430
|
);
|
|
@@ -58918,14 +59490,14 @@ Run 'openmates chats show ` + chatId + "' to check if suggestions have been save
|
|
|
58918
59490
|
}
|
|
58919
59491
|
return;
|
|
58920
59492
|
}
|
|
58921
|
-
const { chat, messages } = await client.getChatMessages(resolvedId);
|
|
59493
|
+
const { chat, messages } = await client.getChatMessages(resolvedId, teamContext);
|
|
58922
59494
|
if (flags.json === true) {
|
|
58923
|
-
const followUpSuggestions = await client.getChatFollowUpSuggestions(chat.id).catch(() => []);
|
|
59495
|
+
const followUpSuggestions = await client.getChatFollowUpSuggestions(chat.id, teamContext).catch(() => []);
|
|
58924
59496
|
printJson2({ chat, messages, follow_up_suggestions: followUpSuggestions });
|
|
58925
59497
|
} else if (flags.raw === true) {
|
|
58926
59498
|
await printChatConversationRaw(chat, messages);
|
|
58927
59499
|
} else {
|
|
58928
|
-
const followUpSuggestions = await client.getChatFollowUpSuggestions(chat.id).catch(() => []);
|
|
59500
|
+
const followUpSuggestions = await client.getChatFollowUpSuggestions(chat.id, teamContext).catch(() => []);
|
|
58929
59501
|
await printChatConversation(client, chat, messages, followUpSuggestions);
|
|
58930
59502
|
}
|
|
58931
59503
|
return;
|
|
@@ -58940,7 +59512,7 @@ Run 'openmates chats show ` + chatId + "' to check if suggestions have been save
|
|
|
58940
59512
|
const resolved = [];
|
|
58941
59513
|
for (const id of chatIds) {
|
|
58942
59514
|
try {
|
|
58943
|
-
const { chat } = await client.getChatMessages(id);
|
|
59515
|
+
const { chat } = await client.getChatMessages(id, teamContext);
|
|
58944
59516
|
resolved.push({ input: id, title: chat.title ?? null });
|
|
58945
59517
|
} catch {
|
|
58946
59518
|
resolved.push({ input: id, title: null });
|
|
@@ -58980,7 +59552,7 @@ Run 'openmates chats show ` + chatId + "' to check if suggestions have been save
|
|
|
58980
59552
|
{ confirmed: true }
|
|
58981
59553
|
);
|
|
58982
59554
|
} else {
|
|
58983
|
-
await client.deleteChat(r.input);
|
|
59555
|
+
await client.deleteChat(r.input, teamContext);
|
|
58984
59556
|
}
|
|
58985
59557
|
const label = r.title ? `"${r.title}"` : r.input;
|
|
58986
59558
|
process.stdout.write(` \x1B[32m\u2713\x1B[0m Deleted ${label}
|
|
@@ -59006,7 +59578,7 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
59006
59578
|
process.exit(1);
|
|
59007
59579
|
}
|
|
59008
59580
|
const resolvedId = chatId.toLowerCase() === "last" ? "__last__" : chatId;
|
|
59009
|
-
const { chat, messages } = await client.getChatMessages(resolvedId);
|
|
59581
|
+
const { chat, messages } = await client.getChatMessages(resolvedId, teamContext);
|
|
59010
59582
|
const outputDir = typeof flags.output === "string" ? flags.output : process.cwd();
|
|
59011
59583
|
const useZip = flags.zip === true;
|
|
59012
59584
|
const timestampMs = chat.updatedAt && chat.updatedAt < 1e12 ? chat.updatedAt * 1e3 : chat.updatedAt ?? Date.now();
|
|
@@ -59316,7 +59888,7 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
59316
59888
|
);
|
|
59317
59889
|
process.exit(1);
|
|
59318
59890
|
}
|
|
59319
|
-
const result = await client.listChats(n, 1);
|
|
59891
|
+
const result = await client.listChats(n, 1, teamContext);
|
|
59320
59892
|
if (result.total === 0) {
|
|
59321
59893
|
console.error(
|
|
59322
59894
|
"No chats found. Run 'openmates chats list' to sync."
|
|
@@ -59537,7 +60109,7 @@ async function handleWorkflows(client, subcommand, rest, flags) {
|
|
|
59537
60109
|
return;
|
|
59538
60110
|
}
|
|
59539
60111
|
if (subcommand === "list") {
|
|
59540
|
-
const workflows = await client.listWorkflows();
|
|
60112
|
+
const workflows = await client.listWorkflows(teamContextFromFlags(flags));
|
|
59541
60113
|
if (flags.json === true) {
|
|
59542
60114
|
printJson2(workflows);
|
|
59543
60115
|
} else {
|
|
@@ -59681,7 +60253,7 @@ async function handleWorkflows(client, subcommand, rest, flags) {
|
|
|
59681
60253
|
if (subcommand === "show") {
|
|
59682
60254
|
const workflowId = rest[0];
|
|
59683
60255
|
if (!workflowId) throw new Error("Missing workflow ID. Example: openmates workflows show <id>");
|
|
59684
|
-
const workflow = await client.getWorkflow(workflowId);
|
|
60256
|
+
const workflow = await client.getWorkflow(workflowId, teamContextFromFlags(flags));
|
|
59685
60257
|
if (flags.json === true) {
|
|
59686
60258
|
printJson2(workflow);
|
|
59687
60259
|
} else {
|
|
@@ -61334,8 +61906,8 @@ async function writeSecretFile(filePath, content, force = false) {
|
|
|
61334
61906
|
return filePath;
|
|
61335
61907
|
}
|
|
61336
61908
|
async function generateProvisioningPassword() {
|
|
61337
|
-
const { randomBytes:
|
|
61338
|
-
return `OM-${
|
|
61909
|
+
const { randomBytes: randomBytes6 } = await import("crypto");
|
|
61910
|
+
return `OM-${randomBytes6(18).toString("base64url")}-aA2#`;
|
|
61339
61911
|
}
|
|
61340
61912
|
function decodeBase32(input) {
|
|
61341
61913
|
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
@@ -62153,7 +62725,7 @@ async function handleMemories(client, rest, flags) {
|
|
|
62153
62725
|
if (action === "list") {
|
|
62154
62726
|
const appId = typeof flags["app-id"] === "string" ? flags["app-id"] : null;
|
|
62155
62727
|
const itemType = typeof flags["item-type"] === "string" ? flags["item-type"] : null;
|
|
62156
|
-
let result = await client.listMemories();
|
|
62728
|
+
let result = await client.listMemories(teamContextFromFlags(flags));
|
|
62157
62729
|
if (appId) result = result.filter((m) => m.app_id === appId);
|
|
62158
62730
|
if (itemType) result = result.filter((m) => m.item_type === itemType);
|
|
62159
62731
|
if (flags.json === true) {
|
|
@@ -62200,7 +62772,7 @@ Example: --data '{"name":"Python","proficiency":"advanced"}'`
|
|
|
62200
62772
|
process.exit(1);
|
|
62201
62773
|
}
|
|
62202
62774
|
const itemValue = JSON.parse(dataRaw);
|
|
62203
|
-
const result = await client.createMemory({ appId, itemType, itemValue });
|
|
62775
|
+
const result = await client.createMemory({ appId, itemType, itemValue, ...teamContextFromFlags(flags) });
|
|
62204
62776
|
if (flags.json === true) {
|
|
62205
62777
|
printJson2(result);
|
|
62206
62778
|
} else {
|
|
@@ -62232,7 +62804,8 @@ Example: --data '{"name":"Python","proficiency":"advanced"}'`
|
|
|
62232
62804
|
appId,
|
|
62233
62805
|
itemType,
|
|
62234
62806
|
itemValue,
|
|
62235
|
-
currentVersion
|
|
62807
|
+
currentVersion,
|
|
62808
|
+
...teamContextFromFlags(flags)
|
|
62236
62809
|
});
|
|
62237
62810
|
if (flags.json === true) {
|
|
62238
62811
|
printJson2(result);
|
|
@@ -62251,7 +62824,7 @@ Example: --data '{"name":"Python","proficiency":"advanced"}'`
|
|
|
62251
62824
|
);
|
|
62252
62825
|
process.exit(1);
|
|
62253
62826
|
}
|
|
62254
|
-
const result = await client.deleteMemory(entryId);
|
|
62827
|
+
const result = await client.deleteMemory(entryId, teamContextFromFlags(flags));
|
|
62255
62828
|
if (flags.json === true) {
|
|
62256
62829
|
printJson2(result);
|
|
62257
62830
|
} else {
|
|
@@ -62760,6 +63333,8 @@ async function sendMessageStreaming(client, params, redactor) {
|
|
|
62760
63333
|
const result = await client.sendMessage({
|
|
62761
63334
|
message: finalMessage,
|
|
62762
63335
|
chatId: params.chatId,
|
|
63336
|
+
teamId: params.teamId,
|
|
63337
|
+
personal: params.personal,
|
|
62763
63338
|
incognito: params.incognito,
|
|
62764
63339
|
onStream,
|
|
62765
63340
|
onSubChatEvent,
|
|
@@ -64272,6 +64847,7 @@ Commands:
|
|
|
64272
64847
|
openmates whoami [--json] Show account info
|
|
64273
64848
|
openmates chats [--help] Chat commands (list, search, show, ...)
|
|
64274
64849
|
openmates tasks [--help] Task commands (list, create, board, ...)
|
|
64850
|
+
openmates teams [--help] Team lifecycle, membership, billing, and move commands
|
|
64275
64851
|
openmates drafts [--help] Encrypted draft lifecycle commands
|
|
64276
64852
|
openmates apps [--help] App skill commands (list, run, ...)
|
|
64277
64853
|
openmates workflows [--help] Server-side workflow commands
|
|
@@ -64584,6 +65160,35 @@ Notes:
|
|
|
64584
65160
|
Labels organize tasks privately. --tag, --tags, --add-tag, and --remove-tag are accepted aliases.
|
|
64585
65161
|
Normal output decrypts task title, description, and labels locally; use --json for machine-readable plaintext fields.`);
|
|
64586
65162
|
}
|
|
65163
|
+
function printTeamsHelp() {
|
|
65164
|
+
console.log(`Teams commands:
|
|
65165
|
+
openmates teams list [--json]
|
|
65166
|
+
openmates teams switch <team-id> [--json]
|
|
65167
|
+
openmates teams personal [--json]
|
|
65168
|
+
openmates teams show <team-id> [--json]
|
|
65169
|
+
openmates teams create --name <name> [--description <description>] [--slug <slug>] [--switch] [--json]
|
|
65170
|
+
openmates teams update <team-id> [--name <encrypted-name>] [--description <encrypted-description>] [--slug <slug>] [--json]
|
|
65171
|
+
openmates teams delete <team-id> --yes [--json]
|
|
65172
|
+
openmates teams invite <team-id> (--email <email>|--user <user-id>) [--role admin|member|viewer] [--json]
|
|
65173
|
+
openmates teams accept-invite <invite-id> [--json]
|
|
65174
|
+
openmates teams decline-invite <invite-id> [--json]
|
|
65175
|
+
openmates teams access-requests <team-id> [--status pending_access_approval|all] [--json]
|
|
65176
|
+
openmates teams approve-access <team-id> <access-request-id> --encrypted-team-key <value> [--json]
|
|
65177
|
+
openmates teams reject-access <team-id> <access-request-id> [--json]
|
|
65178
|
+
openmates teams role <team-id> --user <user-id> --role admin|member|viewer [--json]
|
|
65179
|
+
openmates teams remove-member <team-id> --user <user-id> [--json]
|
|
65180
|
+
openmates teams billing <team-id> [--json]
|
|
65181
|
+
openmates teams add-credits <team-id> --credits <amount> [--json]
|
|
65182
|
+
openmates teams usage <team-id> [--user <user-id>] [--json]
|
|
65183
|
+
openmates teams move <team-id> --type chat|project|task|plan|workflow --id <resource-id> --yes [--json]
|
|
65184
|
+
openmates teams export <team-id> --output <path> [--json]
|
|
65185
|
+
openmates teams import --file <path> (--team <team-id>|--new-team-name <name>) [--json]
|
|
65186
|
+
|
|
65187
|
+
Context:
|
|
65188
|
+
openmates teams switch <team-id> persists the active team for team-aware commands.
|
|
65189
|
+
openmates teams personal clears the active team and returns commands to personal context.
|
|
65190
|
+
Team V1 only supports team-wide workspace visibility.`);
|
|
65191
|
+
}
|
|
64587
65192
|
function printDraftsHelp() {
|
|
64588
65193
|
console.log(`Draft commands:
|
|
64589
65194
|
openmates drafts create <text> [--chat <uuid>] [--preview <text>] [--json]
|