@mseep/wanderlog-mcp 0.3.1

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 (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +282 -0
  3. package/dist/cache/trip-cache.js +87 -0
  4. package/dist/cache/trip-cache.js.map +1 -0
  5. package/dist/config.js +38 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/context.js +12 -0
  8. package/dist/context.js.map +1 -0
  9. package/dist/errors.js +93 -0
  10. package/dist/errors.js.map +1 -0
  11. package/dist/formatters/trip-summary.js +296 -0
  12. package/dist/formatters/trip-summary.js.map +1 -0
  13. package/dist/http.js +165 -0
  14. package/dist/http.js.map +1 -0
  15. package/dist/index.js +48 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/ot/apply.js +282 -0
  18. package/dist/ot/apply.js.map +1 -0
  19. package/dist/resolvers/day.js +83 -0
  20. package/dist/resolvers/day.js.map +1 -0
  21. package/dist/resolvers/place-ref.js +194 -0
  22. package/dist/resolvers/place-ref.js.map +1 -0
  23. package/dist/server.js +164 -0
  24. package/dist/server.js.map +1 -0
  25. package/dist/tools/add-checklist.js +59 -0
  26. package/dist/tools/add-checklist.js.map +1 -0
  27. package/dist/tools/add-expense.js +127 -0
  28. package/dist/tools/add-expense.js.map +1 -0
  29. package/dist/tools/add-hotel.js +92 -0
  30. package/dist/tools/add-hotel.js.map +1 -0
  31. package/dist/tools/add-note.js +63 -0
  32. package/dist/tools/add-note.js.map +1 -0
  33. package/dist/tools/add-place.js +151 -0
  34. package/dist/tools/add-place.js.map +1 -0
  35. package/dist/tools/annotate-place.js +114 -0
  36. package/dist/tools/annotate-place.js.map +1 -0
  37. package/dist/tools/create-trip.js +85 -0
  38. package/dist/tools/create-trip.js.map +1 -0
  39. package/dist/tools/edit-note.js +217 -0
  40. package/dist/tools/edit-note.js.map +1 -0
  41. package/dist/tools/get-guide.js +42 -0
  42. package/dist/tools/get-guide.js.map +1 -0
  43. package/dist/tools/get-trip-url.js +52 -0
  44. package/dist/tools/get-trip-url.js.map +1 -0
  45. package/dist/tools/get-trip.js +43 -0
  46. package/dist/tools/get-trip.js.map +1 -0
  47. package/dist/tools/list-trips.js +32 -0
  48. package/dist/tools/list-trips.js.map +1 -0
  49. package/dist/tools/remove-note.js +107 -0
  50. package/dist/tools/remove-note.js.map +1 -0
  51. package/dist/tools/remove-place.js +95 -0
  52. package/dist/tools/remove-place.js.map +1 -0
  53. package/dist/tools/rename-day.js +64 -0
  54. package/dist/tools/rename-day.js.map +1 -0
  55. package/dist/tools/search-guides.js +172 -0
  56. package/dist/tools/search-guides.js.map +1 -0
  57. package/dist/tools/search-places.js +81 -0
  58. package/dist/tools/search-places.js.map +1 -0
  59. package/dist/tools/shared.js +216 -0
  60. package/dist/tools/shared.js.map +1 -0
  61. package/dist/tools/update-trip-dates.js +211 -0
  62. package/dist/tools/update-trip-dates.js.map +1 -0
  63. package/dist/transport/rest.js +152 -0
  64. package/dist/transport/rest.js.map +1 -0
  65. package/dist/transport/sharedb.js +323 -0
  66. package/dist/transport/sharedb.js.map +1 -0
  67. package/dist/types.js +7 -0
  68. package/dist/types.js.map +1 -0
  69. package/package.json +61 -0
@@ -0,0 +1,151 @@
1
+ import { z } from "zod";
2
+ import { WanderlogError, WanderlogValidationError } from "../errors.js";
3
+ import { resolveDay } from "../resolvers/day.js";
4
+ import { buildPlaceBlock, findDaySectionByDate, findPlacesToVisitSection, findTripCenter, requireUserId, submitOp, } from "./shared.js";
5
+ export const addPlaceInputSchema = {
6
+ trip_key: z
7
+ .string()
8
+ .min(1)
9
+ .describe("The trip to add to. Use wanderlog_list_trips if you don't know the key."),
10
+ place: z
11
+ .string()
12
+ .min(1)
13
+ .describe("Name of the place to add. Examples: 'Sensō-ji', 'a ramen place in Shinjuku', 'Louvre'. Will be matched against Google Places near the trip's destination; if multiple match, the top result is used."),
14
+ day: z
15
+ .string()
16
+ .optional()
17
+ .describe("Optional day to add the place to. Accepts 'day 2', 'May 4', or ISO '2026-05-04'. Omit to add the place to the trip's 'Places to visit' list (unscheduled)."),
18
+ note: z
19
+ .string()
20
+ .optional()
21
+ .describe("Optional inline note attached directly to this place. Use for practical context: transit directions, what to order, booking tips, time guidance. Appears on the place itself in Wanderlog (not as a separate note block)."),
22
+ start_time: z
23
+ .string()
24
+ .regex(/^\d{2}:\d{2}$/, "must be HH:mm")
25
+ .optional()
26
+ .describe("Optional start time in HH:mm format (e.g. '09:00'). Adds a scheduled time to the place."),
27
+ end_time: z
28
+ .string()
29
+ .regex(/^\d{2}:\d{2}$/, "must be HH:mm")
30
+ .optional()
31
+ .describe("Optional end time in HH:mm format (e.g. '11:30'). Only used with start_time."),
32
+ };
33
+ export const addPlaceDescription = `
34
+ Adds a place to a Wanderlog trip. Searches for the place near the trip's destination, picks the
35
+ best match, and inserts it into either a specific day or the general "Places to visit" list.
36
+
37
+ PREFERRED: Use the "note" parameter to attach practical context directly to each place — transit
38
+ directions, what to order, booking tips, time guidance. This is better than a separate
39
+ wanderlog_add_note call because the note lives on the place itself in the itinerary. Use the
40
+ "start_time" and "end_time" parameters to give the place a scheduled time window.
41
+
42
+ Use standalone wanderlog_add_note only for freestanding commentary between places (neighborhood
43
+ context, multi-stop transit, day-level tips that aren't about a specific place).
44
+
45
+ Returns a confirmation including the resolved place name and where it was added.
46
+ `.trim();
47
+ export async function addPlace(ctx, args) {
48
+ try {
49
+ const userId = requireUserId(ctx);
50
+ const entry = await ctx.tripCache.getEntry(args.trip_key);
51
+ const trip = entry.snapshot;
52
+ // Resolve target section
53
+ let targetIndex;
54
+ let targetLabel;
55
+ if (args.day) {
56
+ const daySection = resolveDay(trip, args.day);
57
+ const found = findDaySectionByDate(trip, daySection.date);
58
+ if (!found) {
59
+ throw new WanderlogValidationError(`Day ${args.day} not found in trip`);
60
+ }
61
+ targetIndex = found.index;
62
+ targetLabel = `day ${daySection.date}`;
63
+ }
64
+ else {
65
+ const places = findPlacesToVisitSection(trip);
66
+ if (!places) {
67
+ throw new WanderlogError("Trip has no 'Places to visit' list", "no_places_section", "This is unexpected — Wanderlog usually creates one automatically. Try adding to a specific day instead.");
68
+ }
69
+ targetIndex = places.index;
70
+ targetLabel = "places to visit";
71
+ }
72
+ const center = findTripCenter(trip, entry.geos);
73
+ if (!center) {
74
+ throw new WanderlogValidationError(`Cannot add places to "${trip.title}" because no location anchor is available`, "This trip has no associated geo and no existing places. Add a place via the Wanderlog UI first.");
75
+ }
76
+ const predictions = await ctx.rest.searchPlacesAutocomplete({
77
+ input: args.place,
78
+ sessionToken: crypto.randomUUID(),
79
+ location: { latitude: center.lat, longitude: center.lng },
80
+ radius: 15000,
81
+ });
82
+ if (predictions.length === 0) {
83
+ throw new WanderlogError(`No place found matching "${args.place}" near ${trip.title}`, "place_not_found", {
84
+ hint: "Try a more specific name, or widen the search with wanderlog_search_places first.",
85
+ followUps: [
86
+ `Call wanderlog_search_places with trip_key "${args.trip_key}" and a broader query to see nearby candidates.`,
87
+ "Retry wanderlog_add_place with a more specific place name (include the city or neighborhood).",
88
+ ],
89
+ });
90
+ }
91
+ const topPrediction = predictions[0];
92
+ const detail = await ctx.rest.getPlaceDetails(topPrediction.place_id);
93
+ // Build the block WITHOUT timing — timing is set via separate oi ops
94
+ // to match the Wanderlog UI's two-step pattern (insert block, then set fields).
95
+ const block = buildPlaceBlock(detail, userId);
96
+ const section = trip.itinerary.sections[targetIndex];
97
+ const insertIndex = section.blocks.length;
98
+ const blockPath = ["itinerary", "sections", targetIndex, "blocks", insertIndex];
99
+ const ops = [
100
+ { p: blockPath, li: block },
101
+ ];
102
+ await submitOp(ctx, args.trip_key, ops);
103
+ // Follow-up: set inline note text via rich-text subtype op
104
+ if (args.note) {
105
+ const textOps = [
106
+ {
107
+ p: [...blockPath, "text"],
108
+ t: "rich-text",
109
+ o: [{ insert: `${args.note}\n` }],
110
+ },
111
+ ];
112
+ await submitOp(ctx, args.trip_key, textOps);
113
+ }
114
+ // Follow-up: set timing via plain oi ops. The block was inserted without
115
+ // timing fields, so we use oi (object insert) without od — the key doesn't
116
+ // exist yet. This matches the Wanderlog UI's two-step pattern.
117
+ if (args.start_time || args.end_time) {
118
+ const timeOps = [];
119
+ if (args.start_time) {
120
+ timeOps.push({
121
+ p: [...blockPath, "startTime"],
122
+ oi: args.start_time,
123
+ });
124
+ }
125
+ if (args.end_time) {
126
+ timeOps.push({
127
+ p: [...blockPath, "endTime"],
128
+ oi: args.end_time,
129
+ });
130
+ }
131
+ await submitOp(ctx, args.trip_key, timeOps);
132
+ }
133
+ const parts = [`Added ${detail.name} to ${targetLabel} in "${trip.title}".`];
134
+ if (args.start_time) {
135
+ parts.push(`Scheduled: ${args.start_time}${args.end_time ? `–${args.end_time}` : ""}.`);
136
+ }
137
+ if (args.note) {
138
+ const preview = args.note.length > 60 ? `${args.note.slice(0, 57)}…` : args.note;
139
+ parts.push(`Note: "${preview}"`);
140
+ }
141
+ const text = parts.join(" ");
142
+ return { content: [{ type: "text", text }] };
143
+ }
144
+ catch (err) {
145
+ const msg = err instanceof WanderlogError
146
+ ? err.toUserMessage()
147
+ : `Unexpected error: ${err.message}`;
148
+ return { content: [{ type: "text", text: msg }], isError: true };
149
+ }
150
+ }
151
+ //# sourceMappingURL=add-place.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-place.js","sourceRoot":"","sources":["../../src/tools/add-place.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ import { z } from "zod";
2
+ import { WanderlogError, WanderlogValidationError } from "../errors.js";
3
+ import { resolvePlaceRef } from "../resolvers/place-ref.js";
4
+ import { isPlaceBlock } from "../types.js";
5
+ import { submitOp } from "./shared.js";
6
+ export const annotatePlaceInputSchema = {
7
+ trip_key: z
8
+ .string()
9
+ .min(1)
10
+ .describe("The trip containing the place."),
11
+ place: z
12
+ .string()
13
+ .min(1)
14
+ .describe("Natural-language reference to the place. Examples: 'Sensō-ji', 'the hotel', 'Queenstown Gardens on day 2'. Supports ordinals for duplicates: '2nd Starbucks'."),
15
+ note: z
16
+ .string()
17
+ .optional()
18
+ .describe("Set or replace the inline note on this place. Practical context: transit, tips, timing, what to see."),
19
+ start_time: z
20
+ .string()
21
+ .regex(/^\d{2}:\d{2}$/, "must be HH:mm")
22
+ .optional()
23
+ .describe("Set or replace the start time (HH:mm format)."),
24
+ end_time: z
25
+ .string()
26
+ .regex(/^\d{2}:\d{2}$/, "must be HH:mm")
27
+ .optional()
28
+ .describe("Set or replace the end time (HH:mm format)."),
29
+ };
30
+ export const annotatePlaceDescription = `
31
+ Updates an existing place in a Wanderlog trip with an inline note, start/end time, or both.
32
+ Use this to enrich places that were already added — set practical context, scheduled times,
33
+ or both in one call.
34
+
35
+ At least one of note, start_time, or end_time must be provided.
36
+
37
+ The place is resolved by natural-language reference (same syntax as wanderlog_remove_place).
38
+ If ambiguous, returns a disambiguation list without making changes.
39
+ `.trim();
40
+ export async function annotatePlace(ctx, args) {
41
+ try {
42
+ if (!args.note && !args.start_time && !args.end_time) {
43
+ throw new WanderlogValidationError("At least one of note, start_time, or end_time must be provided");
44
+ }
45
+ const entry = await ctx.tripCache.getEntry(args.trip_key);
46
+ const trip = entry.snapshot;
47
+ const result = resolvePlaceRef(trip, args.place);
48
+ if (result.kind === "none") {
49
+ throw new WanderlogError(`No place matching "${args.place}" found in "${trip.title}"`, "place_ref_not_found", {
50
+ hint: "Check the place name or use wanderlog_get_trip to see what's in the itinerary.",
51
+ followUps: [
52
+ `Call wanderlog_get_trip with trip_key "${args.trip_key}" to see all places.`,
53
+ ],
54
+ });
55
+ }
56
+ if (result.kind === "ambiguous") {
57
+ const lines = result.candidates.map((c, i) => {
58
+ const name = isPlaceBlock(c.block) ? c.block.place.name : `block #${c.block.id}`;
59
+ const loc = c.section.date ? `day ${c.section.date}` : c.section.heading || "unscheduled";
60
+ return ` ${i + 1}. ${name} (${loc})`;
61
+ });
62
+ const text = `Multiple places match "${args.place}":\n${lines.join("\n")}\n\nRetry with a more specific reference or an ordinal prefix (e.g. "1st ${args.place}").`;
63
+ return { content: [{ type: "text", text }] };
64
+ }
65
+ const { sectionIndex, blockIndex, block } = result.match;
66
+ const blockPath = ["itinerary", "sections", sectionIndex, "blocks", blockIndex];
67
+ const placeName = isPlaceBlock(block) ? block.place.name : `block #${block.id}`;
68
+ // Set inline note via rich-text subtype op
69
+ if (args.note) {
70
+ const textOps = [
71
+ {
72
+ p: [...blockPath, "text"],
73
+ t: "rich-text",
74
+ o: [{ insert: `${args.note}\n` }],
75
+ },
76
+ ];
77
+ await submitOp(ctx, args.trip_key, textOps);
78
+ }
79
+ // Set timing — use od+oi when the field already exists, plain oi when it doesn't
80
+ if (args.start_time || args.end_time) {
81
+ const timeOps = [];
82
+ const existingBlock = block;
83
+ if (args.start_time) {
84
+ const op = { p: [...blockPath, "startTime"], oi: args.start_time };
85
+ if ("startTime" in existingBlock)
86
+ op.od = existingBlock.startTime;
87
+ timeOps.push(op);
88
+ }
89
+ if (args.end_time) {
90
+ const op = { p: [...blockPath, "endTime"], oi: args.end_time };
91
+ if ("endTime" in existingBlock)
92
+ op.od = existingBlock.endTime;
93
+ timeOps.push(op);
94
+ }
95
+ await submitOp(ctx, args.trip_key, timeOps);
96
+ }
97
+ const parts = [`Updated ${placeName} in "${trip.title}".`];
98
+ if (args.start_time) {
99
+ parts.push(`Time: ${args.start_time}${args.end_time ? `–${args.end_time}` : ""}.`);
100
+ }
101
+ if (args.note) {
102
+ const preview = args.note.length > 60 ? `${args.note.slice(0, 57)}…` : args.note;
103
+ parts.push(`Note: "${preview}"`);
104
+ }
105
+ return { content: [{ type: "text", text: parts.join(" ") }] };
106
+ }
107
+ catch (err) {
108
+ const msg = err instanceof WanderlogError
109
+ ? err.toUserMessage()
110
+ : `Unexpected error: ${err.message}`;
111
+ return { content: [{ type: "text", text: msg }], isError: true };
112
+ }
113
+ }
114
+ //# sourceMappingURL=annotate-place.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotate-place.js","sourceRoot":"","sources":["../../src/tools/annotate-place.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import { z } from "zod";
2
+ import { WanderlogError, WanderlogValidationError } from "../errors.js";
3
+ export const createTripInputSchema = {
4
+ destination: z
5
+ .string()
6
+ .min(1)
7
+ .describe("City or region name to plan the trip around (e.g. 'Lisbon', 'Tokyo', 'Banff'). Resolved via Wanderlog's geo autocomplete — the top-ranked result is used."),
8
+ start_date: z
9
+ .string()
10
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "must be YYYY-MM-DD")
11
+ .describe("First day of the trip, YYYY-MM-DD."),
12
+ end_date: z
13
+ .string()
14
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "must be YYYY-MM-DD")
15
+ .describe("Last day of the trip, YYYY-MM-DD."),
16
+ title: z
17
+ .string()
18
+ .optional()
19
+ .describe("Optional custom title. If omitted, Wanderlog auto-generates one like 'Trip to Lisbon'."),
20
+ privacy: z
21
+ .enum(["private", "friends", "public"])
22
+ .default("private")
23
+ .describe("Trip visibility. 'private' is the safe default."),
24
+ };
25
+ export const createTripDescription = `
26
+ Creates a new Wanderlog trip for the given destination and date range. The trip is created
27
+ empty (no places yet) with one pre-generated day section per day in the range.
28
+
29
+ After creating a trip, populate each day using ALL of these tools together — places alone
30
+ make a flat list, but notes and checklists are what make an itinerary actually useful:
31
+
32
+ 1. wanderlog_add_place — add attractions, restaurants, and activities
33
+ 2. wanderlog_add_note — add between places for transit directions, practical tips, time
34
+ warnings, or local recommendations (e.g. "Walk 10 min south along the river to the next
35
+ stop" or "Closed Mondays — check hours before visiting")
36
+ 3. wanderlog_add_hotel — add accommodation with check-in/check-out dates
37
+ 4. wanderlog_add_checklist — add a packing list to the trip, or per-day task lists
38
+ (e.g. "Day 1 prep: print tickets, charge camera, pack umbrella")
39
+
40
+ A good itinerary has notes after most places — think of them as the connective tissue that
41
+ turns a list of pins on a map into a real travel plan.
42
+
43
+ Returns the new trip key so you can reference it in subsequent tool calls.
44
+ `.trim();
45
+ export async function createTrip(ctx, args) {
46
+ try {
47
+ if (args.end_date < args.start_date) {
48
+ throw new WanderlogValidationError(`end_date (${args.end_date}) is before start_date (${args.start_date})`);
49
+ }
50
+ const geos = await ctx.rest.geoAutocomplete(args.destination);
51
+ if (geos.length === 0) {
52
+ throw new WanderlogError(`No location found for "${args.destination}"`, "geo_not_found", "Try a more specific or well-known place name.");
53
+ }
54
+ const top = geos[0];
55
+ const result = await ctx.rest.createTrip({
56
+ geoIds: [top.id],
57
+ startDate: args.start_date,
58
+ endDate: args.end_date,
59
+ title: args.title ?? null,
60
+ privacy: args.privacy ?? "private",
61
+ });
62
+ const locationLabel = top.stateName
63
+ ? `${top.name}, ${top.stateName}, ${top.countryName}`
64
+ : `${top.name}, ${top.countryName ?? ""}`.trim().replace(/,\s*$/, "");
65
+ const days = result.key ? Math.round((new Date(args.end_date).getTime() - new Date(args.start_date).getTime()) / 86_400_000) + 1 : 0;
66
+ const text = [
67
+ `Created "${result.title}" for ${locationLabel}. Dates: ${args.start_date} → ${args.end_date} (${days} days). Key: ${result.key}`,
68
+ ``,
69
+ `Now build the itinerary. For each day, follow this pattern:`,
70
+ ` 1. wanderlog_add_place — add 3-5 places (attractions, food, activities)`,
71
+ ` 2. wanderlog_add_note — add a note after each place with transit directions, practical tips, or local advice`,
72
+ ` 3. wanderlog_add_checklist — add a day-specific task list if useful (e.g. "bring cash", "book ahead")`,
73
+ `Also call wanderlog_add_hotel for accommodation, and wanderlog_add_checklist (no day) for a packing list.`,
74
+ `A great itinerary interleaves places and notes — don't add all places first and skip the notes.`,
75
+ ].join("\n");
76
+ return { content: [{ type: "text", text }] };
77
+ }
78
+ catch (err) {
79
+ const msg = err instanceof WanderlogError
80
+ ? err.toUserMessage()
81
+ : `Unexpected error: ${err.message}`;
82
+ return { content: [{ type: "text", text: msg }], isError: true };
83
+ }
84
+ }
85
+ //# sourceMappingURL=create-trip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-trip.js","sourceRoot":"","sources":["../../src/tools/create-trip.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,217 @@
1
+ import { z } from "zod";
2
+ import { WanderlogError, WanderlogNotFoundError } from "../errors.js";
3
+ import { resolveDay } from "../resolvers/day.js";
4
+ import { isChecklistBlock, isPlaceBlock } from "../types.js";
5
+ import { findDaySectionByDate, submitOp } from "./shared.js";
6
+ import { extractDeltaText } from "./remove-note.js";
7
+ export const editNoteInputSchema = {
8
+ trip_key: z.string().min(1).describe("The trip to edit."),
9
+ old_text: z
10
+ .string()
11
+ .min(1)
12
+ .describe("Substring to find and replace (case-insensitive)."),
13
+ new_text: z.string().describe("Replacement text."),
14
+ day: z
15
+ .string()
16
+ .optional()
17
+ .describe("Optional day to search. Accepts 'day 2', 'May 4', or ISO '2026-05-04'. Omit to search the entire trip."),
18
+ };
19
+ export const editNoteDescription = `
20
+ Edits note content in a Wanderlog trip by finding and replacing a substring.
21
+
22
+ Searches across freestanding notes, place annotations, and checklist titles and items.
23
+ The match is case-insensitive. If exactly one match is found, the replacement is made in place.
24
+ If no matches are found, an error is returned. If multiple matches are found, a numbered list
25
+ of previews is returned — call again with a more specific substring.
26
+
27
+ Use the optional 'day' filter to limit the search to a specific day.
28
+ `.trim();
29
+ function previewText(text) {
30
+ const flat = text.replace(/\n/g, " ").trim();
31
+ return flat.length > 60 ? `${flat.slice(0, 57)}…` : flat;
32
+ }
33
+ function matchInDelta(delta, query) {
34
+ const ops = delta?.ops ?? [];
35
+ const lowerQuery = query.toLowerCase();
36
+ const boundaries = [];
37
+ let plainText = "";
38
+ for (const op of ops) {
39
+ boundaries.push(plainText.length);
40
+ plainText += typeof op.insert === "string" ? op.insert : "";
41
+ }
42
+ const lowerText = plainText.toLowerCase();
43
+ const matchStart = lowerText.indexOf(lowerQuery);
44
+ if (matchStart === -1)
45
+ return null;
46
+ const matchEnd = matchStart + lowerQuery.length;
47
+ const crossesBoundary = boundaries.some((b) => b > matchStart && b < matchEnd);
48
+ return { offset: matchStart, matchedLen: lowerQuery.length, crossesBoundary };
49
+ }
50
+ export function findEditTargets(trip, query, day) {
51
+ const sections = trip.itinerary.sections;
52
+ const targets = [];
53
+ const lowerQuery = query.toLowerCase();
54
+ let sectionIndices;
55
+ if (day) {
56
+ const resolved = resolveDay(trip, day);
57
+ const found = findDaySectionByDate(trip, resolved.date);
58
+ if (!found)
59
+ return [];
60
+ sectionIndices = [found.index];
61
+ }
62
+ else {
63
+ sectionIndices = Array.from({ length: sections.length }, (_, i) => i);
64
+ }
65
+ for (const si of sectionIndices) {
66
+ const section = sections[si];
67
+ for (let bi = 0; bi < section.blocks.length; bi++) {
68
+ const block = section.blocks[bi];
69
+ const blockBase = ["itinerary", "sections", si, "blocks", bi];
70
+ if (block.type === "note") {
71
+ const delta = block.text;
72
+ const m = matchInDelta(delta, query);
73
+ if (m) {
74
+ targets.push({
75
+ kind: "rich-text",
76
+ label: "note",
77
+ preview: `Note: "${previewText(extractDeltaText(delta))}"`,
78
+ sectionIndex: si,
79
+ blockIndex: bi,
80
+ fieldPath: [...blockBase, "text"],
81
+ offset: m.offset,
82
+ matchedLen: m.matchedLen,
83
+ crossesBoundary: m.crossesBoundary,
84
+ });
85
+ }
86
+ }
87
+ else if (isPlaceBlock(block)) {
88
+ const delta = block.text;
89
+ if (delta) {
90
+ const m = matchInDelta(delta, query);
91
+ if (m) {
92
+ targets.push({
93
+ kind: "rich-text",
94
+ label: `"${block.place.name}" annotation`,
95
+ preview: `"${block.place.name}" annotation: "${previewText(extractDeltaText(delta))}"`,
96
+ sectionIndex: si,
97
+ blockIndex: bi,
98
+ fieldPath: [...blockBase, "text"],
99
+ offset: m.offset,
100
+ matchedLen: m.matchedLen,
101
+ crossesBoundary: m.crossesBoundary,
102
+ });
103
+ }
104
+ }
105
+ }
106
+ else if (isChecklistBlock(block)) {
107
+ const cb = block;
108
+ // Checklist title (plain string)
109
+ const title = cb.title ?? "";
110
+ if (title && title.toLowerCase().includes(lowerQuery)) {
111
+ const offset = title.toLowerCase().indexOf(lowerQuery);
112
+ targets.push({
113
+ kind: "plain",
114
+ label: "checklist title",
115
+ preview: `Checklist title: "${previewText(title)}"`,
116
+ sectionIndex: si,
117
+ blockIndex: bi,
118
+ fieldPath: [...blockBase, "title"],
119
+ oldValue: title,
120
+ offset,
121
+ matchedLen: query.length,
122
+ });
123
+ }
124
+ // Checklist items
125
+ for (let ii = 0; ii < cb.items.length; ii++) {
126
+ const item = cb.items[ii];
127
+ const m = matchInDelta(item.text, query);
128
+ if (m) {
129
+ targets.push({
130
+ kind: "rich-text",
131
+ label: "checklist item",
132
+ preview: `Checklist item: "${previewText(extractDeltaText(item.text))}"`,
133
+ sectionIndex: si,
134
+ blockIndex: bi,
135
+ fieldPath: [...blockBase, "items", ii, "text"],
136
+ offset: m.offset,
137
+ matchedLen: m.matchedLen,
138
+ crossesBoundary: m.crossesBoundary,
139
+ });
140
+ }
141
+ }
142
+ }
143
+ }
144
+ }
145
+ return targets;
146
+ }
147
+ export async function editNote(ctx, args) {
148
+ try {
149
+ const trip = await ctx.tripCache.get(args.trip_key);
150
+ const targets = findEditTargets(trip, args.old_text, args.day);
151
+ if (targets.length === 0) {
152
+ throw new WanderlogNotFoundError("Note", args.old_text);
153
+ }
154
+ if (targets.length > 1) {
155
+ const lines = targets
156
+ .slice(0, 5)
157
+ .map((t, i) => ` ${i + 1}. ${t.preview}`)
158
+ .join("\n");
159
+ const suffix = targets.length > 5 ? `\n (${targets.length - 5} more…)` : "";
160
+ return {
161
+ content: [
162
+ {
163
+ type: "text",
164
+ text: `"${args.old_text}" matches ${targets.length} notes:\n${lines}${suffix}\n\nCall again with a more specific substring to identify the one you want.`,
165
+ },
166
+ ],
167
+ isError: true,
168
+ };
169
+ }
170
+ const target = targets[0];
171
+ if (target.kind === "rich-text" && target.crossesBoundary) {
172
+ return {
173
+ content: [
174
+ {
175
+ type: "text",
176
+ text: `Cannot replace "${args.old_text}": the match crosses a formatting boundary (e.g. a link or bold section). Use a more specific substring that stays within one formatting run.`,
177
+ },
178
+ ],
179
+ isError: true,
180
+ };
181
+ }
182
+ let ops;
183
+ if (target.kind === "rich-text") {
184
+ const deltaOps = [];
185
+ if (target.offset > 0)
186
+ deltaOps.push({ retain: target.offset });
187
+ deltaOps.push({ delete: target.matchedLen });
188
+ if (args.new_text)
189
+ deltaOps.push({ insert: args.new_text });
190
+ ops = [{ p: target.fieldPath, t: "rich-text", o: deltaOps }];
191
+ }
192
+ else {
193
+ const newValue = target.oldValue.slice(0, target.offset) +
194
+ args.new_text +
195
+ target.oldValue.slice(target.offset + target.matchedLen);
196
+ ops = [{ p: target.fieldPath, od: target.oldValue, oi: newValue }];
197
+ }
198
+ await submitOp(ctx, args.trip_key, ops);
199
+ const oldPreview = previewText(args.old_text);
200
+ const newPreview = previewText(args.new_text || "(empty)");
201
+ return {
202
+ content: [
203
+ {
204
+ type: "text",
205
+ text: `Updated ${target.label} in "${trip.title}". Changed "${oldPreview}" → "${newPreview}".`,
206
+ },
207
+ ],
208
+ };
209
+ }
210
+ catch (err) {
211
+ const msg = err instanceof WanderlogError
212
+ ? err.toUserMessage()
213
+ : `Unexpected error: ${err.message}`;
214
+ return { content: [{ type: "text", text: msg }], isError: true };
215
+ }
216
+ }
217
+ //# sourceMappingURL=edit-note.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit-note.js","sourceRoot":"","sources":["../../src/tools/edit-note.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { z } from "zod";
2
+ import { WanderlogError, WanderlogValidationError } from "../errors.js";
3
+ import { formatTrip } from "../formatters/trip-summary.js";
4
+ import { resolveDay } from "../resolvers/day.js";
5
+ export const getGuideInputSchema = {
6
+ guide_key: z
7
+ .string()
8
+ .min(1)
9
+ .describe("Guide's viewKey (the 'guide_key' returned by wanderlog_search_guides, e.g. 'hejurejdks')."),
10
+ day: z
11
+ .string()
12
+ .optional()
13
+ .describe("Optional day filter — pass a day heading or date to scope the output to one day."),
14
+ response_format: z
15
+ .enum(["concise", "detailed"])
16
+ .default("concise")
17
+ .describe("Output verbosity. 'concise' is a readable summary; 'detailed' adds addresses, phone numbers, ratings."),
18
+ };
19
+ export const getGuideDescription = `
20
+ Fetches the full content of a public Wanderlog guide — sections, places, and notes — and
21
+ renders it as readable text. Pass the guide_key from a wanderlog_search_guides response.
22
+
23
+ For your own trips, use wanderlog_get_trip instead.
24
+ `.trim();
25
+ export async function getGuide(ctx, args) {
26
+ try {
27
+ if (!args.guide_key || args.guide_key.trim().length === 0) {
28
+ throw new WanderlogValidationError("guide_key is required");
29
+ }
30
+ const trip = await ctx.rest.getGuideContent(args.guide_key);
31
+ const day = args.day ? resolveDay(trip, args.day) : undefined;
32
+ const text = formatTrip(trip, args.response_format ?? "concise", day);
33
+ return { content: [{ type: "text", text }] };
34
+ }
35
+ catch (err) {
36
+ const e = err instanceof WanderlogError
37
+ ? err.toUserMessage()
38
+ : `Unexpected error: ${err.message}`;
39
+ return { content: [{ type: "text", text: e }], isError: true };
40
+ }
41
+ }
42
+ //# sourceMappingURL=get-guide.js.map