@ai-setting/roy-agent-core 1.7.4 → 1.7.6
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/env/index.js +4 -4
- package/dist/env/plugin/index.js +1 -1
- package/dist/env/workflow/engine/index.js +2 -2
- package/dist/env/workflow/index.js +3 -3
- package/dist/env/workflow/nodes/index.js +1 -1
- package/dist/index.js +4 -4
- package/dist/shared/@ai-setting/{roy-agent-core-c9kbf0ce.js → roy-agent-core-7bskb5j2.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-ya1tr7xq.js → roy-agent-core-cpfdvzqk.js} +59 -5
- package/dist/shared/@ai-setting/{roy-agent-core-0qjw25e8.js → roy-agent-core-hmqmznjc.js} +33 -1
- package/dist/shared/@ai-setting/{roy-agent-core-3x3k7gfs.js → roy-agent-core-mfxwnyhs.js} +46 -3
- package/package.json +1 -1
package/dist/env/index.js
CHANGED
|
@@ -29,7 +29,7 @@ import"../shared/@ai-setting/roy-agent-core-1pg0fepg.js";
|
|
|
29
29
|
import"../shared/@ai-setting/roy-agent-core-skqt40yy.js";
|
|
30
30
|
import {
|
|
31
31
|
WorkflowComponent
|
|
32
|
-
} from "../shared/@ai-setting/roy-agent-core-
|
|
32
|
+
} from "../shared/@ai-setting/roy-agent-core-7bskb5j2.js";
|
|
33
33
|
import"../shared/@ai-setting/roy-agent-core-7xek618f.js";
|
|
34
34
|
import"../shared/@ai-setting/roy-agent-core-h0x19xgn.js";
|
|
35
35
|
import"../shared/@ai-setting/roy-agent-core-1ce3fqrk.js";
|
|
@@ -38,10 +38,10 @@ import"../shared/@ai-setting/roy-agent-core-v13dq3nc.js";
|
|
|
38
38
|
import"../shared/@ai-setting/roy-agent-core-wgp3q62x.js";
|
|
39
39
|
import"../shared/@ai-setting/roy-agent-core-hhrg314p.js";
|
|
40
40
|
import"../shared/@ai-setting/roy-agent-core-j9ybhwnq.js";
|
|
41
|
-
import"../shared/@ai-setting/roy-agent-core-
|
|
41
|
+
import"../shared/@ai-setting/roy-agent-core-cpfdvzqk.js";
|
|
42
42
|
import"../shared/@ai-setting/roy-agent-core-6atd905e.js";
|
|
43
43
|
import"../shared/@ai-setting/roy-agent-core-ec4djnzd.js";
|
|
44
|
-
import"../shared/@ai-setting/roy-agent-core-
|
|
44
|
+
import"../shared/@ai-setting/roy-agent-core-hmqmznjc.js";
|
|
45
45
|
import"../shared/@ai-setting/roy-agent-core-1db4vpc6.js";
|
|
46
46
|
import"../shared/@ai-setting/roy-agent-core-w8rv08d3.js";
|
|
47
47
|
import"../shared/@ai-setting/roy-agent-core-h1cb2jzh.js";
|
|
@@ -68,7 +68,7 @@ import"../shared/@ai-setting/roy-agent-core-c1v263jn.js";
|
|
|
68
68
|
import"../shared/@ai-setting/roy-agent-core-e25xkv53.js";
|
|
69
69
|
import {
|
|
70
70
|
PluginComponent
|
|
71
|
-
} from "../shared/@ai-setting/roy-agent-core-
|
|
71
|
+
} from "../shared/@ai-setting/roy-agent-core-mfxwnyhs.js";
|
|
72
72
|
import"../shared/@ai-setting/roy-agent-core-az13yzmc.js";
|
|
73
73
|
import {
|
|
74
74
|
McpComponent
|
package/dist/env/plugin/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EventBusNotificationChannel,
|
|
3
3
|
PluginComponent
|
|
4
|
-
} from "../../shared/@ai-setting/roy-agent-core-
|
|
4
|
+
} from "../../shared/@ai-setting/roy-agent-core-mfxwnyhs.js";
|
|
5
5
|
import {
|
|
6
6
|
BasePlugin
|
|
7
7
|
} from "../../shared/@ai-setting/roy-agent-core-az13yzmc.js";
|
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
Scheduler,
|
|
6
6
|
WorkflowEngine,
|
|
7
7
|
init_engine
|
|
8
|
-
} from "../../../shared/@ai-setting/roy-agent-core-
|
|
8
|
+
} from "../../../shared/@ai-setting/roy-agent-core-cpfdvzqk.js";
|
|
9
9
|
import"../../../shared/@ai-setting/roy-agent-core-6atd905e.js";
|
|
10
10
|
import"../../../shared/@ai-setting/roy-agent-core-ec4djnzd.js";
|
|
11
|
-
import"../../../shared/@ai-setting/roy-agent-core-
|
|
11
|
+
import"../../../shared/@ai-setting/roy-agent-core-hmqmznjc.js";
|
|
12
12
|
import"../../../shared/@ai-setting/roy-agent-core-1db4vpc6.js";
|
|
13
13
|
import"../../../shared/@ai-setting/roy-agent-core-h1cb2jzh.js";
|
|
14
14
|
import"../../../shared/@ai-setting/roy-agent-core-ddwa0n6h.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
WorkflowComponent
|
|
3
|
-
} from "../../shared/@ai-setting/roy-agent-core-
|
|
3
|
+
} from "../../shared/@ai-setting/roy-agent-core-7bskb5j2.js";
|
|
4
4
|
import"../../shared/@ai-setting/roy-agent-core-7xek618f.js";
|
|
5
5
|
import {
|
|
6
6
|
Edge,
|
|
@@ -19,10 +19,10 @@ import"../../shared/@ai-setting/roy-agent-core-v13dq3nc.js";
|
|
|
19
19
|
import"../../shared/@ai-setting/roy-agent-core-wgp3q62x.js";
|
|
20
20
|
import"../../shared/@ai-setting/roy-agent-core-hhrg314p.js";
|
|
21
21
|
import"../../shared/@ai-setting/roy-agent-core-j9ybhwnq.js";
|
|
22
|
-
import"../../shared/@ai-setting/roy-agent-core-
|
|
22
|
+
import"../../shared/@ai-setting/roy-agent-core-cpfdvzqk.js";
|
|
23
23
|
import"../../shared/@ai-setting/roy-agent-core-6atd905e.js";
|
|
24
24
|
import"../../shared/@ai-setting/roy-agent-core-ec4djnzd.js";
|
|
25
|
-
import"../../shared/@ai-setting/roy-agent-core-
|
|
25
|
+
import"../../shared/@ai-setting/roy-agent-core-hmqmznjc.js";
|
|
26
26
|
import"../../shared/@ai-setting/roy-agent-core-1db4vpc6.js";
|
|
27
27
|
import"../../shared/@ai-setting/roy-agent-core-w8rv08d3.js";
|
|
28
28
|
import"../../shared/@ai-setting/roy-agent-core-h1cb2jzh.js";
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
init_skill_node,
|
|
8
8
|
init_tool_node,
|
|
9
9
|
init_workflow_node
|
|
10
|
-
} from "../../../shared/@ai-setting/roy-agent-core-
|
|
10
|
+
} from "../../../shared/@ai-setting/roy-agent-core-hmqmznjc.js";
|
|
11
11
|
import"../../../shared/@ai-setting/roy-agent-core-gb7pm9c0.js";
|
|
12
12
|
import"../../../shared/@ai-setting/roy-agent-core-kaq037np.js";
|
|
13
13
|
import"../../../shared/@ai-setting/roy-agent-core-1khp1m0r.js";
|
package/dist/index.js
CHANGED
|
@@ -119,7 +119,7 @@ import {
|
|
|
119
119
|
} from "./shared/@ai-setting/roy-agent-core-skqt40yy.js";
|
|
120
120
|
import {
|
|
121
121
|
WorkflowComponent
|
|
122
|
-
} from "./shared/@ai-setting/roy-agent-core-
|
|
122
|
+
} from "./shared/@ai-setting/roy-agent-core-7bskb5j2.js";
|
|
123
123
|
import {
|
|
124
124
|
init_node_registry_helper,
|
|
125
125
|
registerDecoratorNodeType
|
|
@@ -141,10 +141,10 @@ import {
|
|
|
141
141
|
} from "./shared/@ai-setting/roy-agent-core-wgp3q62x.js";
|
|
142
142
|
import"./shared/@ai-setting/roy-agent-core-hhrg314p.js";
|
|
143
143
|
import"./shared/@ai-setting/roy-agent-core-j9ybhwnq.js";
|
|
144
|
-
import"./shared/@ai-setting/roy-agent-core-
|
|
144
|
+
import"./shared/@ai-setting/roy-agent-core-cpfdvzqk.js";
|
|
145
145
|
import"./shared/@ai-setting/roy-agent-core-6atd905e.js";
|
|
146
146
|
import"./shared/@ai-setting/roy-agent-core-ec4djnzd.js";
|
|
147
|
-
import"./shared/@ai-setting/roy-agent-core-
|
|
147
|
+
import"./shared/@ai-setting/roy-agent-core-hmqmznjc.js";
|
|
148
148
|
import"./shared/@ai-setting/roy-agent-core-1db4vpc6.js";
|
|
149
149
|
import"./shared/@ai-setting/roy-agent-core-w8rv08d3.js";
|
|
150
150
|
import"./shared/@ai-setting/roy-agent-core-h1cb2jzh.js";
|
|
@@ -188,7 +188,7 @@ import {
|
|
|
188
188
|
} from "./shared/@ai-setting/roy-agent-core-e25xkv53.js";
|
|
189
189
|
import {
|
|
190
190
|
PluginComponent
|
|
191
|
-
} from "./shared/@ai-setting/roy-agent-core-
|
|
191
|
+
} from "./shared/@ai-setting/roy-agent-core-mfxwnyhs.js";
|
|
192
192
|
import {
|
|
193
193
|
BasePlugin
|
|
194
194
|
} from "./shared/@ai-setting/roy-agent-core-az13yzmc.js";
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
init_skill_node,
|
|
18
18
|
init_tool_node,
|
|
19
19
|
init_workflow_node
|
|
20
|
-
} from "./roy-agent-core-
|
|
20
|
+
} from "./roy-agent-core-hmqmznjc.js";
|
|
21
21
|
import {
|
|
22
22
|
WORKFLOW_SUBMIT_OUTPUT_TOOL_NAME,
|
|
23
23
|
init_json_schema_to_zod,
|
|
@@ -1423,6 +1423,57 @@ function mapNonTerminal(agentSessions, terminalStatus) {
|
|
|
1423
1423
|
}
|
|
1424
1424
|
var init_agent_session_metadata = () => {};
|
|
1425
1425
|
|
|
1426
|
+
// src/env/workflow/utils/sensitive-redact.ts
|
|
1427
|
+
function redactSensitiveFields(input) {
|
|
1428
|
+
if (input === undefined || input === null) {
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
if (typeof input !== "object") {
|
|
1432
|
+
return input;
|
|
1433
|
+
}
|
|
1434
|
+
return redactValue(input);
|
|
1435
|
+
}
|
|
1436
|
+
function redactValue(value) {
|
|
1437
|
+
if (value === null || value === undefined) {
|
|
1438
|
+
return value;
|
|
1439
|
+
}
|
|
1440
|
+
if (Array.isArray(value)) {
|
|
1441
|
+
return value.map((item) => redactValue(item));
|
|
1442
|
+
}
|
|
1443
|
+
if (typeof value !== "object") {
|
|
1444
|
+
return value;
|
|
1445
|
+
}
|
|
1446
|
+
const obj = value;
|
|
1447
|
+
const result = {};
|
|
1448
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
1449
|
+
if (SENSITIVE_KEYS.has(k.toLowerCase())) {
|
|
1450
|
+
result[k] = REDACTED_SENTINEL;
|
|
1451
|
+
} else {
|
|
1452
|
+
result[k] = redactValue(v);
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
return result;
|
|
1456
|
+
}
|
|
1457
|
+
var REDACTED_SENTINEL = "[REDACTED]", SENSITIVE_KEYS;
|
|
1458
|
+
var init_sensitive_redact = __esm(() => {
|
|
1459
|
+
SENSITIVE_KEYS = new Set([
|
|
1460
|
+
"password",
|
|
1461
|
+
"ldap_password",
|
|
1462
|
+
"apikey",
|
|
1463
|
+
"api_key",
|
|
1464
|
+
"token",
|
|
1465
|
+
"secret",
|
|
1466
|
+
"auth",
|
|
1467
|
+
"access_token",
|
|
1468
|
+
"refresh_token",
|
|
1469
|
+
"authorization",
|
|
1470
|
+
"cookie",
|
|
1471
|
+
"private_key",
|
|
1472
|
+
"session_token",
|
|
1473
|
+
"sid"
|
|
1474
|
+
]);
|
|
1475
|
+
});
|
|
1476
|
+
|
|
1426
1477
|
// src/env/workflow/runtime/runtime-cancellation-scope.ts
|
|
1427
1478
|
var RuntimeCancellationScope;
|
|
1428
1479
|
var init_runtime_cancellation_scope = __esm(() => {
|
|
@@ -1561,6 +1612,7 @@ var init_engine = __esm(() => {
|
|
|
1561
1612
|
init_decorator();
|
|
1562
1613
|
init_template_resolver();
|
|
1563
1614
|
init_workflow_error();
|
|
1615
|
+
init_sensitive_redact();
|
|
1564
1616
|
init_runtime_cancellation_scope();
|
|
1565
1617
|
execFileAsync = promisify(execFileCb);
|
|
1566
1618
|
logger3 = createLogger("workflow:engine");
|
|
@@ -1676,7 +1728,7 @@ var init_engine = __esm(() => {
|
|
|
1676
1728
|
workflowName,
|
|
1677
1729
|
workflowVersion: workflowDef.version,
|
|
1678
1730
|
status: "running",
|
|
1679
|
-
input: options?.input,
|
|
1731
|
+
input: redactSensitiveFields(options?.input),
|
|
1680
1732
|
agentSessions: []
|
|
1681
1733
|
};
|
|
1682
1734
|
await this.sessionComponent.create({
|
|
@@ -1706,14 +1758,16 @@ var init_engine = __esm(() => {
|
|
|
1706
1758
|
const hasNewInput = typeof options.input === "string" ? options.input !== undefined && options.input !== "" : Object.keys(options.input).length > 0;
|
|
1707
1759
|
if (hasNewInput) {
|
|
1708
1760
|
const existingInput = metadata.input || {};
|
|
1709
|
-
const
|
|
1761
|
+
const newInputRaw = typeof options.input === "string" ? { userQuery: options.input } : options.input;
|
|
1762
|
+
const newInput = redactSensitiveFields(newInputRaw);
|
|
1763
|
+
const mergedInput = { ...existingInput, ...newInput };
|
|
1710
1764
|
await this.sessionComponent.update(sessionId, {
|
|
1711
1765
|
metadata: {
|
|
1712
1766
|
...metadata,
|
|
1713
|
-
input:
|
|
1767
|
+
input: mergedInput
|
|
1714
1768
|
}
|
|
1715
1769
|
});
|
|
1716
|
-
metadata.input =
|
|
1770
|
+
metadata.input = mergedInput;
|
|
1717
1771
|
logger3.info(`[WorkflowEngine] Updated session ${sessionId} input with resume user input`);
|
|
1718
1772
|
}
|
|
1719
1773
|
}
|
|
@@ -125,9 +125,10 @@ var init_tool_node = __esm(() => {
|
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
const extractedOutput = this.extractFromWrapper(output);
|
|
128
|
+
const wrapperError = this.extractErrorFromWrapper(output);
|
|
128
129
|
return {
|
|
129
130
|
output: extractedOutput,
|
|
130
|
-
error:
|
|
131
|
+
error: wrapperError,
|
|
131
132
|
durationMs: Date.now() - startTime
|
|
132
133
|
};
|
|
133
134
|
} catch (error) {
|
|
@@ -158,6 +159,37 @@ var init_tool_node = __esm(() => {
|
|
|
158
159
|
}
|
|
159
160
|
return result;
|
|
160
161
|
}
|
|
162
|
+
extractErrorFromWrapper(value) {
|
|
163
|
+
if (value === null || value === undefined) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (typeof value !== "object") {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const obj = value;
|
|
170
|
+
if (obj.success !== false) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const err = obj.error;
|
|
174
|
+
if (typeof err === "string" && err.length > 0) {
|
|
175
|
+
return err;
|
|
176
|
+
}
|
|
177
|
+
if (err instanceof Error) {
|
|
178
|
+
return err;
|
|
179
|
+
}
|
|
180
|
+
const md = obj.metadata;
|
|
181
|
+
if (md) {
|
|
182
|
+
if (md.timed_out === true) {
|
|
183
|
+
const ms = typeof md.execution_time_ms === "number" ? md.execution_time_ms : 0;
|
|
184
|
+
return `Tool execution timed out after ${ms}ms`;
|
|
185
|
+
}
|
|
186
|
+
if (typeof md.exit_code === "number" && md.exit_code !== 0) {
|
|
187
|
+
const stderr = typeof md.stderr === "string" ? md.stderr : "";
|
|
188
|
+
return stderr.length > 0 ? stderr : `Tool exited with code ${md.exit_code}`;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return `Tool execution failed (success=false, no error message)`;
|
|
192
|
+
}
|
|
161
193
|
};
|
|
162
194
|
__legacyDecorateClassTS([
|
|
163
195
|
TracedAs("workflow.tool.execute")
|
|
@@ -18,6 +18,9 @@ import {
|
|
|
18
18
|
createLogger,
|
|
19
19
|
init_logger
|
|
20
20
|
} from "./roy-agent-core-kaq037np.js";
|
|
21
|
+
import {
|
|
22
|
+
__require
|
|
23
|
+
} from "./roy-agent-core-fs0mn2jk.js";
|
|
21
24
|
|
|
22
25
|
// src/env/plugin/event-bus-notification-channel.ts
|
|
23
26
|
init_logger();
|
|
@@ -71,8 +74,35 @@ init_global_hook_manager();
|
|
|
71
74
|
init_logger();
|
|
72
75
|
init_context();
|
|
73
76
|
import { existsSync, readFileSync } from "node:fs";
|
|
74
|
-
import { join } from "node:path";
|
|
77
|
+
import { join, dirname } from "node:path";
|
|
75
78
|
import { homedir } from "node:os";
|
|
79
|
+
function readActualVersion(resolvedPath) {
|
|
80
|
+
let dir = dirname(resolvedPath);
|
|
81
|
+
const root = dirname(dir);
|
|
82
|
+
while (dir !== root) {
|
|
83
|
+
const pkgPath = join(dir, "package.json");
|
|
84
|
+
if (existsSync(pkgPath)) {
|
|
85
|
+
try {
|
|
86
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
87
|
+
return pkg.version ?? null;
|
|
88
|
+
} catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
dir = dirname(dir);
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
function checkVersionDrift(declaredVersion, resolvedPath, logger2) {
|
|
97
|
+
const actual = readActualVersion(resolvedPath);
|
|
98
|
+
const drifted = actual !== null && actual !== declaredVersion;
|
|
99
|
+
if (drifted && logger2) {
|
|
100
|
+
const pkgName = resolvedPath.includes("/node_modules/") ? resolvedPath.split("/node_modules/").pop() ?? resolvedPath : resolvedPath;
|
|
101
|
+
logger2.warn(`⚠️ Plugin '${pkgName}' version mismatch: declared ${declaredVersion} vs loaded ${actual} (path: ${resolvedPath})`);
|
|
102
|
+
}
|
|
103
|
+
return { declared: declaredVersion, actual, resolvedPath, drifted };
|
|
104
|
+
}
|
|
105
|
+
|
|
76
106
|
class PluginComponent extends BaseComponent {
|
|
77
107
|
name = "plugin";
|
|
78
108
|
version = "1.0.0";
|
|
@@ -127,22 +157,29 @@ class PluginComponent extends BaseComponent {
|
|
|
127
157
|
this.logger.info(`[PluginComponent] Loading ${allPlugins.length} installed plugin(s) from all configs`);
|
|
128
158
|
for (const entry of allPlugins) {
|
|
129
159
|
try {
|
|
130
|
-
await this.loadPluginFromPackage(entry.packageName);
|
|
160
|
+
await this.loadPluginFromPackage(entry.packageName, entry.version);
|
|
131
161
|
} catch (err) {
|
|
132
162
|
this.logger.error(`[PluginComponent] Failed to load plugin '${entry.packageName}': ${err}`);
|
|
133
163
|
}
|
|
134
164
|
}
|
|
135
165
|
}
|
|
136
|
-
async loadPluginFromPackage(packageName) {
|
|
166
|
+
async loadPluginFromPackage(packageName, declaredVersion) {
|
|
137
167
|
let pluginModule;
|
|
168
|
+
let resolvedPath = null;
|
|
138
169
|
try {
|
|
139
170
|
pluginModule = await import(packageName);
|
|
171
|
+
try {
|
|
172
|
+
const { createRequire } = await import("node:module");
|
|
173
|
+
const req = createRequire(import.meta.url);
|
|
174
|
+
resolvedPath = req.resolve(packageName);
|
|
175
|
+
} catch {}
|
|
140
176
|
} catch (_err) {
|
|
141
177
|
const projectPluginPath = join(process.cwd(), ".roy", "plugins", packageName);
|
|
142
178
|
if (existsSync(projectPluginPath)) {
|
|
143
179
|
this.logger.debug(`[PluginComponent] Falling back to project plugin path: ${projectPluginPath}`);
|
|
144
180
|
try {
|
|
145
181
|
pluginModule = await import(projectPluginPath);
|
|
182
|
+
resolvedPath = projectPluginPath;
|
|
146
183
|
} catch (err2) {
|
|
147
184
|
this.logger.warn(`[PluginComponent] Could not import plugin '${packageName}' from project path: ${err2}`);
|
|
148
185
|
return;
|
|
@@ -153,6 +190,7 @@ class PluginComponent extends BaseComponent {
|
|
|
153
190
|
this.logger.debug(`[PluginComponent] Falling back to global plugin path: ${globalPluginPath}`);
|
|
154
191
|
try {
|
|
155
192
|
pluginModule = await import(globalPluginPath);
|
|
193
|
+
resolvedPath = globalPluginPath;
|
|
156
194
|
} catch (err3) {
|
|
157
195
|
this.logger.warn(`[PluginComponent] Could not import plugin '${packageName}' from global path: ${err3}`);
|
|
158
196
|
return;
|
|
@@ -163,6 +201,11 @@ class PluginComponent extends BaseComponent {
|
|
|
163
201
|
}
|
|
164
202
|
}
|
|
165
203
|
}
|
|
204
|
+
if (declaredVersion && resolvedPath) {
|
|
205
|
+
checkVersionDrift(declaredVersion, resolvedPath, {
|
|
206
|
+
warn: (msg) => this.logger.warn(`[PluginComponent] ${msg}`)
|
|
207
|
+
});
|
|
208
|
+
}
|
|
166
209
|
const tryCreateInstance = (candidate, exportKind) => {
|
|
167
210
|
if (!candidate)
|
|
168
211
|
return;
|