kiro-memory 1.8.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -4
- package/plugin/dist/cli/contextkit.js +428 -205
- package/plugin/dist/hooks/agentSpawn.js +311 -180
- package/plugin/dist/hooks/kiro-hooks.js +299 -168
- package/plugin/dist/hooks/postToolUse.js +303 -172
- package/plugin/dist/hooks/stop.js +308 -177
- package/plugin/dist/hooks/userPromptSubmit.js +303 -172
- package/plugin/dist/index.js +303 -299
- package/plugin/dist/sdk/index.js +299 -172
- package/plugin/dist/services/search/EmbeddingService.js +88 -23
- package/plugin/dist/services/search/HybridSearch.js +190 -84
- package/plugin/dist/services/search/VectorSearch.js +128 -45
- package/plugin/dist/services/search/index.js +192 -223
- package/plugin/dist/services/sqlite/Database.js +55 -153
- package/plugin/dist/services/sqlite/Observations.js +23 -12
- package/plugin/dist/services/sqlite/Search.js +31 -19
- package/plugin/dist/services/sqlite/Sessions.js +5 -0
- package/plugin/dist/services/sqlite/index.js +113 -183
- package/plugin/dist/viewer.css +1 -0
- package/plugin/dist/viewer.html +2 -100
- package/plugin/dist/viewer.js +15 -24896
- package/plugin/dist/viewer.js.map +7 -0
- package/plugin/dist/worker-service.js +158 -5551
- package/plugin/dist/worker-service.js.map +7 -0
- package/scripts/postinstall.cjs +42 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../node_modules/ip-address/src/common.ts", "../../node_modules/ip-address/src/v4/constants.ts", "../../node_modules/ip-address/src/address-error.ts", "../../node_modules/ip-address/src/ipv4.ts", "../../node_modules/ip-address/src/v6/constants.ts", "../../node_modules/ip-address/src/v6/helpers.ts", "../../node_modules/ip-address/src/v6/regular-expressions.ts", "../../node_modules/ip-address/src/ipv6.ts", "../../node_modules/ip-address/src/ip-address.ts", "../../src/services/sqlite/Search.ts", "../../src/services/sqlite/Observations.ts", "../../src/services/worker-service.ts", "../../node_modules/helmet/index.mjs", "../../node_modules/express-rate-limit/dist/index.mjs", "../../src/shims/bun-sqlite.ts", "../../src/shared/paths.ts", "../../src/utils/logger.ts", "../../src/services/sqlite/Database.ts", "../../src/services/search/EmbeddingService.ts", "../../src/services/search/VectorSearch.ts", "../../src/services/search/ScoringEngine.ts", "../../src/services/search/HybridSearch.ts", "../../src/services/worker-context.ts", "../../src/services/routes/core.ts", "../../src/services/routes/observations.ts", "../../src/services/sqlite/Summaries.ts", "../../src/types/worker-types.ts", "../../src/services/routes/summaries.ts", "../../src/services/routes/search.ts", "../../src/services/routes/analytics.ts", "../../src/services/sqlite/Analytics.ts", "../../src/services/routes/sessions.ts", "../../src/services/sqlite/Sessions.ts", "../../src/services/sqlite/Checkpoints.ts", "../../src/services/routes/projects.ts", "../../src/services/routes/data.ts", "../../src/services/sqlite/Reports.ts", "../../src/services/report-formatter.ts"],
|
|
4
|
+
"sourcesContent": ["import { Address4 } from './ipv4';\nimport { Address6 } from './ipv6';\n\nexport interface ReverseFormOptions {\n omitSuffix?: boolean;\n}\n\nexport function isInSubnet(this: Address4 | Address6, address: Address4 | Address6) {\n if (this.subnetMask < address.subnetMask) {\n return false;\n }\n\n if (this.mask(address.subnetMask) === address.mask()) {\n return true;\n }\n\n return false;\n}\n\nexport function isCorrect(defaultBits: number) {\n return function (this: Address4 | Address6) {\n if (this.addressMinusSuffix !== this.correctForm()) {\n return false;\n }\n\n if (this.subnetMask === defaultBits && !this.parsedSubnet) {\n return true;\n }\n\n return this.parsedSubnet === String(this.subnetMask);\n };\n}\n\nexport function numberToPaddedHex(number: number) {\n return number.toString(16).padStart(2, '0');\n}\n\nexport function stringToPaddedHex(numberString: string) {\n return numberToPaddedHex(parseInt(numberString, 10));\n}\n\n/**\n * @param binaryValue Binary representation of a value (e.g. `10`)\n * @param position Byte position, where 0 is the least significant bit\n */\nexport function testBit(binaryValue: string, position: number): boolean {\n const { length } = binaryValue;\n\n if (position > length) {\n return false;\n }\n\n const positionInString = length - position;\n return binaryValue.substring(positionInString, positionInString + 1) === '1';\n}\n", "export const BITS = 32;\nexport const GROUPS = 4;\n\nexport const RE_ADDRESS =\n /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/g;\n\nexport const RE_SUBNET_STRING = /\\/\\d{1,2}$/;\n", "export class AddressError extends Error {\n parseMessage?: string;\n\n constructor(message: string, parseMessage?: string) {\n super(message);\n\n this.name = 'AddressError';\n\n this.parseMessage = parseMessage;\n }\n}\n", "/* eslint-disable no-param-reassign */\n\nimport * as common from './common';\nimport * as constants from './v4/constants';\nimport { AddressError } from './address-error';\n\n/**\n * Represents an IPv4 address\n * @class Address4\n * @param {string} address - An IPv4 address string\n */\nexport class Address4 {\n address: string;\n addressMinusSuffix?: string;\n groups: number = constants.GROUPS;\n parsedAddress: string[] = [];\n parsedSubnet: string = '';\n subnet: string = '/32';\n subnetMask: number = 32;\n v4: boolean = true;\n\n constructor(address: string) {\n this.address = address;\n\n const subnet = constants.RE_SUBNET_STRING.exec(address);\n\n if (subnet) {\n this.parsedSubnet = subnet[0].replace('/', '');\n this.subnetMask = parseInt(this.parsedSubnet, 10);\n this.subnet = `/${this.subnetMask}`;\n\n if (this.subnetMask < 0 || this.subnetMask > constants.BITS) {\n throw new AddressError('Invalid subnet mask.');\n }\n\n address = address.replace(constants.RE_SUBNET_STRING, '');\n }\n\n this.addressMinusSuffix = address;\n\n this.parsedAddress = this.parse(address);\n }\n\n static isValid(address: string): boolean {\n try {\n // eslint-disable-next-line no-new\n new Address4(address);\n\n return true;\n } catch (e) {\n return false;\n }\n }\n\n /*\n * Parses a v4 address\n */\n parse(address: string) {\n const groups = address.split('.');\n\n if (!address.match(constants.RE_ADDRESS)) {\n throw new AddressError('Invalid IPv4 address.');\n }\n\n return groups;\n }\n\n /**\n * Returns the correct form of an address\n * @memberof Address4\n * @instance\n * @returns {String}\n */\n correctForm(): string {\n return this.parsedAddress.map((part) => parseInt(part, 10)).join('.');\n }\n\n /**\n * Returns true if the address is correct, false otherwise\n * @memberof Address4\n * @instance\n * @returns {Boolean}\n */\n isCorrect = common.isCorrect(constants.BITS);\n\n /**\n * Converts a hex string to an IPv4 address object\n * @memberof Address4\n * @static\n * @param {string} hex - a hex string to convert\n * @returns {Address4}\n */\n static fromHex(hex: string): Address4 {\n const padded = hex.replace(/:/g, '').padStart(8, '0');\n const groups = [];\n let i;\n\n for (i = 0; i < 8; i += 2) {\n const h = padded.slice(i, i + 2);\n\n groups.push(parseInt(h, 16));\n }\n\n return new Address4(groups.join('.'));\n }\n\n /**\n * Converts an integer into a IPv4 address object\n * @memberof Address4\n * @static\n * @param {integer} integer - a number to convert\n * @returns {Address4}\n */\n static fromInteger(integer: number): Address4 {\n return Address4.fromHex(integer.toString(16));\n }\n\n /**\n * Return an address from in-addr.arpa form\n * @memberof Address4\n * @static\n * @param {string} arpaFormAddress - an 'in-addr.arpa' form ipv4 address\n * @returns {Adress4}\n * @example\n * var address = Address4.fromArpa(42.2.0.192.in-addr.arpa.)\n * address.correctForm(); // '192.0.2.42'\n */\n static fromArpa(arpaFormAddress: string): Address4 {\n // remove ending \".in-addr.arpa.\" or just \".\"\n const leader = arpaFormAddress.replace(/(\\.in-addr\\.arpa)?\\.$/, '');\n\n const address = leader.split('.').reverse().join('.');\n\n return new Address4(address);\n }\n\n /**\n * Converts an IPv4 address object to a hex string\n * @memberof Address4\n * @instance\n * @returns {String}\n */\n toHex(): string {\n return this.parsedAddress.map((part) => common.stringToPaddedHex(part)).join(':');\n }\n\n /**\n * Converts an IPv4 address object to an array of bytes\n * @memberof Address4\n * @instance\n * @returns {Array}\n */\n toArray(): number[] {\n return this.parsedAddress.map((part) => parseInt(part, 10));\n }\n\n /**\n * Converts an IPv4 address object to an IPv6 address group\n * @memberof Address4\n * @instance\n * @returns {String}\n */\n toGroup6(): string {\n const output = [];\n let i;\n\n for (i = 0; i < constants.GROUPS; i += 2) {\n output.push(\n `${common.stringToPaddedHex(this.parsedAddress[i])}${common.stringToPaddedHex(\n this.parsedAddress[i + 1],\n )}`,\n );\n }\n\n return output.join(':');\n }\n\n /**\n * Returns the address as a `bigint`\n * @memberof Address4\n * @instance\n * @returns {bigint}\n */\n bigInt(): bigint {\n return BigInt(`0x${this.parsedAddress.map((n) => common.stringToPaddedHex(n)).join('')}`);\n }\n\n /**\n * Helper function getting start address.\n * @memberof Address4\n * @instance\n * @returns {bigint}\n */\n _startAddress(): bigint {\n return BigInt(`0b${this.mask() + '0'.repeat(constants.BITS - this.subnetMask)}`);\n }\n\n /**\n * The first address in the range given by this address' subnet.\n * Often referred to as the Network Address.\n * @memberof Address4\n * @instance\n * @returns {Address4}\n */\n startAddress(): Address4 {\n return Address4.fromBigInt(this._startAddress());\n }\n\n /**\n * The first host address in the range given by this address's subnet ie\n * the first address after the Network Address\n * @memberof Address4\n * @instance\n * @returns {Address4}\n */\n startAddressExclusive(): Address4 {\n const adjust = BigInt('1');\n return Address4.fromBigInt(this._startAddress() + adjust);\n }\n\n /**\n * Helper function getting end address.\n * @memberof Address4\n * @instance\n * @returns {bigint}\n */\n _endAddress(): bigint {\n return BigInt(`0b${this.mask() + '1'.repeat(constants.BITS - this.subnetMask)}`);\n }\n\n /**\n * The last address in the range given by this address' subnet\n * Often referred to as the Broadcast\n * @memberof Address4\n * @instance\n * @returns {Address4}\n */\n endAddress(): Address4 {\n return Address4.fromBigInt(this._endAddress());\n }\n\n /**\n * The last host address in the range given by this address's subnet ie\n * the last address prior to the Broadcast Address\n * @memberof Address4\n * @instance\n * @returns {Address4}\n */\n endAddressExclusive(): Address4 {\n const adjust = BigInt('1');\n return Address4.fromBigInt(this._endAddress() - adjust);\n }\n\n /**\n * Converts a BigInt to a v4 address object\n * @memberof Address4\n * @static\n * @param {bigint} bigInt - a BigInt to convert\n * @returns {Address4}\n */\n static fromBigInt(bigInt: bigint): Address4 {\n return Address4.fromHex(bigInt.toString(16));\n }\n\n /**\n * Returns the first n bits of the address, defaulting to the\n * subnet mask\n * @memberof Address4\n * @instance\n * @returns {String}\n */\n mask(mask?: number): string {\n if (mask === undefined) {\n mask = this.subnetMask;\n }\n\n return this.getBitsBase2(0, mask);\n }\n\n /**\n * Returns the bits in the given range as a base-2 string\n * @memberof Address4\n * @instance\n * @returns {string}\n */\n getBitsBase2(start: number, end: number): string {\n return this.binaryZeroPad().slice(start, end);\n }\n\n /**\n * Return the reversed ip6.arpa form of the address\n * @memberof Address4\n * @param {Object} options\n * @param {boolean} options.omitSuffix - omit the \"in-addr.arpa\" suffix\n * @instance\n * @returns {String}\n */\n reverseForm(options?: common.ReverseFormOptions): string {\n if (!options) {\n options = {};\n }\n\n const reversed = this.correctForm().split('.').reverse().join('.');\n\n if (options.omitSuffix) {\n return reversed;\n }\n\n return `${reversed}.in-addr.arpa.`;\n }\n\n /**\n * Returns true if the given address is in the subnet of the current address\n * @memberof Address4\n * @instance\n * @returns {boolean}\n */\n isInSubnet = common.isInSubnet;\n\n /**\n * Returns true if the given address is a multicast address\n * @memberof Address4\n * @instance\n * @returns {boolean}\n */\n isMulticast(): boolean {\n return this.isInSubnet(new Address4('224.0.0.0/4'));\n }\n\n /**\n * Returns a zero-padded base-2 string representation of the address\n * @memberof Address4\n * @instance\n * @returns {string}\n */\n binaryZeroPad(): string {\n return this.bigInt().toString(2).padStart(constants.BITS, '0');\n }\n\n /**\n * Groups an IPv4 address for inclusion at the end of an IPv6 address\n * @returns {String}\n */\n groupForV6(): string {\n const segments = this.parsedAddress;\n\n return this.address.replace(\n constants.RE_ADDRESS,\n `<span class=\"hover-group group-v4 group-6\">${segments\n .slice(0, 2)\n .join('.')}</span>.<span class=\"hover-group group-v4 group-7\">${segments\n .slice(2, 4)\n .join('.')}</span>`,\n );\n }\n}\n", "export const BITS = 128;\nexport const GROUPS = 8;\n\n/**\n * Represents IPv6 address scopes\n * @memberof Address6\n * @static\n */\nexport const SCOPES: { [key: number]: string | undefined } = {\n 0: 'Reserved',\n 1: 'Interface local',\n 2: 'Link local',\n 4: 'Admin local',\n 5: 'Site local',\n 8: 'Organization local',\n 14: 'Global',\n 15: 'Reserved',\n} as const;\n\n/**\n * Represents IPv6 address types\n * @memberof Address6\n * @static\n */\nexport const TYPES: { [key: string]: string | undefined } = {\n 'ff01::1/128': 'Multicast (All nodes on this interface)',\n 'ff01::2/128': 'Multicast (All routers on this interface)',\n 'ff02::1/128': 'Multicast (All nodes on this link)',\n 'ff02::2/128': 'Multicast (All routers on this link)',\n 'ff05::2/128': 'Multicast (All routers in this site)',\n 'ff02::5/128': 'Multicast (OSPFv3 AllSPF routers)',\n 'ff02::6/128': 'Multicast (OSPFv3 AllDR routers)',\n 'ff02::9/128': 'Multicast (RIP routers)',\n 'ff02::a/128': 'Multicast (EIGRP routers)',\n 'ff02::d/128': 'Multicast (PIM routers)',\n 'ff02::16/128': 'Multicast (MLDv2 reports)',\n 'ff01::fb/128': 'Multicast (mDNSv6)',\n 'ff02::fb/128': 'Multicast (mDNSv6)',\n 'ff05::fb/128': 'Multicast (mDNSv6)',\n 'ff02::1:2/128': 'Multicast (All DHCP servers and relay agents on this link)',\n 'ff05::1:2/128': 'Multicast (All DHCP servers and relay agents in this site)',\n 'ff02::1:3/128': 'Multicast (All DHCP servers on this link)',\n 'ff05::1:3/128': 'Multicast (All DHCP servers in this site)',\n '::/128': 'Unspecified',\n '::1/128': 'Loopback',\n 'ff00::/8': 'Multicast',\n 'fe80::/10': 'Link-local unicast',\n} as const;\n\n/**\n * A regular expression that matches bad characters in an IPv6 address\n * @memberof Address6\n * @static\n */\nexport const RE_BAD_CHARACTERS = /([^0-9a-f:/%])/gi;\n\n/**\n * A regular expression that matches an incorrect IPv6 address\n * @memberof Address6\n * @static\n */\nexport const RE_BAD_ADDRESS = /([0-9a-f]{5,}|:{3,}|[^:]:$|^:[^:]|\\/$)/gi;\n\n/**\n * A regular expression that matches an IPv6 subnet\n * @memberof Address6\n * @static\n */\nexport const RE_SUBNET_STRING = /\\/\\d{1,3}(?=%|$)/;\n\n/**\n * A regular expression that matches an IPv6 zone\n * @memberof Address6\n * @static\n */\nexport const RE_ZONE_STRING = /%.*$/;\n\nexport const RE_URL = /^\\[{0,1}([0-9a-f:]+)\\]{0,1}/;\nexport const RE_URL_WITH_PORT = /\\[([0-9a-f:]+)\\]:([0-9]{1,5})/;\n", "/**\n * @returns {String} the string with all zeroes contained in a <span>\n */\nexport function spanAllZeroes(s: string): string {\n return s.replace(/(0+)/g, '<span class=\"zero\">$1</span>');\n}\n\n/**\n * @returns {String} the string with each character contained in a <span>\n */\nexport function spanAll(s: string, offset: number = 0): string {\n const letters = s.split('');\n\n return letters\n .map(\n (n, i) => `<span class=\"digit value-${n} position-${i + offset}\">${spanAllZeroes(n)}</span>`,\n )\n .join('');\n}\n\nfunction spanLeadingZeroesSimple(group: string): string {\n return group.replace(/^(0+)/, '<span class=\"zero\">$1</span>');\n}\n\n/**\n * @returns {String} the string with leading zeroes contained in a <span>\n */\nexport function spanLeadingZeroes(address: string): string {\n const groups = address.split(':');\n\n return groups.map((g) => spanLeadingZeroesSimple(g)).join(':');\n}\n\n/**\n * Groups an address\n * @returns {String} a grouped address\n */\nexport function simpleGroup(addressString: string, offset: number = 0): string[] {\n const groups = addressString.split(':');\n\n return groups.map((g, i) => {\n if (/group-v4/.test(g)) {\n return g;\n }\n\n return `<span class=\"hover-group group-${i + offset}\">${spanLeadingZeroesSimple(g)}</span>`;\n });\n}\n", "import * as v6 from './constants';\n\nexport function groupPossibilities(possibilities: string[]): string {\n return `(${possibilities.join('|')})`;\n}\n\nexport function padGroup(group: string): string {\n if (group.length < 4) {\n return `0{0,${4 - group.length}}${group}`;\n }\n\n return group;\n}\n\nexport const ADDRESS_BOUNDARY = '[^A-Fa-f0-9:]';\n\nexport function simpleRegularExpression(groups: string[]) {\n const zeroIndexes: number[] = [];\n\n groups.forEach((group, i) => {\n const groupInteger = parseInt(group, 16);\n\n if (groupInteger === 0) {\n zeroIndexes.push(i);\n }\n });\n\n // You can technically elide a single 0, this creates the regular expressions\n // to match that eventuality\n const possibilities = zeroIndexes.map((zeroIndex) =>\n groups\n .map((group, i) => {\n if (i === zeroIndex) {\n const elision = i === 0 || i === v6.GROUPS - 1 ? ':' : '';\n\n return groupPossibilities([padGroup(group), elision]);\n }\n\n return padGroup(group);\n })\n .join(':'),\n );\n\n // The simplest case\n possibilities.push(groups.map(padGroup).join(':'));\n\n return groupPossibilities(possibilities);\n}\n\nexport function possibleElisions(\n elidedGroups: number,\n moreLeft?: boolean,\n moreRight?: boolean,\n): string {\n const left = moreLeft ? '' : ':';\n const right = moreRight ? '' : ':';\n\n const possibilities = [];\n\n // 1. elision of everything (::)\n if (!moreLeft && !moreRight) {\n possibilities.push('::');\n }\n\n // 2. complete elision of the middle\n if (moreLeft && moreRight) {\n possibilities.push('');\n }\n\n if ((moreRight && !moreLeft) || (!moreRight && moreLeft)) {\n // 3. complete elision of one side\n possibilities.push(':');\n }\n\n // 4. elision from the left side\n possibilities.push(`${left}(:0{1,4}){1,${elidedGroups - 1}}`);\n\n // 5. elision from the right side\n possibilities.push(`(0{1,4}:){1,${elidedGroups - 1}}${right}`);\n\n // 6. no elision\n possibilities.push(`(0{1,4}:){${elidedGroups - 1}}0{1,4}`);\n\n // 7. elision (including sloppy elision) from the middle\n for (let groups = 1; groups < elidedGroups - 1; groups++) {\n for (let position = 1; position < elidedGroups - groups; position++) {\n possibilities.push(\n `(0{1,4}:){${position}}:(0{1,4}:){${elidedGroups - position - groups - 1}}0{1,4}`,\n );\n }\n }\n\n return groupPossibilities(possibilities);\n}\n", "/* eslint-disable prefer-destructuring */\n/* eslint-disable no-param-reassign */\n\nimport * as common from './common';\nimport * as constants4 from './v4/constants';\nimport * as constants6 from './v6/constants';\nimport * as helpers from './v6/helpers';\nimport { Address4 } from './ipv4';\nimport {\n ADDRESS_BOUNDARY,\n possibleElisions,\n simpleRegularExpression,\n} from './v6/regular-expressions';\nimport { AddressError } from './address-error';\nimport { testBit } from './common';\n\nfunction assert(condition: any): asserts condition {\n if (!condition) {\n throw new Error('Assertion failed.');\n }\n}\n\nfunction addCommas(number: string): string {\n const r = /(\\d+)(\\d{3})/;\n\n while (r.test(number)) {\n number = number.replace(r, '$1,$2');\n }\n\n return number;\n}\n\nfunction spanLeadingZeroes4(n: string): string {\n n = n.replace(/^(0{1,})([1-9]+)$/, '<span class=\"parse-error\">$1</span>$2');\n n = n.replace(/^(0{1,})(0)$/, '<span class=\"parse-error\">$1</span>$2');\n\n return n;\n}\n\n/*\n * A helper function to compact an array\n */\nfunction compact(address: string[], slice: number[]) {\n const s1 = [];\n const s2 = [];\n let i;\n\n for (i = 0; i < address.length; i++) {\n if (i < slice[0]) {\n s1.push(address[i]);\n } else if (i > slice[1]) {\n s2.push(address[i]);\n }\n }\n\n return s1.concat(['compact']).concat(s2);\n}\n\nfunction paddedHex(octet: string): string {\n return parseInt(octet, 16).toString(16).padStart(4, '0');\n}\n\nfunction unsignByte(b: number) {\n // eslint-disable-next-line no-bitwise\n return b & 0xff;\n}\n\ninterface SixToFourProperties {\n prefix: string;\n gateway: string;\n}\n\ninterface TeredoProperties {\n prefix: string;\n server4: string;\n client4: string;\n flags: string;\n coneNat: boolean;\n microsoft: {\n reserved: boolean;\n universalLocal: boolean;\n groupIndividual: boolean;\n nonce: string;\n };\n udpPort: string;\n}\n\n/**\n * Represents an IPv6 address\n * @class Address6\n * @param {string} address - An IPv6 address string\n * @param {number} [groups=8] - How many octets to parse\n * @example\n * var address = new Address6('2001::/32');\n */\nexport class Address6 {\n address4?: Address4;\n address: string;\n addressMinusSuffix: string = '';\n elidedGroups?: number;\n elisionBegin?: number;\n elisionEnd?: number;\n groups: number;\n parsedAddress4?: string;\n parsedAddress: string[];\n parsedSubnet: string = '';\n subnet: string = '/128';\n subnetMask: number = 128;\n v4: boolean = false;\n zone: string = '';\n\n constructor(address: string, optionalGroups?: number) {\n if (optionalGroups === undefined) {\n this.groups = constants6.GROUPS;\n } else {\n this.groups = optionalGroups;\n }\n\n this.address = address;\n\n const subnet = constants6.RE_SUBNET_STRING.exec(address);\n\n if (subnet) {\n this.parsedSubnet = subnet[0].replace('/', '');\n this.subnetMask = parseInt(this.parsedSubnet, 10);\n this.subnet = `/${this.subnetMask}`;\n\n if (\n Number.isNaN(this.subnetMask) ||\n this.subnetMask < 0 ||\n this.subnetMask > constants6.BITS\n ) {\n throw new AddressError('Invalid subnet mask.');\n }\n\n address = address.replace(constants6.RE_SUBNET_STRING, '');\n } else if (/\\//.test(address)) {\n throw new AddressError('Invalid subnet mask.');\n }\n\n const zone = constants6.RE_ZONE_STRING.exec(address);\n\n if (zone) {\n this.zone = zone[0];\n\n address = address.replace(constants6.RE_ZONE_STRING, '');\n }\n\n this.addressMinusSuffix = address;\n\n this.parsedAddress = this.parse(this.addressMinusSuffix);\n }\n\n static isValid(address: string): boolean {\n try {\n // eslint-disable-next-line no-new\n new Address6(address);\n\n return true;\n } catch (e) {\n return false;\n }\n }\n\n /**\n * Convert a BigInt to a v6 address object\n * @memberof Address6\n * @static\n * @param {bigint} bigInt - a BigInt to convert\n * @returns {Address6}\n * @example\n * var bigInt = BigInt('1000000000000');\n * var address = Address6.fromBigInt(bigInt);\n * address.correctForm(); // '::e8:d4a5:1000'\n */\n static fromBigInt(bigInt: bigint): Address6 {\n const hex = bigInt.toString(16).padStart(32, '0');\n const groups = [];\n let i;\n\n for (i = 0; i < constants6.GROUPS; i++) {\n groups.push(hex.slice(i * 4, (i + 1) * 4));\n }\n\n return new Address6(groups.join(':'));\n }\n\n /**\n * Convert a URL (with optional port number) to an address object\n * @memberof Address6\n * @static\n * @param {string} url - a URL with optional port number\n * @example\n * var addressAndPort = Address6.fromURL('http://[ffff::]:8080/foo/');\n * addressAndPort.address.correctForm(); // 'ffff::'\n * addressAndPort.port; // 8080\n */\n static fromURL(url: string) {\n let host: string;\n let port: string | number | null = null;\n let result: string[] | null;\n\n // If we have brackets parse them and find a port\n if (url.indexOf('[') !== -1 && url.indexOf(']:') !== -1) {\n result = constants6.RE_URL_WITH_PORT.exec(url);\n\n if (result === null) {\n return {\n error: 'failed to parse address with port',\n address: null,\n port: null,\n };\n }\n\n host = result[1];\n port = result[2];\n // If there's a URL extract the address\n } else if (url.indexOf('/') !== -1) {\n // Remove the protocol prefix\n url = url.replace(/^[a-z0-9]+:\\/\\//, '');\n\n // Parse the address\n result = constants6.RE_URL.exec(url);\n\n if (result === null) {\n return {\n error: 'failed to parse address from URL',\n address: null,\n port: null,\n };\n }\n\n host = result[1];\n // Otherwise just assign the URL to the host and let the library parse it\n } else {\n host = url;\n }\n\n // If there's a port convert it to an integer\n if (port) {\n port = parseInt(port, 10);\n\n // squelch out of range ports\n if (port < 0 || port > 65536) {\n port = null;\n }\n } else {\n // Standardize `undefined` to `null`\n port = null;\n }\n\n return {\n address: new Address6(host),\n port,\n };\n }\n\n /**\n * Create an IPv6-mapped address given an IPv4 address\n * @memberof Address6\n * @static\n * @param {string} address - An IPv4 address string\n * @returns {Address6}\n * @example\n * var address = Address6.fromAddress4('192.168.0.1');\n * address.correctForm(); // '::ffff:c0a8:1'\n * address.to4in6(); // '::ffff:192.168.0.1'\n */\n static fromAddress4(address: string): Address6 {\n const address4 = new Address4(address);\n\n const mask6 = constants6.BITS - (constants4.BITS - address4.subnetMask);\n\n return new Address6(`::ffff:${address4.correctForm()}/${mask6}`);\n }\n\n /**\n * Return an address from ip6.arpa form\n * @memberof Address6\n * @static\n * @param {string} arpaFormAddress - an 'ip6.arpa' form address\n * @returns {Adress6}\n * @example\n * var address = Address6.fromArpa(e.f.f.f.3.c.2.6.f.f.f.e.6.6.8.e.1.0.6.7.9.4.e.c.0.0.0.0.1.0.0.2.ip6.arpa.)\n * address.correctForm(); // '2001:0:ce49:7601:e866:efff:62c3:fffe'\n */\n static fromArpa(arpaFormAddress: string): Address6 {\n // remove ending \".ip6.arpa.\" or just \".\"\n let address = arpaFormAddress.replace(/(\\.ip6\\.arpa)?\\.$/, '');\n const semicolonAmount = 7;\n\n // correct ip6.arpa form with ending removed will be 63 characters\n if (address.length !== 63) {\n throw new AddressError(\"Invalid 'ip6.arpa' form.\");\n }\n\n const parts = address.split('.').reverse();\n\n for (let i = semicolonAmount; i > 0; i--) {\n const insertIndex = i * 4;\n parts.splice(insertIndex, 0, ':');\n }\n\n address = parts.join('');\n\n return new Address6(address);\n }\n\n /**\n * Return the Microsoft UNC transcription of the address\n * @memberof Address6\n * @instance\n * @returns {String} the Microsoft UNC transcription of the address\n */\n microsoftTranscription(): string {\n return `${this.correctForm().replace(/:/g, '-')}.ipv6-literal.net`;\n }\n\n /**\n * Return the first n bits of the address, defaulting to the subnet mask\n * @memberof Address6\n * @instance\n * @param {number} [mask=subnet] - the number of bits to mask\n * @returns {String} the first n bits of the address as a string\n */\n mask(mask: number = this.subnetMask): string {\n return this.getBitsBase2(0, mask);\n }\n\n /**\n * Return the number of possible subnets of a given size in the address\n * @memberof Address6\n * @instance\n * @param {number} [subnetSize=128] - the subnet size\n * @returns {String}\n */\n // TODO: probably useful to have a numeric version of this too\n possibleSubnets(subnetSize: number = 128): string {\n const availableBits = constants6.BITS - this.subnetMask;\n const subnetBits = Math.abs(subnetSize - constants6.BITS);\n const subnetPowers = availableBits - subnetBits;\n\n if (subnetPowers < 0) {\n return '0';\n }\n\n return addCommas((BigInt('2') ** BigInt(subnetPowers)).toString(10));\n }\n\n /**\n * Helper function getting start address.\n * @memberof Address6\n * @instance\n * @returns {bigint}\n */\n _startAddress(): bigint {\n return BigInt(`0b${this.mask() + '0'.repeat(constants6.BITS - this.subnetMask)}`);\n }\n\n /**\n * The first address in the range given by this address' subnet\n * Often referred to as the Network Address.\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n startAddress(): Address6 {\n return Address6.fromBigInt(this._startAddress());\n }\n\n /**\n * The first host address in the range given by this address's subnet ie\n * the first address after the Network Address\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n startAddressExclusive(): Address6 {\n const adjust = BigInt('1');\n return Address6.fromBigInt(this._startAddress() + adjust);\n }\n\n /**\n * Helper function getting end address.\n * @memberof Address6\n * @instance\n * @returns {bigint}\n */\n _endAddress(): bigint {\n return BigInt(`0b${this.mask() + '1'.repeat(constants6.BITS - this.subnetMask)}`);\n }\n\n /**\n * The last address in the range given by this address' subnet\n * Often referred to as the Broadcast\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n endAddress(): Address6 {\n return Address6.fromBigInt(this._endAddress());\n }\n\n /**\n * The last host address in the range given by this address's subnet ie\n * the last address prior to the Broadcast Address\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n endAddressExclusive(): Address6 {\n const adjust = BigInt('1');\n return Address6.fromBigInt(this._endAddress() - adjust);\n }\n\n /**\n * Return the scope of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getScope(): string {\n let scope = constants6.SCOPES[parseInt(this.getBits(12, 16).toString(10), 10)];\n\n if (this.getType() === 'Global unicast' && scope !== 'Link local') {\n scope = 'Global';\n }\n\n return scope || 'Unknown';\n }\n\n /**\n * Return the type of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getType(): string {\n for (const subnet of Object.keys(constants6.TYPES)) {\n if (this.isInSubnet(new Address6(subnet))) {\n return constants6.TYPES[subnet] as string;\n }\n }\n\n return 'Global unicast';\n }\n\n /**\n * Return the bits in the given range as a BigInt\n * @memberof Address6\n * @instance\n * @returns {bigint}\n */\n getBits(start: number, end: number): bigint {\n return BigInt(`0b${this.getBitsBase2(start, end)}`);\n }\n\n /**\n * Return the bits in the given range as a base-2 string\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getBitsBase2(start: number, end: number): string {\n return this.binaryZeroPad().slice(start, end);\n }\n\n /**\n * Return the bits in the given range as a base-16 string\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getBitsBase16(start: number, end: number): string {\n const length = end - start;\n\n if (length % 4 !== 0) {\n throw new Error('Length of bits to retrieve must be divisible by four');\n }\n\n return this.getBits(start, end)\n .toString(16)\n .padStart(length / 4, '0');\n }\n\n /**\n * Return the bits that are set past the subnet mask length\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getBitsPastSubnet(): string {\n return this.getBitsBase2(this.subnetMask, constants6.BITS);\n }\n\n /**\n * Return the reversed ip6.arpa form of the address\n * @memberof Address6\n * @param {Object} options\n * @param {boolean} options.omitSuffix - omit the \"ip6.arpa\" suffix\n * @instance\n * @returns {String}\n */\n reverseForm(options?: common.ReverseFormOptions): string {\n if (!options) {\n options = {};\n }\n\n const characters = Math.floor(this.subnetMask / 4);\n\n const reversed = this.canonicalForm()\n .replace(/:/g, '')\n .split('')\n .slice(0, characters)\n .reverse()\n .join('.');\n\n if (characters > 0) {\n if (options.omitSuffix) {\n return reversed;\n }\n\n return `${reversed}.ip6.arpa.`;\n }\n\n if (options.omitSuffix) {\n return '';\n }\n\n return 'ip6.arpa.';\n }\n\n /**\n * Return the correct form of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n correctForm(): string {\n let i;\n let groups = [];\n\n let zeroCounter = 0;\n const zeroes = [];\n\n for (i = 0; i < this.parsedAddress.length; i++) {\n const value = parseInt(this.parsedAddress[i], 16);\n\n if (value === 0) {\n zeroCounter++;\n }\n\n if (value !== 0 && zeroCounter > 0) {\n if (zeroCounter > 1) {\n zeroes.push([i - zeroCounter, i - 1]);\n }\n\n zeroCounter = 0;\n }\n }\n\n // Do we end with a string of zeroes?\n if (zeroCounter > 1) {\n zeroes.push([this.parsedAddress.length - zeroCounter, this.parsedAddress.length - 1]);\n }\n\n const zeroLengths = zeroes.map((n) => n[1] - n[0] + 1);\n\n if (zeroes.length > 0) {\n const index = zeroLengths.indexOf(Math.max(...zeroLengths) as number);\n\n groups = compact(this.parsedAddress, zeroes[index]);\n } else {\n groups = this.parsedAddress;\n }\n\n for (i = 0; i < groups.length; i++) {\n if (groups[i] !== 'compact') {\n groups[i] = parseInt(groups[i], 16).toString(16);\n }\n }\n\n let correct = groups.join(':');\n\n correct = correct.replace(/^compact$/, '::');\n correct = correct.replace(/(^compact)|(compact$)/, ':');\n correct = correct.replace(/compact/, '');\n\n return correct;\n }\n\n /**\n * Return a zero-padded base-2 string representation of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n * @example\n * var address = new Address6('2001:4860:4001:803::1011');\n * address.binaryZeroPad();\n * // '0010000000000001010010000110000001000000000000010000100000000011\n * // 0000000000000000000000000000000000000000000000000001000000010001'\n */\n binaryZeroPad(): string {\n return this.bigInt().toString(2).padStart(constants6.BITS, '0');\n }\n\n // TODO: Improve the semantics of this helper function\n parse4in6(address: string): string {\n const groups = address.split(':');\n const lastGroup = groups.slice(-1)[0];\n\n const address4 = lastGroup.match(constants4.RE_ADDRESS);\n\n if (address4) {\n this.parsedAddress4 = address4[0];\n this.address4 = new Address4(this.parsedAddress4);\n\n for (let i = 0; i < this.address4.groups; i++) {\n if (/^0[0-9]+/.test(this.address4.parsedAddress[i])) {\n throw new AddressError(\n \"IPv4 addresses can't have leading zeroes.\",\n address.replace(\n constants4.RE_ADDRESS,\n this.address4.parsedAddress.map(spanLeadingZeroes4).join('.'),\n ),\n );\n }\n }\n\n this.v4 = true;\n\n groups[groups.length - 1] = this.address4.toGroup6();\n\n address = groups.join(':');\n }\n\n return address;\n }\n\n // TODO: Make private?\n parse(address: string): string[] {\n address = this.parse4in6(address);\n\n const badCharacters = address.match(constants6.RE_BAD_CHARACTERS);\n\n if (badCharacters) {\n throw new AddressError(\n `Bad character${\n badCharacters.length > 1 ? 's' : ''\n } detected in address: ${badCharacters.join('')}`,\n address.replace(constants6.RE_BAD_CHARACTERS, '<span class=\"parse-error\">$1</span>'),\n );\n }\n\n const badAddress = address.match(constants6.RE_BAD_ADDRESS);\n\n if (badAddress) {\n throw new AddressError(\n `Address failed regex: ${badAddress.join('')}`,\n address.replace(constants6.RE_BAD_ADDRESS, '<span class=\"parse-error\">$1</span>'),\n );\n }\n\n let groups: string[] = [];\n\n const halves = address.split('::');\n\n if (halves.length === 2) {\n let first = halves[0].split(':');\n let last = halves[1].split(':');\n\n if (first.length === 1 && first[0] === '') {\n first = [];\n }\n\n if (last.length === 1 && last[0] === '') {\n last = [];\n }\n\n const remaining = this.groups - (first.length + last.length);\n\n if (!remaining) {\n throw new AddressError('Error parsing groups');\n }\n\n this.elidedGroups = remaining;\n\n this.elisionBegin = first.length;\n this.elisionEnd = first.length + this.elidedGroups;\n\n groups = groups.concat(first);\n\n for (let i = 0; i < remaining; i++) {\n groups.push('0');\n }\n\n groups = groups.concat(last);\n } else if (halves.length === 1) {\n groups = address.split(':');\n\n this.elidedGroups = 0;\n } else {\n throw new AddressError('Too many :: groups found');\n }\n\n groups = groups.map((group: string) => parseInt(group, 16).toString(16));\n\n if (groups.length !== this.groups) {\n throw new AddressError('Incorrect number of groups found');\n }\n\n return groups;\n }\n\n /**\n * Return the canonical form of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n canonicalForm(): string {\n return this.parsedAddress.map(paddedHex).join(':');\n }\n\n /**\n * Return the decimal form of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n decimal(): string {\n return this.parsedAddress.map((n) => parseInt(n, 16).toString(10).padStart(5, '0')).join(':');\n }\n\n /**\n * Return the address as a BigInt\n * @memberof Address6\n * @instance\n * @returns {bigint}\n */\n bigInt(): bigint {\n return BigInt(`0x${this.parsedAddress.map(paddedHex).join('')}`);\n }\n\n /**\n * Return the last two groups of this address as an IPv4 address string\n * @memberof Address6\n * @instance\n * @returns {Address4}\n * @example\n * var address = new Address6('2001:4860:4001::1825:bf11');\n * address.to4().correctForm(); // '24.37.191.17'\n */\n to4(): Address4 {\n const binary = this.binaryZeroPad().split('');\n\n return Address4.fromHex(BigInt(`0b${binary.slice(96, 128).join('')}`).toString(16));\n }\n\n /**\n * Return the v4-in-v6 form of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n to4in6(): string {\n const address4 = this.to4();\n const address6 = new Address6(this.parsedAddress.slice(0, 6).join(':'), 6);\n\n const correct = address6.correctForm();\n\n let infix = '';\n\n if (!/:$/.test(correct)) {\n infix = ':';\n }\n\n return correct + infix + address4.address;\n }\n\n /**\n * Return an object containing the Teredo properties of the address\n * @memberof Address6\n * @instance\n * @returns {Object}\n */\n inspectTeredo(): TeredoProperties {\n /*\n - Bits 0 to 31 are set to the Teredo prefix (normally 2001:0000::/32).\n - Bits 32 to 63 embed the primary IPv4 address of the Teredo server that\n is used.\n - Bits 64 to 79 can be used to define some flags. Currently only the\n higher order bit is used; it is set to 1 if the Teredo client is\n located behind a cone NAT, 0 otherwise. For Microsoft's Windows Vista\n and Windows Server 2008 implementations, more bits are used. In those\n implementations, the format for these 16 bits is \"CRAAAAUG AAAAAAAA\",\n where \"C\" remains the \"Cone\" flag. The \"R\" bit is reserved for future\n use. The \"U\" bit is for the Universal/Local flag (set to 0). The \"G\" bit\n is Individual/Group flag (set to 0). The A bits are set to a 12-bit\n randomly generated number chosen by the Teredo client to introduce\n additional protection for the Teredo node against IPv6-based scanning\n attacks.\n - Bits 80 to 95 contains the obfuscated UDP port number. This is the\n port number that is mapped by the NAT to the Teredo client with all\n bits inverted.\n - Bits 96 to 127 contains the obfuscated IPv4 address. This is the\n public IPv4 address of the NAT with all bits inverted.\n */\n const prefix = this.getBitsBase16(0, 32);\n\n const bitsForUdpPort: bigint = this.getBits(80, 96);\n // eslint-disable-next-line no-bitwise\n const udpPort = (bitsForUdpPort ^ BigInt('0xffff')).toString();\n\n const server4 = Address4.fromHex(this.getBitsBase16(32, 64));\n\n const bitsForClient4 = this.getBits(96, 128);\n // eslint-disable-next-line no-bitwise\n const client4 = Address4.fromHex((bitsForClient4 ^ BigInt('0xffffffff')).toString(16));\n\n const flagsBase2 = this.getBitsBase2(64, 80);\n\n const coneNat = testBit(flagsBase2, 15);\n const reserved = testBit(flagsBase2, 14);\n const groupIndividual = testBit(flagsBase2, 8);\n const universalLocal = testBit(flagsBase2, 9);\n const nonce = BigInt(`0b${flagsBase2.slice(2, 6) + flagsBase2.slice(8, 16)}`).toString(10);\n\n return {\n prefix: `${prefix.slice(0, 4)}:${prefix.slice(4, 8)}`,\n server4: server4.address,\n client4: client4.address,\n flags: flagsBase2,\n coneNat,\n microsoft: {\n reserved,\n universalLocal,\n groupIndividual,\n nonce,\n },\n udpPort,\n };\n }\n\n /**\n * Return an object containing the 6to4 properties of the address\n * @memberof Address6\n * @instance\n * @returns {Object}\n */\n inspect6to4(): SixToFourProperties {\n /*\n - Bits 0 to 15 are set to the 6to4 prefix (2002::/16).\n - Bits 16 to 48 embed the IPv4 address of the 6to4 gateway that is used.\n */\n\n const prefix = this.getBitsBase16(0, 16);\n\n const gateway = Address4.fromHex(this.getBitsBase16(16, 48));\n\n return {\n prefix: prefix.slice(0, 4),\n gateway: gateway.address,\n };\n }\n\n /**\n * Return a v6 6to4 address from a v6 v4inv6 address\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n to6to4(): Address6 | null {\n if (!this.is4()) {\n return null;\n }\n\n const addr6to4 = [\n '2002',\n this.getBitsBase16(96, 112),\n this.getBitsBase16(112, 128),\n '',\n '/16',\n ].join(':');\n\n return new Address6(addr6to4);\n }\n\n /**\n * Return a byte array\n * @memberof Address6\n * @instance\n * @returns {Array}\n */\n toByteArray(): number[] {\n const valueWithoutPadding = this.bigInt().toString(16);\n const leadingPad = '0'.repeat(valueWithoutPadding.length % 2);\n\n const value = `${leadingPad}${valueWithoutPadding}`;\n\n const bytes = [];\n for (let i = 0, length = value.length; i < length; i += 2) {\n bytes.push(parseInt(value.substring(i, i + 2), 16));\n }\n\n return bytes;\n }\n\n /**\n * Return an unsigned byte array\n * @memberof Address6\n * @instance\n * @returns {Array}\n */\n toUnsignedByteArray(): number[] {\n return this.toByteArray().map(unsignByte);\n }\n\n /**\n * Convert a byte array to an Address6 object\n * @memberof Address6\n * @static\n * @returns {Address6}\n */\n static fromByteArray(bytes: Array<any>): Address6 {\n return this.fromUnsignedByteArray(bytes.map(unsignByte));\n }\n\n /**\n * Convert an unsigned byte array to an Address6 object\n * @memberof Address6\n * @static\n * @returns {Address6}\n */\n static fromUnsignedByteArray(bytes: Array<any>): Address6 {\n const BYTE_MAX = BigInt('256');\n let result = BigInt('0');\n let multiplier = BigInt('1');\n\n for (let i = bytes.length - 1; i >= 0; i--) {\n result += multiplier * BigInt(bytes[i].toString(10));\n\n multiplier *= BYTE_MAX;\n }\n\n return Address6.fromBigInt(result);\n }\n\n // #region Attributes\n /**\n * Returns true if the given address is in the subnet of the current address\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isInSubnet = common.isInSubnet;\n\n /**\n * Returns true if the address is correct, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isCorrect = common.isCorrect(constants6.BITS);\n\n /**\n * Returns true if the address is in the canonical form, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isCanonical(): boolean {\n return this.addressMinusSuffix === this.canonicalForm();\n }\n\n /**\n * Returns true if the address is a link local address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isLinkLocal(): boolean {\n // Zeroes are required, i.e. we can't check isInSubnet with 'fe80::/10'\n if (\n this.getBitsBase2(0, 64) ===\n '1111111010000000000000000000000000000000000000000000000000000000'\n ) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Returns true if the address is a multicast address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isMulticast(): boolean {\n return this.getType() === 'Multicast';\n }\n\n /**\n * Returns true if the address is a v4-in-v6 address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n is4(): boolean {\n return this.v4;\n }\n\n /**\n * Returns true if the address is a Teredo address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isTeredo(): boolean {\n return this.isInSubnet(new Address6('2001::/32'));\n }\n\n /**\n * Returns true if the address is a 6to4 address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n is6to4(): boolean {\n return this.isInSubnet(new Address6('2002::/16'));\n }\n\n /**\n * Returns true if the address is a loopback address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isLoopback(): boolean {\n return this.getType() === 'Loopback';\n }\n // #endregion\n\n // #region HTML\n /**\n * @returns {String} the address in link form with a default port of 80\n */\n href(optionalPort?: number | string): string {\n if (optionalPort === undefined) {\n optionalPort = '';\n } else {\n optionalPort = `:${optionalPort}`;\n }\n\n return `http://[${this.correctForm()}]${optionalPort}/`;\n }\n\n /**\n * @returns {String} a link suitable for conveying the address via a URL hash\n */\n link(options?: { className?: string; prefix?: string; v4?: boolean }): string {\n if (!options) {\n options = {};\n }\n\n if (options.className === undefined) {\n options.className = '';\n }\n\n if (options.prefix === undefined) {\n options.prefix = '/#address=';\n }\n\n if (options.v4 === undefined) {\n options.v4 = false;\n }\n\n let formFunction = this.correctForm;\n\n if (options.v4) {\n formFunction = this.to4in6;\n }\n\n const form = formFunction.call(this);\n\n if (options.className) {\n return `<a href=\"${options.prefix}${form}\" class=\"${options.className}\">${form}</a>`;\n }\n\n return `<a href=\"${options.prefix}${form}\">${form}</a>`;\n }\n\n /**\n * Groups an address\n * @returns {String}\n */\n group(): string {\n if (this.elidedGroups === 0) {\n // The simple case\n return helpers.simpleGroup(this.address).join(':');\n }\n\n assert(typeof this.elidedGroups === 'number');\n assert(typeof this.elisionBegin === 'number');\n\n // The elided case\n const output = [];\n\n const [left, right] = this.address.split('::');\n\n if (left.length) {\n output.push(...helpers.simpleGroup(left));\n } else {\n output.push('');\n }\n\n const classes = ['hover-group'];\n\n for (let i = this.elisionBegin; i < this.elisionBegin + this.elidedGroups; i++) {\n classes.push(`group-${i}`);\n }\n\n output.push(`<span class=\"${classes.join(' ')}\"></span>`);\n\n if (right.length) {\n output.push(...helpers.simpleGroup(right, this.elisionEnd));\n } else {\n output.push('');\n }\n\n if (this.is4()) {\n assert(this.address4 instanceof Address4);\n\n output.pop();\n output.push(this.address4.groupForV6());\n }\n\n return output.join(':');\n }\n // #endregion\n\n // #region Regular expressions\n /**\n * Generate a regular expression string that can be used to find or validate\n * all variations of this address\n * @memberof Address6\n * @instance\n * @param {boolean} substringSearch\n * @returns {string}\n */\n regularExpressionString(this: Address6, substringSearch: boolean = false): string {\n let output: string[] = [];\n\n // TODO: revisit why this is necessary\n const address6 = new Address6(this.correctForm());\n\n if (address6.elidedGroups === 0) {\n // The simple case\n output.push(simpleRegularExpression(address6.parsedAddress));\n } else if (address6.elidedGroups === constants6.GROUPS) {\n // A completely elided address\n output.push(possibleElisions(constants6.GROUPS));\n } else {\n // A partially elided address\n const halves = address6.address.split('::');\n\n if (halves[0].length) {\n output.push(simpleRegularExpression(halves[0].split(':')));\n }\n\n assert(typeof address6.elidedGroups === 'number');\n\n output.push(\n possibleElisions(address6.elidedGroups, halves[0].length !== 0, halves[1].length !== 0),\n );\n\n if (halves[1].length) {\n output.push(simpleRegularExpression(halves[1].split(':')));\n }\n\n output = [output.join(':')];\n }\n\n if (!substringSearch) {\n output = [\n '(?=^|',\n ADDRESS_BOUNDARY,\n '|[^\\\\w\\\\:])(',\n ...output,\n ')(?=[^\\\\w\\\\:]|',\n ADDRESS_BOUNDARY,\n '|$)',\n ];\n }\n\n return output.join('');\n }\n\n /**\n * Generate a regular expression that can be used to find or validate all\n * variations of this address.\n * @memberof Address6\n * @instance\n * @param {boolean} substringSearch\n * @returns {RegExp}\n */\n regularExpression(this: Address6, substringSearch: boolean = false): RegExp {\n return new RegExp(this.regularExpressionString(substringSearch), 'i');\n }\n // #endregion\n}\n", "export { Address4 } from './ipv4';\nexport { Address6 } from './ipv6';\nexport { AddressError } from './address-error';\n\nimport * as helpers from './v6/helpers';\n\nexport const v6 = { helpers };\n", "import { Database } from 'bun:sqlite';\nimport { existsSync, statSync } from 'fs';\nimport type { Observation, Summary, SearchFilters, TimelineEntry } from '../../types/worker-types.js';\n\n/**\n * Advanced search module for Kiro Memory\n * Supports FTS5 full-text search with LIKE fallback\n */\n\n/**\n * BM25 weights for FTS5 columns: title, text, narrative, concepts.\n * Higher values = more relevant column in ranking.\n */\nconst BM25_WEIGHTS = '10.0, 1.0, 5.0, 3.0';\n\n/** Escape LIKE wildcard characters to prevent pattern injection */\nfunction escapeLikePattern(input: string): string {\n return input.replace(/[%_\\\\]/g, '\\\\$&');\n}\n\n/**\n * Sanitize a query for FTS5: wraps each term in quotes\n * to prevent reserved operators (AND, OR, NOT, NEAR, *, ^, :)\n * from causing parsing errors. Limits length and term count to prevent ReDoS.\n */\nfunction sanitizeFTS5Query(query: string): string {\n // Limit input length before parsing\n const trimmed = query.length > 10_000 ? query.substring(0, 10_000) : query;\n\n const terms = trimmed\n .replace(/[\"\"\\u0022]/g, '')\n .split(/\\s+/)\n .filter(t => t.length > 0)\n .slice(0, 100)\n .map(t => `\"${t}\"`);\n\n return terms.join(' ');\n}\n\n/**\n * Search observations with FTS5 (full-text) and optional filters.\n * Sanitizes the FTS5 query and falls back to LIKE on error.\n */\nexport function searchObservationsFTS(\n db: Database,\n query: string,\n filters: SearchFilters = {}\n): Observation[] {\n const limit = filters.limit || 50;\n\n try {\n const safeQuery = sanitizeFTS5Query(query);\n if (!safeQuery) return searchObservationsLIKE(db, query, filters);\n\n let sql = `\n SELECT o.* FROM observations o\n JOIN observations_fts fts ON o.id = fts.rowid\n WHERE observations_fts MATCH ?\n `;\n const params: (string | number)[] = [safeQuery];\n\n if (filters.project) {\n sql += ' AND o.project = ?';\n params.push(filters.project);\n }\n if (filters.type) {\n sql += ' AND o.type = ?';\n params.push(filters.type);\n }\n if (filters.dateStart) {\n sql += ' AND o.created_at_epoch >= ?';\n params.push(filters.dateStart);\n }\n if (filters.dateEnd) {\n sql += ' AND o.created_at_epoch <= ?';\n params.push(filters.dateEnd);\n }\n\n sql += ` ORDER BY bm25(observations_fts, ${BM25_WEIGHTS}) LIMIT ?`;\n params.push(limit);\n\n const stmt = db.query(sql);\n return stmt.all(...params) as Observation[];\n } catch {\n // Fallback to LIKE if FTS5 is unavailable or query is malformed\n return searchObservationsLIKE(db, query, filters);\n }\n}\n\n/**\n * FTS5 search that exposes the raw rank for scoring.\n * The FTS5 rank is negative: more negative = more relevant.\n * Uses sanitizeFTS5Query for safety, falls back to LIKE without rank.\n */\nexport function searchObservationsFTSWithRank(\n db: Database,\n query: string,\n filters: SearchFilters = {}\n): Array<Observation & { fts5_rank: number }> {\n const limit = filters.limit || 50;\n\n try {\n const safeQuery = sanitizeFTS5Query(query);\n if (!safeQuery) return [];\n\n let sql = `\n SELECT o.*, bm25(observations_fts, ${BM25_WEIGHTS}) as fts5_rank FROM observations o\n JOIN observations_fts fts ON o.id = fts.rowid\n WHERE observations_fts MATCH ?\n `;\n const params: (string | number)[] = [safeQuery];\n\n if (filters.project) {\n sql += ' AND o.project = ?';\n params.push(filters.project);\n }\n if (filters.type) {\n sql += ' AND o.type = ?';\n params.push(filters.type);\n }\n if (filters.dateStart) {\n sql += ' AND o.created_at_epoch >= ?';\n params.push(filters.dateStart);\n }\n if (filters.dateEnd) {\n sql += ' AND o.created_at_epoch <= ?';\n params.push(filters.dateEnd);\n }\n\n sql += ` ORDER BY bm25(observations_fts, ${BM25_WEIGHTS}) LIMIT ?`;\n params.push(limit);\n\n const stmt = db.query(sql);\n return stmt.all(...params) as Array<Observation & { fts5_rank: number }>;\n } catch {\n // Fallback: no rank available\n return [];\n }\n}\n\n/**\n * Fallback: LIKE search on observations\n */\nexport function searchObservationsLIKE(\n db: Database,\n query: string,\n filters: SearchFilters = {}\n): Observation[] {\n const limit = filters.limit || 50;\n const pattern = `%${escapeLikePattern(query)}%`;\n let sql = `\n SELECT * FROM observations\n WHERE (title LIKE ? ESCAPE '\\\\' OR text LIKE ? ESCAPE '\\\\' OR narrative LIKE ? ESCAPE '\\\\' OR concepts LIKE ? ESCAPE '\\\\')\n `;\n const params: (string | number)[] = [pattern, pattern, pattern, pattern];\n\n if (filters.project) {\n sql += ' AND project = ?';\n params.push(filters.project);\n }\n if (filters.type) {\n sql += ' AND type = ?';\n params.push(filters.type);\n }\n if (filters.dateStart) {\n sql += ' AND created_at_epoch >= ?';\n params.push(filters.dateStart);\n }\n if (filters.dateEnd) {\n sql += ' AND created_at_epoch <= ?';\n params.push(filters.dateEnd);\n }\n\n sql += ' ORDER BY created_at_epoch DESC LIMIT ?';\n params.push(limit);\n\n const stmt = db.query(sql);\n return stmt.all(...params) as Observation[];\n}\n\n/**\n * Search summaries with filters\n */\nexport function searchSummariesFiltered(\n db: Database,\n query: string,\n filters: SearchFilters = {}\n): Summary[] {\n const limit = filters.limit || 20;\n const pattern = `%${escapeLikePattern(query)}%`;\n let sql = `\n SELECT * FROM summaries\n WHERE (request LIKE ? ESCAPE '\\\\' OR learned LIKE ? ESCAPE '\\\\' OR completed LIKE ? ESCAPE '\\\\' OR notes LIKE ? ESCAPE '\\\\' OR next_steps LIKE ? ESCAPE '\\\\')\n `;\n const params: (string | number)[] = [pattern, pattern, pattern, pattern, pattern];\n\n if (filters.project) {\n sql += ' AND project = ?';\n params.push(filters.project);\n }\n if (filters.dateStart) {\n sql += ' AND created_at_epoch >= ?';\n params.push(filters.dateStart);\n }\n if (filters.dateEnd) {\n sql += ' AND created_at_epoch <= ?';\n params.push(filters.dateEnd);\n }\n\n sql += ' ORDER BY created_at_epoch DESC LIMIT ?';\n params.push(limit);\n\n const stmt = db.query(sql);\n return stmt.all(...params) as Summary[];\n}\n\n/**\n * Retrieve observations by ID (batch)\n */\nexport function getObservationsByIds(db: Database, ids: number[]): Observation[] {\n if (!Array.isArray(ids) || ids.length === 0) return [];\n\n // Validate and filter: only positive integers, max 500 per query\n const validIds = ids\n .filter(id => typeof id === 'number' && Number.isInteger(id) && id > 0)\n .slice(0, 500);\n\n if (validIds.length === 0) return [];\n\n const placeholders = validIds.map(() => '?').join(',');\n const sql = `SELECT * FROM observations WHERE id IN (${placeholders}) ORDER BY created_at_epoch DESC`;\n const stmt = db.query(sql);\n return stmt.all(...validIds) as Observation[];\n}\n\n/**\n * Timeline: chronological context around an observation\n */\nexport function getTimeline(\n db: Database,\n anchorId: number,\n depthBefore: number = 5,\n depthAfter: number = 5\n): TimelineEntry[] {\n // Find the anchor's epoch\n const anchorStmt = db.query('SELECT created_at_epoch FROM observations WHERE id = ?');\n const anchor = anchorStmt.get(anchorId) as { created_at_epoch: number } | null;\n\n if (!anchor) return [];\n\n const anchorEpoch = anchor.created_at_epoch;\n\n // Observations before\n const beforeStmt = db.query(`\n SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch\n FROM observations\n WHERE created_at_epoch < ?\n ORDER BY created_at_epoch DESC\n LIMIT ?\n `);\n const before = (beforeStmt.all(anchorEpoch, depthBefore) as TimelineEntry[]).reverse();\n\n // The anchor itself\n const selfStmt = db.query(`\n SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch\n FROM observations WHERE id = ?\n `);\n const self = selfStmt.all(anchorId) as TimelineEntry[];\n\n // Observations after\n const afterStmt = db.query(`\n SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch\n FROM observations\n WHERE created_at_epoch > ?\n ORDER BY created_at_epoch ASC\n LIMIT ?\n `);\n const after = afterStmt.all(anchorEpoch, depthAfter) as TimelineEntry[];\n\n return [...before, ...self, ...after];\n}\n\n/**\n * Database statistics for a project.\n * Single CTE query replacing 6 separate queries.\n */\nexport function getProjectStats(db: Database, project: string): {\n observations: number;\n summaries: number;\n sessions: number;\n prompts: number;\n tokenEconomics: { discoveryTokens: number; readTokens: number; savings: number };\n} {\n const sql = `\n WITH\n obs_stats AS (\n SELECT\n COUNT(*) as count,\n COALESCE(SUM(discovery_tokens), 0) as discovery_tokens,\n COALESCE(SUM(\n CAST((LENGTH(COALESCE(title, '')) + LENGTH(COALESCE(narrative, ''))) / 4 AS INTEGER)\n ), 0) as read_tokens\n FROM observations WHERE project = ?\n ),\n sum_count AS (SELECT COUNT(*) as count FROM summaries WHERE project = ?),\n ses_count AS (SELECT COUNT(*) as count FROM sessions WHERE project = ?),\n prm_count AS (SELECT COUNT(*) as count FROM prompts WHERE project = ?)\n SELECT\n obs_stats.count as observations,\n obs_stats.discovery_tokens,\n obs_stats.read_tokens,\n sum_count.count as summaries,\n ses_count.count as sessions,\n prm_count.count as prompts\n FROM obs_stats, sum_count, ses_count, prm_count\n `;\n\n const row = db.query(sql).get(project, project, project, project) as any;\n\n const discoveryTokens = row?.discovery_tokens || 0;\n const readTokens = row?.read_tokens || 0;\n const savings = Math.max(0, discoveryTokens - readTokens);\n\n return {\n observations: row?.observations || 0,\n summaries: row?.summaries || 0,\n sessions: row?.sessions || 0,\n prompts: row?.prompts || 0,\n tokenEconomics: { discoveryTokens, readTokens, savings },\n };\n}\n\n/**\n * Find observations with files modified after the observation was created.\n * Checks the filesystem mtime for each file in files_modified.\n */\nexport function getStaleObservations(db: Database, project: string): Observation[] {\n // Query observations with non-empty files_modified\n const rows = db.query(`\n SELECT * FROM observations\n WHERE project = ? AND files_modified IS NOT NULL AND files_modified != ''\n ORDER BY created_at_epoch DESC\n LIMIT 500\n `).all(project) as Observation[];\n\n const staleObs: Observation[] = [];\n\n for (const obs of rows) {\n if (!obs.files_modified) continue;\n\n // Parse files_modified (comma-separated)\n const files = obs.files_modified.split(',').map(f => f.trim()).filter(Boolean);\n\n let isStale = false;\n for (const filepath of files) {\n try {\n if (!existsSync(filepath)) continue; // File removed, cannot verify\n const stat = statSync(filepath);\n if (stat.mtimeMs > obs.created_at_epoch) {\n isStale = true;\n break;\n }\n } catch {\n // File not accessible, skip\n }\n }\n\n if (isStale) {\n staleObs.push(obs);\n }\n }\n\n return staleObs;\n}\n\n/**\n * Mark observations as stale (1) or fresh (0) in the database.\n */\nexport function markObservationsStale(db: Database, ids: number[], stale: boolean): void {\n if (!Array.isArray(ids) || ids.length === 0) return;\n\n const validIds = ids\n .filter(id => typeof id === 'number' && Number.isInteger(id) && id > 0)\n .slice(0, 500);\n\n if (validIds.length === 0) return;\n\n const placeholders = validIds.map(() => '?').join(',');\n db.run(\n `UPDATE observations SET is_stale = ? WHERE id IN (${placeholders})`,\n [stale ? 1 : 0, ...validIds]\n );\n}\n", "import { Database } from 'bun:sqlite';\nimport type { Observation } from '../../types/worker-types.js';\n\n/**\n * Observation operations for Kiro Memory database\n */\n\n/** Escape LIKE wildcard characters to prevent pattern injection */\nfunction escapeLikePattern(input: string): string {\n return input.replace(/[%_\\\\]/g, '\\\\$&');\n}\n\n/**\n * Check if an observation with the same content_hash exists within the last 30 seconds.\n * Returns true if it is a duplicate (to be discarded).\n */\nexport function isDuplicateObservation(db: Database, contentHash: string, windowMs: number = 30_000): boolean {\n if (!contentHash) return false;\n const threshold = Date.now() - windowMs;\n const result = db.query(\n 'SELECT id FROM observations WHERE content_hash = ? AND created_at_epoch > ? LIMIT 1'\n ).get(contentHash, threshold);\n return !!result;\n}\n\nexport function createObservation(\n db: Database,\n memorySessionId: string,\n project: string,\n type: string,\n title: string,\n subtitle: string | null,\n text: string | null,\n narrative: string | null,\n facts: string | null,\n concepts: string | null,\n filesRead: string | null,\n filesModified: string | null,\n promptNumber: number,\n contentHash: string | null = null,\n discoveryTokens: number = 0\n): number {\n const now = new Date();\n const result = db.run(\n `INSERT INTO observations\n (memory_session_id, project, type, title, subtitle, text, narrative, facts, concepts, files_read, files_modified, prompt_number, created_at, created_at_epoch, content_hash, discovery_tokens)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [memorySessionId, project, type, title, subtitle, text, narrative, facts, concepts, filesRead, filesModified, promptNumber, now.toISOString(), now.getTime(), contentHash, discoveryTokens]\n );\n return Number(result.lastInsertRowid);\n}\n\nexport function getObservationsBySession(db: Database, memorySessionId: string): Observation[] {\n const query = db.query(\n 'SELECT * FROM observations WHERE memory_session_id = ? ORDER BY prompt_number ASC'\n );\n return query.all(memorySessionId) as Observation[];\n}\n\nexport function getObservationsByProject(db: Database, project: string, limit: number = 100): Observation[] {\n const query = db.query(\n 'SELECT * FROM observations WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ?'\n );\n return query.all(project, limit) as Observation[];\n}\n\nexport function searchObservations(db: Database, searchTerm: string, project?: string): Observation[] {\n const sql = project\n ? `SELECT * FROM observations\n WHERE project = ? AND (title LIKE ? ESCAPE '\\\\' OR text LIKE ? ESCAPE '\\\\' OR narrative LIKE ? ESCAPE '\\\\')\n ORDER BY created_at_epoch DESC`\n : `SELECT * FROM observations\n WHERE title LIKE ? ESCAPE '\\\\' OR text LIKE ? ESCAPE '\\\\' OR narrative LIKE ? ESCAPE '\\\\'\n ORDER BY created_at_epoch DESC`;\n\n const pattern = `%${escapeLikePattern(searchTerm)}%`;\n const query = db.query(sql);\n\n if (project) {\n return query.all(project, pattern, pattern, pattern) as Observation[];\n }\n return query.all(pattern, pattern, pattern) as Observation[];\n}\n\nexport function deleteObservation(db: Database, id: number): void {\n db.run('DELETE FROM observations WHERE id = ?', [id]);\n}\n\n/**\n * Update the last access timestamp for observations found in search.\n * Fire-and-forget: non-blocking, ignores errors.\n */\nexport function updateLastAccessed(db: Database, ids: number[]): void {\n if (!Array.isArray(ids) || ids.length === 0) return;\n\n const validIds = ids\n .filter(id => typeof id === 'number' && Number.isInteger(id) && id > 0)\n .slice(0, 500);\n\n if (validIds.length === 0) return;\n\n const now = Date.now();\n const placeholders = validIds.map(() => '?').join(',');\n db.run(\n `UPDATE observations SET last_accessed_epoch = ? WHERE id IN (${placeholders})`,\n [now, ...validIds]\n );\n}\n\n/**\n * Consolidate duplicate observations on the same file and type.\n * Groups by (project, type, files_modified), keeps the most recent,\n * concatenates unique contents, deletes the old ones.\n *\n * Fix: counts calculated inside the transaction and returned directly,\n * dry-run separated from the transaction to avoid unnecessary locks.\n */\nexport function consolidateObservations(\n db: Database,\n project: string,\n options: { dryRun?: boolean; minGroupSize?: number } = {}\n): { merged: number; removed: number } {\n const minGroupSize = options.minGroupSize || 3;\n\n // Find groups of observations with the same (project, type, files_modified)\n const groups = db.query(`\n SELECT type, files_modified, COUNT(*) as cnt, GROUP_CONCAT(id) as ids\n FROM observations\n WHERE project = ? AND files_modified IS NOT NULL AND files_modified != ''\n GROUP BY type, files_modified\n HAVING cnt >= ?\n ORDER BY cnt DESC\n `).all(project, minGroupSize) as Array<{\n type: string;\n files_modified: string;\n cnt: number;\n ids: string;\n }>;\n\n if (groups.length === 0) return { merged: 0, removed: 0 };\n\n // Dry-run: calculate counts without opening a transaction\n if (options.dryRun) {\n let totalMerged = 0;\n let totalRemoved = 0;\n\n for (const group of groups) {\n const obsIds = group.ids.split(',').map(Number);\n const placeholders = obsIds.map(() => '?').join(',');\n const count = (db.query(\n `SELECT COUNT(*) as cnt FROM observations WHERE id IN (${placeholders})`\n ).get(...obsIds) as { cnt: number })?.cnt || 0;\n\n if (count >= minGroupSize) {\n totalMerged += 1;\n totalRemoved += count - 1;\n }\n }\n\n return { merged: totalMerged, removed: totalRemoved };\n }\n\n // Execute consolidation in an atomic transaction.\n // Counts are calculated and returned by the transaction itself,\n // so if it fails no partial values remain.\n const runConsolidation = db.transaction(() => {\n let merged = 0;\n let removed = 0;\n\n for (const group of groups) {\n const obsIds = group.ids.split(',').map(Number);\n const placeholders = obsIds.map(() => '?').join(',');\n const observations = db.query(\n `SELECT * FROM observations WHERE id IN (${placeholders}) ORDER BY created_at_epoch DESC`\n ).all(...obsIds) as Observation[];\n\n if (observations.length < minGroupSize) continue;\n\n // Keep the most recent, concatenate unique contents from the others\n const keeper = observations[0];\n const others = observations.slice(1);\n\n const uniqueTexts = new Set<string>();\n if (keeper.text) uniqueTexts.add(keeper.text);\n for (const obs of others) {\n if (obs.text && !uniqueTexts.has(obs.text)) {\n uniqueTexts.add(obs.text);\n }\n }\n\n // Update the keeper with consolidated text\n const consolidatedText = Array.from(uniqueTexts).join('\\n---\\n').substring(0, 100_000);\n db.run(\n 'UPDATE observations SET text = ?, title = ? WHERE id = ?',\n [consolidatedText, `[consolidated x${observations.length}] ${keeper.title}`, keeper.id]\n );\n\n // Delete old observations (and their embeddings)\n const removeIds = others.map(o => o.id);\n const removePlaceholders = removeIds.map(() => '?').join(',');\n db.run(`DELETE FROM observations WHERE id IN (${removePlaceholders})`, removeIds);\n db.run(`DELETE FROM observation_embeddings WHERE observation_id IN (${removePlaceholders})`, removeIds);\n\n merged += 1;\n removed += removeIds.length;\n }\n\n return { merged, removed };\n });\n\n return runConsolidation();\n}\n", "/**\n * Kiro Memory Worker Service\n *\n * Lean orchestrator: configures Express, mounts modular routers,\n * manages lifecycle (PID, shutdown, error handling).\n *\n * Routes defined in src/services/routes/:\n * core.ts \u2014 health, SSE, notify\n * observations.ts \u2014 CRUD observations, knowledge, memory save\n * summaries.ts \u2014 CRUD summaries\n * search.ts \u2014 FTS5, hybrid search, timeline\n * analytics.ts \u2014 overview, timeline, types, sessions\n * sessions.ts \u2014 sessions, checkpoint, prompts\n * projects.ts \u2014 project list, aliases, stats\n * data.ts \u2014 embeddings, retention, export, report\n */\n\nimport express from 'express';\nimport cors from 'cors';\nimport helmet from 'helmet';\nimport rateLimit from 'express-rate-limit';\nimport crypto from 'crypto';\nimport { join, dirname } from 'path';\nimport { existsSync, mkdirSync, writeFileSync, unlinkSync, chmodSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { KiroMemoryDatabase } from './sqlite/Database.js';\nimport { getHybridSearch } from './search/HybridSearch.js';\nimport { createWorkerContext, getClients } from './worker-context.js';\nimport { logger } from '../utils/logger.js';\nimport { DATA_DIR } from '../shared/paths.js';\n\n// Modular routers\nimport { createCoreRouter } from './routes/core.js';\nimport { createObservationsRouter } from './routes/observations.js';\nimport { createSummariesRouter } from './routes/summaries.js';\nimport { createSearchRouter } from './routes/search.js';\nimport { createAnalyticsRouter } from './routes/analytics.js';\nimport { createSessionsRouter } from './routes/sessions.js';\nimport { createProjectsRouter } from './routes/projects.js';\nimport { createDataRouter } from './routes/data.js';\n\n// \u2500\u2500 Configuration \u2500\u2500\n\nconst __worker_dirname = dirname(fileURLToPath(import.meta.url));\nconst PORT = process.env.KIRO_MEMORY_WORKER_PORT || process.env.CONTEXTKIT_WORKER_PORT || 3001;\nconst HOST = process.env.KIRO_MEMORY_WORKER_HOST || process.env.CONTEXTKIT_WORKER_HOST || '127.0.0.1';\nconst PID_FILE = join(DATA_DIR, 'worker.pid');\nconst TOKEN_FILE = join(DATA_DIR, 'worker.token');\n\n// \u2500\u2500 Initialization \u2500\u2500\n\nif (!existsSync(DATA_DIR)) {\n mkdirSync(DATA_DIR, { recursive: true });\n}\n\n// Authentication token for hook \u2192 worker communication\nconst WORKER_TOKEN = crypto.randomBytes(32).toString('hex');\nwriteFileSync(TOKEN_FILE, WORKER_TOKEN, 'utf-8');\ntry {\n chmodSync(TOKEN_FILE, 0o600);\n} catch (err) {\n if (process.platform !== 'win32') {\n logger.warn('WORKER', `chmod 600 failed on ${TOKEN_FILE}`, {}, err as Error);\n }\n}\n\n// Database\nconst db = new KiroMemoryDatabase();\nlogger.info('WORKER', 'Database initialized');\n\n// Embedding service (lazy, non bloccante)\ngetHybridSearch().initialize().catch(err => {\n logger.warn('WORKER', 'Embedding initialization failed, FTS5 search only', {}, err as Error);\n});\n\n// Shared context for all routers\nconst ctx = createWorkerContext(db);\n\n// \u2500\u2500 Express app \u2500\u2500\n\nconst app = express();\n\n// Security: protective HTTP headers\napp.use(helmet({\n contentSecurityPolicy: {\n directives: {\n defaultSrc: [\"'self'\"],\n scriptSrc: [\"'self'\", \"'unsafe-inline'\"],\n styleSrc: [\"'self'\", \"'unsafe-inline'\", \"https://fonts.googleapis.com\"],\n imgSrc: [\"'self'\", \"data:\"],\n connectSrc: [\"'self'\"],\n fontSrc: [\"'self'\", \"https://fonts.gstatic.com\"],\n frameSrc: [\"'none'\"]\n }\n }\n}));\n\n// CORS restricted to localhost\napp.use(cors({\n origin: [\n `http://localhost:${PORT}`,\n `http://127.0.0.1:${PORT}`,\n `http://${HOST}:${PORT}`\n ],\n credentials: true,\n maxAge: 86400\n}));\n\n// Body size limit: 1MB\napp.use(express.json({ limit: '1mb' }));\n\n// Global rate limiting: 200 req/min per IP\napp.use('/api/', rateLimit({\n windowMs: 60_000,\n max: 200,\n standardHeaders: true,\n legacyHeaders: false,\n message: { error: 'Too many requests, retry later' }\n}));\n\n// \u2500\u2500 Mount modular routers \u2500\u2500\n\napp.use(createCoreRouter(ctx, WORKER_TOKEN));\napp.use(createObservationsRouter(ctx));\napp.use(createSummariesRouter(ctx));\napp.use(createSearchRouter(ctx));\napp.use(createAnalyticsRouter(ctx));\napp.use(createSessionsRouter(ctx));\napp.use(createProjectsRouter(ctx));\napp.use(createDataRouter(ctx, WORKER_TOKEN));\n\n// \u2500\u2500 Static files and viewer \u2500\u2500\n\napp.use(express.static(__worker_dirname, {\n index: false,\n maxAge: '1h'\n}));\n\napp.get('/', (_req, res) => {\n const viewerPath = join(__worker_dirname, 'viewer.html');\n if (existsSync(viewerPath)) {\n res.sendFile(viewerPath);\n } else {\n res.status(404).json({ error: 'Viewer not found. Run npm run build first.' });\n }\n});\n\n// \u2500\u2500 Server startup \u2500\u2500\n\nconst server = app.listen(Number(PORT), HOST, () => {\n logger.info('WORKER', `Kiro Memory worker started on http://${HOST}:${PORT}`);\n writeFileSync(PID_FILE, String(process.pid), 'utf-8');\n});\n\n// \u2500\u2500 Graceful shutdown \u2500\u2500\n\nfunction shutdown(signal: string): void {\n logger.info('WORKER', `Received ${signal}, shutting down...`);\n\n // Close all SSE clients to unblock server.close()\n const sseClients = getClients();\n for (const client of sseClients) {\n try { client.end(); } catch { /* ignora errori su client gi\u00E0 chiusi */ }\n }\n\n // Force timeout: if server.close() doesn't complete in 5s, force exit\n const forceTimeout = setTimeout(() => {\n logger.warn('WORKER', 'Forced shutdown after 5s timeout');\n if (existsSync(PID_FILE)) unlinkSync(PID_FILE);\n db.close();\n process.exit(1);\n }, 5000);\n\n server.close(() => {\n clearTimeout(forceTimeout);\n logger.info('WORKER', 'Server closed');\n\n if (existsSync(PID_FILE)) {\n unlinkSync(PID_FILE);\n }\n\n db.close();\n process.exit(0);\n });\n}\n\nprocess.on('SIGTERM', () => shutdown('SIGTERM'));\nprocess.on('SIGINT', () => shutdown('SIGINT'));\n\nprocess.on('uncaughtException', (error) => {\n logger.error('WORKER', 'Uncaught exception', {}, error);\n shutdown('uncaughtException');\n});\n\nprocess.on('unhandledRejection', (reason) => {\n logger.error('WORKER', 'Unhandled promise rejection', { reason }, reason as Error);\n});\n", "const dangerouslyDisableDefaultSrc = Symbol(\"dangerouslyDisableDefaultSrc\")\nconst SHOULD_BE_QUOTED = new Set([\"none\", \"self\", \"strict-dynamic\", \"report-sample\", \"inline-speculation-rules\", \"unsafe-inline\", \"unsafe-eval\", \"unsafe-hashes\", \"wasm-unsafe-eval\"])\nconst getDefaultDirectives = () => ({\n\t\"default-src\": [\"'self'\"],\n\t\"base-uri\": [\"'self'\"],\n\t\"font-src\": [\"'self'\", \"https:\", \"data:\"],\n\t\"form-action\": [\"'self'\"],\n\t\"frame-ancestors\": [\"'self'\"],\n\t\"img-src\": [\"'self'\", \"data:\"],\n\t\"object-src\": [\"'none'\"],\n\t\"script-src\": [\"'self'\"],\n\t\"script-src-attr\": [\"'none'\"],\n\t\"style-src\": [\"'self'\", \"https:\", \"'unsafe-inline'\"],\n\t\"upgrade-insecure-requests\": []\n})\nconst dashify = str => str.replace(/[A-Z]/g, capitalLetter => \"-\" + capitalLetter.toLowerCase())\nconst assertDirectiveValueIsValid = (directiveName, directiveValue) => {\n\tif (/;|,/.test(directiveValue)) {\n\t\tthrow new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}`)\n\t}\n}\nconst assertDirectiveValueEntryIsValid = (directiveName, directiveValueEntry) => {\n\tif (SHOULD_BE_QUOTED.has(directiveValueEntry) || directiveValueEntry.startsWith(\"nonce-\") || directiveValueEntry.startsWith(\"sha256-\") || directiveValueEntry.startsWith(\"sha384-\") || directiveValueEntry.startsWith(\"sha512-\")) {\n\t\tthrow new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}. ${JSON.stringify(directiveValueEntry)} should be quoted`)\n\t}\n}\nfunction normalizeDirectives(options) {\n\tconst defaultDirectives = getDefaultDirectives()\n\tconst {useDefaults = true, directives: rawDirectives = defaultDirectives} = options\n\tconst result = new Map()\n\tconst directiveNamesSeen = new Set()\n\tconst directivesExplicitlyDisabled = new Set()\n\tfor (const rawDirectiveName in rawDirectives) {\n\t\tif (!Object.hasOwn(rawDirectives, rawDirectiveName)) {\n\t\t\tcontinue\n\t\t}\n\t\tif (rawDirectiveName.length === 0 || /[^a-zA-Z0-9-]/.test(rawDirectiveName)) {\n\t\t\tthrow new Error(`Content-Security-Policy received an invalid directive name ${JSON.stringify(rawDirectiveName)}`)\n\t\t}\n\t\tconst directiveName = dashify(rawDirectiveName)\n\t\tif (directiveNamesSeen.has(directiveName)) {\n\t\t\tthrow new Error(`Content-Security-Policy received a duplicate directive ${JSON.stringify(directiveName)}`)\n\t\t}\n\t\tdirectiveNamesSeen.add(directiveName)\n\t\tconst rawDirectiveValue = rawDirectives[rawDirectiveName]\n\t\tlet directiveValue\n\t\tif (rawDirectiveValue === null) {\n\t\t\tif (directiveName === \"default-src\") {\n\t\t\t\tthrow new Error(\"Content-Security-Policy needs a default-src but it was set to `null`. If you really want to disable it, set it to `contentSecurityPolicy.dangerouslyDisableDefaultSrc`.\")\n\t\t\t}\n\t\t\tdirectivesExplicitlyDisabled.add(directiveName)\n\t\t\tcontinue\n\t\t} else if (typeof rawDirectiveValue === \"string\") {\n\t\t\tdirectiveValue = [rawDirectiveValue]\n\t\t} else if (!rawDirectiveValue) {\n\t\t\tthrow new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}`)\n\t\t} else if (rawDirectiveValue === dangerouslyDisableDefaultSrc) {\n\t\t\tif (directiveName === \"default-src\") {\n\t\t\t\tdirectivesExplicitlyDisabled.add(\"default-src\")\n\t\t\t\tcontinue\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Content-Security-Policy: tried to disable ${JSON.stringify(directiveName)} as if it were default-src; simply omit the key`)\n\t\t\t}\n\t\t} else {\n\t\t\tdirectiveValue = rawDirectiveValue\n\t\t}\n\t\tfor (const element of directiveValue) {\n\t\t\tif (typeof element !== \"string\") continue\n\t\t\tassertDirectiveValueIsValid(directiveName, element)\n\t\t\tassertDirectiveValueEntryIsValid(directiveName, element)\n\t\t}\n\t\tresult.set(directiveName, directiveValue)\n\t}\n\tif (useDefaults) {\n\t\tObject.entries(defaultDirectives).forEach(([defaultDirectiveName, defaultDirectiveValue]) => {\n\t\t\tif (!result.has(defaultDirectiveName) && !directivesExplicitlyDisabled.has(defaultDirectiveName)) {\n\t\t\t\tresult.set(defaultDirectiveName, defaultDirectiveValue)\n\t\t\t}\n\t\t})\n\t}\n\tif (!result.size) {\n\t\tthrow new Error(\"Content-Security-Policy has no directives. Either set some or disable the header\")\n\t}\n\tif (!result.has(\"default-src\") && !directivesExplicitlyDisabled.has(\"default-src\")) {\n\t\tthrow new Error(\"Content-Security-Policy needs a default-src but none was provided. If you really want to disable it, set it to `contentSecurityPolicy.dangerouslyDisableDefaultSrc`.\")\n\t}\n\treturn result\n}\nfunction getHeaderValue(req, res, normalizedDirectives) {\n\tconst result = []\n\tfor (const [directiveName, rawDirectiveValue] of normalizedDirectives) {\n\t\tlet directiveValue = \"\"\n\t\tfor (const element of rawDirectiveValue) {\n\t\t\tif (typeof element === \"function\") {\n\t\t\t\tconst newElement = element(req, res)\n\t\t\t\tassertDirectiveValueEntryIsValid(directiveName, newElement)\n\t\t\t\tdirectiveValue += \" \" + newElement\n\t\t\t} else {\n\t\t\t\tdirectiveValue += \" \" + element\n\t\t\t}\n\t\t}\n\t\tif (directiveValue) {\n\t\t\tassertDirectiveValueIsValid(directiveName, directiveValue)\n\t\t\tresult.push(`${directiveName}${directiveValue}`)\n\t\t} else {\n\t\t\tresult.push(directiveName)\n\t\t}\n\t}\n\treturn result.join(\";\")\n}\nconst contentSecurityPolicy = function contentSecurityPolicy(options = {}) {\n\tconst headerName = options.reportOnly ? \"Content-Security-Policy-Report-Only\" : \"Content-Security-Policy\"\n\tconst normalizedDirectives = normalizeDirectives(options)\n\treturn function contentSecurityPolicyMiddleware(req, res, next) {\n\t\tconst result = getHeaderValue(req, res, normalizedDirectives)\n\t\tif (result instanceof Error) {\n\t\t\tnext(result)\n\t\t} else {\n\t\t\tres.setHeader(headerName, result)\n\t\t\tnext()\n\t\t}\n\t}\n}\ncontentSecurityPolicy.getDefaultDirectives = getDefaultDirectives\ncontentSecurityPolicy.dangerouslyDisableDefaultSrc = dangerouslyDisableDefaultSrc\n\nconst ALLOWED_POLICIES$2 = new Set([\"require-corp\", \"credentialless\", \"unsafe-none\"])\nfunction getHeaderValueFromOptions$6({policy = \"require-corp\"}) {\n\tif (ALLOWED_POLICIES$2.has(policy)) {\n\t\treturn policy\n\t} else {\n\t\tthrow new Error(`Cross-Origin-Embedder-Policy does not support the ${JSON.stringify(policy)} policy`)\n\t}\n}\nfunction crossOriginEmbedderPolicy(options = {}) {\n\tconst headerValue = getHeaderValueFromOptions$6(options)\n\treturn function crossOriginEmbedderPolicyMiddleware(_req, res, next) {\n\t\tres.setHeader(\"Cross-Origin-Embedder-Policy\", headerValue)\n\t\tnext()\n\t}\n}\n\nconst ALLOWED_POLICIES$1 = new Set([\"same-origin\", \"same-origin-allow-popups\", \"unsafe-none\"])\nfunction getHeaderValueFromOptions$5({policy = \"same-origin\"}) {\n\tif (ALLOWED_POLICIES$1.has(policy)) {\n\t\treturn policy\n\t} else {\n\t\tthrow new Error(`Cross-Origin-Opener-Policy does not support the ${JSON.stringify(policy)} policy`)\n\t}\n}\nfunction crossOriginOpenerPolicy(options = {}) {\n\tconst headerValue = getHeaderValueFromOptions$5(options)\n\treturn function crossOriginOpenerPolicyMiddleware(_req, res, next) {\n\t\tres.setHeader(\"Cross-Origin-Opener-Policy\", headerValue)\n\t\tnext()\n\t}\n}\n\nconst ALLOWED_POLICIES = new Set([\"same-origin\", \"same-site\", \"cross-origin\"])\nfunction getHeaderValueFromOptions$4({policy = \"same-origin\"}) {\n\tif (ALLOWED_POLICIES.has(policy)) {\n\t\treturn policy\n\t} else {\n\t\tthrow new Error(`Cross-Origin-Resource-Policy does not support the ${JSON.stringify(policy)} policy`)\n\t}\n}\nfunction crossOriginResourcePolicy(options = {}) {\n\tconst headerValue = getHeaderValueFromOptions$4(options)\n\treturn function crossOriginResourcePolicyMiddleware(_req, res, next) {\n\t\tres.setHeader(\"Cross-Origin-Resource-Policy\", headerValue)\n\t\tnext()\n\t}\n}\n\nfunction originAgentCluster() {\n\treturn function originAgentClusterMiddleware(_req, res, next) {\n\t\tres.setHeader(\"Origin-Agent-Cluster\", \"?1\")\n\t\tnext()\n\t}\n}\n\nconst ALLOWED_TOKENS = new Set([\"no-referrer\", \"no-referrer-when-downgrade\", \"same-origin\", \"origin\", \"strict-origin\", \"origin-when-cross-origin\", \"strict-origin-when-cross-origin\", \"unsafe-url\", \"\"])\nfunction getHeaderValueFromOptions$3({policy = [\"no-referrer\"]}) {\n\tconst tokens = typeof policy === \"string\" ? [policy] : policy\n\tif (tokens.length === 0) {\n\t\tthrow new Error(\"Referrer-Policy received no policy tokens\")\n\t}\n\tconst tokensSeen = new Set()\n\ttokens.forEach(token => {\n\t\tif (!ALLOWED_TOKENS.has(token)) {\n\t\t\tthrow new Error(`Referrer-Policy received an unexpected policy token ${JSON.stringify(token)}`)\n\t\t} else if (tokensSeen.has(token)) {\n\t\t\tthrow new Error(`Referrer-Policy received a duplicate policy token ${JSON.stringify(token)}`)\n\t\t}\n\t\ttokensSeen.add(token)\n\t})\n\treturn tokens.join(\",\")\n}\nfunction referrerPolicy(options = {}) {\n\tconst headerValue = getHeaderValueFromOptions$3(options)\n\treturn function referrerPolicyMiddleware(_req, res, next) {\n\t\tres.setHeader(\"Referrer-Policy\", headerValue)\n\t\tnext()\n\t}\n}\n\nconst DEFAULT_MAX_AGE = 365 * 24 * 60 * 60\nfunction parseMaxAge(value = DEFAULT_MAX_AGE) {\n\tif (value >= 0 && Number.isFinite(value)) {\n\t\treturn Math.floor(value)\n\t} else {\n\t\tthrow new Error(`Strict-Transport-Security: ${JSON.stringify(value)} is not a valid value for maxAge. Please choose a positive integer.`)\n\t}\n}\nfunction getHeaderValueFromOptions$2(options) {\n\tif (\"maxage\" in options) {\n\t\tthrow new Error(\"Strict-Transport-Security received an unsupported property, `maxage`. Did you mean to pass `maxAge`?\")\n\t}\n\tif (\"includeSubdomains\" in options) {\n\t\tthrow new Error('Strict-Transport-Security middleware should use `includeSubDomains` instead of `includeSubdomains`. (The correct one has an uppercase \"D\".)')\n\t}\n\tconst directives = [`max-age=${parseMaxAge(options.maxAge)}`]\n\tif (options.includeSubDomains === undefined || options.includeSubDomains) {\n\t\tdirectives.push(\"includeSubDomains\")\n\t}\n\tif (options.preload) {\n\t\tdirectives.push(\"preload\")\n\t}\n\treturn directives.join(\"; \")\n}\nfunction strictTransportSecurity(options = {}) {\n\tconst headerValue = getHeaderValueFromOptions$2(options)\n\treturn function strictTransportSecurityMiddleware(_req, res, next) {\n\t\tres.setHeader(\"Strict-Transport-Security\", headerValue)\n\t\tnext()\n\t}\n}\n\nfunction xContentTypeOptions() {\n\treturn function xContentTypeOptionsMiddleware(_req, res, next) {\n\t\tres.setHeader(\"X-Content-Type-Options\", \"nosniff\")\n\t\tnext()\n\t}\n}\n\nfunction xDnsPrefetchControl(options = {}) {\n\tconst headerValue = options.allow ? \"on\" : \"off\"\n\treturn function xDnsPrefetchControlMiddleware(_req, res, next) {\n\t\tres.setHeader(\"X-DNS-Prefetch-Control\", headerValue)\n\t\tnext()\n\t}\n}\n\nfunction xDownloadOptions() {\n\treturn function xDownloadOptionsMiddleware(_req, res, next) {\n\t\tres.setHeader(\"X-Download-Options\", \"noopen\")\n\t\tnext()\n\t}\n}\n\nfunction getHeaderValueFromOptions$1({action = \"sameorigin\"}) {\n\tconst normalizedAction = typeof action === \"string\" ? action.toUpperCase() : action\n\tswitch (normalizedAction) {\n\t\tcase \"SAME-ORIGIN\":\n\t\t\treturn \"SAMEORIGIN\"\n\t\tcase \"DENY\":\n\t\tcase \"SAMEORIGIN\":\n\t\t\treturn normalizedAction\n\t\tdefault:\n\t\t\tthrow new Error(`X-Frame-Options received an invalid action ${JSON.stringify(action)}`)\n\t}\n}\nfunction xFrameOptions(options = {}) {\n\tconst headerValue = getHeaderValueFromOptions$1(options)\n\treturn function xFrameOptionsMiddleware(_req, res, next) {\n\t\tres.setHeader(\"X-Frame-Options\", headerValue)\n\t\tnext()\n\t}\n}\n\nconst ALLOWED_PERMITTED_POLICIES = new Set([\"none\", \"master-only\", \"by-content-type\", \"all\"])\nfunction getHeaderValueFromOptions({permittedPolicies = \"none\"}) {\n\tif (ALLOWED_PERMITTED_POLICIES.has(permittedPolicies)) {\n\t\treturn permittedPolicies\n\t} else {\n\t\tthrow new Error(`X-Permitted-Cross-Domain-Policies does not support ${JSON.stringify(permittedPolicies)}`)\n\t}\n}\nfunction xPermittedCrossDomainPolicies(options = {}) {\n\tconst headerValue = getHeaderValueFromOptions(options)\n\treturn function xPermittedCrossDomainPoliciesMiddleware(_req, res, next) {\n\t\tres.setHeader(\"X-Permitted-Cross-Domain-Policies\", headerValue)\n\t\tnext()\n\t}\n}\n\nfunction xPoweredBy() {\n\treturn function xPoweredByMiddleware(_req, res, next) {\n\t\tres.removeHeader(\"X-Powered-By\")\n\t\tnext()\n\t}\n}\n\nfunction xXssProtection() {\n\treturn function xXssProtectionMiddleware(_req, res, next) {\n\t\tres.setHeader(\"X-XSS-Protection\", \"0\")\n\t\tnext()\n\t}\n}\n\nfunction getMiddlewareFunctionsFromOptions(options) {\n\tconst result = []\n\tswitch (options.contentSecurityPolicy) {\n\t\tcase undefined:\n\t\tcase true:\n\t\t\tresult.push(contentSecurityPolicy())\n\t\t\tbreak\n\t\tcase false:\n\t\t\tbreak\n\t\tdefault:\n\t\t\tresult.push(contentSecurityPolicy(options.contentSecurityPolicy))\n\t\t\tbreak\n\t}\n\tswitch (options.crossOriginEmbedderPolicy) {\n\t\tcase undefined:\n\t\tcase false:\n\t\t\tbreak\n\t\tcase true:\n\t\t\tresult.push(crossOriginEmbedderPolicy())\n\t\t\tbreak\n\t\tdefault:\n\t\t\tresult.push(crossOriginEmbedderPolicy(options.crossOriginEmbedderPolicy))\n\t\t\tbreak\n\t}\n\tswitch (options.crossOriginOpenerPolicy) {\n\t\tcase undefined:\n\t\tcase true:\n\t\t\tresult.push(crossOriginOpenerPolicy())\n\t\t\tbreak\n\t\tcase false:\n\t\t\tbreak\n\t\tdefault:\n\t\t\tresult.push(crossOriginOpenerPolicy(options.crossOriginOpenerPolicy))\n\t\t\tbreak\n\t}\n\tswitch (options.crossOriginResourcePolicy) {\n\t\tcase undefined:\n\t\tcase true:\n\t\t\tresult.push(crossOriginResourcePolicy())\n\t\t\tbreak\n\t\tcase false:\n\t\t\tbreak\n\t\tdefault:\n\t\t\tresult.push(crossOriginResourcePolicy(options.crossOriginResourcePolicy))\n\t\t\tbreak\n\t}\n\tswitch (options.originAgentCluster) {\n\t\tcase undefined:\n\t\tcase true:\n\t\t\tresult.push(originAgentCluster())\n\t\t\tbreak\n\t\tcase false:\n\t\t\tbreak\n\t\tdefault:\n\t\t\tconsole.warn(\"Origin-Agent-Cluster does not take options. Remove the property to silence this warning.\")\n\t\t\tresult.push(originAgentCluster())\n\t\t\tbreak\n\t}\n\tswitch (options.referrerPolicy) {\n\t\tcase undefined:\n\t\tcase true:\n\t\t\tresult.push(referrerPolicy())\n\t\t\tbreak\n\t\tcase false:\n\t\t\tbreak\n\t\tdefault:\n\t\t\tresult.push(referrerPolicy(options.referrerPolicy))\n\t\t\tbreak\n\t}\n\tif (\"strictTransportSecurity\" in options && \"hsts\" in options) {\n\t\tthrow new Error(\"Strict-Transport-Security option was specified twice. Remove `hsts` to silence this warning.\")\n\t}\n\tconst strictTransportSecurityOption = options.strictTransportSecurity ?? options.hsts\n\tswitch (strictTransportSecurityOption) {\n\t\tcase undefined:\n\t\tcase true:\n\t\t\tresult.push(strictTransportSecurity())\n\t\t\tbreak\n\t\tcase false:\n\t\t\tbreak\n\t\tdefault:\n\t\t\tresult.push(strictTransportSecurity(strictTransportSecurityOption))\n\t\t\tbreak\n\t}\n\tif (\"xContentTypeOptions\" in options && \"noSniff\" in options) {\n\t\tthrow new Error(\"X-Content-Type-Options option was specified twice. Remove `noSniff` to silence this warning.\")\n\t}\n\tconst xContentTypeOptionsOption = options.xContentTypeOptions ?? options.noSniff\n\tswitch (xContentTypeOptionsOption) {\n\t\tcase undefined:\n\t\tcase true:\n\t\t\tresult.push(xContentTypeOptions())\n\t\t\tbreak\n\t\tcase false:\n\t\t\tbreak\n\t\tdefault:\n\t\t\tconsole.warn(\"X-Content-Type-Options does not take options. Remove the property to silence this warning.\")\n\t\t\tresult.push(xContentTypeOptions())\n\t\t\tbreak\n\t}\n\tif (\"xDnsPrefetchControl\" in options && \"dnsPrefetchControl\" in options) {\n\t\tthrow new Error(\"X-DNS-Prefetch-Control option was specified twice. Remove `dnsPrefetchControl` to silence this warning.\")\n\t}\n\tconst xDnsPrefetchControlOption = options.xDnsPrefetchControl ?? options.dnsPrefetchControl\n\tswitch (xDnsPrefetchControlOption) {\n\t\tcase undefined:\n\t\tcase true:\n\t\t\tresult.push(xDnsPrefetchControl())\n\t\t\tbreak\n\t\tcase false:\n\t\t\tbreak\n\t\tdefault:\n\t\t\tresult.push(xDnsPrefetchControl(xDnsPrefetchControlOption))\n\t\t\tbreak\n\t}\n\tif (\"xDownloadOptions\" in options && \"ieNoOpen\" in options) {\n\t\tthrow new Error(\"X-Download-Options option was specified twice. Remove `ieNoOpen` to silence this warning.\")\n\t}\n\tconst xDownloadOptionsOption = options.xDownloadOptions ?? options.ieNoOpen\n\tswitch (xDownloadOptionsOption) {\n\t\tcase undefined:\n\t\tcase true:\n\t\t\tresult.push(xDownloadOptions())\n\t\t\tbreak\n\t\tcase false:\n\t\t\tbreak\n\t\tdefault:\n\t\t\tconsole.warn(\"X-Download-Options does not take options. Remove the property to silence this warning.\")\n\t\t\tresult.push(xDownloadOptions())\n\t\t\tbreak\n\t}\n\tif (\"xFrameOptions\" in options && \"frameguard\" in options) {\n\t\tthrow new Error(\"X-Frame-Options option was specified twice. Remove `frameguard` to silence this warning.\")\n\t}\n\tconst xFrameOptionsOption = options.xFrameOptions ?? options.frameguard\n\tswitch (xFrameOptionsOption) {\n\t\tcase undefined:\n\t\tcase true:\n\t\t\tresult.push(xFrameOptions())\n\t\t\tbreak\n\t\tcase false:\n\t\t\tbreak\n\t\tdefault:\n\t\t\tresult.push(xFrameOptions(xFrameOptionsOption))\n\t\t\tbreak\n\t}\n\tif (\"xPermittedCrossDomainPolicies\" in options && \"permittedCrossDomainPolicies\" in options) {\n\t\tthrow new Error(\"X-Permitted-Cross-Domain-Policies option was specified twice. Remove `permittedCrossDomainPolicies` to silence this warning.\")\n\t}\n\tconst xPermittedCrossDomainPoliciesOption = options.xPermittedCrossDomainPolicies ?? options.permittedCrossDomainPolicies\n\tswitch (xPermittedCrossDomainPoliciesOption) {\n\t\tcase undefined:\n\t\tcase true:\n\t\t\tresult.push(xPermittedCrossDomainPolicies())\n\t\t\tbreak\n\t\tcase false:\n\t\t\tbreak\n\t\tdefault:\n\t\t\tresult.push(xPermittedCrossDomainPolicies(xPermittedCrossDomainPoliciesOption))\n\t\t\tbreak\n\t}\n\tif (\"xPoweredBy\" in options && \"hidePoweredBy\" in options) {\n\t\tthrow new Error(\"X-Powered-By option was specified twice. Remove `hidePoweredBy` to silence this warning.\")\n\t}\n\tconst xPoweredByOption = options.xPoweredBy ?? options.hidePoweredBy\n\tswitch (xPoweredByOption) {\n\t\tcase undefined:\n\t\tcase true:\n\t\t\tresult.push(xPoweredBy())\n\t\t\tbreak\n\t\tcase false:\n\t\t\tbreak\n\t\tdefault:\n\t\t\tconsole.warn(\"X-Powered-By does not take options. Remove the property to silence this warning.\")\n\t\t\tresult.push(xPoweredBy())\n\t\t\tbreak\n\t}\n\tif (\"xXssProtection\" in options && \"xssFilter\" in options) {\n\t\tthrow new Error(\"X-XSS-Protection option was specified twice. Remove `xssFilter` to silence this warning.\")\n\t}\n\tconst xXssProtectionOption = options.xXssProtection ?? options.xssFilter\n\tswitch (xXssProtectionOption) {\n\t\tcase undefined:\n\t\tcase true:\n\t\t\tresult.push(xXssProtection())\n\t\t\tbreak\n\t\tcase false:\n\t\t\tbreak\n\t\tdefault:\n\t\t\tconsole.warn(\"X-XSS-Protection does not take options. Remove the property to silence this warning.\")\n\t\t\tresult.push(xXssProtection())\n\t\t\tbreak\n\t}\n\treturn result\n}\nconst helmet = Object.assign(\n\tfunction helmet(options = {}) {\n\t\t// People should be able to pass an options object with no prototype,\n\t\t// so we want this optional chaining.\n\t\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n\t\tif (options.constructor?.name === \"IncomingMessage\") {\n\t\t\tthrow new Error(\"It appears you have done something like `app.use(helmet)`, but it should be `app.use(helmet())`.\")\n\t\t}\n\t\tconst middlewareFunctions = getMiddlewareFunctionsFromOptions(options)\n\t\treturn function helmetMiddleware(req, res, next) {\n\t\t\tlet middlewareIndex = 0\n\t\t\t;(function internalNext(err) {\n\t\t\t\tif (err) {\n\t\t\t\t\tnext(err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst middlewareFunction = middlewareFunctions[middlewareIndex]\n\t\t\t\tif (middlewareFunction) {\n\t\t\t\t\tmiddlewareIndex++\n\t\t\t\t\tmiddlewareFunction(req, res, internalNext)\n\t\t\t\t} else {\n\t\t\t\t\tnext()\n\t\t\t\t}\n\t\t\t})()\n\t\t}\n\t},\n\t{\n\t\tcontentSecurityPolicy,\n\t\tcrossOriginEmbedderPolicy,\n\t\tcrossOriginOpenerPolicy,\n\t\tcrossOriginResourcePolicy,\n\t\toriginAgentCluster,\n\t\treferrerPolicy,\n\t\tstrictTransportSecurity,\n\t\txContentTypeOptions,\n\t\txDnsPrefetchControl,\n\t\txDownloadOptions,\n\t\txFrameOptions,\n\t\txPermittedCrossDomainPolicies,\n\t\txPoweredBy,\n\t\txXssProtection,\n\t\t// Legacy aliases\n\t\tdnsPrefetchControl: xDnsPrefetchControl,\n\t\txssFilter: xXssProtection,\n\t\tpermittedCrossDomainPolicies: xPermittedCrossDomainPolicies,\n\t\tieNoOpen: xDownloadOptions,\n\t\tnoSniff: xContentTypeOptions,\n\t\tframeguard: xFrameOptions,\n\t\thidePoweredBy: xPoweredBy,\n\t\thsts: strictTransportSecurity\n\t}\n)\n\nexport {contentSecurityPolicy, crossOriginEmbedderPolicy, crossOriginOpenerPolicy, crossOriginResourcePolicy, helmet as default, xDnsPrefetchControl as dnsPrefetchControl, xFrameOptions as frameguard, xPoweredBy as hidePoweredBy, strictTransportSecurity as hsts, xDownloadOptions as ieNoOpen, xContentTypeOptions as noSniff, originAgentCluster, xPermittedCrossDomainPolicies as permittedCrossDomainPolicies, referrerPolicy, strictTransportSecurity, xContentTypeOptions, xDnsPrefetchControl, xDownloadOptions, xFrameOptions, xPermittedCrossDomainPolicies, xPoweredBy, xXssProtection, xXssProtection as xssFilter}\n", "// source/ip-key-generator.ts\nimport { isIPv6 } from \"node:net\";\nimport { Address6 } from \"ip-address\";\nfunction ipKeyGenerator(ip, ipv6Subnet = 56) {\n if (ipv6Subnet && isIPv6(ip)) {\n return `${new Address6(`${ip}/${ipv6Subnet}`).startAddress().correctForm()}/${ipv6Subnet}`;\n }\n return ip;\n}\n\n// source/memory-store.ts\nvar MemoryStore = class {\n constructor(validations2) {\n this.validations = validations2;\n /**\n * These two maps store usage (requests) and reset time by key (for example, IP\n * addresses or API keys).\n *\n * They are split into two to avoid having to iterate through the entire set to\n * determine which ones need reset. Instead, `Client`s are moved from `previous`\n * to `current` as they hit the endpoint. Once `windowMs` has elapsed, all clients\n * left in `previous`, i.e., those that have not made any recent requests, are\n * known to be expired and can be deleted in bulk.\n */\n this.previous = /* @__PURE__ */ new Map();\n this.current = /* @__PURE__ */ new Map();\n /**\n * Confirmation that the keys incremented in once instance of MemoryStore\n * cannot affect other instances.\n */\n this.localKeys = true;\n }\n /**\n * Method that initializes the store.\n *\n * @param options {Options} - The options used to setup the middleware.\n */\n init(options) {\n this.windowMs = options.windowMs;\n this.validations?.windowMs(this.windowMs);\n if (this.interval) clearInterval(this.interval);\n this.interval = setInterval(() => {\n this.clearExpired();\n }, this.windowMs);\n this.interval.unref?.();\n }\n /**\n * Method to fetch a client's hit count and reset time.\n *\n * @param key {string} - The identifier for a client.\n *\n * @returns {ClientRateLimitInfo | undefined} - The number of hits and reset time for that client.\n *\n * @public\n */\n async get(key) {\n return this.current.get(key) ?? this.previous.get(key);\n }\n /**\n * Method to increment a client's hit counter.\n *\n * @param key {string} - The identifier for a client.\n *\n * @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.\n *\n * @public\n */\n async increment(key) {\n const client = this.getClient(key);\n const now = Date.now();\n if (client.resetTime.getTime() <= now) {\n this.resetClient(client, now);\n }\n client.totalHits++;\n return client;\n }\n /**\n * Method to decrement a client's hit counter.\n *\n * @param key {string} - The identifier for a client.\n *\n * @public\n */\n async decrement(key) {\n const client = this.getClient(key);\n if (client.totalHits > 0) client.totalHits--;\n }\n /**\n * Method to reset a client's hit counter.\n *\n * @param key {string} - The identifier for a client.\n *\n * @public\n */\n async resetKey(key) {\n this.current.delete(key);\n this.previous.delete(key);\n }\n /**\n * Method to reset everyone's hit counter.\n *\n * @public\n */\n async resetAll() {\n this.current.clear();\n this.previous.clear();\n }\n /**\n * Method to stop the timer (if currently running) and prevent any memory\n * leaks.\n *\n * @public\n */\n shutdown() {\n clearInterval(this.interval);\n void this.resetAll();\n }\n /**\n * Recycles a client by setting its hit count to zero, and reset time to\n * `windowMs` milliseconds from now.\n *\n * NOT to be confused with `#resetKey()`, which removes a client from both the\n * `current` and `previous` maps.\n *\n * @param client {Client} - The client to recycle.\n * @param now {number} - The current time, to which the `windowMs` is added to get the `resetTime` for the client.\n *\n * @return {Client} - The modified client that was passed in, to allow for chaining.\n */\n resetClient(client, now = Date.now()) {\n client.totalHits = 0;\n client.resetTime.setTime(now + this.windowMs);\n return client;\n }\n /**\n * Retrieves or creates a client, given a key. Also ensures that the client being\n * returned is in the `current` map.\n *\n * @param key {string} - The key under which the client is (or is to be) stored.\n *\n * @returns {Client} - The requested client.\n */\n getClient(key) {\n if (this.current.has(key)) return this.current.get(key);\n let client;\n if (this.previous.has(key)) {\n client = this.previous.get(key);\n this.previous.delete(key);\n } else {\n client = { totalHits: 0, resetTime: /* @__PURE__ */ new Date() };\n this.resetClient(client);\n }\n this.current.set(key, client);\n return client;\n }\n /**\n * Move current clients to previous, create a new map for current.\n *\n * This function is called every `windowMs`.\n */\n clearExpired() {\n this.previous = this.current;\n this.current = /* @__PURE__ */ new Map();\n }\n};\n\n// source/rate-limit.ts\nimport { isIPv6 as isIPv62 } from \"node:net\";\n\n// source/headers.ts\nimport { Buffer } from \"node:buffer\";\nimport { createHash } from \"node:crypto\";\nvar SUPPORTED_DRAFT_VERSIONS = [\n \"draft-6\",\n \"draft-7\",\n \"draft-8\"\n];\nvar getResetSeconds = (windowMs, resetTime) => {\n let resetSeconds;\n if (resetTime) {\n const deltaSeconds = Math.ceil((resetTime.getTime() - Date.now()) / 1e3);\n resetSeconds = Math.max(0, deltaSeconds);\n } else {\n resetSeconds = Math.ceil(windowMs / 1e3);\n }\n return resetSeconds;\n};\nvar getPartitionKey = (key) => {\n const hash = createHash(\"sha256\");\n hash.update(key);\n const partitionKey = hash.digest(\"hex\").slice(0, 12);\n return Buffer.from(partitionKey).toString(\"base64\");\n};\nvar setLegacyHeaders = (response, info) => {\n if (response.headersSent) return;\n response.setHeader(\"X-RateLimit-Limit\", info.limit.toString());\n response.setHeader(\"X-RateLimit-Remaining\", info.remaining.toString());\n if (info.resetTime instanceof Date) {\n response.setHeader(\"Date\", (/* @__PURE__ */ new Date()).toUTCString());\n response.setHeader(\n \"X-RateLimit-Reset\",\n Math.ceil(info.resetTime.getTime() / 1e3).toString()\n );\n }\n};\nvar setDraft6Headers = (response, info, windowMs) => {\n if (response.headersSent) return;\n const windowSeconds = Math.ceil(windowMs / 1e3);\n const resetSeconds = getResetSeconds(windowMs, info.resetTime);\n response.setHeader(\"RateLimit-Policy\", `${info.limit};w=${windowSeconds}`);\n response.setHeader(\"RateLimit-Limit\", info.limit.toString());\n response.setHeader(\"RateLimit-Remaining\", info.remaining.toString());\n if (typeof resetSeconds === \"number\")\n response.setHeader(\"RateLimit-Reset\", resetSeconds.toString());\n};\nvar setDraft7Headers = (response, info, windowMs) => {\n if (response.headersSent) return;\n const windowSeconds = Math.ceil(windowMs / 1e3);\n const resetSeconds = getResetSeconds(windowMs, info.resetTime);\n response.setHeader(\"RateLimit-Policy\", `${info.limit};w=${windowSeconds}`);\n response.setHeader(\n \"RateLimit\",\n `limit=${info.limit}, remaining=${info.remaining}, reset=${resetSeconds}`\n );\n};\nvar setDraft8Headers = (response, info, windowMs, name, key) => {\n if (response.headersSent) return;\n const windowSeconds = Math.ceil(windowMs / 1e3);\n const resetSeconds = getResetSeconds(windowMs, info.resetTime);\n const partitionKey = getPartitionKey(key);\n const header = `r=${info.remaining}; t=${resetSeconds}`;\n const policy = `q=${info.limit}; w=${windowSeconds}; pk=:${partitionKey}:`;\n response.append(\"RateLimit\", `\"${name}\"; ${header}`);\n response.append(\"RateLimit-Policy\", `\"${name}\"; ${policy}`);\n};\nvar setRetryAfterHeader = (response, info, windowMs) => {\n if (response.headersSent) return;\n const resetSeconds = getResetSeconds(windowMs, info.resetTime);\n response.setHeader(\"Retry-After\", resetSeconds.toString());\n};\n\n// source/utils.ts\nvar omitUndefinedProperties = (passedOptions) => {\n const omittedOptions = {};\n for (const k of Object.keys(passedOptions)) {\n const key = k;\n if (passedOptions[key] !== void 0) {\n omittedOptions[key] = passedOptions[key];\n }\n }\n return omittedOptions;\n};\n\n// source/validations.ts\nimport { isIP } from \"node:net\";\nvar ValidationError = class extends Error {\n /**\n * The code must be a string, in snake case and all capital, that starts with\n * the substring `ERR_ERL_`.\n *\n * The message must be a string, starting with an uppercase character,\n * describing the issue in detail.\n */\n constructor(code, message) {\n const url = `https://express-rate-limit.github.io/${code}/`;\n super(`${message} See ${url} for more information.`);\n this.name = this.constructor.name;\n this.code = code;\n this.help = url;\n }\n};\nvar ChangeWarning = class extends ValidationError {\n};\nvar usedStores = /* @__PURE__ */ new Set();\nvar singleCountKeys = /* @__PURE__ */ new WeakMap();\nvar validations = {\n enabled: {\n default: true\n },\n // Should be EnabledValidations type, but that's a circular reference\n disable() {\n for (const k of Object.keys(this.enabled)) this.enabled[k] = false;\n },\n /**\n * Checks whether the IP address is valid, and that it does not have a port\n * number in it.\n *\n * See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_invalid_ip_address.\n *\n * @param ip {string | undefined} - The IP address provided by Express as request.ip.\n *\n * @returns {void}\n */\n ip(ip) {\n if (ip === void 0) {\n throw new ValidationError(\n \"ERR_ERL_UNDEFINED_IP_ADDRESS\",\n `An undefined 'request.ip' was detected. This might indicate a misconfiguration or the connection being destroyed prematurely.`\n );\n }\n if (!isIP(ip)) {\n throw new ValidationError(\n \"ERR_ERL_INVALID_IP_ADDRESS\",\n `An invalid 'request.ip' (${ip}) was detected. Consider passing a custom 'keyGenerator' function to the rate limiter.`\n );\n }\n },\n /**\n * Makes sure the trust proxy setting is not set to `true`.\n *\n * See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_permissive_trust_proxy.\n *\n * @param request {Request} - The Express request object.\n *\n * @returns {void}\n */\n trustProxy(request) {\n if (request.app.get(\"trust proxy\") === true) {\n throw new ValidationError(\n \"ERR_ERL_PERMISSIVE_TRUST_PROXY\",\n `The Express 'trust proxy' setting is true, which allows anyone to trivially bypass IP-based rate limiting.`\n );\n }\n },\n /**\n * Makes sure the trust proxy setting is set in case the `X-Forwarded-For`\n * header is present.\n *\n * See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_unset_trust_proxy.\n *\n * @param request {Request} - The Express request object.\n *\n * @returns {void}\n */\n xForwardedForHeader(request) {\n if (request.headers[\"x-forwarded-for\"] && request.app.get(\"trust proxy\") === false) {\n throw new ValidationError(\n \"ERR_ERL_UNEXPECTED_X_FORWARDED_FOR\",\n `The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false (default). This could indicate a misconfiguration which would prevent express-rate-limit from accurately identifying users.`\n );\n }\n },\n /**\n * Alert the user if the Forwarded header is set (standardized version of X-Forwarded-For - not supported by express as of version 5.1.0)\n *\n * @param request {Request} - The Express request object.\n *\n * @returns {void}\n */\n forwardedHeader(request) {\n if (request.headers.forwarded && request.ip === request.socket?.remoteAddress) {\n throw new ValidationError(\n \"ERR_ERL_FORWARDED_HEADER\",\n `The 'Forwarded' header (standardized X-Forwarded-For) is set but currently being ignored. Add a custom keyGenerator to use a value from this header.`\n );\n }\n },\n /**\n * Ensures totalHits value from store is a positive integer.\n *\n * @param hits {any} - The `totalHits` returned by the store.\n */\n positiveHits(hits) {\n if (typeof hits !== \"number\" || hits < 1 || hits !== Math.round(hits)) {\n throw new ValidationError(\n \"ERR_ERL_INVALID_HITS\",\n `The totalHits value returned from the store must be a positive integer, got ${hits}`\n );\n }\n },\n /**\n * Ensures a single store instance is not used with multiple express-rate-limit instances\n */\n unsharedStore(store) {\n if (usedStores.has(store)) {\n const maybeUniquePrefix = store?.localKeys ? \"\" : \" (with a unique prefix)\";\n throw new ValidationError(\n \"ERR_ERL_STORE_REUSE\",\n `A Store instance must not be shared across multiple rate limiters. Create a new instance of ${store.constructor.name}${maybeUniquePrefix} for each limiter instead.`\n );\n }\n usedStores.add(store);\n },\n /**\n * Ensures a given key is incremented only once per request.\n *\n * @param request {Request} - The Express request object.\n * @param store {Store} - The store class.\n * @param key {string} - The key used to store the client's hit count.\n *\n * @returns {void}\n */\n singleCount(request, store, key) {\n let storeKeys = singleCountKeys.get(request);\n if (!storeKeys) {\n storeKeys = /* @__PURE__ */ new Map();\n singleCountKeys.set(request, storeKeys);\n }\n const storeKey = store.localKeys ? store : store.constructor.name;\n let keys = storeKeys.get(storeKey);\n if (!keys) {\n keys = [];\n storeKeys.set(storeKey, keys);\n }\n const prefixedKey = `${store.prefix ?? \"\"}${key}`;\n if (keys.includes(prefixedKey)) {\n throw new ValidationError(\n \"ERR_ERL_DOUBLE_COUNT\",\n `The hit count for ${key} was incremented more than once for a single request.`\n );\n }\n keys.push(prefixedKey);\n },\n /**\n * Warns the user that the behaviour for `max: 0` / `limit: 0` is\n * changing in the next major release.\n *\n * @param limit {number} - The maximum number of hits per client.\n *\n * @returns {void}\n */\n limit(limit) {\n if (limit === 0) {\n throw new ChangeWarning(\n \"WRN_ERL_MAX_ZERO\",\n \"Setting limit or max to 0 disables rate limiting in express-rate-limit v6 and older, but will cause all requests to be blocked in v7\"\n );\n }\n },\n /**\n * Warns the user that the `draft_polli_ratelimit_headers` option is deprecated\n * and will be removed in the next major release.\n *\n * @param draft_polli_ratelimit_headers {any | undefined} - The now-deprecated setting that was used to enable standard headers.\n *\n * @returns {void}\n */\n draftPolliHeaders(draft_polli_ratelimit_headers) {\n if (draft_polli_ratelimit_headers) {\n throw new ChangeWarning(\n \"WRN_ERL_DEPRECATED_DRAFT_POLLI_HEADERS\",\n `The draft_polli_ratelimit_headers configuration option is deprecated and has been removed in express-rate-limit v7, please set standardHeaders: 'draft-6' instead.`\n );\n }\n },\n /**\n * Warns the user that the `onLimitReached` option is deprecated and\n * will be removed in the next major release.\n *\n * @param onLimitReached {any | undefined} - The maximum number of hits per client.\n *\n * @returns {void}\n */\n onLimitReached(onLimitReached) {\n if (onLimitReached) {\n throw new ChangeWarning(\n \"WRN_ERL_DEPRECATED_ON_LIMIT_REACHED\",\n \"The onLimitReached configuration option is deprecated and has been removed in express-rate-limit v7.\"\n );\n }\n },\n /**\n * Warns the user when an invalid/unsupported version of the draft spec is passed.\n *\n * @param version {any | undefined} - The version passed by the user.\n *\n * @returns {void}\n */\n headersDraftVersion(version) {\n if (typeof version !== \"string\" || // @ts-expect-error This is fine. If version is not in the array, it will just return false.\n !SUPPORTED_DRAFT_VERSIONS.includes(version)) {\n const versionString = SUPPORTED_DRAFT_VERSIONS.join(\", \");\n throw new ValidationError(\n \"ERR_ERL_HEADERS_UNSUPPORTED_DRAFT_VERSION\",\n `standardHeaders: only the following versions of the IETF draft specification are supported: ${versionString}.`\n );\n }\n },\n /**\n * Warns the user when the selected headers option requires a reset time but\n * the store does not provide one.\n *\n * @param resetTime {Date | undefined} - The timestamp when the client's hit count will be reset.\n *\n * @returns {void}\n */\n headersResetTime(resetTime) {\n if (!resetTime) {\n throw new ValidationError(\n \"ERR_ERL_HEADERS_NO_RESET\",\n `standardHeaders: 'draft-7' requires a 'resetTime', but the store did not provide one. The 'windowMs' value will be used instead, which may cause clients to wait longer than necessary.`\n );\n }\n },\n knownOptions(passedOptions) {\n if (!passedOptions) return;\n const optionsMap = {\n windowMs: true,\n limit: true,\n message: true,\n statusCode: true,\n legacyHeaders: true,\n standardHeaders: true,\n identifier: true,\n requestPropertyName: true,\n skipFailedRequests: true,\n skipSuccessfulRequests: true,\n keyGenerator: true,\n ipv6Subnet: true,\n handler: true,\n skip: true,\n requestWasSuccessful: true,\n store: true,\n validate: true,\n headers: true,\n max: true,\n passOnStoreError: true\n };\n const validOptions = Object.keys(optionsMap).concat(\n \"draft_polli_ratelimit_headers\",\n // not a valid option anymore, but we have a more specific check for this one, so don't warn for it here\n // from express-slow-down - https://github.com/express-rate-limit/express-slow-down/blob/main/source/types.ts#L65\n \"delayAfter\",\n \"delayMs\",\n \"maxDelayMs\"\n );\n for (const key of Object.keys(passedOptions)) {\n if (!validOptions.includes(key)) {\n throw new ValidationError(\n \"ERR_ERL_UNKNOWN_OPTION\",\n `Unexpected configuration option: ${key}`\n // todo: suggest a valid option with a short levenstein distance?\n );\n }\n }\n },\n /**\n * Checks the options.validate setting to ensure that only recognized\n * validations are enabled or disabled.\n *\n * If any unrecognized values are found, an error is logged that\n * includes the list of supported validations.\n */\n validationsConfig() {\n const supportedValidations = Object.keys(this).filter(\n (k) => ![\"enabled\", \"disable\"].includes(k)\n );\n supportedValidations.push(\"default\");\n for (const key of Object.keys(this.enabled)) {\n if (!supportedValidations.includes(key)) {\n throw new ValidationError(\n \"ERR_ERL_UNKNOWN_VALIDATION\",\n `options.validate.${key} is not recognized. Supported validate options are: ${supportedValidations.join(\n \", \"\n )}.`\n );\n }\n }\n },\n /**\n * Checks to see if the instance was created inside of a request handler,\n * which would prevent it from working correctly, with the default memory\n * store (or any other store with localKeys.)\n */\n creationStack(store) {\n const { stack } = new Error(\n \"express-rate-limit validation check (set options.validate.creationStack=false to disable)\"\n );\n if (stack?.includes(\"Layer.handle [as handle_request]\") || // express v4\n stack?.includes(\"Layer.handleRequest\")) {\n if (!store.localKeys) {\n throw new ValidationError(\n \"ERR_ERL_CREATED_IN_REQUEST_HANDLER\",\n \"express-rate-limit instance should *usually* be created at app initialization, not when responding to a request.\"\n );\n }\n throw new ValidationError(\n \"ERR_ERL_CREATED_IN_REQUEST_HANDLER\",\n \"express-rate-limit instance should be created at app initialization, not when responding to a request.\"\n );\n }\n },\n ipv6Subnet(ipv6Subnet) {\n if (ipv6Subnet === false) {\n return;\n }\n if (!Number.isInteger(ipv6Subnet) || ipv6Subnet < 32 || ipv6Subnet > 64) {\n throw new ValidationError(\n \"ERR_ERL_IPV6_SUBNET\",\n `Unexpected ipv6Subnet value: ${ipv6Subnet}. Expected an integer between 32 and 64 (usually 48-64).`\n );\n }\n },\n ipv6SubnetOrKeyGenerator(options) {\n if (options.ipv6Subnet !== void 0 && options.keyGenerator) {\n throw new ValidationError(\n \"ERR_ERL_IPV6SUBNET_OR_KEYGENERATOR\",\n `Incompatible options: the 'ipv6Subnet' option is ignored when a custom 'keyGenerator' function is also set.`\n );\n }\n },\n keyGeneratorIpFallback(keyGenerator) {\n if (!keyGenerator) {\n return;\n }\n const src = keyGenerator.toString();\n if ((src.includes(\"req.ip\") || src.includes(\"request.ip\")) && !src.includes(\"ipKeyGenerator\")) {\n throw new ValidationError(\n \"ERR_ERL_KEY_GEN_IPV6\",\n \"Custom keyGenerator appears to use request IP without calling the ipKeyGenerator helper function for IPv6 addresses. This could allow IPv6 users to bypass limits.\"\n );\n }\n },\n /**\n * Checks to see if the window duration is greater than 2^32 - 1. This is only\n * called by the default MemoryStore, since it uses Node's setInterval method.\n *\n * See https://nodejs.org/api/timers.html#setintervalcallback-delay-args.\n */\n windowMs(windowMs) {\n const SET_TIMEOUT_MAX = 2 ** 31 - 1;\n if (typeof windowMs !== \"number\" || Number.isNaN(windowMs) || windowMs < 1 || windowMs > SET_TIMEOUT_MAX) {\n throw new ValidationError(\n \"ERR_ERL_WINDOW_MS\",\n `Invalid windowMs value: ${windowMs}${typeof windowMs !== \"number\" ? ` (${typeof windowMs})` : \"\"}, must be a number between 1 and ${SET_TIMEOUT_MAX} when using the default MemoryStore`\n );\n }\n }\n};\nvar getValidations = (_enabled) => {\n let enabled;\n if (typeof _enabled === \"boolean\") {\n enabled = {\n default: _enabled\n };\n } else {\n enabled = {\n default: true,\n ..._enabled\n };\n }\n const wrappedValidations = { enabled };\n for (const [name, validation] of Object.entries(validations)) {\n if (typeof validation === \"function\")\n wrappedValidations[name] = (...args) => {\n if (!(enabled[name] ?? enabled.default)) {\n return;\n }\n try {\n ;\n validation.apply(\n wrappedValidations,\n args\n );\n } catch (error) {\n if (error instanceof ChangeWarning) console.warn(error);\n else console.error(error);\n }\n };\n }\n return wrappedValidations;\n};\n\n// source/rate-limit.ts\nvar isLegacyStore = (store) => (\n // Check that `incr` exists but `increment` does not - store authors might want\n // to keep both around for backwards compatibility.\n typeof store.incr === \"function\" && typeof store.increment !== \"function\"\n);\nvar promisifyStore = (passedStore) => {\n if (!isLegacyStore(passedStore)) {\n return passedStore;\n }\n const legacyStore = passedStore;\n class PromisifiedStore {\n async increment(key) {\n return new Promise((resolve, reject) => {\n legacyStore.incr(\n key,\n (error, totalHits, resetTime) => {\n if (error) reject(error);\n resolve({ totalHits, resetTime });\n }\n );\n });\n }\n async decrement(key) {\n return legacyStore.decrement(key);\n }\n async resetKey(key) {\n return legacyStore.resetKey(key);\n }\n /* istanbul ignore next */\n async resetAll() {\n if (typeof legacyStore.resetAll === \"function\")\n return legacyStore.resetAll();\n }\n }\n return new PromisifiedStore();\n};\nvar getOptionsFromConfig = (config) => {\n const { validations: validations2, ...directlyPassableEntries } = config;\n return {\n ...directlyPassableEntries,\n validate: validations2.enabled\n };\n};\nvar parseOptions = (passedOptions) => {\n const notUndefinedOptions = omitUndefinedProperties(passedOptions);\n const validations2 = getValidations(notUndefinedOptions?.validate ?? true);\n validations2.validationsConfig();\n validations2.knownOptions(passedOptions);\n validations2.draftPolliHeaders(\n // @ts-expect-error see the note above.\n notUndefinedOptions.draft_polli_ratelimit_headers\n );\n validations2.onLimitReached(notUndefinedOptions.onLimitReached);\n if (notUndefinedOptions.ipv6Subnet !== void 0 && typeof notUndefinedOptions.ipv6Subnet !== \"function\") {\n validations2.ipv6Subnet(notUndefinedOptions.ipv6Subnet);\n }\n validations2.keyGeneratorIpFallback(notUndefinedOptions.keyGenerator);\n validations2.ipv6SubnetOrKeyGenerator(notUndefinedOptions);\n let standardHeaders = notUndefinedOptions.standardHeaders ?? false;\n if (standardHeaders === true) standardHeaders = \"draft-6\";\n const config = {\n windowMs: 60 * 1e3,\n limit: passedOptions.max ?? 5,\n // `max` is deprecated, but support it anyways.\n message: \"Too many requests, please try again later.\",\n statusCode: 429,\n legacyHeaders: passedOptions.headers ?? true,\n identifier(request, _response) {\n let duration = \"\";\n const property = config.requestPropertyName;\n const { limit } = request[property];\n const seconds = config.windowMs / 1e3;\n const minutes = config.windowMs / (1e3 * 60);\n const hours = config.windowMs / (1e3 * 60 * 60);\n const days = config.windowMs / (1e3 * 60 * 60 * 24);\n if (seconds < 60) duration = `${seconds}sec`;\n else if (minutes < 60) duration = `${minutes}min`;\n else if (hours < 24) duration = `${hours}hr${hours > 1 ? \"s\" : \"\"}`;\n else duration = `${days}day${days > 1 ? \"s\" : \"\"}`;\n return `${limit}-in-${duration}`;\n },\n requestPropertyName: \"rateLimit\",\n skipFailedRequests: false,\n skipSuccessfulRequests: false,\n requestWasSuccessful: (_request, response) => response.statusCode < 400,\n skip: (_request, _response) => false,\n async keyGenerator(request, response) {\n validations2.ip(request.ip);\n validations2.trustProxy(request);\n validations2.xForwardedForHeader(request);\n validations2.forwardedHeader(request);\n const ip = request.ip;\n let subnet = 56;\n if (isIPv62(ip)) {\n subnet = typeof config.ipv6Subnet === \"function\" ? await config.ipv6Subnet(request, response) : config.ipv6Subnet;\n if (typeof config.ipv6Subnet === \"function\")\n validations2.ipv6Subnet(subnet);\n }\n return ipKeyGenerator(ip, subnet);\n },\n ipv6Subnet: 56,\n async handler(request, response, _next, _optionsUsed) {\n response.status(config.statusCode);\n const message = typeof config.message === \"function\" ? await config.message(\n request,\n response\n ) : config.message;\n if (!response.writableEnded) response.send(message);\n },\n passOnStoreError: false,\n // Allow the default options to be overridden by the passed options.\n ...notUndefinedOptions,\n // `standardHeaders` is resolved into a draft version above, use that.\n standardHeaders,\n // Note that this field is declared after the user's options are spread in,\n // so that this field doesn't get overridden with an un-promisified store!\n store: promisifyStore(\n notUndefinedOptions.store ?? new MemoryStore(validations2)\n ),\n // Print an error to the console if a few known misconfigurations are detected.\n validations: validations2\n };\n if (typeof config.store.increment !== \"function\" || typeof config.store.decrement !== \"function\" || typeof config.store.resetKey !== \"function\" || config.store.resetAll !== void 0 && typeof config.store.resetAll !== \"function\" || config.store.init !== void 0 && typeof config.store.init !== \"function\") {\n throw new TypeError(\n \"An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface.\"\n );\n }\n return config;\n};\nvar handleAsyncErrors = (fn) => async (request, response, next) => {\n try {\n await Promise.resolve(fn(request, response, next)).catch(next);\n } catch (error) {\n next(error);\n }\n};\nvar rateLimit = (passedOptions) => {\n const config = parseOptions(passedOptions ?? {});\n const options = getOptionsFromConfig(config);\n config.validations.creationStack(config.store);\n config.validations.unsharedStore(config.store);\n if (typeof config.store.init === \"function\") config.store.init(options);\n const middleware = handleAsyncErrors(\n async (request, response, next) => {\n const skip = await config.skip(request, response);\n if (skip) {\n next();\n return;\n }\n const augmentedRequest = request;\n const key = await config.keyGenerator(request, response);\n let totalHits = 0;\n let resetTime;\n try {\n const incrementResult = await config.store.increment(key);\n totalHits = incrementResult.totalHits;\n resetTime = incrementResult.resetTime;\n } catch (error) {\n if (config.passOnStoreError) {\n console.error(\n \"express-rate-limit: error from store, allowing request without rate-limiting.\",\n error\n );\n next();\n return;\n }\n throw error;\n }\n config.validations.positiveHits(totalHits);\n config.validations.singleCount(request, config.store, key);\n const retrieveLimit = typeof config.limit === \"function\" ? config.limit(request, response) : config.limit;\n const limit = await retrieveLimit;\n config.validations.limit(limit);\n const info = {\n limit,\n used: totalHits,\n remaining: Math.max(limit - totalHits, 0),\n resetTime,\n key\n };\n Object.defineProperty(info, \"current\", {\n configurable: false,\n enumerable: false,\n value: totalHits\n });\n augmentedRequest[config.requestPropertyName] = info;\n if (config.legacyHeaders && !response.headersSent) {\n setLegacyHeaders(response, info);\n }\n if (config.standardHeaders && !response.headersSent) {\n switch (config.standardHeaders) {\n case \"draft-6\": {\n setDraft6Headers(response, info, config.windowMs);\n break;\n }\n case \"draft-7\": {\n config.validations.headersResetTime(info.resetTime);\n setDraft7Headers(response, info, config.windowMs);\n break;\n }\n case \"draft-8\": {\n const retrieveName = typeof config.identifier === \"function\" ? config.identifier(request, response) : config.identifier;\n const name = await retrieveName;\n config.validations.headersResetTime(info.resetTime);\n setDraft8Headers(response, info, config.windowMs, name, key);\n break;\n }\n default: {\n config.validations.headersDraftVersion(config.standardHeaders);\n break;\n }\n }\n }\n if (config.skipFailedRequests || config.skipSuccessfulRequests) {\n let decremented = false;\n const decrementKey = async () => {\n if (!decremented) {\n await config.store.decrement(key);\n decremented = true;\n }\n };\n if (config.skipFailedRequests) {\n response.on(\"finish\", async () => {\n if (!await config.requestWasSuccessful(request, response))\n await decrementKey();\n });\n response.on(\"close\", async () => {\n if (!response.writableEnded) await decrementKey();\n });\n response.on(\"error\", async () => {\n await decrementKey();\n });\n }\n if (config.skipSuccessfulRequests) {\n response.on(\"finish\", async () => {\n if (await config.requestWasSuccessful(request, response))\n await decrementKey();\n });\n }\n }\n config.validations.disable();\n if (totalHits > limit) {\n if (config.legacyHeaders || config.standardHeaders) {\n setRetryAfterHeader(response, info, config.windowMs);\n }\n config.handler(request, response, next, options);\n return;\n }\n next();\n }\n );\n const getThrowFn = () => {\n throw new Error(\"The current store does not support the get/getKey method\");\n };\n middleware.resetKey = config.store.resetKey.bind(config.store);\n middleware.getKey = typeof config.store.get === \"function\" ? config.store.get.bind(config.store) : getThrowFn;\n return middleware;\n};\nvar rate_limit_default = rateLimit;\nexport {\n MemoryStore,\n rate_limit_default as default,\n ipKeyGenerator,\n rate_limit_default as rateLimit\n};\n", "/**\n * Shim bun:sqlite \u2192 better-sqlite3\n *\n * Provides a bun:sqlite-compatible API using better-sqlite3\n * to allow execution on plain Node.js.\n */\n\nimport BetterSqlite3 from 'better-sqlite3';\n\n/**\n * bun:sqlite-compatible Database class\n */\nexport class Database {\n private _db: BetterSqlite3.Database;\n private _stmtCache: Map<string, BunQueryCompat> = new Map();\n\n constructor(path: string, options?: { create?: boolean; readwrite?: boolean }) {\n this._db = new BetterSqlite3(path, {\n // better-sqlite3 creates the file by default ('create' not needed)\n readonly: options?.readwrite === false ? true : false\n });\n }\n\n /**\n * Execute a SQL query without results\n */\n run(sql: string, params?: any[]): { lastInsertRowid: number | bigint; changes: number } {\n const stmt = this._db.prepare(sql);\n const result = params ? stmt.run(...params) : stmt.run();\n return result;\n }\n\n /**\n * Prepare a query with bun:sqlite-compatible interface.\n * Returns a cached prepared statement for repeated queries.\n */\n query(sql: string): BunQueryCompat {\n let cached = this._stmtCache.get(sql);\n if (!cached) {\n cached = new BunQueryCompat(this._db, sql);\n this._stmtCache.set(sql, cached);\n }\n return cached;\n }\n\n /**\n * Create a transaction\n */\n transaction<T>(fn: (...args: any[]) => T): (...args: any[]) => T {\n return this._db.transaction(fn) as any;\n }\n\n /**\n * Close the connection\n */\n close(): void {\n this._stmtCache.clear();\n this._db.close();\n }\n}\n\n/**\n * Query wrapper compatible with the bun:sqlite Statement API.\n * Prepares the statement once at construction time (cached).\n */\nclass BunQueryCompat {\n private _stmt: BetterSqlite3.Statement;\n\n constructor(db: BetterSqlite3.Database, sql: string) {\n this._stmt = db.prepare(sql);\n }\n\n /**\n * Returns all rows\n */\n all(...params: any[]): any[] {\n return params.length > 0 ? this._stmt.all(...params) : this._stmt.all();\n }\n\n /**\n * Returns the first row or null\n */\n get(...params: any[]): any {\n return params.length > 0 ? this._stmt.get(...params) : this._stmt.get();\n }\n\n /**\n * Execute without results\n */\n run(...params: any[]): { lastInsertRowid: number | bigint; changes: number } {\n return params.length > 0 ? this._stmt.run(...params) : this._stmt.run();\n }\n}\n\nexport default { Database };\n", "import { join, dirname, basename } from 'path';\nimport { homedir } from 'os';\nimport { existsSync, mkdirSync } from 'fs';\nimport { execSync } from 'child_process';\nimport { fileURLToPath } from 'url';\nimport { logger } from '../utils/logger.js';\n\n// Get __dirname that works in both ESM and CJS contexts\nfunction getDirname(): string {\n if (typeof __dirname !== 'undefined') {\n return __dirname;\n }\n return dirname(fileURLToPath(import.meta.url));\n}\n\nconst _dirname = getDirname();\n\n/**\n * Simple path configuration for Kiro Memory\n */\n\n// Base directory - Kiro Memory data in home directory\n// Backward compat: if ~/.contextkit (old name) exists, use it; otherwise ~/.kiro-memory\nconst _legacyDir = join(homedir(), '.contextkit');\nconst _defaultDir = existsSync(_legacyDir) ? _legacyDir : join(homedir(), '.kiro-memory');\nexport const DATA_DIR = process.env.KIRO_MEMORY_DATA_DIR || process.env.CONTEXTKIT_DATA_DIR || _defaultDir;\n\n// Kiro config directory\nexport const KIRO_CONFIG_DIR = process.env.KIRO_CONFIG_DIR || join(homedir(), '.kiro');\n\n// Plugin installation directory\nexport const PLUGIN_ROOT = join(KIRO_CONFIG_DIR, 'plugins', 'kiro-memory');\n\n// Data subdirectories\nexport const ARCHIVES_DIR = join(DATA_DIR, 'archives');\nexport const LOGS_DIR = join(DATA_DIR, 'logs');\nexport const TRASH_DIR = join(DATA_DIR, 'trash');\nexport const BACKUPS_DIR = join(DATA_DIR, 'backups');\nexport const MODES_DIR = join(DATA_DIR, 'modes');\nexport const USER_SETTINGS_PATH = join(DATA_DIR, 'settings.json');\n// Backward compat: if the DB with the old name exists, use it\nconst _legacyDb = join(DATA_DIR, 'contextkit.db');\nexport const DB_PATH = existsSync(_legacyDb) ? _legacyDb : join(DATA_DIR, 'kiro-memory.db');\nexport const VECTOR_DB_DIR = join(DATA_DIR, 'vector-db');\n\n// Observer sessions directory\nexport const OBSERVER_SESSIONS_DIR = join(DATA_DIR, 'observer-sessions');\n\n// Kiro integration paths\nexport const KIRO_SETTINGS_PATH = join(KIRO_CONFIG_DIR, 'settings.json');\nexport const KIRO_CONTEXT_PATH = join(KIRO_CONFIG_DIR, 'context.md');\n\n/**\n * Get project-specific archive directory\n */\nexport function getProjectArchiveDir(projectName: string): string {\n return join(ARCHIVES_DIR, projectName);\n}\n\n/**\n * Get worker socket path for a session\n */\nexport function getWorkerSocketPath(sessionId: number): string {\n return join(DATA_DIR, `worker-${sessionId}.sock`);\n}\n\n/**\n * Ensure a directory exists\n */\nexport function ensureDir(dirPath: string): void {\n mkdirSync(dirPath, { recursive: true });\n}\n\n/**\n * Ensure all data directories exist\n */\nexport function ensureAllDataDirs(): void {\n ensureDir(DATA_DIR);\n ensureDir(ARCHIVES_DIR);\n ensureDir(LOGS_DIR);\n ensureDir(TRASH_DIR);\n ensureDir(BACKUPS_DIR);\n ensureDir(MODES_DIR);\n}\n\n/**\n * Ensure modes directory exists\n */\nexport function ensureModesDir(): void {\n ensureDir(MODES_DIR);\n}\n\n/**\n * Get current project name from git root or cwd\n */\nexport function getCurrentProjectName(): string {\n try {\n const gitRoot = execSync('git rev-parse --show-toplevel', {\n cwd: process.cwd(),\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'ignore'],\n windowsHide: true\n }).trim();\n return basename(gitRoot);\n } catch (error) {\n logger.debug('SYSTEM', 'Git root detection failed, using cwd basename', {\n cwd: process.cwd()\n }, error as Error);\n return basename(process.cwd());\n }\n}\n\n/**\n * Find package root directory\n */\nexport function getPackageRoot(): string {\n return join(_dirname, '..');\n}\n\n/**\n * Create a timestamped backup filename\n */\nexport function createBackupFilename(originalPath: string): string {\n const timestamp = new Date()\n .toISOString()\n .replace(/[:.]/g, '-')\n .replace('T', '_')\n .slice(0, 19);\n\n return `${originalPath}.backup.${timestamp}`;\n}\n", "/**\n * Structured Logger for Kiro Memory Worker Service\n * Provides readable, traceable logging with correlation IDs and data flow tracking\n */\n\nimport { appendFileSync, existsSync, mkdirSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\nexport enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3,\n SILENT = 4\n}\n\nexport type Component = 'HOOK' | 'WORKER' | 'SDK' | 'PARSER' | 'DB' | 'SYSTEM' | 'HTTP' | 'SESSION' | 'CHROMA' | 'CHROMA_SYNC' | 'FOLDER_INDEX' | 'CONTEXT' | 'QUEUE' | 'EMBEDDING' | 'SEARCH' | 'VECTOR';\n\ninterface LogContext {\n sessionId?: number;\n memorySessionId?: string;\n correlationId?: string;\n [key: string]: any;\n}\n\n// Default data directory for Kiro Memory\nconst DEFAULT_DATA_DIR = join(homedir(), '.contextkit');\n\nclass Logger {\n private level: LogLevel | null = null;\n private useColor: boolean;\n private logFilePath: string | null = null;\n private logFileInitialized: boolean = false;\n\n constructor() {\n // Disable colors when output is not a TTY (e.g., PM2 logs)\n this.useColor = process.stdout.isTTY ?? false;\n }\n\n /**\n * Initialize log file path and ensure directory exists (lazy initialization)\n */\n private ensureLogFileInitialized(): void {\n if (this.logFileInitialized) return;\n this.logFileInitialized = true;\n\n try {\n const logsDir = join(DEFAULT_DATA_DIR, 'logs');\n\n // Ensure logs directory exists\n if (!existsSync(logsDir)) {\n mkdirSync(logsDir, { recursive: true });\n }\n\n // Create log file path with date\n const date = new Date().toISOString().split('T')[0];\n this.logFilePath = join(logsDir, `kiro-memory-${date}.log`);\n } catch (error) {\n console.error('[LOGGER] Failed to initialize log file:', error);\n this.logFilePath = null;\n }\n }\n\n /**\n * Lazy-load log level from settings file\n */\n private getLevel(): LogLevel {\n if (this.level === null) {\n try {\n const settingsPath = join(DEFAULT_DATA_DIR, 'settings.json');\n if (existsSync(settingsPath)) {\n const settingsData = readFileSync(settingsPath, 'utf-8');\n const settings = JSON.parse(settingsData);\n const envLevel = (settings.KIRO_MEMORY_LOG_LEVEL || settings.CONTEXTKIT_LOG_LEVEL || 'INFO').toUpperCase();\n this.level = LogLevel[envLevel as keyof typeof LogLevel] ?? LogLevel.INFO;\n } else {\n this.level = LogLevel.INFO;\n }\n } catch (error) {\n this.level = LogLevel.INFO;\n }\n }\n return this.level;\n }\n\n /**\n * Create correlation ID for tracking an observation through the pipeline\n */\n correlationId(sessionId: number, observationNum: number): string {\n return `obs-${sessionId}-${observationNum}`;\n }\n\n /**\n * Create session correlation ID\n */\n sessionId(sessionId: number): string {\n return `session-${sessionId}`;\n }\n\n /**\n * Format data for logging - create compact summaries instead of full dumps\n */\n private formatData(data: any): string {\n if (data === null || data === undefined) return '';\n if (typeof data === 'string') return data;\n if (typeof data === 'number') return data.toString();\n if (typeof data === 'boolean') return data.toString();\n\n if (typeof data === 'object') {\n if (data instanceof Error) {\n return this.getLevel() === LogLevel.DEBUG\n ? `${data.message}\\n${data.stack}`\n : data.message;\n }\n\n if (Array.isArray(data)) {\n return `[${data.length} items]`;\n }\n\n const keys = Object.keys(data);\n if (keys.length === 0) return '{}';\n if (keys.length <= 3) {\n return JSON.stringify(data);\n }\n return `{${keys.length} keys: ${keys.slice(0, 3).join(', ')}...}`;\n }\n\n return String(data);\n }\n\n /**\n * Format timestamp in local timezone (YYYY-MM-DD HH:MM:SS.mmm)\n */\n private formatTimestamp(date: Date): string {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n const hours = String(date.getHours()).padStart(2, '0');\n const minutes = String(date.getMinutes()).padStart(2, '0');\n const seconds = String(date.getSeconds()).padStart(2, '0');\n const ms = String(date.getMilliseconds()).padStart(3, '0');\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${ms}`;\n }\n\n /**\n * Core logging method\n */\n private log(\n level: LogLevel,\n component: Component,\n message: string,\n context?: LogContext,\n data?: any\n ): void {\n if (level < this.getLevel()) return;\n\n this.ensureLogFileInitialized();\n\n const timestamp = this.formatTimestamp(new Date());\n const levelStr = LogLevel[level].padEnd(5);\n const componentStr = component.padEnd(6);\n\n let correlationStr = '';\n if (context?.correlationId) {\n correlationStr = `[${context.correlationId}] `;\n } else if (context?.sessionId) {\n correlationStr = `[session-${context.sessionId}] `;\n }\n\n let dataStr = '';\n if (data !== undefined && data !== null) {\n if (data instanceof Error) {\n dataStr = this.getLevel() === LogLevel.DEBUG\n ? `\\n${data.message}\\n${data.stack}`\n : ` ${data.message}`;\n } else if (this.getLevel() === LogLevel.DEBUG && typeof data === 'object') {\n dataStr = '\\n' + JSON.stringify(data, null, 2);\n } else {\n dataStr = ' ' + this.formatData(data);\n }\n }\n\n let contextStr = '';\n if (context) {\n const { sessionId, memorySessionId, correlationId, ...rest } = context;\n if (Object.keys(rest).length > 0) {\n const pairs = Object.entries(rest).map(([k, v]) => `${k}=${v}`);\n contextStr = ` {${pairs.join(', ')}}`;\n }\n }\n\n const logLine = `[${timestamp}] [${levelStr}] [${componentStr}] ${correlationStr}${message}${contextStr}${dataStr}`;\n\n if (this.logFilePath) {\n try {\n appendFileSync(this.logFilePath, logLine + '\\n', 'utf8');\n } catch (error) {\n process.stderr.write(`[LOGGER] Failed to write to log file: ${error}\\n`);\n }\n } else {\n process.stderr.write(logLine + '\\n');\n }\n }\n\n // Public logging methods\n debug(component: Component, message: string, context?: LogContext, data?: any): void {\n this.log(LogLevel.DEBUG, component, message, context, data);\n }\n\n info(component: Component, message: string, context?: LogContext, data?: any): void {\n this.log(LogLevel.INFO, component, message, context, data);\n }\n\n warn(component: Component, message: string, context?: LogContext, data?: any): void {\n this.log(LogLevel.WARN, component, message, context, data);\n }\n\n error(component: Component, message: string, context?: LogContext, data?: any): void {\n this.log(LogLevel.ERROR, component, message, context, data);\n }\n\n /**\n * Log data flow: input \u2192 processing\n */\n dataIn(component: Component, message: string, context?: LogContext, data?: any): void {\n this.info(component, `\u2192 ${message}`, context, data);\n }\n\n /**\n * Log data flow: processing \u2192 output\n */\n dataOut(component: Component, message: string, context?: LogContext, data?: any): void {\n this.info(component, `\u2190 ${message}`, context, data);\n }\n\n /**\n * Log successful completion\n */\n success(component: Component, message: string, context?: LogContext, data?: any): void {\n this.info(component, `\u2713 ${message}`, context, data);\n }\n\n /**\n * Log failure\n */\n failure(component: Component, message: string, context?: LogContext, data?: any): void {\n this.error(component, `\u2717 ${message}`, context, data);\n }\n\n /**\n * Log timing information\n */\n timing(component: Component, message: string, durationMs: number, context?: LogContext): void {\n this.info(component, `\u23F1 ${message}`, context, { duration: `${durationMs}ms` });\n }\n\n /**\n * Happy Path Error - logs when the expected \"happy path\" fails but we have a fallback\n */\n happyPathError<T = string>(\n component: Component,\n message: string,\n context?: LogContext,\n data?: any,\n fallback: T = '' as T\n ): T {\n const stack = new Error().stack || '';\n const stackLines = stack.split('\\n');\n const callerLine = stackLines[2] || '';\n const callerMatch = callerLine.match(/at\\s+(?:.*\\s+)?\\(?([^:]+):(\\d+):(\\d+)\\)?/);\n const location = callerMatch\n ? `${callerMatch[1].split('/').pop()}:${callerMatch[2]}`\n : 'unknown';\n\n const enhancedContext = {\n ...context,\n location\n };\n\n this.warn(component, `[HAPPY-PATH] ${message}`, enhancedContext, data);\n\n return fallback;\n }\n}\n\n// Export singleton instance\nexport const logger = new Logger();\n", "import { Database } from 'bun:sqlite';\nimport { DATA_DIR, DB_PATH, ensureDir } from '../../shared/paths.js';\nimport { logger } from '../../utils/logger.js';\n\n// SQLite configuration constants\nconst SQLITE_MMAP_SIZE_BYTES = 256 * 1024 * 1024; // 256MB\nconst SQLITE_CACHE_SIZE_PAGES = 10_000;\n\nexport interface Migration {\n version: number;\n up: (db: Database) => void;\n down?: (db: Database) => void;\n}\n\n\n\n/**\n * KiroMemoryDatabase - Main entry point for the sqlite module\n *\n * Sets up bun:sqlite with optimized settings and runs all migrations.\n *\n * Usage:\n * const db = new KiroMemoryDatabase(); // uses default DB_PATH\n * const db = new KiroMemoryDatabase('/path/to/db.sqlite');\n * const db = new KiroMemoryDatabase(':memory:'); // for tests\n */\nexport class KiroMemoryDatabase {\n private _db: Database;\n\n /**\n * Readonly accessor for the underlying Database instance.\n * Prefer using query() and run() proxy methods directly.\n */\n get db(): Database {\n return this._db;\n }\n\n /**\n * @param dbPath - Path to the SQLite file (default: DB_PATH)\n * @param skipMigrations - If true, skip the migration runner (for high-frequency hooks)\n */\n constructor(dbPath: string = DB_PATH, skipMigrations: boolean = false) {\n // Ensure data directory exists (skip for in-memory databases)\n if (dbPath !== ':memory:') {\n ensureDir(DATA_DIR);\n }\n\n // Create database connection\n this._db = new Database(dbPath, { create: true, readwrite: true });\n\n // Apply optimized SQLite settings\n this._db.run('PRAGMA journal_mode = WAL');\n this._db.run('PRAGMA busy_timeout = 5000'); // Wait up to 5s on concurrent lock (hook + worker)\n this._db.run('PRAGMA synchronous = NORMAL');\n this._db.run('PRAGMA foreign_keys = ON');\n this._db.run('PRAGMA temp_store = memory');\n this._db.run(`PRAGMA mmap_size = ${SQLITE_MMAP_SIZE_BYTES}`);\n this._db.run(`PRAGMA cache_size = ${SQLITE_CACHE_SIZE_PAGES}`);\n\n // Run migrations only if needed (hooks skip them for performance)\n if (!skipMigrations) {\n const migrationRunner = new MigrationRunner(this._db);\n migrationRunner.runAllMigrations();\n }\n }\n\n /**\n * Prepare a query (delegates to underlying Database).\n * Proxy method to avoid ctx.db.db.query() double access.\n */\n query(sql: string) {\n return this._db.query(sql);\n }\n\n /**\n * Execute a SQL statement without results (delegates to underlying Database).\n * Proxy method to avoid ctx.db.db.run() double access.\n */\n run(sql: string, params?: any[]) {\n return this._db.run(sql, params);\n }\n\n /**\n * Executes a function within an atomic transaction.\n * If fn() throws an error, the transaction is automatically rolled back.\n */\n withTransaction<T>(fn: (db: Database) => T): T {\n const transaction = this._db.transaction(fn);\n return transaction(this._db);\n }\n\n /**\n * Close the database connection\n */\n close(): void {\n this._db.close();\n }\n}\n\n/**\n * Migration runner for Kiro Memory\n */\nclass MigrationRunner {\n private db: Database;\n\n constructor(db: Database) {\n this.db = db;\n }\n\n runAllMigrations(): void {\n // Create schema_versions table if not exists\n this.db.run(`\n CREATE TABLE IF NOT EXISTS schema_versions (\n id INTEGER PRIMARY KEY,\n version INTEGER UNIQUE NOT NULL,\n applied_at TEXT NOT NULL\n )\n `);\n\n // Get current version\n const versionQuery = this.db.query('SELECT MAX(version) as version FROM schema_versions');\n const result = versionQuery.get() as { version: number } | null;\n const currentVersion = result?.version || 0;\n\n // Run migrations\n const migrations = this.getMigrations();\n for (const migration of migrations) {\n if (migration.version > currentVersion) {\n logger.info('DB', `Applying migration ${migration.version}`);\n \n const transaction = this.db.transaction(() => {\n migration.up(this.db);\n const insert = this.db.query('INSERT INTO schema_versions (version, applied_at) VALUES (?, ?)');\n insert.run(migration.version, new Date().toISOString());\n });\n \n transaction();\n logger.info('DB', `Migration ${migration.version} applied successfully`);\n }\n }\n }\n\n private getMigrations(): Migration[] {\n return [\n {\n version: 1,\n up: (db) => {\n // Sessions table\n db.run(`\n CREATE TABLE IF NOT EXISTS sessions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n content_session_id TEXT NOT NULL UNIQUE,\n project TEXT NOT NULL,\n user_prompt TEXT NOT NULL,\n memory_session_id TEXT,\n status TEXT DEFAULT 'active',\n started_at TEXT NOT NULL,\n started_at_epoch INTEGER NOT NULL,\n completed_at TEXT,\n completed_at_epoch INTEGER\n )\n `);\n\n // Observations table\n db.run(`\n CREATE TABLE IF NOT EXISTS observations (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n memory_session_id TEXT NOT NULL,\n project TEXT NOT NULL,\n type TEXT NOT NULL,\n title TEXT NOT NULL,\n subtitle TEXT,\n text TEXT,\n narrative TEXT,\n facts TEXT,\n concepts TEXT,\n files_read TEXT,\n files_modified TEXT,\n prompt_number INTEGER NOT NULL,\n created_at TEXT NOT NULL,\n created_at_epoch INTEGER NOT NULL\n )\n `);\n\n // Summaries table\n db.run(`\n CREATE TABLE IF NOT EXISTS summaries (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n project TEXT NOT NULL,\n request TEXT,\n investigated TEXT,\n learned TEXT,\n completed TEXT,\n next_steps TEXT,\n notes TEXT,\n created_at TEXT NOT NULL,\n created_at_epoch INTEGER NOT NULL\n )\n `);\n\n // Prompts table\n db.run(`\n CREATE TABLE IF NOT EXISTS prompts (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n content_session_id TEXT NOT NULL,\n project TEXT NOT NULL,\n prompt_number INTEGER NOT NULL,\n prompt_text TEXT NOT NULL,\n created_at TEXT NOT NULL,\n created_at_epoch INTEGER NOT NULL\n )\n `);\n\n // Pending messages table\n db.run(`\n CREATE TABLE IF NOT EXISTS pending_messages (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n content_session_id TEXT NOT NULL,\n type TEXT NOT NULL,\n data TEXT NOT NULL,\n created_at TEXT NOT NULL,\n created_at_epoch INTEGER NOT NULL\n )\n `);\n\n // Indexes\n db.run('CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project)');\n db.run('CREATE INDEX IF NOT EXISTS idx_observations_project ON observations(project)');\n db.run('CREATE INDEX IF NOT EXISTS idx_observations_session ON observations(memory_session_id)');\n db.run('CREATE INDEX IF NOT EXISTS idx_summaries_session ON summaries(session_id)');\n db.run('CREATE INDEX IF NOT EXISTS idx_prompts_session ON prompts(content_session_id)');\n }\n },\n {\n version: 2,\n up: (db) => {\n // FTS5 table for full-text search on observations\n db.run(`\n CREATE VIRTUAL TABLE IF NOT EXISTS observations_fts USING fts5(\n title, text, narrative, concepts,\n content='observations',\n content_rowid='id'\n )\n `);\n\n // Triggers to keep FTS5 synchronized\n db.run(`\n CREATE TRIGGER IF NOT EXISTS observations_ai AFTER INSERT ON observations BEGIN\n INSERT INTO observations_fts(rowid, title, text, narrative, concepts)\n VALUES (new.id, new.title, new.text, new.narrative, new.concepts);\n END\n `);\n\n db.run(`\n CREATE TRIGGER IF NOT EXISTS observations_ad AFTER DELETE ON observations BEGIN\n INSERT INTO observations_fts(observations_fts, rowid, title, text, narrative, concepts)\n VALUES ('delete', old.id, old.title, old.text, old.narrative, old.concepts);\n END\n `);\n\n db.run(`\n CREATE TRIGGER IF NOT EXISTS observations_au AFTER UPDATE ON observations BEGIN\n INSERT INTO observations_fts(observations_fts, rowid, title, text, narrative, concepts)\n VALUES ('delete', old.id, old.title, old.text, old.narrative, old.concepts);\n INSERT INTO observations_fts(rowid, title, text, narrative, concepts)\n VALUES (new.id, new.title, new.text, new.narrative, new.concepts);\n END\n `);\n\n // Backfill existing observations into the FTS5 table\n db.run(`\n INSERT INTO observations_fts(rowid, title, text, narrative, concepts)\n SELECT id, title, text, narrative, concepts FROM observations\n `);\n\n // Additional indexes for search performance\n db.run('CREATE INDEX IF NOT EXISTS idx_observations_type ON observations(type)');\n db.run('CREATE INDEX IF NOT EXISTS idx_observations_epoch ON observations(created_at_epoch)');\n db.run('CREATE INDEX IF NOT EXISTS idx_summaries_project ON summaries(project)');\n db.run('CREATE INDEX IF NOT EXISTS idx_summaries_epoch ON summaries(created_at_epoch)');\n db.run('CREATE INDEX IF NOT EXISTS idx_prompts_project ON prompts(project)');\n }\n },\n {\n version: 3,\n up: (db) => {\n // Alias table for renaming projects in the UI\n db.run(`\n CREATE TABLE IF NOT EXISTS project_aliases (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n project_name TEXT NOT NULL UNIQUE,\n display_name TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n )\n `);\n\n db.run('CREATE UNIQUE INDEX IF NOT EXISTS idx_project_aliases_name ON project_aliases(project_name)');\n }\n },\n {\n version: 4,\n up: (db) => {\n // Embeddings table for local semantic search\n db.run(`\n CREATE TABLE IF NOT EXISTS observation_embeddings (\n observation_id INTEGER PRIMARY KEY,\n embedding BLOB NOT NULL,\n model TEXT NOT NULL,\n dimensions INTEGER NOT NULL,\n created_at TEXT NOT NULL,\n FOREIGN KEY (observation_id) REFERENCES observations(id) ON DELETE CASCADE\n )\n `);\n\n db.run('CREATE INDEX IF NOT EXISTS idx_embeddings_model ON observation_embeddings(model)');\n }\n },\n {\n version: 5,\n up: (db) => {\n // Track last access (search that found the observation)\n db.run('ALTER TABLE observations ADD COLUMN last_accessed_epoch INTEGER');\n // Stale flag: 0 = fresh, 1 = file modified after the observation\n db.run('ALTER TABLE observations ADD COLUMN is_stale INTEGER DEFAULT 0');\n // Index for decay queries\n db.run('CREATE INDEX IF NOT EXISTS idx_observations_last_accessed ON observations(last_accessed_epoch)');\n // Index for stale queries\n db.run('CREATE INDEX IF NOT EXISTS idx_observations_stale ON observations(is_stale)');\n }\n },\n {\n version: 6,\n up: (db) => {\n // Checkpoint table for session resume\n db.run(`\n CREATE TABLE IF NOT EXISTS checkpoints (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id INTEGER NOT NULL,\n project TEXT NOT NULL,\n task TEXT NOT NULL,\n progress TEXT,\n next_steps TEXT,\n open_questions TEXT,\n relevant_files TEXT,\n context_snapshot TEXT,\n created_at TEXT NOT NULL,\n created_at_epoch INTEGER NOT NULL,\n FOREIGN KEY (session_id) REFERENCES sessions(id)\n )\n `);\n db.run('CREATE INDEX IF NOT EXISTS idx_checkpoints_session ON checkpoints(session_id)');\n db.run('CREATE INDEX IF NOT EXISTS idx_checkpoints_project ON checkpoints(project)');\n db.run('CREATE INDEX IF NOT EXISTS idx_checkpoints_epoch ON checkpoints(created_at_epoch)');\n }\n },\n {\n version: 7,\n up: (db) => {\n // Content hash for content-based deduplication (SHA256)\n db.run('ALTER TABLE observations ADD COLUMN content_hash TEXT');\n db.run('CREATE INDEX IF NOT EXISTS idx_observations_hash ON observations(content_hash)');\n }\n },\n {\n version: 8,\n up: (db) => {\n // Token economics: tokens spent to generate the observation (discovery cost)\n db.run('ALTER TABLE observations ADD COLUMN discovery_tokens INTEGER DEFAULT 0');\n // Token economics on summaries\n db.run('ALTER TABLE summaries ADD COLUMN discovery_tokens INTEGER DEFAULT 0');\n }\n },\n {\n version: 9,\n up: (db) => {\n // Composite indexes for pagination and project filters\n db.run('CREATE INDEX IF NOT EXISTS idx_observations_project_epoch ON observations(project, created_at_epoch DESC)');\n db.run('CREATE INDEX IF NOT EXISTS idx_observations_project_type ON observations(project, type)');\n db.run('CREATE INDEX IF NOT EXISTS idx_summaries_project_epoch ON summaries(project, created_at_epoch DESC)');\n db.run('CREATE INDEX IF NOT EXISTS idx_prompts_project_epoch ON prompts(project, created_at_epoch DESC)');\n }\n }\n ];\n }\n}\n\n// Re-export bun:sqlite Database type\nexport { Database };\n", "/**\n * Local embedding service for Kiro Memory\n *\n * Provider: fastembed (primary) \u2192 @huggingface/transformers (fallback) \u2192 null (FTS5 only)\n * Generates 384-dim vector embeddings for semantic search.\n * Lazy loading: the model is loaded only on first use.\n */\n\nimport { logger } from '../../utils/logger.js';\n\ntype EmbeddingProvider = 'fastembed' | 'transformers' | null;\n\nexport class EmbeddingService {\n private provider: EmbeddingProvider = null;\n private model: any = null;\n private initialized = false;\n private initializing: Promise<boolean> | null = null;\n\n /**\n * Initialize the embedding service.\n * Tries fastembed, then @huggingface/transformers, then fallback to null.\n */\n async initialize(): Promise<boolean> {\n if (this.initialized) return this.provider !== null;\n\n // Avoid concurrent initializations\n if (this.initializing) return this.initializing;\n\n this.initializing = this._doInitialize();\n const result = await this.initializing;\n this.initializing = null;\n return result;\n }\n\n private async _doInitialize(): Promise<boolean> {\n // Attempt 1: fastembed\n try {\n const fastembed = await import('fastembed');\n const EmbeddingModel = fastembed.EmbeddingModel || fastembed.default?.EmbeddingModel;\n const FlagEmbedding = fastembed.FlagEmbedding || fastembed.default?.FlagEmbedding;\n\n if (FlagEmbedding && EmbeddingModel) {\n this.model = await FlagEmbedding.init({\n model: EmbeddingModel.BGESmallENV15\n });\n this.provider = 'fastembed';\n this.initialized = true;\n logger.info('EMBEDDING', 'Initialized with fastembed (BGE-small-en-v1.5)');\n return true;\n }\n } catch (error) {\n logger.debug('EMBEDDING', `fastembed not available: ${error}`);\n }\n\n // Attempt 2: @huggingface/transformers\n try {\n const transformers = await import('@huggingface/transformers');\n const pipeline = (transformers as any).pipeline || (transformers as any).default?.pipeline;\n\n if (pipeline) {\n this.model = await pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2', {\n quantized: true\n } as any);\n this.provider = 'transformers';\n this.initialized = true;\n logger.info('EMBEDDING', 'Initialized with @huggingface/transformers (all-MiniLM-L6-v2)');\n return true;\n }\n } catch (error) {\n logger.debug('EMBEDDING', `@huggingface/transformers not available: ${error}`);\n }\n\n // No provider available\n this.provider = null;\n this.initialized = true;\n logger.warn('EMBEDDING', 'No embedding provider available, semantic search disabled');\n return false;\n }\n\n /**\n * Generate embedding for a single text.\n * Returns Float32Array with 384 dimensions, or null if not available.\n */\n async embed(text: string): Promise<Float32Array | null> {\n if (!this.initialized) await this.initialize();\n if (!this.provider || !this.model) return null;\n\n try {\n // Truncate text that is too long (max ~512 tokens \u2248 2000 chars)\n const truncated = text.substring(0, 2000);\n\n if (this.provider === 'fastembed') {\n return await this._embedFastembed(truncated);\n } else if (this.provider === 'transformers') {\n return await this._embedTransformers(truncated);\n }\n } catch (error) {\n logger.error('EMBEDDING', `Error generating embedding: ${error}`);\n }\n\n return null;\n }\n\n /**\n * Generate embeddings in batch.\n * Uses native batch support when available (fastembed, transformers),\n * falls back to serial processing on batch failure.\n */\n async embedBatch(texts: string[]): Promise<(Float32Array | null)[]> {\n if (!this.initialized) await this.initialize();\n if (!this.provider || !this.model) return texts.map(() => null);\n if (texts.length === 0) return [];\n\n // Truncate all texts upfront (max ~512 tokens \u2248 2000 chars)\n const truncated = texts.map(t => t.substring(0, 2000));\n\n // Try native batch embedding first\n try {\n if (this.provider === 'fastembed') {\n return await this._embedBatchFastembed(truncated);\n } else if (this.provider === 'transformers') {\n return await this._embedBatchTransformers(truncated);\n }\n } catch (error) {\n logger.warn('EMBEDDING', `Batch embedding failed, falling back to serial: ${error}`);\n }\n\n // Serial fallback: process one at a time\n return this._embedBatchSerial(truncated);\n }\n\n /**\n * Check if the service is available.\n */\n isAvailable(): boolean {\n return this.initialized && this.provider !== null;\n }\n\n /**\n * Name of the active provider.\n */\n getProvider(): string | null {\n return this.provider;\n }\n\n /**\n * Embedding vector dimensions.\n */\n getDimensions(): number {\n return 384;\n }\n\n // --- Batch implementations ---\n\n /**\n * Native batch embedding with fastembed.\n * FlagEmbedding.embed() accepts string[] and returns an async iterable of batches.\n */\n private async _embedBatchFastembed(texts: string[]): Promise<(Float32Array | null)[]> {\n const results: (Float32Array | null)[] = [];\n // Pass entire array at once; second param is internal batch size for chunking\n const embeddings = this.model.embed(texts, texts.length);\n for await (const batch of embeddings) {\n if (batch) {\n for (const vec of batch) {\n results.push(vec instanceof Float32Array ? vec : new Float32Array(vec));\n }\n }\n }\n // Pad with nulls if fastembed returned fewer results than expected\n while (results.length < texts.length) {\n results.push(null);\n }\n return results;\n }\n\n /**\n * Batch embedding with @huggingface/transformers pipeline.\n * The pipeline accepts string[] and returns a Tensor with shape [N, dims].\n */\n private async _embedBatchTransformers(texts: string[]): Promise<(Float32Array | null)[]> {\n const output = await this.model(texts, {\n pooling: 'mean',\n normalize: true\n });\n\n if (!output?.data) {\n return texts.map(() => null);\n }\n\n const dims = this.getDimensions();\n const data = output.data instanceof Float32Array\n ? output.data\n : new Float32Array(output.data);\n\n // The output tensor is flattened [N * dims], slice into individual vectors\n const results: (Float32Array | null)[] = [];\n for (let i = 0; i < texts.length; i++) {\n const offset = i * dims;\n if (offset + dims <= data.length) {\n results.push(data.slice(offset, offset + dims));\n } else {\n results.push(null);\n }\n }\n return results;\n }\n\n /**\n * Serial fallback: embed texts one at a time.\n * Used when native batch fails.\n */\n private async _embedBatchSerial(texts: string[]): Promise<(Float32Array | null)[]> {\n const results: (Float32Array | null)[] = [];\n for (const text of texts) {\n try {\n const embedding = await this.embed(text);\n results.push(embedding);\n } catch {\n results.push(null);\n }\n }\n return results;\n }\n\n // --- Single-text provider implementations ---\n\n private async _embedFastembed(text: string): Promise<Float32Array | null> {\n const embeddings = this.model.embed([text], 1);\n for await (const batch of embeddings) {\n if (batch && batch.length > 0) {\n // fastembed returns array of arrays\n const vec = batch[0];\n return vec instanceof Float32Array ? vec : new Float32Array(vec);\n }\n }\n return null;\n }\n\n private async _embedTransformers(text: string): Promise<Float32Array | null> {\n const output = await this.model(text, {\n pooling: 'mean',\n normalize: true\n });\n\n // transformers.js returns a Tensor, extract the data\n if (output?.data) {\n return output.data instanceof Float32Array\n ? output.data\n : new Float32Array(output.data);\n }\n\n return null;\n }\n}\n\n// Singleton\nlet embeddingService: EmbeddingService | null = null;\n\nexport function getEmbeddingService(): EmbeddingService {\n if (!embeddingService) {\n embeddingService = new EmbeddingService();\n }\n return embeddingService;\n}\n", "/**\n * Local vector search on SQLite BLOB\n *\n * Stores embeddings as BLOB in observation_embeddings,\n * computes cosine similarity in JavaScript for semantic search.\n *\n * Optimizations vs brute-force O(n):\n * - SQL pre-filtering by project and recency (reduces candidates)\n * - Maximum limit of candidates loaded in memory (maxCandidates)\n * - Buffer pooling to reduce GC allocations\n */\n\nimport type { Database } from 'bun:sqlite';\nimport { getEmbeddingService } from './EmbeddingService.js';\nimport { logger } from '../../utils/logger.js';\n\n// Maximum number of embeddings loaded in memory per query\nconst DEFAULT_MAX_CANDIDATES = 2000;\n\nexport interface VectorSearchResult {\n id: number;\n observationId: number;\n similarity: number;\n title: string;\n text: string | null;\n type: string;\n project: string;\n created_at: string;\n created_at_epoch: number;\n}\n\n/**\n * Compute cosine similarity between two Float32Array vectors.\n * Optimized version: unified loop with a single final sqrt.\n */\nexport function cosineSimilarity(a: Float32Array, b: Float32Array): number {\n const len = a.length;\n if (len !== b.length) return 0;\n\n let dotProduct = 0;\n let normA = 0;\n let normB = 0;\n\n // Unified loop \u2014 avoids 3 separate passes\n for (let i = 0; i < len; i++) {\n const ai = a[i];\n const bi = b[i];\n dotProduct += ai * bi;\n normA += ai * ai;\n normB += bi * bi;\n }\n\n const denominator = Math.sqrt(normA * normB);\n if (denominator === 0) return 0;\n\n return dotProduct / denominator;\n}\n\n/**\n * Convert Float32Array to Buffer for SQLite BLOB storage.\n */\nfunction float32ToBuffer(arr: Float32Array): Buffer {\n return Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n\n/**\n * Convert SQLite BLOB Buffer to Float32Array.\n */\nfunction bufferToFloat32(buf: Buffer | Uint8Array): Float32Array {\n const arrayBuffer = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);\n return new Float32Array(arrayBuffer);\n}\n\nexport class VectorSearch {\n\n /**\n * Semantic search with SQL pre-filtering for scalability.\n *\n * 2-phase strategy:\n * 1. SQL pre-filters by project + sorts by recency (loads max N candidates)\n * 2. JS computes cosine similarity only on filtered candidates\n *\n * With 50k observations and maxCandidates=2000, loads only ~4% of data.\n */\n async search(\n db: Database,\n queryEmbedding: Float32Array,\n options: {\n project?: string;\n limit?: number;\n threshold?: number;\n maxCandidates?: number;\n } = {}\n ): Promise<VectorSearchResult[]> {\n const limit = options.limit || 10;\n const threshold = options.threshold || 0.3;\n const maxCandidates = options.maxCandidates || DEFAULT_MAX_CANDIDATES;\n\n try {\n // Phase 1: pre-filter in SQL by project, sort by recency, limit candidates\n const conditions: string[] = [];\n const params: any[] = [];\n\n if (options.project) {\n conditions.push('o.project = ?');\n params.push(options.project);\n }\n\n const whereClause = conditions.length > 0\n ? `WHERE ${conditions.join(' AND ')}`\n : '';\n\n // Sort by recency and limit candidates \u2014 avoids loading all embeddings\n const sql = `\n SELECT e.observation_id, e.embedding,\n o.title, o.text, o.type, o.project, o.created_at, o.created_at_epoch\n FROM observation_embeddings e\n JOIN observations o ON o.id = e.observation_id\n ${whereClause}\n ORDER BY o.created_at_epoch DESC\n LIMIT ?\n `;\n params.push(maxCandidates);\n\n const rows = db.query(sql).all(...params) as Array<{\n observation_id: number;\n embedding: Buffer;\n title: string;\n text: string | null;\n type: string;\n project: string;\n created_at: string;\n created_at_epoch: number;\n }>;\n\n // Phase 2: compute similarity only on pre-filtered candidates\n const scored: VectorSearchResult[] = [];\n\n for (const row of rows) {\n const embedding = bufferToFloat32(row.embedding);\n const similarity = cosineSimilarity(queryEmbedding, embedding);\n\n if (similarity >= threshold) {\n scored.push({\n id: row.observation_id,\n observationId: row.observation_id,\n similarity,\n title: row.title,\n text: row.text,\n type: row.type,\n project: row.project,\n created_at: row.created_at,\n created_at_epoch: row.created_at_epoch\n });\n }\n }\n\n // Sort by similarity descending\n scored.sort((a, b) => b.similarity - a.similarity);\n\n logger.debug('VECTOR', `Search: ${rows.length} candidates \u2192 ${scored.length} above threshold \u2192 ${Math.min(scored.length, limit)} results`);\n\n return scored.slice(0, limit);\n } catch (error) {\n logger.error('VECTOR', `Vector search error: ${error}`);\n return [];\n }\n }\n\n /**\n * Store embedding for an observation.\n */\n async storeEmbedding(\n db: Database,\n observationId: number,\n embedding: Float32Array,\n model: string\n ): Promise<void> {\n try {\n const blob = float32ToBuffer(embedding);\n\n db.query(`\n INSERT OR REPLACE INTO observation_embeddings\n (observation_id, embedding, model, dimensions, created_at)\n VALUES (?, ?, ?, ?, ?)\n `).run(\n observationId,\n blob,\n model,\n embedding.length,\n new Date().toISOString()\n );\n\n logger.debug('VECTOR', `Embedding saved for observation ${observationId}`);\n } catch (error) {\n logger.error('VECTOR', `Error saving embedding: ${error}`);\n }\n }\n\n /**\n * Generate embeddings for observations that don't have them yet.\n */\n async backfillEmbeddings(\n db: Database,\n batchSize: number = 50\n ): Promise<number> {\n const embeddingService = getEmbeddingService();\n if (!await embeddingService.initialize()) {\n logger.warn('VECTOR', 'Embedding service not available, backfill skipped');\n return 0;\n }\n\n // Find observations without embeddings\n const rows = db.query(`\n SELECT o.id, o.title, o.text, o.narrative, o.concepts\n FROM observations o\n LEFT JOIN observation_embeddings e ON e.observation_id = o.id\n WHERE e.observation_id IS NULL\n ORDER BY o.created_at_epoch DESC\n LIMIT ?\n `).all(batchSize) as Array<{\n id: number;\n title: string;\n text: string | null;\n narrative: string | null;\n concepts: string | null;\n }>;\n\n if (rows.length === 0) return 0;\n\n let count = 0;\n const model = embeddingService.getProvider() || 'unknown';\n\n for (const row of rows) {\n // Compose text for embedding: title + text + concepts\n const parts = [row.title];\n if (row.text) parts.push(row.text);\n if (row.narrative) parts.push(row.narrative);\n if (row.concepts) parts.push(row.concepts);\n const fullText = parts.join(' ').substring(0, 2000);\n\n const embedding = await embeddingService.embed(fullText);\n if (embedding) {\n await this.storeEmbedding(db, row.id, embedding, model);\n count++;\n }\n }\n\n logger.info('VECTOR', `Backfill completed: ${count}/${rows.length} embeddings generated`);\n return count;\n }\n\n /**\n * Embedding statistics.\n */\n getStats(db: Database): { total: number; embedded: number; percentage: number } {\n try {\n const totalRow = db.query('SELECT COUNT(*) as count FROM observations').get() as { count: number };\n const embeddedRow = db.query('SELECT COUNT(*) as count FROM observation_embeddings').get() as { count: number };\n\n const total = totalRow?.count || 0;\n const embedded = embeddedRow?.count || 0;\n const percentage = total > 0 ? Math.round((embedded / total) * 100) : 0;\n\n return { total, embedded, percentage };\n } catch {\n return { total: 0, embedded: 0, percentage: 0 };\n }\n }\n}\n\n// Singleton\nlet vectorSearch: VectorSearch | null = null;\n\nexport function getVectorSearch(): VectorSearch {\n if (!vectorSearch) {\n vectorSearch = new VectorSearch();\n }\n return vectorSearch;\n}\n", "/**\n * Scoring engine for intelligent ranking\n *\n * Pure functions with no DB dependencies. Combines 4 signals:\n * - semantic: cosine similarity from embedding\n * - fts5: normalized FTS5 rank\n * - recency: exponential decay based on age\n * - projectMatch: 1 if project matches, 0 otherwise\n */\n\nimport type { ScoringWeights } from '../../types/worker-types.js';\n\n/** Weights for search mode (with text query) */\nexport const SEARCH_WEIGHTS: ScoringWeights = {\n semantic: 0.4,\n fts5: 0.3,\n recency: 0.2,\n projectMatch: 0.1\n};\n\n/** Weights for context mode (no query, e.g. agentSpawn) */\nexport const CONTEXT_WEIGHTS: ScoringWeights = {\n semantic: 0.0,\n fts5: 0.0,\n recency: 0.7,\n projectMatch: 0.3\n};\n\n/**\n * Calculate recency score with exponential decay.\n * More recent = higher (close to 1). After halfLifeHours the score is ~0.5.\n *\n * @param createdAtEpoch - Creation timestamp in milliseconds\n * @param halfLifeHours - Half-life in hours (default: 168 = 7 days)\n * @returns Score 0-1\n */\nexport function recencyScore(createdAtEpoch: number, halfLifeHours: number = 168): number {\n if (!createdAtEpoch || createdAtEpoch <= 0) return 0;\n\n const nowMs = Date.now();\n const ageMs = nowMs - createdAtEpoch;\n\n // If timestamp is in the future, maximum score\n if (ageMs <= 0) return 1;\n\n const ageHours = ageMs / (1000 * 60 * 60);\n\n // Exponential decay: exp(-age * ln(2) / halfLife)\n return Math.exp(-ageHours * Math.LN2 / halfLifeHours);\n}\n\n/**\n * Normalize a raw FTS5 rank into 0-1 range.\n * FTS5 rank is negative: more negative = more relevant.\n * Min-max normalization relative to all ranks in the batch.\n *\n * @param rank - Raw FTS5 rank (negative)\n * @param allRanks - All ranks in the batch for normalization\n * @returns Score 0-1 (1 = most relevant)\n */\nexport function normalizeFTS5Rank(rank: number, allRanks: number[]): number {\n if (allRanks.length === 0) return 0;\n if (allRanks.length === 1) return 1; // Single result: maximum relevance\n\n const minRank = Math.min(...allRanks); // Most negative = best\n const maxRank = Math.max(...allRanks); // Least negative = worst\n\n // If all equal, return 1\n if (minRank === maxRank) return 1;\n\n // Invert: most negative becomes 1, least negative becomes 0\n return (maxRank - rank) / (maxRank - minRank);\n}\n\n/**\n * Binary score for project match.\n *\n * @param itemProject - Project of the item\n * @param targetProject - Target project (e.g. current project)\n * @returns 1 if they match, 0 otherwise\n */\nexport function projectMatchScore(itemProject: string, targetProject: string): number {\n if (!itemProject || !targetProject) return 0;\n return itemProject.toLowerCase() === targetProject.toLowerCase() ? 1 : 0;\n}\n\n/**\n * Calculate weighted composite score combining the 4 signals.\n *\n * @param signals - Values of the 4 signals (each 0-1)\n * @param weights - Weights for each signal\n * @returns Composite score 0-1\n */\nexport function computeCompositeScore(\n signals: {\n semantic: number;\n fts5: number;\n recency: number;\n projectMatch: number;\n },\n weights: ScoringWeights\n): number {\n return (\n signals.semantic * weights.semantic +\n signals.fts5 * weights.fts5 +\n signals.recency * weights.recency +\n signals.projectMatch * weights.projectMatch\n );\n}\n\n/**\n * Recency score based on last access (search that found the observation).\n * Uses shorter half-life than recencyScore() because access is more volatile.\n *\n * If the observation was never accessed, returns 0 (maximum penalty).\n *\n * @param lastAccessedEpoch - Last access timestamp in milliseconds (null if never accessed)\n * @param halfLifeHours - Half-life in hours (default: 48 = 2 days)\n * @returns Score 0-1 (1 = recently accessed)\n */\nexport function accessRecencyScore(lastAccessedEpoch: number | null, halfLifeHours: number = 48): number {\n if (!lastAccessedEpoch || lastAccessedEpoch <= 0) return 0;\n\n const nowMs = Date.now();\n const ageMs = nowMs - lastAccessedEpoch;\n\n // If timestamp is in the future, maximum score\n if (ageMs <= 0) return 1;\n\n const ageHours = ageMs / (1000 * 60 * 60);\n return Math.exp(-ageHours * Math.LN2 / halfLifeHours);\n}\n\n/**\n * Penalty for stale observations (files modified after the observation).\n * Returns a multiplier: 1.0 if fresh, 0.5 if stale.\n * Does not remove the observation from ranking but penalizes it significantly.\n *\n * @param isStale - Stale flag (0 = fresh, 1 = stale)\n * @returns Multiplier 0.5-1.0\n */\nexport function stalenessPenalty(isStale: number): number {\n return isStale === 1 ? 0.5 : 1.0;\n}\n\n/**\n * Multiplicative boost for structured knowledge types.\n * Constraint and decision weigh more because they represent critical rules and choices.\n * Non-knowledge types stay at 1.0 (no boost).\n */\nexport const KNOWLEDGE_TYPE_BOOST: Record<string, number> = {\n constraint: 1.30,\n decision: 1.25,\n heuristic: 1.15,\n rejected: 1.10\n};\n\n/**\n * Returns the boost multiplier for the observation type.\n * Knowledge types get a boost, all others stay at 1.0.\n *\n * @param type - Observation type\n * @returns Multiplier >= 1.0\n */\nexport function knowledgeTypeBoost(type: string): number {\n return KNOWLEDGE_TYPE_BOOST[type] ?? 1.0;\n}\n\n/**\n * Approximate token estimation from a string.\n * Uses the rule of thumb: 1 token \u2248 4 characters.\n */\nexport function estimateTokens(text: string): number {\n if (!text) return 0;\n return Math.ceil(text.length / 4);\n}\n", "/**\n * Hybrid search: combines local vector search (SQLite BLOB) with keyword search (FTS5)\n *\n * 4-signal scoring:\n * - semantic: cosine similarity from embedding\n * - fts5: normalized FTS5 rank\n * - recency: exponential decay\n * - projectMatch: project match\n *\n * If the embedding service is not available, falls back to FTS5 only.\n */\n\nimport { getEmbeddingService } from './EmbeddingService.js';\nimport { getVectorSearch } from './VectorSearch.js';\nimport {\n recencyScore,\n normalizeFTS5Rank,\n projectMatchScore,\n computeCompositeScore,\n knowledgeTypeBoost,\n SEARCH_WEIGHTS\n} from './ScoringEngine.js';\nimport type { Database } from 'bun:sqlite';\nimport type { ScoringWeights } from '../../types/worker-types.js';\nimport { logger } from '../../utils/logger.js';\n\nexport interface SearchResult {\n id: string;\n title: string;\n content: string;\n type: string;\n project: string;\n created_at: string;\n created_at_epoch: number;\n score: number;\n source: 'vector' | 'keyword' | 'hybrid';\n signals: {\n semantic: number;\n fts5: number;\n recency: number;\n projectMatch: number;\n };\n}\n\nexport class HybridSearch {\n private embeddingInitialized = false;\n\n /**\n * Initialize the embedding service (lazy, non-blocking)\n */\n async initialize(): Promise<void> {\n try {\n const embeddingService = getEmbeddingService();\n await embeddingService.initialize();\n this.embeddingInitialized = embeddingService.isAvailable();\n logger.info('SEARCH', `HybridSearch initialized (embedding: ${this.embeddingInitialized ? 'active' : 'disabled'})`);\n } catch (error) {\n logger.warn('SEARCH', 'Embedding initialization failed, using only FTS5', {}, error as Error);\n this.embeddingInitialized = false;\n }\n }\n\n /**\n * Hybrid search with 4-signal scoring\n */\n async search(\n db: Database,\n query: string,\n options: {\n project?: string;\n limit?: number;\n weights?: ScoringWeights;\n } = {}\n ): Promise<SearchResult[]> {\n const limit = options.limit || 10;\n const weights = options.weights || SEARCH_WEIGHTS;\n const targetProject = options.project || '';\n\n // Collect raw results from both sources\n const rawItems = new Map<string, {\n id: string;\n title: string;\n content: string;\n type: string;\n project: string;\n created_at: string;\n created_at_epoch: number;\n semanticScore: number;\n fts5Rank: number | null; // raw rank, to be normalized later\n source: 'vector' | 'keyword';\n }>();\n\n // Vector search (if embedding available)\n if (this.embeddingInitialized) {\n try {\n const embeddingService = getEmbeddingService();\n const queryEmbedding = await embeddingService.embed(query);\n\n if (queryEmbedding) {\n const vectorSearch = getVectorSearch();\n const vectorResults = await vectorSearch.search(db, queryEmbedding, {\n project: options.project,\n limit: limit * 2, // Fetch more results for ranking\n threshold: 0.3\n });\n\n for (const hit of vectorResults) {\n rawItems.set(String(hit.observationId), {\n id: String(hit.observationId),\n title: hit.title,\n content: hit.text || '',\n type: hit.type,\n project: hit.project,\n created_at: hit.created_at,\n created_at_epoch: hit.created_at_epoch,\n semanticScore: hit.similarity,\n fts5Rank: null,\n source: 'vector'\n });\n }\n\n logger.debug('SEARCH', `Vector search: ${vectorResults.length} results`);\n }\n } catch (error) {\n logger.warn('SEARCH', 'Vector search failed, using only keyword', {}, error as Error);\n }\n }\n\n // Keyword search FTS5 with rank (always active)\n try {\n const { searchObservationsFTSWithRank } = await import('../sqlite/Search.js');\n const keywordResults = searchObservationsFTSWithRank(db, query, {\n project: options.project,\n limit: limit * 2\n });\n\n for (const obs of keywordResults) {\n const id = String(obs.id);\n const existing = rawItems.get(id);\n\n if (existing) {\n // Present in both sources: add FTS5 rank\n existing.fts5Rank = obs.fts5_rank;\n existing.source = 'vector'; // Keep vector as primary source\n } else {\n rawItems.set(id, {\n id,\n title: obs.title,\n content: obs.text || obs.narrative || '',\n type: obs.type,\n project: obs.project,\n created_at: obs.created_at,\n created_at_epoch: obs.created_at_epoch,\n semanticScore: 0,\n fts5Rank: obs.fts5_rank,\n source: 'keyword'\n });\n }\n }\n\n logger.debug('SEARCH', `Keyword search: ${keywordResults.length} results`);\n } catch (error) {\n logger.error('SEARCH', 'Keyword search failed', {}, error as Error);\n }\n\n // No results\n if (rawItems.size === 0) return [];\n\n // Normalize FTS5 ranks\n const allFTS5Ranks = Array.from(rawItems.values())\n .filter(item => item.fts5Rank !== null)\n .map(item => item.fts5Rank as number);\n\n // Compute composite score for each item\n const scored: SearchResult[] = [];\n\n for (const item of rawItems.values()) {\n const signals = {\n semantic: item.semanticScore,\n fts5: item.fts5Rank !== null ? normalizeFTS5Rank(item.fts5Rank, allFTS5Ranks) : 0,\n recency: recencyScore(item.created_at_epoch),\n projectMatch: targetProject ? projectMatchScore(item.project, targetProject) : 0\n };\n\n const score = computeCompositeScore(signals, weights);\n\n // Boost for items present in both sources\n const isHybrid = item.semanticScore > 0 && item.fts5Rank !== null;\n const hybridBoost = isHybrid ? 1.15 : 1.0;\n // Boost for knowledge types (constraint, decision, heuristic, rejected)\n const finalScore = Math.min(1, score * hybridBoost * knowledgeTypeBoost(item.type));\n\n scored.push({\n id: item.id,\n title: item.title,\n content: item.content,\n type: item.type,\n project: item.project,\n created_at: item.created_at,\n created_at_epoch: item.created_at_epoch,\n score: finalScore,\n source: isHybrid ? 'hybrid' : item.source,\n signals\n });\n }\n\n // Sort by score descending and limit\n scored.sort((a, b) => b.score - a.score);\n const finalResults = scored.slice(0, limit);\n\n // Access tracking: update last_accessed_epoch for found results (fire-and-forget)\n if (finalResults.length > 0) {\n try {\n const { updateLastAccessed } = await import('../sqlite/Observations.js');\n const ids = finalResults.map(r => parseInt(r.id, 10)).filter(id => id > 0);\n if (ids.length > 0) {\n updateLastAccessed(db, ids);\n }\n } catch {\n // Don't propagate errors \u2014 access tracking is optional\n }\n }\n\n return finalResults;\n }\n}\n\n// Singleton\nlet hybridSearch: HybridSearch | null = null;\n\nexport function getHybridSearch(): HybridSearch {\n if (!hybridSearch) {\n hybridSearch = new HybridSearch();\n }\n return hybridSearch;\n}\n", "/**\n * Shared context for all worker routers.\n * Centralizes database, SSE broadcast, cache, and validation helpers.\n */\n\nimport type { Response } from 'express';\nimport { KiroMemoryDatabase } from './sqlite/Database.js';\nimport { getEmbeddingService } from './search/EmbeddingService.js';\nimport { getVectorSearch } from './search/VectorSearch.js';\nimport { logger } from '../utils/logger.js';\n\n// \u2500\u2500 Shared context type \u2500\u2500\n\nexport interface WorkerContext {\n db: KiroMemoryDatabase;\n broadcast: (event: string, data: any) => void;\n invalidateProjectsCache: () => void;\n generateEmbeddingForObservation: (\n observationId: number,\n title: string,\n content: string | null,\n concepts?: string[]\n ) => Promise<void>;\n}\n\n// \u2500\u2500 SSE Client Management \u2500\u2500\n\nconst MAX_SSE_CLIENTS = 50;\nconst clients: Response[] = [];\n\nexport function getClients(): Response[] {\n return clients;\n}\n\nexport function getMaxSSEClients(): number {\n return MAX_SSE_CLIENTS;\n}\n\nexport function addClient(res: Response): void {\n clients.push(res);\n}\n\nexport function removeClient(res: Response): void {\n const index = clients.indexOf(res);\n if (index > -1) {\n clients.splice(index, 1);\n }\n}\n\n/** Broadcast SSE event to all connected clients */\nexport function broadcast(event: string, data: any): void {\n const message = `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`;\n clients.forEach(client => {\n try {\n client.write(message);\n } catch (err) {\n logger.warn('WORKER', 'Broadcast failed to client', {}, err as Error);\n }\n });\n}\n\n// \u2500\u2500 Projects cache \u2500\u2500\n\nexport let projectsCache: { data: string[]; ts: number } = { data: [], ts: 0 };\nexport const PROJECTS_CACHE_TTL = 60_000;\n\nexport function invalidateProjectsCache(): void {\n projectsCache.ts = 0;\n}\n\n// \u2500\u2500 Validation helpers (shared across all routers) \u2500\u2500\n\n/** Parse an integer with safe range, returns default if invalid */\nexport function parseIntSafe(value: string | undefined, defaultVal: number, min: number, max: number): number {\n if (!value) return defaultVal;\n const parsed = parseInt(value, 10);\n if (isNaN(parsed) || parsed < min || parsed > max) return defaultVal;\n return parsed;\n}\n\n/** Validate that a project name contains only safe characters */\nexport function isValidProject(project: unknown): project is string {\n return typeof project === 'string'\n && project.length > 0\n && project.length <= 200\n && /^[\\w\\-\\.\\/@ ]+$/.test(project)\n && !project.includes('..');\n}\n\n/** Validate a non-empty string with maximum length */\nexport function isValidString(val: unknown, maxLen: number): val is string {\n return typeof val === 'string' && val.length > 0 && val.length <= maxLen;\n}\n\n// \u2500\u2500 Embedding helper \u2500\u2500\n\n/** Generate embedding for an observation (fire-and-forget) */\nexport async function generateEmbeddingForObservation(\n db: KiroMemoryDatabase,\n observationId: number,\n title: string,\n content: string | null,\n concepts?: string[]\n): Promise<void> {\n try {\n const embeddingService = getEmbeddingService();\n if (!embeddingService.isAvailable()) return;\n\n const parts = [title];\n if (content) parts.push(content);\n if (concepts?.length) parts.push(concepts.join(', '));\n const fullText = parts.join(' ').substring(0, 2000);\n\n const embedding = await embeddingService.embed(fullText);\n if (embedding) {\n const vectorSearch = getVectorSearch();\n await vectorSearch.storeEmbedding(\n db.db,\n observationId,\n embedding,\n embeddingService.getProvider() || 'unknown'\n );\n }\n } catch (error) {\n logger.debug('WORKER', `Embedding generation failed for obs ${observationId}: ${error}`);\n }\n}\n\n// \u2500\u2500 Context factory \u2500\u2500\n\nexport function createWorkerContext(db: KiroMemoryDatabase): WorkerContext {\n return {\n db,\n broadcast,\n invalidateProjectsCache,\n generateEmbeddingForObservation: (id, title, content, concepts) =>\n generateEmbeddingForObservation(db, id, title, content, concepts),\n };\n}\n", "/**\n * Router Core: health check, SSE events, notify endpoint.\n * Manages the base worker infrastructure.\n */\n\nimport { Router } from 'express';\nimport rateLimit from 'express-rate-limit';\nimport type { WorkerContext } from '../worker-context.js';\nimport { getClients, getMaxSSEClients, addClient, removeClient } from '../worker-context.js';\nimport { logger } from '../../utils/logger.js';\n\nconst ALLOWED_EVENTS = new Set([\n 'observation-created',\n 'summary-created',\n 'prompt-created',\n 'session-created'\n]);\n\nexport function createCoreRouter(ctx: WorkerContext, workerToken: string): Router {\n const router = Router();\n\n // Dedicated rate limit for /api/notify (more restrictive)\n const notifyLimiter = rateLimit({\n windowMs: 60_000,\n max: 60,\n standardHeaders: true,\n legacyHeaders: false\n });\n\n // Notification from hooks \u2192 SSE broadcast to dashboard clients\n router.post('/api/notify', notifyLimiter, (req, res) => {\n const token = req.headers['x-worker-token'] as string;\n if (token !== workerToken) {\n res.status(401).json({ error: 'Invalid or missing X-Worker-Token' });\n return;\n }\n\n const { event, data } = req.body || {};\n if (!event || typeof event !== 'string' || !ALLOWED_EVENTS.has(event)) {\n res.status(400).json({ error: `Event must be one of: ${[...ALLOWED_EVENTS].join(', ')}` });\n return;\n }\n\n ctx.broadcast(event, data || {});\n res.json({ ok: true });\n });\n\n // Health check\n router.get('/health', (_req, res) => {\n res.json({\n status: 'ok',\n timestamp: Date.now(),\n version: '1.9.0'\n });\n });\n\n // SSE endpoint with keepalive and connection limit\n router.get('/events', (req, res) => {\n const clients = getClients();\n if (clients.length >= getMaxSSEClients()) {\n res.status(503).json({ error: 'Too many SSE connections' });\n return;\n }\n\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n addClient(res);\n logger.info('WORKER', 'SSE client connected', { clients: clients.length });\n\n // Initial connection event\n res.write(`event: connected\\ndata: ${JSON.stringify({ timestamp: Date.now() })}\\n\\n`);\n\n // Keepalive every 15 seconds\n const keepaliveInterval = setInterval(() => {\n try {\n res.write(`:keepalive ${Date.now()}\\n\\n`);\n } catch {\n clearInterval(keepaliveInterval);\n }\n }, 15000);\n\n req.on('close', () => {\n clearInterval(keepaliveInterval);\n removeClient(res);\n logger.info('WORKER', 'SSE client disconnected', { clients: getClients().length });\n });\n });\n\n return router;\n}\n", "/**\n * Router Observations: CRUD observations, batch, knowledge, memory save.\n */\n\nimport { Router } from 'express';\nimport type { WorkerContext } from '../worker-context.js';\nimport { isValidProject, isValidString, parseIntSafe } from '../worker-context.js';\nimport { getObservationsByProject, createObservation } from '../sqlite/Observations.js';\nimport { getSummariesByProject } from '../sqlite/Summaries.js';\nimport { getObservationsByIds } from '../sqlite/Search.js';\nimport { KNOWLEDGE_TYPES } from '../../types/worker-types.js';\nimport type { KnowledgeMetadata } from '../../types/worker-types.js';\nimport { logger } from '../../utils/logger.js';\n\nexport function createObservationsRouter(ctx: WorkerContext): Router {\n const router = Router();\n\n // Paginated observations list\n router.get('/api/observations', (req, res) => {\n const { offset, limit, project } = req.query as { offset?: string; limit?: string; project?: string };\n const _offset = parseIntSafe(offset, 0, 0, 1_000_000);\n const _limit = parseIntSafe(limit, 50, 1, 200);\n\n try {\n const countSql = project\n ? 'SELECT COUNT(*) as total FROM observations WHERE project = ?'\n : 'SELECT COUNT(*) as total FROM observations';\n const countStmt = ctx.db.db.query(countSql);\n const { total } = (project ? countStmt.get(project) : countStmt.get()) as { total: number };\n\n const sql = project\n ? 'SELECT * FROM observations WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ? OFFSET ?'\n : 'SELECT * FROM observations ORDER BY created_at_epoch DESC LIMIT ? OFFSET ?';\n const stmt = ctx.db.db.query(sql);\n const rows = project ? stmt.all(project, _limit, _offset) : stmt.all(_limit, _offset);\n res.setHeader('X-Total-Count', total);\n res.json(rows);\n } catch (error) {\n logger.error('WORKER', 'Observation list failed', {}, error as Error);\n res.status(500).json({ error: 'Failed to list observations' });\n }\n });\n\n // Create observation\n router.post('/api/observations', (req, res) => {\n const { memorySessionId, project, type, title, content, concepts, files } = req.body;\n\n if (!isValidProject(project)) {\n res.status(400).json({ error: 'Invalid or missing \"project\"' });\n return;\n }\n if (!isValidString(title, 500)) {\n res.status(400).json({ error: 'Invalid or missing \"title\" (max 500 chars)' });\n return;\n }\n if (content && !isValidString(content, 100_000)) {\n res.status(400).json({ error: '\"content\" too large (max 100KB)' });\n return;\n }\n if (concepts && !Array.isArray(concepts)) {\n res.status(400).json({ error: '\"concepts\" must be an array' });\n return;\n }\n if (files && !Array.isArray(files)) {\n res.status(400).json({ error: '\"files\" must be an array' });\n return;\n }\n\n try {\n const id = createObservation(\n ctx.db.db,\n memorySessionId || 'api-' + Date.now(),\n project,\n type || 'manual',\n title,\n null,\n content,\n null,\n null,\n concepts?.join(', ') || null,\n files?.join(', ') || null,\n null,\n 0\n );\n\n ctx.broadcast('observation-created', { id, project, title });\n ctx.invalidateProjectsCache();\n\n // Background embedding\n ctx.generateEmbeddingForObservation(id, title, content, concepts).catch(() => {});\n\n res.json({ id, success: true });\n } catch (error) {\n logger.error('WORKER', 'Observation creation failed', {}, error as Error);\n res.status(500).json({ error: 'Failed to store observation' });\n }\n });\n\n // Batch fetch observations by ID (max 100)\n router.post('/api/observations/batch', (req, res) => {\n const { ids } = req.body;\n\n if (!ids || !Array.isArray(ids) || ids.length === 0 || ids.length > 100) {\n res.status(400).json({ error: '\"ids\" must be an array of 1-100 elements' });\n return;\n }\n if (!ids.every((id: unknown) => typeof id === 'number' && Number.isInteger(id) && id > 0)) {\n res.status(400).json({ error: 'All IDs must be positive integers' });\n return;\n }\n\n try {\n const observations = getObservationsByIds(ctx.db.db, ids);\n res.json({ observations });\n } catch (error) {\n logger.error('WORKER', 'Batch fetch failed', { ids }, error as Error);\n res.status(500).json({ error: 'Batch fetch failed' });\n }\n });\n\n // Store structured knowledge\n router.post('/api/knowledge', (req, res) => {\n const { project, knowledge_type, title, content, concepts, files,\n severity, alternatives, reason, context: metaContext, confidence } = req.body;\n\n if (!isValidProject(project)) {\n res.status(400).json({ error: 'Invalid or missing \"project\"' });\n return;\n }\n if (!knowledge_type || !KNOWLEDGE_TYPES.includes(knowledge_type)) {\n res.status(400).json({ error: `Invalid \"knowledge_type\". Must be one of: ${KNOWLEDGE_TYPES.join(', ')}` });\n return;\n }\n if (!isValidString(title, 500)) {\n res.status(400).json({ error: 'Invalid or missing \"title\" (max 500 chars)' });\n return;\n }\n if (!isValidString(content, 100_000)) {\n res.status(400).json({ error: 'Invalid or missing \"content\" (max 100KB)' });\n return;\n }\n if (concepts && !Array.isArray(concepts)) {\n res.status(400).json({ error: '\"concepts\" must be an array' });\n return;\n }\n if (files && !Array.isArray(files)) {\n res.status(400).json({ error: '\"files\" must be an array' });\n return;\n }\n\n try {\n let metadata: KnowledgeMetadata;\n switch (knowledge_type) {\n case 'constraint':\n metadata = { knowledgeType: 'constraint', severity: severity === 'hard' ? 'hard' : 'soft', reason };\n break;\n case 'decision':\n metadata = { knowledgeType: 'decision', alternatives, reason };\n break;\n case 'heuristic':\n metadata = { knowledgeType: 'heuristic', context: metaContext, confidence: ['high', 'medium', 'low'].includes(confidence) ? confidence : undefined };\n break;\n case 'rejected':\n metadata = { knowledgeType: 'rejected', reason: reason || '', alternatives };\n break;\n default:\n res.status(400).json({ error: 'Invalid knowledge_type' });\n return;\n }\n\n const id = createObservation(\n ctx.db.db,\n 'api-' + Date.now(),\n project,\n knowledge_type,\n title,\n null,\n content,\n null,\n JSON.stringify(metadata),\n concepts?.join(', ') || null,\n files?.join(', ') || null,\n null,\n 0\n );\n\n ctx.broadcast('observation-created', { id, project, title, type: knowledge_type });\n ctx.generateEmbeddingForObservation(id, title, content, concepts).catch(() => {});\n\n res.json({ id, success: true, knowledge_type });\n } catch (error) {\n logger.error('WORKER', 'Knowledge save failed', {}, error as Error);\n res.status(500).json({ error: 'Failed to store knowledge' });\n }\n });\n\n // Save memory (programmable endpoint)\n router.post('/api/memory/save', (req, res) => {\n const { project, title, content, type, concepts } = req.body;\n\n if (!isValidProject(project)) {\n res.status(400).json({ error: 'Invalid or missing \"project\"' });\n return;\n }\n if (!isValidString(title, 500)) {\n res.status(400).json({ error: 'Invalid or missing \"title\" (max 500 chars)' });\n return;\n }\n if (!isValidString(content, 100_000)) {\n res.status(400).json({ error: 'Invalid or missing \"content\" (max 100KB)' });\n return;\n }\n\n const obsType = type || 'research';\n const conceptStr = Array.isArray(concepts) ? concepts.join(', ') : (concepts || null);\n\n try {\n const id = createObservation(\n ctx.db.db,\n 'memory-save-' + Date.now(),\n project,\n obsType,\n title,\n null,\n content,\n content,\n null,\n conceptStr,\n null,\n null,\n 0\n );\n\n ctx.broadcast('observation-created', { id, project, title });\n ctx.invalidateProjectsCache();\n ctx.generateEmbeddingForObservation(id, title, content, Array.isArray(concepts) ? concepts : undefined).catch(() => {});\n\n res.json({ id, success: true });\n } catch (error) {\n logger.error('WORKER', 'Memory save failed', {}, error as Error);\n res.status(500).json({ error: 'Failed to save memory' });\n }\n });\n\n // Context by project\n router.get('/api/context/:project', (req, res) => {\n const { project } = req.params;\n\n if (!isValidProject(project)) {\n res.status(400).json({ error: 'Invalid project name' });\n return;\n }\n\n try {\n const context = {\n project,\n observations: getObservationsByProject(ctx.db.db, project, 20),\n summaries: getSummariesByProject(ctx.db.db, project, 5)\n };\n res.json(context);\n } catch (error) {\n logger.error('WORKER', 'Context retrieval failed', { project }, error as Error);\n res.status(500).json({ error: 'Failed to get context' });\n }\n });\n\n return router;\n}\n", "import { Database } from 'bun:sqlite';\nimport type { Summary } from '../../types/worker-types.js';\n\n/**\n * Summary operations for Kiro Memory database\n */\n\n/** Escape dei caratteri wildcard LIKE per prevenire pattern injection */\nfunction escapeLikePattern(input: string): string {\n return input.replace(/[%_\\\\]/g, '\\\\$&');\n}\n\nexport function createSummary(\n db: Database,\n sessionId: string,\n project: string,\n request: string | null,\n investigated: string | null,\n learned: string | null,\n completed: string | null,\n nextSteps: string | null,\n notes: string | null\n): number {\n const now = new Date();\n const result = db.run(\n `INSERT INTO summaries \n (session_id, project, request, investigated, learned, completed, next_steps, notes, created_at, created_at_epoch)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [sessionId, project, request, investigated, learned, completed, nextSteps, notes, now.toISOString(), now.getTime()]\n );\n return Number(result.lastInsertRowid);\n}\n\nexport function getSummaryBySession(db: Database, sessionId: string): Summary | null {\n const query = db.query('SELECT * FROM summaries WHERE session_id = ? ORDER BY created_at_epoch DESC LIMIT 1');\n return query.get(sessionId) as Summary | null;\n}\n\nexport function getSummariesByProject(db: Database, project: string, limit: number = 50): Summary[] {\n const query = db.query(\n 'SELECT * FROM summaries WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ?'\n );\n return query.all(project, limit) as Summary[];\n}\n\nexport function searchSummaries(db: Database, searchTerm: string, project?: string): Summary[] {\n const sql = project\n ? `SELECT * FROM summaries\n WHERE project = ? AND (request LIKE ? ESCAPE '\\\\' OR learned LIKE ? ESCAPE '\\\\' OR completed LIKE ? ESCAPE '\\\\' OR notes LIKE ? ESCAPE '\\\\')\n ORDER BY created_at_epoch DESC`\n : `SELECT * FROM summaries\n WHERE request LIKE ? ESCAPE '\\\\' OR learned LIKE ? ESCAPE '\\\\' OR completed LIKE ? ESCAPE '\\\\' OR notes LIKE ? ESCAPE '\\\\'\n ORDER BY created_at_epoch DESC`;\n\n const pattern = `%${escapeLikePattern(searchTerm)}%`;\n const query = db.query(sql);\n\n if (project) {\n return query.all(project, pattern, pattern, pattern, pattern) as Summary[];\n }\n return query.all(pattern, pattern, pattern, pattern) as Summary[];\n}\n\nexport function deleteSummary(db: Database, id: number): void {\n db.run('DELETE FROM summaries WHERE id = ?', [id]);\n}\n", "/**\n * Shared types for Kiro Memory Worker Service\n */\n\n// ============================================================================\n// Pagination Types\n// ============================================================================\n\nexport interface PaginatedResult<T> {\n items: T[];\n hasMore: boolean;\n offset: number;\n limit: number;\n}\n\nexport interface PaginationParams {\n offset: number;\n limit: number;\n project?: string;\n}\n\n// ============================================================================\n// Database Record Types\n// ============================================================================\n\nexport interface Observation {\n id: number;\n memory_session_id: string;\n project: string;\n type: string;\n title: string;\n subtitle: string | null;\n text: string | null;\n narrative: string | null;\n facts: string | null;\n concepts: string | null;\n files_read: string | null;\n files_modified: string | null;\n prompt_number: number;\n created_at: string;\n created_at_epoch: number;\n last_accessed_epoch: number | null;\n is_stale: number; // 0 = fresh, 1 = file modified after the observation\n}\n\nexport interface Summary {\n id: number;\n session_id: string;\n project: string;\n request: string | null;\n investigated: string | null;\n learned: string | null;\n completed: string | null;\n next_steps: string | null;\n notes: string | null;\n created_at: string;\n created_at_epoch: number;\n}\n\nexport interface UserPrompt {\n id: number;\n content_session_id: string;\n project: string;\n prompt_number: number;\n prompt_text: string;\n created_at: string;\n created_at_epoch: number;\n}\n\nexport interface DBSession {\n id: number;\n content_session_id: string;\n project: string;\n user_prompt: string;\n memory_session_id: string | null;\n status: 'active' | 'completed' | 'failed';\n started_at: string;\n started_at_epoch: number;\n completed_at: string | null;\n completed_at_epoch: number | null;\n}\n\nexport interface DBCheckpoint {\n id: number;\n session_id: number;\n project: string;\n task: string;\n progress: string | null;\n next_steps: string | null;\n open_questions: string | null;\n relevant_files: string | null;\n context_snapshot: string | null;\n created_at: string;\n created_at_epoch: number;\n}\n\n// ============================================================================\n// Report Types\n// ============================================================================\n\nexport interface ReportData {\n period: {\n start: string;\n end: string;\n days: number;\n label: string;\n };\n overview: {\n observations: number;\n summaries: number;\n sessions: number;\n prompts: number;\n knowledgeCount: number;\n staleCount: number;\n };\n timeline: Array<{ day: string; count: number }>;\n typeDistribution: Array<{ type: string; count: number }>;\n sessionStats: {\n total: number;\n completed: number;\n avgDurationMinutes: number;\n };\n topLearnings: string[];\n completedTasks: string[];\n nextSteps: string[];\n fileHotspots: Array<{ file: string; count: number }>;\n}\n\n// ============================================================================\n// Kiro Integration Types\n// ============================================================================\n\nexport interface KiroMessage {\n role: 'user' | 'assistant' | 'system';\n content: string;\n timestamp?: number;\n}\n\nexport interface KiroSession {\n id: string;\n project: string;\n messages: KiroMessage[];\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface ContextContext {\n project: string;\n relevantObservations: Observation[];\n relevantSummaries: Summary[];\n recentPrompts: UserPrompt[];\n}\n\n// ============================================================================\n// Kiro CLI Hook Types\n// ============================================================================\n\n/**\n * Input JSON received via stdin from Kiro CLI / Claude Code hooks\n *\n * Fields common to all hooks:\n * - session_id, cwd, hook_event_name\n *\n * Hook-specific fields:\n * - UserPromptSubmit: prompt (user text, top-level)\n * - PostToolUse: tool_name, tool_input, tool_response, tool_use_id\n * - Stop: stop_hook_active, transcript_path\n * - SessionStart/agentSpawn: transcript_path\n */\nexport interface KiroHookInput {\n hook_event_name: string;\n session_id?: string;\n cwd: string;\n transcript_path?: string;\n permission_mode?: string;\n\n // UserPromptSubmit: the prompt is top-level, NOT in tool_input\n prompt?: string;\n user_prompt?: string;\n\n // PostToolUse / PreToolUse\n tool_name?: string;\n tool_input?: any;\n tool_response?: any;\n tool_use_id?: string;\n\n // Stop\n stop_hook_active?: boolean;\n\n // Catch-all for fields not yet mapped\n [key: string]: any;\n}\n\n// ============================================================================\n// Search Types\n// ============================================================================\n\nexport interface SearchFilters {\n project?: string;\n type?: string;\n dateStart?: number;\n dateEnd?: number;\n limit?: number;\n}\n\nexport interface SearchResult {\n observations: Observation[];\n summaries: Summary[];\n total: number;\n}\n\nexport interface TimelineEntry {\n id: number;\n type: 'observation' | 'summary' | 'session';\n title: string;\n content: string | null;\n project: string;\n created_at: string;\n created_at_epoch: number;\n}\n\n// ============================================================================\n// Smart Ranking Types (Phase 2B)\n// ============================================================================\n\n/** Weights for the 4 scoring signals */\nexport interface ScoringWeights {\n semantic: number;\n fts5: number;\n recency: number;\n projectMatch: number;\n}\n\n/** Item with composite score and individual signals */\nexport interface ScoredItem {\n id: number;\n title: string;\n content: string;\n type: string;\n project: string;\n created_at: string;\n created_at_epoch: number;\n score: number;\n signals: {\n semantic: number;\n fts5: number;\n recency: number;\n projectMatch: number;\n };\n}\n\n/** Smart context with token budget */\nexport interface SmartContext {\n project: string;\n items: ScoredItem[];\n summaries: Summary[];\n tokenBudget: number;\n tokensUsed: number;\n}\n\n// ============================================================================\n// Structured Knowledge Types (Phase 5A)\n// ============================================================================\n\n/** Structured knowledge types */\nexport type KnowledgeType = 'constraint' | 'decision' | 'heuristic' | 'rejected';\n\n/** Constant for runtime validation */\nexport const KNOWLEDGE_TYPES: KnowledgeType[] = ['constraint', 'decision', 'heuristic', 'rejected'];\n\n/** Metadata for constraints (hard/soft rules) */\nexport interface ConstraintMeta {\n knowledgeType: 'constraint';\n severity: 'hard' | 'soft';\n reason?: string;\n}\n\n/** Metadata for architectural decisions */\nexport interface DecisionMeta {\n knowledgeType: 'decision';\n alternatives?: string[];\n reason?: string;\n}\n\n/** Metadata for preferences/heuristics */\nexport interface HeuristicMeta {\n knowledgeType: 'heuristic';\n context?: string;\n confidence?: 'high' | 'medium' | 'low';\n}\n\n/** Metadata for rejected solutions */\nexport interface RejectedMeta {\n knowledgeType: 'rejected';\n reason: string;\n alternatives?: string[];\n}\n\n/** Discriminated union for knowledge metadata */\nexport type KnowledgeMetadata = ConstraintMeta | DecisionMeta | HeuristicMeta | RejectedMeta;\n\n/** Input for storing structured knowledge */\nexport interface StoreKnowledgeInput {\n project: string;\n knowledgeType: KnowledgeType;\n title: string;\n content: string;\n concepts?: string[];\n files?: string[];\n /** Type-specific metadata (severity, alternatives, reason, context, confidence) */\n metadata?: Partial<Omit<ConstraintMeta, 'knowledgeType'>> &\n Partial<Omit<DecisionMeta, 'knowledgeType'>> &\n Partial<Omit<HeuristicMeta, 'knowledgeType'>> &\n Partial<Omit<RejectedMeta, 'knowledgeType'>>;\n}\n", "/**\n * Router Summaries: session summary CRUD.\n */\n\nimport { Router } from 'express';\nimport type { WorkerContext } from '../worker-context.js';\nimport { isValidProject, isValidString, parseIntSafe } from '../worker-context.js';\nimport { createSummary } from '../sqlite/Summaries.js';\nimport { logger } from '../../utils/logger.js';\n\nexport function createSummariesRouter(ctx: WorkerContext): Router {\n const router = Router();\n\n // Paginated summary list\n router.get('/api/summaries', (req, res) => {\n const { offset, limit, project } = req.query as { offset?: string; limit?: string; project?: string };\n const _offset = parseIntSafe(offset, 0, 0, 1_000_000);\n const _limit = parseIntSafe(limit, 20, 1, 200);\n\n try {\n const countSql = project\n ? 'SELECT COUNT(*) as total FROM summaries WHERE project = ?'\n : 'SELECT COUNT(*) as total FROM summaries';\n const countStmt = ctx.db.db.query(countSql);\n const { total } = (project ? countStmt.get(project) : countStmt.get()) as { total: number };\n\n const sql = project\n ? 'SELECT * FROM summaries WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ? OFFSET ?'\n : 'SELECT * FROM summaries ORDER BY created_at_epoch DESC LIMIT ? OFFSET ?';\n const stmt = ctx.db.db.query(sql);\n const rows = project ? stmt.all(project, _limit, _offset) : stmt.all(_limit, _offset);\n res.setHeader('X-Total-Count', total);\n res.json(rows);\n } catch (error) {\n logger.error('WORKER', 'Summary list failed', {}, error as Error);\n res.status(500).json({ error: 'Failed to list summaries' });\n }\n });\n\n // Create summary\n router.post('/api/summaries', (req, res) => {\n const { sessionId, project, request, learned, completed, nextSteps } = req.body;\n\n if (!isValidProject(project)) {\n res.status(400).json({ error: 'Invalid or missing \"project\"' });\n return;\n }\n const MAX_FIELD = 50_000;\n if (request && !isValidString(request, MAX_FIELD)) { res.status(400).json({ error: '\"request\" too large' }); return; }\n if (learned && !isValidString(learned, MAX_FIELD)) { res.status(400).json({ error: '\"learned\" too large' }); return; }\n if (completed && !isValidString(completed, MAX_FIELD)) { res.status(400).json({ error: '\"completed\" too large' }); return; }\n if (nextSteps && !isValidString(nextSteps, MAX_FIELD)) { res.status(400).json({ error: '\"nextSteps\" too large' }); return; }\n\n try {\n const id = createSummary(\n ctx.db.db,\n sessionId || 'api-' + Date.now(),\n project,\n request || null,\n null,\n learned || null,\n completed || null,\n nextSteps || null,\n null\n );\n\n ctx.broadcast('summary-created', { id, project });\n res.json({ id, success: true });\n } catch (error) {\n logger.error('WORKER', 'Summary creation failed', {}, error as Error);\n res.status(500).json({ error: 'Failed to store summary' });\n }\n });\n\n return router;\n}\n", "/**\n * Router Search: FTS5 search, hybrid search, timeline.\n */\n\nimport { Router } from 'express';\nimport type { WorkerContext } from '../worker-context.js';\nimport { parseIntSafe } from '../worker-context.js';\nimport { searchObservationsFTS, searchSummariesFiltered, getTimeline } from '../sqlite/Search.js';\nimport { getHybridSearch } from '../search/HybridSearch.js';\nimport { logger } from '../../utils/logger.js';\n\nexport function createSearchRouter(ctx: WorkerContext): Router {\n const router = Router();\n\n // FTS5 search with filters\n router.get('/api/search', (req, res) => {\n const { q, project, type, limit } = req.query as { q: string; project?: string; type?: string; limit?: string };\n\n if (!q) {\n res.status(400).json({ error: 'Query parameter \"q\" is required' });\n return;\n }\n\n try {\n const filters = {\n project: project || undefined,\n type: type || undefined,\n limit: parseIntSafe(limit, 20, 1, 100)\n };\n\n const results = {\n observations: searchObservationsFTS(ctx.db.db, q, filters),\n summaries: searchSummariesFiltered(ctx.db.db, q, filters)\n };\n\n res.json(results);\n } catch (error) {\n logger.error('WORKER', 'Search failed', { query: q }, error as Error);\n res.status(500).json({ error: 'Search failed' });\n }\n });\n\n // Hybrid search (vector + keyword)\n router.get('/api/hybrid-search', async (req, res) => {\n const { q, project, limit } = req.query as { q: string; project?: string; limit?: string };\n\n if (!q) {\n res.status(400).json({ error: 'Query parameter \"q\" is required' });\n return;\n }\n\n try {\n const hybridSearch = getHybridSearch();\n const results = await hybridSearch.search(ctx.db.db, q, {\n project: project || undefined,\n limit: parseIntSafe(limit, 10, 1, 100)\n });\n\n res.json({ results, count: results.length });\n } catch (error) {\n logger.error('WORKER', 'Hybrid search failed', { query: q }, error as Error);\n res.status(500).json({ error: 'Hybrid search failed' });\n }\n });\n\n // Timeline: chronological context around an observation\n router.get('/api/timeline', (req, res) => {\n const { anchor, depth_before, depth_after } = req.query as { anchor: string; depth_before?: string; depth_after?: string };\n\n if (!anchor) {\n res.status(400).json({ error: 'Query parameter \"anchor\" is required' });\n return;\n }\n\n const anchorId = parseIntSafe(anchor, 0, 1, Number.MAX_SAFE_INTEGER);\n if (anchorId === 0) {\n res.status(400).json({ error: 'Invalid \"anchor\" (must be positive integer)' });\n return;\n }\n\n try {\n const timeline = getTimeline(\n ctx.db.db,\n anchorId,\n parseIntSafe(depth_before, 5, 1, 50),\n parseIntSafe(depth_after, 5, 1, 50)\n );\n\n res.json({ timeline });\n } catch (error) {\n logger.error('WORKER', 'Timeline failed', { anchor }, error as Error);\n res.status(500).json({ error: 'Timeline failed' });\n }\n });\n\n return router;\n}\n", "/**\n * Router Analytics: overview, timeline, type distribution, sessions.\n */\n\nimport { Router } from 'express';\nimport type { WorkerContext } from '../worker-context.js';\nimport { isValidProject, parseIntSafe } from '../worker-context.js';\nimport { getObservationsTimeline, getTypeDistribution, getSessionStats, getAnalyticsOverview } from '../sqlite/Analytics.js';\nimport { logger } from '../../utils/logger.js';\n\nexport function createAnalyticsRouter(ctx: WorkerContext): Router {\n const router = Router();\n\n router.get('/api/analytics/overview', (req, res) => {\n const { project } = req.query as { project?: string };\n\n if (project && !isValidProject(project)) {\n res.status(400).json({ error: 'Invalid project name' });\n return;\n }\n\n try {\n const overview = getAnalyticsOverview(ctx.db.db, project || undefined);\n res.json(overview);\n } catch (error) {\n logger.error('WORKER', 'Analytics overview failed', { project }, error as Error);\n res.status(500).json({ error: 'Analytics overview failed' });\n }\n });\n\n router.get('/api/analytics/timeline', (req, res) => {\n const { project, days } = req.query as { project?: string; days?: string };\n\n if (project && !isValidProject(project)) {\n res.status(400).json({ error: 'Invalid project name' });\n return;\n }\n\n try {\n const timeline = getObservationsTimeline(\n ctx.db.db,\n project || undefined,\n parseIntSafe(days, 30, 1, 365)\n );\n res.json(timeline);\n } catch (error) {\n logger.error('WORKER', 'Analytics timeline failed', { project }, error as Error);\n res.status(500).json({ error: 'Analytics timeline failed' });\n }\n });\n\n router.get('/api/analytics/types', (req, res) => {\n const { project } = req.query as { project?: string };\n\n if (project && !isValidProject(project)) {\n res.status(400).json({ error: 'Invalid project name' });\n return;\n }\n\n try {\n const distribution = getTypeDistribution(ctx.db.db, project || undefined);\n res.json(distribution);\n } catch (error) {\n logger.error('WORKER', 'Analytics types failed', { project }, error as Error);\n res.status(500).json({ error: 'Analytics types failed' });\n }\n });\n\n router.get('/api/analytics/sessions', (req, res) => {\n const { project } = req.query as { project?: string };\n\n if (project && !isValidProject(project)) {\n res.status(400).json({ error: 'Invalid project name' });\n return;\n }\n\n try {\n const stats = getSessionStats(ctx.db.db, project || undefined);\n res.json(stats);\n } catch (error) {\n logger.error('WORKER', 'Analytics sessions failed', { project }, error as Error);\n res.status(500).json({ error: 'Analytics sessions failed' });\n }\n });\n\n return router;\n}\n", "import { Database } from 'bun:sqlite';\n\n/**\n * Analytics module for Kiro Memory.\n * Aggregate queries for metrics dashboard.\n */\n\n// ============================================================================\n// Return types\n// ============================================================================\n\nexport interface TimelineDayEntry {\n day: string;\n count: number;\n}\n\nexport interface TypeDistributionEntry {\n type: string;\n count: number;\n}\n\nexport interface SessionStatsResult {\n total: number;\n completed: number;\n avgDurationMinutes: number;\n}\n\nexport interface TokenEconomicsResult {\n discoveryTokens: number;\n readTokens: number;\n savings: number;\n reductionPct: number;\n}\n\nexport interface AnalyticsOverviewResult {\n observations: number;\n summaries: number;\n sessions: number;\n prompts: number;\n observationsToday: number;\n observationsThisWeek: number;\n staleCount: number;\n knowledgeCount: number;\n tokenEconomics: TokenEconomicsResult;\n}\n\n// ============================================================================\n// Query functions\n// ============================================================================\n\n/**\n * Observations per day (last N days).\n * Returns array sorted chronologically (oldest to most recent).\n */\nexport function getObservationsTimeline(\n db: Database,\n project?: string,\n days: number = 30\n): TimelineDayEntry[] {\n const cutoffEpoch = Date.now() - (days * 24 * 60 * 60 * 1000);\n\n const sql = project\n ? `SELECT DATE(datetime(created_at_epoch / 1000, 'unixepoch')) as day, COUNT(*) as count\n FROM observations\n WHERE project = ? AND created_at_epoch >= ?\n GROUP BY day\n ORDER BY day ASC`\n : `SELECT DATE(datetime(created_at_epoch / 1000, 'unixepoch')) as day, COUNT(*) as count\n FROM observations\n WHERE created_at_epoch >= ?\n GROUP BY day\n ORDER BY day ASC`;\n\n const stmt = db.query(sql);\n const rows = project\n ? stmt.all(project, cutoffEpoch) as TimelineDayEntry[]\n : stmt.all(cutoffEpoch) as TimelineDayEntry[];\n\n return rows;\n}\n\n/**\n * Observation distribution by type.\n * Returns array sorted by count descending.\n */\nexport function getTypeDistribution(\n db: Database,\n project?: string\n): TypeDistributionEntry[] {\n const sql = project\n ? `SELECT type, COUNT(*) as count\n FROM observations\n WHERE project = ?\n GROUP BY type\n ORDER BY count DESC`\n : `SELECT type, COUNT(*) as count\n FROM observations\n GROUP BY type\n ORDER BY count DESC`;\n\n const stmt = db.query(sql);\n const rows = project\n ? stmt.all(project) as TypeDistributionEntry[]\n : stmt.all() as TypeDistributionEntry[];\n\n return rows;\n}\n\n/**\n * Session statistics: total, completed, average duration.\n * Single query with conditional aggregation replacing 3 separate queries.\n */\nexport function getSessionStats(\n db: Database,\n project?: string\n): SessionStatsResult {\n const projectFilter = project ? 'WHERE project = ?' : '';\n\n const sql = `\n SELECT\n COUNT(*) as total,\n COUNT(CASE WHEN status = 'completed' THEN 1 END) as completed,\n AVG(CASE\n WHEN status = 'completed' AND completed_at_epoch IS NOT NULL AND completed_at_epoch > started_at_epoch\n THEN (completed_at_epoch - started_at_epoch) / 1000.0 / 60.0\n END) as avg_min\n FROM sessions\n ${projectFilter}\n `;\n\n const row = project\n ? db.query(sql).get(project) as any\n : db.query(sql).get() as any;\n\n return {\n total: row?.total || 0,\n completed: row?.completed || 0,\n avgDurationMinutes: Math.round((row?.avg_min || 0) * 10) / 10,\n };\n}\n\n/**\n * General overview: base counts + daily/weekly trends.\n * Single CTE query replacing the 10 separate queries (fix N+1).\n */\nexport function getAnalyticsOverview(\n db: Database,\n project?: string\n): AnalyticsOverviewResult {\n const now = Date.now();\n const todayStart = now - (now % (24 * 60 * 60 * 1000)); // Start of day UTC\n const weekStart = now - (7 * 24 * 60 * 60 * 1000);\n\n // Single CTE query: 10 counts in a single DB roundtrip\n const projectFilter = project ? 'WHERE project = @project' : '';\n const obsProjectFilter = project ? 'WHERE project = @project' : '';\n\n const sql = `\n WITH\n obs_stats AS (\n SELECT\n COUNT(*) as total,\n COUNT(CASE WHEN created_at_epoch >= @todayStart THEN 1 END) as today,\n COUNT(CASE WHEN created_at_epoch >= @weekStart THEN 1 END) as this_week,\n COUNT(CASE WHEN is_stale = 1 THEN 1 END) as stale,\n COUNT(CASE WHEN type IN ('constraint', 'decision', 'heuristic', 'rejected') THEN 1 END) as knowledge,\n COALESCE(SUM(discovery_tokens), 0) as discovery_tokens,\n COALESCE(SUM(CAST((LENGTH(COALESCE(title, '')) + LENGTH(COALESCE(narrative, ''))) / 4 AS INTEGER)), 0) as read_tokens\n FROM observations\n ${obsProjectFilter}\n ),\n sum_count AS (\n SELECT COUNT(*) as total FROM summaries ${projectFilter}\n ),\n sess_count AS (\n SELECT COUNT(*) as total FROM sessions ${projectFilter}\n ),\n prompt_count AS (\n SELECT COUNT(*) as total FROM prompts ${projectFilter}\n )\n SELECT\n obs_stats.total as observations,\n obs_stats.today as observations_today,\n obs_stats.this_week as observations_this_week,\n obs_stats.stale as stale_count,\n obs_stats.knowledge as knowledge_count,\n obs_stats.discovery_tokens,\n obs_stats.read_tokens,\n sum_count.total as summaries,\n sess_count.total as sessions,\n prompt_count.total as prompts\n FROM obs_stats, sum_count, sess_count, prompt_count\n `;\n\n const params: Record<string, any> = {\n '@todayStart': todayStart,\n '@weekStart': weekStart\n };\n if (project) {\n params['@project'] = project;\n }\n\n const row = db.query(sql).get(params) as any;\n\n const discoveryTokens = row?.discovery_tokens || 0;\n const readTokens = row?.read_tokens || 0;\n const savings = Math.max(0, discoveryTokens - readTokens);\n const reductionPct = discoveryTokens > 0 ? Math.round((1 - readTokens / discoveryTokens) * 100) : 0;\n\n return {\n observations: row?.observations || 0,\n summaries: row?.summaries || 0,\n sessions: row?.sessions || 0,\n prompts: row?.prompts || 0,\n observationsToday: row?.observations_today || 0,\n observationsThisWeek: row?.observations_this_week || 0,\n staleCount: row?.stale_count || 0,\n knowledgeCount: row?.knowledge_count || 0,\n tokenEconomics: { discoveryTokens, readTokens, savings, reductionPct }\n };\n}\n", "/**\n * Router Sessions: session list, checkpoints, prompts.\n */\n\nimport { Router } from 'express';\nimport type { WorkerContext } from '../worker-context.js';\nimport { isValidProject, parseIntSafe } from '../worker-context.js';\nimport { getSessionsByProject, getAllSessions } from '../sqlite/Sessions.js';\nimport { getLatestCheckpoint, getLatestCheckpointByProject } from '../sqlite/Checkpoints.js';\nimport { logger } from '../../utils/logger.js';\n\nexport function createSessionsRouter(ctx: WorkerContext): Router {\n const router = Router();\n\n // Session list\n router.get('/api/sessions', (req, res) => {\n const { project } = req.query as { project?: string };\n\n if (project && !isValidProject(project)) {\n res.status(400).json({ error: 'Invalid project name' });\n return;\n }\n\n try {\n const sessions = project\n ? getSessionsByProject(ctx.db.db, project, 50)\n : getAllSessions(ctx.db.db, 50);\n res.json(sessions);\n } catch (error) {\n logger.error('WORKER', 'Session list failed', { project }, error as Error);\n res.status(500).json({ error: 'Sessions list failed' });\n }\n });\n\n // Checkpoint by session\n router.get('/api/sessions/:id/checkpoint', (req, res) => {\n const sessionId = parseInt(req.params.id, 10);\n\n if (isNaN(sessionId) || sessionId <= 0) {\n res.status(400).json({ error: 'Invalid session ID' });\n return;\n }\n\n try {\n const checkpoint = getLatestCheckpoint(ctx.db.db, sessionId);\n if (!checkpoint) {\n res.status(404).json({ error: 'No checkpoint found for this session' });\n return;\n }\n res.json(checkpoint);\n } catch (error) {\n logger.error('WORKER', 'Checkpoint fetch failed', { sessionId }, error as Error);\n res.status(500).json({ error: 'Checkpoint fetch failed' });\n }\n });\n\n // Checkpoint by project\n router.get('/api/checkpoint', (req, res) => {\n const { project } = req.query as { project?: string };\n\n if (!project) {\n res.status(400).json({ error: 'Project parameter is required' });\n return;\n }\n if (!isValidProject(project)) {\n res.status(400).json({ error: 'Invalid project name' });\n return;\n }\n\n try {\n const checkpoint = getLatestCheckpointByProject(ctx.db.db, project);\n if (!checkpoint) {\n res.status(404).json({ error: 'No checkpoint found for this project' });\n return;\n }\n res.json(checkpoint);\n } catch (error) {\n logger.error('WORKER', 'Project checkpoint fetch failed', { project }, error as Error);\n res.status(500).json({ error: 'Project checkpoint fetch failed' });\n }\n });\n\n // Paginated prompt list\n router.get('/api/prompts', (req, res) => {\n const { offset, limit, project } = req.query as { offset?: string; limit?: string; project?: string };\n const _offset = parseIntSafe(offset, 0, 0, 1_000_000);\n const _limit = parseIntSafe(limit, 20, 1, 200);\n\n try {\n const countSql = project\n ? 'SELECT COUNT(*) as total FROM prompts WHERE project = ?'\n : 'SELECT COUNT(*) as total FROM prompts';\n const countStmt = ctx.db.db.query(countSql);\n const { total } = (project ? countStmt.get(project) : countStmt.get()) as { total: number };\n\n const sql = project\n ? 'SELECT * FROM prompts WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ? OFFSET ?'\n : 'SELECT * FROM prompts ORDER BY created_at_epoch DESC LIMIT ? OFFSET ?';\n const stmt = ctx.db.db.query(sql);\n const rows = project ? stmt.all(project, _limit, _offset) : stmt.all(_limit, _offset);\n res.setHeader('X-Total-Count', total);\n res.json(rows);\n } catch (error) {\n logger.error('WORKER', 'Prompt list failed', {}, error as Error);\n res.status(500).json({ error: 'Failed to list prompts' });\n }\n });\n\n return router;\n}\n", "import { Database } from 'bun:sqlite';\nimport type { DBSession } from '../../types/worker-types.js';\n\n/**\n * Session operations for Kiro Memory database\n */\n\nexport function createSession(\n db: Database,\n contentSessionId: string,\n project: string,\n userPrompt: string\n): number {\n const now = new Date();\n const result = db.run(\n `INSERT INTO sessions (content_session_id, project, user_prompt, status, started_at, started_at_epoch)\n VALUES (?, ?, ?, 'active', ?, ?)`,\n [contentSessionId, project, userPrompt, now.toISOString(), now.getTime()]\n );\n return Number(result.lastInsertRowid);\n}\n\nexport function getSessionByContentId(db: Database, contentSessionId: string): DBSession | null {\n const query = db.query('SELECT * FROM sessions WHERE content_session_id = ?');\n return query.get(contentSessionId) as DBSession | null;\n}\n\nexport function getSessionById(db: Database, id: number): DBSession | null {\n const query = db.query('SELECT * FROM sessions WHERE id = ?');\n return query.get(id) as DBSession | null;\n}\n\nexport function updateSessionMemoryId(\n db: Database,\n id: number,\n memorySessionId: string\n): void {\n db.run(\n 'UPDATE sessions SET memory_session_id = ? WHERE id = ?',\n [memorySessionId, id]\n );\n}\n\nexport function completeSession(db: Database, id: number): void {\n const now = new Date();\n db.run(\n `UPDATE sessions \n SET status = 'completed', completed_at = ?, completed_at_epoch = ?\n WHERE id = ?`,\n [now.toISOString(), now.getTime(), id]\n );\n}\n\nexport function failSession(db: Database, id: number): void {\n const now = new Date();\n db.run(\n `UPDATE sessions \n SET status = 'failed', completed_at = ?, completed_at_epoch = ?\n WHERE id = ?`,\n [now.toISOString(), now.getTime(), id]\n );\n}\n\nexport function getActiveSessions(db: Database): DBSession[] {\n const query = db.query('SELECT * FROM sessions WHERE status = \\'active\\' ORDER BY started_at_epoch DESC');\n return query.all() as DBSession[];\n}\n\nexport function getAllSessions(db: Database, limit: number = 100): DBSession[] {\n const query = db.query('SELECT * FROM sessions ORDER BY started_at_epoch DESC LIMIT ?');\n return query.all(limit) as DBSession[];\n}\n\nexport function getSessionsByProject(db: Database, project: string, limit: number = 100): DBSession[] {\n const query = db.query('SELECT * FROM sessions WHERE project = ? ORDER BY started_at_epoch DESC LIMIT ?');\n return query.all(project, limit) as DBSession[];\n}\n", "import { Database } from 'bun:sqlite';\nimport type { DBCheckpoint } from '../../types/worker-types.js';\n\n/**\n * Checkpoint operations per Kiro Memory database.\n * I checkpoint salvano uno snapshot strutturato della sessione per resume futuro.\n */\n\nexport function createCheckpoint(\n db: Database,\n sessionId: number,\n project: string,\n data: {\n task: string;\n progress?: string;\n nextSteps?: string;\n openQuestions?: string;\n relevantFiles?: string;\n contextSnapshot?: string;\n }\n): number {\n const now = new Date();\n const result = db.run(\n `INSERT INTO checkpoints (session_id, project, task, progress, next_steps, open_questions, relevant_files, context_snapshot, created_at, created_at_epoch)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n sessionId,\n project,\n data.task,\n data.progress || null,\n data.nextSteps || null,\n data.openQuestions || null,\n data.relevantFiles || null,\n data.contextSnapshot || null,\n now.toISOString(),\n now.getTime()\n ]\n );\n return Number(result.lastInsertRowid);\n}\n\nexport function getLatestCheckpoint(db: Database, sessionId: number): DBCheckpoint | null {\n const query = db.query(\n 'SELECT * FROM checkpoints WHERE session_id = ? ORDER BY created_at_epoch DESC LIMIT 1'\n );\n return query.get(sessionId) as DBCheckpoint | null;\n}\n\nexport function getLatestCheckpointByProject(db: Database, project: string): DBCheckpoint | null {\n const query = db.query(\n 'SELECT * FROM checkpoints WHERE project = ? ORDER BY created_at_epoch DESC LIMIT 1'\n );\n return query.get(project) as DBCheckpoint | null;\n}\n\nexport function getCheckpointsBySession(db: Database, sessionId: number): DBCheckpoint[] {\n const query = db.query(\n 'SELECT * FROM checkpoints WHERE session_id = ? ORDER BY created_at_epoch DESC'\n );\n return query.all(sessionId) as DBCheckpoint[];\n}\n", "/**\n * Router Projects: project list, aliases, project statistics.\n */\n\nimport { Router } from 'express';\nimport type { WorkerContext } from '../worker-context.js';\nimport { isValidProject } from '../worker-context.js';\nimport { projectsCache, PROJECTS_CACHE_TTL } from '../worker-context.js';\nimport { getProjectStats } from '../sqlite/Search.js';\nimport { logger } from '../../utils/logger.js';\n\nexport function createProjectsRouter(ctx: WorkerContext): Router {\n const router = Router();\n\n // Distinct project list (with 60s cache TTL)\n router.get('/api/projects', (_req, res) => {\n try {\n const now = Date.now();\n if (now - projectsCache.ts < PROJECTS_CACHE_TTL && projectsCache.data.length > 0) {\n res.json(projectsCache.data);\n return;\n }\n\n const stmt = ctx.db.db.query(\n `SELECT DISTINCT project FROM (\n SELECT project FROM observations\n UNION\n SELECT project FROM summaries\n UNION\n SELECT project FROM prompts\n ) ORDER BY project ASC`\n );\n const rows = stmt.all() as { project: string }[];\n projectsCache.data = rows.map(r => r.project);\n projectsCache.ts = now;\n res.json(projectsCache.data);\n } catch (error) {\n logger.error('WORKER', 'Project list failed', {}, error as Error);\n res.status(500).json({ error: 'Failed to list projects' });\n }\n });\n\n // GET project aliases\n router.get('/api/project-aliases', (_req, res) => {\n try {\n const stmt = ctx.db.db.query('SELECT project_name, display_name FROM project_aliases');\n const rows = stmt.all() as { project_name: string; display_name: string }[];\n const aliases: Record<string, string> = {};\n for (const row of rows) {\n aliases[row.project_name] = row.display_name;\n }\n res.json(aliases);\n } catch (error) {\n logger.error('WORKER', 'Alias list failed', {}, error as Error);\n res.status(500).json({ error: 'Failed to list project aliases' });\n }\n });\n\n // PUT project alias (create or update)\n router.put('/api/project-aliases/:project', (req, res) => {\n const { project } = req.params;\n const { displayName } = req.body;\n\n if (!isValidProject(project)) {\n res.status(400).json({ error: 'Invalid project name' });\n return;\n }\n if (!displayName || typeof displayName !== 'string' || displayName.trim().length === 0 || displayName.length > 100) {\n res.status(400).json({ error: 'Field \"displayName\" is required (string, max 100 chars)' });\n return;\n }\n\n try {\n const now = new Date().toISOString();\n const stmt = ctx.db.db.query(`\n INSERT INTO project_aliases (project_name, display_name, created_at, updated_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT(project_name) DO UPDATE SET display_name = excluded.display_name, updated_at = excluded.updated_at\n `);\n stmt.run(project, displayName.trim(), now, now);\n res.json({ ok: true, project_name: project, display_name: displayName.trim() });\n } catch (error) {\n logger.error('WORKER', 'Alias update failed', { project }, error as Error);\n res.status(500).json({ error: 'Failed to update project alias' });\n }\n });\n\n // Project statistics\n router.get('/api/stats/:project', (req, res) => {\n const { project } = req.params;\n\n if (!isValidProject(project)) {\n res.status(400).json({ error: 'Invalid project name' });\n return;\n }\n\n try {\n const stats = getProjectStats(ctx.db.db, project);\n res.json(stats);\n } catch (error) {\n logger.error('WORKER', 'Stats failed', { project }, error as Error);\n res.status(500).json({ error: 'Stats failed' });\n }\n });\n\n return router;\n}\n", "/**\n * Router Data: embeddings, retention, export, report.\n * Handles heavy data operations and maintenance.\n */\n\nimport { Router } from 'express';\nimport type { WorkerContext } from '../worker-context.js';\nimport { isValidProject, parseIntSafe } from '../worker-context.js';\nimport { getEmbeddingService } from '../search/EmbeddingService.js';\nimport { getVectorSearch } from '../search/VectorSearch.js';\nimport { getReportData } from '../sqlite/Reports.js';\nimport { formatReportMarkdown } from '../report-formatter.js';\nimport { logger } from '../../utils/logger.js';\n\nexport function createDataRouter(ctx: WorkerContext, workerToken?: string): Router {\n const router = Router();\n\n /** Middleware: requires X-Worker-Token for destructive endpoints */\n function requireAuth(req: import('express').Request, res: import('express').Response, next: import('express').NextFunction): void {\n if (!workerToken) { next(); return; } // No token configured, skip\n const token = req.headers['x-worker-token'] as string;\n if (token !== workerToken) {\n res.status(401).json({ error: 'Invalid or missing X-Worker-Token' });\n return;\n }\n next();\n }\n\n // \u2500\u2500 Embeddings \u2500\u2500\n\n // Backfill embeddings for observations without embeddings\n router.post('/api/embeddings/backfill', requireAuth, async (req, res) => {\n const { batchSize } = req.body || {};\n\n try {\n const vectorSearch = getVectorSearch();\n const count = await vectorSearch.backfillEmbeddings(\n ctx.db.db,\n parseIntSafe(String(batchSize), 50, 1, 500)\n );\n res.json({ success: true, generated: count });\n } catch (error) {\n logger.error('WORKER', 'Backfill embeddings failed', {}, error as Error);\n res.status(500).json({ error: 'Backfill failed' });\n }\n });\n\n // Embedding statistics\n router.get('/api/embeddings/stats', (_req, res) => {\n try {\n const vectorSearch = getVectorSearch();\n const stats = vectorSearch.getStats(ctx.db.db);\n const embeddingService = getEmbeddingService();\n\n res.json({\n ...stats,\n provider: embeddingService.getProvider(),\n dimensions: embeddingService.getDimensions(),\n available: embeddingService.isAvailable()\n });\n } catch (error) {\n logger.error('WORKER', 'Embedding stats failed', {}, error as Error);\n res.status(500).json({ error: 'Stats failed' });\n }\n });\n\n // \u2500\u2500 Retention Policy \u2500\u2500\n\n router.post('/api/retention/cleanup', requireAuth, (req, res) => {\n const { maxAgeDays, dryRun } = req.body || {};\n const days = parseIntSafe(String(maxAgeDays), 90, 7, 730);\n const threshold = Date.now() - (days * 86_400_000);\n\n try {\n if (dryRun) {\n const obsCount = (ctx.db.db.query('SELECT COUNT(*) as c FROM observations WHERE created_at_epoch < ?').get(threshold) as { c: number }).c;\n const sumCount = (ctx.db.db.query('SELECT COUNT(*) as c FROM summaries WHERE created_at_epoch < ?').get(threshold) as { c: number }).c;\n const promptCount = (ctx.db.db.query('SELECT COUNT(*) as c FROM prompts WHERE created_at_epoch < ?').get(threshold) as { c: number }).c;\n res.json({ dryRun: true, maxAgeDays: days, wouldDelete: { observations: obsCount, summaries: sumCount, prompts: promptCount } });\n return;\n }\n\n const cleanup = ctx.db.db.transaction(() => {\n ctx.db.db.run('DELETE FROM observation_embeddings WHERE observation_id IN (SELECT id FROM observations WHERE created_at_epoch < ?)', [threshold]);\n const obsResult = ctx.db.db.run('DELETE FROM observations WHERE created_at_epoch < ?', [threshold]);\n const sumResult = ctx.db.db.run('DELETE FROM summaries WHERE created_at_epoch < ?', [threshold]);\n const promptResult = ctx.db.db.run('DELETE FROM prompts WHERE created_at_epoch < ?', [threshold]);\n return {\n observations: obsResult.changes,\n summaries: sumResult.changes,\n prompts: promptResult.changes,\n };\n });\n\n const deleted = cleanup();\n ctx.invalidateProjectsCache();\n\n logger.info('WORKER', `Retention cleanup: deleted ${deleted.observations} obs, ${deleted.summaries} sum, ${deleted.prompts} prompts (> ${days}d)`);\n res.json({ success: true, maxAgeDays: days, deleted });\n } catch (error) {\n logger.error('WORKER', 'Retention cleanup failed', { maxAgeDays: days }, error as Error);\n res.status(500).json({ error: 'Retention cleanup failed' });\n }\n });\n\n // \u2500\u2500 Export \u2500\u2500\n\n router.get('/api/export', (req, res) => {\n const { project, format: fmt, type, days } = req.query as {\n project?: string; format?: string; type?: string; days?: string;\n };\n\n if (project && !isValidProject(project)) {\n res.status(400).json({ error: 'Invalid project name' });\n return;\n }\n\n const daysBack = parseIntSafe(days, 30, 1, 365);\n const threshold = Date.now() - (daysBack * 86_400_000);\n\n try {\n let sql = 'SELECT * FROM observations WHERE created_at_epoch > ?';\n const params: (string | number)[] = [threshold];\n if (project) { sql += ' AND project = ?'; params.push(project); }\n if (type) { sql += ' AND type = ?'; params.push(type); }\n sql += ' ORDER BY created_at_epoch DESC LIMIT 1000';\n const observations = ctx.db.db.query(sql).all(...params) as any[];\n\n let sumSql = 'SELECT * FROM summaries WHERE created_at_epoch > ?';\n const sumParams: (string | number)[] = [threshold];\n if (project) { sumSql += ' AND project = ?'; sumParams.push(project); }\n sumSql += ' ORDER BY created_at_epoch DESC LIMIT 100';\n const summaries = ctx.db.db.query(sumSql).all(...sumParams) as any[];\n\n if (fmt === 'markdown' || fmt === 'md') {\n const lines: string[] = [\n `# Kiro Memory Export`,\n `> Project: ${project || 'All'} | Period: ${daysBack} days | Generated: ${new Date().toISOString()}`,\n '',\n `## Observations (${observations.length})`,\n '',\n ];\n\n for (const obs of observations) {\n const date = new Date(obs.created_at_epoch).toISOString().split('T')[0];\n lines.push(`### [${obs.type}] ${obs.title}`);\n lines.push(`- **Date**: ${date} | **Project**: ${obs.project} | **ID**: #${obs.id}`);\n if (obs.narrative) lines.push(`- ${obs.narrative}`);\n if (obs.concepts) lines.push(`- **Concepts**: ${obs.concepts}`);\n lines.push('');\n }\n\n lines.push(`## Summaries (${summaries.length})`, '');\n for (const sum of summaries) {\n const date = new Date(sum.created_at_epoch).toISOString().split('T')[0];\n lines.push(`### Session ${sum.session_id} (${date})`);\n if (sum.request) lines.push(`- **Request**: ${sum.request}`);\n if (sum.completed) lines.push(`- **Completed**: ${sum.completed}`);\n if (sum.next_steps) lines.push(`- **Next steps**: ${sum.next_steps}`);\n lines.push('');\n }\n\n res.type('text/markdown').send(lines.join('\\n'));\n } else {\n res.json({\n meta: { project: project || 'all', daysBack, exportedAt: new Date().toISOString() },\n observations,\n summaries,\n });\n }\n } catch (error) {\n logger.error('WORKER', 'Export failed', { project, fmt }, error as Error);\n res.status(500).json({ error: 'Export failed' });\n }\n });\n\n // \u2500\u2500 Report \u2500\u2500\n\n router.get('/api/report', (req, res) => {\n const { project, period, format } = req.query as {\n project?: string; period?: string; format?: string;\n };\n\n if (project && !isValidProject(project)) {\n res.status(400).json({ error: 'Invalid project name' });\n return;\n }\n\n const validPeriods = ['weekly', 'monthly'];\n const reportPeriod = validPeriods.includes(period || '') ? period : 'weekly';\n const daysBack = reportPeriod === 'monthly' ? 30 : 7;\n const now = Date.now();\n const startEpoch = now - (daysBack * 24 * 60 * 60 * 1000);\n\n try {\n const data = getReportData(ctx.db.db, project || undefined, startEpoch, now);\n\n const outputFormat = format || 'json';\n if (outputFormat === 'markdown' || outputFormat === 'md') {\n res.type('text/markdown').send(formatReportMarkdown(data));\n } else if (outputFormat === 'text') {\n res.type('text/plain').send(JSON.stringify(data, null, 2));\n } else {\n res.json(data);\n }\n } catch (error) {\n logger.error('WORKER', 'Report generation failed', { project, period }, error as Error);\n res.status(500).json({ error: 'Report generation failed' });\n }\n });\n\n return router;\n}\n", "import { Database } from 'bun:sqlite';\nimport type { ReportData } from '../../types/worker-types.js';\n\n/**\n * Report module for Kiro Memory.\n * Aggregates metrics for a specific time range.\n */\n\n/**\n * Generate aggregated data for an activity report.\n * Executes 8 queries on the range [startEpoch, endEpoch].\n */\nexport function getReportData(\n db: Database,\n project: string | undefined,\n startEpoch: number,\n endEpoch: number\n): ReportData {\n // Calculate period\n const startDate = new Date(startEpoch);\n const endDate = new Date(endEpoch);\n const days = Math.ceil((endEpoch - startEpoch) / (24 * 60 * 60 * 1000));\n const label = days <= 7 ? 'Weekly' : days <= 31 ? 'Monthly' : 'Custom';\n\n // Helper for queries with project filter + time range\n const countInRange = (table: string, epochCol: string = 'created_at_epoch'): number => {\n const sql = project\n ? `SELECT COUNT(*) as count FROM ${table} WHERE project = ? AND ${epochCol} >= ? AND ${epochCol} <= ?`\n : `SELECT COUNT(*) as count FROM ${table} WHERE ${epochCol} >= ? AND ${epochCol} <= ?`;\n const stmt = db.query(sql);\n const row = project\n ? stmt.get(project, startEpoch, endEpoch) as any\n : stmt.get(startEpoch, endEpoch) as any;\n return row?.count || 0;\n };\n\n // 1. Base counts in the period\n const observations = countInRange('observations');\n const summaries = countInRange('summaries');\n const prompts = countInRange('prompts');\n // Sessions: use started_at_epoch as reference\n const sessions = countInRange('sessions', 'started_at_epoch');\n\n // 2. Daily timeline\n const timelineSql = project\n ? `SELECT DATE(datetime(created_at_epoch / 1000, 'unixepoch')) as day, COUNT(*) as count\n FROM observations\n WHERE project = ? AND created_at_epoch >= ? AND created_at_epoch <= ?\n GROUP BY day ORDER BY day ASC`\n : `SELECT DATE(datetime(created_at_epoch / 1000, 'unixepoch')) as day, COUNT(*) as count\n FROM observations\n WHERE created_at_epoch >= ? AND created_at_epoch <= ?\n GROUP BY day ORDER BY day ASC`;\n const timelineStmt = db.query(timelineSql);\n const timeline = (project\n ? timelineStmt.all(project, startEpoch, endEpoch)\n : timelineStmt.all(startEpoch, endEpoch)\n ) as Array<{ day: string; count: number }>;\n\n // 3. Distribution by type\n const typeSql = project\n ? `SELECT type, COUNT(*) as count FROM observations\n WHERE project = ? AND created_at_epoch >= ? AND created_at_epoch <= ?\n GROUP BY type ORDER BY count DESC`\n : `SELECT type, COUNT(*) as count FROM observations\n WHERE created_at_epoch >= ? AND created_at_epoch <= ?\n GROUP BY type ORDER BY count DESC`;\n const typeStmt = db.query(typeSql);\n const typeDistribution = (project\n ? typeStmt.all(project, startEpoch, endEpoch)\n : typeStmt.all(startEpoch, endEpoch)\n ) as Array<{ type: string; count: number }>;\n\n // 4. Session stats in the period\n const sessionTotalSql = project\n ? `SELECT COUNT(*) as count FROM sessions WHERE project = ? AND started_at_epoch >= ? AND started_at_epoch <= ?`\n : `SELECT COUNT(*) as count FROM sessions WHERE started_at_epoch >= ? AND started_at_epoch <= ?`;\n const sessionTotal = (project\n ? (db.query(sessionTotalSql).get(project, startEpoch, endEpoch) as any)?.count\n : (db.query(sessionTotalSql).get(startEpoch, endEpoch) as any)?.count\n ) || 0;\n\n const sessionCompletedSql = project\n ? `SELECT COUNT(*) as count FROM sessions WHERE project = ? AND started_at_epoch >= ? AND started_at_epoch <= ? AND status = 'completed'`\n : `SELECT COUNT(*) as count FROM sessions WHERE started_at_epoch >= ? AND started_at_epoch <= ? AND status = 'completed'`;\n const sessionCompleted = (project\n ? (db.query(sessionCompletedSql).get(project, startEpoch, endEpoch) as any)?.count\n : (db.query(sessionCompletedSql).get(startEpoch, endEpoch) as any)?.count\n ) || 0;\n\n const sessionAvgSql = project\n ? `SELECT AVG((completed_at_epoch - started_at_epoch) / 1000.0 / 60.0) as avg_min\n FROM sessions\n WHERE project = ? AND started_at_epoch >= ? AND started_at_epoch <= ?\n AND status = 'completed' AND completed_at_epoch IS NOT NULL AND completed_at_epoch > started_at_epoch`\n : `SELECT AVG((completed_at_epoch - started_at_epoch) / 1000.0 / 60.0) as avg_min\n FROM sessions\n WHERE started_at_epoch >= ? AND started_at_epoch <= ?\n AND status = 'completed' AND completed_at_epoch IS NOT NULL AND completed_at_epoch > started_at_epoch`;\n const avgRow = project\n ? db.query(sessionAvgSql).get(project, startEpoch, endEpoch) as any\n : db.query(sessionAvgSql).get(startEpoch, endEpoch) as any;\n const avgDurationMinutes = Math.round((avgRow?.avg_min || 0) * 10) / 10;\n\n // 5. Knowledge count\n const knowledgeSql = project\n ? `SELECT COUNT(*) as count FROM observations\n WHERE project = ? AND created_at_epoch >= ? AND created_at_epoch <= ?\n AND type IN ('constraint', 'decision', 'heuristic', 'rejected')`\n : `SELECT COUNT(*) as count FROM observations\n WHERE created_at_epoch >= ? AND created_at_epoch <= ?\n AND type IN ('constraint', 'decision', 'heuristic', 'rejected')`;\n const knowledgeCount = (project\n ? (db.query(knowledgeSql).get(project, startEpoch, endEpoch) as any)?.count\n : (db.query(knowledgeSql).get(startEpoch, endEpoch) as any)?.count\n ) || 0;\n\n // 6. Stale count\n const staleSql = project\n ? `SELECT COUNT(*) as count FROM observations\n WHERE project = ? AND created_at_epoch >= ? AND created_at_epoch <= ? AND is_stale = 1`\n : `SELECT COUNT(*) as count FROM observations\n WHERE created_at_epoch >= ? AND created_at_epoch <= ? AND is_stale = 1`;\n const staleCount = (project\n ? (db.query(staleSql).get(project, startEpoch, endEpoch) as any)?.count\n : (db.query(staleSql).get(startEpoch, endEpoch) as any)?.count\n ) || 0;\n\n // 7. Summary contents (learnings, completed, next steps)\n const summarySql = project\n ? `SELECT learned, completed, next_steps FROM summaries\n WHERE project = ? AND created_at_epoch >= ? AND created_at_epoch <= ?\n ORDER BY created_at_epoch DESC`\n : `SELECT learned, completed, next_steps FROM summaries\n WHERE created_at_epoch >= ? AND created_at_epoch <= ?\n ORDER BY created_at_epoch DESC`;\n const summaryRows = (project\n ? db.query(summarySql).all(project, startEpoch, endEpoch)\n : db.query(summarySql).all(startEpoch, endEpoch)\n ) as Array<{ learned: string | null; completed: string | null; next_steps: string | null }>;\n\n const topLearnings: string[] = [];\n const completedTasks: string[] = [];\n const nextStepsArr: string[] = [];\n\n for (const row of summaryRows) {\n if (row.learned) {\n // Split by '; ' if concatenated (hook stop.ts format)\n const parts = row.learned.split('; ').filter(Boolean);\n topLearnings.push(...parts);\n }\n if (row.completed) {\n const parts = row.completed.split('; ').filter(Boolean);\n completedTasks.push(...parts);\n }\n if (row.next_steps) {\n const parts = row.next_steps.split('; ').filter(Boolean);\n nextStepsArr.push(...parts);\n }\n }\n\n // 8. File hotspots (most modified files in the period)\n const filesSql = project\n ? `SELECT files_modified FROM observations\n WHERE project = ? AND created_at_epoch >= ? AND created_at_epoch <= ?\n AND files_modified IS NOT NULL AND files_modified != ''`\n : `SELECT files_modified FROM observations\n WHERE created_at_epoch >= ? AND created_at_epoch <= ?\n AND files_modified IS NOT NULL AND files_modified != ''`;\n const fileRows = (project\n ? db.query(filesSql).all(project, startEpoch, endEpoch)\n : db.query(filesSql).all(startEpoch, endEpoch)\n ) as Array<{ files_modified: string }>;\n\n const fileCounts = new Map<string, number>();\n for (const row of fileRows) {\n const files = row.files_modified.split(',').map(f => f.trim()).filter(Boolean);\n for (const file of files) {\n fileCounts.set(file, (fileCounts.get(file) || 0) + 1);\n }\n }\n\n const fileHotspots = Array.from(fileCounts.entries())\n .map(([file, count]) => ({ file, count }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 15);\n\n return {\n period: {\n start: startDate.toISOString().split('T')[0],\n end: endDate.toISOString().split('T')[0],\n days,\n label\n },\n overview: {\n observations,\n summaries,\n sessions,\n prompts,\n knowledgeCount,\n staleCount\n },\n timeline,\n typeDistribution,\n sessionStats: {\n total: sessionTotal,\n completed: sessionCompleted,\n avgDurationMinutes\n },\n topLearnings: [...new Set(topLearnings)].slice(0, 10),\n completedTasks: [...new Set(completedTasks)].slice(0, 10),\n nextSteps: [...new Set(nextStepsArr)].slice(0, 10),\n fileHotspots\n };\n}\n", "import type { ReportData } from '../types/worker-types.js';\n\n/**\n * Report formatters for Kiro Memory.\n * Three outputs: ANSI text (CLI), markdown (file/sharing), JSON (automations).\n */\n\n// ============================================================================\n// ANSI text format (for CLI)\n// ============================================================================\n\nexport function formatReportText(data: ReportData): string {\n const lines: string[] = [];\n\n // Header\n lines.push('');\n lines.push(` \\x1b[36m\u2550\u2550\u2550 Kiro Memory Report \u2014 ${data.period.label} \u2550\u2550\u2550\\x1b[0m`);\n lines.push(` \\x1b[2m${data.period.start} \u2192 ${data.period.end} (${data.period.days} days)\\x1b[0m`);\n lines.push('');\n\n // Overview\n lines.push(` \\x1b[1mOverview\\x1b[0m`);\n lines.push(` Observations: ${data.overview.observations}`);\n lines.push(` Summaries: ${data.overview.summaries}`);\n lines.push(` Sessions: ${data.overview.sessions}`);\n lines.push(` Prompts: ${data.overview.prompts}`);\n lines.push(` Knowledge: ${data.overview.knowledgeCount}`);\n if (data.overview.staleCount > 0) {\n lines.push(` Stale: ${data.overview.staleCount}`);\n }\n lines.push('');\n\n // Session stats\n if (data.sessionStats.total > 0) {\n const completionPct = data.sessionStats.total > 0\n ? Math.round((data.sessionStats.completed / data.sessionStats.total) * 100)\n : 0;\n lines.push(` \\x1b[1mSessions\\x1b[0m`);\n lines.push(` Total: ${data.sessionStats.total} | Completed: ${data.sessionStats.completed} (${completionPct}%)`);\n if (data.sessionStats.avgDurationMinutes > 0) {\n lines.push(` Avg duration: ${data.sessionStats.avgDurationMinutes} min`);\n }\n lines.push('');\n }\n\n // Timeline (bar chart ASCII)\n if (data.timeline.length > 0) {\n lines.push(` \\x1b[1mTimeline\\x1b[0m`);\n const maxCount = Math.max(...data.timeline.map(t => t.count));\n const maxBarLen = 30;\n for (const entry of data.timeline) {\n const barLen = maxCount > 0 ? Math.round((entry.count / maxCount) * maxBarLen) : 0;\n const bar = '\\x1b[32m' + '\u2593'.repeat(barLen) + '\\x1b[0m';\n const dayShort = entry.day.substring(5); // MM-DD\n lines.push(` ${dayShort} ${bar} ${entry.count}`);\n }\n lines.push('');\n }\n\n // Type distribution\n if (data.typeDistribution.length > 0) {\n lines.push(` \\x1b[1mBy Type\\x1b[0m`);\n for (const entry of data.typeDistribution) {\n lines.push(` ${entry.type.padEnd(16)} ${entry.count}`);\n }\n lines.push('');\n }\n\n // Learnings\n if (data.topLearnings.length > 0) {\n lines.push(` \\x1b[1mKey Learnings\\x1b[0m`);\n for (const learning of data.topLearnings) {\n lines.push(` - ${learning}`);\n }\n lines.push('');\n }\n\n // Completed tasks\n if (data.completedTasks.length > 0) {\n lines.push(` \\x1b[1mCompleted\\x1b[0m`);\n for (const task of data.completedTasks) {\n lines.push(` - ${task}`);\n }\n lines.push('');\n }\n\n // Next steps\n if (data.nextSteps.length > 0) {\n lines.push(` \\x1b[1mNext Steps\\x1b[0m`);\n for (const step of data.nextSteps) {\n lines.push(` - ${step}`);\n }\n lines.push('');\n }\n\n // File hotspots\n if (data.fileHotspots.length > 0) {\n lines.push(` \\x1b[1mFile Hotspots\\x1b[0m`);\n for (const entry of data.fileHotspots.slice(0, 10)) {\n lines.push(` ${entry.file} (${entry.count}x)`);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n// ============================================================================\n// Markdown format (for file/sharing)\n// ============================================================================\n\nexport function formatReportMarkdown(data: ReportData): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`# Kiro Memory Report \u2014 ${data.period.label}`);\n lines.push('');\n lines.push(`**Period**: ${data.period.start} \u2192 ${data.period.end} (${data.period.days} days)`);\n lines.push('');\n\n // Overview table\n lines.push('## Overview');\n lines.push('');\n lines.push('| Metric | Count |');\n lines.push('|--------|------:|');\n lines.push(`| Observations | ${data.overview.observations} |`);\n lines.push(`| Summaries | ${data.overview.summaries} |`);\n lines.push(`| Sessions | ${data.overview.sessions} |`);\n lines.push(`| Prompts | ${data.overview.prompts} |`);\n lines.push(`| Knowledge items | ${data.overview.knowledgeCount} |`);\n if (data.overview.staleCount > 0) {\n lines.push(`| Stale observations | ${data.overview.staleCount} |`);\n }\n lines.push('');\n\n // Sessions\n if (data.sessionStats.total > 0) {\n const completionPct = Math.round((data.sessionStats.completed / data.sessionStats.total) * 100);\n lines.push('## Sessions');\n lines.push('');\n lines.push(`- **Total**: ${data.sessionStats.total}`);\n lines.push(`- **Completed**: ${data.sessionStats.completed} (${completionPct}%)`);\n if (data.sessionStats.avgDurationMinutes > 0) {\n lines.push(`- **Avg duration**: ${data.sessionStats.avgDurationMinutes} min`);\n }\n lines.push('');\n }\n\n // Timeline\n if (data.timeline.length > 0) {\n lines.push('## Activity Timeline');\n lines.push('');\n lines.push('| Date | Observations |');\n lines.push('|------|------------:|');\n for (const entry of data.timeline) {\n lines.push(`| ${entry.day} | ${entry.count} |`);\n }\n lines.push('');\n }\n\n // Type distribution\n if (data.typeDistribution.length > 0) {\n lines.push('## Observation Types');\n lines.push('');\n for (const entry of data.typeDistribution) {\n lines.push(`- **${entry.type}**: ${entry.count}`);\n }\n lines.push('');\n }\n\n // Learnings\n if (data.topLearnings.length > 0) {\n lines.push('## Key Learnings');\n lines.push('');\n for (const learning of data.topLearnings) {\n lines.push(`- ${learning}`);\n }\n lines.push('');\n }\n\n // Completed\n if (data.completedTasks.length > 0) {\n lines.push('## Completed');\n lines.push('');\n for (const task of data.completedTasks) {\n lines.push(`- ${task}`);\n }\n lines.push('');\n }\n\n // Next steps\n if (data.nextSteps.length > 0) {\n lines.push('## Next Steps');\n lines.push('');\n for (const step of data.nextSteps) {\n lines.push(`- ${step}`);\n }\n lines.push('');\n }\n\n // File hotspots\n if (data.fileHotspots.length > 0) {\n lines.push('## File Hotspots');\n lines.push('');\n lines.push('| File | Modifications |');\n lines.push('|------|-------------:|');\n for (const entry of data.fileHotspots.slice(0, 10)) {\n lines.push(`| \\`${entry.file}\\` | ${entry.count} |`);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n// ============================================================================\n// JSON format (for automations/webhooks)\n// ============================================================================\n\nexport function formatReportJson(data: ReportData): string {\n return JSON.stringify(data, null, 2);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["exports", "isInSubnet", "isCorrect", "numberToPaddedHex", "stringToPaddedHex", "testBit", "address", "defaultBits", "number", "numberString", "binaryValue", "position", "length", "positionInString", "exports", "AddressError", "message", "parseMessage", "exports", "common", "__importStar", "constants", "address_error_1", "Address4", "_Address4", "address", "subnet", "groups", "part", "hex", "padded", "i", "h", "integer", "arpaFormAddress", "output", "n", "adjust", "bigInt", "mask", "start", "end", "options", "reversed", "segments", "exports", "exports", "exports", "spanAllZeroes", "spanAll", "spanLeadingZeroes", "simpleGroup", "s", "offset", "n", "i", "spanLeadingZeroesSimple", "group", "address", "g", "addressString", "exports", "groupPossibilities", "padGroup", "simpleRegularExpression", "possibleElisions", "v6", "__importStar", "possibilities", "group", "groups", "zeroIndexes", "i", "zeroIndex", "elision", "elidedGroups", "moreLeft", "moreRight", "left", "right", "position", "common", "__importStar", "constants4", "constants6", "helpers", "ipv4_1", "regular_expressions_1", "address_error_1", "common_1", "assert", "condition", "addCommas", "number", "r", "spanLeadingZeroes4", "n", "compact", "address", "slice", "s1", "s2", "i", "paddedHex", "octet", "unsignByte", "b", "Address6", "_Address6", "optionalGroups", "subnet", "zone", "bigInt", "hex", "groups", "url", "host", "port", "result", "address4", "mask6", "arpaFormAddress", "semicolonAmount", "parts", "insertIndex", "mask", "subnetSize", "availableBits", "subnetBits", "subnetPowers", "adjust", "scope", "start", "end", "length", "options", "characters", "reversed", "zeroCounter", "zeroes", "value", "zeroLengths", "index", "correct", "badCharacters", "badAddress", "halves", "first", "last", "remaining", "group", "binary", "infix", "prefix", "udpPort", "server4", "bitsForClient4", "client4", "flagsBase2", "coneNat", "reserved", "groupIndividual", "universalLocal", "nonce", "gateway", "addr6to4", "valueWithoutPadding", "bytes", "BYTE_MAX", "multiplier", "optionalPort", "formFunction", "form", "output", "left", "right", "classes", "substringSearch", "address6", "exports", "ipv4_1", "exports", "ipv6_1", "address_error_1", "helpers", "__importStar", "Search_exports", "__export", "getObservationsByIds", "getProjectStats", "getStaleObservations", "getTimeline", "markObservationsStale", "searchObservationsFTS", "searchObservationsFTSWithRank", "searchObservationsLIKE", "searchSummariesFiltered", "existsSync", "statSync", "escapeLikePattern", "input", "sanitizeFTS5Query", "query", "t", "db", "filters", "limit", "safeQuery", "sql", "params", "BM25_WEIGHTS", "pattern", "ids", "validIds", "id", "anchorId", "depthBefore", "depthAfter", "anchor", "anchorEpoch", "before", "self", "after", "project", "row", "discoveryTokens", "readTokens", "savings", "rows", "staleObs", "obs", "files", "f", "isStale", "filepath", "stale", "placeholders", "init_Search", "__esmMin", "Observations_exports", "__export", "consolidateObservations", "createObservation", "deleteObservation", "getObservationsByProject", "getObservationsBySession", "isDuplicateObservation", "searchObservations", "updateLastAccessed", "escapeLikePattern", "input", "db", "contentHash", "windowMs", "threshold", "memorySessionId", "project", "type", "title", "subtitle", "text", "narrative", "facts", "concepts", "filesRead", "filesModified", "promptNumber", "discoveryTokens", "now", "result", "limit", "searchTerm", "sql", "pattern", "query", "id", "ids", "validIds", "placeholders", "options", "minGroupSize", "groups", "totalMerged", "totalRemoved", "group", "obsIds", "count", "merged", "removed", "observations", "keeper", "others", "uniqueTexts", "obs", "consolidatedText", "removeIds", "o", "removePlaceholders", "init_Observations", "__esmMin", "express", "cors", "dangerouslyDisableDefaultSrc", "SHOULD_BE_QUOTED", "getDefaultDirectives", "dashify", "str", "capitalLetter", "assertDirectiveValueIsValid", "directiveName", "directiveValue", "assertDirectiveValueEntryIsValid", "directiveValueEntry", "normalizeDirectives", "options", "defaultDirectives", "useDefaults", "rawDirectives", "result", "directiveNamesSeen", "directivesExplicitlyDisabled", "rawDirectiveName", "rawDirectiveValue", "element", "defaultDirectiveName", "defaultDirectiveValue", "getHeaderValue", "req", "res", "normalizedDirectives", "newElement", "contentSecurityPolicy", "headerName", "next", "ALLOWED_POLICIES$2", "getHeaderValueFromOptions$6", "policy", "crossOriginEmbedderPolicy", "headerValue", "_req", "ALLOWED_POLICIES$1", "getHeaderValueFromOptions$5", "crossOriginOpenerPolicy", "ALLOWED_POLICIES", "getHeaderValueFromOptions$4", "crossOriginResourcePolicy", "originAgentCluster", "ALLOWED_TOKENS", "getHeaderValueFromOptions$3", "tokens", "tokensSeen", "token", "referrerPolicy", "DEFAULT_MAX_AGE", "parseMaxAge", "value", "getHeaderValueFromOptions$2", "directives", "strictTransportSecurity", "xContentTypeOptions", "xDnsPrefetchControl", "xDownloadOptions", "getHeaderValueFromOptions$1", "action", "normalizedAction", "xFrameOptions", "ALLOWED_PERMITTED_POLICIES", "getHeaderValueFromOptions", "permittedPolicies", "xPermittedCrossDomainPolicies", "xPoweredBy", "xXssProtection", "getMiddlewareFunctionsFromOptions", "strictTransportSecurityOption", "xDnsPrefetchControlOption", "xFrameOptionsOption", "xPermittedCrossDomainPoliciesOption", "helmet", "middlewareFunctions", "middlewareIndex", "internalNext", "err", "middlewareFunction", "import_ip_address", "isIPv6", "isIPv62", "Buffer", "createHash", "isIP", "ipKeyGenerator", "ip", "ipv6Subnet", "MemoryStore", "validations2", "options", "key", "client", "now", "SUPPORTED_DRAFT_VERSIONS", "getResetSeconds", "windowMs", "resetTime", "resetSeconds", "deltaSeconds", "getPartitionKey", "hash", "partitionKey", "setLegacyHeaders", "response", "info", "setDraft6Headers", "windowSeconds", "setDraft7Headers", "setDraft8Headers", "name", "header", "policy", "setRetryAfterHeader", "omitUndefinedProperties", "passedOptions", "omittedOptions", "k", "ValidationError", "code", "message", "url", "ChangeWarning", "usedStores", "singleCountKeys", "validations", "request", "hits", "store", "maybeUniquePrefix", "storeKeys", "storeKey", "keys", "prefixedKey", "limit", "draft_polli_ratelimit_headers", "onLimitReached", "version", "versionString", "validOptions", "supportedValidations", "stack", "keyGenerator", "src", "getValidations", "_enabled", "enabled", "wrappedValidations", "validation", "args", "error", "isLegacyStore", "promisifyStore", "passedStore", "legacyStore", "PromisifiedStore", "resolve", "reject", "totalHits", "getOptionsFromConfig", "config", "directlyPassableEntries", "parseOptions", "notUndefinedOptions", "standardHeaders", "_response", "duration", "property", "seconds", "minutes", "hours", "days", "_request", "subnet", "_next", "_optionsUsed", "handleAsyncErrors", "fn", "next", "rateLimit", "middleware", "augmentedRequest", "incrementResult", "decremented", "decrementKey", "getThrowFn", "rate_limit_default", "crypto", "join", "dirname", "existsSync", "mkdirSync", "writeFileSync", "unlinkSync", "chmodSync", "fileURLToPath", "BetterSqlite3", "Database", "path", "options", "sql", "params", "stmt", "cached", "BunQueryCompat", "fn", "db", "join", "dirname", "basename", "homedir", "existsSync", "mkdirSync", "fileURLToPath", "appendFileSync", "existsSync", "mkdirSync", "readFileSync", "join", "homedir", "LogLevel", "DEFAULT_DATA_DIR", "Logger", "logsDir", "date", "error", "settingsPath", "settingsData", "settings", "envLevel", "sessionId", "observationNum", "data", "keys", "year", "month", "day", "hours", "minutes", "seconds", "ms", "level", "component", "message", "context", "timestamp", "levelStr", "componentStr", "correlationStr", "dataStr", "contextStr", "memorySessionId", "correlationId", "rest", "k", "v", "logLine", "durationMs", "fallback", "callerMatch", "location", "enhancedContext", "logger", "getDirname", "dirname", "fileURLToPath", "_dirname", "_legacyDir", "join", "homedir", "_defaultDir", "existsSync", "DATA_DIR", "KIRO_CONFIG_DIR", "PLUGIN_ROOT", "ARCHIVES_DIR", "LOGS_DIR", "TRASH_DIR", "BACKUPS_DIR", "MODES_DIR", "USER_SETTINGS_PATH", "_legacyDb", "DB_PATH", "VECTOR_DB_DIR", "OBSERVER_SESSIONS_DIR", "KIRO_SETTINGS_PATH", "KIRO_CONTEXT_PATH", "ensureDir", "dirPath", "mkdirSync", "SQLITE_MMAP_SIZE_BYTES", "SQLITE_CACHE_SIZE_PAGES", "KiroMemoryDatabase", "dbPath", "DB_PATH", "skipMigrations", "ensureDir", "DATA_DIR", "Database", "MigrationRunner", "sql", "params", "fn", "db", "currentVersion", "migrations", "migration", "logger", "EmbeddingService", "result", "fastembed", "EmbeddingModel", "FlagEmbedding", "logger", "error", "transformers", "pipeline", "text", "truncated", "texts", "t", "results", "embeddings", "batch", "vec", "output", "dims", "data", "offset", "embedding", "embeddingService", "getEmbeddingService", "DEFAULT_MAX_CANDIDATES", "cosineSimilarity", "a", "b", "len", "dotProduct", "normA", "normB", "i", "ai", "bi", "denominator", "float32ToBuffer", "arr", "bufferToFloat32", "buf", "arrayBuffer", "VectorSearch", "db", "queryEmbedding", "options", "limit", "threshold", "maxCandidates", "conditions", "params", "sql", "rows", "scored", "row", "embedding", "similarity", "logger", "error", "observationId", "model", "blob", "batchSize", "embeddingService", "getEmbeddingService", "count", "parts", "fullText", "totalRow", "embeddedRow", "total", "embedded", "percentage", "vectorSearch", "getVectorSearch", "SEARCH_WEIGHTS", "recencyScore", "createdAtEpoch", "halfLifeHours", "ageMs", "ageHours", "normalizeFTS5Rank", "rank", "allRanks", "minRank", "maxRank", "projectMatchScore", "itemProject", "targetProject", "computeCompositeScore", "signals", "weights", "KNOWLEDGE_TYPE_BOOST", "knowledgeTypeBoost", "type", "HybridSearch", "embeddingService", "getEmbeddingService", "logger", "error", "db", "query", "options", "limit", "weights", "SEARCH_WEIGHTS", "targetProject", "rawItems", "queryEmbedding", "vectorResults", "getVectorSearch", "hit", "searchObservationsFTSWithRank", "keywordResults", "obs", "id", "existing", "allFTS5Ranks", "item", "scored", "signals", "normalizeFTS5Rank", "recencyScore", "projectMatchScore", "score", "computeCompositeScore", "isHybrid", "finalScore", "knowledgeTypeBoost", "a", "b", "finalResults", "updateLastAccessed", "ids", "r", "hybridSearch", "getHybridSearch", "MAX_SSE_CLIENTS", "clients", "getClients", "getMaxSSEClients", "addClient", "res", "removeClient", "index", "broadcast", "event", "data", "message", "client", "err", "logger", "projectsCache", "PROJECTS_CACHE_TTL", "invalidateProjectsCache", "parseIntSafe", "value", "defaultVal", "min", "max", "parsed", "isValidProject", "project", "isValidString", "val", "maxLen", "generateEmbeddingForObservation", "db", "observationId", "title", "content", "concepts", "embeddingService", "getEmbeddingService", "parts", "fullText", "embedding", "getVectorSearch", "error", "createWorkerContext", "id", "Router", "ALLOWED_EVENTS", "createCoreRouter", "ctx", "workerToken", "router", "Router", "notifyLimiter", "rate_limit_default", "req", "res", "event", "data", "_req", "clients", "getClients", "getMaxSSEClients", "addClient", "logger", "keepaliveInterval", "removeClient", "Router", "init_Observations", "createSummary", "db", "sessionId", "project", "request", "investigated", "learned", "completed", "nextSteps", "notes", "now", "result", "getSummariesByProject", "db", "project", "limit", "init_Search", "KNOWLEDGE_TYPES", "createObservationsRouter", "ctx", "router", "Router", "req", "res", "offset", "limit", "project", "_offset", "parseIntSafe", "_limit", "countSql", "countStmt", "total", "sql", "stmt", "rows", "error", "logger", "memorySessionId", "type", "title", "content", "concepts", "files", "isValidProject", "isValidString", "id", "createObservation", "ids", "observations", "getObservationsByIds", "knowledge_type", "severity", "alternatives", "reason", "metaContext", "confidence", "KNOWLEDGE_TYPES", "metadata", "obsType", "conceptStr", "context", "getObservationsByProject", "getSummariesByProject", "Router", "createSummariesRouter", "ctx", "router", "Router", "req", "res", "offset", "limit", "project", "_offset", "parseIntSafe", "_limit", "countSql", "countStmt", "total", "sql", "stmt", "rows", "error", "logger", "sessionId", "request", "learned", "completed", "nextSteps", "isValidProject", "MAX_FIELD", "isValidString", "id", "createSummary", "Router", "init_Search", "createSearchRouter", "ctx", "router", "Router", "req", "res", "q", "project", "type", "limit", "filters", "parseIntSafe", "results", "searchObservationsFTS", "searchSummariesFiltered", "error", "logger", "getHybridSearch", "anchor", "depth_before", "depth_after", "anchorId", "timeline", "getTimeline", "Router", "getObservationsTimeline", "db", "project", "days", "cutoffEpoch", "sql", "stmt", "getTypeDistribution", "getSessionStats", "row", "getAnalyticsOverview", "now", "todayStart", "weekStart", "projectFilter", "params", "discoveryTokens", "readTokens", "savings", "reductionPct", "createAnalyticsRouter", "ctx", "router", "Router", "req", "res", "project", "isValidProject", "overview", "getAnalyticsOverview", "error", "logger", "days", "timeline", "getObservationsTimeline", "parseIntSafe", "distribution", "getTypeDistribution", "stats", "getSessionStats", "Router", "getAllSessions", "db", "limit", "getSessionsByProject", "project", "getLatestCheckpoint", "db", "sessionId", "getLatestCheckpointByProject", "project", "createSessionsRouter", "ctx", "router", "Router", "req", "res", "project", "isValidProject", "sessions", "getSessionsByProject", "getAllSessions", "error", "logger", "sessionId", "checkpoint", "getLatestCheckpoint", "getLatestCheckpointByProject", "offset", "limit", "_offset", "parseIntSafe", "_limit", "countSql", "countStmt", "total", "sql", "stmt", "rows", "Router", "init_Search", "createProjectsRouter", "ctx", "router", "Router", "_req", "res", "now", "projectsCache", "PROJECTS_CACHE_TTL", "rows", "r", "error", "logger", "aliases", "row", "req", "project", "displayName", "isValidProject", "stats", "getProjectStats", "Router", "getReportData", "db", "project", "startEpoch", "endEpoch", "startDate", "endDate", "days", "label", "countInRange", "table", "epochCol", "sql", "stmt", "observations", "summaries", "prompts", "sessions", "timelineSql", "timelineStmt", "timeline", "typeSql", "typeStmt", "typeDistribution", "sessionTotalSql", "sessionTotal", "sessionCompletedSql", "sessionCompleted", "sessionAvgSql", "avgRow", "avgDurationMinutes", "knowledgeSql", "knowledgeCount", "staleSql", "staleCount", "summarySql", "summaryRows", "topLearnings", "completedTasks", "nextStepsArr", "row", "parts", "filesSql", "fileRows", "fileCounts", "files", "f", "file", "fileHotspots", "count", "a", "b", "formatReportMarkdown", "data", "lines", "completionPct", "entry", "learning", "task", "step", "createDataRouter", "ctx", "workerToken", "router", "Router", "requireAuth", "req", "res", "next", "batchSize", "count", "getVectorSearch", "parseIntSafe", "error", "logger", "_req", "stats", "embeddingService", "getEmbeddingService", "maxAgeDays", "dryRun", "days", "threshold", "obsCount", "sumCount", "promptCount", "deleted", "obsResult", "sumResult", "promptResult", "project", "fmt", "type", "isValidProject", "daysBack", "sql", "params", "observations", "sumSql", "sumParams", "summaries", "lines", "obs", "date", "sum", "period", "format", "now", "startEpoch", "data", "getReportData", "outputFormat", "formatReportMarkdown", "__worker_dirname", "dirname", "fileURLToPath", "PORT", "HOST", "PID_FILE", "join", "DATA_DIR", "TOKEN_FILE", "existsSync", "mkdirSync", "WORKER_TOKEN", "crypto", "writeFileSync", "chmodSync", "err", "logger", "db", "KiroMemoryDatabase", "getHybridSearch", "ctx", "createWorkerContext", "app", "express", "helmet", "cors", "rate_limit_default", "createCoreRouter", "createObservationsRouter", "createSummariesRouter", "createSearchRouter", "createAnalyticsRouter", "createSessionsRouter", "createProjectsRouter", "createDataRouter", "_req", "res", "viewerPath", "server", "shutdown", "signal", "sseClients", "getClients", "client", "forceTimeout", "unlinkSync", "error", "reason"]
|
|
7
|
+
}
|