negotium 0.2.24 → 0.2.26
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/agent-helpers.js +82 -29
- package/dist/agent-helpers.js.map +5 -5
- package/dist/hosted-agent.js +2 -2
- package/dist/hosted-agent.js.map +2 -2
- package/dist/main.js +167 -364
- package/dist/main.js.map +26 -27
- package/dist/mcp-factories.js +84 -30
- package/dist/mcp-factories.js.map +6 -6
- package/dist/registry.js +2 -2
- package/dist/registry.js.map +2 -2
- package/dist/runtime/src/index.ts +3 -7
- package/dist/runtime/src/mcp/session-comm/default-host.ts +6 -1
- package/dist/runtime/src/mcp/session-comm/topic-catalog.ts +17 -1
- package/dist/runtime/src/mcp/session-comm/topics.ts +23 -1
- package/dist/runtime/src/node-host.ts +2 -3
- package/dist/runtime/src/storage/api-topics.ts +164 -52
- package/dist/runtime/src/storage/storage-public.ts +0 -1
- package/dist/runtime/src/topics/create.ts +12 -6
- package/dist/runtime/src/topics/derive.ts +20 -11
- package/dist/runtime/src/types/api.ts +8 -4
- package/dist/runtime/src/version.ts +1 -1
- package/dist/storage.js +92 -38
- package/dist/storage.js.map +3 -3
- package/dist/types/packages/core/src/mcp/session-comm/topic-catalog.d.ts +7 -0
- package/dist/types/packages/core/src/storage/api-topics.d.ts +34 -19
- package/dist/types/packages/core/src/storage/storage-public.d.ts +1 -1
- package/dist/types/packages/core/src/topics/derive.d.ts +13 -4
- package/dist/types/packages/core/src/types/api.d.ts +8 -4
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/dist/runtime/src/application/switch-topic-access-mode.ts +0 -110
package/dist/mcp-factories.js
CHANGED
|
@@ -1016,7 +1016,7 @@ var init_claude_registry = __esm(() => {
|
|
|
1016
1016
|
});
|
|
1017
1017
|
|
|
1018
1018
|
// ../../packages/core/src/version.ts
|
|
1019
|
-
var NEGOTIUM_VERSION = "0.2.
|
|
1019
|
+
var NEGOTIUM_VERSION = "0.2.26";
|
|
1020
1020
|
|
|
1021
1021
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
1022
1022
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -4059,6 +4059,12 @@ var init_constants = __esm(() => {
|
|
|
4059
4059
|
});
|
|
4060
4060
|
|
|
4061
4061
|
// ../../packages/core/src/storage/api-topics.ts
|
|
4062
|
+
function defaultTopicSurface() {
|
|
4063
|
+
return normalizeTopicSurface(process.env.NEGOTIUM_DEFAULT_SURFACE);
|
|
4064
|
+
}
|
|
4065
|
+
function normalizeTopicSurface(value2) {
|
|
4066
|
+
return value2 === "telegram" || value2 === "otium" || value2 === "terminal" ? value2 : "terminal";
|
|
4067
|
+
}
|
|
4062
4068
|
function tableColumns(table) {
|
|
4063
4069
|
const rows = db.query(`PRAGMA table_info(${table})`).all();
|
|
4064
4070
|
return new Set(rows.map((row) => row.name));
|
|
@@ -4182,7 +4188,7 @@ function initializeApiTopicsSchema() {
|
|
|
4182
4188
|
is_fork INTEGER NOT NULL DEFAULT 0 CHECK (is_fork IN (0,1)),
|
|
4183
4189
|
is_subagent INTEGER NOT NULL DEFAULT 0 CHECK (is_subagent IN (0,1)),
|
|
4184
4190
|
visibility TEXT NOT NULL DEFAULT 'visible' CHECK (visibility IN ('visible','hidden')),
|
|
4185
|
-
|
|
4191
|
+
surface TEXT NOT NULL DEFAULT 'terminal' CHECK (surface IN ('terminal','telegram','otium')),
|
|
4186
4192
|
browser_profile TEXT NOT NULL DEFAULT 'default',
|
|
4187
4193
|
browser_profile_owner TEXT,
|
|
4188
4194
|
session_id TEXT,
|
|
@@ -4228,8 +4234,8 @@ function initializeApiTopicsSchema() {
|
|
|
4228
4234
|
const legacyBaseEffort = row.base_effort ?? row.default_effort;
|
|
4229
4235
|
db.query(`INSERT INTO api_topics_next
|
|
4230
4236
|
(id,title,kind,description,agent,base_model,base_effort,response_policy,
|
|
4231
|
-
created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,
|
|
4232
|
-
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`).run(String(row.id), String(row.title), normalized.kind, typeof row.description === "string" ? row.description : null, normalized.agent ?? null, typeof legacyBaseModel === "string" ? legacyBaseModel : null, typeof legacyBaseEffort === "string" ? legacyBaseEffort : null, normalized.aiMode, String(row.created_at), typeof row.last_message_at === "string" ? row.last_message_at : null, typeof row.parent_topic_id === "string" ? row.parent_topic_id : null, typeof row.memory_topic_id === "string" ? row.memory_topic_id : null, typeof row.memory_key === "string" ? row.memory_key : null, Number(row.is_fork ?? 0) !== 0 ? 1 : 0, Number(row.is_subagent ?? 0) !== 0 ? 1 : 0, row.visibility === "hidden" ? "hidden" : "visible", row.
|
|
4237
|
+
created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,surface,session_id)
|
|
4238
|
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`).run(String(row.id), String(row.title), normalized.kind, typeof row.description === "string" ? row.description : null, normalized.agent ?? null, typeof legacyBaseModel === "string" ? legacyBaseModel : null, typeof legacyBaseEffort === "string" ? legacyBaseEffort : null, normalized.aiMode, String(row.created_at), typeof row.last_message_at === "string" ? row.last_message_at : null, typeof row.parent_topic_id === "string" ? row.parent_topic_id : null, typeof row.memory_topic_id === "string" ? row.memory_topic_id : null, typeof row.memory_key === "string" ? row.memory_key : null, Number(row.is_fork ?? 0) !== 0 ? 1 : 0, Number(row.is_subagent ?? 0) !== 0 ? 1 : 0, row.visibility === "hidden" ? "hidden" : "visible", row.surface === undefined ? defaultTopicSurface() : normalizeTopicSurface(row.surface), typeof row.session_id === "string" ? row.session_id : null);
|
|
4233
4239
|
}
|
|
4234
4240
|
db.exec("DROP TABLE IF EXISTS topic_members");
|
|
4235
4241
|
db.exec("DROP TABLE api_topics");
|
|
@@ -4283,8 +4289,15 @@ function initializeApiTopicsSchema() {
|
|
|
4283
4289
|
if (!tableColumns("api_topics").has("visibility")) {
|
|
4284
4290
|
db.exec("ALTER TABLE api_topics ADD COLUMN visibility TEXT NOT NULL DEFAULT 'visible'");
|
|
4285
4291
|
}
|
|
4286
|
-
if (!tableColumns("api_topics").has("
|
|
4287
|
-
db.exec("ALTER TABLE api_topics ADD COLUMN
|
|
4292
|
+
if (!tableColumns("api_topics").has("surface")) {
|
|
4293
|
+
db.exec("ALTER TABLE api_topics ADD COLUMN surface TEXT NOT NULL DEFAULT 'terminal'");
|
|
4294
|
+
}
|
|
4295
|
+
if (tableColumns("api_topics").has("access_mode")) {
|
|
4296
|
+
try {
|
|
4297
|
+
db.exec("ALTER TABLE api_topics DROP COLUMN access_mode");
|
|
4298
|
+
} catch (err) {
|
|
4299
|
+
logger.warn({ err }, "api_topics: could not drop the retired access_mode column");
|
|
4300
|
+
}
|
|
4288
4301
|
}
|
|
4289
4302
|
if (!tableColumns("api_topics").has("browser_profile")) {
|
|
4290
4303
|
db.exec("ALTER TABLE api_topics ADD COLUMN browser_profile TEXT NOT NULL DEFAULT 'default'");
|
|
@@ -4311,7 +4324,48 @@ function initializeApiTopicsSchema() {
|
|
|
4311
4324
|
)
|
|
4312
4325
|
WHERE browser_profile_owner IS NULL
|
|
4313
4326
|
`);
|
|
4327
|
+
backfillTopicSurfaces();
|
|
4314
4328
|
db.exec("CREATE INDEX IF NOT EXISTS idx_api_topics_last_message ON api_topics(last_message_at DESC)");
|
|
4329
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_api_topics_surface ON api_topics(surface)");
|
|
4330
|
+
}
|
|
4331
|
+
function backfillTopicSurfaces() {
|
|
4332
|
+
db.exec(`
|
|
4333
|
+
CREATE TABLE IF NOT EXISTS api_schema_migrations (
|
|
4334
|
+
key TEXT PRIMARY KEY,
|
|
4335
|
+
applied_at TEXT NOT NULL
|
|
4336
|
+
)
|
|
4337
|
+
`);
|
|
4338
|
+
const applied = db.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(SURFACE_BACKFILL_MIGRATION);
|
|
4339
|
+
if (applied)
|
|
4340
|
+
return;
|
|
4341
|
+
const surface = defaultTopicSurface();
|
|
4342
|
+
db.transaction(() => {
|
|
4343
|
+
db.query("UPDATE api_topics SET surface = ?").run(surface);
|
|
4344
|
+
renameSurfaceTitleCollisions();
|
|
4345
|
+
db.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(SURFACE_BACKFILL_MIGRATION, new Date().toISOString());
|
|
4346
|
+
})();
|
|
4347
|
+
logger.info({ surface }, "api_topics: surface backfilled");
|
|
4348
|
+
}
|
|
4349
|
+
function renameSurfaceTitleCollisions() {
|
|
4350
|
+
const rows = db.query("SELECT id, title, kind, surface FROM api_topics ORDER BY created_at ASC, rowid ASC").all();
|
|
4351
|
+
const taken = new Set;
|
|
4352
|
+
const update = db.query("UPDATE api_topics SET title = ? WHERE id = ?");
|
|
4353
|
+
for (const row of rows) {
|
|
4354
|
+
const key = (title) => [row.surface, row.kind, normalizedTitle(title)].join("\x00");
|
|
4355
|
+
if (!taken.has(key(row.title))) {
|
|
4356
|
+
taken.add(key(row.title));
|
|
4357
|
+
continue;
|
|
4358
|
+
}
|
|
4359
|
+
let suffix = 2;
|
|
4360
|
+
let candidate = `${row.title} (${suffix})`;
|
|
4361
|
+
while (taken.has(key(candidate))) {
|
|
4362
|
+
suffix += 1;
|
|
4363
|
+
candidate = `${row.title} (${suffix})`;
|
|
4364
|
+
}
|
|
4365
|
+
taken.add(key(candidate));
|
|
4366
|
+
update.run(candidate, row.id);
|
|
4367
|
+
logger.warn({ topicId: row.id, surface: row.surface, from: row.title, to: candidate }, "api_topics: renamed a duplicate title for surface-scoped uniqueness");
|
|
4368
|
+
}
|
|
4315
4369
|
}
|
|
4316
4370
|
function shortSessionId(sessionId) {
|
|
4317
4371
|
return sessionId ? sessionId.slice(0, 8) : null;
|
|
@@ -4371,12 +4425,9 @@ function rowToDto2(r, participants = getTopicParticipants(r.id), tellTargets) {
|
|
|
4371
4425
|
subagentReportMode: r.subagent_report_mode === "tell" || r.subagent_report_mode === "status-only" ? r.subagent_report_mode : "auto"
|
|
4372
4426
|
} : {},
|
|
4373
4427
|
visibility: normalizeTopicVisibility(r.visibility),
|
|
4374
|
-
|
|
4428
|
+
surface: normalizeTopicSurface(r.surface)
|
|
4375
4429
|
};
|
|
4376
4430
|
}
|
|
4377
|
-
function normalizeTopicAccessMode(value2) {
|
|
4378
|
-
return value2 === "shared" ? "shared" : "private";
|
|
4379
|
-
}
|
|
4380
4431
|
function normalizeTopicVisibility(value2) {
|
|
4381
4432
|
return value2 === "hidden" ? "hidden" : "visible";
|
|
4382
4433
|
}
|
|
@@ -4433,7 +4484,7 @@ function upsertTopic(t) {
|
|
|
4433
4484
|
db.transaction(() => {
|
|
4434
4485
|
db.query(`INSERT INTO api_topics
|
|
4435
4486
|
(id,title,kind,description,agent,base_model,base_effort,response_policy,
|
|
4436
|
-
created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,
|
|
4487
|
+
created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,surface,
|
|
4437
4488
|
subagent_report_mode)
|
|
4438
4489
|
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
|
4439
4490
|
ON CONFLICT(id) DO UPDATE SET
|
|
@@ -4452,8 +4503,8 @@ function upsertTopic(t) {
|
|
|
4452
4503
|
is_fork = excluded.is_fork,
|
|
4453
4504
|
is_subagent = excluded.is_subagent,
|
|
4454
4505
|
visibility = excluded.visibility,
|
|
4455
|
-
|
|
4456
|
-
subagent_report_mode = excluded.subagent_report_mode`).run(t.id, t.title, normalized.kind, t.description ?? null, normalized.agent ?? null, t.defaultModel ?? null, t.defaultEffort ?? null, normalized.aiMode, t.createdAt, t.lastMessageAt ?? null, t.parentTopicId ?? null, t.memoryTopicId ?? null, t.memoryKey ?? null, t.isFork ? 1 : 0, t.isSubagent ? 1 : 0, normalizeTopicVisibility(t.visibility),
|
|
4506
|
+
surface = excluded.surface,
|
|
4507
|
+
subagent_report_mode = excluded.subagent_report_mode`).run(t.id, t.title, normalized.kind, t.description ?? null, normalized.agent ?? null, t.defaultModel ?? null, t.defaultEffort ?? null, normalized.aiMode, t.createdAt, t.lastMessageAt ?? null, t.parentTopicId ?? null, t.memoryTopicId ?? null, t.memoryKey ?? null, t.isFork ? 1 : 0, t.isSubagent ? 1 : 0, normalizeTopicVisibility(t.visibility), normalizeTopicSurface(t.surface ?? defaultTopicSurface()), t.subagentReportMode ?? "auto");
|
|
4457
4508
|
db.query("DELETE FROM topic_members WHERE topic_id = ?").run(t.id);
|
|
4458
4509
|
for (const participant of t.participants) {
|
|
4459
4510
|
db.query("INSERT INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(t.id, participant.userId, participant.role);
|
|
@@ -4466,8 +4517,8 @@ function upsertTopic(t) {
|
|
|
4466
4517
|
}
|
|
4467
4518
|
})();
|
|
4468
4519
|
}
|
|
4469
|
-
function listTopics() {
|
|
4470
|
-
const rows = db.query("SELECT * FROM api_topics ORDER BY last_message_at DESC").all();
|
|
4520
|
+
function listTopics(opts = {}) {
|
|
4521
|
+
const rows = opts.surface ? db.query("SELECT * FROM api_topics WHERE surface = ? ORDER BY last_message_at DESC").all(normalizeTopicSurface(opts.surface)) : db.query("SELECT * FROM api_topics ORDER BY last_message_at DESC").all();
|
|
4471
4522
|
const participants = getAllTopicParticipants();
|
|
4472
4523
|
const tellTargets = rows.some((row) => row.is_subagent !== 0) ? getAllSubagentTellTargets() : undefined;
|
|
4473
4524
|
return rows.map((row) => rowToDto2(row, participants.get(row.id) ?? [], tellTargets));
|
|
@@ -4514,14 +4565,15 @@ function getTopicByName(title) {
|
|
|
4514
4565
|
}
|
|
4515
4566
|
function findTopicTitleConflict(title, kind, opts = {}) {
|
|
4516
4567
|
const wanted = normalizedTitle(title);
|
|
4568
|
+
const surface = normalizeTopicSurface(opts.surface ?? defaultTopicSurface());
|
|
4517
4569
|
const generalTitleRequested = wanted === normalizedTitle(GENERAL_TOPIC_ID);
|
|
4518
4570
|
if (generalTitleRequested && opts.excludeTopicId !== GENERAL_TOPIC_ID) {
|
|
4519
4571
|
const general = db.query("SELECT * FROM api_topics WHERE id = ?").get(GENERAL_TOPIC_ID);
|
|
4520
4572
|
if (general)
|
|
4521
4573
|
return rowToDto2(general);
|
|
4522
4574
|
}
|
|
4523
|
-
const params = [wanted];
|
|
4524
|
-
let sql = "SELECT * FROM api_topics WHERE LOWER(TRIM(title)) = ?";
|
|
4575
|
+
const params = [wanted, surface];
|
|
4576
|
+
let sql = "SELECT * FROM api_topics WHERE LOWER(TRIM(title)) = ? AND surface = ?";
|
|
4525
4577
|
if (kind !== "manager") {
|
|
4526
4578
|
sql += " AND (kind = ? OR id = ?)";
|
|
4527
4579
|
params.push(kind, GENERAL_TOPIC_ID);
|
|
@@ -4606,7 +4658,7 @@ function reparentTopicChildren(deletedTopicId, replacementParentTopicId) {
|
|
|
4606
4658
|
}
|
|
4607
4659
|
return rows.map((row) => row.id);
|
|
4608
4660
|
}
|
|
4609
|
-
var DEFAULT_AGENT_ROOM_AGENT = "maestro";
|
|
4661
|
+
var DEFAULT_AGENT_ROOM_AGENT = "maestro", SURFACE_BACKFILL_MIGRATION = "api_topics_surface_backfill_20260808";
|
|
4610
4662
|
var init_api_topics = __esm(async () => {
|
|
4611
4663
|
init_constants();
|
|
4612
4664
|
init_logger();
|
|
@@ -11965,11 +12017,11 @@ __export(exports_derive, {
|
|
|
11965
12017
|
});
|
|
11966
12018
|
import { createHash as createHash4, randomUUID as randomUUID11 } from "crypto";
|
|
11967
12019
|
import { mkdirSync as mkdirSync14, rmSync as rmSync5, unlinkSync as unlinkSync14 } from "fs";
|
|
11968
|
-
function getTopics() {
|
|
11969
|
-
return listTopics().filter((topic) => !isLegacySharedGeneral(topic.id));
|
|
12020
|
+
function getTopics(opts = {}) {
|
|
12021
|
+
return listTopics(opts).filter((topic) => !isLegacySharedGeneral(topic.id));
|
|
11970
12022
|
}
|
|
11971
|
-
function getVisibleTopics() {
|
|
11972
|
-
return getTopics().filter(isTopicVisible).map((topic) => {
|
|
12023
|
+
function getVisibleTopics(opts = {}) {
|
|
12024
|
+
return getTopics(opts).filter(isTopicVisible).map((topic) => {
|
|
11973
12025
|
if (!topic.agent)
|
|
11974
12026
|
return topic;
|
|
11975
12027
|
const registry = getRegistry(topic.agent);
|
|
@@ -11994,8 +12046,8 @@ function updateTopic(topicId, patch) {
|
|
|
11994
12046
|
function isParticipant(topic, userId) {
|
|
11995
12047
|
return topic.participants.some((p) => p.userId === userId);
|
|
11996
12048
|
}
|
|
11997
|
-
function nextDerivedTopicTitle(sourceTitle, kind, suffix) {
|
|
11998
|
-
const visibleTitles = new Set(listTopics().filter((topic) => topic.kind === kind).map((topic) => topic.title.toLowerCase()));
|
|
12049
|
+
function nextDerivedTopicTitle(sourceTitle, kind, suffix, surface) {
|
|
12050
|
+
const visibleTitles = new Set(listTopics(surface ? { surface } : {}).filter((topic) => topic.kind === kind).map((topic) => topic.title.toLowerCase()));
|
|
11999
12051
|
let n = 1;
|
|
12000
12052
|
let title = `${sourceTitle}-${suffix}-${n}`;
|
|
12001
12053
|
while (visibleTitles.has(title.toLowerCase())) {
|
|
@@ -12059,8 +12111,9 @@ async function createDerivedTopicImpl(topic, sourceTopicId, userId, copyHistory,
|
|
|
12059
12111
|
{ userId, role: "owner" }
|
|
12060
12112
|
] : [{ userId, role: "owner" }];
|
|
12061
12113
|
const kind = topic.kind ?? inferTopicKind(topic);
|
|
12062
|
-
const
|
|
12063
|
-
const
|
|
12114
|
+
const surface = topic.surface ?? defaultTopicSurface();
|
|
12115
|
+
const title = opts?.name?.trim() || nextDerivedTopicTitle(topic.title, kind, suffix, surface);
|
|
12116
|
+
const conflict = findTopicTitleConflict(title, kind, { surface });
|
|
12064
12117
|
if (conflict) {
|
|
12065
12118
|
logger.info({ sourceTopicId, title, kind, conflictTopicId: conflict.id }, "createDerivedTopic: title conflict");
|
|
12066
12119
|
throw new TopicTitleConflictError(title);
|
|
@@ -12083,7 +12136,7 @@ async function createDerivedTopicImpl(topic, sourceTopicId, userId, copyHistory,
|
|
|
12083
12136
|
isFork: copyHistory,
|
|
12084
12137
|
...subagent ? { isSubagent: true } : {},
|
|
12085
12138
|
visibility: topic.visibility,
|
|
12086
|
-
|
|
12139
|
+
surface
|
|
12087
12140
|
};
|
|
12088
12141
|
let sessionId;
|
|
12089
12142
|
let rollbackHandle;
|
|
@@ -12191,7 +12244,7 @@ async function createDerivedTopicImpl(topic, sourceTopicId, userId, copyHistory,
|
|
|
12191
12244
|
if (!currentSource || currentSource.kind === "manager" || !isParticipant(currentSource, userId) || subagent && isRuntimeTopicMaintenance(sourceTopicId)) {
|
|
12192
12245
|
throw new TopicDeriveBusyError("Source topic changed while deriving; try again");
|
|
12193
12246
|
}
|
|
12194
|
-
const transactionalConflict = findTopicTitleConflict(title, kind);
|
|
12247
|
+
const transactionalConflict = findTopicTitleConflict(title, kind, { surface });
|
|
12195
12248
|
if (transactionalConflict)
|
|
12196
12249
|
throw new TopicTitleConflictError(title);
|
|
12197
12250
|
upsertTopic(derived);
|
|
@@ -17835,7 +17888,8 @@ function parseSessionCommContext(args, defaults) {
|
|
|
17835
17888
|
function createSessionTargetCatalog(host) {
|
|
17836
17889
|
const { currentTopicId, currentTopicName, isAgent, listRows } = host;
|
|
17837
17890
|
function listTargets() {
|
|
17838
|
-
const
|
|
17891
|
+
const currentSurface = host.currentSurface;
|
|
17892
|
+
const eligibleRows = listRows().filter((row) => row.kind !== "manager" && (!currentSurface || (row.surface ?? currentSurface) === currentSurface));
|
|
17839
17893
|
const titleCounts = new Map;
|
|
17840
17894
|
const qualifiedCounts = new Map;
|
|
17841
17895
|
for (const row of eligibleRows) {
|
|
@@ -21024,4 +21078,4 @@ export {
|
|
|
21024
21078
|
createAgentHealthMcpServer
|
|
21025
21079
|
};
|
|
21026
21080
|
|
|
21027
|
-
//# debugId=
|
|
21081
|
+
//# debugId=A3645A70D023CC9C64756E2164756E21
|