Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions packages/genkit_llamadart/doc/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,10 @@ block; zero closes the block immediately. Enable thinking separately with
`startTag`/`endTag` from the selected template; custom delimiters and
`forcedMessage` pass through unchanged, except that on Qwen3-Coder XML
templates (Qwen3.5) with no `endTag` set, a `\n` is appended to `forcedMessage`
before `</think>`. Budgets need runtime support and cannot
be combined with media or speculative decoding.
before `</think>`; an unset `forcedMessage` becomes a lone `\n`. Backends that
take chat messages, such as LiteRT-LM, close the thought themselves and get no
`\n`. Budgets need runtime support and cannot be combined with media or
speculative decoding.

`reusePromptPrefix: false` disables native llama.cpp prefix reuse. It does not
create an isolated conversation: always pass the complete history. The adapter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ void main() {
..templateResult = const llama.LlamaChatTemplateResult(
prompt: 'prompt',
format: 0,
grammar: 'root ::= "answer"',
grammarTriggers: [
llama.GrammarTrigger(type: 0, value: '<json>'),
llama.GrammarTrigger(type: 1, value: '42', token: 42),
Expand Down Expand Up @@ -47,6 +48,7 @@ void main() {

expect(runtime.chatTemplateCallCount, 1);
expect(runtime.generateCallCount, 1);
expect(runtime.lastGenerationParams!.grammar, 'root ::= "answer"');
expect(
runtime.lastGenerationParams!.grammarTriggers.map(
(trigger) => trigger.triggerType,
Expand Down
8 changes: 8 additions & 0 deletions test/ci/test_genkit_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,14 @@ def test_version_or_changelog_mismatch_fails(self):
(self.root / "packages/genkit_llamadart/CHANGELOG.md").write_text(heading + "\n")
self.run_step("Validate release state", success=False)

def test_changelog_date_must_be_iso(self):
self.env.update(GITHUB_REF_TYPE="tag", GITHUB_REF_NAME="genkit_llamadart-v1.5.0", GITHUB_REF="refs/tags/genkit_llamadart-v1.5.0")
changelog = self.root / "packages/genkit_llamadart/CHANGELOG.md"
for heading in ["## 1.5.0 - 2026-9-28", "## 1.5.0 - soon", "## 1.5.0 - 2026-09-28T00:00", "## 1.5.0 - 2026-09-28 extra"]:
changelog.write_text(heading + "\n")
self.run_step("Validate release state", success=False)
self.run_step("Verify package-specific stable tag", success=False, workflow="publish_genkit_pubdev.yml")

def test_published_version_requires_tag_and_skips_dispatch(self):
self.scenario["pub_http"] = "200"
self.run_step("Validate release state", success=False)
Expand Down
25 changes: 20 additions & 5 deletions test/unit/hook/build_hook_litert_lm_integration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1081,9 +1081,19 @@ dependency_overrides: {llamadart_llama_cpp_flutter: {path: resolved companion}}
final previousTemplateIsCurrent =
hookTemplateHash('_previousLiteRtLmCompanionManifestTemplateSha256') ==
hookTemplateHash('_liteRtLmCompanionManifestTemplateSha256');
final previousFixtureOnCoreLine = previousFixturePin.startsWith(
'$coreUpstream-',
final previousFixtureRebuild = _rebuildOnLine(
previousFixturePin,
coreUpstream,
);
final previousFixtureOnCoreLine = previousFixtureRebuild != null;

test('a bare tag is rebuild 0 of its own release line only', () {
expect(_rebuildOnLine('v0.20.0', 'v0.20.0'), 0);
expect(_rebuildOnLine('v0.20.0-3', 'v0.20.0'), 3);
expect(_rebuildOnLine('v0.20.1', 'v0.20.0'), isNull);
expect(_rebuildOnLine('v0.20.10', 'v0.20.1'), isNull);
expect(_rebuildOnLine('v0.20.1-2', 'v0.20.0'), isNull);
});

test('previous companion template fixture matches the hook hash and, on the '
'core release line, is an earlier rebuild', () {
Expand All @@ -1099,10 +1109,9 @@ dependency_overrides: {llamadart_llama_cpp_flutter: {path: resolved companion}}
).firstMatch(hookSource)!.group(1);
expect(sha256.convert(utf8.encode(template)).toString(), expected);

if (previousFixtureOnCoreLine) {
if (previousFixtureRebuild != null) {
expect(
int.parse(previousFixturePin.substring(coreUpstream.length + 1)) <
coreRebuild,
previousFixtureRebuild < coreRebuild,
isTrue,
reason:
'the fixture pins $previousFixturePin, not an earlier build of '
Expand Down Expand Up @@ -2936,3 +2945,9 @@ Future<void> _writeBundleLibraries(
await File(path.join(bundleDir.path, name)).writeAsString('fake-$name');
}
}

int? _rebuildOnLine(String pin, String upstream) {
if (pin == upstream) return 0;
if (!pin.startsWith('$upstream-')) return null;
return int.tryParse(pin.substring(upstream.length + 1));
}
68 changes: 63 additions & 5 deletions test/unit/tooling/ci_workflow_selection_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1536,13 +1536,42 @@ for event,flag,native,cancel,good,main in itertools.product(('push','pull_reques
{'run': 'npx playwright install-deps'},
{'uses': 'awalsh128/cache-apt-pkgs-action@v1'},
{'uses': 'ConorMacBride/install-linux-deps@v1'},
{
'uses': 'ConorMacBride/install-package@v1',
'with': {'apt': 'libfoo'},
},
{
'uses': 'some/setup@v1',
'with': {'pre-script': 'sudo apt-get update'},
},
]) {
expect(_installsSystemPackages(step), isTrue, reason: '$step');
}
final root = Directory.systemTemp.createTempSync('apt_action_');
addTearDown(() => root.deleteSync(recursive: true));
Directory('${root.path}/local').createSync();
File('${root.path}/local/action.yml').writeAsStringSync('''
runs:
using: composite
steps:
- run: echo ok
- run: sudo apt-get install -y libfoo
shell: bash
''');
expect(
_installsSystemPackages({'uses': './local'}, root: root.path),
isTrue,
);
for (final step in <Map>[
{'run': 'npx playwright install chromium'},
{'uses': 'actions/checkout@v7'},
{'uses': 'subosito/flutter-action@v2'},
{'uses': 'actions/setup-captain@v1'},
{
'uses': 'actions/checkout@v7',
'with': {'path': 'notes'},
},
{'uses': './.github/actions/companion-package'},
]) {
expect(_installsSystemPackages(step), isFalse, reason: '$step');
}
Expand Down Expand Up @@ -1889,8 +1918,37 @@ for event,flag,native,cancel,good,main in itertools.product(('push','pull_reques
/// against.
const _pinnedCoverageVersion = '1.16.0';

bool _installsSystemPackages(Map step) =>
RegExp(
r'\bapt(-get)?\b|dpkg|install-deps|--with-deps',
).hasMatch('${step['run']}') ||
RegExp(r'apt|dpkg|install-.*deps').hasMatch('${step['uses']}');
final _systemPackageCommand = RegExp(
r'\bapt(-get)?\b|\bdpkg\b|install-deps|--with-deps',
);
final _systemPackageAction = RegExp(
r'(^|[/@_-])(apt|apt-get|dpkg)([/@_-]|$)|install-.*deps',
);

/// Whether [step] installs system packages through a command, an action name,
/// an `apt`-style `with:` input or a local composite action.
bool _installsSystemPackages(Map step, {String root = '.'}) {
if (_systemPackageCommand.hasMatch('${step['run']}')) return true;
final uses = '${step['uses'] ?? ''}';
if (_systemPackageAction.hasMatch(uses)) return true;
final inputs = step['with'];
if (inputs is Map) {
for (final entry in inputs.entries) {
if (_systemPackageAction.hasMatch('${entry.key}') ||
_systemPackageCommand.hasMatch('${entry.value}')) {
return true;
}
}
}
if (uses.startsWith('./')) {
final action = File('$root/$uses/action.yml');
if (!action.existsSync()) return false;
final steps =
(loadYaml(action.readAsStringSync()) as Map)['runs']?['steps'];
return steps is List &&
steps.any(
(nested) => _installsSystemPackages(nested as Map, root: root),
);
}
return false;
}
4 changes: 2 additions & 2 deletions website/docs/guides/generation-and-streaming.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,8 +354,8 @@ forced text is a line break before the end delimiter, as llama.cpp forces it.
On native llama.cpp, a grammar that takes the template-opened thought itself
(its root starts with `think-body`, as for `responseFormat` on Qwen3.5) stays
applied while the model reasons, so it also constrains the reply after a spent
budget. Any other grammar, including a caller `grammar` or a lazy grammar,
waits until the thought closes. WebGPU still pauses every grammar during
budget. Other grammars, such as a typical caller `grammar` or a lazy grammar,
wait until the thought closes. WebGPU still pauses every grammar during
budgeted reasoning
([#1954](https://github.com/leehack/llamadart/issues/1954)).
Native llama.cpp, WebGPU bridges that report `thinkingBudget` and native
Expand Down
8 changes: 5 additions & 3 deletions website/docs/maintainers/release-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -497,13 +497,15 @@ pub.dev rejects an upload whose `CHANGELOG.md`, `README.md`, `LICENSE` or
Example-tab file is over 256 KiB (262,144 bytes, `maxContentLength` in
pub-dev's `pub_package_reader`), and it does so only after the release tag is
pushed: `v0.19.2` was tagged but never published for this reason. It likewise
rejects a `pubspec.yaml` over 128 KiB (131,072 bytes, `maxPubspecLength`).
rejects a `pubspec.yaml` over 128 KiB (131,072 bytes, an inline `128 * 1024`
in the same reader).
`verify_release_docs_versions.dart` checks those files in the core, every
Apple companion and `genkit_llamadart`, in PR CI and in
`release_on_prep_merge.yml` before any tag. It fails a file over the limit and
warns above 90% of it. Genkit joins only this size check: its version and
release routing stay independent
([Genkit package](./genkit-package.md)).
release routing stay independent ([Genkit package](./genkit-package.md)). A
genkit-only PR and a genkit release do not run it, so check the
`genkit_llamadart` sizes by hand when preparing its release.

`CHANGELOG.md` keeps every release from 0.10.0 on; older ones are in
`doc/changelog_archive.md`, which pub does not package (`/doc/` is in
Expand Down
Loading