@opengeni/core 0.17.1 → 0.18.1
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/domain/memory-slack-publication.d.ts +107 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +260 -3
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
- package/src/domain/capabilities.ts +15 -1
- package/src/domain/memory-slack-publication.ts +448 -0
- package/src/domain/sessions.ts +4 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { type KnowledgeMemoryKind, type KnowledgeMemoryStatus } from "@opengeni/contracts";
|
|
2
|
+
export declare const MEMORY_SLACK_PROJECTION_VERSION = 1;
|
|
3
|
+
export declare const MEMORY_SLACK_SUMMARY_MAX_UTF8_BYTES = 512;
|
|
4
|
+
export declare const MEMORY_SLACK_NAMESPACE_MAX_UTF8_BYTES = 128;
|
|
5
|
+
export declare const MEMORY_SLACK_LABEL_MAX_UTF8_BYTES = 64;
|
|
6
|
+
export declare const MEMORY_SLACK_LABEL_MAX_COUNT = 8;
|
|
7
|
+
export declare const MEMORY_SLACK_OWNER_MAX_UTF8_BYTES = 96;
|
|
8
|
+
export declare const MEMORY_SLACK_PROJECTION_MAX_UTF8_BYTES = 4096;
|
|
9
|
+
export type MemorySlackImportance = "major" | "normal" | "minor";
|
|
10
|
+
export type MemorySlackRequestedMode = "auto" | "review" | "never";
|
|
11
|
+
export type MemorySlackDeliveryMode = Exclude<MemorySlackRequestedMode, "never">;
|
|
12
|
+
export type MemorySlackChangeKind = "created" | "corrected" | "superseded";
|
|
13
|
+
export type MemorySlackOrigin = "native" | "slack_derived";
|
|
14
|
+
export type MemorySlackAudience = "workspace" | "restricted";
|
|
15
|
+
export type MemorySlackPublicationPolicy = {
|
|
16
|
+
enabled: boolean;
|
|
17
|
+
autoImportances: readonly MemorySlackImportance[];
|
|
18
|
+
reviewImportances: readonly MemorySlackImportance[];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Nothing publishes without an explicit workspace-admin enablement. When
|
|
22
|
+
* enabled without tuning, major changes may publish automatically, normal
|
|
23
|
+
* changes require review, and minor changes stay quiet.
|
|
24
|
+
*/
|
|
25
|
+
export declare const DEFAULT_MEMORY_SLACK_PUBLICATION_POLICY: {
|
|
26
|
+
readonly enabled: false;
|
|
27
|
+
readonly autoImportances: readonly ["major"];
|
|
28
|
+
readonly reviewImportances: readonly ["normal"];
|
|
29
|
+
};
|
|
30
|
+
export type MemorySlackPublicationInput = {
|
|
31
|
+
context: {
|
|
32
|
+
accountId: string;
|
|
33
|
+
workspaceId: string;
|
|
34
|
+
now: string;
|
|
35
|
+
};
|
|
36
|
+
policy?: MemorySlackPublicationPolicy | undefined;
|
|
37
|
+
memory: {
|
|
38
|
+
sourceType: "workspace_memory";
|
|
39
|
+
accountId: string;
|
|
40
|
+
workspaceId: string;
|
|
41
|
+
id: string;
|
|
42
|
+
version: number;
|
|
43
|
+
status: KnowledgeMemoryStatus;
|
|
44
|
+
kind: KnowledgeMemoryKind;
|
|
45
|
+
scopeType: "workspace" | "user" | "role" | "session" | "ephemeral" | "legacy";
|
|
46
|
+
namespace: string;
|
|
47
|
+
labels: readonly string[];
|
|
48
|
+
validFrom: string;
|
|
49
|
+
validUntil: string | null;
|
|
50
|
+
supersedesId: string | null;
|
|
51
|
+
supersededById: string | null;
|
|
52
|
+
};
|
|
53
|
+
change: {
|
|
54
|
+
kind: MemorySlackChangeKind;
|
|
55
|
+
relatedMemoryId: string | null;
|
|
56
|
+
occurredAt: string;
|
|
57
|
+
origin: MemorySlackOrigin;
|
|
58
|
+
ownerLabel?: string | null | undefined;
|
|
59
|
+
};
|
|
60
|
+
distribution: {
|
|
61
|
+
importance: MemorySlackImportance;
|
|
62
|
+
audience: MemorySlackAudience;
|
|
63
|
+
slackMode: MemorySlackRequestedMode;
|
|
64
|
+
shareSummary: string;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
export type MemorySlackPublicationDenialReason = "disabled" | "invalid_input" | "unsupported_source" | "tenant_mismatch" | "not_decision" | "status_ineligible" | "restricted_scope" | "restricted_audience" | "not_yet_valid" | "expired" | "slack_origin_loop" | "mode_never" | "below_noise_policy" | "missing_summary" | "invalid_change_lineage";
|
|
68
|
+
export type MemorySlackPublicationProjection = {
|
|
69
|
+
version: typeof MEMORY_SLACK_PROJECTION_VERSION;
|
|
70
|
+
workspaceId: string;
|
|
71
|
+
memoryId: string;
|
|
72
|
+
memoryVersion: number;
|
|
73
|
+
changeKind: MemorySlackChangeKind;
|
|
74
|
+
relatedMemoryId: string | null;
|
|
75
|
+
occurredAt: string;
|
|
76
|
+
importance: MemorySlackImportance;
|
|
77
|
+
deliveryMode: MemorySlackDeliveryMode;
|
|
78
|
+
summary: string;
|
|
79
|
+
summaryRedacted: boolean;
|
|
80
|
+
summaryTruncated: boolean;
|
|
81
|
+
namespace: string;
|
|
82
|
+
labels: string[];
|
|
83
|
+
labelsTruncated: boolean;
|
|
84
|
+
ownerLabel: string | null;
|
|
85
|
+
ownerLabelRedacted: boolean;
|
|
86
|
+
ownerLabelTruncated: boolean;
|
|
87
|
+
authoritativeRecord: {
|
|
88
|
+
workspaceId: string;
|
|
89
|
+
memoryId: string;
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
export type MemorySlackPublicationDecision = {
|
|
93
|
+
eligible: false;
|
|
94
|
+
reason: MemorySlackPublicationDenialReason;
|
|
95
|
+
} | {
|
|
96
|
+
eligible: true;
|
|
97
|
+
deliveryMode: MemorySlackDeliveryMode;
|
|
98
|
+
idempotencyKey: string;
|
|
99
|
+
projection: MemorySlackPublicationProjection;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Produce the only data shape a later delivery slice may persist or
|
|
103
|
+
* render. This is a deterministic policy/security boundary, not a persistence
|
|
104
|
+
* hook: callers must durably bind the returned projection and key in a later
|
|
105
|
+
* transaction/outbox slice.
|
|
106
|
+
*/
|
|
107
|
+
export declare function evaluateMemorySlackPublication(input: MemorySlackPublicationInput): MemorySlackPublicationDecision;
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export * from "./domain/session-tool-policy";
|
|
|
18
18
|
export * from "./domain/scheduled-tasks";
|
|
19
19
|
export * from "./domain/sessions";
|
|
20
20
|
export * from "./domain/insights";
|
|
21
|
+
export * from "./domain/memory-slack-publication";
|
|
21
22
|
export * from "./domain/slack-bot";
|
|
22
23
|
export * from "./domain/workspace-members";
|
|
23
24
|
export * from "./application/new-session-drafts";
|
package/dist/index.js
CHANGED
|
@@ -2356,6 +2356,19 @@ async function requireCatalogItem(db, workspaceId, settings, capabilityId) {
|
|
|
2356
2356
|
return item;
|
|
2357
2357
|
}
|
|
2358
2358
|
function packCatalogItem(pack, source) {
|
|
2359
|
+
const customMetadata = { ...pack.metadata };
|
|
2360
|
+
for (const key of [
|
|
2361
|
+
"packId",
|
|
2362
|
+
"version",
|
|
2363
|
+
"connectors",
|
|
2364
|
+
"knowledge",
|
|
2365
|
+
"scheduledTaskTemplates",
|
|
2366
|
+
"sandboxImage",
|
|
2367
|
+
"sandboxProviderImages",
|
|
2368
|
+
"skills"
|
|
2369
|
+
]) {
|
|
2370
|
+
delete customMetadata[key];
|
|
2371
|
+
}
|
|
2359
2372
|
return CapabilityCatalogItem.parse({
|
|
2360
2373
|
id: `pack:${pack.id}`,
|
|
2361
2374
|
kind: "pack",
|
|
@@ -2370,6 +2383,7 @@ function packCatalogItem(pack, source) {
|
|
|
2370
2383
|
notes: "Enables role-scoped tools, connectors, knowledge, and scheduled-task templates."
|
|
2371
2384
|
},
|
|
2372
2385
|
metadata: {
|
|
2386
|
+
...customMetadata,
|
|
2373
2387
|
packId: pack.id,
|
|
2374
2388
|
version: pack.version,
|
|
2375
2389
|
connectors: pack.connectors,
|
|
@@ -2377,8 +2391,8 @@ function packCatalogItem(pack, source) {
|
|
|
2377
2391
|
scheduledTaskTemplates: pack.scheduledTaskTemplates,
|
|
2378
2392
|
// Runtime composition surface only: skill names, never file content.
|
|
2379
2393
|
...pack.sandboxImage ? { sandboxImage: pack.sandboxImage } : {},
|
|
2380
|
-
...pack.
|
|
2381
|
-
...pack.
|
|
2394
|
+
...pack.sandboxProviderImages ? { sandboxProviderImages: pack.sandboxProviderImages } : {},
|
|
2395
|
+
...pack.skills.length > 0 ? { skills: pack.skills.map((skill) => skill.name) } : {}
|
|
2382
2396
|
}
|
|
2383
2397
|
});
|
|
2384
2398
|
}
|
|
@@ -3716,7 +3730,8 @@ import {
|
|
|
3716
3730
|
canonicalizeConfiguredModelId,
|
|
3717
3731
|
configuredAllowedModels,
|
|
3718
3732
|
policyProviderIdForModel,
|
|
3719
|
-
resolveTurnExecutionPolicyV1
|
|
3733
|
+
resolveTurnExecutionPolicyV1,
|
|
3734
|
+
WORKSPACE_GATEWAY_MODEL_ID_PREFIX
|
|
3720
3735
|
} from "@opengeni/config";
|
|
3721
3736
|
import {
|
|
3722
3737
|
CreateSessionRequest,
|
|
@@ -4295,6 +4310,9 @@ function canonicalConfiguredModel(settings, model) {
|
|
|
4295
4310
|
if (settings.codexSubscriptionEnabled && canonicalModel.startsWith(CODEX_MODEL_ID_PREFIX)) {
|
|
4296
4311
|
return canonicalModel;
|
|
4297
4312
|
}
|
|
4313
|
+
if (canonicalModel.startsWith(WORKSPACE_GATEWAY_MODEL_ID_PREFIX)) {
|
|
4314
|
+
return canonicalModel;
|
|
4315
|
+
}
|
|
4298
4316
|
throw new HTTPException10(422, { message: `model is not available: ${model}` });
|
|
4299
4317
|
}
|
|
4300
4318
|
function assertConfiguredModel(settings, model) {
|
|
@@ -5965,6 +5983,236 @@ async function getWorkspaceInsights(db, settings, input) {
|
|
|
5965
5983
|
return { snapshot };
|
|
5966
5984
|
}
|
|
5967
5985
|
|
|
5986
|
+
// src/domain/memory-slack-publication.ts
|
|
5987
|
+
import { createHash } from "crypto";
|
|
5988
|
+
import {
|
|
5989
|
+
redactSensitiveText,
|
|
5990
|
+
stableJson as stableJson3
|
|
5991
|
+
} from "@opengeni/contracts";
|
|
5992
|
+
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
5993
|
+
var SELECTOR_SEGMENT_PATTERN = /^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/;
|
|
5994
|
+
var encoder = new TextEncoder();
|
|
5995
|
+
var decoder = new TextDecoder();
|
|
5996
|
+
var MEMORY_SLACK_PROJECTION_VERSION = 1;
|
|
5997
|
+
var MEMORY_SLACK_SUMMARY_MAX_UTF8_BYTES = 512;
|
|
5998
|
+
var MEMORY_SLACK_NAMESPACE_MAX_UTF8_BYTES = 128;
|
|
5999
|
+
var MEMORY_SLACK_LABEL_MAX_UTF8_BYTES = 64;
|
|
6000
|
+
var MEMORY_SLACK_LABEL_MAX_COUNT = 8;
|
|
6001
|
+
var MEMORY_SLACK_OWNER_MAX_UTF8_BYTES = 96;
|
|
6002
|
+
var MEMORY_SLACK_PROJECTION_MAX_UTF8_BYTES = 4096;
|
|
6003
|
+
var DEFAULT_MEMORY_SLACK_PUBLICATION_POLICY = {
|
|
6004
|
+
enabled: false,
|
|
6005
|
+
autoImportances: ["major"],
|
|
6006
|
+
reviewImportances: ["normal"]
|
|
6007
|
+
};
|
|
6008
|
+
var IMPORTANCES = /* @__PURE__ */ new Set(["major", "normal", "minor"]);
|
|
6009
|
+
var REQUESTED_MODES = /* @__PURE__ */ new Set(["auto", "review", "never"]);
|
|
6010
|
+
var CHANGE_KINDS = /* @__PURE__ */ new Set(["created", "corrected", "superseded"]);
|
|
6011
|
+
var ORIGINS = /* @__PURE__ */ new Set(["native", "slack_derived"]);
|
|
6012
|
+
var AUDIENCES = /* @__PURE__ */ new Set(["workspace", "restricted"]);
|
|
6013
|
+
var SCOPE_TYPES = /* @__PURE__ */ new Set([
|
|
6014
|
+
"workspace",
|
|
6015
|
+
"user",
|
|
6016
|
+
"role",
|
|
6017
|
+
"session",
|
|
6018
|
+
"ephemeral",
|
|
6019
|
+
"legacy"
|
|
6020
|
+
]);
|
|
6021
|
+
var MEMORY_STATUSES = /* @__PURE__ */ new Set([
|
|
6022
|
+
"proposed",
|
|
6023
|
+
"approved",
|
|
6024
|
+
"rejected",
|
|
6025
|
+
"active",
|
|
6026
|
+
"superseded",
|
|
6027
|
+
"archived"
|
|
6028
|
+
]);
|
|
6029
|
+
var MEMORY_KINDS = /* @__PURE__ */ new Set([
|
|
6030
|
+
"semantic",
|
|
6031
|
+
"episodic",
|
|
6032
|
+
"procedural",
|
|
6033
|
+
"decision",
|
|
6034
|
+
"preference"
|
|
6035
|
+
]);
|
|
6036
|
+
var VISIBLE_STATUSES = /* @__PURE__ */ new Set(["active", "approved"]);
|
|
6037
|
+
function evaluateMemorySlackPublication(input) {
|
|
6038
|
+
const policy = input.policy ?? DEFAULT_MEMORY_SLACK_PUBLICATION_POLICY;
|
|
6039
|
+
if (!validPolicy(policy)) return denied("invalid_input");
|
|
6040
|
+
if (!policy.enabled) return denied("disabled");
|
|
6041
|
+
if (input.memory.sourceType !== "workspace_memory") return denied("unsupported_source");
|
|
6042
|
+
if (!validIdentity(input)) return denied("invalid_input");
|
|
6043
|
+
if (input.memory.accountId !== input.context.accountId || input.memory.workspaceId !== input.context.workspaceId) {
|
|
6044
|
+
return denied("tenant_mismatch");
|
|
6045
|
+
}
|
|
6046
|
+
if (input.memory.kind !== "decision") return denied("not_decision");
|
|
6047
|
+
if (input.memory.scopeType !== "workspace") return denied("restricted_scope");
|
|
6048
|
+
if (input.distribution.audience !== "workspace") return denied("restricted_audience");
|
|
6049
|
+
if (input.change.origin === "slack_derived") return denied("slack_origin_loop");
|
|
6050
|
+
if (input.distribution.slackMode === "never") return denied("mode_never");
|
|
6051
|
+
const timeDecision = evaluateValidity(input);
|
|
6052
|
+
if (timeDecision) return denied(timeDecision);
|
|
6053
|
+
if (!statusEligibleForChange(input)) return denied("status_ineligible");
|
|
6054
|
+
if (!validChangeLineage(input)) return denied("invalid_change_lineage");
|
|
6055
|
+
const deliveryMode = effectiveDeliveryMode(policy, input.distribution);
|
|
6056
|
+
if (!deliveryMode) return denied("below_noise_policy");
|
|
6057
|
+
const collapsedSummary = collapseText(input.distribution.shareSummary);
|
|
6058
|
+
const redactedSummary = redactSensitiveText(collapsedSummary);
|
|
6059
|
+
if (!redactedSummary) return denied("missing_summary");
|
|
6060
|
+
const summary = truncateUtf8(redactedSummary, MEMORY_SLACK_SUMMARY_MAX_UTF8_BYTES);
|
|
6061
|
+
const namespace = normalizeNamespace(input.memory.namespace);
|
|
6062
|
+
const labels = normalizeLabels(input.memory.labels);
|
|
6063
|
+
if (!namespace || !labels) return denied("invalid_input");
|
|
6064
|
+
const owner = boundedOptionalText(input.change.ownerLabel, MEMORY_SLACK_OWNER_MAX_UTF8_BYTES);
|
|
6065
|
+
const projection = {
|
|
6066
|
+
version: MEMORY_SLACK_PROJECTION_VERSION,
|
|
6067
|
+
workspaceId: input.context.workspaceId,
|
|
6068
|
+
memoryId: input.memory.id,
|
|
6069
|
+
memoryVersion: input.memory.version,
|
|
6070
|
+
changeKind: input.change.kind,
|
|
6071
|
+
relatedMemoryId: input.change.relatedMemoryId,
|
|
6072
|
+
occurredAt: new Date(input.change.occurredAt).toISOString(),
|
|
6073
|
+
importance: input.distribution.importance,
|
|
6074
|
+
deliveryMode,
|
|
6075
|
+
summary: summary.value,
|
|
6076
|
+
summaryRedacted: redactedSummary !== collapsedSummary,
|
|
6077
|
+
summaryTruncated: summary.truncated,
|
|
6078
|
+
namespace,
|
|
6079
|
+
labels: labels.values,
|
|
6080
|
+
labelsTruncated: labels.truncated,
|
|
6081
|
+
ownerLabel: owner.value,
|
|
6082
|
+
ownerLabelRedacted: owner.redacted,
|
|
6083
|
+
ownerLabelTruncated: owner.truncated,
|
|
6084
|
+
authoritativeRecord: {
|
|
6085
|
+
workspaceId: input.context.workspaceId,
|
|
6086
|
+
memoryId: input.memory.id
|
|
6087
|
+
}
|
|
6088
|
+
};
|
|
6089
|
+
if (utf8Bytes(stableJson3(projection)) > MEMORY_SLACK_PROJECTION_MAX_UTF8_BYTES) {
|
|
6090
|
+
return denied("invalid_input");
|
|
6091
|
+
}
|
|
6092
|
+
const digest = createHash("sha256").update(stableJson3(projection), "utf8").digest("hex");
|
|
6093
|
+
return {
|
|
6094
|
+
eligible: true,
|
|
6095
|
+
deliveryMode,
|
|
6096
|
+
idempotencyKey: `memory-slack:v${MEMORY_SLACK_PROJECTION_VERSION}:${digest}`,
|
|
6097
|
+
projection
|
|
6098
|
+
};
|
|
6099
|
+
}
|
|
6100
|
+
function validPolicy(policy) {
|
|
6101
|
+
return typeof policy.enabled === "boolean" && Array.isArray(policy.autoImportances) && Array.isArray(policy.reviewImportances) && policy.autoImportances.every((importance) => IMPORTANCES.has(importance)) && policy.reviewImportances.every((importance) => IMPORTANCES.has(importance));
|
|
6102
|
+
}
|
|
6103
|
+
function validIdentity(input) {
|
|
6104
|
+
const uuids = [
|
|
6105
|
+
input.context.accountId,
|
|
6106
|
+
input.context.workspaceId,
|
|
6107
|
+
input.memory.accountId,
|
|
6108
|
+
input.memory.workspaceId,
|
|
6109
|
+
input.memory.id,
|
|
6110
|
+
input.memory.supersedesId,
|
|
6111
|
+
input.memory.supersededById,
|
|
6112
|
+
input.change.relatedMemoryId
|
|
6113
|
+
].filter((value) => value !== null);
|
|
6114
|
+
return uuids.every((value) => UUID_PATTERN.test(value)) && Number.isSafeInteger(input.memory.version) && input.memory.version > 0 && typeof input.memory.namespace === "string" && Array.isArray(input.memory.labels) && input.memory.labels.every((label) => typeof label === "string") && (input.change.ownerLabel === void 0 || input.change.ownerLabel === null || typeof input.change.ownerLabel === "string") && typeof input.distribution.shareSummary === "string" && IMPORTANCES.has(input.distribution.importance) && REQUESTED_MODES.has(input.distribution.slackMode) && CHANGE_KINDS.has(input.change.kind) && ORIGINS.has(input.change.origin) && AUDIENCES.has(input.distribution.audience) && SCOPE_TYPES.has(input.memory.scopeType) && MEMORY_STATUSES.has(input.memory.status) && MEMORY_KINDS.has(input.memory.kind);
|
|
6115
|
+
}
|
|
6116
|
+
function evaluateValidity(input) {
|
|
6117
|
+
const now = Date.parse(input.context.now);
|
|
6118
|
+
const occurredAt = Date.parse(input.change.occurredAt);
|
|
6119
|
+
const validFrom = Date.parse(input.memory.validFrom);
|
|
6120
|
+
const validUntil = input.memory.validUntil === null ? null : Date.parse(input.memory.validUntil);
|
|
6121
|
+
if (!Number.isFinite(now) || !Number.isFinite(occurredAt) || !Number.isFinite(validFrom) || validUntil !== null && !Number.isFinite(validUntil) || validUntil !== null && validUntil <= validFrom) {
|
|
6122
|
+
return "invalid_input";
|
|
6123
|
+
}
|
|
6124
|
+
if (now < validFrom) return "not_yet_valid";
|
|
6125
|
+
if (validUntil !== null && now >= validUntil) return "expired";
|
|
6126
|
+
return null;
|
|
6127
|
+
}
|
|
6128
|
+
function validChangeLineage(input) {
|
|
6129
|
+
if (input.memory.supersedesId === input.memory.id || input.memory.supersededById === input.memory.id || input.change.relatedMemoryId === input.memory.id) {
|
|
6130
|
+
return false;
|
|
6131
|
+
}
|
|
6132
|
+
switch (input.change.kind) {
|
|
6133
|
+
case "created":
|
|
6134
|
+
return input.change.relatedMemoryId === null && input.memory.supersedesId === null && input.memory.supersededById === null;
|
|
6135
|
+
case "corrected":
|
|
6136
|
+
return input.change.relatedMemoryId !== null && input.change.relatedMemoryId !== input.memory.id && input.memory.supersedesId === input.change.relatedMemoryId && input.memory.supersededById === null;
|
|
6137
|
+
case "superseded":
|
|
6138
|
+
return input.change.relatedMemoryId !== null && input.change.relatedMemoryId !== input.memory.id && input.memory.supersededById === input.change.relatedMemoryId;
|
|
6139
|
+
}
|
|
6140
|
+
}
|
|
6141
|
+
function statusEligibleForChange(input) {
|
|
6142
|
+
return input.change.kind === "superseded" ? input.memory.status === "superseded" : VISIBLE_STATUSES.has(input.memory.status);
|
|
6143
|
+
}
|
|
6144
|
+
function effectiveDeliveryMode(policy, distribution) {
|
|
6145
|
+
const auto = new Set(policy.autoImportances);
|
|
6146
|
+
const review = new Set(policy.reviewImportances);
|
|
6147
|
+
if (distribution.slackMode === "review") {
|
|
6148
|
+
return auto.has(distribution.importance) || review.has(distribution.importance) ? "review" : null;
|
|
6149
|
+
}
|
|
6150
|
+
if (auto.has(distribution.importance)) return "auto";
|
|
6151
|
+
if (review.has(distribution.importance)) return "review";
|
|
6152
|
+
return null;
|
|
6153
|
+
}
|
|
6154
|
+
function normalizeNamespace(value) {
|
|
6155
|
+
const trimmed = value.trim();
|
|
6156
|
+
if (redactSensitiveText(trimmed) !== trimmed) return null;
|
|
6157
|
+
const namespace = trimmed.toLowerCase();
|
|
6158
|
+
if (!namespace || utf8Bytes(namespace) > MEMORY_SLACK_NAMESPACE_MAX_UTF8_BYTES) return null;
|
|
6159
|
+
if (redactSensitiveText(namespace) !== namespace) return null;
|
|
6160
|
+
const segments = namespace.split("/");
|
|
6161
|
+
if (segments.some((segment) => !SELECTOR_SEGMENT_PATTERN.test(segment))) return null;
|
|
6162
|
+
return segments.join("/");
|
|
6163
|
+
}
|
|
6164
|
+
function normalizeLabels(values) {
|
|
6165
|
+
if (!Array.isArray(values)) return null;
|
|
6166
|
+
const labels = /* @__PURE__ */ new Set();
|
|
6167
|
+
for (const value of values) {
|
|
6168
|
+
if (typeof value !== "string") return null;
|
|
6169
|
+
const trimmed = value.trim();
|
|
6170
|
+
if (redactSensitiveText(trimmed) !== trimmed) return null;
|
|
6171
|
+
const label = trimmed.toLowerCase();
|
|
6172
|
+
if (redactSensitiveText(label) !== label || !SELECTOR_SEGMENT_PATTERN.test(label) || utf8Bytes(label) > MEMORY_SLACK_LABEL_MAX_UTF8_BYTES) {
|
|
6173
|
+
return null;
|
|
6174
|
+
}
|
|
6175
|
+
labels.add(label);
|
|
6176
|
+
}
|
|
6177
|
+
const sorted = [...labels].sort();
|
|
6178
|
+
return {
|
|
6179
|
+
values: sorted.slice(0, MEMORY_SLACK_LABEL_MAX_COUNT),
|
|
6180
|
+
truncated: sorted.length > MEMORY_SLACK_LABEL_MAX_COUNT
|
|
6181
|
+
};
|
|
6182
|
+
}
|
|
6183
|
+
function boundedOptionalText(value, maxBytes) {
|
|
6184
|
+
const collapsed = collapseText(value ?? "");
|
|
6185
|
+
if (!collapsed) return { value: null, redacted: false, truncated: false };
|
|
6186
|
+
const redacted = redactSensitiveText(collapsed);
|
|
6187
|
+
const bounded = truncateUtf8(redacted, maxBytes);
|
|
6188
|
+
return {
|
|
6189
|
+
value: bounded.value || null,
|
|
6190
|
+
redacted: redacted !== collapsed,
|
|
6191
|
+
truncated: bounded.truncated
|
|
6192
|
+
};
|
|
6193
|
+
}
|
|
6194
|
+
function collapseText(value) {
|
|
6195
|
+
return value.replace(/[\u0000-\u001F\u007F-\u009F]/g, " ").replace(/\s+/g, " ").trim();
|
|
6196
|
+
}
|
|
6197
|
+
function truncateUtf8(value, maxBytes) {
|
|
6198
|
+
const bytes = encoder.encode(value);
|
|
6199
|
+
if (bytes.byteLength <= maxBytes) return { value, truncated: false };
|
|
6200
|
+
const marker = "\u2026";
|
|
6201
|
+
const markerBytes = encoder.encode(marker);
|
|
6202
|
+
let end = Math.max(0, maxBytes - markerBytes.byteLength);
|
|
6203
|
+
while (end > 0 && (bytes[end] & 192) === 128) end -= 1;
|
|
6204
|
+
return {
|
|
6205
|
+
value: `${decoder.decode(bytes.subarray(0, end)).trimEnd()}${marker}`,
|
|
6206
|
+
truncated: true
|
|
6207
|
+
};
|
|
6208
|
+
}
|
|
6209
|
+
function utf8Bytes(value) {
|
|
6210
|
+
return encoder.encode(value).byteLength;
|
|
6211
|
+
}
|
|
6212
|
+
function denied(reason) {
|
|
6213
|
+
return { eligible: false, reason };
|
|
6214
|
+
}
|
|
6215
|
+
|
|
5968
6216
|
// src/domain/workspace-members.ts
|
|
5969
6217
|
import { HTTPException as HTTPException12 } from "hono/http-exception";
|
|
5970
6218
|
var MEMBER_ADMIN_PERMISSIONS = ["workspace:admin", "members:manage"];
|
|
@@ -6678,6 +6926,7 @@ async function saveHumanComposerDraft(deps, context, input) {
|
|
|
6678
6926
|
export {
|
|
6679
6927
|
CODEX_COMPACTION_V2_PROVIDER_LOCKED,
|
|
6680
6928
|
CodexCompactionV2ProviderLockedError,
|
|
6929
|
+
DEFAULT_MEMORY_SLACK_PUBLICATION_POLICY,
|
|
6681
6930
|
MARKETING_SOCIAL_PACK_ID,
|
|
6682
6931
|
MAX_CHECKS_PER_RIG,
|
|
6683
6932
|
MAX_CREDENTIAL_HOOKS_PER_RIG,
|
|
@@ -6685,6 +6934,13 @@ export {
|
|
|
6685
6934
|
MAX_ENVIRONMENTS_PER_WORKSPACE,
|
|
6686
6935
|
MAX_RIGS_PER_WORKSPACE,
|
|
6687
6936
|
MAX_VARIABLES_PER_ENVIRONMENT,
|
|
6937
|
+
MEMORY_SLACK_LABEL_MAX_COUNT,
|
|
6938
|
+
MEMORY_SLACK_LABEL_MAX_UTF8_BYTES,
|
|
6939
|
+
MEMORY_SLACK_NAMESPACE_MAX_UTF8_BYTES,
|
|
6940
|
+
MEMORY_SLACK_OWNER_MAX_UTF8_BYTES,
|
|
6941
|
+
MEMORY_SLACK_PROJECTION_MAX_UTF8_BYTES,
|
|
6942
|
+
MEMORY_SLACK_PROJECTION_VERSION,
|
|
6943
|
+
MEMORY_SLACK_SUMMARY_MAX_UTF8_BYTES,
|
|
6688
6944
|
SESSION_AUTHORIZATION_DEFAULT_REAUTHORIZE_MS,
|
|
6689
6945
|
SESSION_WORKFLOW_WAKE_DISPATCHER_PERIOD_MS,
|
|
6690
6946
|
SESSION_WORKFLOW_WAKE_DISPATCHER_SCHEDULE_ID,
|
|
@@ -6734,6 +6990,7 @@ export {
|
|
|
6734
6990
|
editHumanQueuePrompt,
|
|
6735
6991
|
enableCapability,
|
|
6736
6992
|
enabledCapabilityMcpToolRefs,
|
|
6993
|
+
evaluateMemorySlackPublication,
|
|
6737
6994
|
executeRunOnSelfhostedMachine,
|
|
6738
6995
|
filenameForMimeType,
|
|
6739
6996
|
freezePersonalConnectionDelegations,
|