@fitlab-ai/agent-infra 0.9.7 → 0.9.9
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/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/bin/internal-cli.js +11 -1
- package/dist/lib/agent-clients/adapters/claude-code.js +3 -3
- package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +60 -22
- package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +8 -1
- package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +175 -11
- package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-context.js +147 -0
- package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +14 -0
- package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +86 -69
- package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +2 -1
- package/dist/lib/decide.js +68 -14
- package/dist/lib/git/workflow.js +10 -1
- package/dist/lib/init.js +1 -1
- package/dist/lib/internal/codex-lifecycle.js +19 -5
- package/dist/lib/internal/codex-sandbox-controller.js +6 -13
- package/dist/lib/internal/git-workflow.js +5 -7
- package/dist/lib/internal/platform-pr.js +20 -7
- package/dist/lib/internal/release-workflow.js +3 -4
- package/dist/lib/internal/sandbox-control.js +79 -2
- package/dist/lib/internal/task-activity.js +57 -7
- package/dist/lib/internal/task-event.js +57 -4
- package/dist/lib/internal/task-finalization.js +54 -0
- package/dist/lib/internal/task-ledger.js +59 -5
- package/dist/lib/internal/task-lifecycle.js +59 -8
- package/dist/lib/internal/task-orchestration.js +161 -288
- package/dist/lib/internal/task-override.js +131 -0
- package/dist/lib/internal/task-review.js +64 -6
- package/dist/lib/internal/task-verify.js +65 -3
- package/dist/lib/internal/task-warning.js +57 -4
- package/dist/lib/platform/pr-summary.js +53 -13
- package/dist/lib/platform/pull-requests.js +205 -41
- package/dist/lib/runtime/agent-runtime.js +56 -0
- package/dist/lib/sandbox/commands/create.js +389 -311
- package/dist/lib/sandbox/commands/rm.js +316 -55
- package/dist/lib/sandbox/control/client.js +190 -6
- package/dist/lib/sandbox/control/container-identity.js +1 -1
- package/dist/lib/sandbox/control/controller-registration.js +273 -0
- package/dist/lib/sandbox/control/executor.js +145 -5
- package/dist/lib/sandbox/control/lifecycle.js +395 -73
- package/dist/lib/sandbox/control/protocol.js +67 -6
- package/dist/lib/sandbox/control/state.js +27 -11
- package/dist/lib/sandbox/engine.js +14 -7
- package/dist/lib/sandbox/index.js +5 -3
- package/dist/lib/sandbox/managed-fs.js +5 -0
- package/dist/lib/sandbox/mounts.js +20 -5
- package/dist/lib/sandbox/recovery.js +78 -10
- package/dist/lib/sandbox/task-resolver.js +50 -6
- package/dist/lib/sandbox/workspace-identity.js +27 -0
- package/dist/lib/sandbox/workspace-view.js +62 -40
- package/dist/lib/sandbox/worktree-safety.js +215 -2
- package/dist/lib/server/process-state.js +51 -1
- package/dist/lib/task/activity-intent.js +4 -1
- package/dist/lib/task/codex-orchestration.js +158 -33
- package/dist/lib/task/commands/status.js +59 -1
- package/dist/lib/task/commit-operation.js +335 -0
- package/dist/lib/task/commit-policy.js +18 -0
- package/dist/lib/task/decision-intents.js +4 -2
- package/dist/lib/task/delegation-receipts.js +279 -17
- package/dist/lib/task/events.js +9 -5
- package/dist/lib/task/finalization.js +567 -0
- package/dist/lib/task/guard-override.js +31 -0
- package/dist/lib/task/human-override.js +1240 -0
- package/dist/lib/task/ledger-intents.js +6 -3
- package/dist/lib/task/lifecycle.js +69 -14
- package/dist/lib/task/operation-outcome.js +33 -0
- package/dist/lib/task/orchestration.js +199 -719
- package/dist/lib/task/review-finalization.js +3 -2
- package/dist/lib/task/short-id.js +59 -1
- package/dist/lib/task/task-execution-lock.js +6 -1
- package/dist/lib/task/verification-engine.js +138 -59
- package/dist/lib/task/verification.js +15 -2
- package/dist/lib/task/workflow-warning-intents.js +54 -3
- package/dist/lib/task/write.js +2 -1
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-clients/adapters/claude-code.ts +3 -3
- package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +63 -20
- package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +12 -0
- package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +278 -13
- package/lib/agent-clients/adapters/codex-lifecycle/controller-context.ts +180 -0
- package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +19 -0
- package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +9 -1
- package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +112 -93
- package/lib/agent-clients/adapters/codex-lifecycle/store.ts +2 -1
- package/lib/decide.ts +59 -14
- package/lib/git/workflow.ts +11 -2
- package/lib/init.ts +1 -1
- package/lib/internal/codex-lifecycle.ts +18 -5
- package/lib/internal/codex-sandbox-controller.ts +6 -12
- package/lib/internal/git-workflow.ts +5 -6
- package/lib/internal/platform-pr.ts +14 -7
- package/lib/internal/release-workflow.ts +3 -4
- package/lib/internal/sandbox-control.ts +92 -2
- package/lib/internal/task-activity.ts +46 -6
- package/lib/internal/task-event.ts +53 -4
- package/lib/internal/task-finalization.ts +68 -0
- package/lib/internal/task-ledger.ts +48 -4
- package/lib/internal/task-lifecycle.ts +56 -12
- package/lib/internal/task-orchestration.ts +32 -107
- package/lib/internal/task-override.ts +138 -0
- package/lib/internal/task-review.ts +51 -6
- package/lib/internal/task-verify.ts +52 -3
- package/lib/internal/task-warning.ts +44 -3
- package/lib/platform/pr-summary.ts +65 -14
- package/lib/platform/pull-requests.ts +211 -41
- package/lib/runtime/agent-runtime.ts +76 -0
- package/lib/sandbox/commands/create.ts +88 -4
- package/lib/sandbox/commands/rm.ts +413 -61
- package/lib/sandbox/config.ts +2 -1
- package/lib/sandbox/control/client.ts +255 -6
- package/lib/sandbox/control/container-identity.ts +3 -3
- package/lib/sandbox/control/controller-registration.ts +347 -0
- package/lib/sandbox/control/executor.ts +172 -6
- package/lib/sandbox/control/lifecycle.ts +465 -77
- package/lib/sandbox/control/protocol.ts +85 -9
- package/lib/sandbox/control/state.ts +35 -18
- package/lib/sandbox/engine.ts +20 -9
- package/lib/sandbox/index.ts +5 -3
- package/lib/sandbox/managed-fs.ts +5 -0
- package/lib/sandbox/mounts.ts +23 -5
- package/lib/sandbox/recovery.ts +90 -9
- package/lib/sandbox/task-resolver.ts +58 -7
- package/lib/sandbox/workspace-identity.ts +50 -2
- package/lib/sandbox/workspace-view.ts +73 -43
- package/lib/sandbox/worktree-safety.ts +236 -2
- package/lib/server/process-state.ts +48 -1
- package/lib/task/activity-intent.ts +4 -2
- package/lib/task/codex-orchestration.ts +167 -33
- package/lib/task/commands/status.ts +78 -1
- package/lib/task/commit-operation.ts +430 -0
- package/lib/task/commit-policy.ts +30 -0
- package/lib/task/decision-intents.ts +4 -2
- package/lib/task/delegation-receipts.ts +304 -19
- package/lib/task/events.ts +10 -5
- package/lib/task/finalization.ts +719 -0
- package/lib/task/guard-override.ts +50 -0
- package/lib/task/human-override.ts +1503 -0
- package/lib/task/ledger-intents.ts +6 -3
- package/lib/task/lifecycle.ts +71 -14
- package/lib/task/operation-outcome.ts +48 -0
- package/lib/task/orchestration.ts +239 -922
- package/lib/task/review-finalization.ts +6 -2
- package/lib/task/short-id.ts +65 -1
- package/lib/task/task-execution-lock.ts +10 -1
- package/lib/task/verification-engine.ts +145 -64
- package/lib/task/verification.ts +18 -3
- package/lib/task/workflow-warning-intents.ts +61 -4
- package/lib/task/write.ts +4 -1
- package/package.json +2 -2
- package/templates/.agents/QUICKSTART.en.md +2 -2
- package/templates/.agents/QUICKSTART.zh-CN.md +2 -2
- package/templates/.agents/hooks/lifecycle-delegation.js +9 -24
- package/templates/.agents/rules/lifecycle-orchestration.en.md +4 -3
- package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +4 -3
- package/templates/.agents/rules/task-management.en.md +2 -2
- package/templates/.agents/rules/task-management.zh-CN.md +2 -2
- package/templates/.agents/skills/block-task/SKILL.en.md +2 -4
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -4
- package/templates/.agents/skills/cancel-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/close-codescan/SKILL.en.md +6 -2
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +6 -2
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +6 -2
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +6 -2
- package/templates/.agents/skills/commit/SKILL.en.md +41 -125
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +52 -123
- package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -1
- package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -1
- package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +14 -43
- package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +14 -49
- package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
- package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -35
- package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -35
- package/templates/.agents/skills/complete-task/SKILL.en.md +31 -38
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +31 -38
- package/templates/.agents/skills/complete-task/config/verify.en.json +1 -0
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +1 -1
- package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +1 -1
- package/templates/.agents/skills/create-pr/SKILL.en.md +6 -4
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +6 -4
- package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +2 -2
- package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +2 -2
- package/templates/.agents/skills/run-task/SKILL.en.md +5 -5
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/run-task/reference/host-validation.en.md +3 -1
- package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +3 -1
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +1 -1
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +1 -1
- package/templates/.codex/hooks.json +4 -4
- package/dist/lib/task/commit-finalization.js +0 -305
- package/dist/lib/task/commit-intent.js +0 -165
- package/lib/task/commit-finalization.ts +0 -419
- package/lib/task/commit-intent.ts +0 -230
|
@@ -69,6 +69,17 @@ import {
|
|
|
69
69
|
prepareTmpfsMounts,
|
|
70
70
|
startSandboxControlBroker
|
|
71
71
|
} from '../recovery.ts';
|
|
72
|
+
import {
|
|
73
|
+
acquireSandboxControlReplacement,
|
|
74
|
+
assertSandboxControlCutoverSnapshot,
|
|
75
|
+
beginSandboxControlReplacement,
|
|
76
|
+
captureSandboxControlCutoverSnapshot,
|
|
77
|
+
commitSandboxControlReplacement,
|
|
78
|
+
quiesceSandboxControlRoot,
|
|
79
|
+
recoverSandboxControlReplacement,
|
|
80
|
+
readSandboxControlManifestForTransition
|
|
81
|
+
} from '../control/lifecycle.ts';
|
|
82
|
+
import { inspectSandboxControlContainer } from '../control/container-identity.ts';
|
|
72
83
|
import { hostJoin, toEnginePath, volumeArg } from '../engines/wsl2-paths.ts';
|
|
73
84
|
import { sandboxCoreBindMounts } from '../mounts.ts';
|
|
74
85
|
import {
|
|
@@ -76,7 +87,8 @@ import {
|
|
|
76
87
|
finalizeSandboxControlManifest,
|
|
77
88
|
materializeSandboxControl,
|
|
78
89
|
materializeSandboxWorkspaceView,
|
|
79
|
-
|
|
90
|
+
prepareSandboxWorkspaceMountTargets,
|
|
91
|
+
sandboxControlPaths,
|
|
80
92
|
} from '../workspace-view.ts';
|
|
81
93
|
import { clipboardHostDir, CONTAINER_CLIPBOARD_MOUNT } from '../clipboard/paths.ts';
|
|
82
94
|
import { validateSelinuxDisableEnv } from '../engines/selinux.ts';
|
|
@@ -1036,6 +1048,12 @@ export async function create(args: string[]): Promise<void> {
|
|
|
1036
1048
|
}
|
|
1037
1049
|
const effectiveResolvedTools = resolvedTools;
|
|
1038
1050
|
const container = containerName(effectiveConfig, branch);
|
|
1051
|
+
const controlPaths = sandboxControlPaths({
|
|
1052
|
+
base: effectiveConfig.controlBase,
|
|
1053
|
+
project: effectiveConfig.project,
|
|
1054
|
+
container,
|
|
1055
|
+
identity: target.workspace
|
|
1056
|
+
});
|
|
1039
1057
|
const worktree = worktreeCandidates.find((candidate) => fs.existsSync(candidate)) ?? worktreeCandidates[0] ?? '';
|
|
1040
1058
|
const shareCommon = shareCommonDir(effectiveConfig);
|
|
1041
1059
|
const shareBranch = shareBranchDir(effectiveConfig, branch);
|
|
@@ -1224,6 +1242,22 @@ export async function create(args: string[]): Promise<void> {
|
|
|
1224
1242
|
{
|
|
1225
1243
|
title: `Starting container '${container}'`,
|
|
1226
1244
|
task: async (message: (text: string) => void) => {
|
|
1245
|
+
const hadControlRootBeforeAcquire = fs.existsSync(controlPaths.root);
|
|
1246
|
+
const replacementLease = acquireSandboxControlReplacement(controlPaths.root);
|
|
1247
|
+
let replacementLeaseHeld = true;
|
|
1248
|
+
let replacementCutover: ReturnType<typeof beginSandboxControlReplacement> | null = null;
|
|
1249
|
+
try {
|
|
1250
|
+
const recoveryResult = await recoverSandboxControlReplacement(controlPaths.root, replacementLease);
|
|
1251
|
+
const hadExistingControlRoot = hadControlRootBeforeAcquire || recoveryResult === 'restored';
|
|
1252
|
+
const previousManifest = fs.existsSync(controlPaths.manifestPath)
|
|
1253
|
+
? readSandboxControlManifestForTransition(controlPaths.manifestPath)
|
|
1254
|
+
: null;
|
|
1255
|
+
if (hadExistingControlRoot) {
|
|
1256
|
+
await quiesceSandboxControlRoot(controlPaths.root);
|
|
1257
|
+
}
|
|
1258
|
+
const previousCutoverSnapshot = hadExistingControlRoot
|
|
1259
|
+
? captureSandboxControlCutoverSnapshot(controlPaths.root)
|
|
1260
|
+
: null;
|
|
1227
1261
|
const existing = runSafeEngine(engine, 'docker', ['ps', '-a', '--format', '{{.Names}}']).split('\n').filter(Boolean);
|
|
1228
1262
|
const matchedContainers = containerNameCandidates(effectiveConfig, branch)
|
|
1229
1263
|
.filter((name) => existing.includes(name));
|
|
@@ -1266,6 +1300,14 @@ export async function create(args: string[]): Promise<void> {
|
|
|
1266
1300
|
runSafeEngine(engine, 'docker', ['rm', name]);
|
|
1267
1301
|
}
|
|
1268
1302
|
}
|
|
1303
|
+
if (previousManifest) {
|
|
1304
|
+
const oldContainer = await inspectSandboxControlContainer(previousManifest);
|
|
1305
|
+
if (oldContainer.state !== 'absent') {
|
|
1306
|
+
throw new Error(oldContainer.state === 'unknown'
|
|
1307
|
+
? `SANDBOX_CONTROL_CONTAINER_UNKNOWN: ${oldContainer.reason}`
|
|
1308
|
+
: 'SANDBOX_CONTROL_CONTAINER_STILL_EXISTS');
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1269
1311
|
|
|
1270
1312
|
const aliasesFile = ensureSandboxAliasesFile(
|
|
1271
1313
|
effectiveConfig.home,
|
|
@@ -1342,7 +1384,19 @@ export async function create(args: string[]): Promise<void> {
|
|
|
1342
1384
|
container,
|
|
1343
1385
|
identity: target.workspace
|
|
1344
1386
|
});
|
|
1345
|
-
|
|
1387
|
+
prepareSandboxWorkspaceMountTargets(worktree);
|
|
1388
|
+
if (previousCutoverSnapshot) {
|
|
1389
|
+
assertSandboxControlCutoverSnapshot(previousCutoverSnapshot);
|
|
1390
|
+
if (previousManifest) {
|
|
1391
|
+
const finalOldContainer = await inspectSandboxControlContainer(previousManifest);
|
|
1392
|
+
if (finalOldContainer.state !== 'absent') {
|
|
1393
|
+
throw new Error(finalOldContainer.state === 'unknown'
|
|
1394
|
+
? `SANDBOX_CONTROL_CONTAINER_UNKNOWN: ${finalOldContainer.reason}`
|
|
1395
|
+
: 'SANDBOX_CONTROL_CONTAINER_REAPPEARED');
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
replacementCutover = beginSandboxControlReplacement(controlPaths.root, replacementLease);
|
|
1399
|
+
}
|
|
1346
1400
|
const control = materializeSandboxControl({
|
|
1347
1401
|
base: effectiveConfig.controlBase,
|
|
1348
1402
|
repoRoot: effectiveConfig.repoRoot,
|
|
@@ -1351,7 +1405,8 @@ export async function create(args: string[]): Promise<void> {
|
|
|
1351
1405
|
container,
|
|
1352
1406
|
branch,
|
|
1353
1407
|
identity: target.workspace,
|
|
1354
|
-
engine
|
|
1408
|
+
engine,
|
|
1409
|
+
replacementLease
|
|
1355
1410
|
});
|
|
1356
1411
|
hostShellConfig = prepareHostShellConfig({
|
|
1357
1412
|
home: effectiveConfig.home,
|
|
@@ -1365,6 +1420,7 @@ export async function create(args: string[]): Promise<void> {
|
|
|
1365
1420
|
workspaceViewRoot: workspaceView.root,
|
|
1366
1421
|
controlDir: control.channelDir,
|
|
1367
1422
|
controlStatusDir: control.statusDir,
|
|
1423
|
+
...(target.workspace.mode === 'task-bound' ? { runtimeDir: control.runtimeDir } : {}),
|
|
1368
1424
|
...(target.workspace.mode === 'task-bound'
|
|
1369
1425
|
? {
|
|
1370
1426
|
taskSource: assertSandboxTaskSource(
|
|
@@ -1456,6 +1512,9 @@ export async function create(args: string[]): Promise<void> {
|
|
|
1456
1512
|
'AGENT_INFRA_CONTROL_DIR=/run/agent-infra/control',
|
|
1457
1513
|
'-e',
|
|
1458
1514
|
'AGENT_INFRA_CONTROL_STATUS_DIR=/run/agent-infra/control-status',
|
|
1515
|
+
...(target.workspace.mode === 'task-bound'
|
|
1516
|
+
? ['-e', 'AGENT_INFRA_RUNTIME_DIR=/run/agent-infra/runtime']
|
|
1517
|
+
: []),
|
|
1459
1518
|
'--label',
|
|
1460
1519
|
`${sandboxRuntimeCapabilityLabel(effectiveConfig)}=${capabilityPlan.runtimeSignature}`,
|
|
1461
1520
|
...coreVolumes,
|
|
@@ -1512,14 +1571,27 @@ export async function create(args: string[]): Promise<void> {
|
|
|
1512
1571
|
id: containerId,
|
|
1513
1572
|
labels: expectedLabels
|
|
1514
1573
|
});
|
|
1574
|
+
replacementLease.clearQuiescing();
|
|
1515
1575
|
await startSandboxControlBroker(effectiveConfig.repoRoot, control.manifestPath);
|
|
1576
|
+
if (replacementCutover) {
|
|
1577
|
+
commitSandboxControlReplacement(control.root, replacementLease);
|
|
1578
|
+
replacementCutover = null;
|
|
1579
|
+
}
|
|
1516
1580
|
createdTmpfsSeedPlan = tmpfsSeedPlan;
|
|
1517
1581
|
} catch (error) {
|
|
1518
1582
|
if (createdContainerRef) {
|
|
1519
1583
|
runSafeEngine(engine, 'docker', ['stop', createdContainerRef]);
|
|
1520
1584
|
runSafeEngine(engine, 'docker', ['rm', createdContainerRef]);
|
|
1521
1585
|
}
|
|
1522
|
-
removeDirRecursive(control.root);
|
|
1586
|
+
if (!hadExistingControlRoot) removeDirRecursive(control.root);
|
|
1587
|
+
if (replacementCutover) {
|
|
1588
|
+
try {
|
|
1589
|
+
await recoverSandboxControlReplacement(control.root, replacementLease);
|
|
1590
|
+
replacementCutover = null;
|
|
1591
|
+
} catch {
|
|
1592
|
+
// Preserve the cutover state for the next explicit recreate to recover.
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1523
1595
|
removeDirRecursive(workspaceView.root);
|
|
1524
1596
|
throw error;
|
|
1525
1597
|
}
|
|
@@ -1615,7 +1687,19 @@ export async function create(args: string[]): Promise<void> {
|
|
|
1615
1687
|
);
|
|
1616
1688
|
}
|
|
1617
1689
|
|
|
1690
|
+
replacementLease.release();
|
|
1691
|
+
replacementLeaseHeld = false;
|
|
1618
1692
|
return 'Container started';
|
|
1693
|
+
} catch (error) {
|
|
1694
|
+
if (replacementLeaseHeld) {
|
|
1695
|
+
try {
|
|
1696
|
+
replacementLease.release();
|
|
1697
|
+
} catch {
|
|
1698
|
+
// Preserve the original cutover failure and its evidence.
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
throw error;
|
|
1702
|
+
}
|
|
1619
1703
|
}
|
|
1620
1704
|
}
|
|
1621
1705
|
]);
|