@awiki/dsh-plugin 0.3.18 → 0.3.19
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/README.zh.md +11 -0
- package/lib/client.js +644 -100
- package/lib/client.js.map +1 -1
- package/lib/index.js +389 -24
- package/lib/{package-version.generated-D0MSDRZn.mjs → package-version.generated-nZcAVnm8.mjs} +22 -2
- package/lib/provider.js +1 -1
- package/lib/typert.host.js +204 -138
- package/lib/typert.remote-client.d.ts +2 -0
- package/lib/typert.remote-client.d.ts.map +1 -1
- package/lib/typert.remote-client.js +204 -138
- package/lib/types/backend-capabilities.d.ts +12 -0
- package/lib/types/backend-capabilities.d.ts.map +1 -0
- package/lib/types/backend-capabilities.js +48 -0
- package/lib/types/backend-capabilities.js.map +1 -0
- package/lib/types/client/AwikiIdentityAccess.d.ts.map +1 -1
- package/lib/types/client/AwikiIdentityAccess.js +11 -2
- package/lib/types/client/AwikiIdentityAccess.js.map +1 -1
- package/lib/types/client/AwikiOverlay.d.ts.map +1 -1
- package/lib/types/client/AwikiOverlay.js +10 -7
- package/lib/types/client/AwikiOverlay.js.map +1 -1
- package/lib/types/client/AwikiSettingsSection.d.ts +1 -0
- package/lib/types/client/AwikiSettingsSection.d.ts.map +1 -1
- package/lib/types/client/AwikiSettingsSection.js +5 -4
- package/lib/types/client/AwikiSettingsSection.js.map +1 -1
- package/lib/types/client/controller.d.ts +7 -0
- package/lib/types/client/controller.d.ts.map +1 -1
- package/lib/types/client/controller.js +39 -3
- package/lib/types/client/controller.js.map +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +1 -0
- package/lib/types/client/index.js.map +1 -1
- package/lib/types/client/settings-locales.d.ts +1 -1
- package/lib/types/client/settings-locales.d.ts.map +1 -1
- package/lib/types/client/settings-locales.js +26 -2
- package/lib/types/client/settings-locales.js.map +1 -1
- package/lib/types/index.d.ts +18 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +248 -25
- package/lib/types/index.js.map +1 -1
- package/lib/types/package-version.generated.d.ts +2 -2
- package/lib/types/package-version.generated.js +2 -2
- package/lib/types/provider-api.d.ts +19 -0
- package/lib/types/provider-api.d.ts.map +1 -1
- package/lib/types/sdk-adapter.d.ts +4 -0
- package/lib/types/sdk-adapter.d.ts.map +1 -1
- package/lib/types/sdk-adapter.js +20 -0
- package/lib/types/sdk-adapter.js.map +1 -1
- package/lib/types/tenant-capability-cache.d.ts +15 -0
- package/lib/types/tenant-capability-cache.d.ts.map +1 -0
- package/lib/types/tenant-capability-cache.js +45 -0
- package/lib/types/tenant-capability-cache.js.map +1 -0
- package/lib/types/types.d.ts +8 -1
- package/lib/types/types.d.ts.map +1 -1
- package/lib/types/types.js.map +1 -1
- package/lib/types/update-policy.d.ts +2 -2
- package/lib/types/update-policy.d.ts.map +1 -1
- package/lib/types/update-policy.js +10 -1
- package/lib/types/update-policy.js.map +1 -1
- package/package.json +2 -2
package/lib/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { a as downloadedAttachment, c as successfulMailRecoveryObservability, l as isMessageTarget, n as DSH_AWIKI_PACKAGE_VERSION, o as failedMailRecoveryObservability, r as AwikiSdkError, s as fencedMailRecoveryObservability, t as DSH_AWIKI_MODEL_PROXY_PACKAGE_VERSION } from "./package-version.generated-
|
|
2
|
-
import "@deepseek-ai/cordis";
|
|
1
|
+
import { a as downloadedAttachment, c as successfulMailRecoveryObservability, l as isMessageTarget, n as DSH_AWIKI_PACKAGE_VERSION, o as failedMailRecoveryObservability, r as AwikiSdkError, s as fencedMailRecoveryObservability, t as DSH_AWIKI_MODEL_PROXY_PACKAGE_VERSION } from "./package-version.generated-nZcAVnm8.mjs";
|
|
3
2
|
import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
|
|
4
|
-
import {
|
|
3
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
5
4
|
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
5
|
+
import "@deepseek-ai/cordis";
|
|
6
|
+
import { homedir } from "node:os";
|
|
6
7
|
import z from "@deepseek-ai/schemastery";
|
|
7
8
|
import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
8
9
|
import { SettingsConflictError } from "@deepseek-ai/dsh-settings";
|
|
@@ -12,8 +13,122 @@ import { SessionId, SessionLogOffset } from "@deepseek-ai/dsh-session";
|
|
|
12
13
|
import { installModelSelection } from "@deepseek-ai/dsh-agent";
|
|
13
14
|
import { createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
14
15
|
import { fileURLToPath } from "node:url";
|
|
15
|
-
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
16
16
|
import { satisfies, validRange } from "semver";
|
|
17
|
+
//#region lib/types/tenant-capability-cache.js
|
|
18
|
+
/** Host-only metadata. Core owns feature truth; this contains no auth material. */
|
|
19
|
+
var TenantCapabilityCache = class {
|
|
20
|
+
key;
|
|
21
|
+
directory;
|
|
22
|
+
path;
|
|
23
|
+
constructor(stateRoot, endpoint) {
|
|
24
|
+
this.key = createHash("sha256").update(JSON.stringify([
|
|
25
|
+
endpoint,
|
|
26
|
+
stateRoot,
|
|
27
|
+
1
|
|
28
|
+
])).digest("hex");
|
|
29
|
+
this.directory = join(stateRoot, "cache", "tenant-capabilities-v1");
|
|
30
|
+
this.path = join(this.directory, `${this.key}.json`);
|
|
31
|
+
}
|
|
32
|
+
read(validate) {
|
|
33
|
+
try {
|
|
34
|
+
const bytes = readFileSync(this.path);
|
|
35
|
+
if (bytes.length > 16384) return void 0;
|
|
36
|
+
const value = JSON.parse(bytes.toString("utf8"));
|
|
37
|
+
if (value.version !== 1 || value.key !== this.key || typeof value.metadata?.handleRecoveryPhoneEnabled !== "boolean") return void 0;
|
|
38
|
+
return validate(value.metadata);
|
|
39
|
+
} catch {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
write(metadata) {
|
|
44
|
+
const temporary = `${this.path}.${randomUUID()}.tmp`;
|
|
45
|
+
try {
|
|
46
|
+
mkdirSync(this.directory, {
|
|
47
|
+
recursive: true,
|
|
48
|
+
mode: 448
|
|
49
|
+
});
|
|
50
|
+
writeFileSync(temporary, JSON.stringify({
|
|
51
|
+
version: 1,
|
|
52
|
+
key: this.key,
|
|
53
|
+
metadata
|
|
54
|
+
}), {
|
|
55
|
+
mode: 384,
|
|
56
|
+
flag: "wx"
|
|
57
|
+
});
|
|
58
|
+
renameSync(temporary, this.path);
|
|
59
|
+
return true;
|
|
60
|
+
} catch {
|
|
61
|
+
try {
|
|
62
|
+
unlinkSync(temporary);
|
|
63
|
+
} catch {}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region lib/types/backend-capabilities.js
|
|
70
|
+
/** Keep the client ceiling and only project a confirmed positive byte limit. */
|
|
71
|
+
function backendAttachmentMaxBytes(snapshot, clientLimit) {
|
|
72
|
+
if (snapshot?.status !== "confirmed" && snapshot?.status !== "stale") return clientLimit;
|
|
73
|
+
const capability = snapshot.capabilities.attachments;
|
|
74
|
+
if (capability?.support !== "supported") return clientLimit;
|
|
75
|
+
const raw = capability.limits?.max_object_bytes;
|
|
76
|
+
const value = typeof raw === "number" ? raw : typeof raw === "string" && /^\d+$/.test(raw) ? Number(raw) : NaN;
|
|
77
|
+
return Number.isSafeInteger(value) && value > 0 ? Math.min(clientLimit, value) : clientLimit;
|
|
78
|
+
}
|
|
79
|
+
const PUBLIC = [
|
|
80
|
+
"registration.handle_only",
|
|
81
|
+
"identity.multi_device",
|
|
82
|
+
"identity.device_revoke",
|
|
83
|
+
"identity.capability_upgrade",
|
|
84
|
+
"identity.root_transfer",
|
|
85
|
+
"agents.managed_agents",
|
|
86
|
+
"agents.daemon",
|
|
87
|
+
"services.mail",
|
|
88
|
+
"services.model_proxy",
|
|
89
|
+
"services.guest_gateway",
|
|
90
|
+
"account.state_sync",
|
|
91
|
+
"content.pages",
|
|
92
|
+
"content.sites",
|
|
93
|
+
"content.hosting",
|
|
94
|
+
"client_updates.policy"
|
|
95
|
+
];
|
|
96
|
+
const MESSAGE = [
|
|
97
|
+
"direct",
|
|
98
|
+
"groups",
|
|
99
|
+
"attachments",
|
|
100
|
+
"direct_e2ee",
|
|
101
|
+
"group_e2ee",
|
|
102
|
+
"encrypted_attachments",
|
|
103
|
+
"group_open_join",
|
|
104
|
+
"group_admin_add"
|
|
105
|
+
];
|
|
106
|
+
/** Project one source independently so a failed source cannot erase its peer. */
|
|
107
|
+
function projectBackendSnapshot(snapshot, authenticated) {
|
|
108
|
+
const result = {};
|
|
109
|
+
for (const key of authenticated ? MESSAGE : PUBLIC) {
|
|
110
|
+
const support = snapshot?.capabilities[key]?.support;
|
|
111
|
+
result[key] = (snapshot?.status === "confirmed" || snapshot?.status === "stale") && (support === "supported" || support === "unsupported") ? support : "unknown";
|
|
112
|
+
}
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
/** Copy only allowlisted support states. Browser never sees endpoints or SDK errors. */
|
|
116
|
+
async function projectBackendFeatures(client, authenticated) {
|
|
117
|
+
const sources = await Promise.allSettled([client.backendCapabilities?.(false, false), ...authenticated ? [client.backendCapabilities?.(true, false)] : []]);
|
|
118
|
+
const result = {};
|
|
119
|
+
for (const [index, source] of sources.entries()) if (source.status === "fulfilled") Object.assign(result, projectBackendSnapshot(source.value, index === 1));
|
|
120
|
+
else throw source.reason;
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
async function requireBackendFeature(client, key) {
|
|
124
|
+
const snapshot = await client.backendCapabilities?.(!key.includes("."), false);
|
|
125
|
+
const support = snapshot?.status === "confirmed" || snapshot?.status === "stale" ? snapshot.capabilities[key]?.support : "unknown";
|
|
126
|
+
if (support !== "supported") throw Object.assign(/* @__PURE__ */ new Error("Server feature unavailable"), {
|
|
127
|
+
name: "AwikiSdkError",
|
|
128
|
+
code: support === "unsupported" ? "backend-not-supported" : "backend-unconfirmed"
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
//#endregion
|
|
17
132
|
//#region lib/types/builtin-tenant-config.js
|
|
18
133
|
/** Build-injected two-slot tenant catalog with a source-tree default for tests. */
|
|
19
134
|
function record$2(value) {
|
|
@@ -3718,6 +3833,7 @@ async function checkAwikiUpdatePolicy(options) {
|
|
|
3718
3833
|
signal.throwIfAborted();
|
|
3719
3834
|
const endpoint = new URL("/user-service/v1/server-info", origin);
|
|
3720
3835
|
endpoint.searchParams.set("client_platform", "dsh");
|
|
3836
|
+
endpoint.searchParams.set("capabilities_version", "1");
|
|
3721
3837
|
const response = await bounded((options.fetcher ?? fetch)(endpoint, {
|
|
3722
3838
|
method: "GET",
|
|
3723
3839
|
headers: {
|
|
@@ -3746,7 +3862,19 @@ async function checkAwikiUpdatePolicy(options) {
|
|
|
3746
3862
|
const bytes = await bounded(readPolicyBody(response));
|
|
3747
3863
|
signal.throwIfAborted();
|
|
3748
3864
|
if (bytes.byteLength > MAX_POLICY_BYTES) throw new Error("policy response exceeds 1 MiB");
|
|
3749
|
-
const
|
|
3865
|
+
const document = JSON.parse(Buffer.from(bytes).toString("utf8"));
|
|
3866
|
+
if (isRecord(document) && document.schema_version === 1 && document.capabilities_version === 1 && isRecord(document.client_updates) && isRecord(document.client_updates.policy) && document.client_updates.policy.protocol_version === 1 && document.client_updates.policy.enabled === false) return {
|
|
3867
|
+
...cached === void 0 ? {
|
|
3868
|
+
...base,
|
|
3869
|
+
usedCache: false,
|
|
3870
|
+
restricted: false,
|
|
3871
|
+
modelProxyRestricted: false
|
|
3872
|
+
} : statusFromPolicy(base, cached.policy, cached.checkedAt, false, true, options.installedRuntime),
|
|
3873
|
+
offline: false,
|
|
3874
|
+
policyUnavailable: true,
|
|
3875
|
+
checkState: "unavailable"
|
|
3876
|
+
};
|
|
3877
|
+
const policy = decodeServerInfoPolicy(document, origin, cached?.policy.policy_revision);
|
|
3750
3878
|
if (policy === void 0) {
|
|
3751
3879
|
rmSync(cachePath, { force: true });
|
|
3752
3880
|
return {
|
|
@@ -4076,6 +4204,8 @@ const Config = z.object({
|
|
|
4076
4204
|
summaryMaxInputBytes: z.number().default(DEFAULT_SUMMARY_MAX_INPUT_BYTES)
|
|
4077
4205
|
});
|
|
4078
4206
|
const FAILURE_CODES = /* @__PURE__ */ new Set([
|
|
4207
|
+
"backend-not-supported",
|
|
4208
|
+
"backend-unconfirmed",
|
|
4079
4209
|
"client-version-unsupported",
|
|
4080
4210
|
"not-registered",
|
|
4081
4211
|
"signed-out",
|
|
@@ -4116,6 +4246,8 @@ const RESUMABLE_JOIN_PHASES = /* @__PURE__ */ new Set([
|
|
|
4116
4246
|
"approval_prepared"
|
|
4117
4247
|
]);
|
|
4118
4248
|
const FAILURE_MESSAGES = {
|
|
4249
|
+
"backend-not-supported": "This server does not support this feature.",
|
|
4250
|
+
"backend-unconfirmed": "Server features are not confirmed yet. Please retry.",
|
|
4119
4251
|
"client-version-unsupported": "This AWiki plugin version is not supported by the active tenant. Update the plugin or switch tenants.",
|
|
4120
4252
|
"not-registered": "No AWiki identity is registered for this deployment.",
|
|
4121
4253
|
"signed-out": "This installation is signed out of AWiki.",
|
|
@@ -4198,7 +4330,7 @@ function publishedServiceBaseUrl(services, name, allowInsecureLoopbackForTesting
|
|
|
4198
4330
|
const candidate = services[name];
|
|
4199
4331
|
if (typeof candidate !== "object" || candidate === null || Array.isArray(candidate)) return void 0;
|
|
4200
4332
|
const value = candidate;
|
|
4201
|
-
if (value.enabled !== true || typeof value.base_url !== "string") return void 0;
|
|
4333
|
+
if (value.enabled !== true || value.protocol_version !== 1 || typeof value.base_url !== "string") return void 0;
|
|
4202
4334
|
try {
|
|
4203
4335
|
const baseUrl = serviceUrl(`server-info.services.${name}.base_url`, value.base_url, allowInsecureLoopbackForTesting);
|
|
4204
4336
|
if (new URL(baseUrl).search !== "") return void 0;
|
|
@@ -4649,6 +4781,7 @@ let AwikiService = (() => {
|
|
|
4649
4781
|
let _classSuper = TypertRemoteService;
|
|
4650
4782
|
let _instanceExtraInitializers = [];
|
|
4651
4783
|
let _getConfig_decorators;
|
|
4784
|
+
let _refreshBackendCapabilities_decorators;
|
|
4652
4785
|
let _getIntegration_decorators;
|
|
4653
4786
|
let _createIntegration_decorators;
|
|
4654
4787
|
let _updateIntegration_decorators;
|
|
@@ -4721,6 +4854,7 @@ let AwikiService = (() => {
|
|
|
4721
4854
|
static {
|
|
4722
4855
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
4723
4856
|
_getConfig_decorators = [Remote];
|
|
4857
|
+
_refreshBackendCapabilities_decorators = [Remote];
|
|
4724
4858
|
_getIntegration_decorators = [Remote];
|
|
4725
4859
|
_createIntegration_decorators = [Remote];
|
|
4726
4860
|
_updateIntegration_decorators = [Remote];
|
|
@@ -4800,6 +4934,17 @@ let AwikiService = (() => {
|
|
|
4800
4934
|
},
|
|
4801
4935
|
metadata: _metadata
|
|
4802
4936
|
}, null, _instanceExtraInitializers);
|
|
4937
|
+
__esDecorate(this, null, _refreshBackendCapabilities_decorators, {
|
|
4938
|
+
kind: "method",
|
|
4939
|
+
name: "refreshBackendCapabilities",
|
|
4940
|
+
static: false,
|
|
4941
|
+
private: false,
|
|
4942
|
+
access: {
|
|
4943
|
+
has: (obj) => "refreshBackendCapabilities" in obj,
|
|
4944
|
+
get: (obj) => obj.refreshBackendCapabilities
|
|
4945
|
+
},
|
|
4946
|
+
metadata: _metadata
|
|
4947
|
+
}, null, _instanceExtraInitializers);
|
|
4803
4948
|
__esDecorate(this, null, _getIntegration_decorators, {
|
|
4804
4949
|
kind: "method",
|
|
4805
4950
|
name: "getIntegration",
|
|
@@ -5572,6 +5717,15 @@ let AwikiService = (() => {
|
|
|
5572
5717
|
tenantSwitching = false;
|
|
5573
5718
|
tenantParticipants = /* @__PURE__ */ new Set();
|
|
5574
5719
|
activeCapabilities;
|
|
5720
|
+
backendFeatures = {};
|
|
5721
|
+
backendDiagnostics = {};
|
|
5722
|
+
backendFeaturesTask;
|
|
5723
|
+
backendFeaturesRevision = -1;
|
|
5724
|
+
backendSubscriptions = /* @__PURE__ */ new Map();
|
|
5725
|
+
backendSubscriptionPending = /* @__PURE__ */ new Set();
|
|
5726
|
+
backendAttachmentLimit;
|
|
5727
|
+
capabilityDiscoveryTask;
|
|
5728
|
+
capabilityDiscoveryAt = 0;
|
|
5575
5729
|
updatePolicyStatus;
|
|
5576
5730
|
updatePolicyRequest;
|
|
5577
5731
|
updatePolicyTask;
|
|
@@ -5668,6 +5822,7 @@ let AwikiService = (() => {
|
|
|
5668
5822
|
registerAwikiTools(ctx, this);
|
|
5669
5823
|
ctx.effect(() => async () => {
|
|
5670
5824
|
this.updatePolicyRequest?.abort();
|
|
5825
|
+
this.stopBackendSubscriptions();
|
|
5671
5826
|
const provider = this.provider;
|
|
5672
5827
|
if (provider !== void 0) await this.disposeProvider(provider);
|
|
5673
5828
|
}, "awiki: dispose current client provider");
|
|
@@ -5751,12 +5906,49 @@ let AwikiService = (() => {
|
|
|
5751
5906
|
this.conversationPreferenceStore = new AwikiConversationPreferenceStore(options.stateRoot);
|
|
5752
5907
|
this.mailListClient = new AwikiMailListClient(options.mailServiceUrl, this.externalHttpAuth);
|
|
5753
5908
|
this.integrationClient = void 0;
|
|
5909
|
+
this.stopBackendSubscriptions();
|
|
5910
|
+
this.backendFeatures = {};
|
|
5911
|
+
this.backendDiagnostics = {};
|
|
5912
|
+
this.backendFeaturesRevision = -1;
|
|
5913
|
+
this.backendFeaturesTask = void 0;
|
|
5914
|
+
this.backendAttachmentLimit = void 0;
|
|
5915
|
+
this.capabilityDiscoveryTask = void 0;
|
|
5916
|
+
this.capabilityDiscoveryAt = 0;
|
|
5754
5917
|
this.activeCapabilities = {
|
|
5755
5918
|
tenantId: tenant.tenantId,
|
|
5756
5919
|
generation: this.runtimeGeneration,
|
|
5757
5920
|
online: false,
|
|
5758
5921
|
handleRecoveryPhoneEnabled: false
|
|
5759
5922
|
};
|
|
5923
|
+
const metadata = new TenantCapabilityCache(options.stateRoot, options.userServiceUrl).read((value) => {
|
|
5924
|
+
const services = {
|
|
5925
|
+
model_proxy: {
|
|
5926
|
+
enabled: true,
|
|
5927
|
+
protocol_version: 1,
|
|
5928
|
+
base_url: value.modelProxyBaseUrl
|
|
5929
|
+
},
|
|
5930
|
+
guest_gateway: {
|
|
5931
|
+
enabled: true,
|
|
5932
|
+
protocol_version: 1,
|
|
5933
|
+
base_url: value.guestGatewayBaseUrl
|
|
5934
|
+
}
|
|
5935
|
+
};
|
|
5936
|
+
const modelProxyBaseUrl = publishedServiceBaseUrl(services, "model_proxy", this.resolved.allowInsecureLoopbackForTesting);
|
|
5937
|
+
const guestGatewayBaseUrl = publishedServiceBaseUrl(services, "guest_gateway", false);
|
|
5938
|
+
return {
|
|
5939
|
+
handleRecoveryPhoneEnabled: value.handleRecoveryPhoneEnabled,
|
|
5940
|
+
...modelProxyBaseUrl === void 0 ? {} : { modelProxyBaseUrl },
|
|
5941
|
+
...guestGatewayBaseUrl === void 0 ? {} : { guestGatewayBaseUrl }
|
|
5942
|
+
};
|
|
5943
|
+
});
|
|
5944
|
+
if (metadata !== void 0) {
|
|
5945
|
+
this.activeCapabilities = {
|
|
5946
|
+
...this.activeCapabilities,
|
|
5947
|
+
...metadata,
|
|
5948
|
+
online: true
|
|
5949
|
+
};
|
|
5950
|
+
this.integrationClient = metadata.guestGatewayBaseUrl === void 0 ? void 0 : new AwikiIntegrationClient(metadata.guestGatewayBaseUrl, this.externalHttpAuth);
|
|
5951
|
+
}
|
|
5760
5952
|
this.signedOut = void 0;
|
|
5761
5953
|
this.activeIdentityDid = void 0;
|
|
5762
5954
|
this.pendingDeviceJoin = void 0;
|
|
@@ -5934,7 +6126,7 @@ let AwikiService = (() => {
|
|
|
5934
6126
|
await this.sessionStore.signIn();
|
|
5935
6127
|
this.signedOut = false;
|
|
5936
6128
|
}
|
|
5937
|
-
|
|
6129
|
+
Promise.all([this.refreshTenantCapabilities(), this.refreshUpdatePolicy()]).catch(() => void 0);
|
|
5938
6130
|
registry.commitActive(target.tenantId);
|
|
5939
6131
|
committed = true;
|
|
5940
6132
|
for (const participant of prepared) await participant.commitSwitch?.(context);
|
|
@@ -6012,16 +6204,22 @@ let AwikiService = (() => {
|
|
|
6012
6204
|
*/
|
|
6013
6205
|
async getConfig() {
|
|
6014
6206
|
this.ensureTenantOptions();
|
|
6015
|
-
|
|
6016
|
-
if (this.tenantSwitching || capabilities.generation !== this.runtimeGeneration || capabilities.tenantId !== this.activeTenant?.tenantId) return {
|
|
6207
|
+
if (this.runtimeGeneration !== this.runtimeGeneration) return {
|
|
6017
6208
|
ok: false,
|
|
6018
6209
|
error: failure("conflict")
|
|
6019
6210
|
};
|
|
6211
|
+
const capabilities = this.activeCapabilities;
|
|
6212
|
+
this.refreshBackendProjection();
|
|
6213
|
+
this.refreshTenantCapabilities(false).catch(() => void 0);
|
|
6214
|
+
const serverFeatures = this.backendFeatures;
|
|
6215
|
+
const attachmentMaxBytes = this.backendAttachmentLimit ?? this.resolved.attachmentMaxBytes;
|
|
6020
6216
|
return {
|
|
6021
6217
|
ok: true,
|
|
6022
6218
|
value: {
|
|
6219
|
+
serverFeatures,
|
|
6220
|
+
serverFeatureDiagnostics: this.backendDiagnostics,
|
|
6023
6221
|
pollIntervalMs: this.resolved.pollIntervalMs,
|
|
6024
|
-
attachmentMaxBytes
|
|
6222
|
+
attachmentMaxBytes,
|
|
6025
6223
|
mailAttachmentMaxCount: this.resolved.mailAttachmentMaxCount,
|
|
6026
6224
|
mailAttachmentMaxBytes: Math.min(this.resolved.mailAttachmentMaxBytes, MAIL_HTTP_UPLOAD_MAX_BYTES),
|
|
6027
6225
|
mailAttachmentDownloadMaxBytes: this.resolved.mailAttachmentMaxBytes,
|
|
@@ -6029,7 +6227,7 @@ let AwikiService = (() => {
|
|
|
6029
6227
|
handleRecoveryPhoneEnabled: capabilities.handleRecoveryPhoneEnabled,
|
|
6030
6228
|
...capabilities.guestGatewayBaseUrl === void 0 ? {} : { integrationGuideUrl: new URL("/guest/guide/integration", capabilities.guestGatewayBaseUrl).toString() },
|
|
6031
6229
|
tenantId: capabilities.tenantId,
|
|
6032
|
-
tenantStorageScopeId: this.activeTenant
|
|
6230
|
+
tenantStorageScopeId: this.activeTenant.storageScopeId,
|
|
6033
6231
|
tenantGeneration: capabilities.generation,
|
|
6034
6232
|
tenantOnline: capabilities.online,
|
|
6035
6233
|
services: {
|
|
@@ -6039,6 +6237,17 @@ let AwikiService = (() => {
|
|
|
6039
6237
|
}
|
|
6040
6238
|
};
|
|
6041
6239
|
}
|
|
6240
|
+
/** Explicit discovery retry; ordinary config reads retain their zero-argument contract. */
|
|
6241
|
+
async refreshBackendCapabilities() {
|
|
6242
|
+
this.ensureTenantOptions();
|
|
6243
|
+
const generation = this.runtimeGeneration;
|
|
6244
|
+
await Promise.allSettled([this.refreshTenantCapabilities(true), this.refreshBackendProjection(true)]);
|
|
6245
|
+
if (generation !== this.runtimeGeneration) return {
|
|
6246
|
+
ok: false,
|
|
6247
|
+
error: failure("conflict")
|
|
6248
|
+
};
|
|
6249
|
+
return this.getConfig();
|
|
6250
|
+
}
|
|
6042
6251
|
/** Trusted same-process capability binding for optional tenant participants. */
|
|
6043
6252
|
getTenantCapabilities() {
|
|
6044
6253
|
const capabilities = this.activeCapabilities;
|
|
@@ -6046,16 +6255,117 @@ let AwikiService = (() => {
|
|
|
6046
6255
|
return { ...capabilities };
|
|
6047
6256
|
}
|
|
6048
6257
|
/** Refresh the active tenant's optional service advertisement without affecting Core availability. */
|
|
6049
|
-
refreshTenantCapabilities() {
|
|
6258
|
+
refreshTenantCapabilities(force = true) {
|
|
6050
6259
|
this.ensureTenantOptions();
|
|
6051
|
-
return this.
|
|
6260
|
+
if (this.capabilityDiscoveryTask !== void 0) return this.capabilityDiscoveryTask;
|
|
6261
|
+
if (!force && Date.now() - this.capabilityDiscoveryAt < 3e5 && this.activeCapabilities !== void 0) return Promise.resolve(this.activeCapabilities);
|
|
6262
|
+
const generation = this.runtimeGeneration;
|
|
6263
|
+
const task = this.discoverTenantCapabilities(1e4).finally(() => {
|
|
6264
|
+
if (this.runtimeGeneration === generation && this.capabilityDiscoveryTask === task) {
|
|
6265
|
+
this.capabilityDiscoveryTask = void 0;
|
|
6266
|
+
this.capabilityDiscoveryAt = Date.now();
|
|
6267
|
+
}
|
|
6268
|
+
});
|
|
6269
|
+
this.capabilityDiscoveryTask = task;
|
|
6270
|
+
return task;
|
|
6271
|
+
}
|
|
6272
|
+
refreshBackendProjection(force = false) {
|
|
6273
|
+
const provider = this.provider;
|
|
6274
|
+
if (provider === void 0) return Promise.resolve();
|
|
6275
|
+
if (this.backendFeaturesTask !== void 0) return this.backendFeaturesTask;
|
|
6276
|
+
const revision = this.sessionRevision;
|
|
6277
|
+
const generation = this.runtimeGeneration;
|
|
6278
|
+
if (this.backendFeaturesRevision !== revision) {
|
|
6279
|
+
this.backendFeatures = Object.fromEntries(Object.entries(this.backendFeatures).filter(([key]) => key.includes(".")));
|
|
6280
|
+
this.backendAttachmentLimit = void 0;
|
|
6281
|
+
this.backendDiagnostics = this.backendDiagnostics.public === void 0 ? {} : { public: this.backendDiagnostics.public };
|
|
6282
|
+
this.backendFeaturesRevision = revision;
|
|
6283
|
+
}
|
|
6284
|
+
const current = () => provider === this.provider && revision === this.sessionRevision && generation === this.runtimeGeneration;
|
|
6285
|
+
const task = (async () => {
|
|
6286
|
+
const authenticated = !await this.isSignedOut() && await provider.client.getIdentity() !== null;
|
|
6287
|
+
await Promise.all([false, ...authenticated ? [true] : []].map(async (local) => {
|
|
6288
|
+
try {
|
|
6289
|
+
this.observeBackendProjection(provider, local, current);
|
|
6290
|
+
const snapshot = await provider.client.backendCapabilities?.(local, force);
|
|
6291
|
+
if (!current()) return;
|
|
6292
|
+
if (snapshot === void 0) return;
|
|
6293
|
+
if (this.backendSubscriptions.has(local)) return;
|
|
6294
|
+
this.recordBackendDiagnostics(local, snapshot);
|
|
6295
|
+
if (snapshot.status === "unavailable") return;
|
|
6296
|
+
this.backendFeatures = {
|
|
6297
|
+
...this.backendFeatures,
|
|
6298
|
+
...projectBackendSnapshot(snapshot, local)
|
|
6299
|
+
};
|
|
6300
|
+
if (local) this.backendAttachmentLimit = backendAttachmentMaxBytes(snapshot, this.resolved.attachmentMaxBytes);
|
|
6301
|
+
if (this.backendFeatures["agents.managed_agents"] === "unsupported") await this.detachAgentConsumer(provider);
|
|
6302
|
+
else if (this.backendFeatures["agents.managed_agents"] === "supported") this.ensureAgentConsumer(provider);
|
|
6303
|
+
} catch (error) {
|
|
6304
|
+
if (current()) this.ctx.logger("awiki-capabilities").debug("AWiki capability refresh failed: %s", error instanceof AwikiSdkError ? error.code : "unavailable");
|
|
6305
|
+
}
|
|
6306
|
+
}));
|
|
6307
|
+
})().finally(() => {
|
|
6308
|
+
if (this.backendFeaturesTask === task) this.backendFeaturesTask = void 0;
|
|
6309
|
+
});
|
|
6310
|
+
this.backendFeaturesTask = task;
|
|
6311
|
+
task.catch(() => void 0);
|
|
6312
|
+
return task;
|
|
6313
|
+
}
|
|
6314
|
+
recordBackendDiagnostics(local, snapshot) {
|
|
6315
|
+
this.backendDiagnostics = {
|
|
6316
|
+
...this.backendDiagnostics,
|
|
6317
|
+
[local ? "message" : "public"]: {
|
|
6318
|
+
...typeof snapshot.fetched_at === "number" ? { fetchedAt: snapshot.fetched_at } : {},
|
|
6319
|
+
...snapshot.refresh_error === void 0 ? {} : { refreshError: snapshot.refresh_error }
|
|
6320
|
+
}
|
|
6321
|
+
};
|
|
6322
|
+
}
|
|
6323
|
+
stopBackendSubscriptions() {
|
|
6324
|
+
for (const subscription of this.backendSubscriptions.values()) subscription.stop();
|
|
6325
|
+
this.backendSubscriptions.clear();
|
|
6326
|
+
this.backendSubscriptionPending.clear();
|
|
6327
|
+
}
|
|
6328
|
+
observeBackendProjection(provider, local, current) {
|
|
6329
|
+
const subscribe = provider.client.subscribeBackendCapabilities;
|
|
6330
|
+
if (subscribe === void 0 || this.backendSubscriptions.has(local) || this.backendSubscriptionPending.has(local)) return;
|
|
6331
|
+
this.backendSubscriptionPending.add(local);
|
|
6332
|
+
(async () => {
|
|
6333
|
+
const subscription = await subscribe.call(provider.client, local);
|
|
6334
|
+
if (!current()) {
|
|
6335
|
+
subscription.stop();
|
|
6336
|
+
return;
|
|
6337
|
+
}
|
|
6338
|
+
this.backendSubscriptionPending.delete(local);
|
|
6339
|
+
this.backendSubscriptions.set(local, subscription);
|
|
6340
|
+
try {
|
|
6341
|
+
while (current()) {
|
|
6342
|
+
const state = await subscription.nextUpdate();
|
|
6343
|
+
if (state === null || !current()) break;
|
|
6344
|
+
this.recordBackendDiagnostics(local, state.snapshot);
|
|
6345
|
+
if (state.snapshot.status === "unavailable") continue;
|
|
6346
|
+
this.backendFeatures = {
|
|
6347
|
+
...this.backendFeatures,
|
|
6348
|
+
...projectBackendSnapshot(state.snapshot, local)
|
|
6349
|
+
};
|
|
6350
|
+
if (local) this.backendAttachmentLimit = backendAttachmentMaxBytes(state.snapshot, this.resolved.attachmentMaxBytes);
|
|
6351
|
+
if (this.backendFeatures["agents.managed_agents"] === "unsupported") await this.detachAgentConsumer(provider);
|
|
6352
|
+
else if (this.backendFeatures["agents.managed_agents"] === "supported") this.ensureAgentConsumer(provider);
|
|
6353
|
+
}
|
|
6354
|
+
} finally {
|
|
6355
|
+
subscription.stop();
|
|
6356
|
+
if (this.backendSubscriptions.get(local) === subscription) this.backendSubscriptions.delete(local);
|
|
6357
|
+
}
|
|
6358
|
+
})().catch(() => {
|
|
6359
|
+
if (current()) this.backendSubscriptionPending.delete(local);
|
|
6360
|
+
});
|
|
6052
6361
|
}
|
|
6053
6362
|
async discoverTenantCapabilities(timeoutMs) {
|
|
6054
6363
|
const options = this.activeClientOptions;
|
|
6055
6364
|
const tenant = this.activeTenant;
|
|
6056
6365
|
if (options === void 0 || tenant === void 0) throw new ProviderUnavailableError();
|
|
6057
6366
|
const generation = this.runtimeGeneration;
|
|
6058
|
-
const
|
|
6367
|
+
const previous = this.activeCapabilities;
|
|
6368
|
+
const fallback = previous?.tenantId === tenant.tenantId && previous.generation === generation ? { ...previous } : {
|
|
6059
6369
|
tenantId: tenant.tenantId,
|
|
6060
6370
|
generation,
|
|
6061
6371
|
online: false,
|
|
@@ -6075,6 +6385,7 @@ let AwikiService = (() => {
|
|
|
6075
6385
|
try {
|
|
6076
6386
|
const endpoint = new URL("/user-service/v1/server-info", options.userServiceUrl);
|
|
6077
6387
|
endpoint.searchParams.set("client_platform", "dsh");
|
|
6388
|
+
endpoint.searchParams.set("capabilities_version", "1");
|
|
6078
6389
|
const response = await fetch(endpoint, {
|
|
6079
6390
|
method: "GET",
|
|
6080
6391
|
headers: {
|
|
@@ -6089,19 +6400,37 @@ let AwikiService = (() => {
|
|
|
6089
6400
|
const text = await readBoundedResponseText(response, SERVER_INFO_RESPONSE_MAX_BYTES);
|
|
6090
6401
|
const value = text === void 0 ? void 0 : JSON.parse(text);
|
|
6091
6402
|
if (typeof value !== "object" || value === null || value.schema_version !== 1) return publish(fallback);
|
|
6403
|
+
const versioned = value.capabilities_version === 1;
|
|
6404
|
+
if (!versioned) {
|
|
6405
|
+
if ("capabilities_version" in value) return publish({
|
|
6406
|
+
tenantId: tenant.tenantId,
|
|
6407
|
+
generation,
|
|
6408
|
+
online: true,
|
|
6409
|
+
handleRecoveryPhoneEnabled: false
|
|
6410
|
+
});
|
|
6411
|
+
return publish(fallback);
|
|
6412
|
+
}
|
|
6092
6413
|
const methods = value.identity?.handle_recovery?.methods;
|
|
6093
|
-
const handleRecoveryPhoneEnabled = Array.isArray(methods) && methods.some((method) => typeof method === "object" && method !== null && method.id === "phone" && method.enabled === true && method.verification?.required === true && method.verification?.type === "sms_otp");
|
|
6094
|
-
const services = value.services;
|
|
6414
|
+
const handleRecoveryPhoneEnabled = versioned && Array.isArray(methods) && methods.some((method) => typeof method === "object" && method !== null && method.id === "phone" && method.enabled === true && method.verification?.required === true && method.verification?.type === "sms_otp");
|
|
6415
|
+
const services = versioned ? value.services : void 0;
|
|
6095
6416
|
const modelProxyBaseUrl = publishedServiceBaseUrl(services, "model_proxy", this.resolved.allowInsecureLoopbackForTesting);
|
|
6096
6417
|
const guestGatewayBaseUrl = publishedServiceBaseUrl(services, "guest_gateway", false);
|
|
6097
|
-
|
|
6418
|
+
const capabilities = {
|
|
6098
6419
|
tenantId: tenant.tenantId,
|
|
6099
6420
|
generation,
|
|
6100
6421
|
online: true,
|
|
6101
6422
|
handleRecoveryPhoneEnabled,
|
|
6102
6423
|
...modelProxyBaseUrl === void 0 ? {} : { modelProxyBaseUrl },
|
|
6103
6424
|
...guestGatewayBaseUrl === void 0 ? {} : { guestGatewayBaseUrl }
|
|
6104
|
-
}
|
|
6425
|
+
};
|
|
6426
|
+
if (this.runtimeGeneration === generation && this.activeTenant?.tenantId === tenant.tenantId) {
|
|
6427
|
+
if (!new TenantCapabilityCache(options.stateRoot, options.userServiceUrl).write({
|
|
6428
|
+
handleRecoveryPhoneEnabled,
|
|
6429
|
+
...modelProxyBaseUrl === void 0 ? {} : { modelProxyBaseUrl },
|
|
6430
|
+
...guestGatewayBaseUrl === void 0 ? {} : { guestGatewayBaseUrl }
|
|
6431
|
+
})) this.ctx.logger("awiki-capabilities").debug("AWiki capability metadata persistence failed");
|
|
6432
|
+
}
|
|
6433
|
+
return publish(capabilities);
|
|
6105
6434
|
} catch {
|
|
6106
6435
|
return publish(fallback);
|
|
6107
6436
|
} finally {
|
|
@@ -6192,7 +6521,10 @@ let AwikiService = (() => {
|
|
|
6192
6521
|
const session = { status: "signed-out" };
|
|
6193
6522
|
this.publishSession(session);
|
|
6194
6523
|
const provider = this.provider;
|
|
6195
|
-
if (provider !== void 0)
|
|
6524
|
+
if (provider !== void 0) {
|
|
6525
|
+
await this.stopProviderRuntime(provider);
|
|
6526
|
+
await this.updateBackendDiscoveryLifecycle(provider, false);
|
|
6527
|
+
}
|
|
6196
6528
|
return {
|
|
6197
6529
|
ok: true,
|
|
6198
6530
|
value: session
|
|
@@ -6225,7 +6557,10 @@ let AwikiService = (() => {
|
|
|
6225
6557
|
};
|
|
6226
6558
|
this.publishSession(session);
|
|
6227
6559
|
const provider = this.provider;
|
|
6228
|
-
if (provider !== void 0)
|
|
6560
|
+
if (provider !== void 0) {
|
|
6561
|
+
this.ensureProviderRuntime(provider);
|
|
6562
|
+
await this.updateBackendDiscoveryLifecycle(provider, true);
|
|
6563
|
+
}
|
|
6229
6564
|
return {
|
|
6230
6565
|
ok: true,
|
|
6231
6566
|
value: session
|
|
@@ -6459,6 +6794,8 @@ let AwikiService = (() => {
|
|
|
6459
6794
|
const recoveries = await client.listPendingRecoveries();
|
|
6460
6795
|
const pendingRegistrations = await client.pendingIdentityRegistrations();
|
|
6461
6796
|
const creationMethods = await client.identityCreationMethods().catch(() => []);
|
|
6797
|
+
const backend = await client.backendCapabilities?.(false);
|
|
6798
|
+
const registrationHandleOnly = backend?.capabilities["registration.handle_only"]?.support === "supported" && (backend.status === "confirmed" || backend.status === "stale");
|
|
6462
6799
|
const identity = await client.getIdentity();
|
|
6463
6800
|
const capabilities = identity === null ? void 0 : await client.identityMethodCapabilities(identity.did);
|
|
6464
6801
|
const domain = this.activeClientOptions?.userServiceDomain;
|
|
@@ -6473,6 +6810,7 @@ let AwikiService = (() => {
|
|
|
6473
6810
|
},
|
|
6474
6811
|
joining,
|
|
6475
6812
|
creationMethods,
|
|
6813
|
+
registrationHandleOnly,
|
|
6476
6814
|
pendingRegistrations,
|
|
6477
6815
|
...capabilities === void 0 ? {} : { methodCapabilities: capabilities },
|
|
6478
6816
|
recoveries: recoveries.filter((value) => domain !== void 0 && value.fullHandle.slice(value.fullHandle.indexOf(".") + 1) === domain)
|
|
@@ -6874,7 +7212,12 @@ let AwikiService = (() => {
|
|
|
6874
7212
|
ok: false,
|
|
6875
7213
|
error: failure("invalid-request")
|
|
6876
7214
|
};
|
|
6877
|
-
const created = await this.run((client) =>
|
|
7215
|
+
const created = await this.run(async (client) => {
|
|
7216
|
+
await requireBackendFeature(client, "groups");
|
|
7217
|
+
if (normalized.encrypted) await requireBackendFeature(client, "group_e2ee");
|
|
7218
|
+
if (normalized.members.length > 0) await requireBackendFeature(client, "group_admin_add");
|
|
7219
|
+
return client.createGroup(normalized.name, normalized.encrypted, normalized.operationId);
|
|
7220
|
+
});
|
|
6878
7221
|
if (!created.ok) return created;
|
|
6879
7222
|
const addedMembers = [];
|
|
6880
7223
|
const failedMembers = [];
|
|
@@ -6911,7 +7254,10 @@ let AwikiService = (() => {
|
|
|
6911
7254
|
ok: false,
|
|
6912
7255
|
error: failure("invalid-request")
|
|
6913
7256
|
});
|
|
6914
|
-
return this.run((client) =>
|
|
7257
|
+
return this.run(async (client) => {
|
|
7258
|
+
await requireBackendFeature(client, "group_e2ee");
|
|
7259
|
+
return client.repairGroupSecurity(groupDid);
|
|
7260
|
+
});
|
|
6915
7261
|
}
|
|
6916
7262
|
/** Join one open group and return its authoritative membership state. */
|
|
6917
7263
|
joinGroup(request) {
|
|
@@ -6920,7 +7266,10 @@ let AwikiService = (() => {
|
|
|
6920
7266
|
ok: false,
|
|
6921
7267
|
error: failure("invalid-request")
|
|
6922
7268
|
});
|
|
6923
|
-
return this.run((client) =>
|
|
7269
|
+
return this.run(async (client) => {
|
|
7270
|
+
await requireBackendFeature(client, "group_open_join");
|
|
7271
|
+
return client.joinGroup(groupDid);
|
|
7272
|
+
});
|
|
6924
7273
|
}
|
|
6925
7274
|
/** Leave one group. Core rejects owner leave and unsupported security profiles. */
|
|
6926
7275
|
async leaveGroup(request) {
|
|
@@ -7502,6 +7851,7 @@ let AwikiService = (() => {
|
|
|
7502
7851
|
return client.getLocalDeviceJoinVerificationProgress(notice.joinSessionId);
|
|
7503
7852
|
}
|
|
7504
7853
|
async requireDeviceManager(client) {
|
|
7854
|
+
await requireBackendFeature(client, "identity.multi_device");
|
|
7505
7855
|
const current = await client.getCurrentDeviceSummary();
|
|
7506
7856
|
if (!current.canManage || current.role !== "admin" || current.readiness !== "admin_ready") throw Object.assign(/* @__PURE__ */ new Error("device manager required"), {
|
|
7507
7857
|
name: "AwikiSdkError",
|
|
@@ -7509,6 +7859,7 @@ let AwikiService = (() => {
|
|
|
7509
7859
|
});
|
|
7510
7860
|
}
|
|
7511
7861
|
async requireRootTransferRecipient(client, deviceId) {
|
|
7862
|
+
await requireBackendFeature(client, "identity.root_transfer");
|
|
7512
7863
|
if (!client.trustedUserPresenceSupported) throw Object.assign(/* @__PURE__ */ new Error("trusted user presence unsupported"), {
|
|
7513
7864
|
name: "AwikiSdkError",
|
|
7514
7865
|
code: "forbidden"
|
|
@@ -7635,6 +7986,7 @@ let AwikiService = (() => {
|
|
|
7635
7986
|
}
|
|
7636
7987
|
/** Invalidate cached session work and cancel every model request still owned by the old session. */
|
|
7637
7988
|
invalidateSummaries() {
|
|
7989
|
+
this.stopBackendSubscriptions();
|
|
7638
7990
|
this.sessionRevision += 1;
|
|
7639
7991
|
this.requestRefs.clear();
|
|
7640
7992
|
this.requestSessions.clear();
|
|
@@ -7718,7 +8070,10 @@ let AwikiService = (() => {
|
|
|
7718
8070
|
error: failure("invalid-request")
|
|
7719
8071
|
});
|
|
7720
8072
|
}
|
|
7721
|
-
return this.run((client) =>
|
|
8073
|
+
return this.run(async (client) => {
|
|
8074
|
+
await requireBackendFeature(client, "services.mail");
|
|
8075
|
+
return operation(client, request);
|
|
8076
|
+
}, options);
|
|
7722
8077
|
}
|
|
7723
8078
|
/** Read and cache the private Host-owned session marker. */
|
|
7724
8079
|
async isSignedOut() {
|
|
@@ -7772,6 +8127,14 @@ let AwikiService = (() => {
|
|
|
7772
8127
|
this.sessionMutation = pending.then(() => void 0, () => void 0);
|
|
7773
8128
|
return pending;
|
|
7774
8129
|
}
|
|
8130
|
+
/** Discovery is an optional projection, not authority for a committed session transition. */
|
|
8131
|
+
async updateBackendDiscoveryLifecycle(provider, active) {
|
|
8132
|
+
try {
|
|
8133
|
+
await provider.client.setBackendDiscoveryActive?.(active);
|
|
8134
|
+
} catch {
|
|
8135
|
+
this.ctx.logger("awiki-backend").warn("AWiki backend discovery lifecycle unavailable");
|
|
8136
|
+
}
|
|
8137
|
+
}
|
|
7775
8138
|
/** Start identity realtime and the optional Agent consumer without blocking identity success. */
|
|
7776
8139
|
ensureProviderRuntime(provider) {
|
|
7777
8140
|
if (this.tenantSwitching) return;
|
|
@@ -7781,6 +8144,7 @@ let AwikiService = (() => {
|
|
|
7781
8144
|
this.replaceProviderRuntime(provider, identityDid);
|
|
7782
8145
|
return;
|
|
7783
8146
|
}
|
|
8147
|
+
this.refreshBackendProjection();
|
|
7784
8148
|
this.ensureRealtimeSupervisor(provider);
|
|
7785
8149
|
this.ensureAgentConsumer(provider);
|
|
7786
8150
|
}
|
|
@@ -7857,6 +8221,7 @@ let AwikiService = (() => {
|
|
|
7857
8221
|
const logger = this.ctx.logger("awiki-listener");
|
|
7858
8222
|
const observed = (async () => {
|
|
7859
8223
|
await this.detachAgentConsumer(provider);
|
|
8224
|
+
if ((await projectBackendFeatures(provider.client, false))["agents.managed_agents"] !== "supported") return;
|
|
7860
8225
|
if (!this.agentConsumerFenceMatches(provider, workspaceContext, identityDid, generation)) return;
|
|
7861
8226
|
const agents = new DshAwikiListenerAgentRuntime(workspaceContext, this.resolved.listener.workspacePath);
|
|
7862
8227
|
const consumer = new AwikiAgentListener(source, agents, {
|