agentlas 1.0.45 → 1.0.47

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.
Files changed (40) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +7 -7
  3. package/engine/agentlas-capabilities.cjs +3 -2
  4. package/engine/agentlas-core-harness.cjs +18 -0
  5. package/engine/agentlas-i18n.cjs +8 -8
  6. package/engine/agentlas-input.cjs +2 -2
  7. package/engine/agentlas-native-host.cjs +124 -11
  8. package/engine/agentlas-onboard.cjs +8 -3
  9. package/engine/agentlas-permissions.cjs +5 -1
  10. package/engine/agentlas-workforce.cjs +81 -24
  11. package/engine/agents/router.cjs +4 -2
  12. package/engine/architecture.data.json +6 -30
  13. package/engine/automation/daemon.cjs +1 -1
  14. package/engine/bootstrap-schema.sql +216 -191
  15. package/engine/browser/cdp.cjs +10 -4
  16. package/engine/cloud-assets/commands.cjs +1 -1
  17. package/engine/cloud-assets/package.cjs +161 -45
  18. package/engine/commands/context.cjs +14 -3
  19. package/engine/commands/doctor.cjs +7 -4
  20. package/engine/commands/graph.cjs +62 -64
  21. package/engine/commands/search.cjs +8 -3
  22. package/engine/core/desktop-core.cjs +39 -1
  23. package/engine/graph/interview.cjs +2 -11
  24. package/engine/graph/vocabulary.generated.cjs +1 -1
  25. package/engine/hephaestus/runtime.cjs +2 -6
  26. package/engine/project/memory-context.cjs +20 -7
  27. package/engine/project/seed.cjs +46 -31
  28. package/engine/project/state.cjs +8 -1
  29. package/engine/runtimes/auth-evidence.cjs +6 -0
  30. package/engine/runtimes/detect.cjs +1 -1
  31. package/engine/runtimes/resolve.cjs +27 -7
  32. package/engine/sessions/prompt.cjs +2 -2
  33. package/engine/ui/palette.cjs +1 -1
  34. package/engine/ui/repl.cjs +2 -2
  35. package/engine/ui/shell.cjs +108 -1
  36. package/engine/workforce/capture.cjs +52 -3
  37. package/engine/workforce/deps.cjs +2 -2
  38. package/engine/workforce/local-core-transport.cjs +13 -19
  39. package/package.json +1 -1
  40. package/engine/project/super-ontology-seed.json +0 -3288
@@ -1,6 +1,6 @@
1
- -- Agentlas first-run bootstrap schema (project-first Work contract)
2
- -- Source DB user_version=86. Desktop remains the migration authority.
3
- PRAGMA user_version=86;
1
+ -- Agentlas 실행 부트스트랩 스키마 (생성: 2026-08-12T07:38:56Z)
2
+ -- 소스 DB user_version=94 앱이 나중에 설치되면 여기서부터 마이그레이션한다.
3
+ PRAGMA user_version=94;
4
4
  CREATE TABLE active_runtime (
5
5
  id INTEGER PRIMARY KEY CHECK(id = 1),
6
6
  kind TEXT NOT NULL
@@ -21,21 +21,19 @@ CREATE TABLE projects (
21
21
  id TEXT PRIMARY KEY,
22
22
  name TEXT NOT NULL,
23
23
  description TEXT,
24
- system_prompt TEXT,
25
- agent_pool_json TEXT NOT NULL DEFAULT '[]',
26
- source_type TEXT NOT NULL DEFAULT 'local' CHECK(source_type IN ('local','github','sample')),
27
- source_ref TEXT,
24
+ default_agent_id TEXT,
25
+ context_note TEXT,
28
26
  created_at TEXT NOT NULL,
29
- updated_at TEXT NOT NULL,
30
- folder_path TEXT
27
+ updated_at TEXT NOT NULL, folder_path TEXT, system_prompt TEXT, agent_pool_json TEXT NOT NULL DEFAULT '[]', source_type TEXT NOT NULL DEFAULT 'local', source_ref TEXT,
28
+ FOREIGN KEY(default_agent_id) REFERENCES installed_agents(id) ON DELETE SET NULL
31
29
  );
32
30
  CREATE TABLE chats (
33
31
  id TEXT PRIMARY KEY,
34
32
  project_id TEXT,
35
33
  agent_id TEXT NOT NULL,
36
- title TEXT NOT NULL DEFAULT ' 채팅',
34
+ title TEXT NOT NULL DEFAULT 'New chat',
37
35
  created_at TEXT NOT NULL,
38
- updated_at TEXT NOT NULL, firm_id TEXT REFERENCES firms(id) ON DELETE SET NULL, archived_at TEXT, working_folder TEXT, kind TEXT NOT NULL DEFAULT 'user', parent_chat_id TEXT, used_at TEXT, continuous_mode INTEGER NOT NULL DEFAULT 0, swarm_mode INTEGER NOT NULL DEFAULT 0, last_viewed_at TEXT, origin_surface TEXT NOT NULL DEFAULT 'work', runtime_selection_json TEXT,
36
+ updated_at TEXT NOT NULL, firm_id TEXT REFERENCES firms(id) ON DELETE SET NULL, archived_at TEXT, working_folder TEXT, kind TEXT NOT NULL DEFAULT 'user', parent_chat_id TEXT, used_at TEXT, continuous_mode INTEGER NOT NULL DEFAULT 0, swarm_mode INTEGER NOT NULL DEFAULT 0, last_viewed_at TEXT, hired_agents TEXT, origin_surface TEXT NOT NULL DEFAULT 'work', runtime_selection_json TEXT, goal_id TEXT,
39
37
  FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE SET NULL,
40
38
  FOREIGN KEY(agent_id) REFERENCES installed_agents(id) ON DELETE CASCADE
41
39
  );
@@ -52,6 +50,18 @@ CREATE TABLE chat_messages (
52
50
  );
53
51
  CREATE INDEX idx_chat_messages_chat_created
54
52
  ON chat_messages(chat_id, created_at);
53
+ CREATE TABLE firms (
54
+ id TEXT PRIMARY KEY,
55
+ slug TEXT UNIQUE NOT NULL,
56
+ name TEXT NOT NULL,
57
+ tagline TEXT NOT NULL,
58
+ persona TEXT NOT NULL,
59
+ ceo_agent_id TEXT NOT NULL,
60
+ org_chart_json TEXT NOT NULL,
61
+ installed_at TEXT NOT NULL, name_en TEXT NOT NULL DEFAULT '', tagline_en TEXT NOT NULL DEFAULT '',
62
+ FOREIGN KEY(ceo_agent_id) REFERENCES installed_agents(id) ON DELETE RESTRICT
63
+ );
64
+ CREATE INDEX idx_firms_installed ON firms(installed_at DESC);
55
65
  CREATE INDEX idx_chats_firm_updated ON chats(firm_id, updated_at DESC);
56
66
  CREATE INDEX idx_chats_archived_updated ON chats(archived_at, updated_at DESC);
57
67
  CREATE TABLE mcp_servers (
@@ -118,20 +128,8 @@ CREATE TABLE automations (
118
128
  last_run_at TEXT,
119
129
  next_run_at TEXT,
120
130
  created_at TEXT NOT NULL
121
- , graph_json TEXT, schedule_json TEXT, timezone TEXT, end_at TEXT, max_runs INTEGER, run_count INTEGER NOT NULL DEFAULT 0, trigger_type TEXT NOT NULL DEFAULT 'schedule', trigger_json TEXT, claimed_at TEXT, lease_owner TEXT, tool_mode TEXT NOT NULL DEFAULT 'auto', hub_mode TEXT NOT NULL DEFAULT 'hub-allowed', execution_permission TEXT NOT NULL DEFAULT 'write' CHECK(execution_permission IN ('read','write')), target_version TEXT, runtime_selection_json TEXT, project_id TEXT REFERENCES projects(id) ON DELETE SET NULL);
131
+ , graph_json TEXT, goal TEXT, schedule_json TEXT, timezone TEXT, end_at TEXT, max_runs INTEGER, run_count INTEGER NOT NULL DEFAULT 0, trigger_type TEXT NOT NULL DEFAULT 'schedule', trigger_json TEXT, claimed_at TEXT, lease_owner TEXT, tool_mode TEXT NOT NULL DEFAULT 'auto', hub_mode TEXT NOT NULL DEFAULT 'hub-allowed', execution_permission TEXT NOT NULL DEFAULT 'write' CHECK(execution_permission IN ('read','write')), target_version TEXT, runtime_selection_json TEXT, project_id TEXT REFERENCES projects(id) ON DELETE SET NULL, goal_id TEXT, attention_cleared_at TEXT);
122
132
  CREATE INDEX idx_automations_due ON automations(enabled, next_run_at);
123
- CREATE TABLE automation_sessions (
124
- id TEXT PRIMARY KEY,
125
- automation_id TEXT NOT NULL,
126
- target_kind TEXT NOT NULL CHECK(target_kind IN ('host','agent','firm','hub')),
127
- target_id TEXT NOT NULL,
128
- ledger_chat_id TEXT NOT NULL UNIQUE REFERENCES chats(id) ON DELETE CASCADE,
129
- created_at TEXT NOT NULL,
130
- updated_at TEXT NOT NULL,
131
- UNIQUE(automation_id, target_kind, target_id)
132
- );
133
- CREATE INDEX idx_automation_sessions_owner
134
- ON automation_sessions(automation_id, updated_at DESC);
135
133
  CREATE TABLE agent_apps (
136
134
  id TEXT PRIMARY KEY,
137
135
  chat_id TEXT NOT NULL,
@@ -372,26 +370,6 @@ CREATE TABLE agent_runtime_overrides (
372
370
  );
373
371
  CREATE INDEX idx_agent_runtime_overrides_updated
374
372
  ON agent_runtime_overrides(updated_at DESC);
375
- CREATE TABLE persona_loop_runs (
376
- id TEXT PRIMARY KEY,
377
- automation_id TEXT NOT NULL,
378
- target_type TEXT NOT NULL CHECK(target_type IN ('agent','firm')),
379
- target_id TEXT NOT NULL,
380
- target_label TEXT NOT NULL,
381
- persona_label TEXT NOT NULL,
382
- cadence TEXT NOT NULL,
383
- status TEXT NOT NULL,
384
- current_step TEXT NOT NULL,
385
- started_at TEXT NOT NULL,
386
- updated_at TEXT NOT NULL,
387
- ends_at TEXT NOT NULL,
388
- transcript_json TEXT NOT NULL,
389
- FOREIGN KEY(automation_id) REFERENCES automations(id) ON DELETE CASCADE
390
- );
391
- CREATE INDEX idx_persona_loop_runs_updated
392
- ON persona_loop_runs(updated_at DESC);
393
- CREATE INDEX idx_persona_loop_runs_automation
394
- ON persona_loop_runs(automation_id);
395
373
  CREATE INDEX idx_chats_used_updated ON chats(used_at, updated_at DESC);
396
374
  CREATE TABLE run_history (
397
375
  id TEXT PRIMARY KEY,
@@ -401,23 +379,22 @@ CREATE TABLE run_history (
401
379
  status TEXT,
402
380
  skipped_count INTEGER DEFAULT 0,
403
381
  error TEXT
404
- );
382
+ , outcome TEXT, outcome_reason TEXT, acknowledged_at TEXT);
405
383
  CREATE INDEX idx_run_history_automation ON run_history(automation_id);
406
384
  CREATE TABLE automation_runs (
407
385
  id TEXT PRIMARY KEY,
408
386
  automation_id TEXT,
409
387
  started_at TEXT,
388
+ last_activity_at TEXT,
410
389
  status TEXT,
411
- node_states_json TEXT
412
- , last_activity_at TEXT, occurrence_id TEXT, graph_digest TEXT, checkpoint_json TEXT, resume_of_run_id TEXT);
390
+ node_states_json TEXT,
391
+ occurrence_id TEXT,
392
+ graph_digest TEXT,
393
+ checkpoint_json TEXT,
394
+ resume_of_run_id TEXT
395
+ , node_failures_json TEXT, resume_consumed_at TEXT);
413
396
  CREATE INDEX idx_automation_runs_auto
414
- ON automation_runs(automation_id, started_at);
415
- -- (제거됨 2026-08-06) agentlas_auto_cua_social_insert/update 트리거가 여기 있었다.
416
- -- 소셜 키워드 목록("twitter/인스타/댓글/게시/로그인"…)으로 tool_mode를 computer-use로
417
- -- 강제 되돌리던 DB 차원 단어목록 판정 — 코드의 단어목록을 LLM 판정으로 대체할 때
418
- -- 이 트리거만 살아남아, 코드 리뷰가 볼 수 없는 곳에서 toolMode 도출 규칙을 무효화했다
419
- -- (실측: UPDATE tool_mode='auto'가 같은 연결에서 즉시 되돌아왔다). 판정을 DB 트리거로
420
- -- 만들지 않는다 — 판정은 코드·게이트가 보는 곳에만 산다.
397
+ ON automation_runs(automation_id, started_at);
421
398
  CREATE TABLE agent_evolution_proposals (
422
399
  id TEXT PRIMARY KEY,
423
400
  agent_id TEXT NOT NULL,
@@ -482,32 +459,6 @@ CREATE INDEX idx_failure_events_run
482
459
  ON failure_events(run_id, ts DESC);
483
460
  CREATE INDEX idx_failure_events_automation
484
461
  ON failure_events(automation_id, ts DESC);
485
- CREATE TABLE telegram_bindings (
486
- id TEXT PRIMARY KEY,
487
- target_kind TEXT NOT NULL CHECK(target_kind IN ('agent','firm','group')),
488
- target_id TEXT NOT NULL,
489
- telegram_chat_id TEXT,
490
- telegram_chat_title TEXT,
491
- bot_user_id INTEGER,
492
- bot_username TEXT,
493
- bot_display_name TEXT,
494
- chat_session_id TEXT REFERENCES chats(id) ON DELETE SET NULL,
495
- status TEXT NOT NULL,
496
- enabled INTEGER NOT NULL DEFAULT 0,
497
- last_update_id INTEGER NOT NULL DEFAULT 0,
498
- last_error TEXT,
499
- last_test_at TEXT,
500
- created_at TEXT NOT NULL,
501
- updated_at TEXT NOT NULL
502
- , automation_report_enabled INTEGER NOT NULL DEFAULT 0, token_saved INTEGER NOT NULL DEFAULT 0, token_fingerprint TEXT);
503
- CREATE INDEX idx_telegram_bindings_target
504
- ON telegram_bindings(target_kind, target_id);
505
- CREATE INDEX idx_telegram_bindings_chat
506
- ON telegram_bindings(telegram_chat_id);
507
- CREATE INDEX idx_telegram_bindings_enabled
508
- ON telegram_bindings(enabled, status);
509
- CREATE INDEX idx_telegram_bindings_automation_report
510
- ON telegram_bindings(automation_report_enabled, enabled, telegram_chat_id);
511
462
  CREATE TABLE browser_sites (
512
463
  id TEXT PRIMARY KEY,
513
464
  site TEXT NOT NULL UNIQUE,
@@ -546,20 +497,6 @@ CREATE TABLE browser_action_logs (
546
497
  meta TEXT
547
498
  );
548
499
  CREATE INDEX idx_browser_logs_ts ON browser_action_logs(ts DESC);
549
- CREATE TABLE IF NOT EXISTS "firms" (
550
- id TEXT PRIMARY KEY,
551
- slug TEXT UNIQUE NOT NULL,
552
- name TEXT NOT NULL,
553
- name_en TEXT NOT NULL DEFAULT '',
554
- tagline TEXT NOT NULL,
555
- tagline_en TEXT NOT NULL DEFAULT '',
556
- persona TEXT NOT NULL,
557
- ceo_agent_id TEXT NOT NULL,
558
- org_chart_json TEXT NOT NULL,
559
- installed_at TEXT NOT NULL,
560
- FOREIGN KEY(ceo_agent_id) REFERENCES installed_agents(id) ON DELETE RESTRICT
561
- );
562
- CREATE INDEX idx_firms_installed ON firms(installed_at DESC);
563
500
  CREATE TABLE agent_asset_versions (
564
501
  agent_id TEXT PRIMARY KEY,
565
502
  version INTEGER NOT NULL,
@@ -605,10 +542,6 @@ CREATE INDEX idx_hub_agent_bookmarks_workspace_time
605
542
  ON hub_agent_bookmarks(workspace_id, bookmarked_at DESC);
606
543
  CREATE INDEX idx_hub_agent_bookmarks_outbox
607
544
  ON hub_agent_bookmarks(workspace_id, sync_state, bookmarked_at ASC);
608
- CREATE INDEX idx_hub_agent_bookmarks_time
609
- ON hub_agent_bookmarks(bookmarked_at DESC);
610
- CREATE INDEX idx_hub_agent_bookmarks_kind
611
- ON hub_agent_bookmarks(entity_kind, bookmarked_at DESC);
612
545
  CREATE TABLE experience_packs (
613
546
  id TEXT PRIMARY KEY,
614
547
  agent_id TEXT NOT NULL,
@@ -619,6 +552,11 @@ CREATE TABLE experience_packs (
619
552
  name TEXT NOT NULL,
620
553
  description TEXT NOT NULL DEFAULT '',
621
554
  base_package_hash TEXT,
555
+ -- 2축 좌표. 몸통(코어) 해시가 신원이고 부품 목록 해시는 실행 무결성이다.
556
+ -- axis_version 2 = 옛 한 축 기록, 3 = 두 축을 갖춘 기록. 상세는 REQUIRED_COLUMNS 주석.
557
+ axis_version INTEGER NOT NULL DEFAULT 2,
558
+ base_core_hash TEXT,
559
+ module_set_hash TEXT,
622
560
  status TEXT NOT NULL DEFAULT 'active'
623
561
  CHECK(status IN ('active','archived')),
624
562
  created_at TEXT NOT NULL,
@@ -647,7 +585,7 @@ CREATE TABLE experience_candidates (
647
585
  public_safe INTEGER NOT NULL DEFAULT 0 CHECK(public_safe IN (0,1)),
648
586
  created_at TEXT NOT NULL,
649
587
  updated_at TEXT NOT NULL,
650
- promoted_at TEXT, auto_managed INTEGER NOT NULL DEFAULT 0 CHECK(auto_managed IN (0,1)), embedding_model TEXT, embedding_adapter TEXT, embedding_model_sha256 TEXT, embedding_content_hash TEXT, embedding_dimensions INTEGER, embedding_json TEXT,
588
+ promoted_at TEXT, auto_managed INTEGER NOT NULL DEFAULT 0 CHECK(auto_managed IN (0,1)), embedding_model TEXT, embedding_adapter TEXT, embedding_model_sha256 TEXT, embedding_content_hash TEXT, embedding_dimensions INTEGER, embedding_json TEXT, axis_version INTEGER NOT NULL DEFAULT 2, base_core_hash TEXT, module_set_hash TEXT,
651
589
  FOREIGN KEY(pack_id) REFERENCES experience_packs(id) ON DELETE CASCADE,
652
590
  FOREIGN KEY(agent_id) REFERENCES installed_agents(id) ON DELETE CASCADE,
653
591
  UNIQUE(pack_id, source_memory_id)
@@ -790,10 +728,8 @@ CREATE TABLE experience_auto_intake_receipts (
790
728
  );
791
729
  CREATE INDEX idx_experience_auto_intake_agent_status
792
730
  ON experience_auto_intake_receipts(agent_id, status, created_at DESC);
793
- CREATE INDEX idx_run_events_agent_ts
794
- ON run_events(agent_id, ts DESC);
795
- CREATE INDEX idx_failure_events_agent_ts
796
- ON failure_events(agent_id, ts DESC);
731
+ CREATE INDEX idx_run_events_agent_ts ON run_events(agent_id, ts DESC);
732
+ CREATE INDEX idx_failure_events_agent_ts ON failure_events(agent_id, ts DESC);
797
733
  CREATE INDEX idx_run_events_agent_kind_ts
798
734
  ON run_events(agent_id, kind, ts DESC);
799
735
  CREATE TABLE installed_agent_hub_bindings (
@@ -1063,46 +999,8 @@ CREATE INDEX idx_memory_episodes_project_path_created
1063
999
  ON memory_episodes(project_path_hash, created_at DESC);
1064
1000
  CREATE INDEX idx_memory_episodes_agent_created
1065
1001
  ON memory_episodes(agent_id, created_at DESC);
1066
- CREATE TABLE activated_folder_identity (
1067
- path TEXT PRIMARY KEY,
1068
- identity_json TEXT NOT NULL,
1069
- captured_at TEXT NOT NULL
1070
- );
1071
1002
  CREATE INDEX idx_automation_runs_occurrence
1072
1003
  ON automation_runs(automation_id, occurrence_id, started_at);
1073
- CREATE TABLE automation_trigger_events (
1074
- id TEXT PRIMARY KEY,
1075
- automation_id TEXT NOT NULL,
1076
- trigger_kind TEXT NOT NULL CHECK(trigger_kind IN ('fs','chain','webhook','poll')),
1077
- dedupe_key TEXT NOT NULL,
1078
- payload_json TEXT NOT NULL,
1079
- status TEXT NOT NULL DEFAULT 'pending'
1080
- CHECK(status IN ('pending','claimed','delivered','parked')),
1081
- attempt_count INTEGER NOT NULL DEFAULT 0 CHECK(attempt_count >= 0),
1082
- next_attempt_at TEXT NOT NULL,
1083
- claim_owner TEXT,
1084
- claimed_until TEXT,
1085
- run_id TEXT,
1086
- run_outcome TEXT CHECK(run_outcome IS NULL OR run_outcome IN
1087
- ('ok','partial','error','skipped','blocked','needs_input')),
1088
- last_error TEXT,
1089
- created_at TEXT NOT NULL,
1090
- updated_at TEXT NOT NULL,
1091
- delivered_at TEXT,
1092
- FOREIGN KEY(automation_id) REFERENCES automations(id) ON DELETE CASCADE,
1093
- UNIQUE(automation_id, trigger_kind, dedupe_key),
1094
- CHECK(
1095
- (status = 'claimed' AND claim_owner IS NOT NULL AND claimed_until IS NOT NULL) OR
1096
- (status <> 'claimed' AND claim_owner IS NULL AND claimed_until IS NULL)
1097
- ),
1098
- CHECK((status = 'delivered' AND delivered_at IS NOT NULL) OR status <> 'delivered')
1099
- );
1100
- CREATE INDEX idx_automation_trigger_events_due
1101
- ON automation_trigger_events(status, next_attempt_at, created_at);
1102
- CREATE INDEX idx_automation_trigger_events_automation
1103
- ON automation_trigger_events(automation_id, status, created_at);
1104
- CREATE INDEX idx_automation_trigger_events_run
1105
- ON automation_trigger_events(run_id) WHERE run_id IS NOT NULL;
1106
1004
  CREATE TABLE tasks (
1107
1005
  id TEXT PRIMARY KEY,
1108
1006
  title TEXT NOT NULL DEFAULT '',
@@ -1132,56 +1030,6 @@ CREATE TABLE task_agent_participants (
1132
1030
  FOREIGN KEY(agent_id) REFERENCES installed_agents(id) ON DELETE SET NULL
1133
1031
  );
1134
1032
  CREATE INDEX idx_task_participants_agent ON task_agent_participants(agent_id);
1135
- CREATE TABLE terminal_memory_turn_intents (
1136
- turn_id TEXT PRIMARY KEY,
1137
- request_fingerprint TEXT NOT NULL,
1138
- context_key TEXT NOT NULL,
1139
- permission TEXT NOT NULL,
1140
- project_key TEXT,
1141
- owner_key TEXT,
1142
- owner_policy_json TEXT NOT NULL DEFAULT '{}',
1143
- status TEXT NOT NULL DEFAULT 'pending',
1144
- started_at TEXT NOT NULL,
1145
- completed_at TEXT
1146
- );
1147
- CREATE INDEX idx_terminal_memory_intent_pending
1148
- ON terminal_memory_turn_intents(request_fingerprint, status, started_at);
1149
- CREATE UNIQUE INDEX idx_terminal_memory_one_pending_request
1150
- ON terminal_memory_turn_intents(request_fingerprint)
1151
- WHERE status IN ('pending','curating');
1152
- CREATE TABLE terminal_memory_episode_receipts (
1153
- turn_id TEXT PRIMARY KEY,
1154
- ticket_json TEXT NOT NULL,
1155
- project_key TEXT,
1156
- created_at TEXT NOT NULL
1157
- );
1158
- CREATE TABLE terminal_memory_curator_decisions (
1159
- decision_id TEXT PRIMARY KEY,
1160
- turn_id TEXT NOT NULL,
1161
- candidate_id TEXT NOT NULL,
1162
- content_digest TEXT NOT NULL,
1163
- semantic_disposition TEXT NOT NULL,
1164
- semantic_scope TEXT NOT NULL,
1165
- final_disposition TEXT NOT NULL,
1166
- final_scope TEXT NOT NULL,
1167
- reason_codes_json TEXT NOT NULL DEFAULT '[]',
1168
- created_at TEXT NOT NULL
1169
- );
1170
- CREATE INDEX idx_terminal_memory_decisions_turn
1171
- ON terminal_memory_curator_decisions(turn_id);
1172
- CREATE TABLE terminal_memory_scope_timeline (
1173
- event_id TEXT PRIMARY KEY,
1174
- turn_id TEXT NOT NULL,
1175
- memory_id TEXT NOT NULL,
1176
- lane TEXT NOT NULL,
1177
- project_key TEXT,
1178
- owner_key TEXT,
1179
- created_at TEXT NOT NULL
1180
- );
1181
- CREATE INDEX idx_terminal_memory_timeline_project
1182
- ON terminal_memory_scope_timeline(project_key, lane, created_at);
1183
- CREATE INDEX idx_terminal_memory_timeline_owner
1184
- ON terminal_memory_scope_timeline(owner_key, lane, created_at);
1185
1033
  CREATE TABLE agent_usage (
1186
1034
  agent_key TEXT PRIMARY KEY,
1187
1035
  kind TEXT NOT NULL,
@@ -1289,3 +1137,180 @@ CREATE TABLE model_role_members (
1289
1137
  updated_at TEXT NOT NULL,
1290
1138
  PRIMARY KEY(role, position)
1291
1139
  );
1140
+ CREATE TABLE automation_sessions (
1141
+ id TEXT PRIMARY KEY,
1142
+ automation_id TEXT NOT NULL,
1143
+ target_kind TEXT NOT NULL CHECK(target_kind IN ('host','agent','firm','hub')),
1144
+ target_id TEXT NOT NULL,
1145
+ ledger_chat_id TEXT NOT NULL UNIQUE REFERENCES chats(id) ON DELETE CASCADE,
1146
+ created_at TEXT NOT NULL,
1147
+ updated_at TEXT NOT NULL,
1148
+ UNIQUE(automation_id, target_kind, target_id)
1149
+ );
1150
+ CREATE INDEX idx_automation_sessions_owner
1151
+ ON automation_sessions(automation_id, updated_at DESC);
1152
+ CREATE TABLE IF NOT EXISTS "telegram_bindings" (
1153
+ id TEXT PRIMARY KEY,
1154
+ target_kind TEXT NOT NULL CHECK(target_kind IN ('agent','firm','one')),
1155
+ target_id TEXT NOT NULL,
1156
+ telegram_chat_id TEXT,
1157
+ telegram_chat_title TEXT,
1158
+ bot_user_id INTEGER,
1159
+ bot_username TEXT,
1160
+ bot_display_name TEXT,
1161
+ chat_session_id TEXT REFERENCES chats(id) ON DELETE SET NULL,
1162
+ status TEXT NOT NULL,
1163
+ enabled INTEGER NOT NULL DEFAULT 0,
1164
+ last_update_id INTEGER NOT NULL DEFAULT 0,
1165
+ last_error TEXT,
1166
+ last_test_at TEXT,
1167
+ created_at TEXT NOT NULL,
1168
+ updated_at TEXT NOT NULL,
1169
+ automation_report_enabled INTEGER NOT NULL DEFAULT 0,
1170
+ token_saved INTEGER NOT NULL DEFAULT 0,
1171
+ token_fingerprint TEXT,
1172
+ designated_project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
1173
+ designated_graph_id TEXT,
1174
+ legacy_notice_at TEXT
1175
+ );
1176
+ CREATE INDEX idx_telegram_bindings_target
1177
+ ON telegram_bindings(target_kind, target_id);
1178
+ CREATE INDEX idx_telegram_bindings_chat
1179
+ ON telegram_bindings(telegram_chat_id);
1180
+ CREATE INDEX idx_telegram_bindings_enabled
1181
+ ON telegram_bindings(enabled, status);
1182
+ CREATE INDEX idx_telegram_bindings_automation_report
1183
+ ON telegram_bindings(automation_report_enabled, enabled, telegram_chat_id);
1184
+ CREATE UNIQUE INDEX idx_telegram_bindings_one_singleton
1185
+ ON telegram_bindings(target_kind) WHERE target_kind = 'one';
1186
+ CREATE TABLE automation_node_approvals (
1187
+ automation_id TEXT NOT NULL,
1188
+ occurrence_id TEXT NOT NULL,
1189
+ node_id TEXT NOT NULL,
1190
+ decision TEXT NOT NULL,
1191
+ decided_at TEXT NOT NULL,
1192
+ decided_by TEXT NOT NULL, scope TEXT NOT NULL DEFAULT 'once',
1193
+ PRIMARY KEY (automation_id, occurrence_id, node_id)
1194
+ );
1195
+ CREATE INDEX idx_automation_node_approvals_node ON automation_node_approvals(automation_id, node_id, decided_at);
1196
+ CREATE TABLE automation_eval_corrections (
1197
+ automation_id TEXT NOT NULL,
1198
+ node_id TEXT NOT NULL,
1199
+ subject_preview TEXT NOT NULL,
1200
+ corrected_verdict TEXT NOT NULL,
1201
+ note TEXT NOT NULL DEFAULT '',
1202
+ created_at TEXT NOT NULL,
1203
+ PRIMARY KEY (automation_id, node_id, created_at)
1204
+ );
1205
+ CREATE TABLE graph_run_journal (
1206
+ run_id TEXT NOT NULL,
1207
+ seq INTEGER NOT NULL,
1208
+ ts TEXT NOT NULL,
1209
+ kind TEXT NOT NULL,
1210
+ node_id TEXT,
1211
+ payload_json TEXT,
1212
+ PRIMARY KEY (run_id, seq)
1213
+ );
1214
+ CREATE INDEX idx_graph_run_journal_run ON graph_run_journal(run_id, seq);
1215
+ CREATE TABLE automation_graph_versions (
1216
+ id TEXT PRIMARY KEY,
1217
+ automation_id TEXT NOT NULL,
1218
+ saved_at TEXT NOT NULL,
1219
+ note TEXT,
1220
+ node_count INTEGER NOT NULL DEFAULT 0,
1221
+ graph_json TEXT NOT NULL
1222
+ );
1223
+ CREATE INDEX idx_automation_graph_versions ON automation_graph_versions(automation_id, saved_at DESC);
1224
+ CREATE TABLE automation_run_inputs (
1225
+ id TEXT PRIMARY KEY,
1226
+ automation_id TEXT NOT NULL,
1227
+ payload_json TEXT NOT NULL,
1228
+ requested_by TEXT NOT NULL,
1229
+ created_at TEXT NOT NULL,
1230
+ consumed_at TEXT,
1231
+ consumed_run_id TEXT
1232
+ );
1233
+ CREATE INDEX idx_automation_run_inputs_pending ON automation_run_inputs(automation_id, consumed_at, created_at);
1234
+ CREATE TABLE automation_approval_waits (
1235
+ automation_id TEXT NOT NULL,
1236
+ node_id TEXT NOT NULL,
1237
+ first_requested_at TEXT NOT NULL,
1238
+ PRIMARY KEY (automation_id, node_id)
1239
+ );
1240
+ CREATE TABLE automation_trigger_events (
1241
+ id TEXT PRIMARY KEY,
1242
+ automation_id TEXT NOT NULL,
1243
+ trigger_kind TEXT NOT NULL CHECK(trigger_kind IN ('fs','chain','webhook','poll','command')),
1244
+ dedupe_key TEXT NOT NULL,
1245
+ payload_json TEXT NOT NULL,
1246
+ status TEXT NOT NULL DEFAULT 'pending'
1247
+ CHECK(status IN ('pending','claimed','delivered','parked')),
1248
+ attempt_count INTEGER NOT NULL DEFAULT 0 CHECK(attempt_count >= 0),
1249
+ next_attempt_at TEXT NOT NULL,
1250
+ claim_owner TEXT,
1251
+ claimed_until TEXT,
1252
+ run_id TEXT,
1253
+ run_outcome TEXT CHECK(run_outcome IS NULL OR run_outcome IN
1254
+ ('ok','partial','error','skipped','blocked','needs_input')),
1255
+ last_error TEXT,
1256
+ created_at TEXT NOT NULL,
1257
+ updated_at TEXT NOT NULL,
1258
+ delivered_at TEXT,
1259
+ FOREIGN KEY(automation_id) REFERENCES automations(id) ON DELETE CASCADE,
1260
+ UNIQUE(automation_id, trigger_kind, dedupe_key),
1261
+ CHECK(
1262
+ (status = 'claimed' AND claim_owner IS NOT NULL AND claimed_until IS NOT NULL) OR
1263
+ (status <> 'claimed' AND claim_owner IS NULL AND claimed_until IS NULL)
1264
+ ),
1265
+ CHECK((status = 'delivered' AND delivered_at IS NOT NULL) OR status <> 'delivered')
1266
+ );
1267
+ CREATE INDEX idx_automation_trigger_events_due
1268
+ ON automation_trigger_events(status, next_attempt_at, created_at);
1269
+ CREATE INDEX idx_automation_trigger_events_automation
1270
+ ON automation_trigger_events(automation_id, status, created_at);
1271
+ CREATE INDEX idx_automation_trigger_events_run
1272
+ ON automation_trigger_events(run_id) WHERE run_id IS NOT NULL;
1273
+ CREATE INDEX idx_run_events_chat_kind_ts
1274
+ ON run_events(chat_id, kind, ts DESC);
1275
+ CREATE INDEX idx_experience_packs_core_axis
1276
+ ON experience_packs(agent_id, project_scope_key, environment_key, base_core_hash);
1277
+ CREATE TABLE judgment_verdicts (
1278
+ kind TEXT NOT NULL,
1279
+ signature TEXT NOT NULL,
1280
+ verdict TEXT NOT NULL,
1281
+ confidence REAL NOT NULL DEFAULT 0,
1282
+ reason TEXT NOT NULL DEFAULT '',
1283
+ created_at TEXT NOT NULL,
1284
+ last_hit_at TEXT NOT NULL,
1285
+ hits INTEGER NOT NULL DEFAULT 1,
1286
+ PRIMARY KEY (kind, signature)
1287
+ );
1288
+ CREATE INDEX idx_judgment_verdicts_recency ON judgment_verdicts(last_hit_at);
1289
+ CREATE TABLE activated_folder_identity (
1290
+ path TEXT PRIMARY KEY,
1291
+ identity_json TEXT NOT NULL,
1292
+ captured_at TEXT NOT NULL
1293
+ );
1294
+ CREATE TABLE one_artifact_bindings (
1295
+ id TEXT PRIMARY KEY,
1296
+ task_id TEXT NOT NULL,
1297
+ task_version INTEGER NOT NULL,
1298
+ bound_task_version INTEGER NOT NULL,
1299
+ chat_id TEXT NOT NULL,
1300
+ run_id TEXT NOT NULL,
1301
+ manifest_id TEXT NOT NULL,
1302
+ artifact_ref TEXT NOT NULL,
1303
+ source_path TEXT NOT NULL,
1304
+ kind TEXT NOT NULL,
1305
+ mime_type TEXT NOT NULL,
1306
+ size_bytes INTEGER NOT NULL,
1307
+ file_dev TEXT NOT NULL,
1308
+ file_ino TEXT NOT NULL,
1309
+ file_mtime_ns TEXT NOT NULL,
1310
+ file_ctime_ns TEXT NOT NULL,
1311
+ sha256 TEXT NOT NULL,
1312
+ created_at TEXT NOT NULL,
1313
+ UNIQUE(task_id, chat_id, run_id, manifest_id, artifact_ref)
1314
+ );
1315
+ CREATE INDEX idx_one_artifact_binding_exact
1316
+ ON one_artifact_bindings(task_id, chat_id, run_id, manifest_id, artifact_ref);
@@ -21,9 +21,9 @@ const http = require("node:http");
21
21
 
22
22
  const DEFAULT_PORT = Number(process.env.AGENTLAS_CDP_PORT || 9222);
23
23
 
24
- function httpJson(port, path, { timeout = 3000 } = {}) {
24
+ function httpJson(port, path, { timeout = 3000, method = "GET" } = {}) {
25
25
  return new Promise((resolve, reject) => {
26
- const req = http.get({ host: "127.0.0.1", port, path, timeout }, (res) => {
26
+ const req = http.request({ host: "127.0.0.1", port, path, timeout, method }, (res) => {
27
27
  let body = "";
28
28
  res.on("data", (d) => { body += d; });
29
29
  res.on("end", () => {
@@ -32,12 +32,18 @@ function httpJson(port, path, { timeout = 3000 } = {}) {
32
32
  });
33
33
  req.on("error", reject);
34
34
  req.on("timeout", () => { req.destroy(); reject(new Error(`CDP ${path} timed out`)); });
35
+ req.end();
35
36
  });
36
37
  }
37
38
 
38
39
  /** 9222 가 살아있나(Agentlas 전용 Chrome). */
39
40
  async function cdpReady(port = DEFAULT_PORT) {
40
- try { await httpJson(port, "/json/version"); return true; } catch { return false; }
41
+ try {
42
+ const version = await httpJson(port, "/json/version");
43
+ if (!version || typeof version !== "object" || typeof version.webSocketDebuggerUrl !== "string") return false;
44
+ const targets = await httpJson(port, "/json");
45
+ return Array.isArray(targets);
46
+ } catch { return false; }
41
47
  }
42
48
 
43
49
  /** 조종할 page 타겟 하나를 고른다(없으면 새로 연다). 반환: webSocketDebuggerUrl. */
@@ -46,7 +52,7 @@ async function pickPageTarget(port = DEFAULT_PORT) {
46
52
  let page = (Array.isArray(targets) ? targets : []).find((t) => t.type === "page" && t.webSocketDebuggerUrl);
47
53
  if (!page) {
48
54
  // 새 탭을 연다(DevTools HTTP: PUT /json/new).
49
- page = await httpJson(port, "/json/new?about:blank");
55
+ page = await httpJson(port, "/json/new?about:blank", { method: "PUT" });
50
56
  }
51
57
  if (!page || !page.webSocketDebuggerUrl) throw new Error("no CDP page target available");
52
58
  return page.webSocketDebuggerUrl;
@@ -282,7 +282,7 @@ async function runCloud(ctx, args) {
282
282
  const limit = Math.max(1, Math.min(30, Number(flags.limit) || 10));
283
283
  let result;
284
284
  try {
285
- result = await callHubTool("marketplace.search_agents", { q: query, query, limit });
285
+ result = await callHubTool("marketplace.search_agents", { q: query, limit });
286
286
  } catch (e) {
287
287
  ctx.err(e instanceof HubError ? e.message : `Marketplace connection failed: ${(e && e.message) || e}`);
288
288
  return 1;