@captainsafia/stitch 1.0.0-preview.c77f34b → 1.0.0-preview.f2fe33d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/dist/api.d.ts +88 -0
  2. package/dist/api.js +793 -438
  3. package/dist/cli.js +1357 -784
  4. package/dist/mcp.js +22839 -22449
  5. package/package.json +2 -1
package/dist/cli.js CHANGED
@@ -17,6 +17,16 @@ var __toESM = (mod, isNodeMode, target) => {
17
17
  return to;
18
18
  };
19
19
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
20
+ var __export = (target, all) => {
21
+ for (var name in all)
22
+ __defProp(target, name, {
23
+ get: all[name],
24
+ enumerable: true,
25
+ configurable: true,
26
+ set: (newValue) => all[name] = () => newValue
27
+ });
28
+ };
29
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
20
30
  var __require = import.meta.require;
21
31
  var __using = (stack, value, async) => {
22
32
  if (value != null) {
@@ -1891,185 +1901,70 @@ var require_commander = __commonJS((exports) => {
1891
1901
  exports.InvalidOptionArgumentError = InvalidArgumentError;
1892
1902
  });
1893
1903
 
1894
- // package.json
1895
- var require_package = __commonJS((exports, module) => {
1896
- module.exports = {
1897
- name: "@captainsafia/stitch",
1898
- version: "1.0.0-preview.c77f34b",
1899
- type: "module",
1900
- description: "A local-first CLI for recording intent and binding it to git commits/diffs",
1901
- main: "dist/api.js",
1902
- types: "dist/api.d.ts",
1903
- bin: {
1904
- stitch: "dist/cli.js",
1905
- "stitch-mcp": "dist/mcp.js"
1906
- },
1907
- files: [
1908
- "dist"
1909
- ],
1910
- exports: {
1911
- ".": {
1912
- types: "./dist/api.d.ts",
1913
- import: "./dist/api.js"
1914
- }
1915
- },
1916
- scripts: {
1917
- build: "bun run build:api && bun run build:cli && bun run build:mcp",
1918
- "build:api": "bun build src/api.ts --outdir dist --target bun && dts-bundle-generator -o dist/api.d.ts src/api.ts",
1919
- "build:cli": "bun build src/cli.ts --outdir dist --target bun",
1920
- "build:mcp": "bun build src/mcp.ts --outdir dist --target bun",
1921
- compile: "bun run compile:cli && bun run compile:mcp",
1922
- "compile:cli": "bun build src/cli.ts --compile --outfile stitch",
1923
- "compile:mcp": "bun build src/mcp.ts --compile --outfile stitch-mcp",
1924
- "compile:cli:linux-x64": "bun build src/cli.ts --compile --target=bun-linux-x64 --outfile stitch-linux-x64",
1925
- "compile:cli:linux-arm64": "bun build src/cli.ts --compile --target=bun-linux-arm64 --outfile stitch-linux-arm64",
1926
- "compile:cli:darwin-x64": "bun build src/cli.ts --compile --target=bun-darwin-x64 --outfile stitch-darwin-x64",
1927
- "compile:cli:darwin-arm64": "bun build src/cli.ts --compile --target=bun-darwin-arm64 --outfile stitch-darwin-arm64",
1928
- "compile:cli:windows-x64": "bun build src/cli.ts --compile --target=bun-windows-x64 --outfile stitch-windows-x64.exe",
1929
- "compile:mcp:linux-x64": "bun build src/mcp.ts --compile --target=bun-linux-x64 --outfile stitch-mcp-linux-x64",
1930
- "compile:mcp:linux-arm64": "bun build src/mcp.ts --compile --target=bun-linux-arm64 --outfile stitch-mcp-linux-arm64",
1931
- "compile:mcp:darwin-x64": "bun build src/mcp.ts --compile --target=bun-darwin-x64 --outfile stitch-mcp-darwin-x64",
1932
- "compile:mcp:darwin-arm64": "bun build src/mcp.ts --compile --target=bun-darwin-arm64 --outfile stitch-mcp-darwin-arm64",
1933
- "compile:mcp:windows-x64": "bun build src/mcp.ts --compile --target=bun-windows-x64 --outfile stitch-mcp-windows-x64.exe",
1934
- test: "bun test",
1935
- typecheck: "tsc --noEmit"
1936
- },
1937
- devDependencies: {
1938
- "@types/bun": "latest",
1939
- "dts-bundle-generator": "^9.5.1",
1940
- typescript: "^5"
1941
- },
1942
- dependencies: {
1943
- "@modelcontextprotocol/sdk": "^1.25.1",
1944
- "async-mutex": "^0.5.0",
1945
- commander: "^12.0.0",
1946
- "smol-toml": "^1.3.0",
1947
- zod: "^4.2.1"
1948
- },
1949
- license: "MIT",
1950
- repository: {
1951
- type: "git",
1952
- url: "https://github.com/captainsafia/stitch.git"
1953
- },
1954
- keywords: [
1955
- "git",
1956
- "intent",
1957
- "dag",
1958
- "cli",
1959
- "developer-tools"
1960
- ],
1961
- engines: {
1962
- bun: ">=1.0.0"
1904
+ // src/core/errors.ts
1905
+ var StitchError, RepoNotFoundError, NotInitializedError, NoCurrentStitchError, StitchNotFoundError, GitError, ValidationError, FinishForceRequiredError, InvalidSupersededByError;
1906
+ var init_errors = __esm(() => {
1907
+ StitchError = class StitchError extends Error {
1908
+ constructor(message) {
1909
+ super(message);
1910
+ this.name = "StitchError";
1911
+ }
1912
+ };
1913
+ RepoNotFoundError = class RepoNotFoundError extends StitchError {
1914
+ constructor(path) {
1915
+ super(path ? `Not a git repository: ${path}` : "Not a git repository (or any parent up to mount point)");
1916
+ this.name = "RepoNotFoundError";
1917
+ }
1918
+ };
1919
+ NotInitializedError = class NotInitializedError extends StitchError {
1920
+ constructor() {
1921
+ super("Stitch is not initialized in this repository. Run 'stitch init' first.");
1922
+ this.name = "NotInitializedError";
1923
+ }
1924
+ };
1925
+ NoCurrentStitchError = class NoCurrentStitchError extends StitchError {
1926
+ constructor() {
1927
+ super("No current stitch. Start a new stitch with 'stitch start <title>' or switch to an existing one with 'stitch switch <id>'.");
1928
+ this.name = "NoCurrentStitchError";
1929
+ }
1930
+ };
1931
+ StitchNotFoundError = class StitchNotFoundError extends StitchError {
1932
+ constructor(id) {
1933
+ super(`Stitch not found: ${id}`);
1934
+ this.name = "StitchNotFoundError";
1935
+ }
1936
+ };
1937
+ GitError = class GitError extends StitchError {
1938
+ command;
1939
+ exitCode;
1940
+ constructor(message, command, exitCode) {
1941
+ super(`Git error: ${message}`);
1942
+ this.command = command;
1943
+ this.exitCode = exitCode;
1944
+ this.name = "GitError";
1945
+ }
1946
+ };
1947
+ ValidationError = class ValidationError extends StitchError {
1948
+ constructor(message) {
1949
+ super(`Validation error: ${message}`);
1950
+ this.name = "ValidationError";
1951
+ }
1952
+ };
1953
+ FinishForceRequiredError = class FinishForceRequiredError extends StitchError {
1954
+ constructor(message) {
1955
+ super(message);
1956
+ this.name = "FinishForceRequiredError";
1957
+ }
1958
+ };
1959
+ InvalidSupersededByError = class InvalidSupersededByError extends StitchError {
1960
+ constructor() {
1961
+ super("--by requires --status=superseded");
1962
+ this.name = "InvalidSupersededByError";
1963
1963
  }
1964
1964
  };
1965
1965
  });
1966
1966
 
1967
- // node_modules/commander/esm.mjs
1968
- var import__ = __toESM(require_commander(), 1);
1969
- var {
1970
- program,
1971
- createCommand,
1972
- createArgument,
1973
- createOption,
1974
- CommanderError,
1975
- InvalidArgumentError,
1976
- InvalidOptionArgumentError,
1977
- Command,
1978
- Argument,
1979
- Option,
1980
- Help
1981
- } = import__.default;
1982
-
1983
- // src/api.ts
1984
- import { spawn } from "child_process";
1985
-
1986
- // src/core/store.ts
1987
- import { readdir, readFile, writeFile, mkdir } from "fs/promises";
1988
- import { join } from "path";
1989
- import { existsSync } from "fs";
1990
-
1991
- // src/core/errors.ts
1992
- class StitchError extends Error {
1993
- constructor(message) {
1994
- super(message);
1995
- this.name = "StitchError";
1996
- }
1997
- }
1998
-
1999
- class RepoNotFoundError extends StitchError {
2000
- constructor(path) {
2001
- super(path ? `Not a git repository: ${path}` : "Not a git repository (or any parent up to mount point)");
2002
- this.name = "RepoNotFoundError";
2003
- }
2004
- }
2005
-
2006
- class NotInitializedError extends StitchError {
2007
- constructor() {
2008
- super("Stitch is not initialized in this repository. Run 'stitch init' first.");
2009
- this.name = "NotInitializedError";
2010
- }
2011
- }
2012
-
2013
- class NoCurrentStitchError extends StitchError {
2014
- constructor() {
2015
- super("No current stitch. Start a new stitch with 'stitch start <title>' or switch to an existing one with 'stitch switch <id>'.");
2016
- this.name = "NoCurrentStitchError";
2017
- }
2018
- }
2019
-
2020
- class StitchNotFoundError extends StitchError {
2021
- constructor(id) {
2022
- super(`Stitch not found: ${id}`);
2023
- this.name = "StitchNotFoundError";
2024
- }
2025
- }
2026
-
2027
- class GitError extends StitchError {
2028
- command;
2029
- exitCode;
2030
- constructor(message, command, exitCode) {
2031
- super(`Git error: ${message}`);
2032
- this.command = command;
2033
- this.exitCode = exitCode;
2034
- this.name = "GitError";
2035
- }
2036
- }
2037
-
2038
- class ValidationError extends StitchError {
2039
- constructor(message) {
2040
- super(`Validation error: ${message}`);
2041
- this.name = "ValidationError";
2042
- }
2043
- }
2044
-
2045
1967
  // node_modules/smol-toml/dist/error.js
2046
- /*!
2047
- * Copyright (c) Squirrel Chat et al., All rights reserved.
2048
- * SPDX-License-Identifier: BSD-3-Clause
2049
- *
2050
- * Redistribution and use in source and binary forms, with or without
2051
- * modification, are permitted provided that the following conditions are met:
2052
- *
2053
- * 1. Redistributions of source code must retain the above copyright notice, this
2054
- * list of conditions and the following disclaimer.
2055
- * 2. Redistributions in binary form must reproduce the above copyright notice,
2056
- * this list of conditions and the following disclaimer in the
2057
- * documentation and/or other materials provided with the distribution.
2058
- * 3. Neither the name of the copyright holder nor the names of its contributors
2059
- * may be used to endorse or promote products derived from this software without
2060
- * specific prior written permission.
2061
- *
2062
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2063
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2064
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2065
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2066
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2067
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2068
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2069
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2070
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2071
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2072
- */
2073
1968
  function getLineColFromPtr(string, ptr) {
2074
1969
  let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g);
2075
1970
  return [lines.length, lines.pop().length + 1];
@@ -2095,51 +1990,53 @@ function makeCodeBlock(string, line, column) {
2095
1990
  }
2096
1991
  return codeblock;
2097
1992
  }
2098
-
2099
- class TomlError extends Error {
2100
- line;
2101
- column;
2102
- codeblock;
2103
- constructor(message, options) {
2104
- const [line, column] = getLineColFromPtr(options.toml, options.ptr);
2105
- const codeblock = makeCodeBlock(options.toml, line, column);
2106
- super(`Invalid TOML document: ${message}
1993
+ var TomlError;
1994
+ var init_error = __esm(() => {
1995
+ /*!
1996
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
1997
+ * SPDX-License-Identifier: BSD-3-Clause
1998
+ *
1999
+ * Redistribution and use in source and binary forms, with or without
2000
+ * modification, are permitted provided that the following conditions are met:
2001
+ *
2002
+ * 1. Redistributions of source code must retain the above copyright notice, this
2003
+ * list of conditions and the following disclaimer.
2004
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
2005
+ * this list of conditions and the following disclaimer in the
2006
+ * documentation and/or other materials provided with the distribution.
2007
+ * 3. Neither the name of the copyright holder nor the names of its contributors
2008
+ * may be used to endorse or promote products derived from this software without
2009
+ * specific prior written permission.
2010
+ *
2011
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2012
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2013
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2014
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2015
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2016
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2017
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2018
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2019
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2020
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2021
+ */
2022
+ TomlError = class TomlError extends Error {
2023
+ line;
2024
+ column;
2025
+ codeblock;
2026
+ constructor(message, options) {
2027
+ const [line, column] = getLineColFromPtr(options.toml, options.ptr);
2028
+ const codeblock = makeCodeBlock(options.toml, line, column);
2029
+ super(`Invalid TOML document: ${message}
2107
2030
 
2108
2031
  ${codeblock}`, options);
2109
- this.line = line;
2110
- this.column = column;
2111
- this.codeblock = codeblock;
2112
- }
2113
- }
2032
+ this.line = line;
2033
+ this.column = column;
2034
+ this.codeblock = codeblock;
2035
+ }
2036
+ };
2037
+ });
2114
2038
 
2115
2039
  // node_modules/smol-toml/dist/util.js
2116
- /*!
2117
- * Copyright (c) Squirrel Chat et al., All rights reserved.
2118
- * SPDX-License-Identifier: BSD-3-Clause
2119
- *
2120
- * Redistribution and use in source and binary forms, with or without
2121
- * modification, are permitted provided that the following conditions are met:
2122
- *
2123
- * 1. Redistributions of source code must retain the above copyright notice, this
2124
- * list of conditions and the following disclaimer.
2125
- * 2. Redistributions in binary form must reproduce the above copyright notice,
2126
- * this list of conditions and the following disclaimer in the
2127
- * documentation and/or other materials provided with the distribution.
2128
- * 3. Neither the name of the copyright holder nor the names of its contributors
2129
- * may be used to endorse or promote products derived from this software without
2130
- * specific prior written permission.
2131
- *
2132
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2133
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2134
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2135
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2136
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2137
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2138
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2139
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2140
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2141
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2142
- */
2143
2040
  function isEscaped(str, ptr) {
2144
2041
  let i = 0;
2145
2042
  while (str[ptr - ++i] === "\\")
@@ -2219,170 +2116,160 @@ function getStringEnd(str, seek) {
2219
2116
  }
2220
2117
  return seek;
2221
2118
  }
2119
+ var init_util = __esm(() => {
2120
+ init_error();
2121
+ /*!
2122
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
2123
+ * SPDX-License-Identifier: BSD-3-Clause
2124
+ *
2125
+ * Redistribution and use in source and binary forms, with or without
2126
+ * modification, are permitted provided that the following conditions are met:
2127
+ *
2128
+ * 1. Redistributions of source code must retain the above copyright notice, this
2129
+ * list of conditions and the following disclaimer.
2130
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
2131
+ * this list of conditions and the following disclaimer in the
2132
+ * documentation and/or other materials provided with the distribution.
2133
+ * 3. Neither the name of the copyright holder nor the names of its contributors
2134
+ * may be used to endorse or promote products derived from this software without
2135
+ * specific prior written permission.
2136
+ *
2137
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2138
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2139
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2140
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2141
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2142
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2143
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2144
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2145
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2146
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2147
+ */
2148
+ });
2222
2149
 
2223
2150
  // node_modules/smol-toml/dist/date.js
2224
- /*!
2225
- * Copyright (c) Squirrel Chat et al., All rights reserved.
2226
- * SPDX-License-Identifier: BSD-3-Clause
2227
- *
2228
- * Redistribution and use in source and binary forms, with or without
2229
- * modification, are permitted provided that the following conditions are met:
2230
- *
2231
- * 1. Redistributions of source code must retain the above copyright notice, this
2232
- * list of conditions and the following disclaimer.
2233
- * 2. Redistributions in binary form must reproduce the above copyright notice,
2234
- * this list of conditions and the following disclaimer in the
2235
- * documentation and/or other materials provided with the distribution.
2236
- * 3. Neither the name of the copyright holder nor the names of its contributors
2237
- * may be used to endorse or promote products derived from this software without
2238
- * specific prior written permission.
2239
- *
2240
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2241
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2242
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2243
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2244
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2245
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2246
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2247
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2248
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2249
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2250
- */
2251
- var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
2252
-
2253
- class TomlDate extends Date {
2254
- #hasDate = false;
2255
- #hasTime = false;
2256
- #offset = null;
2257
- constructor(date) {
2258
- let hasDate = true;
2259
- let hasTime = true;
2260
- let offset = "Z";
2261
- if (typeof date === "string") {
2262
- let match = date.match(DATE_TIME_RE);
2263
- if (match) {
2264
- if (!match[1]) {
2265
- hasDate = false;
2266
- date = `0000-01-01T${date}`;
2267
- }
2268
- hasTime = !!match[2];
2269
- hasTime && date[10] === " " && (date = date.replace(" ", "T"));
2270
- if (match[2] && +match[2] > 23) {
2271
- date = "";
2151
+ var DATE_TIME_RE, TomlDate;
2152
+ var init_date = __esm(() => {
2153
+ /*!
2154
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
2155
+ * SPDX-License-Identifier: BSD-3-Clause
2156
+ *
2157
+ * Redistribution and use in source and binary forms, with or without
2158
+ * modification, are permitted provided that the following conditions are met:
2159
+ *
2160
+ * 1. Redistributions of source code must retain the above copyright notice, this
2161
+ * list of conditions and the following disclaimer.
2162
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
2163
+ * this list of conditions and the following disclaimer in the
2164
+ * documentation and/or other materials provided with the distribution.
2165
+ * 3. Neither the name of the copyright holder nor the names of its contributors
2166
+ * may be used to endorse or promote products derived from this software without
2167
+ * specific prior written permission.
2168
+ *
2169
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2170
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2171
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2172
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2173
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2174
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2175
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2176
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2177
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2178
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2179
+ */
2180
+ DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
2181
+ TomlDate = class TomlDate extends Date {
2182
+ #hasDate = false;
2183
+ #hasTime = false;
2184
+ #offset = null;
2185
+ constructor(date) {
2186
+ let hasDate = true;
2187
+ let hasTime = true;
2188
+ let offset = "Z";
2189
+ if (typeof date === "string") {
2190
+ let match = date.match(DATE_TIME_RE);
2191
+ if (match) {
2192
+ if (!match[1]) {
2193
+ hasDate = false;
2194
+ date = `0000-01-01T${date}`;
2195
+ }
2196
+ hasTime = !!match[2];
2197
+ hasTime && date[10] === " " && (date = date.replace(" ", "T"));
2198
+ if (match[2] && +match[2] > 23) {
2199
+ date = "";
2200
+ } else {
2201
+ offset = match[3] || null;
2202
+ date = date.toUpperCase();
2203
+ if (!offset && hasTime)
2204
+ date += "Z";
2205
+ }
2272
2206
  } else {
2273
- offset = match[3] || null;
2274
- date = date.toUpperCase();
2275
- if (!offset && hasTime)
2276
- date += "Z";
2207
+ date = "";
2277
2208
  }
2278
- } else {
2279
- date = "";
2280
- }
2281
- }
2282
- super(date);
2283
- if (!isNaN(this.getTime())) {
2284
- this.#hasDate = hasDate;
2285
- this.#hasTime = hasTime;
2286
- this.#offset = offset;
2287
- }
2288
- }
2289
- isDateTime() {
2290
- return this.#hasDate && this.#hasTime;
2291
- }
2292
- isLocal() {
2293
- return !this.#hasDate || !this.#hasTime || !this.#offset;
2294
- }
2295
- isDate() {
2296
- return this.#hasDate && !this.#hasTime;
2297
- }
2298
- isTime() {
2299
- return this.#hasTime && !this.#hasDate;
2300
- }
2301
- isValid() {
2302
- return this.#hasDate || this.#hasTime;
2303
- }
2304
- toISOString() {
2305
- let iso = super.toISOString();
2306
- if (this.isDate())
2307
- return iso.slice(0, 10);
2308
- if (this.isTime())
2309
- return iso.slice(11, 23);
2310
- if (this.#offset === null)
2311
- return iso.slice(0, -1);
2312
- if (this.#offset === "Z")
2313
- return iso;
2314
- let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
2315
- offset = this.#offset[0] === "-" ? offset : -offset;
2316
- let offsetDate = new Date(this.getTime() - offset * 60000);
2317
- return offsetDate.toISOString().slice(0, -1) + this.#offset;
2318
- }
2319
- static wrapAsOffsetDateTime(jsDate, offset = "Z") {
2320
- let date = new TomlDate(jsDate);
2321
- date.#offset = offset;
2322
- return date;
2323
- }
2324
- static wrapAsLocalDateTime(jsDate) {
2325
- let date = new TomlDate(jsDate);
2326
- date.#offset = null;
2327
- return date;
2328
- }
2329
- static wrapAsLocalDate(jsDate) {
2330
- let date = new TomlDate(jsDate);
2331
- date.#hasTime = false;
2332
- date.#offset = null;
2333
- return date;
2334
- }
2335
- static wrapAsLocalTime(jsDate) {
2336
- let date = new TomlDate(jsDate);
2337
- date.#hasDate = false;
2338
- date.#offset = null;
2339
- return date;
2340
- }
2341
- }
2209
+ }
2210
+ super(date);
2211
+ if (!isNaN(this.getTime())) {
2212
+ this.#hasDate = hasDate;
2213
+ this.#hasTime = hasTime;
2214
+ this.#offset = offset;
2215
+ }
2216
+ }
2217
+ isDateTime() {
2218
+ return this.#hasDate && this.#hasTime;
2219
+ }
2220
+ isLocal() {
2221
+ return !this.#hasDate || !this.#hasTime || !this.#offset;
2222
+ }
2223
+ isDate() {
2224
+ return this.#hasDate && !this.#hasTime;
2225
+ }
2226
+ isTime() {
2227
+ return this.#hasTime && !this.#hasDate;
2228
+ }
2229
+ isValid() {
2230
+ return this.#hasDate || this.#hasTime;
2231
+ }
2232
+ toISOString() {
2233
+ let iso = super.toISOString();
2234
+ if (this.isDate())
2235
+ return iso.slice(0, 10);
2236
+ if (this.isTime())
2237
+ return iso.slice(11, 23);
2238
+ if (this.#offset === null)
2239
+ return iso.slice(0, -1);
2240
+ if (this.#offset === "Z")
2241
+ return iso;
2242
+ let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
2243
+ offset = this.#offset[0] === "-" ? offset : -offset;
2244
+ let offsetDate = new Date(this.getTime() - offset * 60000);
2245
+ return offsetDate.toISOString().slice(0, -1) + this.#offset;
2246
+ }
2247
+ static wrapAsOffsetDateTime(jsDate, offset = "Z") {
2248
+ let date = new TomlDate(jsDate);
2249
+ date.#offset = offset;
2250
+ return date;
2251
+ }
2252
+ static wrapAsLocalDateTime(jsDate) {
2253
+ let date = new TomlDate(jsDate);
2254
+ date.#offset = null;
2255
+ return date;
2256
+ }
2257
+ static wrapAsLocalDate(jsDate) {
2258
+ let date = new TomlDate(jsDate);
2259
+ date.#hasTime = false;
2260
+ date.#offset = null;
2261
+ return date;
2262
+ }
2263
+ static wrapAsLocalTime(jsDate) {
2264
+ let date = new TomlDate(jsDate);
2265
+ date.#hasDate = false;
2266
+ date.#offset = null;
2267
+ return date;
2268
+ }
2269
+ };
2270
+ });
2342
2271
 
2343
2272
  // node_modules/smol-toml/dist/primitive.js
2344
- /*!
2345
- * Copyright (c) Squirrel Chat et al., All rights reserved.
2346
- * SPDX-License-Identifier: BSD-3-Clause
2347
- *
2348
- * Redistribution and use in source and binary forms, with or without
2349
- * modification, are permitted provided that the following conditions are met:
2350
- *
2351
- * 1. Redistributions of source code must retain the above copyright notice, this
2352
- * list of conditions and the following disclaimer.
2353
- * 2. Redistributions in binary form must reproduce the above copyright notice,
2354
- * this list of conditions and the following disclaimer in the
2355
- * documentation and/or other materials provided with the distribution.
2356
- * 3. Neither the name of the copyright holder nor the names of its contributors
2357
- * may be used to endorse or promote products derived from this software without
2358
- * specific prior written permission.
2359
- *
2360
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2361
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2362
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2363
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2364
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2365
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2366
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2367
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2368
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2369
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2370
- */
2371
- var INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/;
2372
- var FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/;
2373
- var LEADING_ZERO = /^[+-]?0[0-9_]/;
2374
- var ESCAPE_REGEX = /^[0-9a-f]{2,8}$/i;
2375
- var ESC_MAP = {
2376
- b: "\b",
2377
- t: "\t",
2378
- n: `
2379
- `,
2380
- f: "\f",
2381
- r: "\r",
2382
- e: "\x1B",
2383
- '"': '"',
2384
- "\\": "\\"
2385
- };
2386
2273
  function parseString(str, ptr = 0, endPtr = str.length) {
2387
2274
  let isLiteral = str[ptr] === "'";
2388
2275
  let isMultiline = str[ptr++] === str[ptr] && str[ptr] === str[ptr + 1];
@@ -2511,35 +2398,56 @@ function parseValue(value, toml, ptr, integersAsBigInt) {
2511
2398
  }
2512
2399
  return date;
2513
2400
  }
2401
+ var INT_REGEX, FLOAT_REGEX, LEADING_ZERO, ESCAPE_REGEX, ESC_MAP;
2402
+ var init_primitive = __esm(() => {
2403
+ init_util();
2404
+ init_date();
2405
+ init_error();
2406
+ /*!
2407
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
2408
+ * SPDX-License-Identifier: BSD-3-Clause
2409
+ *
2410
+ * Redistribution and use in source and binary forms, with or without
2411
+ * modification, are permitted provided that the following conditions are met:
2412
+ *
2413
+ * 1. Redistributions of source code must retain the above copyright notice, this
2414
+ * list of conditions and the following disclaimer.
2415
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
2416
+ * this list of conditions and the following disclaimer in the
2417
+ * documentation and/or other materials provided with the distribution.
2418
+ * 3. Neither the name of the copyright holder nor the names of its contributors
2419
+ * may be used to endorse or promote products derived from this software without
2420
+ * specific prior written permission.
2421
+ *
2422
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2423
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2424
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2425
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2426
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2427
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2428
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2429
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2430
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2431
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2432
+ */
2433
+ INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/;
2434
+ FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/;
2435
+ LEADING_ZERO = /^[+-]?0[0-9_]/;
2436
+ ESCAPE_REGEX = /^[0-9a-f]{2,8}$/i;
2437
+ ESC_MAP = {
2438
+ b: "\b",
2439
+ t: "\t",
2440
+ n: `
2441
+ `,
2442
+ f: "\f",
2443
+ r: "\r",
2444
+ e: "\x1B",
2445
+ '"': '"',
2446
+ "\\": "\\"
2447
+ };
2448
+ });
2514
2449
 
2515
2450
  // node_modules/smol-toml/dist/extract.js
2516
- /*!
2517
- * Copyright (c) Squirrel Chat et al., All rights reserved.
2518
- * SPDX-License-Identifier: BSD-3-Clause
2519
- *
2520
- * Redistribution and use in source and binary forms, with or without
2521
- * modification, are permitted provided that the following conditions are met:
2522
- *
2523
- * 1. Redistributions of source code must retain the above copyright notice, this
2524
- * list of conditions and the following disclaimer.
2525
- * 2. Redistributions in binary form must reproduce the above copyright notice,
2526
- * this list of conditions and the following disclaimer in the
2527
- * documentation and/or other materials provided with the distribution.
2528
- * 3. Neither the name of the copyright holder nor the names of its contributors
2529
- * may be used to endorse or promote products derived from this software without
2530
- * specific prior written permission.
2531
- *
2532
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2533
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2534
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2535
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2536
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2537
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2538
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2539
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2540
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2541
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2542
- */
2543
2451
  function sliceAndTrimEndOf(str, startPtr, endPtr) {
2544
2452
  let value = str.slice(startPtr, endPtr);
2545
2453
  let commentIdx = value.indexOf("#");
@@ -2606,36 +2514,41 @@ function extractValue(str, ptr, end, depth, integersAsBigInt) {
2606
2514
  endPtr
2607
2515
  ];
2608
2516
  }
2517
+ var init_extract = __esm(() => {
2518
+ init_primitive();
2519
+ init_struct();
2520
+ init_util();
2521
+ init_error();
2522
+ /*!
2523
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
2524
+ * SPDX-License-Identifier: BSD-3-Clause
2525
+ *
2526
+ * Redistribution and use in source and binary forms, with or without
2527
+ * modification, are permitted provided that the following conditions are met:
2528
+ *
2529
+ * 1. Redistributions of source code must retain the above copyright notice, this
2530
+ * list of conditions and the following disclaimer.
2531
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
2532
+ * this list of conditions and the following disclaimer in the
2533
+ * documentation and/or other materials provided with the distribution.
2534
+ * 3. Neither the name of the copyright holder nor the names of its contributors
2535
+ * may be used to endorse or promote products derived from this software without
2536
+ * specific prior written permission.
2537
+ *
2538
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2539
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2540
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2541
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2542
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2543
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2544
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2545
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2546
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2547
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2548
+ */
2549
+ });
2609
2550
 
2610
2551
  // node_modules/smol-toml/dist/struct.js
2611
- /*!
2612
- * Copyright (c) Squirrel Chat et al., All rights reserved.
2613
- * SPDX-License-Identifier: BSD-3-Clause
2614
- *
2615
- * Redistribution and use in source and binary forms, with or without
2616
- * modification, are permitted provided that the following conditions are met:
2617
- *
2618
- * 1. Redistributions of source code must retain the above copyright notice, this
2619
- * list of conditions and the following disclaimer.
2620
- * 2. Redistributions in binary form must reproduce the above copyright notice,
2621
- * this list of conditions and the following disclaimer in the
2622
- * documentation and/or other materials provided with the distribution.
2623
- * 3. Neither the name of the copyright holder nor the names of its contributors
2624
- * may be used to endorse or promote products derived from this software without
2625
- * specific prior written permission.
2626
- *
2627
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2628
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2629
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2630
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2631
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2632
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2633
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2634
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2635
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2636
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2637
- */
2638
- var KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
2639
2552
  function parseKey(str, ptr, end = "=") {
2640
2553
  let dot = ptr - 1;
2641
2554
  let parsed = [];
@@ -2783,35 +2696,43 @@ function parseArray(str, ptr, depth, integersAsBigInt) {
2783
2696
  }
2784
2697
  return [res, ptr];
2785
2698
  }
2699
+ var KEY_PART_RE;
2700
+ var init_struct = __esm(() => {
2701
+ init_primitive();
2702
+ init_extract();
2703
+ init_util();
2704
+ init_error();
2705
+ /*!
2706
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
2707
+ * SPDX-License-Identifier: BSD-3-Clause
2708
+ *
2709
+ * Redistribution and use in source and binary forms, with or without
2710
+ * modification, are permitted provided that the following conditions are met:
2711
+ *
2712
+ * 1. Redistributions of source code must retain the above copyright notice, this
2713
+ * list of conditions and the following disclaimer.
2714
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
2715
+ * this list of conditions and the following disclaimer in the
2716
+ * documentation and/or other materials provided with the distribution.
2717
+ * 3. Neither the name of the copyright holder nor the names of its contributors
2718
+ * may be used to endorse or promote products derived from this software without
2719
+ * specific prior written permission.
2720
+ *
2721
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2722
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2723
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2724
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2725
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2726
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2727
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2728
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2729
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2730
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2731
+ */
2732
+ KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
2733
+ });
2786
2734
 
2787
2735
  // node_modules/smol-toml/dist/parse.js
2788
- /*!
2789
- * Copyright (c) Squirrel Chat et al., All rights reserved.
2790
- * SPDX-License-Identifier: BSD-3-Clause
2791
- *
2792
- * Redistribution and use in source and binary forms, with or without
2793
- * modification, are permitted provided that the following conditions are met:
2794
- *
2795
- * 1. Redistributions of source code must retain the above copyright notice, this
2796
- * list of conditions and the following disclaimer.
2797
- * 2. Redistributions in binary form must reproduce the above copyright notice,
2798
- * this list of conditions and the following disclaimer in the
2799
- * documentation and/or other materials provided with the distribution.
2800
- * 3. Neither the name of the copyright holder nor the names of its contributors
2801
- * may be used to endorse or promote products derived from this software without
2802
- * specific prior written permission.
2803
- *
2804
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2805
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2806
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2807
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2808
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2809
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2810
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2811
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2812
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2813
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2814
- */
2815
2736
  function peekTable(key, table, meta, type) {
2816
2737
  let t = table;
2817
2738
  let m = meta;
@@ -2924,36 +2845,41 @@ function parse(toml, { maxDepth = 1000, integersAsBigInt } = {}) {
2924
2845
  }
2925
2846
  return res;
2926
2847
  }
2848
+ var init_parse = __esm(() => {
2849
+ init_struct();
2850
+ init_extract();
2851
+ init_util();
2852
+ init_error();
2853
+ /*!
2854
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
2855
+ * SPDX-License-Identifier: BSD-3-Clause
2856
+ *
2857
+ * Redistribution and use in source and binary forms, with or without
2858
+ * modification, are permitted provided that the following conditions are met:
2859
+ *
2860
+ * 1. Redistributions of source code must retain the above copyright notice, this
2861
+ * list of conditions and the following disclaimer.
2862
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
2863
+ * this list of conditions and the following disclaimer in the
2864
+ * documentation and/or other materials provided with the distribution.
2865
+ * 3. Neither the name of the copyright holder nor the names of its contributors
2866
+ * may be used to endorse or promote products derived from this software without
2867
+ * specific prior written permission.
2868
+ *
2869
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2870
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2871
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2872
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2873
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2874
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2875
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2876
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2877
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2878
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2879
+ */
2880
+ });
2927
2881
 
2928
2882
  // node_modules/smol-toml/dist/stringify.js
2929
- /*!
2930
- * Copyright (c) Squirrel Chat et al., All rights reserved.
2931
- * SPDX-License-Identifier: BSD-3-Clause
2932
- *
2933
- * Redistribution and use in source and binary forms, with or without
2934
- * modification, are permitted provided that the following conditions are met:
2935
- *
2936
- * 1. Redistributions of source code must retain the above copyright notice, this
2937
- * list of conditions and the following disclaimer.
2938
- * 2. Redistributions in binary form must reproduce the above copyright notice,
2939
- * this list of conditions and the following disclaimer in the
2940
- * documentation and/or other materials provided with the distribution.
2941
- * 3. Neither the name of the copyright holder nor the names of its contributors
2942
- * may be used to endorse or promote products derived from this software without
2943
- * specific prior written permission.
2944
- *
2945
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2946
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2947
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2948
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2949
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2950
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2951
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2952
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2953
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2954
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2955
- */
2956
- var BARE_KEY = /^[a-z0-9-_]+$/i;
2957
2883
  function extendedTypeOf(obj) {
2958
2884
  let type = typeof obj;
2959
2885
  if (type === "object") {
@@ -3098,38 +3024,80 @@ function stringify(obj, { maxDepth = 1000, numbersAsFloat = false } = {}) {
3098
3024
  `;
3099
3025
  return str;
3100
3026
  }
3027
+ var BARE_KEY;
3028
+ var init_stringify = __esm(() => {
3029
+ /*!
3030
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
3031
+ * SPDX-License-Identifier: BSD-3-Clause
3032
+ *
3033
+ * Redistribution and use in source and binary forms, with or without
3034
+ * modification, are permitted provided that the following conditions are met:
3035
+ *
3036
+ * 1. Redistributions of source code must retain the above copyright notice, this
3037
+ * list of conditions and the following disclaimer.
3038
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
3039
+ * this list of conditions and the following disclaimer in the
3040
+ * documentation and/or other materials provided with the distribution.
3041
+ * 3. Neither the name of the copyright holder nor the names of its contributors
3042
+ * may be used to endorse or promote products derived from this software without
3043
+ * specific prior written permission.
3044
+ *
3045
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
3046
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3047
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3048
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3049
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3050
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
3051
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
3052
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3053
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3054
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3055
+ */
3056
+ BARE_KEY = /^[a-z0-9-_]+$/i;
3057
+ });
3101
3058
 
3102
3059
  // node_modules/smol-toml/dist/index.js
3103
- /*!
3104
- * Copyright (c) Squirrel Chat et al., All rights reserved.
3105
- * SPDX-License-Identifier: BSD-3-Clause
3106
- *
3107
- * Redistribution and use in source and binary forms, with or without
3108
- * modification, are permitted provided that the following conditions are met:
3109
- *
3110
- * 1. Redistributions of source code must retain the above copyright notice, this
3111
- * list of conditions and the following disclaimer.
3112
- * 2. Redistributions in binary form must reproduce the above copyright notice,
3113
- * this list of conditions and the following disclaimer in the
3114
- * documentation and/or other materials provided with the distribution.
3115
- * 3. Neither the name of the copyright holder nor the names of its contributors
3116
- * may be used to endorse or promote products derived from this software without
3117
- * specific prior written permission.
3118
- *
3119
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
3120
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3121
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3122
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3123
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3124
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
3125
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
3126
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3127
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3128
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3129
- */
3060
+ var init_dist = __esm(() => {
3061
+ init_parse();
3062
+ init_stringify();
3063
+ init_date();
3064
+ init_error();
3065
+ /*!
3066
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
3067
+ * SPDX-License-Identifier: BSD-3-Clause
3068
+ *
3069
+ * Redistribution and use in source and binary forms, with or without
3070
+ * modification, are permitted provided that the following conditions are met:
3071
+ *
3072
+ * 1. Redistributions of source code must retain the above copyright notice, this
3073
+ * list of conditions and the following disclaimer.
3074
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
3075
+ * this list of conditions and the following disclaimer in the
3076
+ * documentation and/or other materials provided with the distribution.
3077
+ * 3. Neither the name of the copyright holder nor the names of its contributors
3078
+ * may be used to endorse or promote products derived from this software without
3079
+ * specific prior written permission.
3080
+ *
3081
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
3082
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3083
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3084
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
3085
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3086
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
3087
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
3088
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3089
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3090
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3091
+ */
3092
+ });
3130
3093
 
3131
3094
  // src/core/frontmatter.ts
3132
- var FRONTMATTER_DELIMITER = "+++";
3095
+ var exports_frontmatter = {};
3096
+ __export(exports_frontmatter, {
3097
+ updateTimestamp: () => updateTimestamp,
3098
+ serializeStitchFile: () => serializeStitchFile,
3099
+ parseStitchFile: () => parseStitchFile
3100
+ });
3133
3101
  function parseStitchFile(content) {
3134
3102
  const lines = content.split(`
3135
3103
  `);
@@ -3294,97 +3262,471 @@ function updateTimestamp(frontmatter) {
3294
3262
  updated_at: new Date().toISOString()
3295
3263
  };
3296
3264
  }
3265
+ var FRONTMATTER_DELIMITER = "+++";
3266
+ var init_frontmatter = __esm(() => {
3267
+ init_dist();
3268
+ init_errors();
3269
+ });
3297
3270
 
3298
- // src/core/ids.ts
3299
- function generateStitchId() {
3300
- const now = new Date;
3301
- const dateStr = formatDate(now);
3302
- const suffix = generateHexSuffix(4);
3303
- return `S-${dateStr}-${suffix}`;
3304
- }
3305
- function formatDate(date) {
3306
- const year = date.getFullYear();
3307
- const month = String(date.getMonth() + 1).padStart(2, "0");
3308
- const day = String(date.getDate()).padStart(2, "0");
3309
- return `${year}${month}${day}`;
3310
- }
3311
- function generateHexSuffix(length) {
3312
- const bytes = new Uint8Array(Math.ceil(length / 2));
3313
- crypto.getRandomValues(bytes);
3314
- return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, length);
3315
- }
3316
-
3317
- // src/core/model.ts
3318
- var DEFAULT_STITCH_BODY = `## Intent
3319
-
3320
- [Describe the goal or purpose of this change]
3321
-
3322
- ## Constraints
3323
-
3324
- - [List any constraints or requirements]
3325
-
3326
- ## Alternatives
3327
-
3328
- - [Document alternative approaches considered]
3329
-
3330
- ## Notes
3331
-
3332
- [Additional context or information]
3333
- `;
3334
-
3335
- // src/core/store.ts
3336
- var STITCH_DIR = ".stitch";
3337
- var STITCHES_SUBDIR = "stitches";
3338
- var CURRENT_FILE = "current";
3339
- function getStitchDir(repoRoot) {
3340
- return join(repoRoot, STITCH_DIR);
3341
- }
3342
- function getStitchesDir(repoRoot) {
3343
- return join(repoRoot, STITCH_DIR, STITCHES_SUBDIR);
3344
- }
3345
- function getCurrentFilePath(repoRoot) {
3346
- return join(repoRoot, STITCH_DIR, CURRENT_FILE);
3347
- }
3348
- function isInitialized(repoRoot) {
3349
- return existsSync(getStitchDir(repoRoot));
3350
- }
3351
- async function initializeStitch(repoRoot) {
3352
- const stitchesDir = getStitchesDir(repoRoot);
3353
- const currentPath = getCurrentFilePath(repoRoot);
3354
- await mkdir(stitchesDir, { recursive: true });
3355
- if (!existsSync(currentPath)) {
3356
- await writeFile(currentPath, "", "utf-8");
3357
- }
3358
- }
3359
- async function getCurrentStitchId(repoRoot) {
3360
- if (!isInitialized(repoRoot)) {
3361
- throw new NotInitializedError;
3362
- }
3363
- const currentPath = getCurrentFilePath(repoRoot);
3364
- const content = await readFile(currentPath, "utf-8");
3365
- const trimmed = content.trim();
3366
- return trimmed || null;
3367
- }
3368
- async function setCurrentStitchId(repoRoot, id) {
3369
- if (!isInitialized(repoRoot)) {
3370
- throw new NotInitializedError;
3371
- }
3372
- const currentPath = getCurrentFilePath(repoRoot);
3373
- await writeFile(currentPath, id ?? "", "utf-8");
3374
- }
3375
- function getStitchFilePath(repoRoot, id) {
3376
- return join(getStitchesDir(repoRoot), `${id}.md`);
3377
- }
3378
- async function createStitch(repoRoot, title, parentId) {
3379
- if (!isInitialized(repoRoot)) {
3380
- throw new NotInitializedError;
3381
- }
3382
- const id = generateStitchId();
3383
- const now = new Date().toISOString();
3384
- const frontmatter = {
3385
- id,
3386
- title,
3387
- status: "open",
3271
+ // package.json
3272
+ var require_package = __commonJS((exports, module) => {
3273
+ module.exports = {
3274
+ name: "@captainsafia/stitch",
3275
+ version: "1.0.0-preview.f2fe33d",
3276
+ type: "module",
3277
+ description: "A local-first CLI for recording intent and binding it to git commits/diffs",
3278
+ main: "dist/api.js",
3279
+ types: "dist/api.d.ts",
3280
+ bin: {
3281
+ stitch: "dist/cli.js",
3282
+ "stitch-mcp": "dist/mcp.js"
3283
+ },
3284
+ files: [
3285
+ "dist"
3286
+ ],
3287
+ exports: {
3288
+ ".": {
3289
+ types: "./dist/api.d.ts",
3290
+ import: "./dist/api.js"
3291
+ }
3292
+ },
3293
+ scripts: {
3294
+ build: "bun run build:api && bun run build:cli && bun run build:mcp",
3295
+ "build:api": "bun build src/api.ts --outdir dist --target bun && dts-bundle-generator -o dist/api.d.ts src/api.ts",
3296
+ "build:cli": "bun build src/cli.ts --outdir dist --target bun",
3297
+ "build:mcp": "bun build src/mcp.ts --outdir dist --target bun",
3298
+ compile: "bun run compile:cli && bun run compile:mcp",
3299
+ "compile:cli": "bun build src/cli.ts --compile --outfile stitch",
3300
+ "compile:mcp": "bun build src/mcp.ts --compile --outfile stitch-mcp",
3301
+ "compile:cli:linux-x64": "bun build src/cli.ts --compile --target=bun-linux-x64 --outfile stitch-linux-x64",
3302
+ "compile:cli:linux-arm64": "bun build src/cli.ts --compile --target=bun-linux-arm64 --outfile stitch-linux-arm64",
3303
+ "compile:cli:darwin-x64": "bun build src/cli.ts --compile --target=bun-darwin-x64 --outfile stitch-darwin-x64",
3304
+ "compile:cli:darwin-arm64": "bun build src/cli.ts --compile --target=bun-darwin-arm64 --outfile stitch-darwin-arm64",
3305
+ "compile:cli:windows-x64": "bun build src/cli.ts --compile --target=bun-windows-x64 --outfile stitch-windows-x64.exe",
3306
+ "compile:mcp:linux-x64": "bun build src/mcp.ts --compile --target=bun-linux-x64 --outfile stitch-mcp-linux-x64",
3307
+ "compile:mcp:linux-arm64": "bun build src/mcp.ts --compile --target=bun-linux-arm64 --outfile stitch-mcp-linux-arm64",
3308
+ "compile:mcp:darwin-x64": "bun build src/mcp.ts --compile --target=bun-darwin-x64 --outfile stitch-mcp-darwin-x64",
3309
+ "compile:mcp:darwin-arm64": "bun build src/mcp.ts --compile --target=bun-darwin-arm64 --outfile stitch-mcp-darwin-arm64",
3310
+ "compile:mcp:windows-x64": "bun build src/mcp.ts --compile --target=bun-windows-x64 --outfile stitch-mcp-windows-x64.exe",
3311
+ test: "bun test",
3312
+ typecheck: "tsc --noEmit"
3313
+ },
3314
+ devDependencies: {
3315
+ "@types/bun": "latest",
3316
+ "dts-bundle-generator": "^9.5.1",
3317
+ typescript: "^5"
3318
+ },
3319
+ dependencies: {
3320
+ "@modelcontextprotocol/sdk": "^1.25.1",
3321
+ "async-mutex": "^0.5.0",
3322
+ commander: "^12.0.0",
3323
+ "gh-release-update-notifier": "^1.0.0",
3324
+ "smol-toml": "^1.3.0",
3325
+ zod: "^4.2.1"
3326
+ },
3327
+ license: "MIT",
3328
+ repository: {
3329
+ type: "git",
3330
+ url: "https://github.com/captainsafia/stitch.git"
3331
+ },
3332
+ keywords: [
3333
+ "git",
3334
+ "intent",
3335
+ "dag",
3336
+ "cli",
3337
+ "developer-tools"
3338
+ ],
3339
+ engines: {
3340
+ bun: ">=1.0.0"
3341
+ }
3342
+ };
3343
+ });
3344
+
3345
+ // src/cli.ts
3346
+ import { join as join6 } from "path";
3347
+
3348
+ // node_modules/commander/esm.mjs
3349
+ var import__ = __toESM(require_commander(), 1);
3350
+ var {
3351
+ program,
3352
+ createCommand,
3353
+ createArgument,
3354
+ createOption,
3355
+ CommanderError,
3356
+ InvalidArgumentError,
3357
+ InvalidOptionArgumentError,
3358
+ Command,
3359
+ Argument,
3360
+ Option,
3361
+ Help
3362
+ } = import__.default;
3363
+
3364
+ // node_modules/gh-release-update-notifier/dist/index.mjs
3365
+ import { existsSync, readFileSync, writeFileSync } from "fs";
3366
+ var ReleaseNotifier = class {
3367
+ repo;
3368
+ checkInterval;
3369
+ cacheFilePath;
3370
+ token;
3371
+ cachedReleases = null;
3372
+ lastFetchTime = 0;
3373
+ constructor(config) {
3374
+ this.repo = config.repo;
3375
+ this.checkInterval = config.checkInterval ?? 3600000;
3376
+ this.cacheFilePath = config.cacheFilePath ?? null;
3377
+ this.token = config.token ?? null;
3378
+ this.loadCacheFromDisk();
3379
+ }
3380
+ async getLatestRelease(includePrerelease = false) {
3381
+ try {
3382
+ const validReleases = (await this.fetchAllReleases()).filter((release) => {
3383
+ if (release.draft)
3384
+ return false;
3385
+ if (!includePrerelease && release.prerelease)
3386
+ return false;
3387
+ return true;
3388
+ });
3389
+ if (validReleases.length === 0)
3390
+ return null;
3391
+ const latest = validReleases[0];
3392
+ return {
3393
+ tagName: latest.tag_name,
3394
+ name: latest.name,
3395
+ prerelease: latest.prerelease,
3396
+ draft: latest.draft,
3397
+ htmlUrl: latest.html_url,
3398
+ publishedAt: latest.published_at
3399
+ };
3400
+ } catch (error) {
3401
+ throw new Error(`Failed to fetch releases: ${error instanceof Error ? error.message : String(error)}`);
3402
+ }
3403
+ }
3404
+ async getLatestPrerelease() {
3405
+ try {
3406
+ const prerelease = (await this.fetchAllReleases()).find((release) => release.prerelease && !release.draft);
3407
+ if (!prerelease)
3408
+ return null;
3409
+ return {
3410
+ tagName: prerelease.tag_name,
3411
+ name: prerelease.name,
3412
+ prerelease: prerelease.prerelease,
3413
+ draft: prerelease.draft,
3414
+ htmlUrl: prerelease.html_url,
3415
+ publishedAt: prerelease.published_at
3416
+ };
3417
+ } catch (error) {
3418
+ throw new Error(`Failed to fetch prereleases: ${error instanceof Error ? error.message : String(error)}`);
3419
+ }
3420
+ }
3421
+ async checkVersion(currentVersion, isPrerelease = false) {
3422
+ try {
3423
+ const releases = await this.fetchAllReleases();
3424
+ if (releases.length === 0)
3425
+ return {
3426
+ updateAvailable: false,
3427
+ currentVersion,
3428
+ latestVersion: null,
3429
+ latestRelease: null
3430
+ };
3431
+ const normalizedCurrent = this.normalizeVersion(currentVersion);
3432
+ const currentRelease = releases.find((r) => this.normalizeVersion(r.tag_name) === normalizedCurrent || r.tag_name === currentVersion);
3433
+ const latestRelease = isPrerelease ? releases.find((r) => r.prerelease && !r.draft) : releases.find((r) => !r.prerelease && !r.draft);
3434
+ if (!latestRelease)
3435
+ return {
3436
+ updateAvailable: false,
3437
+ currentVersion,
3438
+ latestVersion: null,
3439
+ latestRelease: null
3440
+ };
3441
+ const latest = {
3442
+ tagName: latestRelease.tag_name,
3443
+ name: latestRelease.name,
3444
+ prerelease: latestRelease.prerelease,
3445
+ draft: latestRelease.draft,
3446
+ htmlUrl: latestRelease.html_url,
3447
+ publishedAt: latestRelease.published_at
3448
+ };
3449
+ if (!currentRelease)
3450
+ return {
3451
+ updateAvailable: true,
3452
+ currentVersion,
3453
+ latestVersion: latestRelease.tag_name,
3454
+ latestRelease: latest
3455
+ };
3456
+ return {
3457
+ updateAvailable: this.isVersionOlder(currentRelease.published_at, latestRelease.published_at),
3458
+ currentVersion,
3459
+ latestVersion: latestRelease.tag_name,
3460
+ latestRelease: latest
3461
+ };
3462
+ } catch (error) {
3463
+ throw new Error(`Failed to check version: ${error instanceof Error ? error.message : String(error)}`);
3464
+ }
3465
+ }
3466
+ async fetchAllReleases() {
3467
+ const now = Date.now();
3468
+ if (this.cachedReleases !== null && this.checkInterval > 0 && now - this.lastFetchTime < this.checkInterval)
3469
+ return this.cachedReleases;
3470
+ const headers = {
3471
+ Accept: "application/vnd.github+json",
3472
+ "X-GitHub-Api-Version": "2022-11-28"
3473
+ };
3474
+ if (this.token)
3475
+ headers["Authorization"] = `Bearer ${this.token}`;
3476
+ const response = await fetch(`https://api.github.com/repos/${this.repo}/releases`, { headers });
3477
+ if (!response.ok)
3478
+ throw new Error(`GitHub API error: ${response.status} ${response.statusText}`);
3479
+ const releases = await response.json();
3480
+ releases.sort((a, b) => new Date(b.published_at).getTime() - new Date(a.published_at).getTime());
3481
+ this.cachedReleases = releases;
3482
+ this.lastFetchTime = now;
3483
+ this.saveCacheToDisk();
3484
+ return releases;
3485
+ }
3486
+ clearCache() {
3487
+ this.cachedReleases = null;
3488
+ this.lastFetchTime = 0;
3489
+ this.saveCacheToDisk();
3490
+ }
3491
+ loadCacheFromDisk() {
3492
+ if (!this.cacheFilePath)
3493
+ return;
3494
+ try {
3495
+ if (existsSync(this.cacheFilePath)) {
3496
+ const data = readFileSync(this.cacheFilePath, "utf-8");
3497
+ const cache = JSON.parse(data);
3498
+ this.cachedReleases = cache.releases;
3499
+ this.lastFetchTime = cache.lastFetchTime;
3500
+ }
3501
+ } catch {
3502
+ this.cachedReleases = null;
3503
+ this.lastFetchTime = 0;
3504
+ }
3505
+ }
3506
+ saveCacheToDisk() {
3507
+ if (!this.cacheFilePath)
3508
+ return;
3509
+ try {
3510
+ if (this.cachedReleases === null)
3511
+ writeFileSync(this.cacheFilePath, JSON.stringify({
3512
+ lastFetchTime: 0,
3513
+ releases: []
3514
+ }), "utf-8");
3515
+ else {
3516
+ const cache = {
3517
+ lastFetchTime: this.lastFetchTime,
3518
+ releases: this.cachedReleases
3519
+ };
3520
+ writeFileSync(this.cacheFilePath, JSON.stringify(cache), "utf-8");
3521
+ }
3522
+ } catch {}
3523
+ }
3524
+ normalizeVersion(version) {
3525
+ return version.trim().replace(/^v/i, "");
3526
+ }
3527
+ isVersionOlder(date1, date2) {
3528
+ return new Date(date1).getTime() < new Date(date2).getTime();
3529
+ }
3530
+ };
3531
+
3532
+ // src/api.ts
3533
+ import { spawn } from "child_process";
3534
+
3535
+ // src/core/store.ts
3536
+ init_errors();
3537
+ init_frontmatter();
3538
+ import { readdir, readFile as readFile2, writeFile as writeFile2, mkdir } from "fs/promises";
3539
+ import { join as join2 } from "path";
3540
+ import { existsSync as existsSync3 } from "fs";
3541
+
3542
+ // src/core/ids.ts
3543
+ function generateStitchId() {
3544
+ const now = new Date;
3545
+ const dateStr = formatDate(now);
3546
+ const suffix = generateHexSuffix(4);
3547
+ return `S-${dateStr}-${suffix}`;
3548
+ }
3549
+ function formatDate(date) {
3550
+ const year = date.getFullYear();
3551
+ const month = String(date.getMonth() + 1).padStart(2, "0");
3552
+ const day = String(date.getDate()).padStart(2, "0");
3553
+ return `${year}${month}${day}`;
3554
+ }
3555
+ function generateHexSuffix(length) {
3556
+ const bytes = new Uint8Array(Math.ceil(length / 2));
3557
+ crypto.getRandomValues(bytes);
3558
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, length);
3559
+ }
3560
+
3561
+ // src/core/model.ts
3562
+ var DEFAULT_STITCH_BODY = `## Intent
3563
+
3564
+ [Describe the goal or purpose of this change]
3565
+
3566
+ ## Constraints
3567
+
3568
+ - [List any constraints or requirements]
3569
+
3570
+ ## Alternatives
3571
+
3572
+ - [Document alternative approaches considered]
3573
+
3574
+ ## Notes
3575
+
3576
+ [Additional context or information]
3577
+ `;
3578
+
3579
+ // src/core/indexing.ts
3580
+ import { readFile, writeFile } from "fs/promises";
3581
+ import { existsSync as existsSync2 } from "fs";
3582
+ import { join } from "path";
3583
+ init_errors();
3584
+ var INDEX_FILE = "index.json";
3585
+ var INDEX_VERSION = 1;
3586
+ function getIndexFilePath(repoRoot) {
3587
+ if (!isInitialized(repoRoot)) {
3588
+ throw new NotInitializedError;
3589
+ }
3590
+ return join(getStitchDir(repoRoot), INDEX_FILE);
3591
+ }
3592
+ function createEmptyIndex() {
3593
+ return {
3594
+ version: INDEX_VERSION,
3595
+ children: {},
3596
+ updated_at: new Date().toISOString()
3597
+ };
3598
+ }
3599
+ async function loadIndex(repoRoot) {
3600
+ const indexPath = getIndexFilePath(repoRoot);
3601
+ if (!existsSync2(indexPath)) {
3602
+ return null;
3603
+ }
3604
+ try {
3605
+ const content = await readFile(indexPath, "utf-8");
3606
+ const parsed = JSON.parse(content);
3607
+ if (parsed.version !== INDEX_VERSION) {
3608
+ return null;
3609
+ }
3610
+ return parsed;
3611
+ } catch {
3612
+ return null;
3613
+ }
3614
+ }
3615
+ async function saveIndex(repoRoot, index) {
3616
+ const indexPath = getIndexFilePath(repoRoot);
3617
+ const content = JSON.stringify(index, null, 2);
3618
+ await writeFile(indexPath, content, "utf-8");
3619
+ }
3620
+ async function rebuildIndex(repoRoot) {
3621
+ const stitches = await listStitches(repoRoot);
3622
+ const index = createEmptyIndex();
3623
+ for (const doc of stitches) {
3624
+ const parentId = doc.frontmatter.relations?.parent;
3625
+ if (parentId) {
3626
+ if (!index.children[parentId]) {
3627
+ index.children[parentId] = [];
3628
+ }
3629
+ index.children[parentId].push(doc.frontmatter.id);
3630
+ }
3631
+ }
3632
+ await saveIndex(repoRoot, index);
3633
+ return index;
3634
+ }
3635
+ async function getIndex(repoRoot) {
3636
+ let index = await loadIndex(repoRoot);
3637
+ if (!index) {
3638
+ index = await rebuildIndex(repoRoot);
3639
+ }
3640
+ return index;
3641
+ }
3642
+ async function getChildren(repoRoot, id) {
3643
+ const index = await getIndex(repoRoot);
3644
+ return index.children[id] ?? [];
3645
+ }
3646
+ async function getDescendants(repoRoot, id) {
3647
+ const index = await getIndex(repoRoot);
3648
+ const descendants = [];
3649
+ const queue = [id];
3650
+ const visited = new Set;
3651
+ while (queue.length > 0) {
3652
+ const currentId = queue.shift();
3653
+ if (visited.has(currentId)) {
3654
+ continue;
3655
+ }
3656
+ visited.add(currentId);
3657
+ const children = index.children[currentId] ?? [];
3658
+ for (const childId of children) {
3659
+ descendants.push(childId);
3660
+ queue.push(childId);
3661
+ }
3662
+ }
3663
+ return descendants;
3664
+ }
3665
+ async function addChildToIndex(repoRoot, parentId, childId) {
3666
+ const index = await getIndex(repoRoot);
3667
+ if (!index.children[parentId]) {
3668
+ index.children[parentId] = [];
3669
+ }
3670
+ if (!index.children[parentId].includes(childId)) {
3671
+ index.children[parentId].push(childId);
3672
+ index.updated_at = new Date().toISOString();
3673
+ await saveIndex(repoRoot, index);
3674
+ }
3675
+ }
3676
+
3677
+ // src/core/store.ts
3678
+ var STITCH_DIR = ".stitch";
3679
+ var STITCHES_SUBDIR = "stitches";
3680
+ var CURRENT_FILE = "current";
3681
+ function getStitchDir(repoRoot) {
3682
+ return join2(repoRoot, STITCH_DIR);
3683
+ }
3684
+ function getStitchesDir(repoRoot) {
3685
+ return join2(repoRoot, STITCH_DIR, STITCHES_SUBDIR);
3686
+ }
3687
+ function getCurrentFilePath(repoRoot) {
3688
+ return join2(repoRoot, STITCH_DIR, CURRENT_FILE);
3689
+ }
3690
+ function isInitialized(repoRoot) {
3691
+ return existsSync3(getStitchDir(repoRoot));
3692
+ }
3693
+ async function initializeStitch(repoRoot) {
3694
+ const stitchesDir = getStitchesDir(repoRoot);
3695
+ const currentPath = getCurrentFilePath(repoRoot);
3696
+ await mkdir(stitchesDir, { recursive: true });
3697
+ if (!existsSync3(currentPath)) {
3698
+ await writeFile2(currentPath, "", "utf-8");
3699
+ }
3700
+ }
3701
+ async function getCurrentStitchId(repoRoot) {
3702
+ if (!isInitialized(repoRoot)) {
3703
+ throw new NotInitializedError;
3704
+ }
3705
+ const currentPath = getCurrentFilePath(repoRoot);
3706
+ const content = await readFile2(currentPath, "utf-8");
3707
+ const trimmed = content.trim();
3708
+ return trimmed || null;
3709
+ }
3710
+ async function setCurrentStitchId(repoRoot, id) {
3711
+ if (!isInitialized(repoRoot)) {
3712
+ throw new NotInitializedError;
3713
+ }
3714
+ const currentPath = getCurrentFilePath(repoRoot);
3715
+ await writeFile2(currentPath, id ?? "", "utf-8");
3716
+ }
3717
+ function getStitchFilePath(repoRoot, id) {
3718
+ return join2(getStitchesDir(repoRoot), `${id}.md`);
3719
+ }
3720
+ async function createStitch(repoRoot, title, parentId) {
3721
+ if (!isInitialized(repoRoot)) {
3722
+ throw new NotInitializedError;
3723
+ }
3724
+ const id = generateStitchId();
3725
+ const now = new Date().toISOString();
3726
+ const frontmatter = {
3727
+ id,
3728
+ title,
3729
+ status: "open",
3388
3730
  created_at: now,
3389
3731
  updated_at: now,
3390
3732
  provenance: "human",
@@ -3395,7 +3737,10 @@ async function createStitch(repoRoot, title, parentId) {
3395
3737
  }
3396
3738
  const filePath = getStitchFilePath(repoRoot, id);
3397
3739
  const content = serializeStitchFile(frontmatter, DEFAULT_STITCH_BODY);
3398
- await writeFile(filePath, content, "utf-8");
3740
+ await writeFile2(filePath, content, "utf-8");
3741
+ if (parentId) {
3742
+ await addChildToIndex(repoRoot, parentId, id);
3743
+ }
3399
3744
  return {
3400
3745
  frontmatter,
3401
3746
  body: DEFAULT_STITCH_BODY,
@@ -3407,10 +3752,10 @@ async function loadStitch(repoRoot, id) {
3407
3752
  throw new NotInitializedError;
3408
3753
  }
3409
3754
  const filePath = getStitchFilePath(repoRoot, id);
3410
- if (!existsSync(filePath)) {
3755
+ if (!existsSync3(filePath)) {
3411
3756
  throw new StitchNotFoundError(id);
3412
3757
  }
3413
- const content = await readFile(filePath, "utf-8");
3758
+ const content = await readFile2(filePath, "utf-8");
3414
3759
  const { frontmatter, body } = parseStitchFile(content);
3415
3760
  return { frontmatter, body, filePath };
3416
3761
  }
@@ -3420,7 +3765,7 @@ async function saveStitch(repoRoot, doc) {
3420
3765
  }
3421
3766
  const updatedFrontmatter = updateTimestamp(doc.frontmatter);
3422
3767
  const content = serializeStitchFile(updatedFrontmatter, doc.body);
3423
- await writeFile(doc.filePath, content, "utf-8");
3768
+ await writeFile2(doc.filePath, content, "utf-8");
3424
3769
  return {
3425
3770
  ...doc,
3426
3771
  frontmatter: updatedFrontmatter
@@ -3431,16 +3776,16 @@ async function listStitches(repoRoot, filter) {
3431
3776
  throw new NotInitializedError;
3432
3777
  }
3433
3778
  const stitchesDir = getStitchesDir(repoRoot);
3434
- if (!existsSync(stitchesDir)) {
3779
+ if (!existsSync3(stitchesDir)) {
3435
3780
  return [];
3436
3781
  }
3437
3782
  const files = await readdir(stitchesDir);
3438
3783
  const mdFiles = files.filter((f) => f.endsWith(".md"));
3439
3784
  const docs = [];
3440
3785
  for (const file of mdFiles) {
3441
- const filePath = join(stitchesDir, file);
3786
+ const filePath = join2(stitchesDir, file);
3442
3787
  try {
3443
- const content = await readFile(filePath, "utf-8");
3788
+ const content = await readFile2(filePath, "utf-8");
3444
3789
  const { frontmatter, body } = parseStitchFile(content);
3445
3790
  if (filter?.status && frontmatter.status !== filter.status) {
3446
3791
  continue;
@@ -3481,6 +3826,7 @@ async function requireCurrentStitchId(repoRoot) {
3481
3826
  }
3482
3827
 
3483
3828
  // src/core/git.ts
3829
+ init_errors();
3484
3830
  var {$ } = globalThis.Bun;
3485
3831
  async function getRepoRoot(cwd) {
3486
3832
  try {
@@ -3568,6 +3914,7 @@ async function getCommitsInRange(range, repoRoot) {
3568
3914
  }
3569
3915
 
3570
3916
  // src/core/link.ts
3917
+ init_errors();
3571
3918
  async function addCommitLink(repoRoot, doc, sha) {
3572
3919
  const exists = await commitExists(sha, repoRoot);
3573
3920
  if (!exists) {
@@ -3683,30 +4030,180 @@ async function stitchBlame(repoRoot, filePath) {
3683
4030
 
3684
4031
  // src/platform/paths.ts
3685
4032
  import { homedir } from "os";
3686
- import { join as join2 } from "path";
4033
+ import { join as join3 } from "path";
3687
4034
  function getConfigDir() {
3688
4035
  const platform = process.platform;
3689
4036
  if (platform === "darwin") {
3690
- return join2(homedir(), "Library", "Application Support", "stitch");
4037
+ return join3(homedir(), "Library", "Application Support", "stitch");
3691
4038
  }
3692
4039
  if (platform === "win32") {
3693
4040
  const appData = process.env["APPDATA"];
3694
4041
  if (appData) {
3695
- return join2(appData, "stitch");
4042
+ return join3(appData, "stitch");
3696
4043
  }
3697
- return join2(homedir(), "AppData", "Roaming", "stitch");
4044
+ return join3(homedir(), "AppData", "Roaming", "stitch");
3698
4045
  }
3699
4046
  const xdgConfig = process.env["XDG_CONFIG_HOME"];
3700
4047
  if (xdgConfig) {
3701
- return join2(xdgConfig, "stitch");
4048
+ return join3(xdgConfig, "stitch");
3702
4049
  }
3703
- return join2(homedir(), ".config", "stitch");
4050
+ return join3(homedir(), ".config", "stitch");
3704
4051
  }
3705
4052
  function getEditor() {
3706
4053
  return process.env["VISUAL"] ?? process.env["EDITOR"] ?? (process.platform === "win32" ? "notepad" : "vi");
3707
4054
  }
3708
4055
 
3709
4056
  // src/api.ts
4057
+ init_errors();
4058
+
4059
+ // src/core/finish.ts
4060
+ import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
4061
+ init_frontmatter();
4062
+ init_errors();
4063
+ function hasLinkedCommits(doc) {
4064
+ const links = doc.frontmatter.git?.links;
4065
+ return links !== undefined && links.length > 0;
4066
+ }
4067
+ async function shouldAutoAbandon(doc, descendants) {
4068
+ if (!hasLinkedCommits(doc)) {
4069
+ return { autoAbandon: true, reason: "No linked commits" };
4070
+ }
4071
+ const openDescendants = descendants.filter((d) => d.frontmatter.status === "open");
4072
+ if (openDescendants.length > 0) {
4073
+ return { autoAbandon: true, reason: `Has ${openDescendants.length} open children` };
4074
+ }
4075
+ return { autoAbandon: false };
4076
+ }
4077
+ async function prepareFinish(repoRoot, id, options = {}) {
4078
+ if (!isInitialized(repoRoot)) {
4079
+ throw new NotInitializedError;
4080
+ }
4081
+ const { status = "closed", supersededBy, force = false } = options;
4082
+ const warnings = [];
4083
+ if (supersededBy && status !== "superseded") {
4084
+ throw new InvalidSupersededByError;
4085
+ }
4086
+ if (supersededBy) {
4087
+ try {
4088
+ await loadStitch(repoRoot, supersededBy);
4089
+ } catch (error) {
4090
+ if (error instanceof StitchNotFoundError) {
4091
+ throw new StitchError(`Superseding stitch '${supersededBy}' not found`);
4092
+ }
4093
+ throw error;
4094
+ }
4095
+ }
4096
+ const target = await loadStitch(repoRoot, id);
4097
+ const descendantIds = await getDescendants(repoRoot, id);
4098
+ const descendants = [];
4099
+ for (const descId of descendantIds) {
4100
+ try {
4101
+ const doc = await loadStitch(repoRoot, descId);
4102
+ descendants.push(doc);
4103
+ } catch {
4104
+ warnings.push(`Warning: Could not load descendant '${descId}'`);
4105
+ }
4106
+ }
4107
+ let finalStatus = status;
4108
+ let autoDetected = false;
4109
+ let forceRequired;
4110
+ const autoAbandonCheck = await shouldAutoAbandon(target, descendants);
4111
+ if (autoAbandonCheck.autoAbandon) {
4112
+ if (status !== "abandoned") {
4113
+ if (force) {
4114
+ warnings.push(`Warning: ${autoAbandonCheck.reason}. Forcing status to '${status}' as requested.`);
4115
+ } else {
4116
+ finalStatus = "abandoned";
4117
+ autoDetected = true;
4118
+ forceRequired = `Cannot set status to '${status}' when ${autoAbandonCheck.reason?.toLowerCase()}. Use --force to override, or --status=abandoned.`;
4119
+ warnings.push(`Warning: ${autoAbandonCheck.reason}. Marking as abandoned. Use --status=superseded if this work was replaced.`);
4120
+ }
4121
+ }
4122
+ }
4123
+ const affected = [target];
4124
+ for (const desc of descendants) {
4125
+ if (desc.frontmatter.status !== finalStatus) {
4126
+ affected.push(desc);
4127
+ }
4128
+ }
4129
+ const requiresConfirmation = affected.length >= 2;
4130
+ return {
4131
+ target,
4132
+ affected,
4133
+ finalStatus,
4134
+ autoDetected,
4135
+ warnings,
4136
+ requiresConfirmation,
4137
+ forceRequired: force ? undefined : forceRequired
4138
+ };
4139
+ }
4140
+ async function executeFinish(preview, options = {}) {
4141
+ const { supersededBy } = options;
4142
+ if (preview.forceRequired) {
4143
+ throw new FinishForceRequiredError(preview.forceRequired);
4144
+ }
4145
+ const updates = [];
4146
+ const finished = [];
4147
+ for (const doc of preview.affected) {
4148
+ const originalContent = await readFile3(doc.filePath, "utf-8");
4149
+ let updatedFrontmatter = {
4150
+ ...doc.frontmatter,
4151
+ status: preview.finalStatus
4152
+ };
4153
+ if (supersededBy && doc.frontmatter.id === preview.target.frontmatter.id) {
4154
+ const existingDependsOn = updatedFrontmatter.relations?.depends_on ?? [];
4155
+ if (!existingDependsOn.includes(supersededBy)) {
4156
+ updatedFrontmatter = {
4157
+ ...updatedFrontmatter,
4158
+ relations: {
4159
+ ...updatedFrontmatter.relations,
4160
+ depends_on: [...existingDependsOn, supersededBy]
4161
+ }
4162
+ };
4163
+ }
4164
+ }
4165
+ updatedFrontmatter = updateTimestamp(updatedFrontmatter);
4166
+ const updatedDoc = {
4167
+ ...doc,
4168
+ frontmatter: updatedFrontmatter
4169
+ };
4170
+ const { serializeStitchFile: serializeStitchFile2 } = await Promise.resolve().then(() => (init_frontmatter(), exports_frontmatter));
4171
+ const newContent = serializeStitchFile2(updatedFrontmatter, doc.body);
4172
+ updates.push({ doc: updatedDoc, originalContent, newContent });
4173
+ finished.push({
4174
+ id: doc.frontmatter.id,
4175
+ title: doc.frontmatter.title,
4176
+ previousStatus: doc.frontmatter.status,
4177
+ newStatus: preview.finalStatus
4178
+ });
4179
+ }
4180
+ const writtenPaths = [];
4181
+ try {
4182
+ for (const update of updates) {
4183
+ await writeFile3(update.doc.filePath, update.newContent, "utf-8");
4184
+ writtenPaths.push(update.doc.filePath);
4185
+ }
4186
+ } catch (error) {
4187
+ for (let i = 0;i < writtenPaths.length; i++) {
4188
+ try {
4189
+ const path = writtenPaths[i];
4190
+ const update = updates[i];
4191
+ await writeFile3(path, update.originalContent, "utf-8");
4192
+ } catch {}
4193
+ }
4194
+ throw error;
4195
+ }
4196
+ return {
4197
+ finished,
4198
+ warnings: preview.warnings,
4199
+ autoDetectedStatus: preview.autoDetected,
4200
+ finalStatus: preview.finalStatus
4201
+ };
4202
+ }
4203
+
4204
+ // src/api.ts
4205
+ init_errors();
4206
+
3710
4207
  class StitchClient {
3711
4208
  repoRoot = null;
3712
4209
  repoRootOverride;
@@ -3819,6 +4316,32 @@ class StitchClient {
3819
4316
  const root = await this.getRepoRoot();
3820
4317
  return stitchBlame(root, path);
3821
4318
  }
4319
+ async getChildren(id) {
4320
+ const root = await this.getRepoRoot();
4321
+ return getChildren(root, id);
4322
+ }
4323
+ async getDescendants(id) {
4324
+ const root = await this.getRepoRoot();
4325
+ return getDescendants(root, id);
4326
+ }
4327
+ async prepareFinish(id, options) {
4328
+ const root = await this.getRepoRoot();
4329
+ const stitchId = id ?? await requireCurrentStitchId(root);
4330
+ return prepareFinish(root, stitchId, options);
4331
+ }
4332
+ async executeFinish(preview, options) {
4333
+ const root = await this.getRepoRoot();
4334
+ const result = await executeFinish(preview, options);
4335
+ const currentId = await getCurrentStitchId(root);
4336
+ if (currentId && result.finished.some((f) => f.id === currentId)) {
4337
+ await setCurrentStitchId(root, null);
4338
+ }
4339
+ return result;
4340
+ }
4341
+ async finish(id, options) {
4342
+ const preview = await this.prepareFinish(id, options);
4343
+ return this.executeFinish(preview, options);
4344
+ }
3822
4345
  [Symbol.dispose]() {
3823
4346
  this.close();
3824
4347
  }
@@ -3966,147 +4489,69 @@ function truncate(str, maxLength) {
3966
4489
  function renderSuccess(message) {
3967
4490
  return `\u2713 ${message}`;
3968
4491
  }
3969
- // src/platform/update/version.ts
3970
- function parseVersion(version) {
3971
- const previewMatch = version.match(/^(\d+)\.(\d+)\.(\d+)(-preview\.([a-f0-9]+))?$/);
3972
- if (!previewMatch) {
3973
- throw new Error(`Invalid version format: ${version}`);
3974
- }
3975
- return {
3976
- major: parseInt(previewMatch[1], 10),
3977
- minor: parseInt(previewMatch[2], 10),
3978
- patch: parseInt(previewMatch[3], 10),
3979
- prerelease: previewMatch[5],
3980
- isPreview: !!previewMatch[4]
3981
- };
3982
- }
3983
- function compareVersions(a, b) {
3984
- const parsedA = parseVersion(a);
3985
- const parsedB = parseVersion(b);
3986
- if (parsedA.major !== parsedB.major) {
3987
- return parsedA.major < parsedB.major ? -1 : 1;
3988
- }
3989
- if (parsedA.minor !== parsedB.minor) {
3990
- return parsedA.minor < parsedB.minor ? -1 : 1;
3991
- }
3992
- if (parsedA.patch !== parsedB.patch) {
3993
- return parsedA.patch < parsedB.patch ? -1 : 1;
3994
- }
3995
- if (!parsedA.isPreview && parsedB.isPreview)
3996
- return 1;
3997
- if (parsedA.isPreview && !parsedB.isPreview)
3998
- return -1;
3999
- if (parsedA.prerelease && parsedB.prerelease) {
4000
- return parsedA.prerelease.localeCompare(parsedB.prerelease);
4001
- }
4002
- return 0;
4003
- }
4004
- function isUpdateAvailable(current, latest) {
4005
- return compareVersions(current, latest) < 0;
4006
- }
4007
- // src/platform/update/check.ts
4008
- import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
4009
- import { existsSync as existsSync2 } from "fs";
4010
- import { join as join3 } from "path";
4011
- var CACHE_FILE = "update-check.json";
4012
- var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
4013
- var GITHUB_API_URL = "https://api.github.com/repos/captainsafia/stitch/releases";
4014
- function getCacheFilePath() {
4015
- return join3(getConfigDir(), CACHE_FILE);
4492
+ function renderWarning(message) {
4493
+ return `\u26A0 ${message}`;
4016
4494
  }
4017
- async function readCache() {
4018
- const cachePath = getCacheFilePath();
4019
- if (!existsSync2(cachePath)) {
4020
- return null;
4495
+ function renderFinishPreview(preview) {
4496
+ const lines = [];
4497
+ lines.push(`This will finish ${preview.affected.length} stitch${preview.affected.length > 1 ? "es" : ""}:`);
4498
+ lines.push("");
4499
+ for (const doc of preview.affected) {
4500
+ const isTarget = doc.frontmatter.id === preview.target.frontmatter.id;
4501
+ const prefix = isTarget ? " \u2192 " : " ";
4502
+ const statusChange = doc.frontmatter.status !== preview.finalStatus ? ` (${doc.frontmatter.status} \u2192 ${preview.finalStatus})` : ` (already ${preview.finalStatus})`;
4503
+ lines.push(`${prefix}${doc.frontmatter.id}: ${truncate(doc.frontmatter.title, 40)}${statusChange}`);
4021
4504
  }
4022
- try {
4023
- const content = await readFile2(cachePath, "utf-8");
4024
- return JSON.parse(content);
4025
- } catch {
4026
- return null;
4505
+ if (preview.warnings.length > 0) {
4506
+ lines.push("");
4507
+ for (const warning of preview.warnings) {
4508
+ lines.push(renderWarning(warning));
4509
+ }
4027
4510
  }
4511
+ return lines.join(`
4512
+ `);
4028
4513
  }
4029
- async function writeCache(cache) {
4030
- const configDir = getConfigDir();
4031
- if (!existsSync2(configDir)) {
4032
- await mkdir2(configDir, { recursive: true });
4514
+ function renderFinishResult(result) {
4515
+ const lines = [];
4516
+ if (result.finished.length === 0) {
4517
+ return "No stitches were finished.";
4033
4518
  }
4034
- const cachePath = getCacheFilePath();
4035
- await writeFile2(cachePath, JSON.stringify(cache, null, 2), "utf-8");
4036
- }
4037
- function isCacheValid(cache) {
4038
- const now = Date.now();
4039
- return now - cache.lastChecked < CHECK_INTERVAL_MS;
4040
- }
4041
- async function fetchLatestRelease() {
4042
- try {
4043
- const response = await fetch(`${GITHUB_API_URL}/latest`, {
4044
- headers: {
4045
- Accept: "application/vnd.github.v3+json",
4046
- "User-Agent": "stitch-cli"
4047
- }
4048
- });
4049
- if (!response.ok) {
4050
- return null;
4051
- }
4052
- const data = await response.json();
4053
- return data.tag_name.replace(/^v/, "");
4054
- } catch {
4055
- return null;
4519
+ const targetStitch = result.finished[0];
4520
+ const childCount = result.finished.length - 1;
4521
+ lines.push(renderSuccess(`Finished stitch ${targetStitch.id} (status: ${result.finalStatus})`));
4522
+ lines.push(` Title: ${targetStitch.title}`);
4523
+ if (result.autoDetectedStatus) {
4524
+ lines.push(` Reason: Auto-detected based on stitch state`);
4056
4525
  }
4057
- }
4058
- async function fetchLatestPreviewRelease() {
4059
- try {
4060
- const response = await fetch(`${GITHUB_API_URL}?per_page=20`, {
4061
- headers: {
4062
- Accept: "application/vnd.github.v3+json",
4063
- "User-Agent": "stitch-cli"
4064
- }
4065
- });
4066
- if (!response.ok) {
4067
- return null;
4068
- }
4069
- const releases = await response.json();
4070
- for (const release of releases) {
4071
- const version = release.tag_name.replace(/^v/, "");
4072
- if (version.includes("-preview.")) {
4073
- return version;
4074
- }
4526
+ if (childCount > 0) {
4527
+ lines.push(` Children finished: ${childCount}`);
4528
+ for (let i = 1;i < result.finished.length; i++) {
4529
+ const child = result.finished[i];
4530
+ lines.push(` - ${child.id}: ${truncate(child.title, 30)}`);
4075
4531
  }
4076
- return null;
4077
- } catch {
4078
- return null;
4079
4532
  }
4080
- }
4081
- async function getLatestVersion(forceRefresh = false) {
4082
- if (!forceRefresh) {
4083
- const cache = await readCache();
4084
- if (cache && isCacheValid(cache)) {
4085
- return {
4086
- stable: cache.latestVersion,
4087
- preview: cache.latestPreviewVersion ?? null
4088
- };
4533
+ if (result.warnings.length > 0) {
4534
+ lines.push("");
4535
+ for (const warning of result.warnings) {
4536
+ if (!warning.startsWith("Warning:")) {
4537
+ lines.push(renderWarning(warning));
4538
+ } else {
4539
+ lines.push(`\u26A0 ${warning}`);
4540
+ }
4089
4541
  }
4090
4542
  }
4091
- const [stableVersion, previewVersion] = await Promise.all([
4092
- fetchLatestRelease(),
4093
- fetchLatestPreviewRelease()
4094
- ]);
4095
- if (stableVersion) {
4096
- const cache = {
4097
- lastChecked: Date.now(),
4098
- latestVersion: stableVersion,
4099
- latestPreviewVersion: previewVersion ?? undefined
4100
- };
4101
- writeCache(cache).catch(() => {});
4102
- }
4103
- return {
4104
- stable: stableVersion,
4105
- preview: previewVersion
4106
- };
4543
+ return lines.join(`
4544
+ `);
4107
4545
  }
4546
+
4547
+ // src/cli.ts
4548
+ init_errors();
4108
4549
  // src/platform/update/download.ts
4550
+ var {$: $2 } = globalThis.Bun;
4551
+ import { existsSync as existsSync4 } from "fs";
4552
+ import { join as join4 } from "path";
4109
4553
  var DOWNLOAD_BASE_URL = "https://github.com/captainsafia/stitch/releases/download";
4554
+ var REPO = "captainsafia/stitch";
4110
4555
  function detectPlatform() {
4111
4556
  const platform = process.platform;
4112
4557
  const arch = process.arch;
@@ -4185,48 +4630,98 @@ async function downloadBinary(url, destPath, onProgress) {
4185
4630
  }
4186
4631
  await Bun.write(destPath, binary);
4187
4632
  }
4633
+ async function downloadPRArtifact(prNumber, destPath, onProgress) {
4634
+ const ghCheck = await $2`which gh`.nothrow().quiet();
4635
+ if (ghCheck.exitCode !== 0) {
4636
+ throw new Error("GitHub CLI (gh) is required to download PR artifacts. Install it from https://cli.github.com/");
4637
+ }
4638
+ const platform = detectPlatform();
4639
+ const artifactName = `stitch-pr-${prNumber}-${platform}`;
4640
+ onProgress?.(`Downloading PR #${prNumber} artifact: ${artifactName}...`);
4641
+ const runsResult = await $2`gh run list --repo ${REPO} --workflow pr-publish.yml --json databaseId,status,conclusion,headBranch --limit 50`.nothrow().quiet();
4642
+ if (runsResult.exitCode !== 0) {
4643
+ throw new Error(`Failed to list workflow runs: ${runsResult.stderr.toString()}`);
4644
+ }
4645
+ const runs = JSON.parse(runsResult.stdout.toString());
4646
+ const { tmpdir } = await import("os");
4647
+ const { mkdtemp } = await import("fs/promises");
4648
+ const tmpDir = await mkdtemp(join4(tmpdir(), `stitch-pr-${prNumber}-`));
4649
+ try {
4650
+ let foundRun = null;
4651
+ for (const run of runs) {
4652
+ if (run.status === "completed" && run.conclusion === "success") {
4653
+ const downloadResult = await $2`gh run download ${run.databaseId} --repo ${REPO} --name ${artifactName} --dir ${tmpDir}`.nothrow().quiet();
4654
+ if (downloadResult.exitCode === 0) {
4655
+ foundRun = run;
4656
+ break;
4657
+ }
4658
+ }
4659
+ }
4660
+ if (!foundRun) {
4661
+ throw new Error(`Failed to find artifact for PR #${prNumber}. Make sure the PR exists and has completed successfully.`);
4662
+ }
4663
+ const binaryName = platform === "windows-x64" ? `stitch-${platform}.exe` : `stitch-${platform}`;
4664
+ const tmpBinaryPath = join4(tmpDir, binaryName);
4665
+ if (!existsSync4(tmpBinaryPath)) {
4666
+ throw new Error(`Downloaded artifact does not contain expected binary: ${binaryName}`);
4667
+ }
4668
+ const binaryData = await Bun.file(tmpBinaryPath).arrayBuffer();
4669
+ await Bun.write(destPath, binaryData);
4670
+ onProgress?.("Download complete");
4671
+ } finally {
4672
+ try {
4673
+ const { rm } = await import("fs/promises");
4674
+ await rm(tmpDir, { recursive: true, force: true });
4675
+ } catch {}
4676
+ }
4677
+ }
4188
4678
  // src/platform/update/install.ts
4189
4679
  import { rename, unlink, chmod } from "fs/promises";
4190
- import { existsSync as existsSync3 } from "fs";
4191
- import { dirname, join as join4 } from "path";
4192
- var {$: $2 } = globalThis.Bun;
4680
+ import { existsSync as existsSync5 } from "fs";
4681
+ import { dirname, join as join5 } from "path";
4682
+ var {$: $3 } = globalThis.Bun;
4193
4683
  function getCurrentExecutablePath() {
4194
4684
  return process.execPath;
4195
4685
  }
4196
4686
  async function cleanupOldBinaries(execPath) {
4197
4687
  const dir = dirname(execPath);
4198
4688
  const baseName = execPath.endsWith(".exe") ? "stitch" : "stitch";
4199
- const oldPath = join4(dir, `${baseName}.old`);
4200
- const oldPathExe = join4(dir, `${baseName}.old.exe`);
4689
+ const oldPath = join5(dir, `${baseName}.old`);
4690
+ const oldPathExe = join5(dir, `${baseName}.old.exe`);
4201
4691
  for (const path of [oldPath, oldPathExe]) {
4202
- if (existsSync3(path)) {
4692
+ if (existsSync5(path)) {
4203
4693
  try {
4204
4694
  await unlink(path);
4205
4695
  } catch {}
4206
4696
  }
4207
4697
  }
4208
4698
  }
4209
- async function installBinaryUpdate(targetVersion, currentVersion, onProgress) {
4699
+ async function installBinaryUpdate(targetVersion, currentVersion, onProgress, prNumber) {
4210
4700
  const platform = detectPlatform();
4211
4701
  const execPath = getCurrentExecutablePath();
4212
4702
  const dir = dirname(execPath);
4213
4703
  const isWindows = platform === "windows-x64";
4214
- const newBinaryPath = join4(dir, isWindows ? "stitch.new.exe" : "stitch.new");
4215
- const oldBinaryPath = join4(dir, isWindows ? "stitch.old.exe" : "stitch.old");
4216
- const downloadUrl = getDownloadUrl(targetVersion, platform);
4704
+ const newBinaryPath = join5(dir, isWindows ? "stitch.new.exe" : "stitch.new");
4705
+ const oldBinaryPath = join5(dir, isWindows ? "stitch.old.exe" : "stitch.old");
4217
4706
  try {
4218
4707
  await cleanupOldBinaries(execPath);
4219
- onProgress?.(`Downloading stitch v${targetVersion}...`);
4220
- let lastPercent = 0;
4221
- await downloadBinary(downloadUrl, newBinaryPath, (downloaded, total) => {
4222
- if (total) {
4223
- const percent = Math.round(downloaded / total * 100);
4224
- if (percent !== lastPercent && percent % 10 === 0) {
4225
- onProgress?.(`Downloading: ${percent}%`);
4226
- lastPercent = percent;
4708
+ if (prNumber) {
4709
+ onProgress?.(`Downloading from PR #${prNumber}...`);
4710
+ await downloadPRArtifact(prNumber, newBinaryPath, onProgress);
4711
+ } else {
4712
+ const downloadUrl = getDownloadUrl(targetVersion, platform);
4713
+ onProgress?.(`Downloading stitch v${targetVersion}...`);
4714
+ let lastPercent = 0;
4715
+ await downloadBinary(downloadUrl, newBinaryPath, (downloaded, total) => {
4716
+ if (total) {
4717
+ const percent = Math.round(downloaded / total * 100);
4718
+ if (percent !== lastPercent && percent % 10 === 0) {
4719
+ onProgress?.(`Downloading: ${percent}%`);
4720
+ lastPercent = percent;
4721
+ }
4227
4722
  }
4228
- }
4229
- });
4723
+ });
4724
+ }
4230
4725
  if (!isWindows) {
4231
4726
  await chmod(newBinaryPath, 493);
4232
4727
  }
@@ -4242,12 +4737,12 @@ async function installBinaryUpdate(targetVersion, currentVersion, onProgress) {
4242
4737
  newVersion: targetVersion
4243
4738
  };
4244
4739
  } catch (error) {
4245
- if (existsSync3(oldBinaryPath) && !existsSync3(execPath)) {
4740
+ if (existsSync5(oldBinaryPath) && !existsSync5(execPath)) {
4246
4741
  try {
4247
4742
  await rename(oldBinaryPath, execPath);
4248
4743
  } catch {}
4249
4744
  }
4250
- if (existsSync3(newBinaryPath)) {
4745
+ if (existsSync5(newBinaryPath)) {
4251
4746
  try {
4252
4747
  await unlink(newBinaryPath);
4253
4748
  } catch {}
@@ -4264,7 +4759,7 @@ async function installNpmUpdate(targetVersion, currentVersion, onProgress) {
4264
4759
  try {
4265
4760
  onProgress?.(`Updating via npm to v${targetVersion}...`);
4266
4761
  const versionSpec = targetVersion === "latest" ? "@captainsafia/stitch@latest" : `@captainsafia/stitch@${targetVersion}`;
4267
- const result = await $2`npm install -g ${versionSpec}`.quiet();
4762
+ const result = await $3`npm install -g ${versionSpec}`.quiet();
4268
4763
  if (result.exitCode !== 0) {
4269
4764
  return {
4270
4765
  success: false,
@@ -4291,7 +4786,7 @@ async function installBunUpdate(targetVersion, currentVersion, onProgress) {
4291
4786
  try {
4292
4787
  onProgress?.(`Updating via bun to v${targetVersion}...`);
4293
4788
  const versionSpec = targetVersion === "latest" ? "@captainsafia/stitch@latest" : `@captainsafia/stitch@${targetVersion}`;
4294
- const result = await $2`bun install -g ${versionSpec}`.quiet();
4789
+ const result = await $3`bun install -g ${versionSpec}`.quiet();
4295
4790
  if (result.exitCode !== 0) {
4296
4791
  return {
4297
4792
  success: false,
@@ -4314,14 +4809,30 @@ async function installBunUpdate(targetVersion, currentVersion, onProgress) {
4314
4809
  };
4315
4810
  }
4316
4811
  }
4317
- async function installUpdate(targetVersion, currentVersion, onProgress) {
4812
+ async function installUpdate(targetVersion, currentVersion, onProgress, prNumber) {
4318
4813
  const installMethod = detectInstallMethod();
4319
4814
  switch (installMethod) {
4320
4815
  case "binary":
4321
- return installBinaryUpdate(targetVersion, currentVersion, onProgress);
4816
+ return installBinaryUpdate(targetVersion, currentVersion, onProgress, prNumber);
4322
4817
  case "npm":
4818
+ if (prNumber) {
4819
+ return {
4820
+ success: false,
4821
+ previousVersion: currentVersion,
4822
+ newVersion: targetVersion,
4823
+ error: "PR updates are only available for standalone binary installations."
4824
+ };
4825
+ }
4323
4826
  return installNpmUpdate(targetVersion, currentVersion, onProgress);
4324
4827
  case "bun":
4828
+ if (prNumber) {
4829
+ return {
4830
+ success: false,
4831
+ previousVersion: currentVersion,
4832
+ newVersion: targetVersion,
4833
+ error: "PR updates are only available for standalone binary installations."
4834
+ };
4835
+ }
4325
4836
  return installBunUpdate(targetVersion, currentVersion, onProgress);
4326
4837
  case "dev":
4327
4838
  return {
@@ -4348,13 +4859,23 @@ function getInstallMethodDescription(method) {
4348
4859
  var packageJson = await Promise.resolve().then(() => __toESM(require_package(), 1));
4349
4860
  var program2 = new Command;
4350
4861
  program2.name("stitch").description(packageJson.description).version(packageJson.version);
4862
+ function createNotifier() {
4863
+ const cacheFilePath = join6(getConfigDir(), "update-check.json");
4864
+ return new ReleaseNotifier({
4865
+ repo: "captainsafia/stitch",
4866
+ checkInterval: 86400000,
4867
+ cacheFilePath,
4868
+ token: process.env["GITHUB_TOKEN"]
4869
+ });
4870
+ }
4351
4871
  async function checkForUpdates() {
4352
4872
  try {
4353
- const versions = await getLatestVersion();
4354
4873
  const current = packageJson.version;
4355
- if (versions.stable && isUpdateAvailable(current, versions.stable)) {
4874
+ const notifier = createNotifier();
4875
+ const result = await notifier.checkVersion(current, true);
4876
+ if (result.updateAvailable && result.latestVersion) {
4356
4877
  console.error("");
4357
- console.error(`A new version of stitch is available: ${versions.stable} (current: ${current})`);
4878
+ console.error(`A new version of stitch is available: ${result.latestVersion} (current: ${current})`);
4358
4879
  console.error("Run 'stitch update' to update.");
4359
4880
  console.error("");
4360
4881
  }
@@ -4576,31 +5097,78 @@ program2.command("blame").description("Show stitch attribution for each line in
4576
5097
  __callDispose(__stack, _err, _hasErr);
4577
5098
  }
4578
5099
  });
4579
- program2.command("update").description("Update stitch to the latest version").option("-t, --target <version>", "Install a specific version").option("-p, --preview", "Install the latest preview version").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
5100
+ program2.command("finish").description("Finish a stitch (transition to terminal status)").argument("[id]", "Stitch ID to finish (defaults to current)").addOption(new Option("-s, --status <status>", "Target status").choices(["closed", "superseded", "abandoned"]).default("closed")).option("-b, --by <id>", "Superseding stitch ID (requires --status=superseded)").option("-f, --force", "Override auto-abandoned detection").option("-y, --yes", "Skip confirmation prompt for cascade closes").action(async (id, options) => {
5101
+ let __stack = [];
5102
+ try {
5103
+ const client = __using(__stack, new StitchClient, 0);
5104
+ try {
5105
+ const finishOptions = {
5106
+ status: options.status,
5107
+ supersededBy: options.by,
5108
+ force: options.force ?? false,
5109
+ skipConfirmation: options.yes ?? false
5110
+ };
5111
+ const preview = await client.prepareFinish(id, finishOptions);
5112
+ if (preview.forceRequired) {
5113
+ console.error(`Error: ${preview.forceRequired}`);
5114
+ process.exit(1);
5115
+ }
5116
+ if (preview.requiresConfirmation && !options.yes) {
5117
+ console.log(renderFinishPreview(preview));
5118
+ console.log("");
5119
+ const answer = prompt("Continue? [y/N]");
5120
+ if (answer?.toLowerCase() !== "y" && answer?.toLowerCase() !== "yes") {
5121
+ console.log("Cancelled.");
5122
+ return;
5123
+ }
5124
+ }
5125
+ const result = await client.executeFinish(preview, finishOptions);
5126
+ console.log(renderFinishResult(result));
5127
+ } catch (error) {
5128
+ handleError(error);
5129
+ }
5130
+ } catch (_catch) {
5131
+ var _err = _catch, _hasErr = 1;
5132
+ } finally {
5133
+ __callDispose(__stack, _err, _hasErr);
5134
+ }
5135
+ });
5136
+ program2.command("update").description("Update stitch to the latest version").allowExcessArguments(false).option("-t, --target <version>", "Install a specific version").option("-p, --preview", "Install the latest preview version").option("--pr <number>", "Install from a PR artifact (requires gh CLI)").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
4580
5137
  try {
4581
5138
  const current = packageJson.version;
4582
5139
  const installMethod = detectInstallMethod();
4583
5140
  let targetVersion;
4584
- if (options.target) {
5141
+ const optionCount = [options.target, options.preview, options.pr].filter(Boolean).length;
5142
+ if (optionCount > 1) {
5143
+ console.error("Error: Cannot specify more than one of --target, --preview, or --pr");
5144
+ process.exit(1);
5145
+ }
5146
+ if (options.pr) {
5147
+ targetVersion = `PR #${options.pr}`;
5148
+ } else if (options.target) {
4585
5149
  targetVersion = options.target;
4586
5150
  } else if (options.preview) {
4587
5151
  console.log("Checking for latest preview version...");
4588
- const versions = await getLatestVersion(true);
4589
- if (!versions.preview) {
5152
+ const notifier = createNotifier();
5153
+ notifier.clearCache();
5154
+ const previewRelease = await notifier.getLatestPrerelease();
5155
+ if (!previewRelease) {
4590
5156
  console.error("Error: No preview version available.");
4591
5157
  process.exit(1);
4592
5158
  }
4593
- targetVersion = versions.preview;
5159
+ targetVersion = previewRelease.tagName.replace(/^v/, "");
4594
5160
  } else {
4595
5161
  console.log("Checking for latest version...");
4596
- const versions = await getLatestVersion(true);
4597
- if (!versions.stable) {
5162
+ const notifier = createNotifier();
5163
+ notifier.clearCache();
5164
+ const stableRelease = await notifier.getLatestRelease();
5165
+ if (!stableRelease) {
4598
5166
  console.error("Error: Could not fetch latest version. Check your network connection.");
4599
5167
  process.exit(1);
4600
5168
  }
4601
- targetVersion = versions.stable;
5169
+ targetVersion = stableRelease.tagName.replace(/^v/, "");
4602
5170
  }
4603
- if (current === targetVersion) {
5171
+ if (!options.pr && current === targetVersion) {
4604
5172
  console.log(`Already running stitch v${current}`);
4605
5173
  return;
4606
5174
  }
@@ -4621,13 +5189,10 @@ program2.command("update").description("Update stitch to the latest version").op
4621
5189
  }
4622
5190
  const result = await installUpdate(targetVersion, current, (message) => {
4623
5191
  console.log(message);
4624
- });
5192
+ }, options.pr);
4625
5193
  if (result.success) {
4626
5194
  console.log("");
4627
5195
  console.log(renderSuccess(`Updated stitch from v${current} to v${targetVersion}`));
4628
- if (installMethod === "binary") {
4629
- console.log("Please restart your terminal for changes to take effect.");
4630
- }
4631
5196
  } else {
4632
5197
  console.error("");
4633
5198
  console.error(`Error: Update failed: ${result.error}`);
@@ -4646,6 +5211,14 @@ function handleError(error) {
4646
5211
  console.error(`Error: ${error.message}`);
4647
5212
  process.exit(1);
4648
5213
  }
5214
+ if (error instanceof FinishForceRequiredError) {
5215
+ console.error(`Error: ${error.message}`);
5216
+ process.exit(1);
5217
+ }
5218
+ if (error instanceof InvalidSupersededByError) {
5219
+ console.error(`Error: ${error.message}`);
5220
+ process.exit(1);
5221
+ }
4649
5222
  if (error instanceof StitchError) {
4650
5223
  console.error(`Error: ${error.message}`);
4651
5224
  process.exit(1);