factory-ai 1.3.0 → 1.5.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/CHANGELOG.md +24 -4
- package/Dockerfile.worker +1 -1
- package/README.md +10 -2
- package/ROADMAP.md +0 -1
- package/bin/factory +130 -3
- package/bootstrap/agent-factory-worker.service +3 -3
- package/bootstrap/auto-update.sh +20 -12
- package/bootstrap/deploy-runtime.sh +7 -3
- package/bootstrap/factory-ai-container-firewall.service +14 -0
- package/bootstrap/factory-ai-ollama.service +16 -0
- package/bootstrap/factory-ai-qdrant.service +16 -0
- package/bootstrap/factory-ai-snapshot.service +1 -0
- package/bootstrap/factory-ai-watchdog.service +21 -0
- package/bootstrap/factory-ai-watchdog.timer +11 -0
- package/bootstrap/setup.sh +33 -8
- package/cmd/factory-ui/main.go +455 -0
- package/go.mod +39 -0
- package/go.sum +82 -0
- package/package.json +7 -3
- package/scripts/test.js +7 -0
- package/src/acp-adapter.js +26 -0
- package/src/acp-cli.js +16 -0
- package/src/activity.js +96 -0
- package/src/agent-executor.js +47 -3
- package/src/agent-runner.js +34 -12
- package/src/approval-policy.js +12 -0
- package/src/azure-harness.js +47 -14
- package/src/bedrock-harness.js +45 -14
- package/src/config.js +13 -0
- package/src/container-runner.js +65 -12
- package/src/context-compaction.js +16 -0
- package/src/control-plane.js +77 -16
- package/src/control-service.js +6 -1
- package/src/dashboard.js +25 -6
- package/src/extension-cli.js +11 -0
- package/src/extension-manifest.js +76 -0
- package/src/hooks.js +62 -0
- package/src/instructions.js +45 -0
- package/src/mcp-tools.js +19 -3
- package/src/objective-status.js +16 -0
- package/src/operator-logs.js +24 -0
- package/src/operator.js +34 -10
- package/src/process.js +3 -3
- package/src/release-gate.js +1 -0
- package/src/release-service.js +4 -1
- package/src/release.js +1 -1
- package/src/repo-map.js +128 -0
- package/src/reporter.js +12 -1
- package/src/retriever.js +154 -0
- package/src/routing.js +11 -1
- package/src/scanner-suite.js +4 -3
- package/src/setup-menu.js +3 -1
- package/src/snapshot.js +16 -0
- package/src/task-entry.js +28 -6
- package/src/task-graph.js +0 -5
- package/src/telegram-service.js +10 -4
- package/src/telegram.js +7 -3
- package/src/telemetry.js +173 -0
- package/src/tui.js +31 -10
- package/src/validation.js +41 -9
- package/src/watchdog.js +62 -0
- package/src/worker.js +34 -3
- package/src/workspace-tools.js +13 -3
- package/src/workspace.js +22 -2
- package/templates/AGENTS.md +15 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,12 +4,32 @@ All notable changes follow semantic versioning and the Keep a Changelog structur
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.5.0] - 2026-07-13
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Cross-platform Bubble Tea/Lip Gloss operator client with direct Azure Blob snapshots, verified release binaries, scrolling, and safe Node action fallback.
|
|
12
|
+
- Automatic Azure and Bedrock context compaction with immutable objective retention and recent tool evidence.
|
|
13
|
+
- Hierarchical `AGENTS.md` discovery, preconfigured project instructions, and bounded `.agent-factory` context.
|
|
14
|
+
- Durable worktree crash recovery, parallel read-only tool batches, live activity timelines, retry/error telemetry, and stale-agent watchdog recovery.
|
|
15
|
+
- Post-setup `factory models show|set|reset` and `factory configure models` workflows with validated routes, atomic runtime rollback, and update-safe persistence.
|
|
16
|
+
- Open-source harness adoption research and executable Go CI gates.
|
|
17
|
+
- Token-budgeted repository maps, safe OpenTelemetry GenAI records, Promptfoo/Inspect/Harbor evaluation contracts, typed lifecycle hooks, durable approval interrupts, optional ACP intake, and signed extension verification.
|
|
18
|
+
|
|
19
|
+
### Security
|
|
20
|
+
|
|
21
|
+
- Read-only role filesystems and command policy, deterministic pre-push Gitleaks enforcement, typed scanner release blockers, terminal-safe Go rendering, and structured allowlisted operator logs.
|
|
22
|
+
- Repository-scoped MCP memory; legacy unscoped memory is retained as `legacy-unscoped-knowledge-graph.jsonl` instead of being mixed into new repositories.
|
|
23
|
+
- Model credentials now enter agent containers through a consumed stdin envelope rather than environment variables; a persistent Docker firewall blocks cloud metadata access.
|
|
24
|
+
- Release publishing now binds tags to package versions, requires full gates and npm provenance, and attests immutable Go binaries.
|
|
25
|
+
|
|
26
|
+
## [1.4.0] - 2026-07-13
|
|
27
|
+
|
|
7
28
|
### Added
|
|
8
29
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
- Durable evaluation, analytics, scaling, policy, extension, and recovery roadmap.
|
|
30
|
+
- Free local semantic code retrieval with pinned Ollama embeddings and retained Qdrant vectors.
|
|
31
|
+
- Commit-aware indexing, bounded chunking, top-k context injection, and failure fallback.
|
|
32
|
+
- Modern agent-harness capability matrix and explicit completion criteria.
|
|
13
33
|
|
|
14
34
|
## [1.3.0] - 2026-07-13
|
|
15
35
|
|
package/Dockerfile.worker
CHANGED
package/README.md
CHANGED
|
@@ -73,7 +73,13 @@ factory ui
|
|
|
73
73
|
| `factory issue OWNER/REPO NUMBER` | Turn a GitHub issue into a tracked objective |
|
|
74
74
|
| `factory telegram configure` | Configure allowlisted Telegram remote intake |
|
|
75
75
|
| `factory dashboard` | Objectives, agents, models, queue, DLQ, and Azure cost |
|
|
76
|
-
| `factory init PATH` | Create durable repo-local project context |
|
|
76
|
+
| `factory init PATH` | Create `AGENTS.md` and durable repo-local project context without overwriting existing files |
|
|
77
|
+
| `factory models show` | Show effective role-to-model routes |
|
|
78
|
+
| `factory models set ROLE PROVIDER/MODEL` | Validate and atomically switch a role to a new model |
|
|
79
|
+
| `factory models reset ROLE` | Restore a role to the versioned default |
|
|
80
|
+
| `factory configure models` | Interactively change model routing after setup |
|
|
81
|
+
| `factory acp REQUEST.json` | Submit a strictly validated optional ACP objective |
|
|
82
|
+
| `factory extension verify MANIFEST ARTIFACT PUBLIC_KEY` | Verify a signed extension manifest and immutable artifact digest |
|
|
77
83
|
| `factory doctor` | Services, storage, memory, and host health |
|
|
78
84
|
| `factory queue` | Queue and dead-letter depth |
|
|
79
85
|
| `factory logs` | Consolidated service logs |
|
|
@@ -131,6 +137,7 @@ Factory AI minimizes tokens before relying on cheaper models:
|
|
|
131
137
|
- File reads are line-ranged and bounded; listings, commands, MCP output, memory, and scanner evidence are truncated with continuation hints.
|
|
132
138
|
- Read-only roles do not receive write-tool schemas.
|
|
133
139
|
- Planner memory is compact, repository-scoped, and limited to recent verified events.
|
|
140
|
+
- Ollama generates local embeddings and Qdrant retrieves only top-ranked code chunks, avoiding embedding API charges and whole-repository prompts.
|
|
134
141
|
- Dashboard and TUI track input, cached-input, and output tokens by model.
|
|
135
142
|
- The planner is instructed to produce the smallest valid DAG, avoiding duplicate agents.
|
|
136
143
|
|
|
@@ -156,7 +163,7 @@ Every repository gets two memory layers:
|
|
|
156
163
|
|
|
157
164
|
Built-in progressive skills include `/goal`, `/loop`, project context, systematic debugging, TDD, verification, security review, dependency security, browser verification, release discipline, and token efficiency. Context7 and Playwright MCPs are pinned and role-scoped.
|
|
158
165
|
|
|
159
|
-
Use `factory init PATH` to create `.agent-factory/` project, architecture, commands, decisions, risks, and handoff files without overwriting existing context.
|
|
166
|
+
Use `factory init PATH` to create a safe root `AGENTS.md` plus `.agent-factory/` project, architecture, commands, decisions, risks, and handoff files without overwriting existing context. The runtime discovers repository `AGENTS.md` instructions for planners and workers. Active Azure and Bedrock conversations compact automatically after their configured token threshold while preserving bounded recent tool evidence.
|
|
160
167
|
|
|
161
168
|
## Credentials
|
|
162
169
|
|
|
@@ -255,6 +262,7 @@ npm pack --dry-run
|
|
|
255
262
|
| [CONTRIBUTING.md](CONTRIBUTING.md) | Development and verification contract |
|
|
256
263
|
| [HANDOFF.md](HANDOFF.md) | Team/friend transfer context |
|
|
257
264
|
| [docs/COMPARISON.md](docs/COMPARISON.md) | Honest comparison with paid alternatives |
|
|
265
|
+
| [docs/HARNESS_PARITY.md](docs/HARNESS_PARITY.md) | Feature parity across modern agent harnesses |
|
|
258
266
|
| [ROADMAP.md](ROADMAP.md) | Planned platform and ecosystem work |
|
|
259
267
|
| [GOVERNANCE.md](GOVERNANCE.md) | Decision and release governance |
|
|
260
268
|
| [SUPPORT.md](SUPPORT.md) | Community support process |
|
package/ROADMAP.md
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
- Evaluation Lab with model promotion and rollback evidence.
|
|
6
6
|
- Enhanced TUI timeline, diffs, files, checks, and safe takeover leases.
|
|
7
|
-
- Telegram remote objective status and completion notifications.
|
|
8
7
|
- Multi-repository objective schema and release groups.
|
|
9
8
|
|
|
10
9
|
## Platform
|
package/bin/factory
CHANGED
|
@@ -10,6 +10,8 @@ VM=${FACTORY_VM:-agent-factory-vm}
|
|
|
10
10
|
NAMESPACE=${FACTORY_SERVICE_BUS:-}
|
|
11
11
|
VAULT=${FACTORY_KEY_VAULT:-}
|
|
12
12
|
STORAGE=${FACTORY_STORAGE_ACCOUNT:-}
|
|
13
|
+
FACTORY_NAME=${FACTORY_NAME:-Factory AI}
|
|
14
|
+
FACTORY_PURPOSE=${FACTORY_PURPOSE:-Ship secure reviewed software continuously}
|
|
13
15
|
|
|
14
16
|
remote() {
|
|
15
17
|
az vm run-command invoke --resource-group "$RESOURCE_GROUP" --name "$VM" \
|
|
@@ -21,6 +23,9 @@ usage() {
|
|
|
21
23
|
'Factory AI operator console' \
|
|
22
24
|
'Usage: factory <command>' \
|
|
23
25
|
' setup' \
|
|
26
|
+
' configure models' \
|
|
27
|
+
' models show | set ROLE PROVIDER/MODEL | reset ROLE' \
|
|
28
|
+
' acp REQUEST.json | extension verify MANIFEST ARTIFACT PUBLIC_KEY' \
|
|
24
29
|
' github status | connect ORG | transfer OWNER/REPO ORG' \
|
|
25
30
|
' telegram status | configure | start | stop' \
|
|
26
31
|
' submit <owner/repo> <objective>' \
|
|
@@ -32,9 +37,99 @@ usage() {
|
|
|
32
37
|
' pause | resume'
|
|
33
38
|
}
|
|
34
39
|
|
|
35
|
-
command=${1:-
|
|
40
|
+
command=${1:-ui}
|
|
36
41
|
shift || true
|
|
42
|
+
|
|
43
|
+
apply_runtime_model() {
|
|
44
|
+
local variable=$1 value=${2:-} mode=${3:-set} script settings
|
|
45
|
+
script="set -euo pipefail; exec 9>/run/lock/factory-ai-config.lock; flock -x 9; first=/etc/agent-factory.env; second=/etc/agent-factory-control.env; backup_first=\$(mktemp); backup_second=\$(mktemp); cp --preserve=mode,ownership \"\$first\" \"\$backup_first\"; cp --preserve=mode,ownership \"\$second\" \"\$backup_second\"; rollback() { install -m 0600 -o root -g root \"\$backup_first\" \"\$first\"; install -m 0600 -o root -g root \"\$backup_second\" \"\$second\"; systemctl restart agent-factory-control agent-factory-worker agent-factory-release || true; rm -f \"\$backup_first\" \"\$backup_second\"; }; trap rollback ERR TERM INT; for file in \"\$first\" \"\$second\"; do tmp=\$(mktemp); grep -v '^${variable}=' \"\$file\" > \"\$tmp\" || true; if [[ '$mode' == set ]]; then printf '${variable}=%s\\n' '$value' >> \"\$tmp\"; fi; install -m 0600 -o root -g root \"\$tmp\" \"\$file\"; rm -f \"\$tmp\"; done; systemctl restart agent-factory-control agent-factory-worker agent-factory-release; systemctl is-active --quiet agent-factory-control agent-factory-worker agent-factory-release; trap - ERR TERM INT; rm -f \"\$backup_first\" \"\$backup_second\""
|
|
46
|
+
printf -v script 'bash -c %q' "$script"
|
|
47
|
+
settings=$(jq -n --arg command "$script" '{commandToExecute:$command}')
|
|
48
|
+
az vm extension set --resource-group "$RESOURCE_GROUP" --vm-name "$VM" --name FactoryAIConfigure \
|
|
49
|
+
--publisher Microsoft.Azure.Extensions --version 2.1 --force-update --protected-settings "$settings" --output none
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
update_local_model() {
|
|
53
|
+
local variable=$1 value=${2:-} mode=${3:-set} temporary
|
|
54
|
+
mkdir -p "$(dirname "$CONFIG_FILE")"
|
|
55
|
+
temporary=$(mktemp "${CONFIG_FILE}.XXXXXX")
|
|
56
|
+
if [[ -f $CONFIG_FILE ]]; then grep -v "^${variable}=" "$CONFIG_FILE" > "$temporary" || true
|
|
57
|
+
elif [[ -f $LEGACY_CONFIG_FILE ]]; then grep -v "^${variable}=" "$LEGACY_CONFIG_FILE" > "$temporary" || true; fi
|
|
58
|
+
if [[ $mode == set ]]; then printf '%s=%q\n' "$variable" "$value" >> "$temporary"; fi
|
|
59
|
+
chmod 0600 "$temporary"
|
|
60
|
+
mv "$temporary" "$CONFIG_FILE"
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
configure_model_transaction() {
|
|
64
|
+
local variable=$1 value=${2:-} mode=${3:-set}
|
|
65
|
+
MODEL_CONFIG_BACKUP=$(mktemp)
|
|
66
|
+
MODEL_CONFIG_EXISTED=false
|
|
67
|
+
if [[ -f $CONFIG_FILE ]]; then cp "$CONFIG_FILE" "$MODEL_CONFIG_BACKUP"; MODEL_CONFIG_EXISTED=true; fi
|
|
68
|
+
rollback_local_model() {
|
|
69
|
+
if [[ $MODEL_CONFIG_EXISTED == true ]]; then mv "$MODEL_CONFIG_BACKUP" "$CONFIG_FILE"; else rm -f "$CONFIG_FILE" "$MODEL_CONFIG_BACKUP"; fi
|
|
70
|
+
}
|
|
71
|
+
trap rollback_local_model EXIT INT TERM
|
|
72
|
+
update_local_model "$variable" "$value" "$mode"
|
|
73
|
+
apply_runtime_model "$variable" "$value" "$mode"
|
|
74
|
+
rm -f "$MODEL_CONFIG_BACKUP"
|
|
75
|
+
trap - EXIT INT TERM
|
|
76
|
+
}
|
|
77
|
+
|
|
37
78
|
case "$command" in
|
|
79
|
+
acp)
|
|
80
|
+
request=${1:?ACP request JSON file required}
|
|
81
|
+
SERVICE_BUS_NAMESPACE="$NAMESPACE" CONTROL_QUEUE=control-events FACTORY_ACP_ENABLED=true exec node "$FACTORY_ROOT/src/acp-cli.js" "$request"
|
|
82
|
+
;;
|
|
83
|
+
extension)
|
|
84
|
+
[[ ${1:-} == verify ]] || { printf 'Usage: factory extension verify MANIFEST ARTIFACT PUBLIC_KEY\n' >&2; exit 2; }
|
|
85
|
+
exec node "$FACTORY_ROOT/src/extension-cli.js" "${2:?manifest required}" "${3:?artifact required}" "${4:?public key required}"
|
|
86
|
+
;;
|
|
87
|
+
configure)
|
|
88
|
+
area=${1:-models}
|
|
89
|
+
[[ $area == models ]] || { printf 'Supported configuration area: models\n' >&2; exit 2; }
|
|
90
|
+
"$0" models show
|
|
91
|
+
read -r -p 'Role to change (or Enter to leave unchanged): ' role
|
|
92
|
+
[[ -n $role ]] || exit 0
|
|
93
|
+
read -r -p 'New provider/model route (or "default"): ' route
|
|
94
|
+
if [[ $route == default ]]; then exec "$0" models reset "$role"; fi
|
|
95
|
+
exec "$0" models set "$role" "$route"
|
|
96
|
+
;;
|
|
97
|
+
models)
|
|
98
|
+
action=${1:-show}
|
|
99
|
+
role=${2:-}
|
|
100
|
+
route=${3:-}
|
|
101
|
+
case "$action" in
|
|
102
|
+
show)
|
|
103
|
+
for current in scout planner builder tester debugger reviewer security release; do
|
|
104
|
+
upper=$(printf '%s' "$current" | tr '[:lower:]' '[:upper:]')
|
|
105
|
+
variable="FACTORY_MODEL_${upper}"
|
|
106
|
+
case "$current" in
|
|
107
|
+
scout) default=azureai-textved/factory-gpt-5-4-nano ;;
|
|
108
|
+
tester) default=azureai-responses/gpt-5.4 ;;
|
|
109
|
+
builder) default=azureai-textved/gpt-5.5 ;;
|
|
110
|
+
*) default=azureai-textved/gpt-5.6-sol ;;
|
|
111
|
+
esac
|
|
112
|
+
printf '%-10s %s%s\n' "$current" "${!variable:-$default}" "$([[ -n ${!variable:-} ]] && printf ' (override)' || true)"
|
|
113
|
+
done
|
|
114
|
+
;;
|
|
115
|
+
set)
|
|
116
|
+
[[ $role =~ ^(scout|planner|builder|tester|debugger|reviewer|security|release)$ ]] || { printf 'Invalid model role\n' >&2; exit 2; }
|
|
117
|
+
node --input-type=module -e "import { validateModelRoute } from 'file://$FACTORY_ROOT/src/routing.js'; validateModelRoute(process.argv[1])" "$route"
|
|
118
|
+
upper=$(printf '%s' "$role" | tr '[:lower:]' '[:upper:]')
|
|
119
|
+
variable="FACTORY_MODEL_${upper}"
|
|
120
|
+
configure_model_transaction "$variable" "$route" set
|
|
121
|
+
printf '%s now routes to %s. Runtime services are healthy.\n' "$role" "$route"
|
|
122
|
+
;;
|
|
123
|
+
reset)
|
|
124
|
+
[[ $role =~ ^(scout|planner|builder|tester|debugger|reviewer|security|release)$ ]] || { printf 'Invalid model role\n' >&2; exit 2; }
|
|
125
|
+
upper=$(printf '%s' "$role" | tr '[:lower:]' '[:upper:]')
|
|
126
|
+
variable="FACTORY_MODEL_${upper}"
|
|
127
|
+
configure_model_transaction "$variable" "" reset
|
|
128
|
+
printf '%s restored to the versioned default. Runtime services are healthy.\n' "$role"
|
|
129
|
+
;;
|
|
130
|
+
*) printf 'Usage: factory models show | set ROLE PROVIDER/MODEL | reset ROLE\n' >&2; exit 2 ;;
|
|
131
|
+
esac
|
|
132
|
+
;;
|
|
38
133
|
telegram)
|
|
39
134
|
action=${1:-status}
|
|
40
135
|
case "$action" in
|
|
@@ -74,7 +169,34 @@ case "$command" in
|
|
|
74
169
|
exec "$0" submit "$repo" "$objective"
|
|
75
170
|
;;
|
|
76
171
|
ui)
|
|
77
|
-
|
|
172
|
+
if [[ ! -f $CONFIG_FILE && ! -f $LEGACY_CONFIG_FILE ]]; then
|
|
173
|
+
"$0" setup
|
|
174
|
+
exec "$0" ui
|
|
175
|
+
fi
|
|
176
|
+
version=$(node -p "require('$FACTORY_ROOT/package.json').version")
|
|
177
|
+
os=$(uname -s | tr '[:upper:]' '[:lower:]')
|
|
178
|
+
arch=$(uname -m)
|
|
179
|
+
[[ $arch == x86_64 ]] && arch=amd64
|
|
180
|
+
[[ $arch == aarch64 ]] && arch=arm64
|
|
181
|
+
cache="$HOME/.cache/factory-ai/$version"
|
|
182
|
+
binary="$cache/factory-ui-$os-$arch"
|
|
183
|
+
if [[ ! -x $binary ]]; then
|
|
184
|
+
mkdir -p "$cache"
|
|
185
|
+
base="https://github.com/itsvedantkumar/factory-ai/releases/download/v$version"
|
|
186
|
+
if curl -fsSL "$base/factory-ui-$os-$arch" -o "$binary.tmp" && curl -fsSL "$base/checksums.txt" -o "$cache/checksums.txt"; then
|
|
187
|
+
expected=""
|
|
188
|
+
while read -r checksum asset; do [[ $asset == "factory-ui-$os-$arch" ]] && expected=$checksum; done < "$cache/checksums.txt"
|
|
189
|
+
actual=""
|
|
190
|
+
if command -v shasum >/dev/null; then actual=$(shasum -a 256 "$binary.tmp"); actual=${actual%% *};
|
|
191
|
+
elif command -v sha256sum >/dev/null; then actual=$(sha256sum "$binary.tmp"); actual=${actual%% *}; fi
|
|
192
|
+
if [[ -n $expected && $actual == "$expected" ]] && gh attestation verify "$binary.tmp" --repo itsvedantkumar/factory-ai >/dev/null 2>&1; then mv "$binary.tmp" "$binary"; chmod 0755 "$binary"; else rm -f "$binary.tmp"; fi
|
|
193
|
+
fi
|
|
194
|
+
fi
|
|
195
|
+
if [[ -x $binary ]]; then
|
|
196
|
+
FACTORY_STORAGE_ACCOUNT="$STORAGE" FACTORY_NAME="$FACTORY_NAME" FACTORY_PURPOSE="$FACTORY_PURPOSE" exec "$binary"
|
|
197
|
+
fi
|
|
198
|
+
printf 'Charm client unavailable for this release; using Node fallback.\n' >&2
|
|
199
|
+
FACTORY_RESOURCE_GROUP="$RESOURCE_GROUP" FACTORY_VM="$VM" FACTORY_SERVICE_BUS="$NAMESPACE" FACTORY_KEY_VAULT="$VAULT" FACTORY_STORAGE_ACCOUNT="$STORAGE" FACTORY_NAME="$FACTORY_NAME" FACTORY_PURPOSE="$FACTORY_PURPOSE" node "$FACTORY_ROOT/src/tui.js"
|
|
78
200
|
;;
|
|
79
201
|
setup)
|
|
80
202
|
for dependency in az gh jq curl ssh-keygen node; do command -v "$dependency" >/dev/null || { printf 'Missing dependency: %s\n' "$dependency" >&2; exit 1; }; done
|
|
@@ -82,6 +204,8 @@ case "$command" in
|
|
|
82
204
|
trap 'rm -f "$choices"' EXIT
|
|
83
205
|
node "$FACTORY_ROOT/src/setup-menu.js" "$choices"
|
|
84
206
|
provider=$(jq -r .provider "$choices")
|
|
207
|
+
factory_name=$(jq -r .factoryName "$choices")
|
|
208
|
+
factory_purpose=$(jq -r .factoryPurpose "$choices")
|
|
85
209
|
location=$(jq -r .location "$choices")
|
|
86
210
|
enterprise_org=$(jq -r .githubOrg "$choices")
|
|
87
211
|
aws_region=$(jq -r .awsRegion "$choices")
|
|
@@ -107,6 +231,8 @@ case "$command" in
|
|
|
107
231
|
printf 'FACTORY_SERVICE_BUS=%q\n' "$namespace"
|
|
108
232
|
printf 'FACTORY_KEY_VAULT=%q\n' "$vault"
|
|
109
233
|
printf 'FACTORY_STORAGE_ACCOUNT=%q\n' "$storage"
|
|
234
|
+
printf 'FACTORY_NAME=%q\n' "$factory_name"
|
|
235
|
+
printf 'FACTORY_PURPOSE=%q\n' "$factory_purpose"
|
|
110
236
|
} > "$CONFIG_FILE"
|
|
111
237
|
chmod 0600 "$CONFIG_FILE"
|
|
112
238
|
ip=$(curl -fsS https://api.ipify.org)
|
|
@@ -154,7 +280,7 @@ case "$command" in
|
|
|
154
280
|
printf 'Azure foundation and credential vault ready. Config: %s\n' "$CONFIG_FILE"
|
|
155
281
|
if [[ $deploy_now == true ]]; then
|
|
156
282
|
source_ref=$(gh api repos/itsvedantkumar/factory-ai/commits/main --jq .sha)
|
|
157
|
-
parameters=(KEY_VAULT_NAME "$vault" SERVICE_BUS_NAMESPACE "$namespace"
|
|
283
|
+
parameters=(KEY_VAULT_NAME "$vault" SERVICE_BUS_NAMESPACE "$namespace" FACTORY_STORAGE_ACCOUNT "$storage" FACTORY_NAME "$factory_name" FACTORY_PURPOSE "$factory_purpose" SOURCE_REPOSITORY itsvedantkumar/factory-ai SOURCE_REF "$source_ref")
|
|
158
284
|
if [[ $provider == bedrock ]]; then
|
|
159
285
|
parameters+=(AWS_REGION "$aws_region")
|
|
160
286
|
for role in SCOUT PLANNER BUILDER TESTER DEBUGGER REVIEWER SECURITY RELEASE; do parameters+=("FACTORY_MODEL_$role" "bedrock/$bedrock_builder"); done
|
|
@@ -233,6 +359,7 @@ case "$command" in
|
|
|
233
359
|
[[ -d $target ]] || { printf 'Project directory does not exist: %s\n' "$target" >&2; exit 2; }
|
|
234
360
|
context="$target/.agent-factory"
|
|
235
361
|
mkdir -p "$context"
|
|
362
|
+
[[ -e $target/AGENTS.md ]] || cp "$FACTORY_ROOT/templates/AGENTS.md" "$target/AGENTS.md"
|
|
236
363
|
for template in "$FACTORY_ROOT/templates/project/"*.md; do
|
|
237
364
|
destination="$context/$(basename "$template")"
|
|
238
365
|
[[ -e $destination ]] || cp "$template" "$destination"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
[Unit]
|
|
2
2
|
Description=Factory AI durable worker
|
|
3
|
-
After=network-online.target docker.service
|
|
4
|
-
Wants=network-online.target
|
|
5
|
-
Requires=docker.service
|
|
3
|
+
After=network-online.target docker.service factory-ai-container-firewall.service factory-ai-qdrant.service factory-ai-ollama.service
|
|
4
|
+
Wants=network-online.target factory-ai-qdrant.service factory-ai-ollama.service
|
|
5
|
+
Requires=docker.service factory-ai-container-firewall.service
|
|
6
6
|
StartLimitIntervalSec=300
|
|
7
7
|
StartLimitBurst=10
|
|
8
8
|
|
package/bootstrap/auto-update.sh
CHANGED
|
@@ -18,6 +18,12 @@ set -a
|
|
|
18
18
|
source /etc/agent-factory.env
|
|
19
19
|
set +a
|
|
20
20
|
github_token=$(az keyvault secret show --vault-name "$KEY_VAULT_NAME" --name github-token --query value --output tsv)
|
|
21
|
+
tag_commit=$(GH_TOKEN="$github_token" gh api "repos/itsvedantkumar/factory-ai/commits/v$version" --jq .sha)
|
|
22
|
+
[[ $tag_commit == "$commit" ]] || { printf 'npm gitHead does not match the immutable release tag.\n' >&2; exit 1; }
|
|
23
|
+
release_ok=$(GH_TOKEN="$github_token" gh release view "v$version" --repo itsvedantkumar/factory-ai --json isDraft,isPrerelease --jq '(.isDraft == false) and (.isPrerelease == false)')
|
|
24
|
+
[[ $release_ok == true ]] || { printf 'Matching stable GitHub release is unavailable.\n' >&2; exit 1; }
|
|
25
|
+
provenance=$(npm view "factory-ai@$version" dist.attestations.provenance.url 2>/dev/null || true)
|
|
26
|
+
[[ $provenance == https://search.sigstore.dev/* ]] || { printf 'npm release lacks verifiable provenance metadata.\n' >&2; exit 1; }
|
|
21
27
|
checks=$(GH_TOKEN="$github_token" gh api "repos/itsvedantkumar/factory-ai/commits/$commit/check-runs" --jq '[.check_runs[] | select(.name == "verify") | .conclusion] | any(. == "success")')
|
|
22
28
|
[[ $checks == true ]] || { printf 'Candidate commit lacks successful CI verification.\n' >&2; exit 1; }
|
|
23
29
|
|
|
@@ -41,20 +47,22 @@ docker run --rm --read-only --volume "$temporary/source:/workspace:ro" \
|
|
|
41
47
|
detect --source /workspace --redact --no-banner --exit-code 1
|
|
42
48
|
|
|
43
49
|
printf 'Deploying Factory AI %s (%s)\n' "$version" "$commit"
|
|
44
|
-
|
|
45
|
-
KEY_VAULT_NAME "$KEY_VAULT_NAME"
|
|
46
|
-
SERVICE_BUS_NAMESPACE "$SERVICE_BUS_NAMESPACE"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
deployment_parameters=(
|
|
51
|
+
KEY_VAULT_NAME "$KEY_VAULT_NAME"
|
|
52
|
+
SERVICE_BUS_NAMESPACE "$SERVICE_BUS_NAMESPACE"
|
|
53
|
+
SOURCE_REPOSITORY itsvedantkumar/factory-ai
|
|
54
|
+
SOURCE_REF "$commit"
|
|
55
|
+
)
|
|
56
|
+
for variable in FACTORY_STORAGE_ACCOUNT FACTORY_NAME FACTORY_PURPOSE AWS_REGION FACTORY_MODEL_SCOUT FACTORY_MODEL_PLANNER FACTORY_MODEL_BUILDER FACTORY_MODEL_TESTER FACTORY_MODEL_DEBUGGER FACTORY_MODEL_REVIEWER FACTORY_MODEL_SECURITY FACTORY_MODEL_RELEASE FACTORY_COMPACT_AFTER_INPUT_TOKENS FACTORY_COMPACT_MAX_CHARACTERS FACTORY_WATCHDOG_STALE_SECONDS FACTORY_HOOKS_JSON; do
|
|
57
|
+
[[ -n ${!variable:-} ]] && deployment_parameters+=("$variable" "${!variable}")
|
|
58
|
+
done
|
|
59
|
+
if ! bash "$temporary/source/bootstrap/deploy-runtime.sh" "${deployment_parameters[@]}"; then
|
|
50
60
|
printf 'Candidate deployment failed. Restoring previous runtime.\n' >&2
|
|
51
61
|
if [[ $previous_commit =~ ^[0-9a-f]{40}$ ]]; then
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
SOURCE_REPOSITORY itsvedantkumar/factory-ai \
|
|
57
|
-
SOURCE_REF "$previous_commit"
|
|
62
|
+
for ((index=0; index<${#deployment_parameters[@]}; index+=2)); do
|
|
63
|
+
[[ ${deployment_parameters[index]} == SOURCE_REF ]] && deployment_parameters[index+1]=$previous_commit
|
|
64
|
+
done
|
|
65
|
+
bash "$temporary/rollback-deploy.sh" "${deployment_parameters[@]}"
|
|
58
66
|
fi
|
|
59
67
|
exit 1
|
|
60
68
|
fi
|
|
@@ -20,7 +20,7 @@ while (($# > 0)); do
|
|
|
20
20
|
shift
|
|
21
21
|
fi
|
|
22
22
|
case "$name" in
|
|
23
|
-
KEY_VAULT_NAME|SERVICE_BUS_NAMESPACE|
|
|
23
|
+
KEY_VAULT_NAME|SERVICE_BUS_NAMESPACE|SOURCE_REPOSITORY|SOURCE_REF|FACTORY_STORAGE_ACCOUNT|FACTORY_NAME|FACTORY_PURPOSE|AWS_REGION|FACTORY_MODEL_SCOUT|FACTORY_MODEL_PLANNER|FACTORY_MODEL_BUILDER|FACTORY_MODEL_TESTER|FACTORY_MODEL_DEBUGGER|FACTORY_MODEL_REVIEWER|FACTORY_MODEL_SECURITY|FACTORY_MODEL_RELEASE|FACTORY_COMPACT_AFTER_INPUT_TOKENS|FACTORY_COMPACT_MAX_CHARACTERS|FACTORY_WATCHDOG_STALE_SECONDS|FACTORY_HOOKS_JSON) printf -v "$name" '%s' "$value" ;;
|
|
24
24
|
*) echo "Unknown deployment parameter: $name" >&2; exit 1 ;;
|
|
25
25
|
esac
|
|
26
26
|
done
|
|
@@ -29,7 +29,6 @@ done
|
|
|
29
29
|
: "${SERVICE_BUS_NAMESPACE:?SERVICE_BUS_NAMESPACE is required}"
|
|
30
30
|
: "${SOURCE_REPOSITORY:?SOURCE_REPOSITORY as OWNER/REPOSITORY is required}"
|
|
31
31
|
: "${SOURCE_REF:?SOURCE_REF must be a full commit SHA}"
|
|
32
|
-
SERVICE_BUS_QUEUE=${SERVICE_BUS_QUEUE:-code-tasks}
|
|
33
32
|
[[ $SOURCE_REPOSITORY =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]] || { echo "Invalid SOURCE_REPOSITORY" >&2; exit 1; }
|
|
34
33
|
[[ $SOURCE_REF =~ ^[0-9a-f]{40}$ ]] || { echo "SOURCE_REF must be a full lowercase commit SHA" >&2; exit 1; }
|
|
35
34
|
|
|
@@ -60,9 +59,10 @@ rsync -a --delete --exclude .git "$temporary/source/" /opt/agent-factory/app/
|
|
|
60
59
|
|
|
61
60
|
KEY_VAULT_NAME="$KEY_VAULT_NAME" \
|
|
62
61
|
SERVICE_BUS_NAMESPACE="$SERVICE_BUS_NAMESPACE" \
|
|
63
|
-
SERVICE_BUS_QUEUE="$SERVICE_BUS_QUEUE" \
|
|
64
62
|
FACTORY_WORKER_IMAGE="agent-factory-worker:$SOURCE_REF" \
|
|
65
63
|
FACTORY_STORAGE_ACCOUNT="${FACTORY_STORAGE_ACCOUNT:-}" \
|
|
64
|
+
FACTORY_NAME="${FACTORY_NAME:-Factory AI}" \
|
|
65
|
+
FACTORY_PURPOSE="${FACTORY_PURPOSE:-Ship secure reviewed software continuously}" \
|
|
66
66
|
AWS_REGION="${AWS_REGION:-}" \
|
|
67
67
|
FACTORY_MODEL_SCOUT="${FACTORY_MODEL_SCOUT:-}" \
|
|
68
68
|
FACTORY_MODEL_PLANNER="${FACTORY_MODEL_PLANNER:-}" \
|
|
@@ -72,6 +72,10 @@ FACTORY_MODEL_DEBUGGER="${FACTORY_MODEL_DEBUGGER:-}" \
|
|
|
72
72
|
FACTORY_MODEL_REVIEWER="${FACTORY_MODEL_REVIEWER:-}" \
|
|
73
73
|
FACTORY_MODEL_SECURITY="${FACTORY_MODEL_SECURITY:-}" \
|
|
74
74
|
FACTORY_MODEL_RELEASE="${FACTORY_MODEL_RELEASE:-}" \
|
|
75
|
+
FACTORY_COMPACT_AFTER_INPUT_TOKENS="${FACTORY_COMPACT_AFTER_INPUT_TOKENS:-80000}" \
|
|
76
|
+
FACTORY_COMPACT_MAX_CHARACTERS="${FACTORY_COMPACT_MAX_CHARACTERS:-24000}" \
|
|
77
|
+
FACTORY_WATCHDOG_STALE_SECONDS="${FACTORY_WATCHDOG_STALE_SECONDS:-900}" \
|
|
78
|
+
FACTORY_HOOKS_JSON="${FACTORY_HOOKS_JSON:-[]}" \
|
|
75
79
|
bash /opt/agent-factory/app/bootstrap/setup.sh
|
|
76
80
|
install -d -o factory -g factory -m 0750 /opt/agent-factory/state
|
|
77
81
|
version=$(node -p 'require("/opt/agent-factory/app/package.json").version')
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=Block cloud metadata access from Factory AI containers
|
|
3
|
+
After=docker.service
|
|
4
|
+
Before=agent-factory-worker.service
|
|
5
|
+
Requires=docker.service
|
|
6
|
+
|
|
7
|
+
[Service]
|
|
8
|
+
Type=oneshot
|
|
9
|
+
ExecStart=/bin/bash -c '/usr/sbin/iptables -C DOCKER-USER -d 169.254.169.254/32 -j REJECT 2>/dev/null || /usr/sbin/iptables -I DOCKER-USER -d 169.254.169.254/32 -j REJECT'
|
|
10
|
+
RemainAfterExit=yes
|
|
11
|
+
NoNewPrivileges=true
|
|
12
|
+
|
|
13
|
+
[Install]
|
|
14
|
+
WantedBy=multi-user.target
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=Factory AI local embedding inference
|
|
3
|
+
After=docker.service
|
|
4
|
+
Requires=docker.service
|
|
5
|
+
|
|
6
|
+
[Service]
|
|
7
|
+
Type=simple
|
|
8
|
+
ExecStartPre=-/usr/bin/docker rm -f factory-ai-ollama
|
|
9
|
+
ExecStart=/usr/bin/docker run --rm --name factory-ai-ollama --userns host --cap-drop ALL --security-opt no-new-privileges --pids-limit 1024 --memory 6g --cpus 4 --publish 127.0.0.1:11434:11434 --env OLLAMA_MODELS=/models --volume /opt/agent-factory/state/ollama:/models ollama/ollama@sha256:3d8a05e3432d50ea57594fabe971e46cc8fe963a0f9f8c40400bd56cd5388e47
|
|
10
|
+
ExecStop=/usr/bin/docker stop -t 20 factory-ai-ollama
|
|
11
|
+
Restart=always
|
|
12
|
+
RestartSec=5
|
|
13
|
+
SyslogIdentifier=factory-ai-ollama
|
|
14
|
+
|
|
15
|
+
[Install]
|
|
16
|
+
WantedBy=multi-user.target
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=Factory AI local Qdrant retrieval store
|
|
3
|
+
After=docker.service
|
|
4
|
+
Requires=docker.service
|
|
5
|
+
|
|
6
|
+
[Service]
|
|
7
|
+
Type=simple
|
|
8
|
+
ExecStartPre=-/usr/bin/docker rm -f factory-ai-qdrant
|
|
9
|
+
ExecStart=/usr/bin/docker run --rm --name factory-ai-qdrant --userns host --read-only --cap-drop ALL --security-opt no-new-privileges --pids-limit 1024 --memory 2g --cpus 2 --publish 127.0.0.1:6333:6333 --volume /opt/agent-factory/state/qdrant:/qdrant/storage --volume /opt/agent-factory/state/qdrant-snapshots:/qdrant/snapshots qdrant/qdrant@sha256:31407c0e8e32eb771b71718f1a4772e2ad47a07557917b21ac96792f40eb8007
|
|
10
|
+
ExecStop=/usr/bin/docker stop -t 20 factory-ai-qdrant
|
|
11
|
+
Restart=always
|
|
12
|
+
RestartSec=5
|
|
13
|
+
SyslogIdentifier=factory-ai-qdrant
|
|
14
|
+
|
|
15
|
+
[Install]
|
|
16
|
+
WantedBy=multi-user.target
|
|
@@ -7,6 +7,7 @@ Wants=network-online.target
|
|
|
7
7
|
Type=oneshot
|
|
8
8
|
User=factory
|
|
9
9
|
Group=factory
|
|
10
|
+
SupplementaryGroups=systemd-journal
|
|
10
11
|
WorkingDirectory=/opt/agent-factory/app
|
|
11
12
|
EnvironmentFile=/etc/agent-factory-control.env
|
|
12
13
|
ExecStart=/usr/bin/node /opt/agent-factory/app/src/snapshot.js
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=Recover stale Factory AI agent containers
|
|
3
|
+
After=network-online.target docker.service agent-factory-control.service
|
|
4
|
+
Wants=network-online.target
|
|
5
|
+
Requires=docker.service
|
|
6
|
+
|
|
7
|
+
[Service]
|
|
8
|
+
Type=oneshot
|
|
9
|
+
User=factory
|
|
10
|
+
Group=factory
|
|
11
|
+
SupplementaryGroups=docker
|
|
12
|
+
WorkingDirectory=/opt/agent-factory/app
|
|
13
|
+
EnvironmentFile=/etc/agent-factory.env
|
|
14
|
+
ExecStart=/usr/bin/node /opt/agent-factory/app/src/watchdog.js
|
|
15
|
+
NoNewPrivileges=true
|
|
16
|
+
PrivateTmp=true
|
|
17
|
+
ProtectSystem=strict
|
|
18
|
+
ProtectHome=true
|
|
19
|
+
ReadWritePaths=/opt/agent-factory/state /opt/agent-factory/workspaces
|
|
20
|
+
UMask=0027
|
|
21
|
+
SyslogIdentifier=factory-ai-watchdog
|
package/bootstrap/setup.sh
CHANGED
|
@@ -10,7 +10,6 @@ fi
|
|
|
10
10
|
: "${KEY_VAULT_NAME:?Set KEY_VAULT_NAME to the existing vault name}"
|
|
11
11
|
: "${SERVICE_BUS_NAMESPACE:?Set SERVICE_BUS_NAMESPACE to the existing namespace name}"
|
|
12
12
|
: "${FACTORY_WORKER_IMAGE:?Set FACTORY_WORKER_IMAGE to an immutable image tag}"
|
|
13
|
-
SERVICE_BUS_QUEUE=${SERVICE_BUS_QUEUE:-code-tasks}
|
|
14
13
|
APP_DIR=${APP_DIR:-/opt/agent-factory/app}
|
|
15
14
|
FACTORY_USER=${FACTORY_USER:-factory}
|
|
16
15
|
|
|
@@ -18,11 +17,11 @@ chmod 0755 /opt/agent-factory "$APP_DIR"
|
|
|
18
17
|
|
|
19
18
|
export DEBIAN_FRONTEND=noninteractive
|
|
20
19
|
apt-get update
|
|
21
|
-
apt-get install -y ca-certificates curl gpg git jq
|
|
20
|
+
apt-get install -y ca-certificates curl gpg git jq iptables
|
|
22
21
|
|
|
23
22
|
install -d -m 0755 /etc/apt/keyrings
|
|
24
23
|
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor --yes -o /etc/apt/keyrings/nodesource.gpg
|
|
25
|
-
printf '%s\n' 'deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/
|
|
24
|
+
printf '%s\n' 'deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main' > /etc/apt/sources.list.d/nodesource.list
|
|
26
25
|
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg -o /etc/apt/keyrings/githubcli-archive-keyring.gpg
|
|
27
26
|
chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg
|
|
28
27
|
printf '%s\n' "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" > /etc/apt/sources.list.d/github-cli.list
|
|
@@ -30,7 +29,7 @@ curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor --y
|
|
|
30
29
|
printf '%s\n' "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ $(. /etc/os-release && echo "$VERSION_CODENAME") main" > /etc/apt/sources.list.d/azure-cli.list
|
|
31
30
|
apt-get update
|
|
32
31
|
apt-get install -y azure-cli gh nodejs
|
|
33
|
-
test "$(node --version | cut -d. -f1)" = "
|
|
32
|
+
test "$(node --version | cut -d. -f1)" = "v22"
|
|
34
33
|
|
|
35
34
|
id "$FACTORY_USER" >/dev/null 2>&1 || useradd --system --create-home --shell /usr/sbin/nologin "$FACTORY_USER"
|
|
36
35
|
test -f "$APP_DIR/package-lock.json"
|
|
@@ -44,6 +43,9 @@ for scanner_image in \
|
|
|
44
43
|
semgrep/semgrep@sha256:183a149fb3e9700ab5294a7b4ab0241a826fd046bc8b721062fbea80fdfa438f; do
|
|
45
44
|
docker pull "$scanner_image"
|
|
46
45
|
done
|
|
46
|
+
docker pull ollama/ollama@sha256:3d8a05e3432d50ea57594fabe971e46cc8fe963a0f9f8c40400bd56cd5388e47
|
|
47
|
+
docker pull qdrant/qdrant@sha256:31407c0e8e32eb771b71718f1a4772e2ad47a07557917b21ac96792f40eb8007
|
|
48
|
+
iptables -C DOCKER-USER -d 169.254.169.254/32 -j REJECT 2>/dev/null || iptables -I DOCKER-USER -d 169.254.169.254/32 -j REJECT
|
|
47
49
|
|
|
48
50
|
STATE_DEVICE=/dev/disk/azure/scsi1/lun0
|
|
49
51
|
if [[ -b $STATE_DEVICE ]]; then
|
|
@@ -65,7 +67,11 @@ for secret_name in "${GITHUB_TOKEN_SECRET:-github-token}"; do
|
|
|
65
67
|
az keyvault secret show --vault-name "$KEY_VAULT_NAME" --name "$secret_name" --query id --output none
|
|
66
68
|
done
|
|
67
69
|
|
|
68
|
-
install -d -o "$FACTORY_USER" -g "$FACTORY_USER" -m 0750 /opt/agent-factory/state /opt/agent-factory/state/home /opt/agent-factory/state/memory /opt/agent-factory/state/telegram /opt/agent-factory/workspaces /opt/agent-factory/logs
|
|
70
|
+
install -d -o "$FACTORY_USER" -g "$FACTORY_USER" -m 0750 /opt/agent-factory/state /opt/agent-factory/state/home /opt/agent-factory/state/memory /opt/agent-factory/state/telegram /opt/agent-factory/state/retrieval /opt/agent-factory/workspaces /opt/agent-factory/logs
|
|
71
|
+
if [[ -f /opt/agent-factory/state/memory/knowledge-graph.jsonl && ! -e /opt/agent-factory/state/memory/legacy-unscoped-knowledge-graph.jsonl ]]; then
|
|
72
|
+
mv /opt/agent-factory/state/memory/knowledge-graph.jsonl /opt/agent-factory/state/memory/legacy-unscoped-knowledge-graph.jsonl
|
|
73
|
+
fi
|
|
74
|
+
install -d -o root -g root -m 0750 /opt/agent-factory/state/qdrant /opt/agent-factory/state/qdrant-snapshots /opt/agent-factory/state/ollama
|
|
69
75
|
install -m 0600 -o root -g root /dev/null /etc/agent-factory.env
|
|
70
76
|
{
|
|
71
77
|
printf 'SERVICE_BUS_NAMESPACE=%s\n' "$SERVICE_BUS_NAMESPACE"
|
|
@@ -81,10 +87,15 @@ install -m 0600 -o root -g root /dev/null /etc/agent-factory.env
|
|
|
81
87
|
printf 'FACTORY_REGISTRY=%s/config/capabilities.json\n' "$APP_DIR"
|
|
82
88
|
printf 'FACTORY_WORKER_IMAGE=%s\n' "$FACTORY_WORKER_IMAGE"
|
|
83
89
|
printf 'FACTORY_VERSION=%s\n' "$factory_version"
|
|
90
|
+
printf 'FACTORY_NAME=%s\n' "${FACTORY_NAME:-Factory AI}"
|
|
91
|
+
printf 'FACTORY_PURPOSE=%s\n' "${FACTORY_PURPOSE:-Ship secure reviewed software continuously}"
|
|
84
92
|
printf 'MAX_CONCURRENCY=3\n'
|
|
85
93
|
printf 'TASK_TIMEOUT_MS=1800000\n'
|
|
94
|
+
printf 'FACTORY_COMPACT_AFTER_INPUT_TOKENS=%s\n' "${FACTORY_COMPACT_AFTER_INPUT_TOKENS:-80000}"
|
|
95
|
+
printf 'FACTORY_COMPACT_MAX_CHARACTERS=%s\n' "${FACTORY_COMPACT_MAX_CHARACTERS:-24000}"
|
|
96
|
+
printf 'FACTORY_WATCHDOG_STALE_SECONDS=%s\n' "${FACTORY_WATCHDOG_STALE_SECONDS:-900}"
|
|
97
|
+
printf 'FACTORY_HOOKS_JSON=%s\n' "${FACTORY_HOOKS_JSON:-[]}"
|
|
86
98
|
printf 'MAX_DELIVERY_COUNT=8\n'
|
|
87
|
-
printf 'FACTORY_VERSION=%s\n' "$factory_version"
|
|
88
99
|
[[ -n ${AWS_REGION:-} ]] && printf 'AWS_REGION=%s\nAWS_DEFAULT_REGION=%s\n' "$AWS_REGION" "$AWS_REGION"
|
|
89
100
|
for variable in FACTORY_MODEL_SCOUT FACTORY_MODEL_PLANNER FACTORY_MODEL_BUILDER FACTORY_MODEL_TESTER FACTORY_MODEL_DEBUGGER FACTORY_MODEL_REVIEWER FACTORY_MODEL_SECURITY FACTORY_MODEL_RELEASE; do
|
|
90
101
|
[[ -n ${!variable:-} ]] && printf '%s=%s\n' "$variable" "${!variable}"
|
|
@@ -104,6 +115,8 @@ install -m 0600 -o root -g root /dev/null /etc/agent-factory-control.env
|
|
|
104
115
|
printf 'FACTORY_STATE_DIR=/opt/agent-factory/state\n'
|
|
105
116
|
printf 'FACTORY_REGISTRY=%s/config/capabilities.json\n' "$APP_DIR"
|
|
106
117
|
printf 'MAX_DELIVERY_COUNT=8\n'
|
|
118
|
+
printf 'FACTORY_COMPACT_AFTER_INPUT_TOKENS=%s\n' "${FACTORY_COMPACT_AFTER_INPUT_TOKENS:-80000}"
|
|
119
|
+
printf 'FACTORY_COMPACT_MAX_CHARACTERS=%s\n' "${FACTORY_COMPACT_MAX_CHARACTERS:-24000}"
|
|
107
120
|
[[ -n ${AWS_REGION:-} ]] && printf 'AWS_REGION=%s\nAWS_DEFAULT_REGION=%s\n' "$AWS_REGION" "$AWS_REGION"
|
|
108
121
|
for variable in FACTORY_MODEL_SCOUT FACTORY_MODEL_PLANNER FACTORY_MODEL_BUILDER FACTORY_MODEL_TESTER FACTORY_MODEL_DEBUGGER FACTORY_MODEL_REVIEWER FACTORY_MODEL_SECURITY FACTORY_MODEL_RELEASE; do
|
|
109
122
|
[[ -n ${!variable:-} ]] && printf '%s=%s\n' "$variable" "${!variable}"
|
|
@@ -111,9 +124,12 @@ install -m 0600 -o root -g root /dev/null /etc/agent-factory-control.env
|
|
|
111
124
|
} > /etc/agent-factory-control.env
|
|
112
125
|
|
|
113
126
|
chown -R "$FACTORY_USER:$FACTORY_USER" /opt/agent-factory/state /opt/agent-factory/workspaces /opt/agent-factory/logs
|
|
127
|
+
chown root:root /opt/agent-factory/state/qdrant /opt/agent-factory/state/qdrant-snapshots /opt/agent-factory/state/ollama
|
|
128
|
+
chmod 0750 /opt/agent-factory/state/qdrant /opt/agent-factory/state/qdrant-snapshots /opt/agent-factory/state/ollama
|
|
114
129
|
chown -R root:root "$APP_DIR"
|
|
115
130
|
chmod -R go-w "$APP_DIR"
|
|
116
131
|
install -m 0644 "$APP_DIR/bootstrap/agent-factory-worker.service" /etc/systemd/system/agent-factory-worker.service
|
|
132
|
+
install -m 0644 "$APP_DIR/bootstrap/factory-ai-container-firewall.service" /etc/systemd/system/factory-ai-container-firewall.service
|
|
117
133
|
install -m 0644 "$APP_DIR/bootstrap/agent-factory-control.service" /etc/systemd/system/agent-factory-control.service
|
|
118
134
|
install -m 0644 "$APP_DIR/bootstrap/agent-factory-release.service" /etc/systemd/system/agent-factory-release.service
|
|
119
135
|
install -m 0644 "$APP_DIR/bootstrap/agent-factory-reporter.service" /etc/systemd/system/agent-factory-reporter.service
|
|
@@ -123,14 +139,23 @@ chmod 0755 "$APP_DIR/bootstrap/auto-update.sh"
|
|
|
123
139
|
install -m 0644 "$APP_DIR/bootstrap/factory-ai-update.service" /etc/systemd/system/factory-ai-update.service
|
|
124
140
|
install -m 0644 "$APP_DIR/bootstrap/factory-ai-update.timer" /etc/systemd/system/factory-ai-update.timer
|
|
125
141
|
install -m 0644 "$APP_DIR/bootstrap/factory-ai-snapshot.service" /etc/systemd/system/factory-ai-snapshot.service
|
|
126
|
-
install -m 0644 "$APP_DIR/bootstrap/factory-ai-snapshot.timer" /etc/systemd/system/factory-ai-snapshot.timer
|
|
142
|
+
install -m 0644 "$APP_DIR/bootstrap/factory-ai-snapshot.timer" /etc/systemd/system/factory-ai-snapshot.timer
|
|
143
|
+
install -m 0644 "$APP_DIR/bootstrap/factory-ai-watchdog.service" /etc/systemd/system/factory-ai-watchdog.service
|
|
144
|
+
install -m 0644 "$APP_DIR/bootstrap/factory-ai-watchdog.timer" /etc/systemd/system/factory-ai-watchdog.timer
|
|
145
|
+
install -m 0644 "$APP_DIR/bootstrap/factory-ai-qdrant.service" /etc/systemd/system/factory-ai-qdrant.service
|
|
146
|
+
install -m 0644 "$APP_DIR/bootstrap/factory-ai-ollama.service" /etc/systemd/system/factory-ai-ollama.service
|
|
127
147
|
systemctl daemon-reload
|
|
148
|
+
systemctl enable --now factory-ai-container-firewall.service
|
|
128
149
|
systemctl enable --now agent-factory-worker.service
|
|
129
150
|
systemctl enable --now agent-factory-control.service
|
|
130
151
|
systemctl enable --now agent-factory-release.service
|
|
131
152
|
systemctl enable --now agent-factory-reporter.timer
|
|
132
153
|
systemctl enable --now agent-factory-telegram.service
|
|
133
154
|
systemctl enable --now factory-ai-update.timer
|
|
134
|
-
systemctl enable --now factory-ai-snapshot.timer
|
|
155
|
+
systemctl enable --now factory-ai-snapshot.timer
|
|
156
|
+
systemctl enable --now factory-ai-watchdog.timer
|
|
157
|
+
systemctl enable --now factory-ai-qdrant.service factory-ai-ollama.service
|
|
158
|
+
for _ in $(seq 1 60); do curl -fsS http://127.0.0.1:11434/api/tags >/dev/null && break; sleep 2; done
|
|
159
|
+
docker exec factory-ai-ollama ollama show embeddinggemma >/dev/null 2>&1 || docker exec factory-ai-ollama ollama pull embeddinggemma
|
|
135
160
|
systemctl restart agent-factory-control.service agent-factory-worker.service agent-factory-release.service
|
|
136
161
|
echo "Agent factory worker installed"
|