@telepat/snoopy 0.1.4

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 (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +255 -0
  3. package/dist/src/cli/commands/analytics.d.ts +3 -0
  4. package/dist/src/cli/commands/analytics.js +147 -0
  5. package/dist/src/cli/commands/analytics.js.map +1 -0
  6. package/dist/src/cli/commands/daemon.d.ts +5 -0
  7. package/dist/src/cli/commands/daemon.js +85 -0
  8. package/dist/src/cli/commands/daemon.js.map +1 -0
  9. package/dist/src/cli/commands/doctor.d.ts +1 -0
  10. package/dist/src/cli/commands/doctor.js +106 -0
  11. package/dist/src/cli/commands/doctor.js.map +1 -0
  12. package/dist/src/cli/commands/errors.d.ts +3 -0
  13. package/dist/src/cli/commands/errors.js +51 -0
  14. package/dist/src/cli/commands/errors.js.map +1 -0
  15. package/dist/src/cli/commands/export.d.ts +1 -0
  16. package/dist/src/cli/commands/export.js +48 -0
  17. package/dist/src/cli/commands/export.js.map +1 -0
  18. package/dist/src/cli/commands/job.d.ts +16 -0
  19. package/dist/src/cli/commands/job.js +350 -0
  20. package/dist/src/cli/commands/job.js.map +1 -0
  21. package/dist/src/cli/commands/logs.d.ts +3 -0
  22. package/dist/src/cli/commands/logs.js +44 -0
  23. package/dist/src/cli/commands/logs.js.map +1 -0
  24. package/dist/src/cli/commands/selection.d.ts +19 -0
  25. package/dist/src/cli/commands/selection.js +182 -0
  26. package/dist/src/cli/commands/selection.js.map +1 -0
  27. package/dist/src/cli/commands/settings.d.ts +1 -0
  28. package/dist/src/cli/commands/settings.js +31 -0
  29. package/dist/src/cli/commands/settings.js.map +1 -0
  30. package/dist/src/cli/commands/startup.d.ts +5 -0
  31. package/dist/src/cli/commands/startup.js +26 -0
  32. package/dist/src/cli/commands/startup.js.map +1 -0
  33. package/dist/src/cli/flows/jobAddFlow.d.ts +26 -0
  34. package/dist/src/cli/flows/jobAddFlow.js +209 -0
  35. package/dist/src/cli/flows/jobAddFlow.js.map +1 -0
  36. package/dist/src/cli/flows/settingsFlow.d.ts +15 -0
  37. package/dist/src/cli/flows/settingsFlow.js +180 -0
  38. package/dist/src/cli/flows/settingsFlow.js.map +1 -0
  39. package/dist/src/cli/flows/settingsFlowModel.d.ts +47 -0
  40. package/dist/src/cli/flows/settingsFlowModel.js +143 -0
  41. package/dist/src/cli/flows/settingsFlowModel.js.map +1 -0
  42. package/dist/src/cli/index.d.ts +2 -0
  43. package/dist/src/cli/index.js +138 -0
  44. package/dist/src/cli/index.js.map +1 -0
  45. package/dist/src/cli/ui/consoleUi.d.ts +13 -0
  46. package/dist/src/cli/ui/consoleUi.js +165 -0
  47. package/dist/src/cli/ui/consoleUi.js.map +1 -0
  48. package/dist/src/cli/ui/time.d.ts +9 -0
  49. package/dist/src/cli/ui/time.js +35 -0
  50. package/dist/src/cli/ui/time.js.map +1 -0
  51. package/dist/src/index.d.ts +1 -0
  52. package/dist/src/index.js +2 -0
  53. package/dist/src/index.js.map +1 -0
  54. package/dist/src/scripts/e2eSmoke.d.ts +1 -0
  55. package/dist/src/scripts/e2eSmoke.js +102 -0
  56. package/dist/src/scripts/e2eSmoke.js.map +1 -0
  57. package/dist/src/services/analytics/analyticsService.d.ts +50 -0
  58. package/dist/src/services/analytics/analyticsService.js +88 -0
  59. package/dist/src/services/analytics/analyticsService.js.map +1 -0
  60. package/dist/src/services/daemonControl.d.ts +12 -0
  61. package/dist/src/services/daemonControl.js +58 -0
  62. package/dist/src/services/daemonControl.js.map +1 -0
  63. package/dist/src/services/db/repositories/jobsRepo.d.ts +19 -0
  64. package/dist/src/services/db/repositories/jobsRepo.js +164 -0
  65. package/dist/src/services/db/repositories/jobsRepo.js.map +1 -0
  66. package/dist/src/services/db/repositories/runsRepo.d.ts +58 -0
  67. package/dist/src/services/db/repositories/runsRepo.js +190 -0
  68. package/dist/src/services/db/repositories/runsRepo.js.map +1 -0
  69. package/dist/src/services/db/repositories/scanItemsRepo.d.ts +69 -0
  70. package/dist/src/services/db/repositories/scanItemsRepo.js +176 -0
  71. package/dist/src/services/db/repositories/scanItemsRepo.js.map +1 -0
  72. package/dist/src/services/db/repositories/settingsRepo.d.ts +14 -0
  73. package/dist/src/services/db/repositories/settingsRepo.js +132 -0
  74. package/dist/src/services/db/repositories/settingsRepo.js.map +1 -0
  75. package/dist/src/services/db/sqlite.d.ts +2 -0
  76. package/dist/src/services/db/sqlite.js +192 -0
  77. package/dist/src/services/db/sqlite.js.map +1 -0
  78. package/dist/src/services/export/csvResults.d.ts +10 -0
  79. package/dist/src/services/export/csvResults.js +42 -0
  80. package/dist/src/services/export/csvResults.js.map +1 -0
  81. package/dist/src/services/logging/logReader.d.ts +4 -0
  82. package/dist/src/services/logging/logReader.js +230 -0
  83. package/dist/src/services/logging/logReader.js.map +1 -0
  84. package/dist/src/services/logging/logRotation.d.ts +1 -0
  85. package/dist/src/services/logging/logRotation.js +30 -0
  86. package/dist/src/services/logging/logRotation.js.map +1 -0
  87. package/dist/src/services/logging/runLogger.d.ts +9 -0
  88. package/dist/src/services/logging/runLogger.js +42 -0
  89. package/dist/src/services/logging/runLogger.js.map +1 -0
  90. package/dist/src/services/openrouter/client.d.ts +60 -0
  91. package/dist/src/services/openrouter/client.js +437 -0
  92. package/dist/src/services/openrouter/client.js.map +1 -0
  93. package/dist/src/services/openrouter/prompts.d.ts +5 -0
  94. package/dist/src/services/openrouter/prompts.js +48 -0
  95. package/dist/src/services/openrouter/prompts.js.map +1 -0
  96. package/dist/src/services/reddit/client.d.ts +25 -0
  97. package/dist/src/services/reddit/client.js +186 -0
  98. package/dist/src/services/reddit/client.js.map +1 -0
  99. package/dist/src/services/scheduler/cronScheduler.d.ts +11 -0
  100. package/dist/src/services/scheduler/cronScheduler.js +76 -0
  101. package/dist/src/services/scheduler/cronScheduler.js.map +1 -0
  102. package/dist/src/services/scheduler/jobRunner.d.ts +76 -0
  103. package/dist/src/services/scheduler/jobRunner.js +414 -0
  104. package/dist/src/services/scheduler/jobRunner.js.map +1 -0
  105. package/dist/src/services/scheduler/jobRunnerStub.d.ts +5 -0
  106. package/dist/src/services/scheduler/jobRunnerStub.js +11 -0
  107. package/dist/src/services/scheduler/jobRunnerStub.js.map +1 -0
  108. package/dist/src/services/security/secretStore.d.ts +6 -0
  109. package/dist/src/services/security/secretStore.js +193 -0
  110. package/dist/src/services/security/secretStore.js.map +1 -0
  111. package/dist/src/services/startup/index.d.ts +13 -0
  112. package/dist/src/services/startup/index.js +120 -0
  113. package/dist/src/services/startup/index.js.map +1 -0
  114. package/dist/src/services/startup/linuxCronFallback.d.ts +2 -0
  115. package/dist/src/services/startup/linuxCronFallback.js +29 -0
  116. package/dist/src/services/startup/linuxCronFallback.js.map +1 -0
  117. package/dist/src/services/startup/linuxSystemd.d.ts +3 -0
  118. package/dist/src/services/startup/linuxSystemd.js +47 -0
  119. package/dist/src/services/startup/linuxSystemd.js.map +1 -0
  120. package/dist/src/services/startup/macosLaunchd.d.ts +2 -0
  121. package/dist/src/services/startup/macosLaunchd.js +40 -0
  122. package/dist/src/services/startup/macosLaunchd.js.map +1 -0
  123. package/dist/src/services/startup/windowsRunFallback.d.ts +2 -0
  124. package/dist/src/services/startup/windowsRunFallback.js +17 -0
  125. package/dist/src/services/startup/windowsRunFallback.js.map +1 -0
  126. package/dist/src/services/startup/windowsTaskScheduler.d.ts +2 -0
  127. package/dist/src/services/startup/windowsTaskScheduler.js +16 -0
  128. package/dist/src/services/startup/windowsTaskScheduler.js.map +1 -0
  129. package/dist/src/types/job.d.ts +34 -0
  130. package/dist/src/types/job.js +2 -0
  131. package/dist/src/types/job.js.map +1 -0
  132. package/dist/src/types/settings.d.ts +35 -0
  133. package/dist/src/types/settings.js +8 -0
  134. package/dist/src/types/settings.js.map +1 -0
  135. package/dist/src/ui/components/AppFrame.d.ts +17 -0
  136. package/dist/src/ui/components/AppFrame.js +26 -0
  137. package/dist/src/ui/components/AppFrame.js.map +1 -0
  138. package/dist/src/ui/components/CliHeader.d.ts +8 -0
  139. package/dist/src/ui/components/CliHeader.js +8 -0
  140. package/dist/src/ui/components/CliHeader.js.map +1 -0
  141. package/dist/src/ui/components/SubredditMultiSelect.d.ts +7 -0
  142. package/dist/src/ui/components/SubredditMultiSelect.js +91 -0
  143. package/dist/src/ui/components/SubredditMultiSelect.js.map +1 -0
  144. package/dist/src/ui/components/TextPrompt.d.ts +10 -0
  145. package/dist/src/ui/components/TextPrompt.js +13 -0
  146. package/dist/src/ui/components/TextPrompt.js.map +1 -0
  147. package/dist/src/ui/components/YesNoSelector.d.ts +10 -0
  148. package/dist/src/ui/components/YesNoSelector.js +25 -0
  149. package/dist/src/ui/components/YesNoSelector.js.map +1 -0
  150. package/dist/src/ui/components/subredditOptions.d.ts +5 -0
  151. package/dist/src/ui/components/subredditOptions.js +14 -0
  152. package/dist/src/ui/components/subredditOptions.js.map +1 -0
  153. package/dist/src/ui/components/yesNoSelectorModel.d.ts +9 -0
  154. package/dist/src/ui/components/yesNoSelectorModel.js +23 -0
  155. package/dist/src/ui/components/yesNoSelectorModel.js.map +1 -0
  156. package/dist/src/ui/theme.d.ts +26 -0
  157. package/dist/src/ui/theme.js +37 -0
  158. package/dist/src/ui/theme.js.map +1 -0
  159. package/dist/src/utils/logger.d.ts +5 -0
  160. package/dist/src/utils/logger.js +15 -0
  161. package/dist/src/utils/logger.js.map +1 -0
  162. package/dist/src/utils/notify.d.ts +6 -0
  163. package/dist/src/utils/notify.js +14 -0
  164. package/dist/src/utils/notify.js.map +1 -0
  165. package/dist/src/utils/paths.d.ts +10 -0
  166. package/dist/src/utils/paths.js +24 -0
  167. package/dist/src/utils/paths.js.map +1 -0
  168. package/dist/src/utils/scanLogFormatting.d.ts +26 -0
  169. package/dist/src/utils/scanLogFormatting.js +60 -0
  170. package/dist/src/utils/scanLogFormatting.js.map +1 -0
  171. package/package.json +74 -0
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ interface TextPromptProps {
3
+ label: string;
4
+ placeholder?: string;
5
+ secret?: boolean;
6
+ initialValue?: string;
7
+ onSubmit: (value: string) => void;
8
+ }
9
+ export declare function TextPrompt({ label, placeholder, secret, initialValue, onSubmit }: TextPromptProps): React.JSX.Element;
10
+ export {};
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from 'ink';
3
+ import { PasswordInput, TextInput } from '@inkjs/ui';
4
+ import { uiTheme } from '../theme.js';
5
+ export function TextPrompt({ label, placeholder, secret = false, initialValue = '', onSubmit }) {
6
+ const inputKey = `${secret ? 'secret' : 'text'}:${label}:${initialValue}`;
7
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: uiTheme.ink.accent, children: label }), secret ? (_jsx(PasswordInput, { placeholder: placeholder, onSubmit: (value) => {
8
+ onSubmit(value.trim());
9
+ } }, inputKey)) : (_jsx(TextInput, { defaultValue: initialValue, placeholder: placeholder, onSubmit: (value) => {
10
+ onSubmit(value.trim());
11
+ } }, inputKey)), _jsx(Text, { color: uiTheme.ink.textMuted, children: "Press Enter to continue" })] }));
12
+ }
13
+ //# sourceMappingURL=TextPrompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextPrompt.js","sourceRoot":"","sources":["../../../../src/ui/components/TextPrompt.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAUtC,MAAM,UAAU,UAAU,CAAC,EACzB,KAAK,EACL,WAAW,EACX,MAAM,GAAG,KAAK,EACd,YAAY,GAAG,EAAE,EACjB,QAAQ,EACQ;IAChB,MAAM,QAAQ,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,IAAI,KAAK,IAAI,YAAY,EAAE,CAAC;IAE1E,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,SAAS,EAAE,CAAC,aACtC,KAAC,IAAI,IAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,YAAG,KAAK,GAAQ,EAC9C,MAAM,CAAC,CAAC,CAAC,CACR,KAAC,aAAa,IAEZ,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;oBAClB,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;gBACzB,CAAC,IAJI,QAAQ,CAKb,CACH,CAAC,CAAC,CAAC,CACF,KAAC,SAAS,IAER,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;oBAClB,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;gBACzB,CAAC,IALI,QAAQ,CAMb,CACH,EACD,KAAC,IAAI,IAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,wCAAgC,IAC9D,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ interface YesNoSelectorProps {
3
+ label: string;
4
+ defaultValue?: boolean;
5
+ yesLabel?: string;
6
+ noLabel?: string;
7
+ onSubmit: (value: boolean) => void;
8
+ }
9
+ export declare function YesNoSelector({ label, defaultValue, yesLabel, noLabel, onSubmit }: YesNoSelectorProps): React.JSX.Element;
10
+ export {};
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { Box, Text, useInput } from 'ink';
4
+ import { uiTheme } from '../theme.js';
5
+ import { cursorForDefaultValue, moveCursor, parseYesNoShortcut, selectionFromCursor } from './yesNoSelectorModel.js';
6
+ export function YesNoSelector({ label, defaultValue = true, yesLabel = 'Yes', noLabel = 'No', onSubmit }) {
7
+ const [cursor, setCursor] = useState(cursorForDefaultValue(defaultValue));
8
+ useInput((input, key) => {
9
+ const shortcutChoice = parseYesNoShortcut(input);
10
+ if (shortcutChoice !== null) {
11
+ onSubmit(shortcutChoice);
12
+ return;
13
+ }
14
+ if (key.return) {
15
+ onSubmit(selectionFromCursor(cursor));
16
+ return;
17
+ }
18
+ const nextCursor = moveCursor(cursor, key);
19
+ if (nextCursor !== cursor) {
20
+ setCursor(nextCursor);
21
+ }
22
+ });
23
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: uiTheme.ink.accent, children: label }), _jsxs(Text, { color: cursor === 0 ? uiTheme.ink.focus : uiTheme.ink.textPrimary, inverse: cursor === 0, children: [cursor === 0 ? '>' : ' ', " ", yesLabel] }), _jsxs(Text, { color: cursor === 1 ? uiTheme.ink.focus : uiTheme.ink.textPrimary, inverse: cursor === 1, children: [cursor === 1 ? '>' : ' ', " ", noLabel] }), _jsx(Text, { color: uiTheme.ink.textMuted, children: "Use Up/Down to switch, Enter to confirm, or press Y/N." })] }));
24
+ }
25
+ //# sourceMappingURL=YesNoSelector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"YesNoSelector.js","sourceRoot":"","sources":["../../../../src/ui/components/YesNoSelector.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EACL,qBAAqB,EACrB,UAAU,EACV,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,yBAAyB,CAAC;AAUjC,MAAM,UAAU,aAAa,CAAC,EAC5B,KAAK,EACL,YAAY,GAAG,IAAI,EACnB,QAAQ,GAAG,KAAK,EAChB,OAAO,GAAG,IAAI,EACd,QAAQ,EACW;IACnB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAQ,qBAAqB,CAAC,YAAY,CAAC,CAAC,CAAC;IAEjF,QAAQ,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtB,MAAM,cAAc,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACjD,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;YAC5B,QAAQ,CAAC,cAAc,CAAC,CAAC;YACzB,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACf,QAAQ,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC;YACtC,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC3C,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;YAC1B,SAAS,CAAC,UAAU,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,SAAS,EAAE,CAAC,aACtC,KAAC,IAAI,IAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,YAAG,KAAK,GAAQ,EAC/C,MAAC,IAAI,IAAC,KAAK,EAAE,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC,aAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,OAAG,QAAQ,IAAQ,EAC5I,MAAC,IAAI,IAAC,KAAK,EAAE,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC,aAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,OAAG,OAAO,IAAQ,EAC3I,KAAC,IAAI,IAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,uEAA+D,IAC7F,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function normalizeSubreddit(value: string): string;
2
+ export declare function resolveCustomSubreddit(options: string[], rawInput: string): {
3
+ normalized: string | null;
4
+ nextOptions: string[];
5
+ };
@@ -0,0 +1,14 @@
1
+ export function normalizeSubreddit(value) {
2
+ return value.trim().replace(/^r\//i, '').replace(/\s+/g, '');
3
+ }
4
+ export function resolveCustomSubreddit(options, rawInput) {
5
+ const normalized = normalizeSubreddit(rawInput);
6
+ if (!normalized) {
7
+ return { normalized: null, nextOptions: options };
8
+ }
9
+ if (options.includes(normalized)) {
10
+ return { normalized, nextOptions: options };
11
+ }
12
+ return { normalized, nextOptions: [...options, normalized] };
13
+ }
14
+ //# sourceMappingURL=subredditOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subredditOptions.js","sourceRoot":"","sources":["../../../../src/ui/components/subredditOptions.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,OAAiB,EACjB,QAAgB;IAEhB,MAAM,UAAU,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;IACpD,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;IAC9C,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,GAAG,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare function cursorForDefaultValue(defaultValue: boolean): 0 | 1;
2
+ export declare function moveCursor(current: 0 | 1, key: {
3
+ upArrow?: boolean;
4
+ downArrow?: boolean;
5
+ leftArrow?: boolean;
6
+ rightArrow?: boolean;
7
+ }): 0 | 1;
8
+ export declare function parseYesNoShortcut(input: string): boolean | null;
9
+ export declare function selectionFromCursor(cursor: 0 | 1): boolean;
@@ -0,0 +1,23 @@
1
+ export function cursorForDefaultValue(defaultValue) {
2
+ return defaultValue ? 0 : 1;
3
+ }
4
+ export function moveCursor(current, key) {
5
+ if (key.upArrow || key.downArrow || key.leftArrow || key.rightArrow) {
6
+ return current === 0 ? 1 : 0;
7
+ }
8
+ return current;
9
+ }
10
+ export function parseYesNoShortcut(input) {
11
+ const normalized = input.trim().toLowerCase();
12
+ if (normalized.startsWith('y')) {
13
+ return true;
14
+ }
15
+ if (normalized.startsWith('n')) {
16
+ return false;
17
+ }
18
+ return null;
19
+ }
20
+ export function selectionFromCursor(cursor) {
21
+ return cursor === 0;
22
+ }
23
+ //# sourceMappingURL=yesNoSelectorModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yesNoSelectorModel.js","sourceRoot":"","sources":["../../../../src/ui/components/yesNoSelectorModel.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,qBAAqB,CAAC,YAAqB;IACzD,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,OAAc,EACd,GAKC;IAED,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACpE,OAAO,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9C,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAa;IAC/C,OAAO,MAAM,KAAK,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,26 @@
1
+ export type ColorSupportLevel = 'ansi16' | 'ansi256' | 'truecolor';
2
+ export interface UiTheme {
3
+ readonly compactBreakpoint: number;
4
+ readonly preferredLineLength: number;
5
+ readonly wrapWarningLength: number;
6
+ readonly ink: {
7
+ readonly accent: 'cyan';
8
+ readonly accentStrong: 'cyanBright';
9
+ readonly focus: 'yellow';
10
+ readonly textPrimary: 'white';
11
+ readonly textMuted: 'gray';
12
+ readonly info: 'blue';
13
+ readonly success: 'green';
14
+ readonly warning: 'yellow';
15
+ readonly danger: 'red';
16
+ };
17
+ readonly symbols: {
18
+ readonly sentimentPositive: '+';
19
+ readonly sentimentNeutral: 'o';
20
+ readonly sentimentNegative: '-';
21
+ readonly sentimentInfo: 'i';
22
+ };
23
+ }
24
+ export declare const uiTheme: UiTheme;
25
+ export declare function detectColorSupportLevel(env?: NodeJS.ProcessEnv): ColorSupportLevel;
26
+ export declare function shouldUseCompactLayout(columns: number, breakpoint?: number): boolean;
@@ -0,0 +1,37 @@
1
+ export const uiTheme = {
2
+ compactBreakpoint: 80,
3
+ preferredLineLength: 66,
4
+ wrapWarningLength: 75,
5
+ ink: {
6
+ accent: 'cyan',
7
+ accentStrong: 'cyanBright',
8
+ focus: 'yellow',
9
+ textPrimary: 'white',
10
+ textMuted: 'gray',
11
+ info: 'blue',
12
+ success: 'green',
13
+ warning: 'yellow',
14
+ danger: 'red'
15
+ },
16
+ symbols: {
17
+ sentimentPositive: '+',
18
+ sentimentNeutral: 'o',
19
+ sentimentNegative: '-',
20
+ sentimentInfo: 'i'
21
+ }
22
+ };
23
+ export function detectColorSupportLevel(env = process.env) {
24
+ const colorterm = (env.COLORTERM ?? '').toLowerCase();
25
+ if (colorterm.includes('truecolor') || colorterm.includes('24bit')) {
26
+ return 'truecolor';
27
+ }
28
+ const term = (env.TERM ?? '').toLowerCase();
29
+ if (term.includes('256color')) {
30
+ return 'ansi256';
31
+ }
32
+ return 'ansi16';
33
+ }
34
+ export function shouldUseCompactLayout(columns, breakpoint = uiTheme.compactBreakpoint) {
35
+ return columns < breakpoint;
36
+ }
37
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../../src/ui/theme.ts"],"names":[],"mappings":"AAyBA,MAAM,CAAC,MAAM,OAAO,GAAY;IAC9B,iBAAiB,EAAE,EAAE;IACrB,mBAAmB,EAAE,EAAE;IACvB,iBAAiB,EAAE,EAAE;IACrB,GAAG,EAAE;QACH,MAAM,EAAE,MAAM;QACd,YAAY,EAAE,YAAY;QAC1B,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,OAAO;QACpB,SAAS,EAAE,MAAM;QACjB,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,QAAQ;QACjB,MAAM,EAAE,KAAK;KACd;IACD,OAAO,EAAE;QACP,iBAAiB,EAAE,GAAG;QACtB,gBAAgB,EAAE,GAAG;QACrB,iBAAiB,EAAE,GAAG;QACtB,aAAa,EAAE,GAAG;KACnB;CACF,CAAC;AAEF,MAAM,UAAU,uBAAuB,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC1E,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACtD,IAAI,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACnE,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAe,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB;IAC5F,OAAO,OAAO,GAAG,UAAU,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const logger: {
2
+ info: (message: string) => void;
3
+ warn: (message: string) => void;
4
+ error: (message: string) => void;
5
+ };
@@ -0,0 +1,15 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { ensureAppDirs } from './paths.js';
4
+ function write(level, message) {
5
+ const paths = ensureAppDirs();
6
+ const line = `[${new Date().toISOString()}] [${level}] ${message}\n`;
7
+ const file = path.join(paths.logsDir, 'snoopy.log');
8
+ fs.appendFileSync(file, line);
9
+ }
10
+ export const logger = {
11
+ info: (message) => write('INFO', message),
12
+ warn: (message) => write('WARN', message),
13
+ error: (message) => write('ERROR', message)
14
+ };
15
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,SAAS,KAAK,CAAC,KAAa,EAAE,OAAe;IAC3C,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;IAC9B,MAAM,IAAI,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,KAAK,OAAO,IAAI,CAAC;IACrE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACpD,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC;IACjD,IAAI,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC;IACjD,KAAK,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;CACpD,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare function sendJobNotification({ jobName, qualifiedCount, discoveredCount, newCount }: {
2
+ jobName: string;
3
+ qualifiedCount: number;
4
+ discoveredCount?: number;
5
+ newCount?: number;
6
+ }): void;
@@ -0,0 +1,14 @@
1
+ // Notification utility for job completion
2
+ import notifier from 'node-notifier';
3
+ export function sendJobNotification({ jobName, qualifiedCount, discoveredCount, newCount }) {
4
+ const message = `${qualifiedCount} post${qualifiedCount === 1 ? '' : 's'} qualified` +
5
+ (typeof discoveredCount === 'number' && typeof newCount === 'number'
6
+ ? ` (out of ${discoveredCount} scanned, ${newCount} new)`
7
+ : '');
8
+ notifier.notify({
9
+ title: `Job Complete: ${jobName}`,
10
+ message,
11
+ wait: false
12
+ });
13
+ }
14
+ //# sourceMappingURL=notify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify.js","sourceRoot":"","sources":["../../../src/utils/notify.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,OAAO,QAAQ,MAAM,eAAe,CAAC;AAErC,MAAM,UAAU,mBAAmB,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,EAKvF;IACC,MAAM,OAAO,GAAG,GAAG,cAAc,QAAQ,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,YAAY;QAClF,CAAC,OAAO,eAAe,KAAK,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAClE,CAAC,CAAC,YAAY,eAAe,aAAa,QAAQ,OAAO;YACzD,CAAC,CAAC,EAAE,CAAC,CAAC;IACV,QAAQ,CAAC,MAAM,CAAC;QACd,KAAK,EAAE,iBAAiB,OAAO,EAAE;QACjC,OAAO;QACP,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,10 @@
1
+ export interface AppPaths {
2
+ rootDir: string;
3
+ dbPath: string;
4
+ logsDir: string;
5
+ resultsDir: string;
6
+ pidFilePath: string;
7
+ startupDir: string;
8
+ }
9
+ export declare function getAppPaths(): AppPaths;
10
+ export declare function ensureAppDirs(): AppPaths;
@@ -0,0 +1,24 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ export function getAppPaths() {
5
+ const rootDir = process.env.SNOOPY_ROOT_DIR || path.join(os.homedir(), '.snoopy');
6
+ return {
7
+ rootDir,
8
+ dbPath: path.join(rootDir, 'snoopy.db'),
9
+ logsDir: path.join(rootDir, 'logs'),
10
+ resultsDir: path.join(rootDir, 'results'),
11
+ pidFilePath: path.join(rootDir, 'daemon.pid'),
12
+ startupDir: path.join(rootDir, 'startup')
13
+ };
14
+ }
15
+ export function ensureAppDirs() {
16
+ const paths = getAppPaths();
17
+ [paths.rootDir, paths.logsDir, paths.resultsDir, paths.startupDir].forEach((dir) => {
18
+ if (!fs.existsSync(dir)) {
19
+ fs.mkdirSync(dir, { recursive: true });
20
+ }
21
+ });
22
+ return paths;
23
+ }
24
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAW7B,MAAM,UAAU,WAAW;IACzB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IAClF,OAAO;QACL,OAAO;QACP,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC;QACvC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC;QACnC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC;QACzC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC;QAC7C,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC;KAC1C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC;IAC5B,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QACjF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,26 @@
1
+ export declare const DEFAULT_SCAN_SNIPPET_LENGTH = 120;
2
+ export declare function toSnippet(value: string | null | undefined, maxLength?: number): string;
3
+ export interface PostScanLineInput {
4
+ postId: string;
5
+ title?: string;
6
+ bodySnippet?: string;
7
+ qualified?: boolean;
8
+ qualificationReason?: string;
9
+ postUrl?: string;
10
+ itemsNew?: number;
11
+ itemsQualified?: number;
12
+ }
13
+ export interface CommentScanLineInput {
14
+ postId: string;
15
+ commentId: string;
16
+ author: string;
17
+ commentSnippet?: string;
18
+ qualified?: boolean;
19
+ qualificationReason?: string;
20
+ postUrl?: string;
21
+ commentUrl?: string;
22
+ itemsNew?: number;
23
+ itemsQualified?: number;
24
+ }
25
+ export declare function formatPostScanLine(input: PostScanLineInput): string;
26
+ export declare function formatCommentScanLine(input: CommentScanLineInput): string;
@@ -0,0 +1,60 @@
1
+ export const DEFAULT_SCAN_SNIPPET_LENGTH = 120;
2
+ function normalizeWhitespace(value) {
3
+ if (!value) {
4
+ return '';
5
+ }
6
+ return value.replace(/\s+/g, ' ').trim();
7
+ }
8
+ export function toSnippet(value, maxLength = DEFAULT_SCAN_SNIPPET_LENGTH) {
9
+ const normalized = normalizeWhitespace(value);
10
+ if (!normalized) {
11
+ return '';
12
+ }
13
+ if (normalized.length <= maxLength) {
14
+ return normalized;
15
+ }
16
+ return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}...`;
17
+ }
18
+ function formatReason(reason) {
19
+ const normalized = normalizeWhitespace(reason);
20
+ return normalized || 'No justification provided.';
21
+ }
22
+ function formatOutcome(qualified, reason) {
23
+ if (qualified === undefined) {
24
+ return 'qualification pending';
25
+ }
26
+ return `${qualified ? 'qualified' : 'not qualified'} (reason: ${formatReason(reason)})`;
27
+ }
28
+ function maybePush(parts, value) {
29
+ if (!value) {
30
+ return;
31
+ }
32
+ parts.push(value);
33
+ }
34
+ export function formatPostScanLine(input) {
35
+ const title = toSnippet(input.title, 80);
36
+ const snippet = toSnippet(input.bodySnippet);
37
+ const parts = [title ? `Post "${title}"` : 'Post'];
38
+ maybePush(parts, snippet ? `snippet: ${snippet}` : undefined);
39
+ parts.push(formatOutcome(input.qualified, input.qualificationReason));
40
+ maybePush(parts, input.postUrl ? `post: ${input.postUrl}` : undefined);
41
+ parts.push(`id: ${input.postId}`);
42
+ if (typeof input.itemsNew === 'number' && typeof input.itemsQualified === 'number') {
43
+ parts.push(`totals new=${input.itemsNew}, qualified=${input.itemsQualified}`);
44
+ }
45
+ return parts.join(' | ');
46
+ }
47
+ export function formatCommentScanLine(input) {
48
+ const snippet = toSnippet(input.commentSnippet);
49
+ const parts = [snippet ? `Comment "${snippet}"` : `Comment by ${input.author}`];
50
+ parts.push(`author: ${input.author}`);
51
+ parts.push(formatOutcome(input.qualified, input.qualificationReason));
52
+ maybePush(parts, input.commentUrl ? `comment: ${input.commentUrl}` : undefined);
53
+ maybePush(parts, input.postUrl ? `post: ${input.postUrl}` : undefined);
54
+ parts.push(`ids: comment=${input.commentId}, post=${input.postId}`);
55
+ if (typeof input.itemsNew === 'number' && typeof input.itemsQualified === 'number') {
56
+ parts.push(`totals new=${input.itemsNew}, qualified=${input.itemsQualified}`);
57
+ }
58
+ return parts.join(' | ');
59
+ }
60
+ //# sourceMappingURL=scanLogFormatting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanLogFormatting.js","sourceRoot":"","sources":["../../../src/utils/scanLogFormatting.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@telepat/snoopy",
3
+ "version": "0.1.4",
4
+ "description": "Snoopy CLI for Reddit conversation monitoring jobs.",
5
+ "type": "module",
6
+ "main": "dist/src/index.js",
7
+ "bin": {
8
+ "snoopy": "dist/src/cli/index.js"
9
+ },
10
+ "files": [
11
+ "dist/src",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "engines": {
16
+ "node": ">=18.0.0"
17
+ },
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "dev": "tsx src/cli/index.ts",
21
+ "docs:start": "npm --prefix website run start",
22
+ "docs:build": "npm --prefix website run build",
23
+ "docs:serve": "npm --prefix website run serve",
24
+ "docs:deploy": "npm --prefix website run deploy",
25
+ "e2e:smoke": "tsx src/scripts/e2eSmoke.ts",
26
+ "lint": "eslint src tests --ext .ts,.tsx",
27
+ "test": "jest",
28
+ "typecheck": "tsc --noEmit",
29
+ "prepublishOnly": "npm run lint && npm run build && npm test"
30
+ },
31
+ "keywords": [
32
+ "reddit",
33
+ "monitoring",
34
+ "cli",
35
+ "scheduler",
36
+ "ai"
37
+ ],
38
+ "author": "",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/telepat-io/snoopy.git"
42
+ },
43
+ "bugs": {
44
+ "url": "https://github.com/telepat-io/snoopy/issues"
45
+ },
46
+ "homepage": "https://docs.telepat.io/ideon/",
47
+ "license": "ISC",
48
+ "dependencies": {
49
+ "@inkjs/ui": "^2.0.0",
50
+ "better-sqlite3": "^12.8.0",
51
+ "commander": "^14.0.3",
52
+ "ink": "^6.8.0",
53
+ "keytar": "^7.9.0",
54
+ "node-cron": "^4.2.1",
55
+ "node-notifier": "^10.0.1",
56
+ "openai": "^6.32.0",
57
+ "react": "^19.2.4",
58
+ "zod": "^4.3.6"
59
+ },
60
+ "devDependencies": {
61
+ "@eslint/js": "^9.39.1",
62
+ "@types/better-sqlite3": "^7.6.13",
63
+ "@types/jest": "^29.5.14",
64
+ "@types/node": "^25.5.0",
65
+ "@types/node-notifier": "^8.0.5",
66
+ "@types/react": "^19.2.14",
67
+ "eslint": "^9.39.1",
68
+ "jest": "^29.7.0",
69
+ "ts-jest": "^29.2.5",
70
+ "tsx": "^4.21.0",
71
+ "typescript": "^5.9.3",
72
+ "typescript-eslint": "^8.57.1"
73
+ }
74
+ }