@shepai/cli 1.111.0 → 1.112.0-pr309.afbf5cb
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/packages/core/src/infrastructure/persistence/sqlite/legacy-migrations.d.ts +27 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/legacy-migrations.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/legacy-migrations.js +540 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.d.ts +13 -7
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.js +94 -545
- package/dist/packages/core/src/infrastructure/persistence/sqlite/sqlite-migration-storage.d.ts +59 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/sqlite-migration-storage.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/sqlite-migration-storage.js +98 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.d.ts +5 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.js +118 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.stories.d.ts +18 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.stories.js +88 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.js +10 -2
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.d.ts +5 -3
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.js +92 -9
- package/dist/src/presentation/web/lib/parse-log-line.d.ts +51 -0
- package/dist/src/presentation/web/lib/parse-log-line.d.ts.map +1 -0
- package/dist/src/presentation/web/lib/parse-log-line.js +132 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +3 -3
- package/web/.next/required-server-files.json +3 -3
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +20 -20
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +18 -18
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +20 -20
- package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +18 -18
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +18 -18
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
- package/web/.next/server/app/api/cli-upgrade/route.js +2 -2
- package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +5 -5
- package/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/skills/page.js.nft.json +1 -1
- package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__d2c18946._.js +2 -2
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__039967e3._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__039967e3._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__07a39ff2._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2773312c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2773312c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b1e68e34._.js +3 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__d91fdd51._.js.map → [root-of-the-server]__b1e68e34._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__cbd8062c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__cbd8062c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e70c5627._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e70c5627._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_2649c1af._.js → _1222306e._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_2649c1af._.js.map → _1222306e._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_4474f9f3._.js → _4a4a2439._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_4474f9f3._.js.map → _4a4a2439._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_8dacd1e7._.js +1 -1
- package/web/.next/server/chunks/ssr/_8dacd1e7._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_ba9c581b._.js → _c4a42f23._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_ba9c581b._.js.map → _c4a42f23._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_888633e1.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_888633e1.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ce7cbc3c._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_ce7cbc3c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_e2604413._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_e2604413._.js.map +1 -1
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +31 -31
- package/web/.next/static/chunks/{185203c3444a4da7.js → 15e74d2df9f57109.js} +2 -2
- package/web/.next/static/chunks/{6d2a5b3e881c75a8.js → 1f3c7bc887739ba8.js} +1 -1
- package/web/.next/static/chunks/4231e7dc69e82f22.css +1 -0
- package/web/.next/static/chunks/44dc9b173486e5e3.js +1 -0
- package/web/.next/static/chunks/{dd15e70af64f5dd0.js → 557089320d21f13c.js} +1 -1
- package/web/.next/static/chunks/{5f52d11e6182396e.js → 72bece914300fb60.js} +1 -1
- package/web/.next/static/chunks/{4e2530a36f28dec7.js → 7ec52f2e58c8a8da.js} +1 -1
- package/web/.next/static/chunks/{cbfa943160cc5f90.js → 84eccb62ced72e3c.js} +1 -1
- package/web/.next/static/chunks/{487babfd13611736.js → 98119860f5aaeb55.js} +1 -1
- package/web/.next/static/chunks/b1f3c0e8e9872ef8.js +1 -0
- package/web/.next/static/chunks/{279db4719a31b985.js → c6d6d8f134385460.js} +1 -1
- package/web/.next/static/chunks/{b27c0bbd1de96d37.js → f7078ad2ada6de3f.js} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d91fdd51._.js +0 -3
- package/web/.next/static/chunks/07b853e29af1e5f2.js +0 -1
- package/web/.next/static/chunks/464557a2dc1fe286.js +0 -1
- package/web/.next/static/chunks/5558a658fa82a01f.css +0 -1
- /package/web/.next/static/{4LIlcvj7VQahrcSQtqQlm → FuSsGPDsyoIxo9siqXUUj}/_buildManifest.js +0 -0
- /package/web/.next/static/{4LIlcvj7VQahrcSQtqQlm → FuSsGPDsyoIxo9siqXUUj}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{4LIlcvj7VQahrcSQtqQlm → FuSsGPDsyoIxo9siqXUUj}/_ssgManifest.js +0 -0
package/dist/packages/core/src/infrastructure/persistence/sqlite/sqlite-migration-storage.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom umzug storage adapter for better-sqlite3.
|
|
3
|
+
*
|
|
4
|
+
* Wraps better-sqlite3's synchronous API in async methods to satisfy
|
|
5
|
+
* umzug's UmzugStorage interface. Manages the `umzug_migrations` tracking
|
|
6
|
+
* table with columns: name (TEXT PK) and created_at (TEXT NOT NULL).
|
|
7
|
+
*
|
|
8
|
+
* Includes a bootstrap seeder that auto-detects existing databases
|
|
9
|
+
* (PRAGMA user_version > 0 with empty umzug_migrations table) and seeds
|
|
10
|
+
* migration records for versions 1 through user_version.
|
|
11
|
+
*/
|
|
12
|
+
import type Database from 'better-sqlite3';
|
|
13
|
+
import type { UmzugStorage, MigrationParams } from 'umzug';
|
|
14
|
+
/**
|
|
15
|
+
* SQLite-backed migration storage for umzug.
|
|
16
|
+
*
|
|
17
|
+
* Tracks which migrations have been applied in a `umzug_migrations` table
|
|
18
|
+
* within the same SQLite database as the application data.
|
|
19
|
+
*/
|
|
20
|
+
export declare class SQLiteMigrationStorage implements UmzugStorage<Database.Database> {
|
|
21
|
+
private readonly db;
|
|
22
|
+
/**
|
|
23
|
+
* @param db - The better-sqlite3 database instance.
|
|
24
|
+
* @param legacyMigrationNames - Ordered list of legacy migration names (e.g.,
|
|
25
|
+
* ['001-create-settings-table', '002-add-agent-config', ...]). When provided,
|
|
26
|
+
* the constructor checks if this is an existing database transitioning from
|
|
27
|
+
* PRAGMA user_version tracking and seeds the umzug_migrations table accordingly.
|
|
28
|
+
*/
|
|
29
|
+
constructor(db: Database.Database, legacyMigrationNames?: string[]);
|
|
30
|
+
/**
|
|
31
|
+
* Returns the names of all executed migrations, sorted lexicographically.
|
|
32
|
+
*/
|
|
33
|
+
executed(_meta: Pick<MigrationParams<Database.Database>, 'context'>): Promise<string[]>;
|
|
34
|
+
/**
|
|
35
|
+
* Records a migration as executed.
|
|
36
|
+
*/
|
|
37
|
+
logMigration(params: MigrationParams<Database.Database>): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Removes a migration record (marks it as pending).
|
|
40
|
+
*/
|
|
41
|
+
unlogMigration(params: MigrationParams<Database.Database>): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Creates the umzug_migrations table if it does not exist.
|
|
44
|
+
*/
|
|
45
|
+
private ensureTable;
|
|
46
|
+
/**
|
|
47
|
+
* Auto-detects existing databases that used PRAGMA user_version tracking
|
|
48
|
+
* and seeds the umzug_migrations table so umzug does not re-apply them.
|
|
49
|
+
*
|
|
50
|
+
* Conditions for bootstrap:
|
|
51
|
+
* - PRAGMA user_version > 0 (database has been migrated before)
|
|
52
|
+
* - umzug_migrations table is empty (not yet transitioned to umzug)
|
|
53
|
+
*
|
|
54
|
+
* When both conditions are met, inserts records for migrations 1 through
|
|
55
|
+
* user_version using the provided legacy migration names.
|
|
56
|
+
*/
|
|
57
|
+
private bootstrapLegacyMigrations;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=sqlite-migration-storage.d.ts.map
|
package/dist/packages/core/src/infrastructure/persistence/sqlite/sqlite-migration-storage.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-migration-storage.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/persistence/sqlite/sqlite-migration-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAE3D;;;;;GAKG;AACH,qBAAa,sBAAuB,YAAW,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAC5E,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;IAEvC;;;;;;OAMG;gBACS,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC,EAAE,MAAM,EAAE;IAQlE;;OAEG;IACG,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAO7F;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7E;;OAEG;IACG,cAAc,CAAC,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/E;;OAEG;IACH,OAAO,CAAC,WAAW;IASnB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,yBAAyB;CA+BlC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom umzug storage adapter for better-sqlite3.
|
|
3
|
+
*
|
|
4
|
+
* Wraps better-sqlite3's synchronous API in async methods to satisfy
|
|
5
|
+
* umzug's UmzugStorage interface. Manages the `umzug_migrations` tracking
|
|
6
|
+
* table with columns: name (TEXT PK) and created_at (TEXT NOT NULL).
|
|
7
|
+
*
|
|
8
|
+
* Includes a bootstrap seeder that auto-detects existing databases
|
|
9
|
+
* (PRAGMA user_version > 0 with empty umzug_migrations table) and seeds
|
|
10
|
+
* migration records for versions 1 through user_version.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* SQLite-backed migration storage for umzug.
|
|
14
|
+
*
|
|
15
|
+
* Tracks which migrations have been applied in a `umzug_migrations` table
|
|
16
|
+
* within the same SQLite database as the application data.
|
|
17
|
+
*/
|
|
18
|
+
export class SQLiteMigrationStorage {
|
|
19
|
+
db;
|
|
20
|
+
/**
|
|
21
|
+
* @param db - The better-sqlite3 database instance.
|
|
22
|
+
* @param legacyMigrationNames - Ordered list of legacy migration names (e.g.,
|
|
23
|
+
* ['001-create-settings-table', '002-add-agent-config', ...]). When provided,
|
|
24
|
+
* the constructor checks if this is an existing database transitioning from
|
|
25
|
+
* PRAGMA user_version tracking and seeds the umzug_migrations table accordingly.
|
|
26
|
+
*/
|
|
27
|
+
constructor(db, legacyMigrationNames) {
|
|
28
|
+
this.db = db;
|
|
29
|
+
this.ensureTable();
|
|
30
|
+
if (legacyMigrationNames && legacyMigrationNames.length > 0) {
|
|
31
|
+
this.bootstrapLegacyMigrations(legacyMigrationNames);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Returns the names of all executed migrations, sorted lexicographically.
|
|
36
|
+
*/
|
|
37
|
+
async executed(_meta) {
|
|
38
|
+
const rows = this.db.prepare('SELECT name FROM umzug_migrations ORDER BY name').all();
|
|
39
|
+
return rows.map((r) => r.name);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Records a migration as executed.
|
|
43
|
+
*/
|
|
44
|
+
async logMigration(params) {
|
|
45
|
+
this.db
|
|
46
|
+
.prepare('INSERT INTO umzug_migrations (name, created_at) VALUES (?, ?)')
|
|
47
|
+
.run(params.name, new Date().toISOString());
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Removes a migration record (marks it as pending).
|
|
51
|
+
*/
|
|
52
|
+
async unlogMigration(params) {
|
|
53
|
+
this.db.prepare('DELETE FROM umzug_migrations WHERE name = ?').run(params.name);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Creates the umzug_migrations table if it does not exist.
|
|
57
|
+
*/
|
|
58
|
+
ensureTable() {
|
|
59
|
+
this.db.exec(`
|
|
60
|
+
CREATE TABLE IF NOT EXISTS umzug_migrations (
|
|
61
|
+
name TEXT PRIMARY KEY NOT NULL,
|
|
62
|
+
created_at TEXT NOT NULL
|
|
63
|
+
)
|
|
64
|
+
`);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Auto-detects existing databases that used PRAGMA user_version tracking
|
|
68
|
+
* and seeds the umzug_migrations table so umzug does not re-apply them.
|
|
69
|
+
*
|
|
70
|
+
* Conditions for bootstrap:
|
|
71
|
+
* - PRAGMA user_version > 0 (database has been migrated before)
|
|
72
|
+
* - umzug_migrations table is empty (not yet transitioned to umzug)
|
|
73
|
+
*
|
|
74
|
+
* When both conditions are met, inserts records for migrations 1 through
|
|
75
|
+
* user_version using the provided legacy migration names.
|
|
76
|
+
*/
|
|
77
|
+
bootstrapLegacyMigrations(legacyMigrationNames) {
|
|
78
|
+
const result = this.db.prepare('PRAGMA user_version').get();
|
|
79
|
+
const userVersion = result.user_version;
|
|
80
|
+
if (userVersion <= 0) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const count = this.db.prepare('SELECT COUNT(*) as count FROM umzug_migrations').get();
|
|
84
|
+
if (count.count > 0) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Seed records for migrations 1 through user_version
|
|
88
|
+
const now = new Date().toISOString();
|
|
89
|
+
const insert = this.db.prepare('INSERT INTO umzug_migrations (name, created_at) VALUES (?, ?)');
|
|
90
|
+
const seedAll = this.db.transaction(() => {
|
|
91
|
+
const count = Math.min(userVersion, legacyMigrationNames.length);
|
|
92
|
+
for (let i = 0; i < count; i++) {
|
|
93
|
+
insert.run(legacyMigrationNames[i], now);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
seedAll();
|
|
97
|
+
}
|
|
98
|
+
}
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-log-viewer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.tsx"],"names":[],"mappings":"AAyBA,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,EAAE,mBAAmB,kDAY9D"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { FileText, Terminal, MessageSquare, CheckCircle2, Coins, Server, FileCode, AlertCircle, } from 'lucide-react';
|
|
5
|
+
import { parseLogContent, parseToolCall, parseResultMessage, parseTokensMessage, } from '../../../lib/parse-log-line.js';
|
|
6
|
+
export function EventLogViewer({ content }) {
|
|
7
|
+
const lines = useMemo(() => parseLogContent(content), [content]);
|
|
8
|
+
if (lines.length === 0)
|
|
9
|
+
return null;
|
|
10
|
+
return (_jsx("div", { className: "flex flex-col", children: lines.map((line) => (_jsx(LogLineRow, { line: line }, line.id))) }));
|
|
11
|
+
}
|
|
12
|
+
/* ---------------------------------------------------------------------------
|
|
13
|
+
* Line router
|
|
14
|
+
* ------------------------------------------------------------------------- */
|
|
15
|
+
function LogLineRow({ line }) {
|
|
16
|
+
switch (line.tag) {
|
|
17
|
+
case 'tool':
|
|
18
|
+
return _jsx(ToolCallRow, { line: line });
|
|
19
|
+
case 'text':
|
|
20
|
+
return _jsx(TextRow, { line: line });
|
|
21
|
+
case 'result':
|
|
22
|
+
return _jsx(ResultRow, { line: line });
|
|
23
|
+
case 'tokens':
|
|
24
|
+
return _jsx(TokensRow, { line: line });
|
|
25
|
+
case 'error':
|
|
26
|
+
return _jsx(ErrorRow, { line: line });
|
|
27
|
+
case 'worker':
|
|
28
|
+
return _jsx(WorkerRow, { line: line });
|
|
29
|
+
case 'info':
|
|
30
|
+
return _jsx(InfoRow, { line: line });
|
|
31
|
+
case 'raw':
|
|
32
|
+
default:
|
|
33
|
+
return _jsx(RawRow, { line: line });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/* ---------------------------------------------------------------------------
|
|
37
|
+
* Shared helpers
|
|
38
|
+
* ------------------------------------------------------------------------- */
|
|
39
|
+
function Timestamp({ value }) {
|
|
40
|
+
if (!value)
|
|
41
|
+
return null;
|
|
42
|
+
const time = value.replace(/^.*T/, '').replace('Z', '');
|
|
43
|
+
return (_jsx("span", { className: "text-muted-foreground/60 w-20 shrink-0 font-mono text-[10px]", children: time }));
|
|
44
|
+
}
|
|
45
|
+
function PhaseBadge({ phase }) {
|
|
46
|
+
if (!phase)
|
|
47
|
+
return null;
|
|
48
|
+
return (_jsx("span", { className: "bg-muted text-muted-foreground shrink-0 rounded px-1.5 py-0.5 font-mono text-[10px] font-medium", children: phase }));
|
|
49
|
+
}
|
|
50
|
+
/* ---------------------------------------------------------------------------
|
|
51
|
+
* Event-specific rows
|
|
52
|
+
* ------------------------------------------------------------------------- */
|
|
53
|
+
function ToolCallRow({ line }) {
|
|
54
|
+
const { toolName, args } = parseToolCall(line.message);
|
|
55
|
+
// Try to extract a key detail from args for common tools
|
|
56
|
+
const detail = getToolDetail(toolName, args);
|
|
57
|
+
return (_jsxs("div", { className: "hover:bg-muted/50 flex items-start gap-2 border-b border-transparent px-3 py-1.5 transition-colors", children: [_jsx(Timestamp, { value: line.timestamp }), _jsx(PhaseBadge, { phase: line.phase }), _jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-1.5", children: [_jsx(ToolIcon, { toolName: toolName }), _jsx("span", { className: "text-xs font-semibold text-violet-600 dark:text-violet-400", children: toolName }), detail ? (_jsx("span", { className: "text-muted-foreground min-w-0 truncate font-mono text-xs", children: detail })) : null] })] }));
|
|
58
|
+
}
|
|
59
|
+
function ToolIcon({ toolName }) {
|
|
60
|
+
const lower = toolName.toLowerCase();
|
|
61
|
+
if (lower === 'bash')
|
|
62
|
+
return _jsx(Terminal, { className: "mt-0.5 h-3 w-3 shrink-0 text-violet-500" });
|
|
63
|
+
if (lower === 'read' || lower === 'glob' || lower === 'grep')
|
|
64
|
+
return _jsx(FileText, { className: "mt-0.5 h-3 w-3 shrink-0 text-violet-500" });
|
|
65
|
+
if (lower === 'write' || lower === 'edit')
|
|
66
|
+
return _jsx(FileCode, { className: "mt-0.5 h-3 w-3 shrink-0 text-violet-500" });
|
|
67
|
+
return _jsx(Terminal, { className: "mt-0.5 h-3 w-3 shrink-0 text-violet-500" });
|
|
68
|
+
}
|
|
69
|
+
function getToolDetail(toolName, args) {
|
|
70
|
+
try {
|
|
71
|
+
const parsed = JSON.parse(args);
|
|
72
|
+
if (toolName === 'Read' && parsed.file_path)
|
|
73
|
+
return parsed.file_path;
|
|
74
|
+
if (toolName === 'Write' && parsed.file_path)
|
|
75
|
+
return parsed.file_path;
|
|
76
|
+
if (toolName === 'Edit' && parsed.file_path)
|
|
77
|
+
return parsed.file_path;
|
|
78
|
+
if (toolName === 'Glob' && parsed.pattern)
|
|
79
|
+
return parsed.pattern;
|
|
80
|
+
if (toolName === 'Grep' && parsed.pattern)
|
|
81
|
+
return parsed.pattern;
|
|
82
|
+
if (toolName === 'Bash' && parsed.command) {
|
|
83
|
+
const cmd = parsed.command;
|
|
84
|
+
return cmd.length > 80 ? `${cmd.slice(0, 80)}...` : cmd;
|
|
85
|
+
}
|
|
86
|
+
if (toolName === 'Task' && parsed.description)
|
|
87
|
+
return parsed.description;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// Not JSON — show truncated raw args
|
|
91
|
+
if (args.length > 0)
|
|
92
|
+
return args.length > 80 ? `${args.slice(0, 80)}...` : args;
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
function TextRow({ line }) {
|
|
97
|
+
return (_jsxs("div", { className: "hover:bg-muted/50 flex items-start gap-2 px-3 py-1.5 transition-colors", children: [_jsx(Timestamp, { value: line.timestamp }), _jsx(PhaseBadge, { phase: line.phase }), _jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-1.5", children: [_jsx(MessageSquare, { className: "mt-0.5 h-3 w-3 shrink-0 text-blue-500" }), _jsx("span", { className: "text-foreground/80 min-w-0 text-xs leading-relaxed", children: line.message })] })] }));
|
|
98
|
+
}
|
|
99
|
+
function ResultRow({ line }) {
|
|
100
|
+
const { chars } = parseResultMessage(line.message);
|
|
101
|
+
return (_jsxs("div", { className: "hover:bg-muted/50 flex items-start gap-2 px-3 py-1.5 transition-colors", children: [_jsx(Timestamp, { value: line.timestamp }), _jsx(PhaseBadge, { phase: line.phase }), _jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-1.5", children: [_jsx(CheckCircle2, { className: "mt-0.5 h-3 w-3 shrink-0 text-emerald-500" }), _jsxs("span", { className: "text-xs font-medium text-emerald-600 dark:text-emerald-400", children: ["Result: ", chars.toLocaleString(), " chars"] })] })] }));
|
|
102
|
+
}
|
|
103
|
+
function TokensRow({ line }) {
|
|
104
|
+
const { inputTokens, outputTokens } = parseTokensMessage(line.message);
|
|
105
|
+
return (_jsxs("div", { className: "hover:bg-muted/50 flex items-start gap-2 px-3 py-1.5 transition-colors", children: [_jsx(Timestamp, { value: line.timestamp }), _jsx(PhaseBadge, { phase: line.phase }), _jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-1.5", children: [_jsx(Coins, { className: "mt-0.5 h-3 w-3 shrink-0 text-amber-500" }), _jsxs("span", { className: "text-muted-foreground text-xs", children: [_jsx("span", { className: "text-amber-600 dark:text-amber-400", children: inputTokens.toLocaleString() }), ' in / ', _jsx("span", { className: "text-amber-600 dark:text-amber-400", children: outputTokens.toLocaleString() }), ' out'] })] })] }));
|
|
106
|
+
}
|
|
107
|
+
function ErrorRow({ line }) {
|
|
108
|
+
return (_jsxs("div", { className: "flex items-start gap-2 border-l-2 border-red-500 bg-red-50/50 px-3 py-1.5 transition-colors hover:bg-red-50 dark:bg-red-950/20 dark:hover:bg-red-950/30", children: [_jsx(Timestamp, { value: line.timestamp }), _jsx(PhaseBadge, { phase: line.phase }), _jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-1.5", children: [_jsx(AlertCircle, { className: "mt-0.5 h-3 w-3 shrink-0 text-red-500" }), _jsx("span", { className: "min-w-0 text-xs font-medium text-red-600 dark:text-red-400", children: line.message })] })] }));
|
|
109
|
+
}
|
|
110
|
+
function WorkerRow({ line }) {
|
|
111
|
+
return (_jsxs("div", { className: "hover:bg-muted/50 flex items-start gap-2 bg-zinc-50 px-3 py-1.5 transition-colors dark:bg-zinc-900/50", children: [_jsx(Timestamp, { value: line.timestamp }), _jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-1.5", children: [_jsx(Server, { className: "mt-0.5 h-3 w-3 shrink-0 text-zinc-500" }), _jsx("span", { className: "text-muted-foreground text-xs font-medium", children: line.message })] })] }));
|
|
112
|
+
}
|
|
113
|
+
function InfoRow({ line }) {
|
|
114
|
+
return (_jsxs("div", { className: "hover:bg-muted/50 flex items-start gap-2 px-3 py-1.5 transition-colors", children: [_jsx(Timestamp, { value: line.timestamp }), _jsx(PhaseBadge, { phase: line.phase }), _jsx("span", { className: "text-muted-foreground min-w-0 text-xs", children: line.message })] }));
|
|
115
|
+
}
|
|
116
|
+
function RawRow({ line }) {
|
|
117
|
+
return (_jsx("div", { className: "px-3 py-0.5", children: _jsx("span", { className: "text-muted-foreground/70 font-mono text-[11px] break-all whitespace-pre-wrap", children: line.raw }) }));
|
|
118
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { EventLogViewer } from './event-log-viewer.js';
|
|
3
|
+
declare const meta: Meta<typeof EventLogViewer>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof EventLogViewer>;
|
|
6
|
+
/** ToolCalls — various tool call types */
|
|
7
|
+
export declare const ToolCalls: Story;
|
|
8
|
+
/** TextMessages — agent thinking/analysis */
|
|
9
|
+
export declare const TextMessages: Story;
|
|
10
|
+
/** WorkerLifecycle — worker bootstrap and shutdown */
|
|
11
|
+
export declare const WorkerLifecycle: Story;
|
|
12
|
+
/** ResultsAndTokens — completion summaries */
|
|
13
|
+
export declare const ResultsAndTokens: Story;
|
|
14
|
+
/** MixedContent — all event types including raw fallback */
|
|
15
|
+
export declare const MixedContent: Story;
|
|
16
|
+
/** EmptyContent — no content */
|
|
17
|
+
export declare const EmptyContent: Story;
|
|
18
|
+
//# sourceMappingURL=event-log-viewer.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-log-viewer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,cAAc,CAqBrC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,cAAc,CAAC,CAAC;AAsD7C,0CAA0C;AAC1C,eAAO,MAAM,SAAS,EAAE,KAEvB,CAAC;AAEF,6CAA6C;AAC7C,eAAO,MAAM,YAAY,EAAE,KAE1B,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,eAAe,EAAE,KAE7B,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,gBAAgB,EAAE,KAE9B,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,YAAY,EAAE,KAE1B,CAAC;AAEF,gCAAgC;AAChC,eAAO,MAAM,YAAY,EAAE,KAE1B,CAAC"}
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.stories.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { EventLogViewer } from './event-log-viewer.js';
|
|
3
|
+
const meta = {
|
|
4
|
+
title: 'Drawers/Feature/Tabs/EventLogViewer',
|
|
5
|
+
component: EventLogViewer,
|
|
6
|
+
tags: ['autodocs'],
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'fullscreen',
|
|
9
|
+
},
|
|
10
|
+
decorators: [
|
|
11
|
+
(Story) => (_jsx("div", { style: {
|
|
12
|
+
height: '600px',
|
|
13
|
+
width: '480px',
|
|
14
|
+
border: '1px solid var(--color-border)',
|
|
15
|
+
overflow: 'auto',
|
|
16
|
+
}, children: _jsx(Story, {}) })),
|
|
17
|
+
],
|
|
18
|
+
};
|
|
19
|
+
export default meta;
|
|
20
|
+
/* ---------------------------------------------------------------------------
|
|
21
|
+
* Fixtures
|
|
22
|
+
* ------------------------------------------------------------------------- */
|
|
23
|
+
const toolEvents = `[2026-03-08T10:00:08.234Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Read {"file_path": "src/main.ts"}
|
|
24
|
+
[2026-03-08T10:00:10.345Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Glob {"pattern": "src/**/*.ts"}
|
|
25
|
+
[2026-03-08T10:00:12.567Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Grep {"pattern": "interface.*Auth", "path": "src/"}
|
|
26
|
+
[2026-03-08T10:00:14.789Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Bash {"command": "find src -name '*.test.ts' | wc -l"}
|
|
27
|
+
[2026-03-08T10:00:16.012Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Write {"file_path": "src/auth/oauth-provider.ts"}
|
|
28
|
+
[2026-03-08T10:00:18.234Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Edit {"file_path": "src/auth/index.ts"}
|
|
29
|
+
[2026-03-08T10:00:20.456Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Task {"description": "Run integration tests"}`;
|
|
30
|
+
const textEvents = `[2026-03-08T10:00:10.345Z] [requirements] [claude-code|claude-sonnet-4-6] [text] Analyzing the codebase structure and identifying key entry points for the authentication module
|
|
31
|
+
[2026-03-08T10:00:18.234Z] [requirements] [claude-code|claude-sonnet-4-6] [text] The project uses a clean architecture pattern with dependency injection
|
|
32
|
+
[2026-03-08T10:02:38.200Z] [plan] [claude-code|claude-sonnet-4-6] [text] Creating implementation plan with TDD approach as required by project conventions
|
|
33
|
+
[2026-03-08T10:05:30.000Z] [implement] [claude-code|claude-sonnet-4-6] [text] All 14 unit tests passing. Moving to integration tests`;
|
|
34
|
+
const workerEvents = `[2026-03-08T10:00:01.000Z] [claude-code|claude-sonnet-4-6] [WORKER] Starting worker — full command:
|
|
35
|
+
[2026-03-08T10:00:01.001Z] [claude-code|claude-sonnet-4-6] [WORKER] feature-agent-worker --feature-id auth-module --run-id run-123
|
|
36
|
+
[2026-03-08T10:00:01.010Z] [claude-code|claude-sonnet-4-6] [WORKER] Initializing container...
|
|
37
|
+
[2026-03-08T10:00:01.050Z] [claude-code|claude-sonnet-4-6] [WORKER] Creating executor from pinned agent type: claude-code
|
|
38
|
+
[2026-03-08T10:00:01.100Z] [claude-code|claude-sonnet-4-6] [WORKER] Updating status to running (PID 54321)...
|
|
39
|
+
[2026-03-08T10:06:00.000Z] [claude-code|claude-sonnet-4-6] [WORKER] Graph invocation completed. Error: none
|
|
40
|
+
[2026-03-08T10:06:00.100Z] [claude-code|claude-sonnet-4-6] [WORKER] Run marked as completed
|
|
41
|
+
[2026-03-08T10:06:00.200Z] [claude-code|claude-sonnet-4-6] [WORKER] Worker completed successfully, exiting.`;
|
|
42
|
+
const resultAndTokenEvents = `[2026-03-08T10:00:45.789Z] [requirements] [claude-code|claude-sonnet-4-6] [result] 8920 chars, session=sess-abc123def456
|
|
43
|
+
[2026-03-08T10:00:45.790Z] [requirements] [claude-code|claude-sonnet-4-6] [tokens] 2450 in / 4560 out
|
|
44
|
+
[2026-03-08T10:03:15.234Z] [plan] [claude-code|claude-sonnet-4-6] [result] 12345 chars, session=sess-abc123def456
|
|
45
|
+
[2026-03-08T10:03:15.235Z] [plan] [claude-code|claude-sonnet-4-6] [tokens] 8900 in / 3456 out
|
|
46
|
+
[2026-03-08T10:05:55.000Z] [implement] [claude-code|claude-sonnet-4-6] [result] 24560 chars, session=sess-abc123def456
|
|
47
|
+
[2026-03-08T10:05:55.001Z] [implement] [claude-code|claude-sonnet-4-6] [tokens] 15200 in / 9360 out`;
|
|
48
|
+
const mixedContent = `[2026-03-08T10:00:01.000Z] [claude-code|claude-sonnet-4-6] [WORKER] Starting worker — full command:
|
|
49
|
+
[2026-03-08T10:00:01.010Z] [claude-code|claude-sonnet-4-6] [WORKER] Initializing container...
|
|
50
|
+
[2026-03-08T10:00:05.000Z] [requirements] [claude-code|claude-sonnet-4-6] Starting...
|
|
51
|
+
[2026-03-08T10:00:08.234Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Read {"file_path": "src/main.ts"}
|
|
52
|
+
[2026-03-08T10:00:10.345Z] [requirements] [claude-code|claude-sonnet-4-6] [text] Analyzing the codebase structure
|
|
53
|
+
[2026-03-08T10:00:12.567Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Bash {"command": "pnpm test:unit"}
|
|
54
|
+
[2026-03-08T10:00:45.789Z] [requirements] [claude-code|claude-sonnet-4-6] [result] 8920 chars, session=sess-abc123
|
|
55
|
+
[2026-03-08T10:00:45.790Z] [requirements] [claude-code|claude-sonnet-4-6] [tokens] 2450 in / 4560 out
|
|
56
|
+
Some unstructured output that doesn't match the format
|
|
57
|
+
Another raw line from stderr
|
|
58
|
+
[2026-03-08T10:02:30.100Z] [plan] [claude-code|claude-sonnet-4-6] Starting...
|
|
59
|
+
[2026-03-08T10:02:35.100Z] [plan] [claude-code|claude-sonnet-4-6] [tool] Write {"file_path": "specs/001-auth/plan.yaml"}
|
|
60
|
+
[2026-03-08T10:03:15.234Z] [plan] [claude-code|claude-sonnet-4-6] [result] 12345 chars, session=sess-abc123
|
|
61
|
+
[2026-03-08T10:03:15.235Z] [plan] [claude-code|claude-sonnet-4-6] [tokens] 8900 in / 3456 out`;
|
|
62
|
+
/* ---------------------------------------------------------------------------
|
|
63
|
+
* Stories
|
|
64
|
+
* ------------------------------------------------------------------------- */
|
|
65
|
+
/** ToolCalls — various tool call types */
|
|
66
|
+
export const ToolCalls = {
|
|
67
|
+
args: { content: toolEvents },
|
|
68
|
+
};
|
|
69
|
+
/** TextMessages — agent thinking/analysis */
|
|
70
|
+
export const TextMessages = {
|
|
71
|
+
args: { content: textEvents },
|
|
72
|
+
};
|
|
73
|
+
/** WorkerLifecycle — worker bootstrap and shutdown */
|
|
74
|
+
export const WorkerLifecycle = {
|
|
75
|
+
args: { content: workerEvents },
|
|
76
|
+
};
|
|
77
|
+
/** ResultsAndTokens — completion summaries */
|
|
78
|
+
export const ResultsAndTokens = {
|
|
79
|
+
args: { content: resultAndTokenEvents },
|
|
80
|
+
};
|
|
81
|
+
/** MixedContent — all event types including raw fallback */
|
|
82
|
+
export const MixedContent = {
|
|
83
|
+
args: { content: mixedContent },
|
|
84
|
+
};
|
|
85
|
+
/** EmptyContent — no content */
|
|
86
|
+
export const EmptyContent = {
|
|
87
|
+
args: { content: '' },
|
|
88
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/log-tab.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"log-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/log-tab.tsx"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAID,wBAAgB,MAAM,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,WAAW,2CAgHlE"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useRef, useEffect, useState, useCallback } from 'react';
|
|
4
|
-
import { AlertCircle, Terminal, ArrowDown } from 'lucide-react';
|
|
4
|
+
import { AlertCircle, Terminal, ArrowDown, Code, FileText } from 'lucide-react';
|
|
5
|
+
import { EventLogViewer } from './event-log-viewer.js';
|
|
5
6
|
export function LogTab({ content, isConnected, error }) {
|
|
6
7
|
const containerRef = useRef(null);
|
|
7
8
|
const [autoScroll, setAutoScroll] = useState(true);
|
|
9
|
+
const [viewMode, setViewMode] = useState('structured');
|
|
8
10
|
const handleScroll = useCallback(() => {
|
|
9
11
|
const el = containerRef.current;
|
|
10
12
|
if (!el)
|
|
@@ -31,5 +33,11 @@ export function LogTab({ content, isConnected, error }) {
|
|
|
31
33
|
if (!content) {
|
|
32
34
|
return (_jsxs("div", { className: "flex flex-col items-center justify-center gap-2 p-8", children: [_jsx(Terminal, { className: "text-muted-foreground h-8 w-8" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "No log output yet" }), isConnected ? (_jsx("p", { className: "text-muted-foreground text-xs", children: "Waiting for log data..." })) : null] }));
|
|
33
35
|
}
|
|
34
|
-
return (_jsxs("div", { className: "flex h-full flex-col", "data-testid": "log-tab", children: [_jsxs("div", { className: "flex items-center gap-2 border-b px-3 py-1.5", children: [_jsx("span", { className: `h-2 w-2 rounded-full ${isConnected ? 'bg-emerald-500' : 'bg-zinc-400'}` }), _jsx("span", { className: "text-muted-foreground text-xs", children: isConnected ? 'Live' : 'Disconnected' }),
|
|
36
|
+
return (_jsxs("div", { className: "flex h-full flex-col", "data-testid": "log-tab", children: [_jsxs("div", { className: "flex items-center gap-2 border-b px-3 py-1.5", children: [_jsx("span", { className: `h-2 w-2 rounded-full ${isConnected ? 'bg-emerald-500' : 'bg-zinc-400'}` }), _jsx("span", { className: "text-muted-foreground text-xs", children: isConnected ? 'Live' : 'Disconnected' }), _jsxs("div", { className: "ml-auto flex items-center gap-1", children: [_jsx("button", { type: "button", onClick: () => setViewMode('structured'), className: `rounded p-1 transition-colors ${viewMode === 'structured'
|
|
37
|
+
? 'bg-muted text-foreground'
|
|
38
|
+
: 'text-muted-foreground hover:text-foreground'}`, title: "Structured view", children: _jsx(FileText, { className: "h-3.5 w-3.5" }) }), _jsx("button", { type: "button", onClick: () => setViewMode('raw'), className: `rounded p-1 transition-colors ${viewMode === 'raw'
|
|
39
|
+
? 'bg-muted text-foreground'
|
|
40
|
+
: 'text-muted-foreground hover:text-foreground'}`, title: "Raw view", children: _jsx(Code, { className: "h-3.5 w-3.5" }) }), !autoScroll ? (_jsxs("button", { type: "button", onClick: jumpToBottom, className: "text-muted-foreground hover:text-foreground ml-1 flex items-center gap-1 text-xs", children: [_jsx(ArrowDown, { className: "h-3 w-3" }), "Jump to bottom"] })) : null] })] }), _jsx("div", { ref: containerRef, onScroll: handleScroll, className: `flex-1 overflow-y-auto ${viewMode === 'raw'
|
|
41
|
+
? 'bg-zinc-950 p-3 font-mono text-xs leading-relaxed break-all whitespace-pre-wrap text-zinc-300'
|
|
42
|
+
: 'bg-background'}`, children: viewMode === 'structured' ? _jsx(EventLogViewer, { content: content }) : content })] }));
|
|
35
43
|
}
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.d.ts
CHANGED
|
@@ -3,10 +3,12 @@ import { LogTab } from './log-tab.js';
|
|
|
3
3
|
declare const meta: Meta<typeof LogTab>;
|
|
4
4
|
export default meta;
|
|
5
5
|
type Story = StoryObj<typeof LogTab>;
|
|
6
|
-
/** Default —
|
|
6
|
+
/** Default — structured agent log output with live connection (claude-code). */
|
|
7
7
|
export declare const Default: Story;
|
|
8
|
-
/**
|
|
9
|
-
export declare const
|
|
8
|
+
/** LongStructured — 100 structured events to test scrolling behavior. */
|
|
9
|
+
export declare const LongStructured: Story;
|
|
10
|
+
/** RawFallback — unstructured log content falls back gracefully. */
|
|
11
|
+
export declare const RawFallback: Story;
|
|
10
12
|
/** Disconnected — log content present but connection is lost. */
|
|
11
13
|
export declare const Disconnected: Story;
|
|
12
14
|
/** Empty — no log content yet, connected and waiting. */
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-tab.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,MAAM,CAc7B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"log-tab.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,MAAM,CAc7B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,MAAM,CAAC,CAAC;AA6GrC,gFAAgF;AAChF,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,cAAc,EAAE,KAM5B,CAAC;AAEF,oEAAoE;AACpE,eAAO,MAAM,WAAW,EAAE,KAMzB,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,KAAK,EAAE,KAMnB,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,iBAAiB,EAAE,KAM/B,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,KAAK,EAAE,KAMnB,CAAC"}
|
|
@@ -8,14 +8,61 @@ const meta = {
|
|
|
8
8
|
layout: 'fullscreen',
|
|
9
9
|
},
|
|
10
10
|
decorators: [
|
|
11
|
-
(Story) => (_jsx("div", { style: { height: '600px', width: '
|
|
11
|
+
(Story) => (_jsx("div", { style: { height: '600px', width: '480px', border: '1px solid var(--color-border)' }, children: _jsx(Story, {}) })),
|
|
12
12
|
],
|
|
13
13
|
};
|
|
14
14
|
export default meta;
|
|
15
15
|
/* ---------------------------------------------------------------------------
|
|
16
16
|
* Data fixtures
|
|
17
17
|
* ------------------------------------------------------------------------- */
|
|
18
|
-
const
|
|
18
|
+
const structuredLogContent = `[2026-03-08T10:00:01.000Z] [claude-code|claude-sonnet-4-6] [WORKER] Starting worker — full command:
|
|
19
|
+
[2026-03-08T10:00:01.001Z] [claude-code|claude-sonnet-4-6] [WORKER] feature-agent-worker --feature-id auth-module --run-id run-123 --repo /home/user/myproject --agent-type claude-code --model claude-sonnet-4-6
|
|
20
|
+
[2026-03-08T10:00:01.010Z] [claude-code|claude-sonnet-4-6] [WORKER] Initializing container...
|
|
21
|
+
[2026-03-08T10:00:01.050Z] [claude-code|claude-sonnet-4-6] [WORKER] Creating executor from pinned agent type: claude-code
|
|
22
|
+
[2026-03-08T10:00:01.100Z] [claude-code|claude-sonnet-4-6] [WORKER] Updating status to running (PID 54321)...
|
|
23
|
+
[2026-03-08T10:00:01.110Z] [claude-code|claude-sonnet-4-6] [WORKER] Starting graph invocation...
|
|
24
|
+
[2026-03-08T10:00:05.000Z] [requirements] [claude-code|claude-sonnet-4-6] Starting...
|
|
25
|
+
[2026-03-08T10:00:05.010Z] [requirements] [claude-code|claude-sonnet-4-6] Executing agent at cwd=/home/user/myproject
|
|
26
|
+
[2026-03-08T10:00:05.020Z] [requirements] [claude-code|claude-sonnet-4-6] Prompt length: 2847 chars
|
|
27
|
+
[2026-03-08T10:00:05.100Z] [requirements] [claude-code|claude-sonnet-4-6] Spawning: claude -p "Analyze this project..." --output-format stream-json --verbose
|
|
28
|
+
[2026-03-08T10:00:05.102Z] [requirements] [claude-code|claude-sonnet-4-6] Subprocess PID: 54322
|
|
29
|
+
[2026-03-08T10:00:08.234Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Read {"file_path": "src/main.ts"}
|
|
30
|
+
[2026-03-08T10:00:10.345Z] [requirements] [claude-code|claude-sonnet-4-6] [text] Analyzing the codebase structure and identifying key entry points for the authentication module
|
|
31
|
+
[2026-03-08T10:00:12.567Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Glob {"pattern": "src/**/*.ts"}
|
|
32
|
+
[2026-03-08T10:00:14.789Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Read {"file_path": "src/auth/providers.ts"}
|
|
33
|
+
[2026-03-08T10:00:16.012Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Grep {"pattern": "interface.*Auth", "path": "src/"}
|
|
34
|
+
[2026-03-08T10:00:18.234Z] [requirements] [claude-code|claude-sonnet-4-6] [text] The project uses a clean architecture pattern with dependency injection. I can see the auth interfaces are defined in the domain layer
|
|
35
|
+
[2026-03-08T10:00:20.456Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Bash {"command": "find src -name '*.test.ts' | wc -l"}
|
|
36
|
+
[2026-03-08T10:00:45.789Z] [requirements] [claude-code|claude-sonnet-4-6] [result] 8920 chars, session=sess-abc123def456
|
|
37
|
+
[2026-03-08T10:00:45.790Z] [requirements] [claude-code|claude-sonnet-4-6] [tokens] 2450 in / 4560 out
|
|
38
|
+
[2026-03-08T10:00:45.791Z] [requirements] [claude-code|claude-sonnet-4-6] Process closed with code 0, result=8920 chars
|
|
39
|
+
[2026-03-08T10:00:45.800Z] [requirements] [claude-code|claude-sonnet-4-6] Complete (8920 chars, 40.8s)
|
|
40
|
+
[2026-03-08T10:00:45.900Z] [requirements] [claude-code|claude-sonnet-4-6] Interrupting for human approval
|
|
41
|
+
[2026-03-08T10:02:30.000Z] [requirements] [claude-code|claude-sonnet-4-6] Phase approved, skipping re-execution
|
|
42
|
+
[2026-03-08T10:02:30.100Z] [plan] [claude-code|claude-sonnet-4-6] Starting...
|
|
43
|
+
[2026-03-08T10:02:30.110Z] [plan] [claude-code|claude-sonnet-4-6] Executing agent at cwd=/home/user/myproject
|
|
44
|
+
[2026-03-08T10:02:30.120Z] [plan] [claude-code|claude-sonnet-4-6] Prompt length: 15234 chars
|
|
45
|
+
[2026-03-08T10:02:35.100Z] [plan] [claude-code|claude-sonnet-4-6] [tool] Read {"file_path": "CLAUDE.md"}
|
|
46
|
+
[2026-03-08T10:02:38.200Z] [plan] [claude-code|claude-sonnet-4-6] [text] Creating implementation plan with TDD approach as required by project conventions
|
|
47
|
+
[2026-03-08T10:02:42.300Z] [plan] [claude-code|claude-sonnet-4-6] [tool] Write {"file_path": "specs/001-auth/plan.yaml"}
|
|
48
|
+
[2026-03-08T10:02:45.400Z] [plan] [claude-code|claude-sonnet-4-6] [text] Plan includes 3 phases: scaffold auth module, implement OAuth2 providers, add tests and documentation
|
|
49
|
+
[2026-03-08T10:03:15.234Z] [plan] [claude-code|claude-sonnet-4-6] [result] 12345 chars, session=sess-abc123def456
|
|
50
|
+
[2026-03-08T10:03:15.235Z] [plan] [claude-code|claude-sonnet-4-6] [tokens] 8900 in / 3456 out
|
|
51
|
+
[2026-03-08T10:03:15.300Z] [plan] [claude-code|claude-sonnet-4-6] Complete (12345 chars, 45.1s)
|
|
52
|
+
[2026-03-08T10:05:00.000Z] [implement] [claude-code|claude-sonnet-4-6] Starting...
|
|
53
|
+
[2026-03-08T10:05:01.000Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Write {"file_path": "src/auth/oauth-provider.ts"}
|
|
54
|
+
[2026-03-08T10:05:03.000Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Write {"file_path": "src/auth/token-manager.ts"}
|
|
55
|
+
[2026-03-08T10:05:05.000Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Edit {"file_path": "src/auth/index.ts"}
|
|
56
|
+
[2026-03-08T10:05:07.000Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Bash {"command": "pnpm test:unit"}
|
|
57
|
+
[2026-03-08T10:05:30.000Z] [implement] [claude-code|claude-sonnet-4-6] [text] All 14 unit tests passing. Moving to integration tests
|
|
58
|
+
[2026-03-08T10:05:35.000Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Bash {"command": "pnpm test:int"}
|
|
59
|
+
[2026-03-08T10:05:55.000Z] [implement] [claude-code|claude-sonnet-4-6] [result] 24560 chars, session=sess-abc123def456
|
|
60
|
+
[2026-03-08T10:05:55.001Z] [implement] [claude-code|claude-sonnet-4-6] [tokens] 15200 in / 9360 out
|
|
61
|
+
[2026-03-08T10:05:55.100Z] [implement] [claude-code|claude-sonnet-4-6] Complete (24560 chars, 54.1s)
|
|
62
|
+
[2026-03-08T10:06:00.000Z] [claude-code|claude-sonnet-4-6] [WORKER] Graph invocation completed. Error: none
|
|
63
|
+
[2026-03-08T10:06:00.100Z] [claude-code|claude-sonnet-4-6] [WORKER] Run marked as completed
|
|
64
|
+
[2026-03-08T10:06:00.200Z] [claude-code|claude-sonnet-4-6] [WORKER] Worker completed successfully, exiting.`;
|
|
65
|
+
const rawLogContent = `[2026-03-08T10:00:01.123Z] Starting agent run for feature "auth-module"
|
|
19
66
|
[2026-03-08T10:00:02.789Z] Agent started — analyzing codebase
|
|
20
67
|
[2026-03-08T10:00:03.456Z] Scanning repository structure...
|
|
21
68
|
[2026-03-08T10:00:04.012Z] Found 127 source files across 14 packages
|
|
@@ -35,22 +82,58 @@ const typicalLogContent = `[2026-03-08T10:00:01.123Z] Starting agent run for fea
|
|
|
35
82
|
[2026-03-08T10:00:24.789Z] Phase 3: add tests and documentation
|
|
36
83
|
[2026-03-08T10:00:26.456Z] Generating test suite...
|
|
37
84
|
[2026-03-08T10:00:28.012Z] All phases complete — feature "auth-module" ready for review`;
|
|
38
|
-
const
|
|
85
|
+
const longStructuredContent = Array.from({ length: 100 }, (_, i) => {
|
|
86
|
+
const min = String(Math.floor(i / 60)).padStart(2, '0');
|
|
87
|
+
const sec = String(i % 60).padStart(2, '0');
|
|
88
|
+
const ms = String((i * 7) % 1000).padStart(3, '0');
|
|
89
|
+
const ts = `2026-03-08T10:${min}:${sec}.${ms}Z`;
|
|
90
|
+
const phase = ['requirements', 'research', 'plan', 'implement'][i % 4];
|
|
91
|
+
const tags = ['[tool]', '[text]', '[tool]', '[text]', '[result]', '[tokens]'];
|
|
92
|
+
const tag = tags[i % tags.length];
|
|
93
|
+
const messages = {
|
|
94
|
+
'[tool]': [
|
|
95
|
+
'Read {"file_path": "src/components/button.tsx"}',
|
|
96
|
+
'Bash {"command": "pnpm test:unit"}',
|
|
97
|
+
'Grep {"pattern": "export function", "path": "src/"}',
|
|
98
|
+
'Write {"file_path": "src/new-file.ts"}',
|
|
99
|
+
'Glob {"pattern": "**/*.test.ts"}',
|
|
100
|
+
],
|
|
101
|
+
'[text]': [
|
|
102
|
+
'Analyzing the component structure for potential improvements',
|
|
103
|
+
'The test suite is comprehensive with good coverage',
|
|
104
|
+
'Implementing the authentication flow with OAuth2 providers',
|
|
105
|
+
'Refactoring to use dependency injection pattern',
|
|
106
|
+
],
|
|
107
|
+
'[result]': ['4520 chars, session=sess-xyz789'],
|
|
108
|
+
'[tokens]': ['3200 in / 1800 out'],
|
|
109
|
+
};
|
|
110
|
+
const msgList = messages[tag] ?? messages['[text]'];
|
|
111
|
+
const msg = msgList[i % msgList.length];
|
|
112
|
+
return `[${ts}] [${phase}] [claude-code|claude-sonnet-4-6] ${tag} ${msg}`;
|
|
113
|
+
}).join('\n');
|
|
39
114
|
/* ---------------------------------------------------------------------------
|
|
40
115
|
* Stories
|
|
41
116
|
* ------------------------------------------------------------------------- */
|
|
42
|
-
/** Default —
|
|
117
|
+
/** Default — structured agent log output with live connection (claude-code). */
|
|
43
118
|
export const Default = {
|
|
44
119
|
args: {
|
|
45
|
-
content:
|
|
120
|
+
content: structuredLogContent,
|
|
46
121
|
isConnected: true,
|
|
47
122
|
error: null,
|
|
48
123
|
},
|
|
49
124
|
};
|
|
50
|
-
/**
|
|
51
|
-
export const
|
|
125
|
+
/** LongStructured — 100 structured events to test scrolling behavior. */
|
|
126
|
+
export const LongStructured = {
|
|
52
127
|
args: {
|
|
53
|
-
content:
|
|
128
|
+
content: longStructuredContent,
|
|
129
|
+
isConnected: true,
|
|
130
|
+
error: null,
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
/** RawFallback — unstructured log content falls back gracefully. */
|
|
134
|
+
export const RawFallback = {
|
|
135
|
+
args: {
|
|
136
|
+
content: rawLogContent,
|
|
54
137
|
isConnected: true,
|
|
55
138
|
error: null,
|
|
56
139
|
},
|
|
@@ -58,7 +141,7 @@ export const LongLog = {
|
|
|
58
141
|
/** Disconnected — log content present but connection is lost. */
|
|
59
142
|
export const Disconnected = {
|
|
60
143
|
args: {
|
|
61
|
-
content:
|
|
144
|
+
content: structuredLogContent,
|
|
62
145
|
isConnected: false,
|
|
63
146
|
error: null,
|
|
64
147
|
},
|