@google/jules-merge 0.0.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.
- package/README.md +201 -0
- package/dist/cli/check-conflicts.command.mjs +387 -0
- package/dist/cli/index.mjs +28 -0
- package/dist/cli/init.command.mjs +159 -0
- package/dist/core/src/activities/client.d.ts +131 -0
- package/dist/core/src/activities/summary.d.ts +22 -0
- package/dist/core/src/activities/types.d.ts +79 -0
- package/dist/core/src/api.d.ts +49 -0
- package/dist/core/src/artifacts.d.ts +105 -0
- package/dist/core/src/caching.d.ts +31 -0
- package/dist/core/src/client.d.ts +180 -0
- package/dist/core/src/errors.d.ts +97 -0
- package/dist/core/src/index.d.ts +49 -0
- package/dist/core/src/mappers.d.ts +53 -0
- package/dist/core/src/network/adapter.d.ts +47 -0
- package/dist/core/src/platform/node.d.ts +45 -0
- package/dist/core/src/platform/types.d.ts +88 -0
- package/dist/core/src/polling.d.ts +43 -0
- package/dist/core/src/query/computed.d.ts +86 -0
- package/dist/core/src/query/projection.d.ts +80 -0
- package/dist/core/src/query/schema.d.ts +124 -0
- package/dist/core/src/query/select.d.ts +21 -0
- package/dist/core/src/query/validate.d.ts +68 -0
- package/dist/core/src/session.d.ts +195 -0
- package/dist/core/src/sessions.d.ts +87 -0
- package/dist/core/src/snapshot.d.ts +46 -0
- package/dist/core/src/sources.d.ts +23 -0
- package/dist/core/src/storage/cache-info.d.ts +43 -0
- package/dist/core/src/storage/memory.d.ts +69 -0
- package/dist/core/src/storage/node-fs.d.ts +95 -0
- package/dist/core/src/storage/root.d.ts +17 -0
- package/dist/core/src/storage/types.d.ts +115 -0
- package/dist/core/src/streaming.d.ts +47 -0
- package/dist/core/src/types.d.ts +1418 -0
- package/dist/core/src/utils/page-token.d.ts +55 -0
- package/dist/core/src/utils.d.ts +27 -0
- package/dist/index.mjs +395 -0
- package/dist/merge/src/__tests__/conflicts/git-handler.test.d.ts +1 -0
- package/dist/merge/src/__tests__/conflicts/git-spec.test.d.ts +1 -0
- package/dist/merge/src/__tests__/conflicts/session-handler.test.d.ts +1 -0
- package/dist/merge/src/__tests__/conflicts/session-spec.test.d.ts +1 -0
- package/dist/merge/src/__tests__/init/init-handler.test.d.ts +1 -0
- package/dist/merge/src/__tests__/init/init-spec.test.d.ts +1 -0
- package/dist/merge/src/__tests__/init/templates.test.d.ts +1 -0
- package/dist/merge/src/__tests__/shared/git.test.d.ts +1 -0
- package/dist/merge/src/__tests__/shared/github.test.d.ts +1 -0
- package/dist/merge/src/__tests__/shared/session.test.d.ts +1 -0
- package/dist/merge/src/cli/check-conflicts.command.d.ts +24 -0
- package/dist/merge/src/cli/index.d.ts +2 -0
- package/dist/merge/src/cli/init.command.d.ts +23 -0
- package/dist/merge/src/conflicts/git-handler.d.ts +4 -0
- package/dist/merge/src/conflicts/git-spec.d.ts +43 -0
- package/dist/merge/src/conflicts/index.d.ts +4 -0
- package/dist/merge/src/conflicts/session-handler.d.ts +9 -0
- package/dist/merge/src/conflicts/session-spec.d.ts +43 -0
- package/dist/merge/src/index.d.ts +5 -0
- package/dist/merge/src/init/index.d.ts +4 -0
- package/dist/merge/src/init/init-handler.d.ts +4 -0
- package/dist/merge/src/init/init-spec.d.ts +41 -0
- package/dist/merge/src/init/templates.d.ts +10 -0
- package/dist/merge/src/mcp/index.d.ts +1 -0
- package/dist/merge/src/mcp/server.d.ts +2 -0
- package/dist/merge/src/shared/git.d.ts +17 -0
- package/dist/merge/src/shared/github.d.ts +18 -0
- package/dist/merge/src/shared/result.d.ts +19 -0
- package/dist/merge/src/shared/session.d.ts +16 -0
- package/package.json +60 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// src/cli/init.command.ts
|
|
2
|
+
import { defineCommand } from "citty";
|
|
3
|
+
|
|
4
|
+
// src/init/init-spec.ts
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
var InitInputSchema = z.object({
|
|
7
|
+
outputDir: z.string().min(1).default("."),
|
|
8
|
+
workflowName: z.string().min(1).default("jules-merge-check"),
|
|
9
|
+
baseBranch: z.string().min(1).default("main"),
|
|
10
|
+
force: z.boolean().default(false)
|
|
11
|
+
});
|
|
12
|
+
var InitErrorCode = z.enum([
|
|
13
|
+
"DIRECTORY_NOT_FOUND",
|
|
14
|
+
"FILE_ALREADY_EXISTS",
|
|
15
|
+
"WRITE_FAILED",
|
|
16
|
+
"UNKNOWN_ERROR"
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
// src/init/init-handler.ts
|
|
20
|
+
import { mkdir, writeFile, access, stat } from "node:fs/promises";
|
|
21
|
+
import { join, resolve } from "node:path";
|
|
22
|
+
|
|
23
|
+
// src/shared/result.ts
|
|
24
|
+
function ok(data) {
|
|
25
|
+
return { success: true, data };
|
|
26
|
+
}
|
|
27
|
+
function fail(code, message, recoverable = false, suggestion) {
|
|
28
|
+
return { success: false, error: { code, message, recoverable, suggestion } };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// src/init/templates.ts
|
|
32
|
+
function buildWorkflowYaml(options) {
|
|
33
|
+
return `# Generated by jules-merge init
|
|
34
|
+
# This workflow checks for merge conflicts on pull requests.
|
|
35
|
+
name: ${options.workflowName}
|
|
36
|
+
|
|
37
|
+
on:
|
|
38
|
+
pull_request:
|
|
39
|
+
branches: [${options.baseBranch}]
|
|
40
|
+
|
|
41
|
+
permissions:
|
|
42
|
+
contents: read
|
|
43
|
+
pull-requests: read
|
|
44
|
+
|
|
45
|
+
jobs:
|
|
46
|
+
check-conflicts:
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v4
|
|
50
|
+
with:
|
|
51
|
+
fetch-depth: 0
|
|
52
|
+
|
|
53
|
+
- name: Attempt merge
|
|
54
|
+
id: merge
|
|
55
|
+
continue-on-error: true
|
|
56
|
+
run: |
|
|
57
|
+
git config user.name "github-actions"
|
|
58
|
+
git config user.email "github-actions@github.com"
|
|
59
|
+
git fetch origin \${{ github.event.pull_request.base.ref }}
|
|
60
|
+
git merge origin/\${{ github.event.pull_request.base.ref }} --no-commit --no-ff || true
|
|
61
|
+
|
|
62
|
+
- name: Check for conflicts
|
|
63
|
+
run: |
|
|
64
|
+
npx @google/jules-merge check-conflicts \\
|
|
65
|
+
--repo \${{ github.repository }} \\
|
|
66
|
+
--pr \${{ github.event.pull_request.number }} \\
|
|
67
|
+
--sha \${{ github.event.pull_request.head.sha }}
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/init/init-handler.ts
|
|
72
|
+
class InitHandler {
|
|
73
|
+
async execute(input) {
|
|
74
|
+
try {
|
|
75
|
+
const outputDir = resolve(input.outputDir);
|
|
76
|
+
try {
|
|
77
|
+
const stats = await stat(outputDir);
|
|
78
|
+
if (!stats.isDirectory()) {
|
|
79
|
+
return fail("DIRECTORY_NOT_FOUND", `${outputDir} is not a directory.`, true, "Provide a valid directory path with --output-dir.");
|
|
80
|
+
}
|
|
81
|
+
} catch {
|
|
82
|
+
return fail("DIRECTORY_NOT_FOUND", `Directory does not exist: ${outputDir}`, true, "Create the directory first or provide a valid path.");
|
|
83
|
+
}
|
|
84
|
+
const workflowDir = join(outputDir, ".github", "workflows");
|
|
85
|
+
const filePath = join(workflowDir, `${input.workflowName}.yml`);
|
|
86
|
+
if (!input.force) {
|
|
87
|
+
try {
|
|
88
|
+
await access(filePath);
|
|
89
|
+
return fail("FILE_ALREADY_EXISTS", `Workflow file already exists: ${filePath}`, true, "Use --force to overwrite.");
|
|
90
|
+
} catch {}
|
|
91
|
+
}
|
|
92
|
+
const content = buildWorkflowYaml({
|
|
93
|
+
workflowName: input.workflowName,
|
|
94
|
+
baseBranch: input.baseBranch
|
|
95
|
+
});
|
|
96
|
+
try {
|
|
97
|
+
await mkdir(workflowDir, { recursive: true });
|
|
98
|
+
await writeFile(filePath, content, "utf-8");
|
|
99
|
+
} catch (error) {
|
|
100
|
+
return fail("WRITE_FAILED", `Failed to write workflow file: ${error.message}`, true);
|
|
101
|
+
}
|
|
102
|
+
return ok({ filePath, content });
|
|
103
|
+
} catch (error) {
|
|
104
|
+
return fail("UNKNOWN_ERROR", error instanceof Error ? error.message : String(error), false);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/cli/init.command.ts
|
|
110
|
+
var init_command_default = defineCommand({
|
|
111
|
+
meta: {
|
|
112
|
+
name: "init",
|
|
113
|
+
description: "Generate a GitHub Actions workflow for merge conflict detection."
|
|
114
|
+
},
|
|
115
|
+
args: {
|
|
116
|
+
"output-dir": {
|
|
117
|
+
type: "string",
|
|
118
|
+
description: "Directory to write .github/workflows/ into (defaults to .)",
|
|
119
|
+
default: "."
|
|
120
|
+
},
|
|
121
|
+
"workflow-name": {
|
|
122
|
+
type: "string",
|
|
123
|
+
description: "Workflow filename (without .yml)",
|
|
124
|
+
default: "jules-merge-check"
|
|
125
|
+
},
|
|
126
|
+
"base-branch": {
|
|
127
|
+
type: "string",
|
|
128
|
+
description: "Base branch to check against",
|
|
129
|
+
default: "main"
|
|
130
|
+
},
|
|
131
|
+
force: {
|
|
132
|
+
type: "boolean",
|
|
133
|
+
description: "Overwrite existing workflow file",
|
|
134
|
+
default: false
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
async run({ args }) {
|
|
138
|
+
const input = InitInputSchema.parse({
|
|
139
|
+
outputDir: args["output-dir"],
|
|
140
|
+
workflowName: args["workflow-name"],
|
|
141
|
+
baseBranch: args["base-branch"],
|
|
142
|
+
force: args.force
|
|
143
|
+
});
|
|
144
|
+
const handler = new InitHandler;
|
|
145
|
+
const result = await handler.execute(input);
|
|
146
|
+
if (result.success) {
|
|
147
|
+
console.log(`✅ Created ${result.data.filePath}`);
|
|
148
|
+
} else {
|
|
149
|
+
console.error(`❌ ${result.error.message}`);
|
|
150
|
+
if (result.error.suggestion) {
|
|
151
|
+
console.error(` ${result.error.suggestion}`);
|
|
152
|
+
}
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
export {
|
|
158
|
+
init_command_default as default
|
|
159
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 Google LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { Activity } from '../types.js';
|
|
17
|
+
import { ActivityStorage } from '../storage/types.js';
|
|
18
|
+
import { ActivityClient, ListOptions, SelectOptions } from './types.js';
|
|
19
|
+
/**
|
|
20
|
+
* Interface for the network layer used by the activity client.
|
|
21
|
+
* Abstracts away the details of polling and fetching from the API.
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export interface NetworkClient {
|
|
25
|
+
rawStream(): AsyncIterable<Activity>;
|
|
26
|
+
listActivities(options?: ListOptions): Promise<{
|
|
27
|
+
activities: Activity[];
|
|
28
|
+
nextPageToken?: string;
|
|
29
|
+
}>;
|
|
30
|
+
fetchActivity(activityId: string): Promise<Activity>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The default implementation of the ActivityClient.
|
|
34
|
+
* Implements a "local-first" architecture where activities are fetched from
|
|
35
|
+
* the network, cached locally, and then served from the cache.
|
|
36
|
+
*/
|
|
37
|
+
export declare class DefaultActivityClient implements ActivityClient {
|
|
38
|
+
private storage;
|
|
39
|
+
private network;
|
|
40
|
+
constructor(storage: ActivityStorage, network: NetworkClient);
|
|
41
|
+
/**
|
|
42
|
+
* Re-hydrates plain artifact objects from storage into rich class instances.
|
|
43
|
+
* JSON serialization loses class information (methods), so we need to restore it.
|
|
44
|
+
*
|
|
45
|
+
* **Behavior:**
|
|
46
|
+
* - Iterates through artifacts in an activity.
|
|
47
|
+
* - If an artifact is a plain object (not a class instance), it's re-instantiated.
|
|
48
|
+
* - Handles backward compatibility: if an artifact is already a class instance, it's skipped.
|
|
49
|
+
*
|
|
50
|
+
* @param activity The activity from storage, potentially with plain artifacts.
|
|
51
|
+
* @returns The same activity with its artifacts guaranteed to be class instances.
|
|
52
|
+
*/
|
|
53
|
+
private _hydrateActivityArtifacts;
|
|
54
|
+
/**
|
|
55
|
+
* Returns an async iterable of all activities.
|
|
56
|
+
*
|
|
57
|
+
* **Behavior:**
|
|
58
|
+
* - Always syncs new activities from the network first (via hydrate).
|
|
59
|
+
* - Then yields all activities from local storage.
|
|
60
|
+
*
|
|
61
|
+
* This ensures callers always get the complete, up-to-date history
|
|
62
|
+
* rather than potentially stale cached data.
|
|
63
|
+
*/
|
|
64
|
+
history(): AsyncIterable<Activity>;
|
|
65
|
+
/**
|
|
66
|
+
* Syncs new activities from the network to local cache.
|
|
67
|
+
*
|
|
68
|
+
* **Optimization Strategy:**
|
|
69
|
+
* Activities are immutable - once downloaded, they never change.
|
|
70
|
+
* We use the Jules API's pageToken (nanosecond timestamp) to fetch
|
|
71
|
+
* only activities newer than our latest cached one.
|
|
72
|
+
*
|
|
73
|
+
* **Behavior:**
|
|
74
|
+
* - Empty cache: Fetches all activities (no pageToken)
|
|
75
|
+
* - Has cached activities: Constructs pageToken from latest createTime,
|
|
76
|
+
* fetches only newer activities
|
|
77
|
+
* - Frozen session (> 30 days): Skips API call entirely
|
|
78
|
+
*
|
|
79
|
+
* @returns The number of new activities synced.
|
|
80
|
+
*/
|
|
81
|
+
hydrate(): Promise<number>;
|
|
82
|
+
/**
|
|
83
|
+
* Returns an async iterable of new activities from the network.
|
|
84
|
+
* This method polls the network and updates the local storage.
|
|
85
|
+
*
|
|
86
|
+
* **Side Effects:**
|
|
87
|
+
* - Polls the network continuously.
|
|
88
|
+
* - Appends new activities to local storage (write-through caching).
|
|
89
|
+
*
|
|
90
|
+
* **Logic:**
|
|
91
|
+
* - Reads the latest activity from storage to determine the "high-water mark".
|
|
92
|
+
* - Ignores incoming activities older than or equal to the high-water mark.
|
|
93
|
+
*/
|
|
94
|
+
updates(): AsyncIterable<Activity>;
|
|
95
|
+
/**
|
|
96
|
+
* Returns a combined stream of history and updates.
|
|
97
|
+
* This is the primary method for consuming the activity stream.
|
|
98
|
+
*
|
|
99
|
+
* **Behavior:**
|
|
100
|
+
* 1. Yields all historical activities from local storage (offline capable).
|
|
101
|
+
* 2. Switches to `updates()` to yield new activities from the network (real-time).
|
|
102
|
+
*/
|
|
103
|
+
stream(): AsyncIterable<Activity>;
|
|
104
|
+
/**
|
|
105
|
+
* Queries local storage for activities matching the given options.
|
|
106
|
+
*/
|
|
107
|
+
select(options?: SelectOptions): Promise<Activity[]>;
|
|
108
|
+
/**
|
|
109
|
+
* Lists activities from the network directly.
|
|
110
|
+
* @param options Pagination options.
|
|
111
|
+
*/
|
|
112
|
+
list(options?: ListOptions): Promise<{
|
|
113
|
+
activities: Activity[];
|
|
114
|
+
nextPageToken?: string;
|
|
115
|
+
}>;
|
|
116
|
+
/**
|
|
117
|
+
* Gets a single activity by ID.
|
|
118
|
+
* Implements a "read-through" caching strategy.
|
|
119
|
+
*
|
|
120
|
+
* **Logic:**
|
|
121
|
+
* 1. Checks local storage. If found, returns it immediately (fast).
|
|
122
|
+
* 2. If missing, fetches from the network.
|
|
123
|
+
* 3. Persists the fetched activity to storage (future reads will hit cache).
|
|
124
|
+
* 4. Returns the activity.
|
|
125
|
+
*
|
|
126
|
+
* **Side Effects:**
|
|
127
|
+
* - May perform a network request.
|
|
128
|
+
* - May write to local storage.
|
|
129
|
+
*/
|
|
130
|
+
get(activityId: string): Promise<Activity>;
|
|
131
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 Google LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import type { Activity, ActivitySummary } from '../types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Creates a concise summary for an activity.
|
|
19
|
+
* @param activity The activity to summarize.
|
|
20
|
+
* @returns A summary of the activity.
|
|
21
|
+
*/
|
|
22
|
+
export declare function toSummary(activity: Activity): ActivitySummary;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 Google LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { Activity } from '../types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Standard pagination options for network requests.
|
|
19
|
+
*/
|
|
20
|
+
export interface ListOptions {
|
|
21
|
+
pageSize?: number;
|
|
22
|
+
pageToken?: string;
|
|
23
|
+
filter?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Options for filtering activities locally.
|
|
27
|
+
*/
|
|
28
|
+
export interface SelectOptions {
|
|
29
|
+
after?: string;
|
|
30
|
+
before?: string;
|
|
31
|
+
type?: string;
|
|
32
|
+
limit?: number;
|
|
33
|
+
order?: 'asc' | 'desc';
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Interface for managing session activities.
|
|
37
|
+
* This interface handles both local caching and network synchronization.
|
|
38
|
+
*/
|
|
39
|
+
export interface ActivityClient {
|
|
40
|
+
/**
|
|
41
|
+
* COLD STREAM: Yields all known past activities from local storage.
|
|
42
|
+
* Ends immediately after yielding the last known activity.
|
|
43
|
+
* Does NOT open a network connection.
|
|
44
|
+
*/
|
|
45
|
+
history(): AsyncIterable<Activity>;
|
|
46
|
+
/**
|
|
47
|
+
* HOT STREAM: Yields ONLY future activities as they arrive from the network.
|
|
48
|
+
* Blocks indefinitely.
|
|
49
|
+
*/
|
|
50
|
+
updates(): AsyncIterable<Activity>;
|
|
51
|
+
/**
|
|
52
|
+
* HYBRID STREAM: Yields full history(), then seamlessly switches to updates().
|
|
53
|
+
* The standard choice for most applications.
|
|
54
|
+
*/
|
|
55
|
+
stream(): AsyncIterable<Activity>;
|
|
56
|
+
/**
|
|
57
|
+
* LOCAL QUERY: Performs rich filtering against local storage only.
|
|
58
|
+
* Fast, but might be incomplete if not synced.
|
|
59
|
+
*/
|
|
60
|
+
select(options?: SelectOptions): Promise<Activity[]>;
|
|
61
|
+
/**
|
|
62
|
+
* NETWORK LIST: Honest wrapper around standard REST pagination.
|
|
63
|
+
* Uses opaque tokens.
|
|
64
|
+
*/
|
|
65
|
+
list(options?: ListOptions): Promise<{
|
|
66
|
+
activities: Activity[];
|
|
67
|
+
nextPageToken?: string;
|
|
68
|
+
}>;
|
|
69
|
+
/**
|
|
70
|
+
* NETWORK GET: Fetches a specific activity from the network and caches it.
|
|
71
|
+
*/
|
|
72
|
+
get(activityId: string): Promise<Activity>;
|
|
73
|
+
/**
|
|
74
|
+
* NETWORK SYNC: Fetches all activities from the network and caches them.
|
|
75
|
+
* Useful when you suspect the cache is stale.
|
|
76
|
+
* @returns The number of activities synced.
|
|
77
|
+
*/
|
|
78
|
+
hydrate(): Promise<number>;
|
|
79
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 Google LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
export type RateLimitRetryConfig = {
|
|
17
|
+
maxRetryTimeMs: number;
|
|
18
|
+
baseDelayMs: number;
|
|
19
|
+
maxDelayMs: number;
|
|
20
|
+
};
|
|
21
|
+
export type ApiClientOptions = {
|
|
22
|
+
apiKey: string | undefined;
|
|
23
|
+
baseUrl: string;
|
|
24
|
+
requestTimeoutMs: number;
|
|
25
|
+
rateLimitRetry?: Partial<RateLimitRetryConfig>;
|
|
26
|
+
maxConcurrentRequests?: number;
|
|
27
|
+
};
|
|
28
|
+
export type ApiRequestOptions = {
|
|
29
|
+
method?: 'GET' | 'POST';
|
|
30
|
+
body?: Record<string, unknown>;
|
|
31
|
+
query?: Record<string, any>;
|
|
32
|
+
headers?: Record<string, string>;
|
|
33
|
+
_isRetry?: boolean;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* A simple internal API client to handle HTTP requests to the Jules API.
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
export declare class ApiClient {
|
|
40
|
+
private readonly apiKey;
|
|
41
|
+
private readonly baseUrl;
|
|
42
|
+
private readonly requestTimeoutMs;
|
|
43
|
+
private readonly rateLimitConfig;
|
|
44
|
+
private readonly semaphore;
|
|
45
|
+
constructor(options: ApiClientOptions);
|
|
46
|
+
request<T>(endpoint: string, options?: ApiRequestOptions): Promise<T>;
|
|
47
|
+
private resolveUrl;
|
|
48
|
+
private fetchWithTimeout;
|
|
49
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 Google LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import type { RestMediaArtifact, RestBashOutputArtifact, GitPatch, ParsedChangeSet, ParsedFile, GeneratedFile, GeneratedFiles } from './types.js';
|
|
17
|
+
import { Platform } from './platform/types.js';
|
|
18
|
+
/**
|
|
19
|
+
* Parses a unified diff string and extracts file information.
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseUnidiff(patch?: string | null): ParsedFile[];
|
|
23
|
+
/**
|
|
24
|
+
* Parses a unified diff and extracts file information including content.
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseUnidiffWithContent(patch?: string | null): GeneratedFile[];
|
|
28
|
+
/**
|
|
29
|
+
* Creates a GeneratedFiles helper object from an array of GeneratedFile.
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
export declare function createGeneratedFiles(files: GeneratedFile[]): GeneratedFiles;
|
|
33
|
+
/**
|
|
34
|
+
* Represents a media artifact (e.g. image) produced by an activity.
|
|
35
|
+
* Provides helper methods for saving and viewing the media.
|
|
36
|
+
*/
|
|
37
|
+
export declare class MediaArtifact {
|
|
38
|
+
readonly type = "media";
|
|
39
|
+
readonly data: string;
|
|
40
|
+
readonly format: string;
|
|
41
|
+
private platform;
|
|
42
|
+
private activityId?;
|
|
43
|
+
constructor(artifact: RestMediaArtifact['media'], platform: Platform, activityId?: string);
|
|
44
|
+
/**
|
|
45
|
+
* Saves the media artifact to a file.
|
|
46
|
+
*
|
|
47
|
+
* **Side Effects:**
|
|
48
|
+
* - Node.js: Writes the file to disk (overwrites if exists).
|
|
49
|
+
* - Browser: Saves the file to the 'artifacts' object store in IndexedDB.
|
|
50
|
+
*
|
|
51
|
+
* @param filepath The path where the file should be saved.
|
|
52
|
+
*/
|
|
53
|
+
save(filepath: string): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Converts the media artifact to a data URL.
|
|
56
|
+
* Useful for displaying images in a browser.
|
|
57
|
+
*
|
|
58
|
+
* **Data Transformation:**
|
|
59
|
+
* - Prefixes the base64 data with `data:<mimeType>;base64,`.
|
|
60
|
+
*
|
|
61
|
+
* @returns A valid Data URI string.
|
|
62
|
+
*/
|
|
63
|
+
toUrl(): string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Represents the output of a bash command executed by the agent.
|
|
67
|
+
*/
|
|
68
|
+
export declare class BashArtifact {
|
|
69
|
+
readonly type = "bashOutput";
|
|
70
|
+
readonly command: string;
|
|
71
|
+
readonly stdout: string;
|
|
72
|
+
readonly stderr: string;
|
|
73
|
+
readonly exitCode: number | null;
|
|
74
|
+
constructor(artifact: RestBashOutputArtifact['bashOutput']);
|
|
75
|
+
/**
|
|
76
|
+
* Formats the bash output as a string, mimicking a terminal session.
|
|
77
|
+
*
|
|
78
|
+
* **Data Transformation:**
|
|
79
|
+
* - Combines `stdout` and `stderr`.
|
|
80
|
+
* - Formats the command with a `$` prompt.
|
|
81
|
+
* - Appends the exit code.
|
|
82
|
+
*/
|
|
83
|
+
toString(): string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Represents a set of code changes (unified diff) produced by an activity.
|
|
87
|
+
* Provides a helper method to parse the diff into structured data.
|
|
88
|
+
*/
|
|
89
|
+
export declare class ChangeSetArtifact {
|
|
90
|
+
readonly type: "changeSet";
|
|
91
|
+
readonly source: string;
|
|
92
|
+
readonly gitPatch: GitPatch;
|
|
93
|
+
constructor(source: string, gitPatch: GitPatch);
|
|
94
|
+
/**
|
|
95
|
+
* Parses the unified diff and returns structured file change information.
|
|
96
|
+
*
|
|
97
|
+
* **Data Transformation:**
|
|
98
|
+
* - Extracts file paths from diff headers.
|
|
99
|
+
* - Determines change type (created/modified/deleted) from /dev/null markers.
|
|
100
|
+
* - Counts additions (+) and deletions (-) in hunks.
|
|
101
|
+
*
|
|
102
|
+
* @returns Parsed diff with file paths, change types, and line counts.
|
|
103
|
+
*/
|
|
104
|
+
parsed(): ParsedChangeSet;
|
|
105
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 Google LLC
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { CachedSession } from './storage/types.js';
|
|
17
|
+
export type CacheTier = 'hot' | 'warm' | 'frozen';
|
|
18
|
+
/**
|
|
19
|
+
* Determines the cache tier for a session based on its state and age.
|
|
20
|
+
*
|
|
21
|
+
* Strategy:
|
|
22
|
+
* - **Frozen (Tier 3):** > 30 days old. Immutable.
|
|
23
|
+
* - **Warm (Tier 2):** Terminal state + Verified < 24h ago. High read performance.
|
|
24
|
+
* - **Hot (Tier 1):** Active or Stale. Requires network sync.
|
|
25
|
+
*/
|
|
26
|
+
export declare function determineCacheTier(cached: CachedSession, now?: number): CacheTier;
|
|
27
|
+
/**
|
|
28
|
+
* Helper to check if a cached session is valid to return immediately.
|
|
29
|
+
* Returns true if the session is Frozen or Warm.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isCacheValid(cached: CachedSession | undefined, now?: number): cached is CachedSession;
|