@opengeni/core 0.17.1 → 0.18.0
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 +255 -2
- 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/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
|
}
|
|
@@ -5965,6 +5979,236 @@ async function getWorkspaceInsights(db, settings, input) {
|
|
|
5965
5979
|
return { snapshot };
|
|
5966
5980
|
}
|
|
5967
5981
|
|
|
5982
|
+
// src/domain/memory-slack-publication.ts
|
|
5983
|
+
import { createHash } from "crypto";
|
|
5984
|
+
import {
|
|
5985
|
+
redactSensitiveText,
|
|
5986
|
+
stableJson as stableJson3
|
|
5987
|
+
} from "@opengeni/contracts";
|
|
5988
|
+
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}$/;
|
|
5989
|
+
var SELECTOR_SEGMENT_PATTERN = /^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/;
|
|
5990
|
+
var encoder = new TextEncoder();
|
|
5991
|
+
var decoder = new TextDecoder();
|
|
5992
|
+
var MEMORY_SLACK_PROJECTION_VERSION = 1;
|
|
5993
|
+
var MEMORY_SLACK_SUMMARY_MAX_UTF8_BYTES = 512;
|
|
5994
|
+
var MEMORY_SLACK_NAMESPACE_MAX_UTF8_BYTES = 128;
|
|
5995
|
+
var MEMORY_SLACK_LABEL_MAX_UTF8_BYTES = 64;
|
|
5996
|
+
var MEMORY_SLACK_LABEL_MAX_COUNT = 8;
|
|
5997
|
+
var MEMORY_SLACK_OWNER_MAX_UTF8_BYTES = 96;
|
|
5998
|
+
var MEMORY_SLACK_PROJECTION_MAX_UTF8_BYTES = 4096;
|
|
5999
|
+
var DEFAULT_MEMORY_SLACK_PUBLICATION_POLICY = {
|
|
6000
|
+
enabled: false,
|
|
6001
|
+
autoImportances: ["major"],
|
|
6002
|
+
reviewImportances: ["normal"]
|
|
6003
|
+
};
|
|
6004
|
+
var IMPORTANCES = /* @__PURE__ */ new Set(["major", "normal", "minor"]);
|
|
6005
|
+
var REQUESTED_MODES = /* @__PURE__ */ new Set(["auto", "review", "never"]);
|
|
6006
|
+
var CHANGE_KINDS = /* @__PURE__ */ new Set(["created", "corrected", "superseded"]);
|
|
6007
|
+
var ORIGINS = /* @__PURE__ */ new Set(["native", "slack_derived"]);
|
|
6008
|
+
var AUDIENCES = /* @__PURE__ */ new Set(["workspace", "restricted"]);
|
|
6009
|
+
var SCOPE_TYPES = /* @__PURE__ */ new Set([
|
|
6010
|
+
"workspace",
|
|
6011
|
+
"user",
|
|
6012
|
+
"role",
|
|
6013
|
+
"session",
|
|
6014
|
+
"ephemeral",
|
|
6015
|
+
"legacy"
|
|
6016
|
+
]);
|
|
6017
|
+
var MEMORY_STATUSES = /* @__PURE__ */ new Set([
|
|
6018
|
+
"proposed",
|
|
6019
|
+
"approved",
|
|
6020
|
+
"rejected",
|
|
6021
|
+
"active",
|
|
6022
|
+
"superseded",
|
|
6023
|
+
"archived"
|
|
6024
|
+
]);
|
|
6025
|
+
var MEMORY_KINDS = /* @__PURE__ */ new Set([
|
|
6026
|
+
"semantic",
|
|
6027
|
+
"episodic",
|
|
6028
|
+
"procedural",
|
|
6029
|
+
"decision",
|
|
6030
|
+
"preference"
|
|
6031
|
+
]);
|
|
6032
|
+
var VISIBLE_STATUSES = /* @__PURE__ */ new Set(["active", "approved"]);
|
|
6033
|
+
function evaluateMemorySlackPublication(input) {
|
|
6034
|
+
const policy = input.policy ?? DEFAULT_MEMORY_SLACK_PUBLICATION_POLICY;
|
|
6035
|
+
if (!validPolicy(policy)) return denied("invalid_input");
|
|
6036
|
+
if (!policy.enabled) return denied("disabled");
|
|
6037
|
+
if (input.memory.sourceType !== "workspace_memory") return denied("unsupported_source");
|
|
6038
|
+
if (!validIdentity(input)) return denied("invalid_input");
|
|
6039
|
+
if (input.memory.accountId !== input.context.accountId || input.memory.workspaceId !== input.context.workspaceId) {
|
|
6040
|
+
return denied("tenant_mismatch");
|
|
6041
|
+
}
|
|
6042
|
+
if (input.memory.kind !== "decision") return denied("not_decision");
|
|
6043
|
+
if (input.memory.scopeType !== "workspace") return denied("restricted_scope");
|
|
6044
|
+
if (input.distribution.audience !== "workspace") return denied("restricted_audience");
|
|
6045
|
+
if (input.change.origin === "slack_derived") return denied("slack_origin_loop");
|
|
6046
|
+
if (input.distribution.slackMode === "never") return denied("mode_never");
|
|
6047
|
+
const timeDecision = evaluateValidity(input);
|
|
6048
|
+
if (timeDecision) return denied(timeDecision);
|
|
6049
|
+
if (!statusEligibleForChange(input)) return denied("status_ineligible");
|
|
6050
|
+
if (!validChangeLineage(input)) return denied("invalid_change_lineage");
|
|
6051
|
+
const deliveryMode = effectiveDeliveryMode(policy, input.distribution);
|
|
6052
|
+
if (!deliveryMode) return denied("below_noise_policy");
|
|
6053
|
+
const collapsedSummary = collapseText(input.distribution.shareSummary);
|
|
6054
|
+
const redactedSummary = redactSensitiveText(collapsedSummary);
|
|
6055
|
+
if (!redactedSummary) return denied("missing_summary");
|
|
6056
|
+
const summary = truncateUtf8(redactedSummary, MEMORY_SLACK_SUMMARY_MAX_UTF8_BYTES);
|
|
6057
|
+
const namespace = normalizeNamespace(input.memory.namespace);
|
|
6058
|
+
const labels = normalizeLabels(input.memory.labels);
|
|
6059
|
+
if (!namespace || !labels) return denied("invalid_input");
|
|
6060
|
+
const owner = boundedOptionalText(input.change.ownerLabel, MEMORY_SLACK_OWNER_MAX_UTF8_BYTES);
|
|
6061
|
+
const projection = {
|
|
6062
|
+
version: MEMORY_SLACK_PROJECTION_VERSION,
|
|
6063
|
+
workspaceId: input.context.workspaceId,
|
|
6064
|
+
memoryId: input.memory.id,
|
|
6065
|
+
memoryVersion: input.memory.version,
|
|
6066
|
+
changeKind: input.change.kind,
|
|
6067
|
+
relatedMemoryId: input.change.relatedMemoryId,
|
|
6068
|
+
occurredAt: new Date(input.change.occurredAt).toISOString(),
|
|
6069
|
+
importance: input.distribution.importance,
|
|
6070
|
+
deliveryMode,
|
|
6071
|
+
summary: summary.value,
|
|
6072
|
+
summaryRedacted: redactedSummary !== collapsedSummary,
|
|
6073
|
+
summaryTruncated: summary.truncated,
|
|
6074
|
+
namespace,
|
|
6075
|
+
labels: labels.values,
|
|
6076
|
+
labelsTruncated: labels.truncated,
|
|
6077
|
+
ownerLabel: owner.value,
|
|
6078
|
+
ownerLabelRedacted: owner.redacted,
|
|
6079
|
+
ownerLabelTruncated: owner.truncated,
|
|
6080
|
+
authoritativeRecord: {
|
|
6081
|
+
workspaceId: input.context.workspaceId,
|
|
6082
|
+
memoryId: input.memory.id
|
|
6083
|
+
}
|
|
6084
|
+
};
|
|
6085
|
+
if (utf8Bytes(stableJson3(projection)) > MEMORY_SLACK_PROJECTION_MAX_UTF8_BYTES) {
|
|
6086
|
+
return denied("invalid_input");
|
|
6087
|
+
}
|
|
6088
|
+
const digest = createHash("sha256").update(stableJson3(projection), "utf8").digest("hex");
|
|
6089
|
+
return {
|
|
6090
|
+
eligible: true,
|
|
6091
|
+
deliveryMode,
|
|
6092
|
+
idempotencyKey: `memory-slack:v${MEMORY_SLACK_PROJECTION_VERSION}:${digest}`,
|
|
6093
|
+
projection
|
|
6094
|
+
};
|
|
6095
|
+
}
|
|
6096
|
+
function validPolicy(policy) {
|
|
6097
|
+
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));
|
|
6098
|
+
}
|
|
6099
|
+
function validIdentity(input) {
|
|
6100
|
+
const uuids = [
|
|
6101
|
+
input.context.accountId,
|
|
6102
|
+
input.context.workspaceId,
|
|
6103
|
+
input.memory.accountId,
|
|
6104
|
+
input.memory.workspaceId,
|
|
6105
|
+
input.memory.id,
|
|
6106
|
+
input.memory.supersedesId,
|
|
6107
|
+
input.memory.supersededById,
|
|
6108
|
+
input.change.relatedMemoryId
|
|
6109
|
+
].filter((value) => value !== null);
|
|
6110
|
+
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);
|
|
6111
|
+
}
|
|
6112
|
+
function evaluateValidity(input) {
|
|
6113
|
+
const now = Date.parse(input.context.now);
|
|
6114
|
+
const occurredAt = Date.parse(input.change.occurredAt);
|
|
6115
|
+
const validFrom = Date.parse(input.memory.validFrom);
|
|
6116
|
+
const validUntil = input.memory.validUntil === null ? null : Date.parse(input.memory.validUntil);
|
|
6117
|
+
if (!Number.isFinite(now) || !Number.isFinite(occurredAt) || !Number.isFinite(validFrom) || validUntil !== null && !Number.isFinite(validUntil) || validUntil !== null && validUntil <= validFrom) {
|
|
6118
|
+
return "invalid_input";
|
|
6119
|
+
}
|
|
6120
|
+
if (now < validFrom) return "not_yet_valid";
|
|
6121
|
+
if (validUntil !== null && now >= validUntil) return "expired";
|
|
6122
|
+
return null;
|
|
6123
|
+
}
|
|
6124
|
+
function validChangeLineage(input) {
|
|
6125
|
+
if (input.memory.supersedesId === input.memory.id || input.memory.supersededById === input.memory.id || input.change.relatedMemoryId === input.memory.id) {
|
|
6126
|
+
return false;
|
|
6127
|
+
}
|
|
6128
|
+
switch (input.change.kind) {
|
|
6129
|
+
case "created":
|
|
6130
|
+
return input.change.relatedMemoryId === null && input.memory.supersedesId === null && input.memory.supersededById === null;
|
|
6131
|
+
case "corrected":
|
|
6132
|
+
return input.change.relatedMemoryId !== null && input.change.relatedMemoryId !== input.memory.id && input.memory.supersedesId === input.change.relatedMemoryId && input.memory.supersededById === null;
|
|
6133
|
+
case "superseded":
|
|
6134
|
+
return input.change.relatedMemoryId !== null && input.change.relatedMemoryId !== input.memory.id && input.memory.supersededById === input.change.relatedMemoryId;
|
|
6135
|
+
}
|
|
6136
|
+
}
|
|
6137
|
+
function statusEligibleForChange(input) {
|
|
6138
|
+
return input.change.kind === "superseded" ? input.memory.status === "superseded" : VISIBLE_STATUSES.has(input.memory.status);
|
|
6139
|
+
}
|
|
6140
|
+
function effectiveDeliveryMode(policy, distribution) {
|
|
6141
|
+
const auto = new Set(policy.autoImportances);
|
|
6142
|
+
const review = new Set(policy.reviewImportances);
|
|
6143
|
+
if (distribution.slackMode === "review") {
|
|
6144
|
+
return auto.has(distribution.importance) || review.has(distribution.importance) ? "review" : null;
|
|
6145
|
+
}
|
|
6146
|
+
if (auto.has(distribution.importance)) return "auto";
|
|
6147
|
+
if (review.has(distribution.importance)) return "review";
|
|
6148
|
+
return null;
|
|
6149
|
+
}
|
|
6150
|
+
function normalizeNamespace(value) {
|
|
6151
|
+
const trimmed = value.trim();
|
|
6152
|
+
if (redactSensitiveText(trimmed) !== trimmed) return null;
|
|
6153
|
+
const namespace = trimmed.toLowerCase();
|
|
6154
|
+
if (!namespace || utf8Bytes(namespace) > MEMORY_SLACK_NAMESPACE_MAX_UTF8_BYTES) return null;
|
|
6155
|
+
if (redactSensitiveText(namespace) !== namespace) return null;
|
|
6156
|
+
const segments = namespace.split("/");
|
|
6157
|
+
if (segments.some((segment) => !SELECTOR_SEGMENT_PATTERN.test(segment))) return null;
|
|
6158
|
+
return segments.join("/");
|
|
6159
|
+
}
|
|
6160
|
+
function normalizeLabels(values) {
|
|
6161
|
+
if (!Array.isArray(values)) return null;
|
|
6162
|
+
const labels = /* @__PURE__ */ new Set();
|
|
6163
|
+
for (const value of values) {
|
|
6164
|
+
if (typeof value !== "string") return null;
|
|
6165
|
+
const trimmed = value.trim();
|
|
6166
|
+
if (redactSensitiveText(trimmed) !== trimmed) return null;
|
|
6167
|
+
const label = trimmed.toLowerCase();
|
|
6168
|
+
if (redactSensitiveText(label) !== label || !SELECTOR_SEGMENT_PATTERN.test(label) || utf8Bytes(label) > MEMORY_SLACK_LABEL_MAX_UTF8_BYTES) {
|
|
6169
|
+
return null;
|
|
6170
|
+
}
|
|
6171
|
+
labels.add(label);
|
|
6172
|
+
}
|
|
6173
|
+
const sorted = [...labels].sort();
|
|
6174
|
+
return {
|
|
6175
|
+
values: sorted.slice(0, MEMORY_SLACK_LABEL_MAX_COUNT),
|
|
6176
|
+
truncated: sorted.length > MEMORY_SLACK_LABEL_MAX_COUNT
|
|
6177
|
+
};
|
|
6178
|
+
}
|
|
6179
|
+
function boundedOptionalText(value, maxBytes) {
|
|
6180
|
+
const collapsed = collapseText(value ?? "");
|
|
6181
|
+
if (!collapsed) return { value: null, redacted: false, truncated: false };
|
|
6182
|
+
const redacted = redactSensitiveText(collapsed);
|
|
6183
|
+
const bounded = truncateUtf8(redacted, maxBytes);
|
|
6184
|
+
return {
|
|
6185
|
+
value: bounded.value || null,
|
|
6186
|
+
redacted: redacted !== collapsed,
|
|
6187
|
+
truncated: bounded.truncated
|
|
6188
|
+
};
|
|
6189
|
+
}
|
|
6190
|
+
function collapseText(value) {
|
|
6191
|
+
return value.replace(/[\u0000-\u001F\u007F-\u009F]/g, " ").replace(/\s+/g, " ").trim();
|
|
6192
|
+
}
|
|
6193
|
+
function truncateUtf8(value, maxBytes) {
|
|
6194
|
+
const bytes = encoder.encode(value);
|
|
6195
|
+
if (bytes.byteLength <= maxBytes) return { value, truncated: false };
|
|
6196
|
+
const marker = "\u2026";
|
|
6197
|
+
const markerBytes = encoder.encode(marker);
|
|
6198
|
+
let end = Math.max(0, maxBytes - markerBytes.byteLength);
|
|
6199
|
+
while (end > 0 && (bytes[end] & 192) === 128) end -= 1;
|
|
6200
|
+
return {
|
|
6201
|
+
value: `${decoder.decode(bytes.subarray(0, end)).trimEnd()}${marker}`,
|
|
6202
|
+
truncated: true
|
|
6203
|
+
};
|
|
6204
|
+
}
|
|
6205
|
+
function utf8Bytes(value) {
|
|
6206
|
+
return encoder.encode(value).byteLength;
|
|
6207
|
+
}
|
|
6208
|
+
function denied(reason) {
|
|
6209
|
+
return { eligible: false, reason };
|
|
6210
|
+
}
|
|
6211
|
+
|
|
5968
6212
|
// src/domain/workspace-members.ts
|
|
5969
6213
|
import { HTTPException as HTTPException12 } from "hono/http-exception";
|
|
5970
6214
|
var MEMBER_ADMIN_PERMISSIONS = ["workspace:admin", "members:manage"];
|
|
@@ -6678,6 +6922,7 @@ async function saveHumanComposerDraft(deps, context, input) {
|
|
|
6678
6922
|
export {
|
|
6679
6923
|
CODEX_COMPACTION_V2_PROVIDER_LOCKED,
|
|
6680
6924
|
CodexCompactionV2ProviderLockedError,
|
|
6925
|
+
DEFAULT_MEMORY_SLACK_PUBLICATION_POLICY,
|
|
6681
6926
|
MARKETING_SOCIAL_PACK_ID,
|
|
6682
6927
|
MAX_CHECKS_PER_RIG,
|
|
6683
6928
|
MAX_CREDENTIAL_HOOKS_PER_RIG,
|
|
@@ -6685,6 +6930,13 @@ export {
|
|
|
6685
6930
|
MAX_ENVIRONMENTS_PER_WORKSPACE,
|
|
6686
6931
|
MAX_RIGS_PER_WORKSPACE,
|
|
6687
6932
|
MAX_VARIABLES_PER_ENVIRONMENT,
|
|
6933
|
+
MEMORY_SLACK_LABEL_MAX_COUNT,
|
|
6934
|
+
MEMORY_SLACK_LABEL_MAX_UTF8_BYTES,
|
|
6935
|
+
MEMORY_SLACK_NAMESPACE_MAX_UTF8_BYTES,
|
|
6936
|
+
MEMORY_SLACK_OWNER_MAX_UTF8_BYTES,
|
|
6937
|
+
MEMORY_SLACK_PROJECTION_MAX_UTF8_BYTES,
|
|
6938
|
+
MEMORY_SLACK_PROJECTION_VERSION,
|
|
6939
|
+
MEMORY_SLACK_SUMMARY_MAX_UTF8_BYTES,
|
|
6688
6940
|
SESSION_AUTHORIZATION_DEFAULT_REAUTHORIZE_MS,
|
|
6689
6941
|
SESSION_WORKFLOW_WAKE_DISPATCHER_PERIOD_MS,
|
|
6690
6942
|
SESSION_WORKFLOW_WAKE_DISPATCHER_SCHEDULE_ID,
|
|
@@ -6734,6 +6986,7 @@ export {
|
|
|
6734
6986
|
editHumanQueuePrompt,
|
|
6735
6987
|
enableCapability,
|
|
6736
6988
|
enabledCapabilityMcpToolRefs,
|
|
6989
|
+
evaluateMemorySlackPublication,
|
|
6737
6990
|
executeRunOnSelfhostedMachine,
|
|
6738
6991
|
filenameForMimeType,
|
|
6739
6992
|
freezePersonalConnectionDelegations,
|