mcoda 0.1.8 → 0.1.11
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/CHANGELOG.md +3 -0
- package/README.md +10 -3
- package/dist/bin/McodaEntrypoint.d.ts.map +1 -1
- package/dist/bin/McodaEntrypoint.js +51 -4
- package/dist/commands/agents/AgentRunCommand.d.ts +4 -0
- package/dist/commands/agents/AgentRunCommand.d.ts.map +1 -0
- package/dist/commands/agents/AgentRunCommand.js +140 -0
- package/dist/commands/agents/AgentsCommands.d.ts.map +1 -1
- package/dist/commands/agents/AgentsCommands.js +259 -6
- package/dist/commands/agents/GatewayAgentCommand.d.ts.map +1 -1
- package/dist/commands/agents/GatewayAgentCommand.js +24 -86
- package/dist/commands/agents/TestAgentCommand.d.ts.map +1 -1
- package/dist/commands/agents/TestAgentCommand.js +3 -0
- package/dist/commands/backlog/BacklogCommands.d.ts +5 -0
- package/dist/commands/backlog/BacklogCommands.d.ts.map +1 -1
- package/dist/commands/backlog/BacklogCommands.js +155 -34
- package/dist/commands/backlog/OrderTasksCommand.d.ts +4 -1
- package/dist/commands/backlog/OrderTasksCommand.d.ts.map +1 -1
- package/dist/commands/backlog/OrderTasksCommand.js +89 -31
- package/dist/commands/docs/DocsCommands.d.ts +18 -0
- package/dist/commands/docs/DocsCommands.d.ts.map +1 -1
- package/dist/commands/docs/DocsCommands.js +302 -4
- package/dist/commands/estimate/EstimateCommands.d.ts +1 -0
- package/dist/commands/estimate/EstimateCommands.d.ts.map +1 -1
- package/dist/commands/estimate/EstimateCommands.js +85 -7
- package/dist/commands/jobs/JobsCommands.d.ts +4 -0
- package/dist/commands/jobs/JobsCommands.d.ts.map +1 -1
- package/dist/commands/jobs/JobsCommands.js +117 -16
- package/dist/commands/openapi/OpenapiCommands.d.ts +2 -0
- package/dist/commands/openapi/OpenapiCommands.d.ts.map +1 -1
- package/dist/commands/openapi/OpenapiCommands.js +59 -6
- package/dist/commands/planning/CreateTasksCommand.d.ts +19 -0
- package/dist/commands/planning/CreateTasksCommand.d.ts.map +1 -1
- package/dist/commands/planning/CreateTasksCommand.js +174 -3
- package/dist/commands/planning/MigrateTasksCommand.js +1 -1
- package/dist/commands/planning/QaTasksCommand.d.ts +5 -1
- package/dist/commands/planning/QaTasksCommand.d.ts.map +1 -1
- package/dist/commands/planning/QaTasksCommand.js +57 -4
- package/dist/commands/planning/RefineTasksCommand.d.ts +1 -0
- package/dist/commands/planning/RefineTasksCommand.d.ts.map +1 -1
- package/dist/commands/planning/RefineTasksCommand.js +26 -2
- package/dist/commands/review/CodeReviewCommand.d.ts +2 -0
- package/dist/commands/review/CodeReviewCommand.d.ts.map +1 -1
- package/dist/commands/review/CodeReviewCommand.js +49 -6
- package/dist/commands/routing/RoutingCommands.d.ts.map +1 -1
- package/dist/commands/routing/RoutingCommands.js +48 -6
- package/dist/commands/telemetry/TelemetryCommands.d.ts +2 -0
- package/dist/commands/telemetry/TelemetryCommands.d.ts.map +1 -1
- package/dist/commands/telemetry/TelemetryCommands.js +3 -3
- package/dist/commands/work/GatewayTrioCommand.d.ts +46 -0
- package/dist/commands/work/GatewayTrioCommand.d.ts.map +1 -0
- package/dist/commands/work/GatewayTrioCommand.js +1180 -0
- package/dist/commands/work/WorkOnTasksCommand.d.ts +6 -0
- package/dist/commands/work/WorkOnTasksCommand.d.ts.map +1 -1
- package/dist/commands/work/WorkOnTasksCommand.js +173 -12
- package/dist/commands/workspace/SetWorkspaceCommand.d.ts +64 -0
- package/dist/commands/workspace/SetWorkspaceCommand.d.ts.map +1 -1
- package/dist/commands/workspace/SetWorkspaceCommand.js +1415 -16
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -13,10 +13,16 @@ mcoda set-workspace --workspace-root .
|
|
|
13
13
|
mcoda docs pdr generate --workspace-root . --project WEB --rfp-path docs/rfp/web.md --agent codex
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
## Docdex & QA
|
|
17
|
+
- mcoda depends on the `docdex` CLI for doc search and context stitching.
|
|
18
|
+
- Run `docdex setup` (or `docdexd browser install`) to install the headless Chromium browser used for web enrichment.
|
|
19
|
+
- Docdex stores state under `~/.docdex`; mcoda does not create repo-local `.docdex` folders.
|
|
20
|
+
- If `~/.docdex/agents.md` exists, it is prepended to every agent run.
|
|
21
|
+
|
|
16
22
|
## Workspace layout
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
23
|
+
- `~/.mcoda/workspaces/<fingerprint>/config.json` for defaults (docdex URL, branch metadata, telemetry preferences).
|
|
24
|
+
- `~/.mcoda/workspaces/<fingerprint>/mcoda.db` for backlog, jobs, and telemetry.
|
|
25
|
+
- `~/.mcoda/workspaces/<fingerprint>/docs/` for generated artifacts.
|
|
20
26
|
|
|
21
27
|
## Common commands
|
|
22
28
|
- Docs: `mcoda docs pdr generate`, `mcoda docs sds generate`
|
|
@@ -25,6 +31,7 @@ mcoda docs pdr generate --workspace-root . --project WEB --rfp-path docs/rfp/web
|
|
|
25
31
|
- Execution: `mcoda work-on-tasks`, `mcoda code-review`, `mcoda qa-tasks`
|
|
26
32
|
- Backlog: `mcoda backlog`, `mcoda task`
|
|
27
33
|
- Jobs/telemetry: `mcoda jobs`, `mcoda tokens`, `mcoda telemetry`
|
|
34
|
+
- Agents: `mcoda test-agent`, `mcoda agent-run`
|
|
28
35
|
- Updates: `mcoda update --check`
|
|
29
36
|
|
|
30
37
|
## Configuration
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McodaEntrypoint.d.ts","sourceRoot":"","sources":["../../src/bin/McodaEntrypoint.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"McodaEntrypoint.d.ts","sourceRoot":"","sources":["../../src/bin/McodaEntrypoint.ts"],"names":[],"mappings":";AA2BA,qBAAa,eAAe;WACb,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;CAkLxE"}
|
|
@@ -15,23 +15,62 @@ import { OrderTasksCommand } from "../commands/backlog/OrderTasksCommand.js";
|
|
|
15
15
|
import { EstimateCommands } from "../commands/estimate/EstimateCommands.js";
|
|
16
16
|
import { TelemetryCommands } from "../commands/telemetry/TelemetryCommands.js";
|
|
17
17
|
import { WorkOnTasksCommand } from "../commands/work/WorkOnTasksCommand.js";
|
|
18
|
+
import { GatewayTrioCommand } from "../commands/work/GatewayTrioCommand.js";
|
|
18
19
|
import { CodeReviewCommand } from "../commands/review/CodeReviewCommand.js";
|
|
19
20
|
import { QaTasksCommand } from "../commands/planning/QaTasksCommand.js";
|
|
20
21
|
import { MigrateTasksCommand } from "../commands/planning/MigrateTasksCommand.js";
|
|
21
22
|
import { UpdateCommands } from "../commands/update/UpdateCommands.js";
|
|
22
23
|
import { RoutingCommands } from "../commands/routing/RoutingCommands.js";
|
|
23
24
|
import { TestAgentCommand } from "../commands/agents/TestAgentCommand.js";
|
|
25
|
+
import { AgentRunCommand } from "../commands/agents/AgentRunCommand.js";
|
|
24
26
|
import { SetWorkspaceCommand } from "../commands/workspace/SetWorkspaceCommand.js";
|
|
25
27
|
export class McodaEntrypoint {
|
|
26
28
|
static async run(argv = process.argv.slice(2)) {
|
|
27
|
-
const
|
|
29
|
+
const applyCodexNoSandboxFlag = (value) => {
|
|
30
|
+
if (value === undefined || value === "") {
|
|
31
|
+
process.env.MCODA_CODEX_NO_SANDBOX = "1";
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const normalized = value.trim().toLowerCase();
|
|
35
|
+
if (["0", "false", "off", "no"].includes(normalized)) {
|
|
36
|
+
process.env.MCODA_CODEX_NO_SANDBOX = "0";
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
process.env.MCODA_CODEX_NO_SANDBOX = "1";
|
|
40
|
+
};
|
|
41
|
+
const filteredArgs = [];
|
|
42
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
43
|
+
const arg = argv[i];
|
|
44
|
+
if (arg === "--codex-no-sandbox") {
|
|
45
|
+
const next = argv[i + 1];
|
|
46
|
+
if (next && !next.startsWith("--")) {
|
|
47
|
+
applyCodexNoSandboxFlag(next);
|
|
48
|
+
i += 1;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
applyCodexNoSandboxFlag(undefined);
|
|
52
|
+
}
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (arg.startsWith("--codex-no-sandbox=")) {
|
|
56
|
+
const [, raw] = arg.split("=", 2);
|
|
57
|
+
applyCodexNoSandboxFlag(raw);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
filteredArgs.push(arg);
|
|
61
|
+
}
|
|
62
|
+
const [command, ...rest] = filteredArgs;
|
|
28
63
|
const wantsJson = argv.some((arg) => arg === "--json" || arg.startsWith("--json="));
|
|
29
64
|
const wantsQuiet = argv.some((arg) => arg === "--quiet" || arg.startsWith("--quiet="));
|
|
30
65
|
if (wantsJson || wantsQuiet) {
|
|
31
66
|
process.env.MCODA_STREAM_IO = "0";
|
|
67
|
+
process.env.MCODA_STREAM_IO_PROMPT = "0";
|
|
32
68
|
}
|
|
33
69
|
else if (process.env.MCODA_STREAM_IO === undefined) {
|
|
34
|
-
process.env.MCODA_STREAM_IO = "
|
|
70
|
+
process.env.MCODA_STREAM_IO = "0";
|
|
71
|
+
if (process.env.MCODA_STREAM_IO_PROMPT === undefined) {
|
|
72
|
+
process.env.MCODA_STREAM_IO_PROMPT = "0";
|
|
73
|
+
}
|
|
35
74
|
}
|
|
36
75
|
if (command === "--version" || command === "-v" || command === "version") {
|
|
37
76
|
// Keep this simple so `mcoda --version` works even in thin installs.
|
|
@@ -40,7 +79,7 @@ export class McodaEntrypoint {
|
|
|
40
79
|
return;
|
|
41
80
|
}
|
|
42
81
|
if (!command) {
|
|
43
|
-
throw new Error("Usage: mcoda <agent|gateway-agent|routing|docs|openapi|job|jobs|tokens|telemetry|create-tasks|migrate-tasks|refine-tasks|order-tasks|tasks|work-on-tasks|code-review|qa-tasks|backlog|task|task-detail|estimate|update|set-workspace|pdr|sds> [...args]\n" +
|
|
82
|
+
throw new Error("Usage: mcoda <agent|gateway-agent|test-agent|agent-run|routing|docs|openapi|job|jobs|tokens|telemetry|create-tasks|migrate-tasks|refine-tasks|order-tasks|tasks|work-on-tasks|gateway-trio|code-review|qa-tasks|backlog|task|task-detail|estimate|update|set-workspace|pdr|sds> [...args]\n" +
|
|
44
83
|
"Routing: use `mcoda routing defaults` to view/update workspace/global defaults, `mcoda routing preview|explain` to inspect agent selection/provenance (override → workspace_default → global_default).\n" +
|
|
45
84
|
"Aliases: `tasks order-by-deps` forwards to `order-tasks` (dependency-aware ordering), `task`/`task-detail` show a single task.\n" +
|
|
46
85
|
"Job commands (mcoda job --help for details): list|status|watch|logs|inspect|resume|cancel|tokens\n" +
|
|
@@ -58,6 +97,10 @@ export class McodaEntrypoint {
|
|
|
58
97
|
await TestAgentCommand.run(rest);
|
|
59
98
|
return;
|
|
60
99
|
}
|
|
100
|
+
if (command === "agent-run") {
|
|
101
|
+
await AgentRunCommand.run(rest);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
61
104
|
if (command === "routing") {
|
|
62
105
|
await RoutingCommands.run(rest);
|
|
63
106
|
return;
|
|
@@ -105,7 +148,7 @@ export class McodaEntrypoint {
|
|
|
105
148
|
if (command === "qa-tasks") {
|
|
106
149
|
if (rest.includes("--help") || rest.includes("-h")) {
|
|
107
150
|
// eslint-disable-next-line no-console
|
|
108
|
-
console.log("Usage: mcoda qa-tasks [--workspace-root <path>] --project <PROJECT_KEY> [--task <TASK_KEY> ... | --epic <EPIC_KEY> | --story <STORY_KEY>] [--status <STATUS_FILTER>] [--mode auto|manual] [--profile <PROFILE_NAME>] [--level unit|integration|acceptance] [--test-command \"<CMD>\"] [--agent <NAME>] [--agent-stream true|false] [--resume <JOB_ID>] [--create-followup-tasks auto|none|prompt] [--result pass|fail
|
|
151
|
+
console.log("Usage: mcoda qa-tasks [--workspace-root <path>] --project <PROJECT_KEY> [--task <TASK_KEY> ... | --epic <EPIC_KEY> | --story <STORY_KEY>] [--status <STATUS_FILTER>] [--limit N] [--mode auto|manual] [--profile <PROFILE_NAME>] [--level unit|integration|acceptance] [--test-command \"<CMD>\"] [--agent <NAME>] [--agent-stream true|false] [--resume <JOB_ID>] [--create-followup-tasks auto|none|prompt] [--result pass|fail] [--notes \"<text>\"] [--evidence-url \"<url>\"] [--dry-run] [--json]");
|
|
109
152
|
return;
|
|
110
153
|
}
|
|
111
154
|
await QaTasksCommand.run(rest);
|
|
@@ -126,6 +169,10 @@ export class McodaEntrypoint {
|
|
|
126
169
|
await WorkOnTasksCommand.run(rest);
|
|
127
170
|
return;
|
|
128
171
|
}
|
|
172
|
+
if (command === "gateway-trio") {
|
|
173
|
+
await GatewayTrioCommand.run(rest);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
129
176
|
if (command === "code-review") {
|
|
130
177
|
await CodeReviewCommand.run(rest);
|
|
131
178
|
return;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentRunCommand.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/AgentRunCommand.ts"],"names":[],"mappings":"AAyDA,qBAAa,eAAe;WACb,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAsFhD"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import { AgentsApi } from "@mcoda/core";
|
|
3
|
+
const USAGE = "Usage: mcoda agent-run <NAME> [--prompt \"<text>\"] [--prompt-file <PATH>] [--task-file <PATH>] [--stdin] [--json]";
|
|
4
|
+
const parseArgs = (argv) => {
|
|
5
|
+
const flags = {};
|
|
6
|
+
const positionals = [];
|
|
7
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
8
|
+
const arg = argv[i];
|
|
9
|
+
if (arg.startsWith("--")) {
|
|
10
|
+
const key = arg.replace(/^--/, "");
|
|
11
|
+
const next = argv[i + 1];
|
|
12
|
+
if (next && !next.startsWith("--")) {
|
|
13
|
+
const existing = flags[key];
|
|
14
|
+
if (Array.isArray(existing)) {
|
|
15
|
+
flags[key] = [...existing, next];
|
|
16
|
+
}
|
|
17
|
+
else if (typeof existing === "string") {
|
|
18
|
+
flags[key] = [existing, next];
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
flags[key] = next;
|
|
22
|
+
}
|
|
23
|
+
i += 1;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
flags[key] = true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
positionals.push(arg);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return { flags, positionals };
|
|
34
|
+
};
|
|
35
|
+
const readTaskFile = async (filePath) => {
|
|
36
|
+
const raw = await fs.readFile(filePath, "utf8");
|
|
37
|
+
return raw
|
|
38
|
+
.split(/\r?\n/)
|
|
39
|
+
.map((line) => line.trim())
|
|
40
|
+
.filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
41
|
+
};
|
|
42
|
+
const toArray = (value) => {
|
|
43
|
+
if (!value || typeof value === "boolean")
|
|
44
|
+
return [];
|
|
45
|
+
return Array.isArray(value) ? value : [value];
|
|
46
|
+
};
|
|
47
|
+
const readStdinIfProvided = async () => {
|
|
48
|
+
if (process.stdin.isTTY)
|
|
49
|
+
return undefined;
|
|
50
|
+
const chunks = [];
|
|
51
|
+
for await (const chunk of process.stdin) {
|
|
52
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
53
|
+
}
|
|
54
|
+
const input = Buffer.concat(chunks).toString("utf8").trim();
|
|
55
|
+
return input.length ? input : undefined;
|
|
56
|
+
};
|
|
57
|
+
export class AgentRunCommand {
|
|
58
|
+
static async run(argv) {
|
|
59
|
+
const parsed = parseArgs(argv);
|
|
60
|
+
const name = parsed.positionals[0];
|
|
61
|
+
if (!name || parsed.flags.help) {
|
|
62
|
+
throw new Error(USAGE);
|
|
63
|
+
}
|
|
64
|
+
if (parsed.flags.prompt === true) {
|
|
65
|
+
throw new Error("agent-run: missing value for --prompt");
|
|
66
|
+
}
|
|
67
|
+
if (parsed.flags["prompt-file"] === true) {
|
|
68
|
+
throw new Error("agent-run: missing value for --prompt-file");
|
|
69
|
+
}
|
|
70
|
+
if (parsed.flags["task-file"] === true) {
|
|
71
|
+
throw new Error("agent-run: missing value for --task-file");
|
|
72
|
+
}
|
|
73
|
+
const prompts = [];
|
|
74
|
+
const inlinePrompts = toArray(parsed.flags.prompt);
|
|
75
|
+
for (const prompt of inlinePrompts) {
|
|
76
|
+
const trimmed = prompt.trim();
|
|
77
|
+
if (trimmed)
|
|
78
|
+
prompts.push(trimmed);
|
|
79
|
+
}
|
|
80
|
+
const promptFiles = toArray(parsed.flags["prompt-file"]);
|
|
81
|
+
for (const filePath of promptFiles) {
|
|
82
|
+
const content = await fs.readFile(String(filePath), "utf8");
|
|
83
|
+
const trimmed = content.trim();
|
|
84
|
+
if (trimmed)
|
|
85
|
+
prompts.push(trimmed);
|
|
86
|
+
}
|
|
87
|
+
const taskFiles = toArray(parsed.flags["task-file"]);
|
|
88
|
+
for (const filePath of taskFiles) {
|
|
89
|
+
const entries = await readTaskFile(String(filePath));
|
|
90
|
+
for (const entry of entries) {
|
|
91
|
+
if (entry)
|
|
92
|
+
prompts.push(entry);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (parsed.flags.stdin) {
|
|
96
|
+
const stdinPrompt = await readStdinIfProvided();
|
|
97
|
+
if (stdinPrompt)
|
|
98
|
+
prompts.push(stdinPrompt);
|
|
99
|
+
}
|
|
100
|
+
else if (prompts.length === 0) {
|
|
101
|
+
const stdinPrompt = await readStdinIfProvided();
|
|
102
|
+
if (stdinPrompt)
|
|
103
|
+
prompts.push(stdinPrompt);
|
|
104
|
+
}
|
|
105
|
+
if (prompts.length === 0) {
|
|
106
|
+
throw new Error("agent-run: at least one prompt is required via --prompt, --prompt-file, --task-file, or stdin");
|
|
107
|
+
}
|
|
108
|
+
const api = await AgentsApi.create();
|
|
109
|
+
try {
|
|
110
|
+
const result = await api.runAgent(name, prompts);
|
|
111
|
+
if (parsed.flags.json) {
|
|
112
|
+
// eslint-disable-next-line no-console
|
|
113
|
+
console.log(JSON.stringify({
|
|
114
|
+
agent: result.agent,
|
|
115
|
+
responses: result.responses.map((response, index) => ({
|
|
116
|
+
prompt: result.prompts[index],
|
|
117
|
+
output: response.output,
|
|
118
|
+
adapter: response.adapter,
|
|
119
|
+
model: response.model,
|
|
120
|
+
metadata: response.metadata,
|
|
121
|
+
})),
|
|
122
|
+
}, null, 2));
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
// eslint-disable-next-line no-console
|
|
126
|
+
console.log(`Agent ${result.agent.slug} responded to ${result.responses.length} prompt(s).`);
|
|
127
|
+
result.responses.forEach((response, index) => {
|
|
128
|
+
const label = `${response.adapter}${response.model ? `:${response.model}` : ""}`;
|
|
129
|
+
// eslint-disable-next-line no-console
|
|
130
|
+
console.log(`\n--- Prompt ${index + 1} ---\n${result.prompts[index]}`);
|
|
131
|
+
// eslint-disable-next-line no-console
|
|
132
|
+
console.log(`--- Response ${index + 1} (${label}) ---\n${response.output}`);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
await api.close();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentsCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/AgentsCommands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AgentsCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/AgentsCommands.ts"],"names":[],"mappings":"AA2TA,qBAAa,cAAc;WACZ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAuThD"}
|