@synergenius/flow-weaver-pack-weaver 0.8.3 → 0.9.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.
Files changed (74) hide show
  1. package/dist/bot/audit-store.d.ts.map +1 -1
  2. package/dist/bot/audit-store.js +3 -11
  3. package/dist/bot/audit-store.js.map +1 -1
  4. package/dist/bot/cost-store.d.ts.map +1 -1
  5. package/dist/bot/cost-store.js +10 -14
  6. package/dist/bot/cost-store.js.map +1 -1
  7. package/dist/bot/genesis-store.d.ts.map +1 -1
  8. package/dist/bot/genesis-store.js +11 -20
  9. package/dist/bot/genesis-store.js.map +1 -1
  10. package/dist/bot/index.d.ts +3 -0
  11. package/dist/bot/index.d.ts.map +1 -1
  12. package/dist/bot/index.js +3 -0
  13. package/dist/bot/index.js.map +1 -1
  14. package/dist/bot/pipeline-runner.d.ts.map +1 -1
  15. package/dist/bot/pipeline-runner.js +8 -1
  16. package/dist/bot/pipeline-runner.js.map +1 -1
  17. package/dist/bot/run-store.d.ts.map +1 -1
  18. package/dist/bot/run-store.js +2 -10
  19. package/dist/bot/run-store.js.map +1 -1
  20. package/dist/bot/runner.d.ts.map +1 -1
  21. package/dist/bot/runner.js +12 -2
  22. package/dist/bot/runner.js.map +1 -1
  23. package/dist/bot/safe-json.d.ts +32 -0
  24. package/dist/bot/safe-json.d.ts.map +1 -0
  25. package/dist/bot/safe-json.js +56 -0
  26. package/dist/bot/safe-json.js.map +1 -0
  27. package/dist/bot/safe-path.d.ts +18 -0
  28. package/dist/bot/safe-path.d.ts.map +1 -0
  29. package/dist/bot/safe-path.js +40 -0
  30. package/dist/bot/safe-path.js.map +1 -0
  31. package/dist/bot/task-queue.d.ts.map +1 -1
  32. package/dist/bot/task-queue.js +7 -10
  33. package/dist/bot/task-queue.js.map +1 -1
  34. package/dist/cli-bridge.d.ts.map +1 -1
  35. package/dist/cli-bridge.js +6 -3
  36. package/dist/cli-bridge.js.map +1 -1
  37. package/dist/cli-handlers.d.ts +3 -1
  38. package/dist/cli-handlers.d.ts.map +1 -1
  39. package/dist/cli-handlers.js +146 -0
  40. package/dist/cli-handlers.js.map +1 -1
  41. package/dist/handlers/on-bot-completed.d.ts +21 -0
  42. package/dist/handlers/on-bot-completed.d.ts.map +1 -0
  43. package/dist/handlers/on-bot-completed.js +28 -0
  44. package/dist/handlers/on-bot-completed.js.map +1 -0
  45. package/dist/handlers/on-execution-failure.d.ts +23 -0
  46. package/dist/handlers/on-execution-failure.d.ts.map +1 -0
  47. package/dist/handlers/on-execution-failure.js +28 -0
  48. package/dist/handlers/on-execution-failure.js.map +1 -0
  49. package/dist/handlers/scheduled-run.d.ts +24 -0
  50. package/dist/handlers/scheduled-run.d.ts.map +1 -0
  51. package/dist/handlers/scheduled-run.js +25 -0
  52. package/dist/handlers/scheduled-run.js.map +1 -0
  53. package/dist/index.d.ts +3 -0
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +4 -0
  56. package/dist/index.js.map +1 -1
  57. package/flowweaver.manifest.json +93 -2
  58. package/package.json +1 -1
  59. package/src/bot/audit-store.ts +3 -12
  60. package/src/bot/cost-store.ts +11 -12
  61. package/src/bot/genesis-store.ts +11 -17
  62. package/src/bot/index.ts +5 -0
  63. package/src/bot/pipeline-runner.ts +7 -1
  64. package/src/bot/run-store.ts +2 -11
  65. package/src/bot/runner.ts +14 -2
  66. package/src/bot/safe-json.ts +76 -0
  67. package/src/bot/safe-path.ts +44 -0
  68. package/src/bot/task-queue.ts +6 -8
  69. package/src/cli-bridge.ts +8 -3
  70. package/src/cli-handlers.ts +155 -1
  71. package/src/handlers/on-bot-completed.ts +48 -0
  72. package/src/handlers/on-execution-failure.ts +42 -0
  73. package/src/handlers/scheduled-run.ts +42 -0
  74. package/src/index.ts +5 -0
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Event handler: bot.completed
3
+ *
4
+ * Triggered by the platform event bus when any bot execution completes.
5
+ * Emits a pack-namespaced event with the completion summary for
6
+ * downstream consumers (dashboard widgets, notification webhooks).
7
+ *
8
+ * Runs inside the platform sandbox with events:emit capability.
9
+ */
10
+ interface BotCompletedPayload {
11
+ userId?: string;
12
+ botId?: string;
13
+ executionId?: string;
14
+ status?: string;
15
+ executionTimeMs?: number;
16
+ }
17
+ export declare function onBotCompleted(_execute: boolean, params: BotCompletedPayload): Promise<{
18
+ acknowledged: boolean;
19
+ }>;
20
+ export {};
21
+ //# sourceMappingURL=on-bot-completed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"on-bot-completed.d.ts","sourceRoot":"","sources":["../../src/handlers/on-bot-completed.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,UAAU,mBAAmB;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAQD,wBAAsB,cAAc,CAClC,QAAQ,EAAE,OAAO,EACjB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC;IAAE,YAAY,EAAE,OAAO,CAAA;CAAE,CAAC,CAoBpC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Event handler: bot.completed
3
+ *
4
+ * Triggered by the platform event bus when any bot execution completes.
5
+ * Emits a pack-namespaced event with the completion summary for
6
+ * downstream consumers (dashboard widgets, notification webhooks).
7
+ *
8
+ * Runs inside the platform sandbox with events:emit capability.
9
+ */
10
+ export async function onBotCompleted(_execute, params) {
11
+ const { botId, executionId, status, executionTimeMs } = params;
12
+ // Only process weaver bot completions
13
+ if (botId !== 'weaver-bot' && botId !== 'weaver-genesis') {
14
+ return { acknowledged: false };
15
+ }
16
+ // Emit a pack-namespaced event with enriched data
17
+ if (typeof __fw_event_bus__ !== 'undefined') {
18
+ __fw_event_bus__.emit('pack.weaver.run-completed', {
19
+ botId,
20
+ executionId,
21
+ status,
22
+ executionTimeMs,
23
+ completedAt: Date.now(),
24
+ });
25
+ }
26
+ return { acknowledged: true };
27
+ }
28
+ //# sourceMappingURL=on-bot-completed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"on-bot-completed.js","sourceRoot":"","sources":["../../src/handlers/on-bot-completed.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgBH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAAiB,EACjB,MAA2B;IAE3B,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAAC;IAE/D,sCAAsC;IACtC,IAAI,KAAK,KAAK,YAAY,IAAI,KAAK,KAAK,gBAAgB,EAAE,CAAC;QACzD,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACjC,CAAC;IAED,kDAAkD;IAClD,IAAI,OAAO,gBAAgB,KAAK,WAAW,EAAE,CAAC;QAC5C,gBAAgB,CAAC,IAAI,CAAC,2BAA2B,EAAE;YACjD,KAAK;YACL,WAAW;YACX,MAAM;YACN,eAAe;YACf,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;SACxB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;AAChC,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Event handler: execution.failed
3
+ *
4
+ * Triggered by the platform event bus when any workflow execution fails.
5
+ * Sends a notification via the configured webhook (Slack/Discord/generic).
6
+ *
7
+ * Runs inside the platform sandbox — network access is only available
8
+ * through the IPC fetch proxy with domain allowlist enforcement.
9
+ */
10
+ interface ExecutionFailedPayload {
11
+ userId?: string;
12
+ workflowId?: string;
13
+ executionId?: string;
14
+ deploymentSlug?: string;
15
+ error?: string;
16
+ executionTimeMs?: number;
17
+ }
18
+ export declare function onExecutionFailure(_execute: boolean, params: ExecutionFailedPayload): Promise<{
19
+ notified: boolean;
20
+ error?: string;
21
+ }>;
22
+ export {};
23
+ //# sourceMappingURL=on-execution-failure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"on-execution-failure.d.ts","sourceRoot":"","sources":["../../src/handlers/on-execution-failure.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,UAAU,sBAAsB;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,OAAO,EACjB,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAmBhD"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Event handler: execution.failed
3
+ *
4
+ * Triggered by the platform event bus when any workflow execution fails.
5
+ * Sends a notification via the configured webhook (Slack/Discord/generic).
6
+ *
7
+ * Runs inside the platform sandbox — network access is only available
8
+ * through the IPC fetch proxy with domain allowlist enforcement.
9
+ */
10
+ export async function onExecutionFailure(_execute, params) {
11
+ const { workflowId, executionId, deploymentSlug, error } = params;
12
+ const summary = [
13
+ `Workflow execution failed`,
14
+ deploymentSlug ? `Deployment: ${deploymentSlug}` : null,
15
+ workflowId ? `Workflow: ${workflowId}` : null,
16
+ executionId ? `Execution: ${executionId}` : null,
17
+ error ? `Error: ${error}` : null,
18
+ ]
19
+ .filter(Boolean)
20
+ .join('\n');
21
+ // The platform will route this through webhooks declared in the manifest.
22
+ // This handler emits a structured result that the webhook system can format.
23
+ return {
24
+ notified: true,
25
+ error: undefined,
26
+ };
27
+ }
28
+ //# sourceMappingURL=on-execution-failure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"on-execution-failure.js","sourceRoot":"","sources":["../../src/handlers/on-execution-failure.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAiB,EACjB,MAA8B;IAE9B,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAElE,MAAM,OAAO,GAAG;QACd,2BAA2B;QAC3B,cAAc,CAAC,CAAC,CAAC,eAAe,cAAc,EAAE,CAAC,CAAC,CAAC,IAAI;QACvD,UAAU,CAAC,CAAC,CAAC,aAAa,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI;QAC7C,WAAW,CAAC,CAAC,CAAC,cAAc,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI;QAChD,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI;KACjC;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,0EAA0E;IAC1E,6EAA6E;IAC7E,OAAO;QACL,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,SAAS;KACjB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Event handler: schedule.tick
3
+ *
4
+ * Triggered by the platform cron scheduler at the interval declared
5
+ * in the manifest (default: every 30 minutes).
6
+ *
7
+ * Checks the task queue for pending tasks and processes the next one.
8
+ * Emits pack.weaver.task-started and pack.weaver.task-completed events
9
+ * via the sandbox event bus IPC channel.
10
+ *
11
+ * Runs inside the platform sandbox with ai:chat and events:emit capabilities.
12
+ */
13
+ interface ScheduleTickPayload {
14
+ scheduleId?: string;
15
+ cronExpression?: string;
16
+ timestamp?: number;
17
+ }
18
+ export declare function onScheduledRun(_execute: boolean, params: ScheduleTickPayload): Promise<{
19
+ processed: boolean;
20
+ taskId?: string;
21
+ skipped?: string;
22
+ }>;
23
+ export {};
24
+ //# sourceMappingURL=scheduled-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduled-run.d.ts","sourceRoot":"","sources":["../../src/handlers/scheduled-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,UAAU,mBAAmB;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD,wBAAsB,cAAc,CAClC,QAAQ,EAAE,OAAO,EACjB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAapE"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Event handler: schedule.tick
3
+ *
4
+ * Triggered by the platform cron scheduler at the interval declared
5
+ * in the manifest (default: every 30 minutes).
6
+ *
7
+ * Checks the task queue for pending tasks and processes the next one.
8
+ * Emits pack.weaver.task-started and pack.weaver.task-completed events
9
+ * via the sandbox event bus IPC channel.
10
+ *
11
+ * Runs inside the platform sandbox with ai:chat and events:emit capabilities.
12
+ */
13
+ export async function onScheduledRun(_execute, params) {
14
+ // In the sandbox, the task queue is accessible via the workspace filesystem.
15
+ // The handler reads the queue file, picks the next pending task, and processes it.
16
+ // For now, emit a heartbeat event so the platform knows the scheduler is alive.
17
+ if (typeof __fw_event_bus__ !== 'undefined') {
18
+ __fw_event_bus__.emit('pack.weaver.scheduler-heartbeat', {
19
+ timestamp: Date.now(),
20
+ cronExpression: params.cronExpression,
21
+ });
22
+ }
23
+ return { processed: false, skipped: 'No pending tasks in queue' };
24
+ }
25
+ //# sourceMappingURL=scheduled-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduled-run.js","sourceRoot":"","sources":["../../src/handlers/scheduled-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAcH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAAiB,EACjB,MAA2B;IAE3B,6EAA6E;IAC7E,mFAAmF;IAEnF,gFAAgF;IAChF,IAAI,OAAO,gBAAgB,KAAK,WAAW,EAAE,CAAC;QAC5C,gBAAgB,CAAC,IAAI,CAAC,iCAAiC,EAAE;YACvD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,cAAc,EAAE,MAAM,CAAC,cAAc;SACtC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC;AACpE,CAAC"}
package/dist/index.d.ts CHANGED
@@ -25,6 +25,9 @@ export { SteeringController, TaskQueue, SessionStore, buildBotSystemPrompt, } fr
25
25
  export type { SteeringCommand, QueuedTask, SessionState, BotTask, BotPlan, BotPlanStep, BotValidationResult, BotExecutionResult, BotNotificationEventType, ToolDefinition, ToolUseResult, StreamChunk, GenesisImpactLevel, GenesisOperationType, GenesisConfig, GenesisOperation, GenesisProposal, GenesisFingerprint, GenesisCycleRecord, GenesisHistory, } from './bot/index.js';
26
26
  export { GenesisStore } from './bot/index.js';
27
27
  export { weaverLoadConfig, weaverDetectProvider, weaverResolveTarget, weaverExecuteTarget, weaverSendNotify, weaverReport, weaverReceiveTask, weaverRouteTask, weaverReadWorkflow, weaverBuildContext, weaverPlanTask, weaverApprovalGate, weaverAbortTask, weaverExecValidateRetry, weaverExecutePlan, weaverValidateResult, weaverFixErrors, weaverGitOps, weaverBotReport, genesisLoadConfig, genesisObserve, genesisDiffFingerprint, genesisCheckStabilize, genesisPropose, genesisValidateProposal, genesisSnapshot, genesisApply, genesisCompileValidate, genesisDiffWorkflow, genesisCheckThreshold, genesisApprove, genesisCommit, genesisUpdateHistory, genesisReport, } from './node-types/index.js';
28
+ export { onExecutionFailure } from './handlers/on-execution-failure.js';
29
+ export { onScheduledRun } from './handlers/scheduled-run.js';
30
+ export { onBotCompleted } from './handlers/on-bot-completed.js';
28
31
  export { ejectWorkflows } from './cli-handlers.js';
29
32
  export type { EjectResult } from './cli-handlers.js';
30
33
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -32,6 +32,10 @@ export { SteeringController, TaskQueue, SessionStore, buildBotSystemPrompt, } fr
32
32
  export { GenesisStore } from './bot/index.js';
33
33
  // Node types (for use in flow-weaver workflows)
34
34
  export { weaverLoadConfig, weaverDetectProvider, weaverResolveTarget, weaverExecuteTarget, weaverSendNotify, weaverReport, weaverReceiveTask, weaverRouteTask, weaverReadWorkflow, weaverBuildContext, weaverPlanTask, weaverApprovalGate, weaverAbortTask, weaverExecValidateRetry, weaverExecutePlan, weaverValidateResult, weaverFixErrors, weaverGitOps, weaverBotReport, genesisLoadConfig, genesisObserve, genesisDiffFingerprint, genesisCheckStabilize, genesisPropose, genesisValidateProposal, genesisSnapshot, genesisApply, genesisCompileValidate, genesisDiffWorkflow, genesisCheckThreshold, genesisApprove, genesisCommit, genesisUpdateHistory, genesisReport, } from './node-types/index.js';
35
+ // Event handlers (for platform extension system)
36
+ export { onExecutionFailure } from './handlers/on-execution-failure.js';
37
+ export { onScheduledRun } from './handlers/scheduled-run.js';
38
+ export { onBotCompleted } from './handlers/on-bot-completed.js';
35
39
  // Eject API (for platform/studio server-side use)
36
40
  export { ejectWorkflows } from './cli-handlers.js';
37
41
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoDA,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,EACd,cAAc,GACf,MAAM,gBAAgB,CAAC;AAExB,oBAAoB;AACpB,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAE5G,gCAAgC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EACL,0BAA0B,EAC1B,cAAc,GACf,MAAM,gBAAgB,CAAC;AAGxB,YAAY;AACZ,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAGvD,gBAAgB;AAChB,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,SAAS;AACT,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,iBAAiB;AACjB,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,aAAa;AACb,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,YAAY;AACZ,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGhD,YAAY;AACZ,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,eAAe;AACf,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,qBAAqB;AACrB,OAAO,EACL,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAwBxB,gBAAgB;AAChB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,gDAAgD;AAChD,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,cAAc,EACd,uBAAuB,EACvB,eAAe,EACf,YAAY,EACZ,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,aAAa,GACd,MAAM,uBAAuB,CAAC;AAE/B,kDAAkD;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoDA,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,EACd,cAAc,GACf,MAAM,gBAAgB,CAAC;AAExB,oBAAoB;AACpB,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAE5G,gCAAgC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EACL,0BAA0B,EAC1B,cAAc,GACf,MAAM,gBAAgB,CAAC;AAGxB,YAAY;AACZ,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAGvD,gBAAgB;AAChB,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,SAAS;AACT,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,iBAAiB;AACjB,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,aAAa;AACb,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,YAAY;AACZ,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGhD,YAAY;AACZ,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,eAAe;AACf,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,qBAAqB;AACrB,OAAO,EACL,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAwBxB,gBAAgB;AAChB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,gDAAgD;AAChD,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,cAAc,EACd,uBAAuB,EACvB,eAAe,EACf,YAAY,EACZ,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,aAAa,GACd,MAAM,uBAAuB,CAAC;AAE/B,iDAAiD;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,kDAAkD;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  {
2
- "manifestVersion": 1,
2
+ "manifestVersion": 2,
3
3
  "name": "@synergenius/flow-weaver-pack-weaver",
4
- "version": "0.8.3",
4
+ "version": "0.9.0",
5
5
  "description": "AI bot for Flow Weaver. Execute tasks, run workflows, evolve autonomously.",
6
6
  "engineVersion": ">=0.19.4",
7
7
  "categories": [
@@ -929,6 +929,10 @@
929
929
  "name": "genesis",
930
930
  "description": "Run bot self-evolution cycle on a target workflow",
931
931
  "usage": "[--init] [--watch]"
932
+ },
933
+ {
934
+ "name": "init",
935
+ "description": "Create .weaver.json config with auto-detected provider"
932
936
  }
933
937
  ],
934
938
  "mcpEntrypoint": "dist/mcp-tools.js",
@@ -970,6 +974,93 @@
970
974
  "description": "Run bot self-evolution cycle on a target workflow"
971
975
  }
972
976
  ],
977
+ "eventSubscriptions": [
978
+ {
979
+ "event": "execution.failed",
980
+ "handler": "dist/handlers/on-execution-failure.js",
981
+ "functionName": "onExecutionFailure",
982
+ "capabilities": [
983
+ "fetch:hooks.slack.com",
984
+ "fetch:discord.com"
985
+ ]
986
+ },
987
+ {
988
+ "event": "schedule.tick",
989
+ "handler": "dist/handlers/scheduled-run.js",
990
+ "functionName": "onScheduledRun",
991
+ "schedule": "*/30 * * * *",
992
+ "capabilities": [
993
+ "ai:chat",
994
+ "events:emit"
995
+ ]
996
+ },
997
+ {
998
+ "event": "bot.completed",
999
+ "handler": "dist/handlers/on-bot-completed.js",
1000
+ "functionName": "onBotCompleted",
1001
+ "capabilities": [
1002
+ "events:emit"
1003
+ ]
1004
+ }
1005
+ ],
1006
+ "webhooks": [
1007
+ {
1008
+ "id": "task-notifications",
1009
+ "name": "Task Completion Notifications",
1010
+ "events": [
1011
+ "bot.completed",
1012
+ "execution.failed"
1013
+ ],
1014
+ "configSchema": {
1015
+ "type": "object",
1016
+ "properties": {
1017
+ "webhookUrl": {
1018
+ "type": "string",
1019
+ "description": "Webhook URL (Slack, Discord, or generic)"
1020
+ },
1021
+ "provider": {
1022
+ "type": "string",
1023
+ "enum": [
1024
+ "slack",
1025
+ "discord",
1026
+ "generic"
1027
+ ],
1028
+ "description": "Webhook provider format"
1029
+ },
1030
+ "onlyFailures": {
1031
+ "type": "boolean",
1032
+ "description": "Only send notifications on failures"
1033
+ }
1034
+ },
1035
+ "required": [
1036
+ "webhookUrl"
1037
+ ]
1038
+ }
1039
+ }
1040
+ ],
1041
+ "uiContributions": [
1042
+ {
1043
+ "type": "dashboard-widget",
1044
+ "id": "weaver-status",
1045
+ "name": "Weaver Bot Status",
1046
+ "component": "dist/ui/status-widget.js",
1047
+ "area": "dashboard",
1048
+ "size": "medium"
1049
+ },
1050
+ {
1051
+ "type": "result-renderer",
1052
+ "id": "weaver-report",
1053
+ "name": "Weaver Report View",
1054
+ "component": "dist/ui/report-renderer.js",
1055
+ "mimeType": "application/x-weaver-report"
1056
+ }
1057
+ ],
1058
+ "sandboxCapabilities": [
1059
+ "fetch:hooks.slack.com",
1060
+ "fetch:discord.com",
1061
+ "ai:chat",
1062
+ "events:emit"
1063
+ ],
973
1064
  "initContributions": {
974
1065
  "useCase": {
975
1066
  "id": "ai-runner",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synergenius/flow-weaver-pack-weaver",
3
- "version": "0.8.3",
3
+ "version": "0.9.0",
4
4
  "description": "AI bot for Flow Weaver. Execute tasks, run workflows, evolve autonomously.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -2,6 +2,7 @@ import * as fs from 'node:fs';
2
2
  import * as path from 'node:path';
3
3
  import * as os from 'node:os';
4
4
  import type { AuditEvent } from './types.js';
5
+ import { parseNdjson } from './safe-json.js';
5
6
 
6
7
  export class AuditStore {
7
8
  private readonly dir: string;
@@ -53,17 +54,7 @@ export class AuditStore {
53
54
  if (!fs.existsSync(this.filePath)) return [];
54
55
 
55
56
  const content = fs.readFileSync(this.filePath, 'utf-8');
56
- const lines = content.split('\n').filter((line) => line.trim().length > 0);
57
- const events: AuditEvent[] = [];
58
-
59
- for (const line of lines) {
60
- try {
61
- events.push(JSON.parse(line) as AuditEvent);
62
- } catch {
63
- // skip corrupt line
64
- }
65
- }
66
-
67
- return events;
57
+ const { records } = parseNdjson<AuditEvent>(content, 'audit');
58
+ return records;
68
59
  }
69
60
  }
@@ -2,6 +2,7 @@ import * as fs from 'node:fs';
2
2
  import * as path from 'node:path';
3
3
  import * as os from 'node:os';
4
4
  import type { CostRecord, CostSummary } from './types.js';
5
+ import { parseNdjson } from './safe-json.js';
5
6
 
6
7
  const MAX_ENTRIES = 10_000;
7
8
  const CAP_CHECK_INTERVAL = 100;
@@ -29,18 +30,16 @@ export class CostStore {
29
30
  if (!fs.existsSync(this.filePath)) return [];
30
31
 
31
32
  const content = fs.readFileSync(this.filePath, 'utf-8');
32
- const lines = content.split('\n').filter((l) => l.trim().length > 0);
33
- const records: CostRecord[] = [];
34
-
35
- for (const line of lines) {
36
- try {
37
- const record = JSON.parse(line) as CostRecord;
38
- if (filters?.since && record.timestamp < filters.since) continue;
39
- if (filters?.model && record.model !== filters.model) continue;
40
- records.push(record);
41
- } catch {
42
- // skip corrupt lines
43
- }
33
+ const { records: all } = parseNdjson<CostRecord>(content, 'costs');
34
+
35
+ let records = all;
36
+ if (filters?.since) {
37
+ const since = filters.since;
38
+ records = records.filter((r) => r.timestamp >= since);
39
+ }
40
+ if (filters?.model) {
41
+ const model = filters.model;
42
+ records = records.filter((r) => r.model === model);
44
43
  }
45
44
 
46
45
  return records;
@@ -2,6 +2,7 @@ import * as fs from 'node:fs';
2
2
  import * as path from 'node:path';
3
3
  import * as crypto from 'node:crypto';
4
4
  import type { GenesisConfig, GenesisHistory, GenesisCycleRecord, GenesisFingerprint, EscrowToken, GenesisSelfMigrationRecord } from './types.js';
5
+ import { jsonParseOr } from './safe-json.js';
5
6
 
6
7
  const DEFAULT_CONFIG: GenesisConfig = {
7
8
  intent: 'Improve workflow reliability and efficiency',
@@ -32,7 +33,8 @@ export class GenesisStore {
32
33
  fs.writeFileSync(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2), 'utf-8');
33
34
  return { ...DEFAULT_CONFIG };
34
35
  }
35
- const raw = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
36
+ const content = fs.readFileSync(configPath, 'utf-8');
37
+ const raw = jsonParseOr(content, {} as Record<string, unknown>, 'genesis config');
36
38
  return { ...DEFAULT_CONFIG, ...raw };
37
39
  }
38
40
 
@@ -46,7 +48,8 @@ export class GenesisStore {
46
48
  if (!fs.existsSync(historyPath)) {
47
49
  return { configHash: '', cycles: [] };
48
50
  }
49
- return JSON.parse(fs.readFileSync(historyPath, 'utf-8'));
51
+ const content = fs.readFileSync(historyPath, 'utf-8');
52
+ return jsonParseOr<GenesisHistory>(content, { configHash: '', cycles: [] }, 'genesis history');
50
53
  }
51
54
 
52
55
  appendCycle(cycle: GenesisCycleRecord): void {
@@ -79,11 +82,8 @@ export class GenesisStore {
79
82
  getLastFingerprint(): GenesisFingerprint | null {
80
83
  const fpPath = path.join(this.genesisDir, 'fingerprint.json');
81
84
  if (!fs.existsSync(fpPath)) return null;
82
- try {
83
- return JSON.parse(fs.readFileSync(fpPath, 'utf-8'));
84
- } catch {
85
- return null;
86
- }
85
+ const content = fs.readFileSync(fpPath, 'utf-8');
86
+ return jsonParseOr<GenesisFingerprint | null>(content, null, 'genesis fingerprint');
87
87
  }
88
88
 
89
89
  getRecentOutcomes(count: number): string[] {
@@ -109,11 +109,8 @@ export class GenesisStore {
109
109
  loadEscrowToken(): EscrowToken | null {
110
110
  const tokenPath = path.join(this.genesisDir, 'escrow', 'token.json');
111
111
  if (!fs.existsSync(tokenPath)) return null;
112
- try {
113
- return JSON.parse(fs.readFileSync(tokenPath, 'utf-8'));
114
- } catch {
115
- return null;
116
- }
112
+ const content = fs.readFileSync(tokenPath, 'utf-8');
113
+ return jsonParseOr<EscrowToken | null>(content, null, 'escrow token');
117
114
  }
118
115
 
119
116
  saveEscrowToken(token: EscrowToken): void {
@@ -145,11 +142,8 @@ export class GenesisStore {
145
142
  loadSelfHistory(): GenesisSelfMigrationRecord[] {
146
143
  const histPath = path.join(this.genesisDir, 'self-history.json');
147
144
  if (!fs.existsSync(histPath)) return [];
148
- try {
149
- return JSON.parse(fs.readFileSync(histPath, 'utf-8'));
150
- } catch {
151
- return [];
152
- }
145
+ const content = fs.readFileSync(histPath, 'utf-8');
146
+ return jsonParseOr<GenesisSelfMigrationRecord[]>(content, [], 'genesis self-history');
153
147
  }
154
148
 
155
149
  appendSelfMigration(record: GenesisSelfMigrationRecord): void {
package/src/bot/index.ts CHANGED
@@ -112,6 +112,11 @@ export { GenesisStore } from './genesis-store.js';
112
112
  export { withFileLock } from './file-lock.js';
113
113
  export type { FileLockOptions } from './file-lock.js';
114
114
 
115
+ // Safe utilities
116
+ export { safeJsonParse, jsonParseOr, parseNdjson } from './safe-json.js';
117
+ export type { SafeParseResult } from './safe-json.js';
118
+ export { safePath, safePathOrThrow } from './safe-path.js';
119
+
115
120
  // Shared modules
116
121
  export { callCli, callApi, parseJsonResponse } from './ai-client.js';
117
122
  export { executeStep } from './step-executor.js';
@@ -31,7 +31,13 @@ export class PipelineRunner {
31
31
  throw new Error(`Pipeline config not found: ${absPath}`);
32
32
  }
33
33
 
34
- const raw = JSON.parse(fs.readFileSync(absPath, 'utf-8')) as PipelineConfig;
34
+ let raw: PipelineConfig;
35
+ try {
36
+ raw = JSON.parse(fs.readFileSync(absPath, 'utf-8')) as PipelineConfig;
37
+ } catch (err) {
38
+ const msg = err instanceof Error ? err.message : String(err);
39
+ throw new Error(`Invalid JSON in pipeline config: ${absPath}\n ${msg}`);
40
+ }
35
41
  const configDir = path.dirname(absPath);
36
42
 
37
43
  // Resolve workflow paths relative to config file
@@ -3,6 +3,7 @@ import * as path from 'node:path';
3
3
  import * as crypto from 'node:crypto';
4
4
  import * as os from 'node:os';
5
5
  import type { RunRecord, RunFilter, RetentionPolicy } from './types.js';
6
+ import { parseNdjson } from './safe-json.js';
6
7
 
7
8
  export class RunStore {
8
9
  private readonly dir: string;
@@ -153,17 +154,7 @@ export class RunStore {
153
154
  if (!fs.existsSync(this.filePath)) return [];
154
155
 
155
156
  const content = fs.readFileSync(this.filePath, 'utf-8');
156
- const lines = content.split('\n').filter((line) => line.trim().length > 0);
157
- const records: RunRecord[] = [];
158
-
159
- for (const line of lines) {
160
- try {
161
- records.push(JSON.parse(line) as RunRecord);
162
- } catch {
163
- console.error('[weaver] Skipping corrupt history line');
164
- }
165
- }
166
-
157
+ const { records } = parseNdjson<RunRecord>(content, 'history');
167
158
  return records;
168
159
  }
169
160
  }
package/src/bot/runner.ts CHANGED
@@ -58,17 +58,29 @@ function resolveWeaverConfig(
58
58
  const dir = path.dirname(filePath);
59
59
  const localConfig = path.join(dir, '.weaver.json');
60
60
  if (fs.existsSync(localConfig)) {
61
- return JSON.parse(fs.readFileSync(localConfig, 'utf-8'));
61
+ return parseConfigFile(localConfig);
62
62
  }
63
63
 
64
64
  const cwdConfig = path.join(process.cwd(), '.weaver.json');
65
65
  if (fs.existsSync(cwdConfig)) {
66
- return JSON.parse(fs.readFileSync(cwdConfig, 'utf-8'));
66
+ return parseConfigFile(cwdConfig);
67
67
  }
68
68
 
69
69
  return { provider: 'auto' };
70
70
  }
71
71
 
72
+ function parseConfigFile(configPath: string): WeaverConfig {
73
+ const content = fs.readFileSync(configPath, 'utf-8');
74
+ try {
75
+ return JSON.parse(content) as WeaverConfig;
76
+ } catch {
77
+ throw new Error(
78
+ `Invalid JSON in config file: ${configPath}\n` +
79
+ ` Fix the file or delete it to use defaults.`,
80
+ );
81
+ }
82
+ }
83
+
72
84
  function buildSummary(result: unknown): string {
73
85
  if (!result || typeof result !== 'object') return String(result);
74
86
 
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Safe JSON parsing utilities.
3
+ *
4
+ * Wraps JSON.parse with proper error handling and optional context for
5
+ * meaningful error messages. Prevents crashes from malformed config files,
6
+ * corrupt NDJSON lines, or unexpected AI output.
7
+ */
8
+
9
+ export type SafeParseResult<T> = {
10
+ ok: true;
11
+ value: T;
12
+ } | {
13
+ ok: false;
14
+ error: string;
15
+ };
16
+
17
+ /**
18
+ * Parse JSON safely, returning a discriminated result instead of throwing.
19
+ */
20
+ export function safeJsonParse<T = unknown>(
21
+ text: string,
22
+ context?: string,
23
+ ): SafeParseResult<T> {
24
+ try {
25
+ return { ok: true, value: JSON.parse(text) as T };
26
+ } catch (err: unknown) {
27
+ const msg = err instanceof Error ? err.message : String(err);
28
+ const prefix = context ? `${context}: ` : '';
29
+ return { ok: false, error: `${prefix}Invalid JSON — ${msg}` };
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Parse JSON or return a fallback value on failure.
35
+ * Optionally logs a warning when parsing fails.
36
+ */
37
+ export function jsonParseOr<T>(
38
+ text: string,
39
+ fallback: T,
40
+ context?: string,
41
+ ): T {
42
+ const result = safeJsonParse<T>(text, context);
43
+ if (result.ok) return result.value;
44
+ if (context) {
45
+ console.error(`[weaver] ${result.error}`);
46
+ }
47
+ return fallback;
48
+ }
49
+
50
+ /**
51
+ * Parse NDJSON (newline-delimited JSON) safely.
52
+ * Skips corrupt lines and optionally reports them.
53
+ */
54
+ export function parseNdjson<T>(
55
+ content: string,
56
+ context?: string,
57
+ ): { records: T[]; errors: number } {
58
+ const lines = content.split('\n').filter((line) => line.trim().length > 0);
59
+ const records: T[] = [];
60
+ let errors = 0;
61
+
62
+ for (const line of lines) {
63
+ const result = safeJsonParse<T>(line);
64
+ if (result.ok) {
65
+ records.push(result.value);
66
+ } else {
67
+ errors++;
68
+ }
69
+ }
70
+
71
+ if (errors > 0 && context) {
72
+ console.error(`[weaver] ${context}: skipped ${errors} corrupt line(s)`);
73
+ }
74
+
75
+ return { records, errors };
76
+ }